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