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