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