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