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