##// END OF EJS Templates
restore My Documents fallback for get_home_dir on Windows
MinRK -
Show More
@@ -1,446 +1,461 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-2009 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 `%s` 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
205 if not _writable_dir(homedir) and os.name == 'nt':
206 # expanduser failed, use the registry to get the 'My Documents' folder.
207 try:
208 import _winreg as wreg
209 key = wreg.OpenKey(
210 wreg.HKEY_CURRENT_USER,
211 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
212 )
213 homedir = wreg.QueryValueEx(key,'Personal')[0]
214 key.Close()
215 except:
216 pass
217
204 218 if (not require_writable) or _writable_dir(homedir):
205 219 return py3compat.cast_unicode(homedir, fs_encoding)
206 220 else:
207 raise HomeDirError('%s is not a writable dir, set $HOME env to override' % homedir)
221 raise HomeDirError('%s is not a writable dir, '
222 'set $HOME environment variable to override' % homedir)
208 223
209 224 def get_xdg_dir():
210 225 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
211 226
212 227 This is only for posix (Linux,Unix,OS X, etc) systems.
213 228 """
214 229
215 230 env = os.environ
216 231
217 232 if os.name == 'posix':
218 233 # Linux, Unix, AIX, OS X
219 234 # use ~/.config if empty OR not set
220 235 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
221 236 if xdg and _writable_dir(xdg):
222 237 return py3compat.cast_unicode(xdg, fs_encoding)
223 238
224 239 return None
225 240
226 241
227 242 def get_ipython_dir():
228 243 """Get the IPython directory for this platform and user.
229 244
230 245 This uses the logic in `get_home_dir` to find the home directory
231 246 and then adds .ipython to the end of the path.
232 247 """
233 248
234 249 env = os.environ
235 250 pjoin = os.path.join
236 251
237 252
238 253 ipdir_def = '.ipython'
239 254 xdg_def = 'ipython'
240 255
241 256 home_dir = get_home_dir()
242 257 xdg_dir = get_xdg_dir()
243 258
244 259 # import pdb; pdb.set_trace() # dbg
245 260 ipdir = env.get('IPYTHON_DIR', env.get('IPYTHONDIR', None))
246 261 if ipdir is None:
247 262 # not set explicitly, use XDG_CONFIG_HOME or HOME
248 263 home_ipdir = pjoin(home_dir, ipdir_def)
249 264 if xdg_dir:
250 265 # use XDG, as long as the user isn't already
251 266 # using $HOME/.ipython and *not* XDG/ipython
252 267
253 268 xdg_ipdir = pjoin(xdg_dir, xdg_def)
254 269
255 270 if _writable_dir(xdg_ipdir) or not _writable_dir(home_ipdir):
256 271 ipdir = xdg_ipdir
257 272
258 273 if ipdir is None:
259 274 # not using XDG
260 275 ipdir = home_ipdir
261 276
262 277 ipdir = os.path.normpath(os.path.expanduser(ipdir))
263 278
264 279 if os.path.exists(ipdir) and not _writable_dir(ipdir):
265 280 # ipdir exists, but is not writable
266 281 warnings.warn("IPython dir '%s' is not a writable location,"
267 282 " using a temp directory."%ipdir)
268 283 ipdir = tempfile.mkdtemp()
269 284 elif not os.path.exists(ipdir):
270 285 parent = ipdir.rsplit(os.path.sep, 1)[0]
271 286 if not _writable_dir(parent):
272 287 # ipdir does not exist and parent isn't writable
273 288 warnings.warn("IPython parent '%s' is not a writable location,"
274 289 " using a temp directory."%parent)
275 290 ipdir = tempfile.mkdtemp()
276 291
277 292 return py3compat.cast_unicode(ipdir, fs_encoding)
278 293
279 294
280 295 def get_ipython_package_dir():
281 296 """Get the base directory where IPython itself is installed."""
282 297 ipdir = os.path.dirname(IPython.__file__)
283 298 return py3compat.cast_unicode(ipdir, fs_encoding)
284 299
285 300
286 301 def get_ipython_module_path(module_str):
287 302 """Find the path to an IPython module in this version of IPython.
288 303
289 304 This will always find the version of the module that is in this importable
290 305 IPython package. This will always return the path to the ``.py``
291 306 version of the module.
292 307 """
293 308 if module_str == 'IPython':
294 309 return os.path.join(get_ipython_package_dir(), '__init__.py')
295 310 mod = import_item(module_str)
296 311 the_path = mod.__file__.replace('.pyc', '.py')
297 312 the_path = the_path.replace('.pyo', '.py')
298 313 return py3compat.cast_unicode(the_path, fs_encoding)
299 314
300 315 def locate_profile(profile='default'):
301 316 """Find the path to the folder associated with a given profile.
302 317
303 318 I.e. find $IPYTHON_DIR/profile_whatever.
304 319 """
305 320 from IPython.core.profiledir import ProfileDir, ProfileDirError
306 321 try:
307 322 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
308 323 except ProfileDirError:
309 324 # IOError makes more sense when people are expecting a path
310 325 raise IOError("Couldn't find profile %r" % profile)
311 326 return pd.location
312 327
313 328 def expand_path(s):
314 329 """Expand $VARS and ~names in a string, like a shell
315 330
316 331 :Examples:
317 332
318 333 In [2]: os.environ['FOO']='test'
319 334
320 335 In [3]: expand_path('variable FOO is $FOO')
321 336 Out[3]: 'variable FOO is test'
322 337 """
323 338 # This is a pretty subtle hack. When expand user is given a UNC path
324 339 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
325 340 # the $ to get (\\server\share\%username%). I think it considered $
326 341 # alone an empty var. But, we need the $ to remains there (it indicates
327 342 # a hidden share).
328 343 if os.name=='nt':
329 344 s = s.replace('$\\', 'IPYTHON_TEMP')
330 345 s = os.path.expandvars(os.path.expanduser(s))
331 346 if os.name=='nt':
332 347 s = s.replace('IPYTHON_TEMP', '$\\')
333 348 return s
334 349
335 350
336 351 def target_outdated(target,deps):
337 352 """Determine whether a target is out of date.
338 353
339 354 target_outdated(target,deps) -> 1/0
340 355
341 356 deps: list of filenames which MUST exist.
342 357 target: single filename which may or may not exist.
343 358
344 359 If target doesn't exist or is older than any file listed in deps, return
345 360 true, otherwise return false.
346 361 """
347 362 try:
348 363 target_time = os.path.getmtime(target)
349 364 except os.error:
350 365 return 1
351 366 for dep in deps:
352 367 dep_time = os.path.getmtime(dep)
353 368 if dep_time > target_time:
354 369 #print "For target",target,"Dep failed:",dep # dbg
355 370 #print "times (dep,tar):",dep_time,target_time # dbg
356 371 return 1
357 372 return 0
358 373
359 374
360 375 def target_update(target,deps,cmd):
361 376 """Update a target with a given command given a list of dependencies.
362 377
363 378 target_update(target,deps,cmd) -> runs cmd if target is outdated.
364 379
365 380 This is just a wrapper around target_outdated() which calls the given
366 381 command if target is outdated."""
367 382
368 383 if target_outdated(target,deps):
369 384 system(cmd)
370 385
371 386 def filehash(path):
372 387 """Make an MD5 hash of a file, ignoring any differences in line
373 388 ending characters."""
374 389 with open(path, "rU") as f:
375 390 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
376 391
377 392 # If the config is unmodified from the default, we'll just delete it.
378 393 # These are consistent for 0.10.x, thankfully. We're not going to worry about
379 394 # older versions.
380 395 old_config_md5 = {'ipy_user_conf.py': 'fc108bedff4b9a00f91fa0a5999140d3',
381 396 'ipythonrc': '12a68954f3403eea2eec09dc8fe5a9b5'}
382 397
383 398 def check_for_old_config(ipython_dir=None):
384 399 """Check for old config files, and present a warning if they exist.
385 400
386 401 A link to the docs of the new config is included in the message.
387 402
388 403 This should mitigate confusion with the transition to the new
389 404 config system in 0.11.
390 405 """
391 406 if ipython_dir is None:
392 407 ipython_dir = get_ipython_dir()
393 408
394 409 old_configs = ['ipy_user_conf.py', 'ipythonrc', 'ipython_config.py']
395 410 warned = False
396 411 for cfg in old_configs:
397 412 f = os.path.join(ipython_dir, cfg)
398 413 if os.path.exists(f):
399 414 if filehash(f) == old_config_md5.get(cfg, ''):
400 415 os.unlink(f)
401 416 else:
402 417 warnings.warn("Found old IPython config file %r (modified by user)"%f)
403 418 warned = True
404 419
405 420 if warned:
406 421 warnings.warn("""
407 422 The IPython configuration system has changed as of 0.11, and these files will
408 423 be ignored. See http://ipython.github.com/ipython-doc/dev/config for details
409 424 of the new config system.
410 425 To start configuring IPython, do `ipython profile create`, and edit
411 426 `ipython_config.py` in <ipython_dir>/profile_default.
412 427 If you need to leave the old config files in place for an older version of
413 428 IPython and want to suppress this warning message, set
414 429 `c.InteractiveShellApp.ignore_old_config=True` in the new config.""")
415 430
416 431 def get_security_file(filename, profile='default'):
417 432 """Return the absolute path of a security file given by filename and profile
418 433
419 434 This allows users and developers to find security files without
420 435 knowledge of the IPython directory structure. The search path
421 436 will be ['.', profile.security_dir]
422 437
423 438 Parameters
424 439 ----------
425 440
426 441 filename : str
427 442 The file to be found. If it is passed as an absolute path, it will
428 443 simply be returned.
429 444 profile : str [default: 'default']
430 445 The name of the profile to search. Leaving this unspecified
431 446 The file to be found. If it is passed as an absolute path, fname will
432 447 simply be returned.
433 448
434 449 Returns
435 450 -------
436 451 Raises :exc:`IOError` if file not found or returns absolute path to file.
437 452 """
438 453 # import here, because profiledir also imports from utils.path
439 454 from IPython.core.profiledir import ProfileDir
440 455 try:
441 456 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
442 457 except Exception:
443 458 # will raise ProfileDirError if no such profile
444 459 raise IOError("Profile %r not found")
445 460 return filefind(filename, ['.', pd.security_dir])
446 461
@@ -1,375 +1,407 b''
1 1 # encoding: utf-8
2 2 """Tests for IPython.utils.path.py"""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2008 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 96 oldstuff = (env.copy(), os.name, 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 105 (oldenv, os.name, 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 nt.assert_equal(home_dir, env["HOME"])
154 154
155 155
156 156 @with_environment
157 157 def test_get_home_dir_4():
158 158 """get_home_dir() still works if $HOME is not set"""
159 159
160 160 if 'HOME' in env: del env['HOME']
161 161 # this should still succeed, but we don't know what the answer should be
162 162 home = path.get_home_dir(True)
163 163 nt.assert_true(path._writable_dir(home))
164 164
165 165 @with_environment
166 166 def test_get_home_dir_5():
167 167 """raise HomeDirError if $HOME is specified, but not a writable dir"""
168 168 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
169 # set os.name = posix, to prevent My Documents fallback on Windows
170 os.name = 'posix'
169 171 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
170 172
173
174 # Should we stub wreg fully so we can run the test on all platforms?
175 @skip_if_not_win32
176 @with_environment
177 def test_get_home_dir_8():
178 """Using registry hack for 'My Documents', os=='nt'
179
180 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
181 """
182 os.name = 'nt'
183 # Remove from stub environment all keys that may be set
184 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
185 env.pop(key, None)
186
187 #Stub windows registry functions
188 def OpenKey(x, y):
189 class key:
190 def Close(self):
191 pass
192 return key()
193 def QueryValueEx(x, y):
194 return [abspath(HOME_TEST_DIR)]
195
196 wreg.OpenKey = OpenKey
197 wreg.QueryValueEx = QueryValueEx
198
199 home_dir = path.get_home_dir()
200 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
201
202
171 203 @with_environment
172 204 def test_get_ipython_dir_1():
173 205 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
174 206 env_ipdir = os.path.join("someplace", ".ipython")
175 207 path._writable_dir = lambda path: True
176 208 env['IPYTHON_DIR'] = env_ipdir
177 209 ipdir = path.get_ipython_dir()
178 210 nt.assert_equal(ipdir, env_ipdir)
179 211
180 212
181 213 @with_environment
182 214 def test_get_ipython_dir_2():
183 215 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
184 216 path.get_home_dir = lambda : "someplace"
185 217 path.get_xdg_dir = lambda : None
186 218 path._writable_dir = lambda path: True
187 219 os.name = "posix"
188 220 env.pop('IPYTHON_DIR', None)
189 221 env.pop('IPYTHONDIR', None)
190 222 env.pop('XDG_CONFIG_HOME', None)
191 223 ipdir = path.get_ipython_dir()
192 224 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
193 225
194 226 @with_environment
195 227 def test_get_ipython_dir_3():
196 228 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
197 229 path.get_home_dir = lambda : "someplace"
198 230 path._writable_dir = lambda path: True
199 231 os.name = "posix"
200 232 env.pop('IPYTHON_DIR', None)
201 233 env.pop('IPYTHONDIR', None)
202 234 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
203 235 ipdir = path.get_ipython_dir()
204 236 nt.assert_equal(ipdir, os.path.join(XDG_TEST_DIR, "ipython"))
205 237
206 238 @with_environment
207 239 def test_get_ipython_dir_4():
208 240 """test_get_ipython_dir_4, use XDG if both exist."""
209 241 path.get_home_dir = lambda : HOME_TEST_DIR
210 242 os.name = "posix"
211 243 env.pop('IPYTHON_DIR', None)
212 244 env.pop('IPYTHONDIR', None)
213 245 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
214 246 xdg_ipdir = os.path.join(XDG_TEST_DIR, "ipython")
215 247 ipdir = path.get_ipython_dir()
216 248 nt.assert_equal(ipdir, xdg_ipdir)
217 249
218 250 @with_environment
219 251 def test_get_ipython_dir_5():
220 252 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
221 253 path.get_home_dir = lambda : HOME_TEST_DIR
222 254 os.name = "posix"
223 255 env.pop('IPYTHON_DIR', None)
224 256 env.pop('IPYTHONDIR', None)
225 257 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
226 258 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
227 259 ipdir = path.get_ipython_dir()
228 260 nt.assert_equal(ipdir, IP_TEST_DIR)
229 261
230 262 @with_environment
231 263 def test_get_ipython_dir_6():
232 264 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
233 265 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
234 266 os.mkdir(xdg)
235 267 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
236 268 path.get_home_dir = lambda : HOME_TEST_DIR
237 269 path.get_xdg_dir = lambda : xdg
238 270 os.name = "posix"
239 271 env.pop('IPYTHON_DIR', None)
240 272 env.pop('IPYTHONDIR', None)
241 273 env.pop('XDG_CONFIG_HOME', None)
242 274 xdg_ipdir = os.path.join(xdg, "ipython")
243 275 ipdir = path.get_ipython_dir()
244 276 nt.assert_equal(ipdir, xdg_ipdir)
245 277
246 278 @with_environment
247 279 def test_get_ipython_dir_7():
248 280 """test_get_ipython_dir_7, test home directory expansion on IPYTHON_DIR"""
249 281 path._writable_dir = lambda path: True
250 282 home_dir = os.path.expanduser('~')
251 283 env['IPYTHON_DIR'] = os.path.join('~', 'somewhere')
252 284 ipdir = path.get_ipython_dir()
253 285 nt.assert_equal(ipdir, os.path.join(home_dir, 'somewhere'))
254 286
255 287
256 288 @with_environment
257 289 def test_get_xdg_dir_1():
258 290 """test_get_xdg_dir_1, check xdg_dir"""
259 291 reload(path)
260 292 path._writable_dir = lambda path: True
261 293 path.get_home_dir = lambda : 'somewhere'
262 294 os.name = "posix"
263 295 env.pop('IPYTHON_DIR', None)
264 296 env.pop('IPYTHONDIR', None)
265 297 env.pop('XDG_CONFIG_HOME', None)
266 298
267 299 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
268 300
269 301
270 302 @with_environment
271 303 def test_get_xdg_dir_1():
272 304 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
273 305 reload(path)
274 306 path.get_home_dir = lambda : HOME_TEST_DIR
275 307 os.name = "posix"
276 308 env.pop('IPYTHON_DIR', None)
277 309 env.pop('IPYTHONDIR', None)
278 310 env.pop('XDG_CONFIG_HOME', None)
279 311 nt.assert_equal(path.get_xdg_dir(), None)
280 312
281 313 @with_environment
282 314 def test_get_xdg_dir_2():
283 315 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
284 316 reload(path)
285 317 path.get_home_dir = lambda : HOME_TEST_DIR
286 318 os.name = "posix"
287 319 env.pop('IPYTHON_DIR', None)
288 320 env.pop('IPYTHONDIR', None)
289 321 env.pop('XDG_CONFIG_HOME', None)
290 322 cfgdir=os.path.join(path.get_home_dir(), '.config')
291 323 os.makedirs(cfgdir)
292 324
293 325 nt.assert_equal(path.get_xdg_dir(), cfgdir)
294 326
295 327 def test_filefind():
296 328 """Various tests for filefind"""
297 329 f = tempfile.NamedTemporaryFile()
298 330 # print 'fname:',f.name
299 331 alt_dirs = path.get_ipython_dir()
300 332 t = path.filefind(f.name, alt_dirs)
301 333 # print 'found:',t
302 334
303 335
304 336 def test_get_ipython_package_dir():
305 337 ipdir = path.get_ipython_package_dir()
306 338 nt.assert_true(os.path.isdir(ipdir))
307 339
308 340
309 341 def test_get_ipython_module_path():
310 342 ipapp_path = path.get_ipython_module_path('IPython.frontend.terminal.ipapp')
311 343 nt.assert_true(os.path.isfile(ipapp_path))
312 344
313 345
314 346 @dec.skip_if_not_win32
315 347 def test_get_long_path_name_win32():
316 348 p = path.get_long_path_name('c:\\docume~1')
317 349 nt.assert_equals(p,u'c:\\Documents and Settings')
318 350
319 351
320 352 @dec.skip_win32
321 353 def test_get_long_path_name():
322 354 p = path.get_long_path_name('/usr/local')
323 355 nt.assert_equals(p,'/usr/local')
324 356
325 357 @dec.skip_win32 # can't create not-user-writable dir on win
326 358 @with_environment
327 359 def test_not_writable_ipdir():
328 360 tmpdir = tempfile.mkdtemp()
329 361 os.name = "posix"
330 362 env.pop('IPYTHON_DIR', None)
331 363 env.pop('IPYTHONDIR', None)
332 364 env.pop('XDG_CONFIG_HOME', None)
333 365 env['HOME'] = tmpdir
334 366 ipdir = os.path.join(tmpdir, '.ipython')
335 367 os.mkdir(ipdir)
336 368 os.chmod(ipdir, 600)
337 369 with AssertPrints('is not a writable location', channel='stderr'):
338 370 ipdir = path.get_ipython_dir()
339 371 env.pop('IPYTHON_DIR', None)
340 372
341 373 def test_unquote_filename():
342 374 for win32 in (True, False):
343 375 nt.assert_equals(path.unquote_filename('foo.py', win32=win32), 'foo.py')
344 376 nt.assert_equals(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
345 377 nt.assert_equals(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
346 378 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
347 379 nt.assert_equals(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
348 380 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
349 381 nt.assert_equals(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
350 382 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
351 383 nt.assert_equals(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
352 384 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
353 385
354 386 @with_environment
355 387 def test_get_py_filename():
356 388 os.chdir(TMP_TEST_DIR)
357 389 for win32 in (True, False):
358 390 with make_tempfile('foo.py'):
359 391 nt.assert_equals(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
360 392 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo.py')
361 393 with make_tempfile('foo'):
362 394 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo')
363 395 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
364 396 nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32)
365 397 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
366 398 true_fn = 'foo with spaces.py'
367 399 with make_tempfile(true_fn):
368 400 nt.assert_equals(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
369 401 nt.assert_equals(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
370 402 if win32:
371 403 nt.assert_equals(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
372 404 nt.assert_equals(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
373 405 else:
374 406 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False)
375 407 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)
General Comments 0
You need to be logged in to leave comments. Login now