##// END OF EJS Templates
Merge pull request #10485 from Carreau/unused-imports...
Thomas Kluyver -
r23576:fcbde473 merge
parent child Browse files
Show More
@@ -1,482 +1,479
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.path.py"""
2 """Tests for IPython.utils.path.py"""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import errno
8 import os
7 import os
9 import shutil
8 import shutil
10 import sys
9 import sys
11 import tempfile
10 import tempfile
12 import warnings
13 from contextlib import contextmanager
11 from contextlib import contextmanager
14 from unittest.mock import patch
12 from unittest.mock import patch
15 from os.path import join, abspath, split
13 from os.path import join, abspath
16 from imp import reload
14 from imp import reload
17
15
18 from nose import SkipTest, with_setup
16 from nose import SkipTest, with_setup
19 import nose.tools as nt
17 import nose.tools as nt
20
18
21 import IPython
19 import IPython
22 from IPython import paths
20 from IPython import paths
23 from IPython.testing import decorators as dec
21 from IPython.testing import decorators as dec
24 from IPython.testing.decorators import (skip_if_not_win32, skip_win32,
22 from IPython.testing.decorators import (skip_if_not_win32, skip_win32,
25 onlyif_unicode_paths,)
23 onlyif_unicode_paths,)
26 from IPython.testing.tools import make_tempfile, AssertPrints
24 from IPython.testing.tools import make_tempfile, AssertPrints
27 from IPython.utils import path
25 from IPython.utils import path
28 from IPython.utils import py3compat
29 from IPython.utils.tempdir import TemporaryDirectory
26 from IPython.utils.tempdir import TemporaryDirectory
30
27
31 # Platform-dependent imports
28 # Platform-dependent imports
32 try:
29 try:
33 import winreg as wreg
30 import winreg as wreg
34 except ImportError:
31 except ImportError:
35 #Fake _winreg module on non-windows platforms
32 #Fake _winreg module on non-windows platforms
36 import types
33 import types
37 wr_name = "winreg"
34 wr_name = "winreg"
38 sys.modules[wr_name] = types.ModuleType(wr_name)
35 sys.modules[wr_name] = types.ModuleType(wr_name)
39 try:
36 try:
40 import winreg as wreg
37 import winreg as wreg
41 except ImportError:
38 except ImportError:
42 import _winreg as wreg
39 import _winreg as wreg
43 #Add entries that needs to be stubbed by the testing code
40 #Add entries that needs to be stubbed by the testing code
44 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
41 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
45
42
46 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
47 # Globals
44 # Globals
48 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
49 env = os.environ
46 env = os.environ
50 TMP_TEST_DIR = tempfile.mkdtemp()
47 TMP_TEST_DIR = tempfile.mkdtemp()
51 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
48 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
52 #
49 #
53 # Setup/teardown functions/decorators
50 # Setup/teardown functions/decorators
54 #
51 #
55
52
56 def setup():
53 def setup():
57 """Setup testenvironment for the module:
54 """Setup testenvironment for the module:
58
55
59 - Adds dummy home dir tree
56 - Adds dummy home dir tree
60 """
57 """
61 # Do not mask exceptions here. In particular, catching WindowsError is a
58 # Do not mask exceptions here. In particular, catching WindowsError is a
62 # problem because that exception is only defined on Windows...
59 # problem because that exception is only defined on Windows...
63 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
60 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
64
61
65
62
66 def teardown():
63 def teardown():
67 """Teardown testenvironment for the module:
64 """Teardown testenvironment for the module:
68
65
69 - Remove dummy home dir tree
66 - Remove dummy home dir tree
70 """
67 """
71 # Note: we remove the parent test dir, which is the root of all test
68 # Note: we remove the parent test dir, which is the root of all test
72 # subdirs we may have created. Use shutil instead of os.removedirs, so
69 # subdirs we may have created. Use shutil instead of os.removedirs, so
73 # that non-empty directories are all recursively removed.
70 # that non-empty directories are all recursively removed.
74 shutil.rmtree(TMP_TEST_DIR)
71 shutil.rmtree(TMP_TEST_DIR)
75
72
76
73
77 def setup_environment():
74 def setup_environment():
78 """Setup testenvironment for some functions that are tested
75 """Setup testenvironment for some functions that are tested
79 in this module. In particular this functions stores attributes
76 in this module. In particular this functions stores attributes
80 and other things that we need to stub in some test functions.
77 and other things that we need to stub in some test functions.
81 This needs to be done on a function level and not module level because
78 This needs to be done on a function level and not module level because
82 each testfunction needs a pristine environment.
79 each testfunction needs a pristine environment.
83 """
80 """
84 global oldstuff, platformstuff
81 global oldstuff, platformstuff
85 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
82 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
86
83
87 def teardown_environment():
84 def teardown_environment():
88 """Restore things that were remembered by the setup_environment function
85 """Restore things that were remembered by the setup_environment function
89 """
86 """
90 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
87 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
91 os.chdir(old_wd)
88 os.chdir(old_wd)
92 reload(path)
89 reload(path)
93
90
94 for key in list(env):
91 for key in list(env):
95 if key not in oldenv:
92 if key not in oldenv:
96 del env[key]
93 del env[key]
97 env.update(oldenv)
94 env.update(oldenv)
98 if hasattr(sys, 'frozen'):
95 if hasattr(sys, 'frozen'):
99 del sys.frozen
96 del sys.frozen
100
97
101 # Build decorator that uses the setup_environment/setup_environment
98 # Build decorator that uses the setup_environment/setup_environment
102 with_environment = with_setup(setup_environment, teardown_environment)
99 with_environment = with_setup(setup_environment, teardown_environment)
103
100
104 @skip_if_not_win32
101 @skip_if_not_win32
105 @with_environment
102 @with_environment
106 def test_get_home_dir_1():
103 def test_get_home_dir_1():
107 """Testcase for py2exe logic, un-compressed lib
104 """Testcase for py2exe logic, un-compressed lib
108 """
105 """
109 unfrozen = path.get_home_dir()
106 unfrozen = path.get_home_dir()
110 sys.frozen = True
107 sys.frozen = True
111
108
112 #fake filename for IPython.__init__
109 #fake filename for IPython.__init__
113 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
110 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
114
111
115 home_dir = path.get_home_dir()
112 home_dir = path.get_home_dir()
116 nt.assert_equal(home_dir, unfrozen)
113 nt.assert_equal(home_dir, unfrozen)
117
114
118
115
119 @skip_if_not_win32
116 @skip_if_not_win32
120 @with_environment
117 @with_environment
121 def test_get_home_dir_2():
118 def test_get_home_dir_2():
122 """Testcase for py2exe logic, compressed lib
119 """Testcase for py2exe logic, compressed lib
123 """
120 """
124 unfrozen = path.get_home_dir()
121 unfrozen = path.get_home_dir()
125 sys.frozen = True
122 sys.frozen = True
126 #fake filename for IPython.__init__
123 #fake filename for IPython.__init__
127 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
124 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
128
125
129 home_dir = path.get_home_dir(True)
126 home_dir = path.get_home_dir(True)
130 nt.assert_equal(home_dir, unfrozen)
127 nt.assert_equal(home_dir, unfrozen)
131
128
132
129
133 @with_environment
130 @with_environment
134 def test_get_home_dir_3():
131 def test_get_home_dir_3():
135 """get_home_dir() uses $HOME if set"""
132 """get_home_dir() uses $HOME if set"""
136 env["HOME"] = HOME_TEST_DIR
133 env["HOME"] = HOME_TEST_DIR
137 home_dir = path.get_home_dir(True)
134 home_dir = path.get_home_dir(True)
138 # get_home_dir expands symlinks
135 # get_home_dir expands symlinks
139 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
136 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
140
137
141
138
142 @with_environment
139 @with_environment
143 def test_get_home_dir_4():
140 def test_get_home_dir_4():
144 """get_home_dir() still works if $HOME is not set"""
141 """get_home_dir() still works if $HOME is not set"""
145
142
146 if 'HOME' in env: del env['HOME']
143 if 'HOME' in env: del env['HOME']
147 # this should still succeed, but we don't care what the answer is
144 # this should still succeed, but we don't care what the answer is
148 home = path.get_home_dir(False)
145 home = path.get_home_dir(False)
149
146
150 @with_environment
147 @with_environment
151 def test_get_home_dir_5():
148 def test_get_home_dir_5():
152 """raise HomeDirError if $HOME is specified, but not a writable dir"""
149 """raise HomeDirError if $HOME is specified, but not a writable dir"""
153 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
150 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
154 # set os.name = posix, to prevent My Documents fallback on Windows
151 # set os.name = posix, to prevent My Documents fallback on Windows
155 os.name = 'posix'
152 os.name = 'posix'
156 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
153 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
157
154
158 # Should we stub wreg fully so we can run the test on all platforms?
155 # Should we stub wreg fully so we can run the test on all platforms?
159 @skip_if_not_win32
156 @skip_if_not_win32
160 @with_environment
157 @with_environment
161 def test_get_home_dir_8():
158 def test_get_home_dir_8():
162 """Using registry hack for 'My Documents', os=='nt'
159 """Using registry hack for 'My Documents', os=='nt'
163
160
164 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
161 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
165 """
162 """
166 os.name = 'nt'
163 os.name = 'nt'
167 # Remove from stub environment all keys that may be set
164 # Remove from stub environment all keys that may be set
168 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
165 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
169 env.pop(key, None)
166 env.pop(key, None)
170
167
171 class key:
168 class key:
172 def Close(self):
169 def Close(self):
173 pass
170 pass
174
171
175 with patch.object(wreg, 'OpenKey', return_value=key()), \
172 with patch.object(wreg, 'OpenKey', return_value=key()), \
176 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
173 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
177 home_dir = path.get_home_dir()
174 home_dir = path.get_home_dir()
178 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
175 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
179
176
180 @with_environment
177 @with_environment
181 def test_get_xdg_dir_0():
178 def test_get_xdg_dir_0():
182 """test_get_xdg_dir_0, check xdg_dir"""
179 """test_get_xdg_dir_0, check xdg_dir"""
183 reload(path)
180 reload(path)
184 path._writable_dir = lambda path: True
181 path._writable_dir = lambda path: True
185 path.get_home_dir = lambda : 'somewhere'
182 path.get_home_dir = lambda : 'somewhere'
186 os.name = "posix"
183 os.name = "posix"
187 sys.platform = "linux2"
184 sys.platform = "linux2"
188 env.pop('IPYTHON_DIR', None)
185 env.pop('IPYTHON_DIR', None)
189 env.pop('IPYTHONDIR', None)
186 env.pop('IPYTHONDIR', None)
190 env.pop('XDG_CONFIG_HOME', None)
187 env.pop('XDG_CONFIG_HOME', None)
191
188
192 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
189 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
193
190
194
191
195 @with_environment
192 @with_environment
196 def test_get_xdg_dir_1():
193 def test_get_xdg_dir_1():
197 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
194 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
198 reload(path)
195 reload(path)
199 path.get_home_dir = lambda : HOME_TEST_DIR
196 path.get_home_dir = lambda : HOME_TEST_DIR
200 os.name = "posix"
197 os.name = "posix"
201 sys.platform = "linux2"
198 sys.platform = "linux2"
202 env.pop('IPYTHON_DIR', None)
199 env.pop('IPYTHON_DIR', None)
203 env.pop('IPYTHONDIR', None)
200 env.pop('IPYTHONDIR', None)
204 env.pop('XDG_CONFIG_HOME', None)
201 env.pop('XDG_CONFIG_HOME', None)
205 nt.assert_equal(path.get_xdg_dir(), None)
202 nt.assert_equal(path.get_xdg_dir(), None)
206
203
207 @with_environment
204 @with_environment
208 def test_get_xdg_dir_2():
205 def test_get_xdg_dir_2():
209 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
206 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
210 reload(path)
207 reload(path)
211 path.get_home_dir = lambda : HOME_TEST_DIR
208 path.get_home_dir = lambda : HOME_TEST_DIR
212 os.name = "posix"
209 os.name = "posix"
213 sys.platform = "linux2"
210 sys.platform = "linux2"
214 env.pop('IPYTHON_DIR', None)
211 env.pop('IPYTHON_DIR', None)
215 env.pop('IPYTHONDIR', None)
212 env.pop('IPYTHONDIR', None)
216 env.pop('XDG_CONFIG_HOME', None)
213 env.pop('XDG_CONFIG_HOME', None)
217 cfgdir=os.path.join(path.get_home_dir(), '.config')
214 cfgdir=os.path.join(path.get_home_dir(), '.config')
218 if not os.path.exists(cfgdir):
215 if not os.path.exists(cfgdir):
219 os.makedirs(cfgdir)
216 os.makedirs(cfgdir)
220
217
221 nt.assert_equal(path.get_xdg_dir(), cfgdir)
218 nt.assert_equal(path.get_xdg_dir(), cfgdir)
222
219
223 @with_environment
220 @with_environment
224 def test_get_xdg_dir_3():
221 def test_get_xdg_dir_3():
225 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
222 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
226 reload(path)
223 reload(path)
227 path.get_home_dir = lambda : HOME_TEST_DIR
224 path.get_home_dir = lambda : HOME_TEST_DIR
228 os.name = "posix"
225 os.name = "posix"
229 sys.platform = "darwin"
226 sys.platform = "darwin"
230 env.pop('IPYTHON_DIR', None)
227 env.pop('IPYTHON_DIR', None)
231 env.pop('IPYTHONDIR', None)
228 env.pop('IPYTHONDIR', None)
232 env.pop('XDG_CONFIG_HOME', None)
229 env.pop('XDG_CONFIG_HOME', None)
233 cfgdir=os.path.join(path.get_home_dir(), '.config')
230 cfgdir=os.path.join(path.get_home_dir(), '.config')
234 if not os.path.exists(cfgdir):
231 if not os.path.exists(cfgdir):
235 os.makedirs(cfgdir)
232 os.makedirs(cfgdir)
236
233
237 nt.assert_equal(path.get_xdg_dir(), None)
234 nt.assert_equal(path.get_xdg_dir(), None)
238
235
239 def test_filefind():
236 def test_filefind():
240 """Various tests for filefind"""
237 """Various tests for filefind"""
241 f = tempfile.NamedTemporaryFile()
238 f = tempfile.NamedTemporaryFile()
242 # print 'fname:',f.name
239 # print 'fname:',f.name
243 alt_dirs = paths.get_ipython_dir()
240 alt_dirs = paths.get_ipython_dir()
244 t = path.filefind(f.name, alt_dirs)
241 t = path.filefind(f.name, alt_dirs)
245 # print 'found:',t
242 # print 'found:',t
246
243
247
244
248 @dec.skip_if_not_win32
245 @dec.skip_if_not_win32
249 def test_get_long_path_name_win32():
246 def test_get_long_path_name_win32():
250 with TemporaryDirectory() as tmpdir:
247 with TemporaryDirectory() as tmpdir:
251
248
252 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
249 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
253 # path component, so ensure we include the long form of it
250 # path component, so ensure we include the long form of it
254 long_path = os.path.join(path.get_long_path_name(tmpdir), 'this is my long path name')
251 long_path = os.path.join(path.get_long_path_name(tmpdir), 'this is my long path name')
255 os.makedirs(long_path)
252 os.makedirs(long_path)
256
253
257 # Test to see if the short path evaluates correctly.
254 # Test to see if the short path evaluates correctly.
258 short_path = os.path.join(tmpdir, 'THISIS~1')
255 short_path = os.path.join(tmpdir, 'THISIS~1')
259 evaluated_path = path.get_long_path_name(short_path)
256 evaluated_path = path.get_long_path_name(short_path)
260 nt.assert_equal(evaluated_path.lower(), long_path.lower())
257 nt.assert_equal(evaluated_path.lower(), long_path.lower())
261
258
262
259
263 @dec.skip_win32
260 @dec.skip_win32
264 def test_get_long_path_name():
261 def test_get_long_path_name():
265 p = path.get_long_path_name('/usr/local')
262 p = path.get_long_path_name('/usr/local')
266 nt.assert_equal(p,'/usr/local')
263 nt.assert_equal(p,'/usr/local')
267
264
268 @dec.skip_win32 # can't create not-user-writable dir on win
265 @dec.skip_win32 # can't create not-user-writable dir on win
269 @with_environment
266 @with_environment
270 def test_not_writable_ipdir():
267 def test_not_writable_ipdir():
271 tmpdir = tempfile.mkdtemp()
268 tmpdir = tempfile.mkdtemp()
272 os.name = "posix"
269 os.name = "posix"
273 env.pop('IPYTHON_DIR', None)
270 env.pop('IPYTHON_DIR', None)
274 env.pop('IPYTHONDIR', None)
271 env.pop('IPYTHONDIR', None)
275 env.pop('XDG_CONFIG_HOME', None)
272 env.pop('XDG_CONFIG_HOME', None)
276 env['HOME'] = tmpdir
273 env['HOME'] = tmpdir
277 ipdir = os.path.join(tmpdir, '.ipython')
274 ipdir = os.path.join(tmpdir, '.ipython')
278 os.mkdir(ipdir, 0o555)
275 os.mkdir(ipdir, 0o555)
279 try:
276 try:
280 open(os.path.join(ipdir, "_foo_"), 'w').close()
277 open(os.path.join(ipdir, "_foo_"), 'w').close()
281 except IOError:
278 except IOError:
282 pass
279 pass
283 else:
280 else:
284 # I can still write to an unwritable dir,
281 # I can still write to an unwritable dir,
285 # assume I'm root and skip the test
282 # assume I'm root and skip the test
286 raise SkipTest("I can't create directories that I can't write to")
283 raise SkipTest("I can't create directories that I can't write to")
287 with AssertPrints('is not a writable location', channel='stderr'):
284 with AssertPrints('is not a writable location', channel='stderr'):
288 ipdir = paths.get_ipython_dir()
285 ipdir = paths.get_ipython_dir()
289 env.pop('IPYTHON_DIR', None)
286 env.pop('IPYTHON_DIR', None)
290
287
291 @with_environment
288 @with_environment
292 def test_get_py_filename():
289 def test_get_py_filename():
293 os.chdir(TMP_TEST_DIR)
290 os.chdir(TMP_TEST_DIR)
294 with make_tempfile('foo.py'):
291 with make_tempfile('foo.py'):
295 nt.assert_equal(path.get_py_filename('foo.py'), 'foo.py')
292 nt.assert_equal(path.get_py_filename('foo.py'), 'foo.py')
296 nt.assert_equal(path.get_py_filename('foo'), 'foo.py')
293 nt.assert_equal(path.get_py_filename('foo'), 'foo.py')
297 with make_tempfile('foo'):
294 with make_tempfile('foo'):
298 nt.assert_equal(path.get_py_filename('foo'), 'foo')
295 nt.assert_equal(path.get_py_filename('foo'), 'foo')
299 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
296 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
300 nt.assert_raises(IOError, path.get_py_filename, 'foo')
297 nt.assert_raises(IOError, path.get_py_filename, 'foo')
301 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
298 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
302 true_fn = 'foo with spaces.py'
299 true_fn = 'foo with spaces.py'
303 with make_tempfile(true_fn):
300 with make_tempfile(true_fn):
304 nt.assert_equal(path.get_py_filename('foo with spaces'), true_fn)
301 nt.assert_equal(path.get_py_filename('foo with spaces'), true_fn)
305 nt.assert_equal(path.get_py_filename('foo with spaces.py'), true_fn)
302 nt.assert_equal(path.get_py_filename('foo with spaces.py'), true_fn)
306 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"')
303 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"')
307 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'")
304 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'")
308
305
309 @onlyif_unicode_paths
306 @onlyif_unicode_paths
310 def test_unicode_in_filename():
307 def test_unicode_in_filename():
311 """When a file doesn't exist, the exception raised should be safe to call
308 """When a file doesn't exist, the exception raised should be safe to call
312 str() on - i.e. in Python 2 it must only have ASCII characters.
309 str() on - i.e. in Python 2 it must only have ASCII characters.
313
310
314 https://github.com/ipython/ipython/issues/875
311 https://github.com/ipython/ipython/issues/875
315 """
312 """
316 try:
313 try:
317 # these calls should not throw unicode encode exceptions
314 # these calls should not throw unicode encode exceptions
318 path.get_py_filename('fooéè.py', force_win32=False)
315 path.get_py_filename('fooéè.py', force_win32=False)
319 except IOError as ex:
316 except IOError as ex:
320 str(ex)
317 str(ex)
321
318
322
319
323 class TestShellGlob(object):
320 class TestShellGlob(object):
324
321
325 @classmethod
322 @classmethod
326 def setUpClass(cls):
323 def setUpClass(cls):
327 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
324 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
328 cls.filenames_end_with_b = ['0b', '1b', '2b']
325 cls.filenames_end_with_b = ['0b', '1b', '2b']
329 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
326 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
330 cls.tempdir = TemporaryDirectory()
327 cls.tempdir = TemporaryDirectory()
331 td = cls.tempdir.name
328 td = cls.tempdir.name
332
329
333 with cls.in_tempdir():
330 with cls.in_tempdir():
334 # Create empty files
331 # Create empty files
335 for fname in cls.filenames:
332 for fname in cls.filenames:
336 open(os.path.join(td, fname), 'w').close()
333 open(os.path.join(td, fname), 'w').close()
337
334
338 @classmethod
335 @classmethod
339 def tearDownClass(cls):
336 def tearDownClass(cls):
340 cls.tempdir.cleanup()
337 cls.tempdir.cleanup()
341
338
342 @classmethod
339 @classmethod
343 @contextmanager
340 @contextmanager
344 def in_tempdir(cls):
341 def in_tempdir(cls):
345 save = os.getcwd()
342 save = os.getcwd()
346 try:
343 try:
347 os.chdir(cls.tempdir.name)
344 os.chdir(cls.tempdir.name)
348 yield
345 yield
349 finally:
346 finally:
350 os.chdir(save)
347 os.chdir(save)
351
348
352 def check_match(self, patterns, matches):
349 def check_match(self, patterns, matches):
353 with self.in_tempdir():
350 with self.in_tempdir():
354 # glob returns unordered list. that's why sorted is required.
351 # glob returns unordered list. that's why sorted is required.
355 nt.assert_equal(sorted(path.shellglob(patterns)),
352 nt.assert_equal(sorted(path.shellglob(patterns)),
356 sorted(matches))
353 sorted(matches))
357
354
358 def common_cases(self):
355 def common_cases(self):
359 return [
356 return [
360 (['*'], self.filenames),
357 (['*'], self.filenames),
361 (['a*'], self.filenames_start_with_a),
358 (['a*'], self.filenames_start_with_a),
362 (['*c'], ['*c']),
359 (['*c'], ['*c']),
363 (['*', 'a*', '*b', '*c'], self.filenames
360 (['*', 'a*', '*b', '*c'], self.filenames
364 + self.filenames_start_with_a
361 + self.filenames_start_with_a
365 + self.filenames_end_with_b
362 + self.filenames_end_with_b
366 + ['*c']),
363 + ['*c']),
367 (['a[012]'], self.filenames_start_with_a),
364 (['a[012]'], self.filenames_start_with_a),
368 ]
365 ]
369
366
370 @skip_win32
367 @skip_win32
371 def test_match_posix(self):
368 def test_match_posix(self):
372 for (patterns, matches) in self.common_cases() + [
369 for (patterns, matches) in self.common_cases() + [
373 ([r'\*'], ['*']),
370 ([r'\*'], ['*']),
374 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
371 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
375 ([r'a\[012]'], ['a[012]']),
372 ([r'a\[012]'], ['a[012]']),
376 ]:
373 ]:
377 yield (self.check_match, patterns, matches)
374 yield (self.check_match, patterns, matches)
378
375
379 @skip_if_not_win32
376 @skip_if_not_win32
380 def test_match_windows(self):
377 def test_match_windows(self):
381 for (patterns, matches) in self.common_cases() + [
378 for (patterns, matches) in self.common_cases() + [
382 # In windows, backslash is interpreted as path
379 # In windows, backslash is interpreted as path
383 # separator. Therefore, you can't escape glob
380 # separator. Therefore, you can't escape glob
384 # using it.
381 # using it.
385 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
382 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
386 ([r'a\[012]'], [r'a\[012]']),
383 ([r'a\[012]'], [r'a\[012]']),
387 ]:
384 ]:
388 yield (self.check_match, patterns, matches)
385 yield (self.check_match, patterns, matches)
389
386
390
387
391 def test_unescape_glob():
388 def test_unescape_glob():
392 nt.assert_equal(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
389 nt.assert_equal(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
393 nt.assert_equal(path.unescape_glob(r'\\*'), r'\*')
390 nt.assert_equal(path.unescape_glob(r'\\*'), r'\*')
394 nt.assert_equal(path.unescape_glob(r'\\\*'), r'\*')
391 nt.assert_equal(path.unescape_glob(r'\\\*'), r'\*')
395 nt.assert_equal(path.unescape_glob(r'\\a'), r'\a')
392 nt.assert_equal(path.unescape_glob(r'\\a'), r'\a')
396 nt.assert_equal(path.unescape_glob(r'\a'), r'\a')
393 nt.assert_equal(path.unescape_glob(r'\a'), r'\a')
397
394
398
395
399 def test_ensure_dir_exists():
396 def test_ensure_dir_exists():
400 with TemporaryDirectory() as td:
397 with TemporaryDirectory() as td:
401 d = os.path.join(td, 'βˆ‚ir')
398 d = os.path.join(td, 'βˆ‚ir')
402 path.ensure_dir_exists(d) # create it
399 path.ensure_dir_exists(d) # create it
403 assert os.path.isdir(d)
400 assert os.path.isdir(d)
404 path.ensure_dir_exists(d) # no-op
401 path.ensure_dir_exists(d) # no-op
405 f = os.path.join(td, 'Ζ’ile')
402 f = os.path.join(td, 'Ζ’ile')
406 open(f, 'w').close() # touch
403 open(f, 'w').close() # touch
407 with nt.assert_raises(IOError):
404 with nt.assert_raises(IOError):
408 path.ensure_dir_exists(f)
405 path.ensure_dir_exists(f)
409
406
410 class TestLinkOrCopy(object):
407 class TestLinkOrCopy(object):
411 def setUp(self):
408 def setUp(self):
412 self.tempdir = TemporaryDirectory()
409 self.tempdir = TemporaryDirectory()
413 self.src = self.dst("src")
410 self.src = self.dst("src")
414 with open(self.src, "w") as f:
411 with open(self.src, "w") as f:
415 f.write("Hello, world!")
412 f.write("Hello, world!")
416
413
417 def tearDown(self):
414 def tearDown(self):
418 self.tempdir.cleanup()
415 self.tempdir.cleanup()
419
416
420 def dst(self, *args):
417 def dst(self, *args):
421 return os.path.join(self.tempdir.name, *args)
418 return os.path.join(self.tempdir.name, *args)
422
419
423 def assert_inode_not_equal(self, a, b):
420 def assert_inode_not_equal(self, a, b):
424 nt.assert_not_equal(os.stat(a).st_ino, os.stat(b).st_ino,
421 nt.assert_not_equal(os.stat(a).st_ino, os.stat(b).st_ino,
425 "%r and %r do reference the same indoes" %(a, b))
422 "%r and %r do reference the same indoes" %(a, b))
426
423
427 def assert_inode_equal(self, a, b):
424 def assert_inode_equal(self, a, b):
428 nt.assert_equal(os.stat(a).st_ino, os.stat(b).st_ino,
425 nt.assert_equal(os.stat(a).st_ino, os.stat(b).st_ino,
429 "%r and %r do not reference the same indoes" %(a, b))
426 "%r and %r do not reference the same indoes" %(a, b))
430
427
431 def assert_content_equal(self, a, b):
428 def assert_content_equal(self, a, b):
432 with open(a) as a_f:
429 with open(a) as a_f:
433 with open(b) as b_f:
430 with open(b) as b_f:
434 nt.assert_equal(a_f.read(), b_f.read())
431 nt.assert_equal(a_f.read(), b_f.read())
435
432
436 @skip_win32
433 @skip_win32
437 def test_link_successful(self):
434 def test_link_successful(self):
438 dst = self.dst("target")
435 dst = self.dst("target")
439 path.link_or_copy(self.src, dst)
436 path.link_or_copy(self.src, dst)
440 self.assert_inode_equal(self.src, dst)
437 self.assert_inode_equal(self.src, dst)
441
438
442 @skip_win32
439 @skip_win32
443 def test_link_into_dir(self):
440 def test_link_into_dir(self):
444 dst = self.dst("some_dir")
441 dst = self.dst("some_dir")
445 os.mkdir(dst)
442 os.mkdir(dst)
446 path.link_or_copy(self.src, dst)
443 path.link_or_copy(self.src, dst)
447 expected_dst = self.dst("some_dir", os.path.basename(self.src))
444 expected_dst = self.dst("some_dir", os.path.basename(self.src))
448 self.assert_inode_equal(self.src, expected_dst)
445 self.assert_inode_equal(self.src, expected_dst)
449
446
450 @skip_win32
447 @skip_win32
451 def test_target_exists(self):
448 def test_target_exists(self):
452 dst = self.dst("target")
449 dst = self.dst("target")
453 open(dst, "w").close()
450 open(dst, "w").close()
454 path.link_or_copy(self.src, dst)
451 path.link_or_copy(self.src, dst)
455 self.assert_inode_equal(self.src, dst)
452 self.assert_inode_equal(self.src, dst)
456
453
457 @skip_win32
454 @skip_win32
458 def test_no_link(self):
455 def test_no_link(self):
459 real_link = os.link
456 real_link = os.link
460 try:
457 try:
461 del os.link
458 del os.link
462 dst = self.dst("target")
459 dst = self.dst("target")
463 path.link_or_copy(self.src, dst)
460 path.link_or_copy(self.src, dst)
464 self.assert_content_equal(self.src, dst)
461 self.assert_content_equal(self.src, dst)
465 self.assert_inode_not_equal(self.src, dst)
462 self.assert_inode_not_equal(self.src, dst)
466 finally:
463 finally:
467 os.link = real_link
464 os.link = real_link
468
465
469 @skip_if_not_win32
466 @skip_if_not_win32
470 def test_windows(self):
467 def test_windows(self):
471 dst = self.dst("target")
468 dst = self.dst("target")
472 path.link_or_copy(self.src, dst)
469 path.link_or_copy(self.src, dst)
473 self.assert_content_equal(self.src, dst)
470 self.assert_content_equal(self.src, dst)
474
471
475 def test_link_twice(self):
472 def test_link_twice(self):
476 # Linking the same file twice shouldn't leave duplicates around.
473 # Linking the same file twice shouldn't leave duplicates around.
477 # See https://github.com/ipython/ipython/issues/6450
474 # See https://github.com/ipython/ipython/issues/6450
478 dst = self.dst('target')
475 dst = self.dst('target')
479 path.link_or_copy(self.src, dst)
476 path.link_or_copy(self.src, dst)
480 path.link_or_copy(self.src, dst)
477 path.link_or_copy(self.src, dst)
481 self.assert_inode_equal(self.src, dst)
478 self.assert_inode_equal(self.src, dst)
482 nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
479 nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
General Comments 0
You need to be logged in to leave comments. Login now