Skip to content

Commit a9df076

Browse files
authored
GH-113528: Move a few misplaced pathlib tests (#113527)
`PurePathBase` does not define `__eq__()`, and so we have no business checking path equality in `test_eq_common` and `test_equivalences`. The tests only pass at the moment because we define the test class's `__eq__()` for use elsewhere. Also move `test_parse_path_common` into the main pathlib test suite. It exercises a private `_parse_path()` method that will be moved to `PurePath` soon. Lastly move a couple more tests concerned with optimisations and path normalisation.
1 parent aef375f commit a9df076

File tree

2 files changed

+86
-86
lines changed

2 files changed

+86
-86
lines changed

Lib/test/test_pathlib/test_pathlib.py

+86
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ class PurePathTest(test_pathlib_abc.DummyPurePathTest):
4545
# Make sure any symbolic links in the base test path are resolved.
4646
base = os.path.realpath(TESTFN)
4747

48+
# Keys are canonical paths, values are list of tuples of arguments
49+
# supposed to produce equal paths.
50+
equivalences = {
51+
'a/b': [
52+
('a', 'b'), ('a/', 'b'), ('a', 'b/'), ('a/', 'b/'),
53+
('a/b/',), ('a//b',), ('a//b//',),
54+
# Empty components get removed.
55+
('', 'a', 'b'), ('a', '', 'b'), ('a', 'b', ''),
56+
],
57+
'/b/c/d': [
58+
('a', '/b/c', 'd'), ('/a', '/b/c', 'd'),
59+
# Empty components get removed.
60+
('/', 'b', '', 'c/d'), ('/', '', 'b/c/d'), ('', '/b/c/d'),
61+
],
62+
}
63+
4864
def test_concrete_class(self):
4965
if self.cls is pathlib.PurePath:
5066
expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath
@@ -95,6 +111,45 @@ def test_constructor_nested(self):
95111
self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c")))
96112
self.assertEqual(P(P('./a:b')), P('./a:b'))
97113

114+
def _check_parse_path(self, raw_path, *expected):
115+
sep = self.pathmod.sep
116+
actual = self.cls._parse_path(raw_path.replace('/', sep))
117+
self.assertEqual(actual, expected)
118+
if altsep := self.pathmod.altsep:
119+
actual = self.cls._parse_path(raw_path.replace('/', altsep))
120+
self.assertEqual(actual, expected)
121+
122+
def test_parse_path_common(self):
123+
check = self._check_parse_path
124+
sep = self.pathmod.sep
125+
check('', '', '', [])
126+
check('a', '', '', ['a'])
127+
check('a/', '', '', ['a'])
128+
check('a/b', '', '', ['a', 'b'])
129+
check('a/b/', '', '', ['a', 'b'])
130+
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
131+
check('a/b//c/d', '', '', ['a', 'b', 'c', 'd'])
132+
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
133+
check('.', '', '', [])
134+
check('././b', '', '', ['b'])
135+
check('a/./b', '', '', ['a', 'b'])
136+
check('a/./.', '', '', ['a'])
137+
check('/a/b', '', sep, ['a', 'b'])
138+
139+
def test_empty_path(self):
140+
# The empty path points to '.'
141+
p = self.cls('')
142+
self.assertEqual(str(p), '.')
143+
144+
def test_parts_interning(self):
145+
P = self.cls
146+
p = P('/usr/bin/foo')
147+
q = P('/usr/local/bin')
148+
# 'usr'
149+
self.assertIs(p.parts[1], q.parts[1])
150+
# 'bin'
151+
self.assertIs(p.parts[2], q.parts[3])
152+
98153
def test_join_nested(self):
99154
P = self.cls
100155
p = P('a/b').joinpath(P('c'))
@@ -168,6 +223,37 @@ def test_as_bytes_common(self):
168223
P = self.cls
169224
self.assertEqual(bytes(P('a/b')), b'a' + sep + b'b')
170225

226+
def test_eq_common(self):
227+
P = self.cls
228+
self.assertEqual(P('a/b'), P('a/b'))
229+
self.assertEqual(P('a/b'), P('a', 'b'))
230+
self.assertNotEqual(P('a/b'), P('a'))
231+
self.assertNotEqual(P('a/b'), P('/a/b'))
232+
self.assertNotEqual(P('a/b'), P())
233+
self.assertNotEqual(P('/a/b'), P('/'))
234+
self.assertNotEqual(P(), P('/'))
235+
self.assertNotEqual(P(), "")
236+
self.assertNotEqual(P(), {})
237+
self.assertNotEqual(P(), int)
238+
239+
def test_equivalences(self):
240+
for k, tuples in self.equivalences.items():
241+
canon = k.replace('/', self.sep)
242+
posix = k.replace(self.sep, '/')
243+
if canon != posix:
244+
tuples = tuples + [
245+
tuple(part.replace('/', self.sep) for part in t)
246+
for t in tuples
247+
]
248+
tuples.append((posix, ))
249+
pcanon = self.cls(canon)
250+
for t in tuples:
251+
p = self.cls(*t)
252+
self.assertEqual(p, pcanon, "failed with args {}".format(t))
253+
self.assertEqual(hash(p), hash(pcanon))
254+
self.assertEqual(str(p), canon)
255+
self.assertEqual(p.as_posix(), posix)
256+
171257
def test_ordering_common(self):
172258
# Ordering is tuple-alike.
173259
def assertLess(a, b):

Lib/test/test_pathlib/test_pathlib_abc.py

-86
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,6 @@ class DummyPurePathTest(unittest.TestCase):
6161
# Use a base path that's unrelated to any real filesystem path.
6262
base = f'/this/path/kills/fascists/{TESTFN}'
6363

64-
# Keys are canonical paths, values are list of tuples of arguments
65-
# supposed to produce equal paths.
66-
equivalences = {
67-
'a/b': [
68-
('a', 'b'), ('a/', 'b'), ('a', 'b/'), ('a/', 'b/'),
69-
('a/b/',), ('a//b',), ('a//b//',),
70-
# Empty components get removed.
71-
('', 'a', 'b'), ('a', '', 'b'), ('a', 'b', ''),
72-
],
73-
'/b/c/d': [
74-
('a', '/b/c', 'd'), ('/a', '/b/c', 'd'),
75-
# Empty components get removed.
76-
('/', 'b', '', 'c/d'), ('/', '', 'b/c/d'), ('', '/b/c/d'),
77-
],
78-
}
79-
8064
def setUp(self):
8165
p = self.cls('a')
8266
self.pathmod = p.pathmod
@@ -132,31 +116,6 @@ def with_segments(self, *pathsegments):
132116
for parent in p.parents:
133117
self.assertEqual(42, parent.session_id)
134118

135-
def _check_parse_path(self, raw_path, *expected):
136-
sep = self.pathmod.sep
137-
actual = self.cls._parse_path(raw_path.replace('/', sep))
138-
self.assertEqual(actual, expected)
139-
if altsep := self.pathmod.altsep:
140-
actual = self.cls._parse_path(raw_path.replace('/', altsep))
141-
self.assertEqual(actual, expected)
142-
143-
def test_parse_path_common(self):
144-
check = self._check_parse_path
145-
sep = self.pathmod.sep
146-
check('', '', '', [])
147-
check('a', '', '', ['a'])
148-
check('a/', '', '', ['a'])
149-
check('a/b', '', '', ['a', 'b'])
150-
check('a/b/', '', '', ['a', 'b'])
151-
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
152-
check('a/b//c/d', '', '', ['a', 'b', 'c', 'd'])
153-
check('a/b/c/d', '', '', ['a', 'b', 'c', 'd'])
154-
check('.', '', '', [])
155-
check('././b', '', '', ['b'])
156-
check('a/./b', '', '', ['a', 'b'])
157-
check('a/./.', '', '', ['a'])
158-
check('/a/b', '', sep, ['a', 'b'])
159-
160119
def test_join_common(self):
161120
P = self.cls
162121
p = P('a/b')
@@ -202,19 +161,6 @@ def test_as_posix_common(self):
202161
self.assertEqual(P(pathstr).as_posix(), pathstr)
203162
# Other tests for as_posix() are in test_equivalences().
204163

205-
def test_eq_common(self):
206-
P = self.cls
207-
self.assertEqual(P('a/b'), P('a/b'))
208-
self.assertEqual(P('a/b'), P('a', 'b'))
209-
self.assertNotEqual(P('a/b'), P('a'))
210-
self.assertNotEqual(P('a/b'), P('/a/b'))
211-
self.assertNotEqual(P('a/b'), P())
212-
self.assertNotEqual(P('/a/b'), P('/'))
213-
self.assertNotEqual(P(), P('/'))
214-
self.assertNotEqual(P(), "")
215-
self.assertNotEqual(P(), {})
216-
self.assertNotEqual(P(), int)
217-
218164
def test_match_empty(self):
219165
P = self.cls
220166
self.assertRaises(ValueError, P('a').match, '')
@@ -299,24 +245,6 @@ def test_parts_common(self):
299245
parts = p.parts
300246
self.assertEqual(parts, (sep, 'a', 'b'))
301247

302-
def test_equivalences(self):
303-
for k, tuples in self.equivalences.items():
304-
canon = k.replace('/', self.sep)
305-
posix = k.replace(self.sep, '/')
306-
if canon != posix:
307-
tuples = tuples + [
308-
tuple(part.replace('/', self.sep) for part in t)
309-
for t in tuples
310-
]
311-
tuples.append((posix, ))
312-
pcanon = self.cls(canon)
313-
for t in tuples:
314-
p = self.cls(*t)
315-
self.assertEqual(p, pcanon, "failed with args {}".format(t))
316-
self.assertEqual(hash(p), hash(pcanon))
317-
self.assertEqual(str(p), canon)
318-
self.assertEqual(p.as_posix(), posix)
319-
320248
def test_parent_common(self):
321249
# Relative
322250
P = self.cls
@@ -918,11 +846,6 @@ def test_samefile(self):
918846
self.assertRaises(FileNotFoundError, r.samefile, r)
919847
self.assertRaises(FileNotFoundError, r.samefile, non_existent)
920848

921-
def test_empty_path(self):
922-
# The empty path points to '.'
923-
p = self.cls('')
924-
self.assertEqual(str(p), '.')
925-
926849
def test_exists(self):
927850
P = self.cls
928851
p = P(self.base)
@@ -1598,15 +1521,6 @@ def test_is_char_device_false(self):
15981521
self.assertIs((P / 'fileA\udfff').is_char_device(), False)
15991522
self.assertIs((P / 'fileA\x00').is_char_device(), False)
16001523

1601-
def test_parts_interning(self):
1602-
P = self.cls
1603-
p = P('/usr/bin/foo')
1604-
q = P('/usr/local/bin')
1605-
# 'usr'
1606-
self.assertIs(p.parts[1], q.parts[1])
1607-
# 'bin'
1608-
self.assertIs(p.parts[2], q.parts[3])
1609-
16101524
def _check_complex_symlinks(self, link0_target):
16111525
if not self.can_symlink:
16121526
self.skipTest("symlinks required")

0 commit comments

Comments
 (0)