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