Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a subdirectory of $XDG_CONFIG_HOME instead of ~/.matplotlibrc on Linux #454

Merged
merged 2 commits into from May 28, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/api/api_changes.rst
Expand Up @@ -17,6 +17,11 @@ For new features that were added to matplotlib, please see
Changes in 1.3.x Changes in 1.3.x
================ ================


* On Linux, the user-specific `matplotlibrc` configuration file is now
located in `~/.config/matplotlib/matplotlibrc` to conform to the
`XDG Base Directory Specification
<http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.

* The following items that were deprecated in version 1.2 or earlier * The following items that were deprecated in version 1.2 or earlier
have now been removed completely. have now been removed completely.


Expand Down
8 changes: 4 additions & 4 deletions doc/faq/troubleshooting_faq.rst
Expand Up @@ -37,10 +37,10 @@ and printing the ``__file__`` attribute::
:file:`.matplotlib` directory location :file:`.matplotlib` directory location
====================================== ======================================


Each user has a :file:`.matplotlib/` directory which may contain a Each user has a matplotlib configuration directory which may contain a
:ref:`matplotlibrc <customizing-with-matplotlibrc-files>` file and various :ref:`matplotlibrc <customizing-with-matplotlibrc-files>` file. To
caches to improve matplotlib's performance. To locate your :file:`.matplotlib/` locate your :file:`.matplotlib/` directory, use
directory, use :func:`matplotlib.get_configdir`:: :func:`matplotlib.get_configdir`::


>>> import matplotlib as mpl >>> import matplotlib as mpl
>>> mpl.get_configdir() >>> mpl.get_configdir()
Expand Down
28 changes: 19 additions & 9 deletions doc/users/customizing.rst
Expand Up @@ -18,21 +18,31 @@ locations, in the following order:


1. :file:`matplotlibrc` in the current working directory, usually used for 1. :file:`matplotlibrc` in the current working directory, usually used for
specific customizations that you do not want to apply elsewhere. specific customizations that you do not want to apply elsewhere.
2. :file:`.matplotlib/matplotlibrc`, for the user's default customizations. See
:ref:`locating-matplotlib-config-dir`. 2. It next looks in a user-specific place, depending on your platform:
3. :file:`{INSTALL}/matplotlib/mpl-data/matplotlibrc`, where :file:`{INSTALL}`
is something like :file:`/usr/lib/python2.5/site-packages` on Linux, and - On Linux, it looks in :file:`.config/matplotlib/matplotlibrc` (or
maybe :file:`C:\\Python25\\Lib\\site-packages` on Windows. Every time you `$XDG_CONFIG_HOME/matplotlib/matplotlibrc` if you've customized
install matplotlib, this file will be overwritten, so if you want your your environment.
customizations to be saved, please move this file to your :file:`.matplotlib`
directory. - On other platforms, it looks in :file:`.matplotlib/matplotlibrc`.

See :ref:`locating-matplotlib-config-dir`.

3. :file:`{INSTALL}/matplotlib/mpl-data/matplotlibrc`, where
:file:`{INSTALL}` is something like
:file:`/usr/lib/python2.5/site-packages` on Linux, and maybe
:file:`C:\\Python25\\Lib\\site-packages` on Windows. Every time you
install matplotlib, this file will be overwritten, so if you want
your customizations to be saved, please move this file to your
user-specific matplotlib directory.


To display where the currently active :file:`matplotlibrc` file was To display where the currently active :file:`matplotlibrc` file was
loaded from, one can do the following:: loaded from, one can do the following::


>>> import matplotlib >>> import matplotlib
>>> matplotlib.matplotlib_fname() >>> matplotlib.matplotlib_fname()
'/home/foo/.matplotlib/matplotlibrc' '/home/foo/.config/matplotlib/matplotlibrc'


See below for a sample :ref:`matplotlibrc file<matplotlibrc-sample>`. See below for a sample :ref:`matplotlibrc file<matplotlibrc-sample>`.


Expand Down
9 changes: 9 additions & 0 deletions doc/users/whats_new.rst
Expand Up @@ -66,6 +66,15 @@ animations as well as being fully interactive.
Future versions of matplotlib will integrate this backend with the Future versions of matplotlib will integrate this backend with the
IPython notebook for a fully web browser based plotting frontend. IPython notebook for a fully web browser based plotting frontend.


XDG base directory support
--------------------------
On Linux, matplotlib now uses the `XDG base directory specification
<http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`
to find the `matplotlibrc` configuration file. `matplotlibrc` should
now be kept in `~/.config/matplotlib`, rather than `~/.matplotlib`. If
your configuration is found in the old location, it will still be used,
but a warning will be displayed.

Path effects on lines Path effects on lines
--------------------- ---------------------
Thanks to Jae-Joon Lee, path effects now also work on plot lines. Thanks to Jae-Joon Lee, path effects now also work on plot lines.
Expand Down
177 changes: 102 additions & 75 deletions lib/matplotlib/__init__.py
Expand Up @@ -146,19 +146,6 @@
sys.argv = ['modpython'] sys.argv = ['modpython']




"""
Manage user customizations through a rc file.

The default file location is given in the following order

- environment variable MATPLOTLIBRC

- HOME/.matplotlib/matplotlibrc if HOME is defined

- PATH/matplotlibrc where PATH is the return value of
get_data_path()
"""

import sys, os, tempfile import sys, os, tempfile


if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
Expand Down Expand Up @@ -525,50 +512,91 @@ def _create_tmp_config_dir():


get_home = verbose.wrap('$HOME=%s', _get_home, always=False) get_home = verbose.wrap('$HOME=%s', _get_home, always=False)


def _get_configdir(): def _get_xdg_config_dir():
""" """
Return the string representing the configuration directory. Returns the XDG configuration directory, according to the `XDG
base directory spec
<http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.
"""
return os.environ.get('XDG_CONFIG_HOME', os.path.join(get_home(), '.config'))


The directory is chosen as follows:


1. If the MPLCONFIGDIR environment variable is supplied, choose that. Else, def _get_xdg_cache_dir():
choose the '.matplotlib' subdirectory of the user's home directory (and """
create it if necessary). Returns the XDG cache directory, according to the `XDG
2. If the chosen directory exists and is writable, use that as the base directory spec
configuration directory. <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.
3. If possible, create a temporary directory, and use it as the
configuration directory.
4. A writable directory could not be found or created; return None.
""" """
return os.environ.get('XDG_CACHE_HOME', os.path.join(get_home(), '.cache'))


def _get_config_or_cache_dir(xdg_base):
from matplotlib.cbook import mkdirs from matplotlib.cbook import mkdirs


configdir = os.environ.get('MPLCONFIGDIR') configdir = os.environ.get('MPLCONFIGDIR')
if configdir is not None: if configdir is not None:
if not os.path.exists(configdir): if not os.path.exists(configdir):
from matplotlib.cbook import mkdirs from matplotlib.cbook import mkdirs
mkdirs(configdir) mkdirs(configdir)

if not _is_writable_dir(configdir): if not _is_writable_dir(configdir):
return _create_tmp_config_dir() return _create_tmp_config_dir()
return configdir return configdir


h = get_home() h = get_home()
if h is not None: p = os.path.join(h, '.matplotlib')
p = os.path.join(h, '.matplotlib') if (sys.platform.startswith('linux') and
not os.path.exists(p)):
p = _get_xdg_config_dir()


if os.path.exists(p): if os.path.exists(p):
if not _is_writable_dir(p): if not _is_writable_dir(p):
return _create_tmp_config_dir() return _create_tmp_config_dir()
else: else:
if not _is_writable_dir(h): if not _is_writable_dir(h):
return _create_tmp_config_dir() return _create_tmp_config_dir()
mkdirs(p) mkdirs(p)

return p


def _get_configdir():
"""
Return the string representing the configuration directory.


return p The directory is chosen as follows:

1. If the MPLCONFIGDIR environment variable is supplied, choose that.

2a. On Linux, if `$HOME/.matplotlib` exists, choose that, but warn that
that is the old location. Barring that, follow the XDG specification
and look first in `$XDG_CONFIG_HOME`, if defined, or `$HOME/.config`.

2b. On other platforms, choose `$HOME/.matplotlib`.

3. If the chosen directory exists and is writable, use that as the
configuration directory.
4. If possible, create a temporary directory, and use it as the
configuration directory.
5. A writable directory could not be found or created; return None.
"""
return _get_config_or_cache_dir(_get_xdg_config_dir())


return _create_tmp_config_dir()
get_configdir = verbose.wrap('CONFIGDIR=%s', _get_configdir, always=False) get_configdir = verbose.wrap('CONFIGDIR=%s', _get_configdir, always=False)




def _get_cachedir():
"""
Return the location of the cache directory.

The procedure used to find the directory is the same as for
_get_config_dir, except using `$XDG_CONFIG_HOME`/`~/.cache` instead.
"""
return _get_config_or_cache_dir(_get_xdg_cache_dir())

get_cachedir = verbose.wrap('CACHEDIR=%s', _get_cachedir, always=False)


def _get_data_path(): def _get_data_path():
'get the path to matplotlib data' 'get the path to matplotlib data'


Expand Down Expand Up @@ -643,50 +671,36 @@ def get_py2exe_datafiles():


def matplotlib_fname(): def matplotlib_fname():
""" """
Return the path to the rc file used by matplotlib. Get the location of the config file.


Search order: The file location is determined in the following order


* current working dir - `$PWD/matplotlibrc`
* environ var MATPLOTLIBRC
* HOME/.matplotlib/matplotlibrc
* MATPLOTLIBDATA/matplotlibrc


""" - environment variable `MATPLOTLIBRC`
oldname = os.path.join(os.getcwd(), '.matplotlibrc')
if os.path.exists(oldname): - `$MPLCONFIGDIR/matplotlib`
try:
shutil.move('.matplotlibrc', 'matplotlibrc') - On Linux,
except IOError as e:
warnings.warn('File could not be renamed: %s' % e) - `$HOME/.matplotlib/matplotlibrc`, if it exists
else:
warnings.warn("""\
Old rc filename ".matplotlibrc" found in working dir and and renamed to new
default rc file name "matplotlibrc" (no leading ".").""")

home = get_home()
configdir = get_configdir()
if home:
oldname = os.path.join(home, '.matplotlibrc')
if os.path.exists(oldname):
if configdir is not None:
newname = os.path.join(configdir, 'matplotlibrc')

try:
shutil.move(oldname, newname)
except IOError as e:
warnings.warn('File could not be renamed: %s' % e)
else:
warnings.warn("""\
Old rc filename "%s" found and renamed to new default rc file name "%s"."""
% (oldname, newname))
else:
warnings.warn("""\
Could not rename old rc file "%s": a suitable configuration directory could not
be found.""" % oldname)


- or `$XDG_CONFIG_HOME/matplotlib/matplotlibrc` (if
$XDG_CONFIG_HOME is defined)

- or `$HOME/.config/matplotlib/matplotlibrc` (if
$XDG_CONFIG_HOME is not defined)

- On other platforms,

- `$HOME/.matplotlib/matplotlibrc` if `$HOME` is defined.

- Lastly, it looks in `$MATPLOTLIBDATA/matplotlibrc` for a
system-defined copy.
"""
fname = os.path.join(os.getcwd(), 'matplotlibrc') fname = os.path.join(os.getcwd(), 'matplotlibrc')
if os.path.exists(fname): return fname if os.path.exists(fname):
return fname


if 'MATPLOTLIBRC' in os.environ: if 'MATPLOTLIBRC' in os.environ:
path = os.environ['MATPLOTLIBRC'] path = os.environ['MATPLOTLIBRC']
Expand All @@ -695,15 +709,28 @@ def matplotlib_fname():
if os.path.exists(fname): if os.path.exists(fname):
return fname return fname


configdir = _get_configdir()
if configdir is not None: if configdir is not None:
fname = os.path.join(configdir, 'matplotlibrc') fname = os.path.join(configdir, 'matplotlibrc')
if os.path.exists(fname): if os.path.exists(fname):
if (sys.platform.startswith('linux') and
fname == os.path.join(
get_home(), '.matplotlib', 'matplotlibrc')):
warnings.warn(
"Found matplotlib configuration in ~/.matplotlib. "
"To conform with the XDG base directory standard, "
"this configuration location has been deprecated "
"on Linux, and the new location is now %r. Please "
"move your configuration there to ensure that "
"matplotlib will continue to find it in the future." %
_get_xdg_config_dir())
return fname return fname


path = get_data_path() # guaranteed to exist or raise path = get_data_path() # guaranteed to exist or raise
fname = os.path.join(path, 'matplotlibrc') fname = os.path.join(path, 'matplotlibrc')
if not os.path.exists(fname): if not os.path.exists(fname):
warnings.warn('Could not find matplotlibrc; using defaults') warnings.warn('Could not find matplotlibrc; using defaults')

return fname return fname




Expand Down
10 changes: 5 additions & 5 deletions lib/matplotlib/finance.py
Expand Up @@ -17,7 +17,7 @@


import numpy as np import numpy as np


from matplotlib import verbose, get_configdir from matplotlib import verbose, get_cachedir
from matplotlib.dates import date2num from matplotlib.dates import date2num
from matplotlib.cbook import iterable, mkdirs from matplotlib.cbook import iterable, mkdirs
from matplotlib.collections import LineCollection, PolyCollection from matplotlib.collections import LineCollection, PolyCollection
Expand All @@ -27,10 +27,10 @@
from matplotlib.transforms import Affine2D from matplotlib.transforms import Affine2D




configdir = get_configdir() cachedir = get_cachedir()
# cachedir will be None if there is no writable directory. # cachedir will be None if there is no writable directory.
if configdir is not None: if cachedir is not None:
cachedir = os.path.join(configdir, 'finance.cache') cachedir = os.path.join(cachedir, 'finance.cache')
else: else:
# Should only happen in a restricted environment (such as Google App # Should only happen in a restricted environment (such as Google App
# Engine). Deal with this gracefully by not caching finance data. # Engine). Deal with this gracefully by not caching finance data.
Expand Down Expand Up @@ -151,7 +151,7 @@ def fetch_historical_yahoo(ticker, date1, date2, cachename=None,dividends=False)
cachename is the name of the local file cache. If None, will cachename is the name of the local file cache. If None, will
default to the md5 hash or the url (which incorporates the ticker default to the md5 hash or the url (which incorporates the ticker
and date range) and date range)

set dividends=True to return dividends instead of price data. With set dividends=True to return dividends instead of price data. With
this option set, parse functions will not work this option set, parse functions will not work


Expand Down
10 changes: 5 additions & 5 deletions lib/matplotlib/font_manager.py
Expand Up @@ -51,7 +51,7 @@
import matplotlib import matplotlib
from matplotlib import afm from matplotlib import afm
from matplotlib import ft2font from matplotlib import ft2font
from matplotlib import rcParams, get_configdir from matplotlib import rcParams, get_cachedir
from matplotlib.cbook import is_string_like from matplotlib.cbook import is_string_like
import matplotlib.cbook as cbook import matplotlib.cbook as cbook
from matplotlib.compat import subprocess from matplotlib.compat import subprocess
Expand Down Expand Up @@ -1323,12 +1323,12 @@ def findfont(prop, fontext='ttf'):
return result return result


else: else:
configdir = get_configdir() cachedir = get_cachedir()
if configdir is not None: if cachedir is not None:
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
_fmcache = os.path.join(configdir, 'fontList.py3k.cache') _fmcache = os.path.join(cachedir, 'fontList.py3k.cache')
else: else:
_fmcache = os.path.join(configdir, 'fontList.cache') _fmcache = os.path.join(cachedir, 'fontList.cache')
else: else:
# Should only happen in a restricted environment (such as Google App # Should only happen in a restricted environment (such as Google App
# Engine). Deal with this gracefully by not caching fonts. # Engine). Deal with this gracefully by not caching fonts.
Expand Down