Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 45c2ef4

Browse filesBrowse files
authored
GH-130614: pathlib ABCs: parametrize test suite for path copying (#131168)
Test copying from `Path` and `ReadableZipPath` (types of `_ReadablePath`) to `Path` and `WritableZipPath` (types of `_WritablePath`).
1 parent 1a8e574 commit 45c2ef4
Copy full SHA for 45c2ef4

File tree

3 files changed

+173
-139
lines changed
Filter options

3 files changed

+173
-139
lines changed

‎Lib/pathlib/_os.py

Copy file name to clipboardExpand all lines: Lib/pathlib/_os.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def copy_file(source, target, follow_symlinks=True, preserve_metadata=False):
248248
"""
249249
info = source.info
250250
if not follow_symlinks and info.is_symlink():
251-
target.symlink_to(source.readlink(), info.is_dir())
251+
target.symlink_to(str(source.readlink()), info.is_dir())
252252
if preserve_metadata:
253253
target._write_info(info, follow_symlinks=False)
254254
elif info.is_dir():

‎Lib/test/test_pathlib/test_copy.py

Copy file name to clipboard
+172Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
"""
2+
Tests for copying from pathlib.types._ReadablePath to _WritablePath.
3+
"""
4+
5+
import contextlib
6+
import unittest
7+
8+
from pathlib import Path
9+
10+
from test.test_pathlib.support.local_path import LocalPathGround, WritableLocalPath
11+
from test.test_pathlib.support.zip_path import ZipPathGround, ReadableZipPath, WritableZipPath
12+
13+
14+
class CopyTestBase:
15+
def setUp(self):
16+
self.source_root = self.source_ground.setup()
17+
self.source_ground.create_hierarchy(self.source_root)
18+
self.target_root = self.target_ground.setup(local_suffix="_target")
19+
20+
def tearDown(self):
21+
self.source_ground.teardown(self.source_root)
22+
self.target_ground.teardown(self.target_root)
23+
24+
def test_copy_file(self):
25+
source = self.source_root / 'fileA'
26+
target = self.target_root / 'copyA'
27+
result = source.copy(target)
28+
self.assertEqual(result, target)
29+
self.assertTrue(self.target_ground.isfile(target))
30+
self.assertEqual(self.source_ground.readbytes(source),
31+
self.target_ground.readbytes(result))
32+
33+
def test_copy_file_empty(self):
34+
source = self.source_root / 'empty'
35+
target = self.target_root / 'copyA'
36+
self.source_ground.create_file(source, b'')
37+
result = source.copy(target)
38+
self.assertEqual(result, target)
39+
self.assertTrue(self.target_ground.isfile(target))
40+
self.assertEqual(self.target_ground.readbytes(result), b'')
41+
42+
def test_copy_file_to_existing_file(self):
43+
source = self.source_root / 'fileA'
44+
target = self.target_root / 'copyA'
45+
self.target_ground.create_file(target, b'this is a copy\n')
46+
with contextlib.ExitStack() as stack:
47+
if isinstance(target, WritableZipPath):
48+
stack.enter_context(self.assertWarns(UserWarning))
49+
result = source.copy(target)
50+
self.assertEqual(result, target)
51+
self.assertTrue(self.target_ground.isfile(target))
52+
self.assertEqual(self.source_ground.readbytes(source),
53+
self.target_ground.readbytes(result))
54+
55+
def test_copy_file_to_directory(self):
56+
if not isinstance(self.target_root, WritableLocalPath):
57+
self.skipTest('needs local target')
58+
source = self.source_root / 'fileA'
59+
target = self.target_root / 'copyA'
60+
self.target_ground.create_dir(target)
61+
self.assertRaises(OSError, source.copy, target)
62+
63+
def test_copy_file_to_itself(self):
64+
source = self.source_root / 'fileA'
65+
self.assertRaises(OSError, source.copy, source)
66+
self.assertRaises(OSError, source.copy, source, follow_symlinks=False)
67+
68+
def test_copy_dir(self):
69+
source = self.source_root / 'dirC'
70+
target = self.target_root / 'copyC'
71+
result = source.copy(target)
72+
self.assertEqual(result, target)
73+
self.assertTrue(self.target_ground.isdir(target))
74+
self.assertTrue(self.target_ground.isfile(target / 'fileC'))
75+
self.assertEqual(self.target_ground.readtext(target / 'fileC'), 'this is file C\n')
76+
self.assertTrue(self.target_ground.isdir(target / 'dirD'))
77+
self.assertTrue(self.target_ground.isfile(target / 'dirD' / 'fileD'))
78+
self.assertEqual(self.target_ground.readtext(target / 'dirD' / 'fileD'), 'this is file D\n')
79+
80+
def test_copy_dir_follow_symlinks_true(self):
81+
if not self.source_ground.can_symlink:
82+
self.skipTest('needs symlink support on source')
83+
source = self.source_root / 'dirC'
84+
target = self.target_root / 'copyC'
85+
self.source_ground.create_symlink(source / 'linkC', 'fileC')
86+
self.source_ground.create_symlink(source / 'linkD', 'dirD')
87+
result = source.copy(target)
88+
self.assertEqual(result, target)
89+
self.assertTrue(self.target_ground.isdir(target))
90+
self.assertFalse(self.target_ground.islink(target / 'linkC'))
91+
self.assertTrue(self.target_ground.isfile(target / 'linkC'))
92+
self.assertEqual(self.target_ground.readtext(target / 'linkC'), 'this is file C\n')
93+
self.assertFalse(self.target_ground.islink(target / 'linkD'))
94+
self.assertTrue(self.target_ground.isdir(target / 'linkD'))
95+
self.assertTrue(self.target_ground.isfile(target / 'linkD' / 'fileD'))
96+
self.assertEqual(self.target_ground.readtext(target / 'linkD' / 'fileD'), 'this is file D\n')
97+
98+
def test_copy_dir_follow_symlinks_false(self):
99+
if not self.source_ground.can_symlink:
100+
self.skipTest('needs symlink support on source')
101+
if not self.target_ground.can_symlink:
102+
self.skipTest('needs symlink support on target')
103+
source = self.source_root / 'dirC'
104+
target = self.target_root / 'copyC'
105+
self.source_ground.create_symlink(source / 'linkC', 'fileC')
106+
self.source_ground.create_symlink(source / 'linkD', 'dirD')
107+
result = source.copy(target, follow_symlinks=False)
108+
self.assertEqual(result, target)
109+
self.assertTrue(self.target_ground.isdir(target))
110+
self.assertTrue(self.target_ground.islink(target / 'linkC'))
111+
self.assertEqual(self.target_ground.readlink(target / 'linkC'), 'fileC')
112+
self.assertTrue(self.target_ground.islink(target / 'linkD'))
113+
self.assertEqual(self.target_ground.readlink(target / 'linkD'), 'dirD')
114+
115+
def test_copy_dir_to_existing_directory(self):
116+
if not isinstance(self.target_root, WritableLocalPath):
117+
self.skipTest('needs local target')
118+
source = self.source_root / 'dirC'
119+
target = self.target_root / 'copyC'
120+
self.target_ground.create_dir(target)
121+
self.assertRaises(FileExistsError, source.copy, target)
122+
123+
def test_copy_dir_to_itself(self):
124+
source = self.source_root / 'dirC'
125+
self.assertRaises(OSError, source.copy, source)
126+
self.assertRaises(OSError, source.copy, source, follow_symlinks=False)
127+
128+
def test_copy_dir_into_itself(self):
129+
source = self.source_root / 'dirC'
130+
target = self.source_root / 'dirC' / 'dirD' / 'copyC'
131+
self.assertRaises(OSError, source.copy, target)
132+
self.assertRaises(OSError, source.copy, target, follow_symlinks=False)
133+
134+
def test_copy_into(self):
135+
source = self.source_root / 'fileA'
136+
target_dir = self.target_root / 'dirA'
137+
self.target_ground.create_dir(target_dir)
138+
result = source.copy_into(target_dir)
139+
self.assertEqual(result, target_dir / 'fileA')
140+
self.assertTrue(self.target_ground.isfile(result))
141+
self.assertEqual(self.source_ground.readbytes(source),
142+
self.target_ground.readbytes(result))
143+
144+
def test_copy_into_empty_name(self):
145+
source = self.source_root.with_segments()
146+
target_dir = self.target_root / 'dirA'
147+
self.target_ground.create_dir(target_dir)
148+
self.assertRaises(ValueError, source.copy_into, target_dir)
149+
150+
151+
class ZipToZipPathCopyTest(CopyTestBase, unittest.TestCase):
152+
source_ground = ZipPathGround(ReadableZipPath)
153+
target_ground = ZipPathGround(WritableZipPath)
154+
155+
156+
class ZipToLocalPathCopyTest(CopyTestBase, unittest.TestCase):
157+
source_ground = ZipPathGround(ReadableZipPath)
158+
target_ground = LocalPathGround(Path)
159+
160+
161+
class LocalToZipPathCopyTest(CopyTestBase, unittest.TestCase):
162+
source_ground = LocalPathGround(Path)
163+
target_ground = ZipPathGround(WritableZipPath)
164+
165+
166+
class LocalToLocalPathCopyTest(CopyTestBase, unittest.TestCase):
167+
source_ground = LocalPathGround(Path)
168+
target_ground = LocalPathGround(Path)
169+
170+
171+
if __name__ == "__main__":
172+
unittest.main()

‎Lib/test/test_pathlib/test_pathlib_abc.py

Copy file name to clipboardExpand all lines: Lib/test/test_pathlib/test_pathlib_abc.py
-138Lines changed: 0 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -343,144 +343,6 @@ class RWPathTest(WritablePathTest, ReadablePathTest):
343343
cls = DummyRWPath
344344
can_symlink = False
345345

346-
def test_copy_file(self):
347-
base = self.cls(self.base)
348-
source = base / 'fileA'
349-
target = base / 'copyA'
350-
result = source.copy(target)
351-
self.assertEqual(result, target)
352-
self.assertTrue(result.info.exists())
353-
self.assertEqual(source.read_text(), result.read_text())
354-
355-
def test_copy_file_to_existing_file(self):
356-
base = self.cls(self.base)
357-
source = base / 'fileA'
358-
target = base / 'dirB' / 'fileB'
359-
result = source.copy(target)
360-
self.assertEqual(result, target)
361-
self.assertTrue(result.info.exists())
362-
self.assertEqual(source.read_text(), result.read_text())
363-
364-
def test_copy_file_to_existing_directory(self):
365-
base = self.cls(self.base)
366-
source = base / 'fileA'
367-
target = base / 'dirA'
368-
self.assertRaises(OSError, source.copy, target)
369-
370-
def test_copy_file_empty(self):
371-
base = self.cls(self.base)
372-
source = base / 'empty'
373-
target = base / 'copyA'
374-
source.write_bytes(b'')
375-
result = source.copy(target)
376-
self.assertEqual(result, target)
377-
self.assertTrue(result.info.exists())
378-
self.assertEqual(result.read_bytes(), b'')
379-
380-
def test_copy_file_to_itself(self):
381-
base = self.cls(self.base)
382-
source = base / 'empty'
383-
source.write_bytes(b'')
384-
self.assertRaises(OSError, source.copy, source)
385-
self.assertRaises(OSError, source.copy, source, follow_symlinks=False)
386-
387-
def test_copy_dir_simple(self):
388-
base = self.cls(self.base)
389-
source = base / 'dirC'
390-
target = base / 'copyC'
391-
result = source.copy(target)
392-
self.assertEqual(result, target)
393-
self.assertTrue(result.info.is_dir())
394-
self.assertTrue(result.joinpath('dirD').info.is_dir())
395-
self.assertTrue(result.joinpath('dirD', 'fileD').info.is_file())
396-
self.assertEqual(result.joinpath('dirD', 'fileD').read_text(),
397-
"this is file D\n")
398-
self.assertTrue(result.joinpath('fileC').info.is_file())
399-
self.assertTrue(result.joinpath('fileC').read_text(),
400-
"this is file C\n")
401-
402-
def test_copy_dir_complex(self, follow_symlinks=True):
403-
def ordered_walk(path):
404-
for dirpath, dirnames, filenames in path.walk(follow_symlinks=follow_symlinks):
405-
dirnames.sort()
406-
filenames.sort()
407-
yield dirpath, dirnames, filenames
408-
base = self.cls(self.base)
409-
source = base / 'dirC'
410-
411-
if self.can_symlink:
412-
# Add some symlinks
413-
source.joinpath('linkC').symlink_to('fileC')
414-
source.joinpath('linkD').symlink_to('dirD', target_is_directory=True)
415-
416-
# Perform the copy
417-
target = base / 'copyC'
418-
result = source.copy(target, follow_symlinks=follow_symlinks)
419-
self.assertEqual(result, target)
420-
421-
# Compare the source and target trees
422-
source_walk = ordered_walk(source)
423-
target_walk = ordered_walk(result)
424-
for source_item, target_item in zip(source_walk, target_walk, strict=True):
425-
self.assertEqual(source_item[0].parts[len(source.parts):],
426-
target_item[0].parts[len(target.parts):]) # dirpath
427-
self.assertEqual(source_item[1], target_item[1]) # dirnames
428-
self.assertEqual(source_item[2], target_item[2]) # filenames
429-
# Compare files and symlinks
430-
for filename in source_item[2]:
431-
source_file = source_item[0].joinpath(filename)
432-
target_file = target_item[0].joinpath(filename)
433-
if follow_symlinks or not source_file.info.is_symlink():
434-
# Regular file.
435-
self.assertEqual(source_file.read_bytes(), target_file.read_bytes())
436-
elif source_file.info.is_dir():
437-
# Symlink to directory.
438-
self.assertTrue(target_file.info.is_dir())
439-
self.assertEqual(source_file.readlink(), target_file.readlink())
440-
else:
441-
# Symlink to file.
442-
self.assertEqual(source_file.read_bytes(), target_file.read_bytes())
443-
self.assertEqual(source_file.readlink(), target_file.readlink())
444-
445-
def test_copy_dir_complex_follow_symlinks_false(self):
446-
self.test_copy_dir_complex(follow_symlinks=False)
447-
448-
def test_copy_dir_to_existing_directory(self):
449-
base = self.cls(self.base)
450-
source = base / 'dirC'
451-
target = base / 'copyC'
452-
target.mkdir()
453-
target.joinpath('dirD').mkdir()
454-
self.assertRaises(FileExistsError, source.copy, target)
455-
456-
def test_copy_dir_to_itself(self):
457-
base = self.cls(self.base)
458-
source = base / 'dirC'
459-
self.assertRaises(OSError, source.copy, source)
460-
self.assertRaises(OSError, source.copy, source, follow_symlinks=False)
461-
462-
def test_copy_dir_into_itself(self):
463-
base = self.cls(self.base)
464-
source = base / 'dirC'
465-
target = base / 'dirC' / 'dirD' / 'copyC'
466-
self.assertRaises(OSError, source.copy, target)
467-
self.assertRaises(OSError, source.copy, target, follow_symlinks=False)
468-
self.assertFalse(target.info.exists())
469-
470-
def test_copy_into(self):
471-
base = self.cls(self.base)
472-
source = base / 'fileA'
473-
target_dir = base / 'dirA'
474-
result = source.copy_into(target_dir)
475-
self.assertEqual(result, target_dir / 'fileA')
476-
self.assertTrue(result.info.exists())
477-
self.assertEqual(source.read_text(), result.read_text())
478-
479-
def test_copy_into_empty_name(self):
480-
source = self.cls('')
481-
target_dir = self.base
482-
self.assertRaises(ValueError, source.copy_into, target_dir)
483-
484346

485347
class ReadablePathWalkTest(unittest.TestCase):
486348
cls = DummyReadablePath

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.