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