From c1c2a7104aa859c980e0d0506429c0cfab3766ce 2011-02-21 05:42:00 From: MinRK Date: 2011-02-21 05:42:00 Subject: [PATCH] use XDG_CONFIG_HOME if available priority is: $XDG/ipython if both or neither exist $HOME/.ipython if it exists and $XDG/ipython does not exist closes gh-48 closes gh-246 --- diff --git a/IPython/utils/path.py b/IPython/utils/path.py index 69cf58f..5d53dbf 100644 --- a/IPython/utils/path.py +++ b/IPython/utils/path.py @@ -246,6 +246,24 @@ def get_home_dir(): else: raise HomeDirError('No valid home directory could be found for your OS') +def get_xdg_dir(): + """Return the XDG_CONFIG_HOME, if it is defined and exists, else None. + + This is only for posix (Linux,Unix,OS X, etc) systems. + """ + + isdir = os.path.isdir + env = os.environ + + if os.name == 'posix': + # Linux, Unix, AIX, OS X + # use ~/.config if not set OR empty + xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config') + if xdg and isdir(xdg): + return xdg.decode(sys.getfilesystemencoding()) + + return None + def get_ipython_dir(): """Get the IPython directory for this platform and user. @@ -253,14 +271,34 @@ def get_ipython_dir(): This uses the logic in `get_home_dir` to find the home directory and the adds .ipython to the end of the path. """ + + env = os.environ + pjoin = os.path.join + exists = os.path.exists + ipdir_def = '.ipython' + xdg_def = 'ipython' + home_dir = get_home_dir() + xdg_dir = get_xdg_dir() # import pdb; pdb.set_trace() # dbg - ipdir = os.environ.get( - 'IPYTHON_DIR', os.environ.get( - 'IPYTHONDIR', os.path.join(home_dir, ipdir_def) - ) - ) + ipdir = env.get('IPYTHON_DIR', env.get('IPYTHONDIR', None)) + if ipdir is None: + # not set explicitly, use XDG_CONFIG_HOME or HOME + home_ipdir = pjoin(home_dir, ipdir_def) + if xdg_dir: + # use XDG, as long as the user isn't already + # using $HOME/.ipython and *not* XDG/ipython + + xdg_ipdir = pjoin(xdg_dir, xdg_def) + + if exists(xdg_ipdir) or not exists(home_ipdir): + ipdir = xdg_ipdir + + if ipdir is None: + # not using XDG + ipdir = home_ipdir + return ipdir.decode(sys.getfilesystemencoding()) diff --git a/IPython/utils/tests/test_path.py b/IPython/utils/tests/test_path.py index db9a8a8..332d4fb 100644 --- a/IPython/utils/tests/test_path.py +++ b/IPython/utils/tests/test_path.py @@ -46,6 +46,7 @@ env = os.environ TEST_FILE_PATH = split(abspath(__file__))[0] 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") IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython') # # Setup/teardown functions/decorators @@ -59,6 +60,7 @@ def setup(): # Do not mask exceptions here. In particular, catching WindowsError is a # problem because that exception is only defined on Windows... os.makedirs(IP_TEST_DIR) + os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython')) def teardown(): @@ -236,9 +238,93 @@ def test_get_ipython_dir_2(): os.name = "posix" env.pop('IPYTHON_DIR', None) env.pop('IPYTHONDIR', None) + env.pop('XDG_CONFIG_HOME', None) ipdir = path.get_ipython_dir() nt.assert_equal(ipdir, os.path.join("someplace", ".ipython")) +@with_environment +def test_get_ipython_dir_3(): + """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist.""" + path.get_home_dir = lambda : "someplace" + os.name = "posix" + env.pop('IPYTHON_DIR', None) + env.pop('IPYTHONDIR', None) + env['XDG_CONFIG_HOME'] = XDG_TEST_DIR + ipdir = path.get_ipython_dir() + nt.assert_equal(ipdir, os.path.join(XDG_TEST_DIR, "ipython")) + +@with_environment +def test_get_ipython_dir_4(): + """test_get_ipython_dir_4, use XDG if both exist.""" + path.get_home_dir = lambda : HOME_TEST_DIR + os.name = "posix" + env.pop('IPYTHON_DIR', None) + env.pop('IPYTHONDIR', None) + env['XDG_CONFIG_HOME'] = XDG_TEST_DIR + xdg_ipdir = os.path.join(XDG_TEST_DIR, "ipython") + ipdir = path.get_ipython_dir() + nt.assert_equal(ipdir, xdg_ipdir) + +@with_environment +def test_get_ipython_dir_5(): + """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist.""" + os.name = "posix" + env.pop('IPYTHON_DIR', None) + env.pop('IPYTHONDIR', None) + env['XDG_CONFIG_HOME'] = XDG_TEST_DIR + os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython')) + ipdir = path.get_ipython_dir() + nt.assert_equal(ipdir, IP_TEST_DIR) + +@with_environment +def test_get_ipython_dir_6(): + """test_get_ipython_dir_6, use XDG if defined and neither exist.""" + path.get_home_dir = lambda : 'somehome' + path.get_xdg_dir = lambda : 'somexdg' + os.name = "posix" + env.pop('IPYTHON_DIR', None) + env.pop('IPYTHONDIR', None) + xdg_ipdir = os.path.join("somexdg", "ipython") + ipdir = path.get_ipython_dir() + nt.assert_equal(ipdir, xdg_ipdir) + +@with_environment +def test_get_xdg_dir_1(): + """test_get_xdg_dir_1, check xdg_dir""" + reload(path) + path.get_home_dir = lambda : 'somewhere' + os.name = "posix" + env.pop('IPYTHON_DIR', None) + env.pop('IPYTHONDIR', None) + env.pop('XDG_CONFIG_HOME', None) + + nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config')) + + +@with_environment +def test_get_xdg_dir_1(): + """test_get_xdg_dir_1, check nonexistant xdg_dir""" + reload(path) + path.get_home_dir = lambda : HOME_TEST_DIR + os.name = "posix" + env.pop('IPYTHON_DIR', None) + env.pop('IPYTHONDIR', None) + env.pop('XDG_CONFIG_HOME', None) + nt.assert_equal(path.get_xdg_dir(), None) + +@with_environment +def test_get_xdg_dir_2(): + """test_get_xdg_dir_2, check xdg_dir default to ~/.config""" + reload(path) + path.get_home_dir = lambda : HOME_TEST_DIR + os.name = "posix" + env.pop('IPYTHON_DIR', None) + env.pop('IPYTHONDIR', None) + env.pop('XDG_CONFIG_HOME', None) + cfgdir=os.path.join(path.get_home_dir(), '.config') + os.makedirs(cfgdir) + + nt.assert_equal(path.get_xdg_dir(), cfgdir) def test_filefind(): """Various tests for filefind"""