Repository: ipython/ipython

Issue:
use XDG_CACHE_HOME for cython objects
cython magics fill a lot of object files into the ipython configuration directory usually located in XDG_CONFIG_HOME
A better place for these would be the the XDG_CACHE_HOME as they in can be deleted and recreated easily.
This is relevant for users with the HOME folder on a shared filesystem with a low quota, who set XDG_CACHE_HOME to a local folder to save space and better performance.



Discussion:
makes sense


Resolving patch:
diff --git a/IPython/extensions/cythonmagic.py b/IPython/extensions/cythonmagic.py
--- a/IPython/extensions/cythonmagic.py
+++ b/IPython/extensions/cythonmagic.py
@@ -59,6 +59,7 @@
 from IPython.core.magic import Magics, magics_class, cell_magic
 from IPython.testing.skipdoctest import skip_doctest
 from IPython.utils import py3compat
+from IPython.utils.path import get_ipython_cache_dir
 
 import Cython
 from Cython.Compiler.Errors import CompileError
@@ -192,7 +193,7 @@ def f(x):
         """
         args = magic_arguments.parse_argstring(self.cython, line)
         code = cell if cell.endswith('\n') else cell+'\n'
-        lib_dir = os.path.join(self.shell.ipython_dir, 'cython')
+        lib_dir = os.path.join(get_ipython_cache_dir(), 'cython')
         quiet = True
         key = code, sys.version_info, sys.executable, Cython.__version__
 
diff --git a/IPython/utils/path.py b/IPython/utils/path.py
--- a/IPython/utils/path.py
+++ b/IPython/utils/path.py
@@ -244,6 +244,24 @@ def get_xdg_dir():
     return None
 
 
+def get_xdg_cache_dir():
+    """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
+
+    This is only for non-OS X posix (Linux,Unix,etc.) systems.
+    """
+
+    env = os.environ
+
+    if os.name == 'posix' and sys.platform != 'darwin':
+        # Linux, Unix, AIX, etc.
+        # use ~/.cache if empty OR not set
+        xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
+        if xdg and _writable_dir(xdg):
+            return py3compat.cast_unicode(xdg, fs_encoding)
+
+    return None
+
+
 def get_ipython_dir():
     """Get the IPython directory for this platform and user.
 
@@ -300,6 +318,20 @@ def get_ipython_dir():
     return py3compat.cast_unicode(ipdir, fs_encoding)
 
 
+def get_ipython_cache_dir():
+    """Get the cache directory it is created if it does not exist."""
+    xdgdir = get_xdg_cache_dir()
+    if xdgdir is None:
+        return get_ipython_dir()
+    ipdir = os.path.join(xdgdir, "ipython")
+    if not os.path.exists(ipdir) and _writable_dir(xdgdir):
+        os.makedirs(ipdir)
+    elif not _writable_dir(xdgdir):
+        return get_ipython_dir()
+
+    return py3compat.cast_unicode(ipdir, fs_encoding)
+
+
 def get_ipython_package_dir():
     """Get the base directory where IPython itself is installed."""
     ipdir = os.path.dirname(IPython.__file__)


Test patch:
diff --git a/IPython/utils/tests/test_path.py b/IPython/utils/tests/test_path.py
--- a/IPython/utils/tests/test_path.py
+++ b/IPython/utils/tests/test_path.py
@@ -60,6 +60,7 @@
 TMP_TEST_DIR = tempfile.mkdtemp()
 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
+XDG_CACHE_DIR = join(HOME_TEST_DIR, "xdg_cache_dir")
 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
 #
 # Setup/teardown functions/decorators
@@ -74,6 +75,7 @@ def setup():
     # problem because that exception is only defined on Windows...
     os.makedirs(IP_TEST_DIR)
     os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
+    os.makedirs(os.path.join(XDG_CACHE_DIR, 'ipython'))
 
 
 def teardown():
@@ -361,6 +363,26 @@ def test_filefind():
     t = path.filefind(f.name, alt_dirs)
     # print 'found:',t
 
+@with_environment
+def test_get_ipython_cache_dir():
+    os.environ["HOME"] = HOME_TEST_DIR
+    if os.name == 'posix' and sys.platform != 'darwin':
+        # test default
+        os.makedirs(os.path.join(HOME_TEST_DIR, ".cache"))
+        os.environ.pop("XDG_CACHE_HOME", None)
+        ipdir = path.get_ipython_cache_dir()
+        nt.assert_equal(os.path.join(HOME_TEST_DIR, ".cache", "ipython"),
+                        ipdir)
+        nt.assert_true(os.path.isdir(ipdir))
+
+        # test env override
+        os.environ["XDG_CACHE_HOME"] = XDG_CACHE_DIR
+        ipdir = path.get_ipython_cache_dir()
+        nt.assert_true(os.path.isdir(ipdir))
+        nt.assert_equal(ipdir, os.path.join(XDG_CACHE_DIR, "ipython"))
+    else:
+        nt.assert_equal(path.get_ipython_cache_dir(),
+                        path.get_ipython_dir())
 
 def test_get_ipython_package_dir():
     ipdir = path.get_ipython_package_dir()