From 811a55aec14d6562cba66052366682f3413cfd42 2009-11-09 04:28:08 From: Brian Granger Date: 2009-11-09 04:28:08 Subject: [PATCH] Fixing subtle bug in expanduser(expandvars(path)) on Windows. On Windows, some paths can have the string $\ in them: \\server\users$\%username%. The "$" means it is a hidden share. Unfortunately, os.path.expandvars turns that into: \\server\users\%username% (it deletes the '$'). I have implemented a simple function (expand_path) that calls os.expanduser and os.expandvars in a way that preserves th '$' on Windows in this case. --- diff --git a/IPython/kernel/clusterdir.py b/IPython/kernel/clusterdir.py index ff6394a..46adef6 100644 --- a/IPython/kernel/clusterdir.py +++ b/IPython/kernel/clusterdir.py @@ -29,6 +29,7 @@ from IPython.core.application import Application from IPython.core.component import Component from IPython.config.loader import ArgParseConfigLoader, NoConfigDefault from IPython.utils.traitlets import Unicode, Bool +from IPython.utils import genutils #----------------------------------------------------------------------------- # Imports @@ -216,9 +217,9 @@ class ClusterDir(Component): ---------- cluster_dir : unicode or str The path of the cluster directory. This is expanded using - :func:`os.path.expandvars` and :func:`os.path.expanduser`. + :func:`IPython.utils.genutils.expand_path`. """ - cluster_dir = os.path.expandvars(os.path.expanduser(cluster_dir)) + cluster_dir = genutils.expand_path(cluster_dir) if not os.path.isdir(cluster_dir): raise ClusterDirError('Cluster directory not found: %s' % cluster_dir) return ClusterDir(cluster_dir) @@ -324,7 +325,7 @@ class ApplicationWithClusterDir(Application): cluster_dir = self.command_line_config.Global.cluster_dir except AttributeError: cluster_dir = self.default_config.Global.cluster_dir - cluster_dir = os.path.expandvars(os.path.expanduser(cluster_dir)) + cluster_dir = genutils.expand_path(cluster_dir) try: self.cluster_dir_obj = ClusterDir.find_cluster_dir(cluster_dir) except ClusterDirError: diff --git a/IPython/utils/genutils.py b/IPython/utils/genutils.py index 996cd83..180c7c5 100644 --- a/IPython/utils/genutils.py +++ b/IPython/utils/genutils.py @@ -559,9 +559,7 @@ def filefind(filename, path_dirs=None): path_dirs = (path_dirs,) for path in path_dirs: if path == '.': path = os.getcwd() - testname = os.path.expandvars( - os.path.expanduser( - os.path.join(path, filename))) + testname = expand_path(os.path.join(path, filename)) if os.path.isfile(testname): return os.path.abspath(testname) raise IOError("File does not exist in any " @@ -1740,7 +1738,7 @@ def extract_vars_above(*names): callerNS = sys._getframe(2).f_locals return dict((k,callerNS[k]) for k in names) -def shexp(s): +def expand_path(s): """Expand $VARS and ~names in a string, like a shell :Examples: @@ -1750,8 +1748,17 @@ def shexp(s): In [3]: shexp('variable FOO is $FOO') Out[3]: 'variable FOO is test' """ - return os.path.expandvars(os.path.expanduser(s)) - + # This is a pretty subtle hack. When expand user is given a UNC path + # on Windows (\\server\share$\%username%), os.path.expandvars, removes + # the $ to get (\\server\share\%username%). I think it considered $ + # alone an empty var. But, we need the $ to remains there (it indicates + # a hidden share). + if os.name=='nt': + s.replace('$\\', 'IPYTHON_TEMP') + s2 = os.path.expandvars(os.path.expanduser(s)) + if os.name=='nt': + s2.replace('IPYTHON_TEMP', '$\\') + return s2 def list_strings(arg): """Always return a list of strings, given a string or list of strings