##// END OF EJS Templates
defer to stdlib for path.get_home_dir()...
MinRK -
Show More
@@ -1,521 +1,436 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for path handling.
3 Utilities for path handling.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 import os
17 import os
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 import warnings
20 import warnings
21 from hashlib import md5
21 from hashlib import md5
22
22
23 import IPython
23 import IPython
24 from IPython.utils.process import system
24 from IPython.utils.process import system
25 from IPython.utils.importstring import import_item
25 from IPython.utils.importstring import import_item
26 from IPython.utils import py3compat
26 from IPython.utils import py3compat
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Code
29 # Code
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32 fs_encoding = sys.getfilesystemencoding()
32 fs_encoding = sys.getfilesystemencoding()
33
33
34 def _get_long_path_name(path):
34 def _get_long_path_name(path):
35 """Dummy no-op."""
35 """Dummy no-op."""
36 return path
36 return path
37
37
38 def _writable_dir(path):
38 def _writable_dir(path):
39 """Whether `path` is a directory, to which the user has write access."""
39 """Whether `path` is a directory, to which the user has write access."""
40 return os.path.isdir(path) and os.access(path, os.W_OK)
40 return os.path.isdir(path) and os.access(path, os.W_OK)
41
41
42 if sys.platform == 'win32':
42 if sys.platform == 'win32':
43 def _get_long_path_name(path):
43 def _get_long_path_name(path):
44 """Get a long path name (expand ~) on Windows using ctypes.
44 """Get a long path name (expand ~) on Windows using ctypes.
45
45
46 Examples
46 Examples
47 --------
47 --------
48
48
49 >>> get_long_path_name('c:\\docume~1')
49 >>> get_long_path_name('c:\\docume~1')
50 u'c:\\\\Documents and Settings'
50 u'c:\\\\Documents and Settings'
51
51
52 """
52 """
53 try:
53 try:
54 import ctypes
54 import ctypes
55 except ImportError:
55 except ImportError:
56 raise ImportError('you need to have ctypes installed for this to work')
56 raise ImportError('you need to have ctypes installed for this to work')
57 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
57 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
58 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
58 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
59 ctypes.c_uint ]
59 ctypes.c_uint ]
60
60
61 buf = ctypes.create_unicode_buffer(260)
61 buf = ctypes.create_unicode_buffer(260)
62 rv = _GetLongPathName(path, buf, 260)
62 rv = _GetLongPathName(path, buf, 260)
63 if rv == 0 or rv > 260:
63 if rv == 0 or rv > 260:
64 return path
64 return path
65 else:
65 else:
66 return buf.value
66 return buf.value
67
67
68
68
69 def get_long_path_name(path):
69 def get_long_path_name(path):
70 """Expand a path into its long form.
70 """Expand a path into its long form.
71
71
72 On Windows this expands any ~ in the paths. On other platforms, it is
72 On Windows this expands any ~ in the paths. On other platforms, it is
73 a null operation.
73 a null operation.
74 """
74 """
75 return _get_long_path_name(path)
75 return _get_long_path_name(path)
76
76
77
77
78 def unquote_filename(name, win32=(sys.platform=='win32')):
78 def unquote_filename(name, win32=(sys.platform=='win32')):
79 """ On Windows, remove leading and trailing quotes from filenames.
79 """ On Windows, remove leading and trailing quotes from filenames.
80 """
80 """
81 if win32:
81 if win32:
82 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
82 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
83 name = name[1:-1]
83 name = name[1:-1]
84 return name
84 return name
85
85
86
86
87 def get_py_filename(name, force_win32=None):
87 def get_py_filename(name, force_win32=None):
88 """Return a valid python filename in the current directory.
88 """Return a valid python filename in the current directory.
89
89
90 If the given name is not a file, it adds '.py' and searches again.
90 If the given name is not a file, it adds '.py' and searches again.
91 Raises IOError with an informative message if the file isn't found.
91 Raises IOError with an informative message if the file isn't found.
92
92
93 On Windows, apply Windows semantics to the filename. In particular, remove
93 On Windows, apply Windows semantics to the filename. In particular, remove
94 any quoting that has been applied to it. This option can be forced for
94 any quoting that has been applied to it. This option can be forced for
95 testing purposes.
95 testing purposes.
96 """
96 """
97
97
98 name = os.path.expanduser(name)
98 name = os.path.expanduser(name)
99 if force_win32 is None:
99 if force_win32 is None:
100 win32 = (sys.platform == 'win32')
100 win32 = (sys.platform == 'win32')
101 else:
101 else:
102 win32 = force_win32
102 win32 = force_win32
103 name = unquote_filename(name, win32=win32)
103 name = unquote_filename(name, win32=win32)
104 if not os.path.isfile(name) and not name.endswith('.py'):
104 if not os.path.isfile(name) and not name.endswith('.py'):
105 name += '.py'
105 name += '.py'
106 if os.path.isfile(name):
106 if os.path.isfile(name):
107 return name
107 return name
108 else:
108 else:
109 raise IOError,'File `%s` not found.' % name
109 raise IOError,'File `%s` not found.' % name
110
110
111
111
112 def filefind(filename, path_dirs=None):
112 def filefind(filename, path_dirs=None):
113 """Find a file by looking through a sequence of paths.
113 """Find a file by looking through a sequence of paths.
114
114
115 This iterates through a sequence of paths looking for a file and returns
115 This iterates through a sequence of paths looking for a file and returns
116 the full, absolute path of the first occurence of the file. If no set of
116 the full, absolute path of the first occurence of the file. If no set of
117 path dirs is given, the filename is tested as is, after running through
117 path dirs is given, the filename is tested as is, after running through
118 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
118 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
119
119
120 filefind('myfile.txt')
120 filefind('myfile.txt')
121
121
122 will find the file in the current working dir, but::
122 will find the file in the current working dir, but::
123
123
124 filefind('~/myfile.txt')
124 filefind('~/myfile.txt')
125
125
126 Will find the file in the users home directory. This function does not
126 Will find the file in the users home directory. This function does not
127 automatically try any paths, such as the cwd or the user's home directory.
127 automatically try any paths, such as the cwd or the user's home directory.
128
128
129 Parameters
129 Parameters
130 ----------
130 ----------
131 filename : str
131 filename : str
132 The filename to look for.
132 The filename to look for.
133 path_dirs : str, None or sequence of str
133 path_dirs : str, None or sequence of str
134 The sequence of paths to look for the file in. If None, the filename
134 The sequence of paths to look for the file in. If None, the filename
135 need to be absolute or be in the cwd. If a string, the string is
135 need to be absolute or be in the cwd. If a string, the string is
136 put into a sequence and the searched. If a sequence, walk through
136 put into a sequence and the searched. If a sequence, walk through
137 each element and join with ``filename``, calling :func:`expandvars`
137 each element and join with ``filename``, calling :func:`expandvars`
138 and :func:`expanduser` before testing for existence.
138 and :func:`expanduser` before testing for existence.
139
139
140 Returns
140 Returns
141 -------
141 -------
142 Raises :exc:`IOError` or returns absolute path to file.
142 Raises :exc:`IOError` or returns absolute path to file.
143 """
143 """
144
144
145 # If paths are quoted, abspath gets confused, strip them...
145 # If paths are quoted, abspath gets confused, strip them...
146 filename = filename.strip('"').strip("'")
146 filename = filename.strip('"').strip("'")
147 # If the input is an absolute path, just check it exists
147 # If the input is an absolute path, just check it exists
148 if os.path.isabs(filename) and os.path.isfile(filename):
148 if os.path.isabs(filename) and os.path.isfile(filename):
149 return filename
149 return filename
150
150
151 if path_dirs is None:
151 if path_dirs is None:
152 path_dirs = ("",)
152 path_dirs = ("",)
153 elif isinstance(path_dirs, basestring):
153 elif isinstance(path_dirs, basestring):
154 path_dirs = (path_dirs,)
154 path_dirs = (path_dirs,)
155
155
156 for path in path_dirs:
156 for path in path_dirs:
157 if path == '.': path = os.getcwdu()
157 if path == '.': path = os.getcwdu()
158 testname = expand_path(os.path.join(path, filename))
158 testname = expand_path(os.path.join(path, filename))
159 if os.path.isfile(testname):
159 if os.path.isfile(testname):
160 return os.path.abspath(testname)
160 return os.path.abspath(testname)
161
161
162 raise IOError("File %r does not exist in any of the search paths: %r" %
162 raise IOError("File %r does not exist in any of the search paths: %r" %
163 (filename, path_dirs) )
163 (filename, path_dirs) )
164
164
165
165
166 class HomeDirError(Exception):
166 class HomeDirError(Exception):
167 pass
167 pass
168
168
169
169
170 def get_home_dir():
170 def get_home_dir():
171 """Return the closest possible equivalent to a 'home' directory.
171 """Return the closest possible equivalent to a 'home' directory.
172
172
173 * On POSIX, we try $HOME.
173 * First, check for frozen env in case of py2exe
174 * On Windows we try:
174 * Otherwise, defer to os.path.expanduser('~'), ensuring unicode
175 - %HOMESHARE%
175
176 - %HOMEDRIVE\%HOMEPATH%
176 See stdlib docs for how this is determined.
177 - %USERPROFILE%
177
178 - Registry hack for My Documents
178 $HOME is first priority on *ALL* platforms.
179 - %HOME%: rare, but some people with unix-like setups may have defined it
180 * On Dos C:\
181
182 Currently only Posix and NT are implemented, a HomeDirError exception is
183 raised for all other OSes.
184 """
179 """
185
180
186 env = os.environ
187
188 # first, check py2exe distribution root directory for _ipython.
181 # first, check py2exe distribution root directory for _ipython.
189 # This overrides all. Normally does not exist.
182 # This overrides all. Normally does not exist.
190
183
191 if hasattr(sys, "frozen"): #Is frozen by py2exe
184 if hasattr(sys, "frozen"): #Is frozen by py2exe
192 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
185 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
193 root, rest = IPython.__file__.lower().split('library.zip')
186 root, rest = IPython.__file__.lower().split('library.zip')
194 else:
187 else:
195 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
188 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
196 root=os.path.abspath(root).rstrip('\\')
189 root=os.path.abspath(root).rstrip('\\')
197 if _writable_dir(os.path.join(root, '_ipython')):
190 if _writable_dir(os.path.join(root, '_ipython')):
198 os.environ["IPYKITROOT"] = root
191 os.environ["IPYKITROOT"] = root
199 return py3compat.cast_unicode(root, fs_encoding)
192 return py3compat.cast_unicode(root, fs_encoding)
200
193
201 if os.name == 'posix':
194 homedir = os.path.expanduser('~')
202 # Linux, Unix, AIX, OS X
195 if _writable_dir(homedir):
203 try:
196 return py3compat.cast_unicode(homedir, fs_encoding)
204 homedir = env['HOME']
205 except KeyError:
206 # Last-ditch attempt at finding a suitable $HOME, on systems where
207 # it may not be defined in the environment but the system shell
208 # still knows it - reported once as:
209 # https://github.com/ipython/ipython/issues/154
210 from subprocess import Popen, PIPE
211 homedir = Popen('echo $HOME', shell=True,
212 stdout=PIPE).communicate()[0].strip()
213 if homedir:
214 return py3compat.cast_unicode(homedir, fs_encoding)
215 else:
216 raise HomeDirError('Undefined $HOME, IPython cannot proceed.')
217 else:
218 return py3compat.cast_unicode(homedir, fs_encoding)
219 elif os.name == 'nt':
220 # Now for win9x, XP, Vista, 7?
221 # For some strange reason all of these return 'nt' for os.name.
222 # First look for a network home directory. This will return the UNC
223 # path (\\server\\Users\%username%) not the mapped path (Z:\). This
224 # is needed when running IPython on cluster where all paths have to
225 # be UNC.
226 try:
227 homedir = env['HOMESHARE']
228 except KeyError:
229 pass
230 else:
231 if _writable_dir(homedir):
232 return py3compat.cast_unicode(homedir, fs_encoding)
233
234 # Now look for a local home directory
235 try:
236 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
237 except KeyError:
238 pass
239 else:
240 if _writable_dir(homedir):
241 return py3compat.cast_unicode(homedir, fs_encoding)
242
243 # Now the users profile directory
244 try:
245 homedir = os.path.join(env['USERPROFILE'])
246 except KeyError:
247 pass
248 else:
249 if _writable_dir(homedir):
250 return py3compat.cast_unicode(homedir, fs_encoding)
251
252 # Use the registry to get the 'My Documents' folder.
253 try:
254 import _winreg as wreg
255 key = wreg.OpenKey(
256 wreg.HKEY_CURRENT_USER,
257 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
258 )
259 homedir = wreg.QueryValueEx(key,'Personal')[0]
260 key.Close()
261 except:
262 pass
263 else:
264 if _writable_dir(homedir):
265 return py3compat.cast_unicode(homedir, fs_encoding)
266
267 # A user with a lot of unix tools in win32 may have defined $HOME.
268 # Try this as a last ditch option.
269 try:
270 homedir = env['HOME']
271 except KeyError:
272 pass
273 else:
274 if _writable_dir(homedir):
275 return py3compat.cast_unicode(homedir, fs_encoding)
276
277 # If all else fails, raise HomeDirError
278 raise HomeDirError('No valid home directory could be found')
279 elif os.name == 'dos':
280 # Desperate, may do absurd things in classic MacOS. May work under DOS.
281 return u'C:\\'
282 else:
197 else:
283 raise HomeDirError('No valid home directory could be found for your OS')
198 raise HomeDirError('%s not a writable dir, set $HOME env to override' % homedir)
284
199
285 def get_xdg_dir():
200 def get_xdg_dir():
286 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
201 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
287
202
288 This is only for posix (Linux,Unix,OS X, etc) systems.
203 This is only for posix (Linux,Unix,OS X, etc) systems.
289 """
204 """
290
205
291 env = os.environ
206 env = os.environ
292
207
293 if os.name == 'posix':
208 if os.name == 'posix':
294 # Linux, Unix, AIX, OS X
209 # Linux, Unix, AIX, OS X
295 # use ~/.config if not set OR empty
210 # use ~/.config if not set OR empty
296 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
211 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
297 if xdg and _writable_dir(xdg):
212 if xdg and _writable_dir(xdg):
298 return py3compat.cast_unicode(xdg, fs_encoding)
213 return py3compat.cast_unicode(xdg, fs_encoding)
299
214
300 return None
215 return None
301
216
302
217
303 def get_ipython_dir():
218 def get_ipython_dir():
304 """Get the IPython directory for this platform and user.
219 """Get the IPython directory for this platform and user.
305
220
306 This uses the logic in `get_home_dir` to find the home directory
221 This uses the logic in `get_home_dir` to find the home directory
307 and then adds .ipython to the end of the path.
222 and then adds .ipython to the end of the path.
308 """
223 """
309
224
310 env = os.environ
225 env = os.environ
311 pjoin = os.path.join
226 pjoin = os.path.join
312
227
313
228
314 ipdir_def = '.ipython'
229 ipdir_def = '.ipython'
315 xdg_def = 'ipython'
230 xdg_def = 'ipython'
316
231
317 home_dir = get_home_dir()
232 home_dir = get_home_dir()
318 xdg_dir = get_xdg_dir()
233 xdg_dir = get_xdg_dir()
319 # import pdb; pdb.set_trace() # dbg
234 # import pdb; pdb.set_trace() # dbg
320 ipdir = env.get('IPYTHON_DIR', env.get('IPYTHONDIR', None))
235 ipdir = env.get('IPYTHON_DIR', env.get('IPYTHONDIR', None))
321 if ipdir is None:
236 if ipdir is None:
322 # not set explicitly, use XDG_CONFIG_HOME or HOME
237 # not set explicitly, use XDG_CONFIG_HOME or HOME
323 home_ipdir = pjoin(home_dir, ipdir_def)
238 home_ipdir = pjoin(home_dir, ipdir_def)
324 if xdg_dir:
239 if xdg_dir:
325 # use XDG, as long as the user isn't already
240 # use XDG, as long as the user isn't already
326 # using $HOME/.ipython and *not* XDG/ipython
241 # using $HOME/.ipython and *not* XDG/ipython
327
242
328 xdg_ipdir = pjoin(xdg_dir, xdg_def)
243 xdg_ipdir = pjoin(xdg_dir, xdg_def)
329
244
330 if _writable_dir(xdg_ipdir) or not _writable_dir(home_ipdir):
245 if _writable_dir(xdg_ipdir) or not _writable_dir(home_ipdir):
331 ipdir = xdg_ipdir
246 ipdir = xdg_ipdir
332
247
333 if ipdir is None:
248 if ipdir is None:
334 # not using XDG
249 # not using XDG
335 ipdir = home_ipdir
250 ipdir = home_ipdir
336
251
337 ipdir = os.path.normpath(os.path.expanduser(ipdir))
252 ipdir = os.path.normpath(os.path.expanduser(ipdir))
338
253
339 if os.path.exists(ipdir) and not _writable_dir(ipdir):
254 if os.path.exists(ipdir) and not _writable_dir(ipdir):
340 # ipdir exists, but is not writable
255 # ipdir exists, but is not writable
341 warnings.warn("IPython dir '%s' is not a writable location,"
256 warnings.warn("IPython dir '%s' is not a writable location,"
342 " using a temp directory."%ipdir)
257 " using a temp directory."%ipdir)
343 ipdir = tempfile.mkdtemp()
258 ipdir = tempfile.mkdtemp()
344 elif not os.path.exists(ipdir):
259 elif not os.path.exists(ipdir):
345 parent = ipdir.rsplit(os.path.sep, 1)[0]
260 parent = ipdir.rsplit(os.path.sep, 1)[0]
346 if not _writable_dir(parent):
261 if not _writable_dir(parent):
347 # ipdir does not exist and parent isn't writable
262 # ipdir does not exist and parent isn't writable
348 warnings.warn("IPython parent '%s' is not a writable location,"
263 warnings.warn("IPython parent '%s' is not a writable location,"
349 " using a temp directory."%parent)
264 " using a temp directory."%parent)
350 ipdir = tempfile.mkdtemp()
265 ipdir = tempfile.mkdtemp()
351
266
352 return py3compat.cast_unicode(ipdir, fs_encoding)
267 return py3compat.cast_unicode(ipdir, fs_encoding)
353
268
354
269
355 def get_ipython_package_dir():
270 def get_ipython_package_dir():
356 """Get the base directory where IPython itself is installed."""
271 """Get the base directory where IPython itself is installed."""
357 ipdir = os.path.dirname(IPython.__file__)
272 ipdir = os.path.dirname(IPython.__file__)
358 return py3compat.cast_unicode(ipdir, fs_encoding)
273 return py3compat.cast_unicode(ipdir, fs_encoding)
359
274
360
275
361 def get_ipython_module_path(module_str):
276 def get_ipython_module_path(module_str):
362 """Find the path to an IPython module in this version of IPython.
277 """Find the path to an IPython module in this version of IPython.
363
278
364 This will always find the version of the module that is in this importable
279 This will always find the version of the module that is in this importable
365 IPython package. This will always return the path to the ``.py``
280 IPython package. This will always return the path to the ``.py``
366 version of the module.
281 version of the module.
367 """
282 """
368 if module_str == 'IPython':
283 if module_str == 'IPython':
369 return os.path.join(get_ipython_package_dir(), '__init__.py')
284 return os.path.join(get_ipython_package_dir(), '__init__.py')
370 mod = import_item(module_str)
285 mod = import_item(module_str)
371 the_path = mod.__file__.replace('.pyc', '.py')
286 the_path = mod.__file__.replace('.pyc', '.py')
372 the_path = the_path.replace('.pyo', '.py')
287 the_path = the_path.replace('.pyo', '.py')
373 return py3compat.cast_unicode(the_path, fs_encoding)
288 return py3compat.cast_unicode(the_path, fs_encoding)
374
289
375 def locate_profile(profile='default'):
290 def locate_profile(profile='default'):
376 """Find the path to the folder associated with a given profile.
291 """Find the path to the folder associated with a given profile.
377
292
378 I.e. find $IPYTHON_DIR/profile_whatever.
293 I.e. find $IPYTHON_DIR/profile_whatever.
379 """
294 """
380 from IPython.core.profiledir import ProfileDir, ProfileDirError
295 from IPython.core.profiledir import ProfileDir, ProfileDirError
381 try:
296 try:
382 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
297 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
383 except ProfileDirError:
298 except ProfileDirError:
384 # IOError makes more sense when people are expecting a path
299 # IOError makes more sense when people are expecting a path
385 raise IOError("Couldn't find profile %r" % profile)
300 raise IOError("Couldn't find profile %r" % profile)
386 return pd.location
301 return pd.location
387
302
388 def expand_path(s):
303 def expand_path(s):
389 """Expand $VARS and ~names in a string, like a shell
304 """Expand $VARS and ~names in a string, like a shell
390
305
391 :Examples:
306 :Examples:
392
307
393 In [2]: os.environ['FOO']='test'
308 In [2]: os.environ['FOO']='test'
394
309
395 In [3]: expand_path('variable FOO is $FOO')
310 In [3]: expand_path('variable FOO is $FOO')
396 Out[3]: 'variable FOO is test'
311 Out[3]: 'variable FOO is test'
397 """
312 """
398 # This is a pretty subtle hack. When expand user is given a UNC path
313 # This is a pretty subtle hack. When expand user is given a UNC path
399 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
314 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
400 # the $ to get (\\server\share\%username%). I think it considered $
315 # the $ to get (\\server\share\%username%). I think it considered $
401 # alone an empty var. But, we need the $ to remains there (it indicates
316 # alone an empty var. But, we need the $ to remains there (it indicates
402 # a hidden share).
317 # a hidden share).
403 if os.name=='nt':
318 if os.name=='nt':
404 s = s.replace('$\\', 'IPYTHON_TEMP')
319 s = s.replace('$\\', 'IPYTHON_TEMP')
405 s = os.path.expandvars(os.path.expanduser(s))
320 s = os.path.expandvars(os.path.expanduser(s))
406 if os.name=='nt':
321 if os.name=='nt':
407 s = s.replace('IPYTHON_TEMP', '$\\')
322 s = s.replace('IPYTHON_TEMP', '$\\')
408 return s
323 return s
409
324
410
325
411 def target_outdated(target,deps):
326 def target_outdated(target,deps):
412 """Determine whether a target is out of date.
327 """Determine whether a target is out of date.
413
328
414 target_outdated(target,deps) -> 1/0
329 target_outdated(target,deps) -> 1/0
415
330
416 deps: list of filenames which MUST exist.
331 deps: list of filenames which MUST exist.
417 target: single filename which may or may not exist.
332 target: single filename which may or may not exist.
418
333
419 If target doesn't exist or is older than any file listed in deps, return
334 If target doesn't exist or is older than any file listed in deps, return
420 true, otherwise return false.
335 true, otherwise return false.
421 """
336 """
422 try:
337 try:
423 target_time = os.path.getmtime(target)
338 target_time = os.path.getmtime(target)
424 except os.error:
339 except os.error:
425 return 1
340 return 1
426 for dep in deps:
341 for dep in deps:
427 dep_time = os.path.getmtime(dep)
342 dep_time = os.path.getmtime(dep)
428 if dep_time > target_time:
343 if dep_time > target_time:
429 #print "For target",target,"Dep failed:",dep # dbg
344 #print "For target",target,"Dep failed:",dep # dbg
430 #print "times (dep,tar):",dep_time,target_time # dbg
345 #print "times (dep,tar):",dep_time,target_time # dbg
431 return 1
346 return 1
432 return 0
347 return 0
433
348
434
349
435 def target_update(target,deps,cmd):
350 def target_update(target,deps,cmd):
436 """Update a target with a given command given a list of dependencies.
351 """Update a target with a given command given a list of dependencies.
437
352
438 target_update(target,deps,cmd) -> runs cmd if target is outdated.
353 target_update(target,deps,cmd) -> runs cmd if target is outdated.
439
354
440 This is just a wrapper around target_outdated() which calls the given
355 This is just a wrapper around target_outdated() which calls the given
441 command if target is outdated."""
356 command if target is outdated."""
442
357
443 if target_outdated(target,deps):
358 if target_outdated(target,deps):
444 system(cmd)
359 system(cmd)
445
360
446 def filehash(path):
361 def filehash(path):
447 """Make an MD5 hash of a file, ignoring any differences in line
362 """Make an MD5 hash of a file, ignoring any differences in line
448 ending characters."""
363 ending characters."""
449 with open(path, "rU") as f:
364 with open(path, "rU") as f:
450 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
365 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
451
366
452 # If the config is unmodified from the default, we'll just delete it.
367 # If the config is unmodified from the default, we'll just delete it.
453 # These are consistent for 0.10.x, thankfully. We're not going to worry about
368 # These are consistent for 0.10.x, thankfully. We're not going to worry about
454 # older versions.
369 # older versions.
455 old_config_md5 = {'ipy_user_conf.py': 'fc108bedff4b9a00f91fa0a5999140d3',
370 old_config_md5 = {'ipy_user_conf.py': 'fc108bedff4b9a00f91fa0a5999140d3',
456 'ipythonrc': '12a68954f3403eea2eec09dc8fe5a9b5'}
371 'ipythonrc': '12a68954f3403eea2eec09dc8fe5a9b5'}
457
372
458 def check_for_old_config(ipython_dir=None):
373 def check_for_old_config(ipython_dir=None):
459 """Check for old config files, and present a warning if they exist.
374 """Check for old config files, and present a warning if they exist.
460
375
461 A link to the docs of the new config is included in the message.
376 A link to the docs of the new config is included in the message.
462
377
463 This should mitigate confusion with the transition to the new
378 This should mitigate confusion with the transition to the new
464 config system in 0.11.
379 config system in 0.11.
465 """
380 """
466 if ipython_dir is None:
381 if ipython_dir is None:
467 ipython_dir = get_ipython_dir()
382 ipython_dir = get_ipython_dir()
468
383
469 old_configs = ['ipy_user_conf.py', 'ipythonrc', 'ipython_config.py']
384 old_configs = ['ipy_user_conf.py', 'ipythonrc', 'ipython_config.py']
470 warned = False
385 warned = False
471 for cfg in old_configs:
386 for cfg in old_configs:
472 f = os.path.join(ipython_dir, cfg)
387 f = os.path.join(ipython_dir, cfg)
473 if os.path.exists(f):
388 if os.path.exists(f):
474 if filehash(f) == old_config_md5.get(cfg, ''):
389 if filehash(f) == old_config_md5.get(cfg, ''):
475 os.unlink(f)
390 os.unlink(f)
476 else:
391 else:
477 warnings.warn("Found old IPython config file %r (modified by user)"%f)
392 warnings.warn("Found old IPython config file %r (modified by user)"%f)
478 warned = True
393 warned = True
479
394
480 if warned:
395 if warned:
481 warnings.warn("""
396 warnings.warn("""
482 The IPython configuration system has changed as of 0.11, and these files will
397 The IPython configuration system has changed as of 0.11, and these files will
483 be ignored. See http://ipython.github.com/ipython-doc/dev/config for details
398 be ignored. See http://ipython.github.com/ipython-doc/dev/config for details
484 of the new config system.
399 of the new config system.
485 To start configuring IPython, do `ipython profile create`, and edit
400 To start configuring IPython, do `ipython profile create`, and edit
486 `ipython_config.py` in <ipython_dir>/profile_default.
401 `ipython_config.py` in <ipython_dir>/profile_default.
487 If you need to leave the old config files in place for an older version of
402 If you need to leave the old config files in place for an older version of
488 IPython and want to suppress this warning message, set
403 IPython and want to suppress this warning message, set
489 `c.InteractiveShellApp.ignore_old_config=True` in the new config.""")
404 `c.InteractiveShellApp.ignore_old_config=True` in the new config.""")
490
405
491 def get_security_file(filename, profile='default'):
406 def get_security_file(filename, profile='default'):
492 """Return the absolute path of a security file given by filename and profile
407 """Return the absolute path of a security file given by filename and profile
493
408
494 This allows users and developers to find security files without
409 This allows users and developers to find security files without
495 knowledge of the IPython directory structure. The search path
410 knowledge of the IPython directory structure. The search path
496 will be ['.', profile.security_dir]
411 will be ['.', profile.security_dir]
497
412
498 Parameters
413 Parameters
499 ----------
414 ----------
500
415
501 filename : str
416 filename : str
502 The file to be found. If it is passed as an absolute path, it will
417 The file to be found. If it is passed as an absolute path, it will
503 simply be returned.
418 simply be returned.
504 profile : str [default: 'default']
419 profile : str [default: 'default']
505 The name of the profile to search. Leaving this unspecified
420 The name of the profile to search. Leaving this unspecified
506 The file to be found. If it is passed as an absolute path, fname will
421 The file to be found. If it is passed as an absolute path, fname will
507 simply be returned.
422 simply be returned.
508
423
509 Returns
424 Returns
510 -------
425 -------
511 Raises :exc:`IOError` if file not found or returns absolute path to file.
426 Raises :exc:`IOError` if file not found or returns absolute path to file.
512 """
427 """
513 # import here, because profiledir also imports from utils.path
428 # import here, because profiledir also imports from utils.path
514 from IPython.core.profiledir import ProfileDir
429 from IPython.core.profiledir import ProfileDir
515 try:
430 try:
516 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
431 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
517 except Exception:
432 except Exception:
518 # will raise ProfileDirError if no such profile
433 # will raise ProfileDirError if no such profile
519 raise IOError("Profile %r not found")
434 raise IOError("Profile %r not found")
520 return filefind(filename, ['.', pd.security_dir])
435 return filefind(filename, ['.', pd.security_dir])
521
436
@@ -1,445 +1,375 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.path.py"""
2 """Tests for IPython.utils.path.py"""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2008 The IPython Development Team
5 # Copyright (C) 2008 The IPython Development Team
6 #
6 #
7 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
8 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 from __future__ import with_statement
15 from __future__ import with_statement
16
16
17 import os
17 import os
18 import shutil
18 import shutil
19 import sys
19 import sys
20 import tempfile
20 import tempfile
21 from io import StringIO
21 from io import StringIO
22
22
23 from os.path import join, abspath, split
23 from os.path import join, abspath, split
24
24
25 import nose.tools as nt
25 import nose.tools as nt
26
26
27 from nose import with_setup
27 from nose import with_setup
28
28
29 import IPython
29 import IPython
30 from IPython.testing import decorators as dec
30 from IPython.testing import decorators as dec
31 from IPython.testing.decorators import skip_if_not_win32, skip_win32
31 from IPython.testing.decorators import skip_if_not_win32, skip_win32
32 from IPython.testing.tools import make_tempfile, AssertPrints
32 from IPython.testing.tools import make_tempfile, AssertPrints
33 from IPython.utils import path, io
33 from IPython.utils import path, io
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35
35
36 # Platform-dependent imports
36 # Platform-dependent imports
37 try:
37 try:
38 import _winreg as wreg
38 import _winreg as wreg
39 except ImportError:
39 except ImportError:
40 #Fake _winreg module on none windows platforms
40 #Fake _winreg module on none windows platforms
41 import types
41 import types
42 wr_name = "winreg" if py3compat.PY3 else "_winreg"
42 wr_name = "winreg" if py3compat.PY3 else "_winreg"
43 sys.modules[wr_name] = types.ModuleType(wr_name)
43 sys.modules[wr_name] = types.ModuleType(wr_name)
44 import _winreg as wreg
44 import _winreg as wreg
45 #Add entries that needs to be stubbed by the testing code
45 #Add entries that needs to be stubbed by the testing code
46 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
46 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
47
47
48 try:
48 try:
49 reload
49 reload
50 except NameError: # Python 3
50 except NameError: # Python 3
51 from imp import reload
51 from imp import reload
52
52
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54 # Globals
54 # Globals
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56 env = os.environ
56 env = os.environ
57 TEST_FILE_PATH = split(abspath(__file__))[0]
57 TEST_FILE_PATH = split(abspath(__file__))[0]
58 TMP_TEST_DIR = tempfile.mkdtemp()
58 TMP_TEST_DIR = tempfile.mkdtemp()
59 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
59 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
60 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
60 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
61 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
61 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
62 #
62 #
63 # Setup/teardown functions/decorators
63 # Setup/teardown functions/decorators
64 #
64 #
65
65
66 def setup():
66 def setup():
67 """Setup testenvironment for the module:
67 """Setup testenvironment for the module:
68
68
69 - Adds dummy home dir tree
69 - Adds dummy home dir tree
70 """
70 """
71 # Do not mask exceptions here. In particular, catching WindowsError is a
71 # Do not mask exceptions here. In particular, catching WindowsError is a
72 # problem because that exception is only defined on Windows...
72 # problem because that exception is only defined on Windows...
73 os.makedirs(IP_TEST_DIR)
73 os.makedirs(IP_TEST_DIR)
74 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
74 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
75
75
76
76
77 def teardown():
77 def teardown():
78 """Teardown testenvironment for the module:
78 """Teardown testenvironment for the module:
79
79
80 - Remove dummy home dir tree
80 - Remove dummy home dir tree
81 """
81 """
82 # Note: we remove the parent test dir, which is the root of all test
82 # Note: we remove the parent test dir, which is the root of all test
83 # subdirs we may have created. Use shutil instead of os.removedirs, so
83 # subdirs we may have created. Use shutil instead of os.removedirs, so
84 # that non-empty directories are all recursively removed.
84 # that non-empty directories are all recursively removed.
85 shutil.rmtree(TMP_TEST_DIR)
85 shutil.rmtree(TMP_TEST_DIR)
86
86
87
87
88 def setup_environment():
88 def setup_environment():
89 """Setup testenvironment for some functions that are tested
89 """Setup testenvironment for some functions that are tested
90 in this module. In particular this functions stores attributes
90 in this module. In particular this functions stores attributes
91 and other things that we need to stub in some test functions.
91 and other things that we need to stub in some test functions.
92 This needs to be done on a function level and not module level because
92 This needs to be done on a function level and not module level because
93 each testfunction needs a pristine environment.
93 each testfunction needs a pristine environment.
94 """
94 """
95 global oldstuff, platformstuff
95 global oldstuff, platformstuff
96 oldstuff = (env.copy(), os.name, path.get_home_dir, IPython.__file__, os.getcwd())
96 oldstuff = (env.copy(), os.name, path.get_home_dir, IPython.__file__, os.getcwd())
97
97
98 if os.name == 'nt':
98 if os.name == 'nt':
99 platformstuff = (wreg.OpenKey, wreg.QueryValueEx,)
99 platformstuff = (wreg.OpenKey, wreg.QueryValueEx,)
100
100
101
101
102 def teardown_environment():
102 def teardown_environment():
103 """Restore things that were remebered by the setup_environment function
103 """Restore things that were remebered by the setup_environment function
104 """
104 """
105 (oldenv, os.name, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
105 (oldenv, os.name, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
106 os.chdir(old_wd)
106 os.chdir(old_wd)
107 reload(path)
107 reload(path)
108
108
109 for key in env.keys():
109 for key in env.keys():
110 if key not in oldenv:
110 if key not in oldenv:
111 del env[key]
111 del env[key]
112 env.update(oldenv)
112 env.update(oldenv)
113 if hasattr(sys, 'frozen'):
113 if hasattr(sys, 'frozen'):
114 del sys.frozen
114 del sys.frozen
115 if os.name == 'nt':
115 if os.name == 'nt':
116 (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff
116 (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff
117
117
118 # Build decorator that uses the setup_environment/setup_environment
118 # Build decorator that uses the setup_environment/setup_environment
119 with_environment = with_setup(setup_environment, teardown_environment)
119 with_environment = with_setup(setup_environment, teardown_environment)
120
120
121
122 @skip_if_not_win32
121 @skip_if_not_win32
123 @with_environment
122 @with_environment
124 def test_get_home_dir_1():
123 def test_get_home_dir_1():
125 """Testcase for py2exe logic, un-compressed lib
124 """Testcase for py2exe logic, un-compressed lib
126 """
125 """
127 sys.frozen = True
126 sys.frozen = True
128
127
129 #fake filename for IPython.__init__
128 #fake filename for IPython.__init__
130 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
129 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
131
130
132 home_dir = path.get_home_dir()
131 home_dir = path.get_home_dir()
133 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
132 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
134
133
135
134
136 @skip_if_not_win32
135 @skip_if_not_win32
137 @with_environment
136 @with_environment
138 def test_get_home_dir_2():
137 def test_get_home_dir_2():
139 """Testcase for py2exe logic, compressed lib
138 """Testcase for py2exe logic, compressed lib
140 """
139 """
141 sys.frozen = True
140 sys.frozen = True
142 #fake filename for IPython.__init__
141 #fake filename for IPython.__init__
143 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
142 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
144
143
145 home_dir = path.get_home_dir()
144 home_dir = path.get_home_dir()
146 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower())
145 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower())
147
146
148
147
149 @with_environment
148 @with_environment
150 @skip_win32
151 def test_get_home_dir_3():
149 def test_get_home_dir_3():
152 """Testcase $HOME is set, then use its value as home directory."""
150 """get_home_dir() uses $HOME if set"""
153 env["HOME"] = HOME_TEST_DIR
151 env["HOME"] = HOME_TEST_DIR
154 home_dir = path.get_home_dir()
152 home_dir = path.get_home_dir()
155 nt.assert_equal(home_dir, env["HOME"])
153 nt.assert_equal(home_dir, env["HOME"])
156
154
157
155
158 @with_environment
156 @with_environment
159 @skip_win32
160 def test_get_home_dir_4():
157 def test_get_home_dir_4():
161 """Testcase $HOME is not set, os=='posix'.
158 """get_home_dir() still works if $HOME is not set"""
162 This should fail with HomeDirError"""
163
159
164 os.name = 'posix'
165 if 'HOME' in env: del env['HOME']
160 if 'HOME' in env: del env['HOME']
166 nt.assert_raises(path.HomeDirError, path.get_home_dir)
161 # this should still succeed, but we don't know what the answer should be
167
162 home = path.get_home_dir()
163 nt.assert_true(path._writable_dir(home))
168
164
169 @skip_if_not_win32
170 @with_environment
165 @with_environment
171 def test_get_home_dir_5():
166 def test_get_home_dir_5():
172 """Using HOMEDRIVE + HOMEPATH, os=='nt'.
167 """raise HomeDirError if $HOME is specified, but not a writable dir"""
173
168 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
174 HOMESHARE is missing.
169 nt.assert_raises(path.HomeDirError, path.get_home_dir)
175 """
176
177 os.name = 'nt'
178 env.pop('HOMESHARE', None)
179 env['HOMEDRIVE'], env['HOMEPATH'] = os.path.splitdrive(HOME_TEST_DIR)
180 home_dir = path.get_home_dir()
181 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
182
183
184 @skip_if_not_win32
185 @with_environment
186 def test_get_home_dir_6():
187 """Using USERPROFILE, os=='nt'.
188
189 HOMESHARE, HOMEDRIVE, HOMEPATH are missing.
190 """
191
192 os.name = 'nt'
193 env.pop('HOMESHARE', None)
194 env.pop('HOMEDRIVE', None)
195 env.pop('HOMEPATH', None)
196 env["USERPROFILE"] = abspath(HOME_TEST_DIR)
197 home_dir = path.get_home_dir()
198 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
199
200
201 @skip_if_not_win32
202 @with_environment
203 def test_get_home_dir_7():
204 """Using HOMESHARE, os=='nt'."""
205
206 os.name = 'nt'
207 env["HOMESHARE"] = abspath(HOME_TEST_DIR)
208 home_dir = path.get_home_dir()
209 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
210
211
212 # Should we stub wreg fully so we can run the test on all platforms?
213 @skip_if_not_win32
214 @with_environment
215 def test_get_home_dir_8():
216 """Using registry hack for 'My Documents', os=='nt'
217
218 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
219 """
220 os.name = 'nt'
221 # Remove from stub environment all keys that may be set
222 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
223 env.pop(key, None)
224
225 #Stub windows registry functions
226 def OpenKey(x, y):
227 class key:
228 def Close(self):
229 pass
230 return key()
231 def QueryValueEx(x, y):
232 return [abspath(HOME_TEST_DIR)]
233
234 wreg.OpenKey = OpenKey
235 wreg.QueryValueEx = QueryValueEx
236
237 home_dir = path.get_home_dir()
238 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
239
240
170
241 @with_environment
171 @with_environment
242 def test_get_ipython_dir_1():
172 def test_get_ipython_dir_1():
243 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
173 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
244 env_ipdir = os.path.join("someplace", ".ipython")
174 env_ipdir = os.path.join("someplace", ".ipython")
245 path._writable_dir = lambda path: True
175 path._writable_dir = lambda path: True
246 env['IPYTHON_DIR'] = env_ipdir
176 env['IPYTHON_DIR'] = env_ipdir
247 ipdir = path.get_ipython_dir()
177 ipdir = path.get_ipython_dir()
248 nt.assert_equal(ipdir, env_ipdir)
178 nt.assert_equal(ipdir, env_ipdir)
249
179
250
180
251 @with_environment
181 @with_environment
252 def test_get_ipython_dir_2():
182 def test_get_ipython_dir_2():
253 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
183 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
254 path.get_home_dir = lambda : "someplace"
184 path.get_home_dir = lambda : "someplace"
255 path.get_xdg_dir = lambda : None
185 path.get_xdg_dir = lambda : None
256 path._writable_dir = lambda path: True
186 path._writable_dir = lambda path: True
257 os.name = "posix"
187 os.name = "posix"
258 env.pop('IPYTHON_DIR', None)
188 env.pop('IPYTHON_DIR', None)
259 env.pop('IPYTHONDIR', None)
189 env.pop('IPYTHONDIR', None)
260 env.pop('XDG_CONFIG_HOME', None)
190 env.pop('XDG_CONFIG_HOME', None)
261 ipdir = path.get_ipython_dir()
191 ipdir = path.get_ipython_dir()
262 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
192 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
263
193
264 @with_environment
194 @with_environment
265 def test_get_ipython_dir_3():
195 def test_get_ipython_dir_3():
266 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
196 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
267 path.get_home_dir = lambda : "someplace"
197 path.get_home_dir = lambda : "someplace"
268 path._writable_dir = lambda path: True
198 path._writable_dir = lambda path: True
269 os.name = "posix"
199 os.name = "posix"
270 env.pop('IPYTHON_DIR', None)
200 env.pop('IPYTHON_DIR', None)
271 env.pop('IPYTHONDIR', None)
201 env.pop('IPYTHONDIR', None)
272 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
202 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
273 ipdir = path.get_ipython_dir()
203 ipdir = path.get_ipython_dir()
274 nt.assert_equal(ipdir, os.path.join(XDG_TEST_DIR, "ipython"))
204 nt.assert_equal(ipdir, os.path.join(XDG_TEST_DIR, "ipython"))
275
205
276 @with_environment
206 @with_environment
277 def test_get_ipython_dir_4():
207 def test_get_ipython_dir_4():
278 """test_get_ipython_dir_4, use XDG if both exist."""
208 """test_get_ipython_dir_4, use XDG if both exist."""
279 path.get_home_dir = lambda : HOME_TEST_DIR
209 path.get_home_dir = lambda : HOME_TEST_DIR
280 os.name = "posix"
210 os.name = "posix"
281 env.pop('IPYTHON_DIR', None)
211 env.pop('IPYTHON_DIR', None)
282 env.pop('IPYTHONDIR', None)
212 env.pop('IPYTHONDIR', None)
283 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
213 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
284 xdg_ipdir = os.path.join(XDG_TEST_DIR, "ipython")
214 xdg_ipdir = os.path.join(XDG_TEST_DIR, "ipython")
285 ipdir = path.get_ipython_dir()
215 ipdir = path.get_ipython_dir()
286 nt.assert_equal(ipdir, xdg_ipdir)
216 nt.assert_equal(ipdir, xdg_ipdir)
287
217
288 @with_environment
218 @with_environment
289 def test_get_ipython_dir_5():
219 def test_get_ipython_dir_5():
290 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
220 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
291 path.get_home_dir = lambda : HOME_TEST_DIR
221 path.get_home_dir = lambda : HOME_TEST_DIR
292 os.name = "posix"
222 os.name = "posix"
293 env.pop('IPYTHON_DIR', None)
223 env.pop('IPYTHON_DIR', None)
294 env.pop('IPYTHONDIR', None)
224 env.pop('IPYTHONDIR', None)
295 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
225 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
296 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
226 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
297 ipdir = path.get_ipython_dir()
227 ipdir = path.get_ipython_dir()
298 nt.assert_equal(ipdir, IP_TEST_DIR)
228 nt.assert_equal(ipdir, IP_TEST_DIR)
299
229
300 @with_environment
230 @with_environment
301 def test_get_ipython_dir_6():
231 def test_get_ipython_dir_6():
302 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
232 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
303 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
233 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
304 os.mkdir(xdg)
234 os.mkdir(xdg)
305 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
235 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
306 path.get_home_dir = lambda : HOME_TEST_DIR
236 path.get_home_dir = lambda : HOME_TEST_DIR
307 path.get_xdg_dir = lambda : xdg
237 path.get_xdg_dir = lambda : xdg
308 os.name = "posix"
238 os.name = "posix"
309 env.pop('IPYTHON_DIR', None)
239 env.pop('IPYTHON_DIR', None)
310 env.pop('IPYTHONDIR', None)
240 env.pop('IPYTHONDIR', None)
311 env.pop('XDG_CONFIG_HOME', None)
241 env.pop('XDG_CONFIG_HOME', None)
312 xdg_ipdir = os.path.join(xdg, "ipython")
242 xdg_ipdir = os.path.join(xdg, "ipython")
313 ipdir = path.get_ipython_dir()
243 ipdir = path.get_ipython_dir()
314 nt.assert_equal(ipdir, xdg_ipdir)
244 nt.assert_equal(ipdir, xdg_ipdir)
315
245
316 @with_environment
246 @with_environment
317 def test_get_ipython_dir_7():
247 def test_get_ipython_dir_7():
318 """test_get_ipython_dir_7, test home directory expansion on IPYTHON_DIR"""
248 """test_get_ipython_dir_7, test home directory expansion on IPYTHON_DIR"""
319 path._writable_dir = lambda path: True
249 path._writable_dir = lambda path: True
320 home_dir = os.path.expanduser('~')
250 home_dir = os.path.expanduser('~')
321 env['IPYTHON_DIR'] = os.path.join('~', 'somewhere')
251 env['IPYTHON_DIR'] = os.path.join('~', 'somewhere')
322 ipdir = path.get_ipython_dir()
252 ipdir = path.get_ipython_dir()
323 nt.assert_equal(ipdir, os.path.join(home_dir, 'somewhere'))
253 nt.assert_equal(ipdir, os.path.join(home_dir, 'somewhere'))
324
254
325
255
326 @with_environment
256 @with_environment
327 def test_get_xdg_dir_1():
257 def test_get_xdg_dir_1():
328 """test_get_xdg_dir_1, check xdg_dir"""
258 """test_get_xdg_dir_1, check xdg_dir"""
329 reload(path)
259 reload(path)
330 path._writable_dir = lambda path: True
260 path._writable_dir = lambda path: True
331 path.get_home_dir = lambda : 'somewhere'
261 path.get_home_dir = lambda : 'somewhere'
332 os.name = "posix"
262 os.name = "posix"
333 env.pop('IPYTHON_DIR', None)
263 env.pop('IPYTHON_DIR', None)
334 env.pop('IPYTHONDIR', None)
264 env.pop('IPYTHONDIR', None)
335 env.pop('XDG_CONFIG_HOME', None)
265 env.pop('XDG_CONFIG_HOME', None)
336
266
337 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
267 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
338
268
339
269
340 @with_environment
270 @with_environment
341 def test_get_xdg_dir_1():
271 def test_get_xdg_dir_1():
342 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
272 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
343 reload(path)
273 reload(path)
344 path.get_home_dir = lambda : HOME_TEST_DIR
274 path.get_home_dir = lambda : HOME_TEST_DIR
345 os.name = "posix"
275 os.name = "posix"
346 env.pop('IPYTHON_DIR', None)
276 env.pop('IPYTHON_DIR', None)
347 env.pop('IPYTHONDIR', None)
277 env.pop('IPYTHONDIR', None)
348 env.pop('XDG_CONFIG_HOME', None)
278 env.pop('XDG_CONFIG_HOME', None)
349 nt.assert_equal(path.get_xdg_dir(), None)
279 nt.assert_equal(path.get_xdg_dir(), None)
350
280
351 @with_environment
281 @with_environment
352 def test_get_xdg_dir_2():
282 def test_get_xdg_dir_2():
353 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
283 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
354 reload(path)
284 reload(path)
355 path.get_home_dir = lambda : HOME_TEST_DIR
285 path.get_home_dir = lambda : HOME_TEST_DIR
356 os.name = "posix"
286 os.name = "posix"
357 env.pop('IPYTHON_DIR', None)
287 env.pop('IPYTHON_DIR', None)
358 env.pop('IPYTHONDIR', None)
288 env.pop('IPYTHONDIR', None)
359 env.pop('XDG_CONFIG_HOME', None)
289 env.pop('XDG_CONFIG_HOME', None)
360 cfgdir=os.path.join(path.get_home_dir(), '.config')
290 cfgdir=os.path.join(path.get_home_dir(), '.config')
361 os.makedirs(cfgdir)
291 os.makedirs(cfgdir)
362
292
363 nt.assert_equal(path.get_xdg_dir(), cfgdir)
293 nt.assert_equal(path.get_xdg_dir(), cfgdir)
364
294
365 def test_filefind():
295 def test_filefind():
366 """Various tests for filefind"""
296 """Various tests for filefind"""
367 f = tempfile.NamedTemporaryFile()
297 f = tempfile.NamedTemporaryFile()
368 # print 'fname:',f.name
298 # print 'fname:',f.name
369 alt_dirs = path.get_ipython_dir()
299 alt_dirs = path.get_ipython_dir()
370 t = path.filefind(f.name, alt_dirs)
300 t = path.filefind(f.name, alt_dirs)
371 # print 'found:',t
301 # print 'found:',t
372
302
373
303
374 def test_get_ipython_package_dir():
304 def test_get_ipython_package_dir():
375 ipdir = path.get_ipython_package_dir()
305 ipdir = path.get_ipython_package_dir()
376 nt.assert_true(os.path.isdir(ipdir))
306 nt.assert_true(os.path.isdir(ipdir))
377
307
378
308
379 def test_get_ipython_module_path():
309 def test_get_ipython_module_path():
380 ipapp_path = path.get_ipython_module_path('IPython.frontend.terminal.ipapp')
310 ipapp_path = path.get_ipython_module_path('IPython.frontend.terminal.ipapp')
381 nt.assert_true(os.path.isfile(ipapp_path))
311 nt.assert_true(os.path.isfile(ipapp_path))
382
312
383
313
384 @dec.skip_if_not_win32
314 @dec.skip_if_not_win32
385 def test_get_long_path_name_win32():
315 def test_get_long_path_name_win32():
386 p = path.get_long_path_name('c:\\docume~1')
316 p = path.get_long_path_name('c:\\docume~1')
387 nt.assert_equals(p,u'c:\\Documents and Settings')
317 nt.assert_equals(p,u'c:\\Documents and Settings')
388
318
389
319
390 @dec.skip_win32
320 @dec.skip_win32
391 def test_get_long_path_name():
321 def test_get_long_path_name():
392 p = path.get_long_path_name('/usr/local')
322 p = path.get_long_path_name('/usr/local')
393 nt.assert_equals(p,'/usr/local')
323 nt.assert_equals(p,'/usr/local')
394
324
395 @dec.skip_win32 # can't create not-user-writable dir on win
325 @dec.skip_win32 # can't create not-user-writable dir on win
396 @with_environment
326 @with_environment
397 def test_not_writable_ipdir():
327 def test_not_writable_ipdir():
398 tmpdir = tempfile.mkdtemp()
328 tmpdir = tempfile.mkdtemp()
399 os.name = "posix"
329 os.name = "posix"
400 env.pop('IPYTHON_DIR', None)
330 env.pop('IPYTHON_DIR', None)
401 env.pop('IPYTHONDIR', None)
331 env.pop('IPYTHONDIR', None)
402 env.pop('XDG_CONFIG_HOME', None)
332 env.pop('XDG_CONFIG_HOME', None)
403 env['HOME'] = tmpdir
333 env['HOME'] = tmpdir
404 ipdir = os.path.join(tmpdir, '.ipython')
334 ipdir = os.path.join(tmpdir, '.ipython')
405 os.mkdir(ipdir)
335 os.mkdir(ipdir)
406 os.chmod(ipdir, 600)
336 os.chmod(ipdir, 600)
407 with AssertPrints('is not a writable location', channel='stderr'):
337 with AssertPrints('is not a writable location', channel='stderr'):
408 ipdir = path.get_ipython_dir()
338 ipdir = path.get_ipython_dir()
409 env.pop('IPYTHON_DIR', None)
339 env.pop('IPYTHON_DIR', None)
410
340
411 def test_unquote_filename():
341 def test_unquote_filename():
412 for win32 in (True, False):
342 for win32 in (True, False):
413 nt.assert_equals(path.unquote_filename('foo.py', win32=win32), 'foo.py')
343 nt.assert_equals(path.unquote_filename('foo.py', win32=win32), 'foo.py')
414 nt.assert_equals(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
344 nt.assert_equals(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
415 nt.assert_equals(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
345 nt.assert_equals(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
416 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
346 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
417 nt.assert_equals(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
347 nt.assert_equals(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
418 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
348 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
419 nt.assert_equals(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
349 nt.assert_equals(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
420 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
350 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
421 nt.assert_equals(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
351 nt.assert_equals(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
422 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
352 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
423
353
424 @with_environment
354 @with_environment
425 def test_get_py_filename():
355 def test_get_py_filename():
426 os.chdir(TMP_TEST_DIR)
356 os.chdir(TMP_TEST_DIR)
427 for win32 in (True, False):
357 for win32 in (True, False):
428 with make_tempfile('foo.py'):
358 with make_tempfile('foo.py'):
429 nt.assert_equals(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
359 nt.assert_equals(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
430 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo.py')
360 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo.py')
431 with make_tempfile('foo'):
361 with make_tempfile('foo'):
432 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo')
362 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo')
433 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
363 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
434 nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32)
364 nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32)
435 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
365 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
436 true_fn = 'foo with spaces.py'
366 true_fn = 'foo with spaces.py'
437 with make_tempfile(true_fn):
367 with make_tempfile(true_fn):
438 nt.assert_equals(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
368 nt.assert_equals(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
439 nt.assert_equals(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
369 nt.assert_equals(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
440 if win32:
370 if win32:
441 nt.assert_equals(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
371 nt.assert_equals(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
442 nt.assert_equals(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
372 nt.assert_equals(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
443 else:
373 else:
444 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False)
374 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False)
445 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)
375 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)
General Comments 0
You need to be logged in to leave comments. Login now