From 30ae2ed54ad02738c3995339f54092e9180671a8 Mon Sep 17 00:00:00 2001 From: barneygale Date: Wed, 24 May 2023 02:36:24 +0100 Subject: [PATCH] Clean up pathlib tests. Merge `PurePathTest` into `_BasePurePathTest`, and `PathTest` into `_BasePathTest`. --- Lib/test/test_pathlib.py | 180 +++++++++++++++++++++------------------ 1 file changed, 96 insertions(+), 84 deletions(-) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index ab2c2b232a0411..1db4f42f426987 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -6,6 +6,7 @@ import errno import pathlib import pickle +import posixpath import socket import stat import tempfile @@ -24,20 +25,23 @@ grp = pwd = None -# -# Tests for the pure classes. -# +# Make sure any symbolic links in the base test path are resolved. +BASE = os.path.realpath(TESTFN) +join = lambda *x: os.path.join(BASE, *x) +rel_join = lambda *x: os.path.join(TESTFN, *x) -class _BasePurePathSubclass(object): - def __init__(self, *pathsegments, session_id): - super().__init__(*pathsegments) - self.session_id = session_id +only_nt = unittest.skipIf(os.name != 'nt', + 'test requires a Windows-compatible system') +only_posix = unittest.skipIf(os.name == 'nt', + 'test requires a POSIX-compatible system') - def with_segments(self, *pathsegments): - return type(self)(*pathsegments, session_id=self.session_id) +# +# Tests for the pure classes. +# -class _BasePurePathTest(object): +class PurePathTest(unittest.TestCase): + cls = pathlib.PurePath # Keys are canonical paths, values are list of tuples of arguments # supposed to produce equal paths. @@ -76,6 +80,37 @@ def test_constructor_common(self): self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c"))) self.assertEqual(P(P('./a:b')), P('./a:b')) + def test_concrete_class(self): + if self.cls is pathlib.PurePath: + expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath + else: + expected = self.cls + p = self.cls('a') + self.assertIs(type(p), expected) + + def test_different_flavours_unequal(self): + p = self.cls('a') + if p._flavour is posixpath: + q = pathlib.PureWindowsPath('a') + else: + q = pathlib.PurePosixPath('a') + self.assertNotEqual(p, q) + + def test_different_flavours_unordered(self): + p = self.cls('a') + if p._flavour is posixpath: + q = pathlib.PureWindowsPath('a') + else: + q = pathlib.PurePosixPath('a') + with self.assertRaises(TypeError): + p < q + with self.assertRaises(TypeError): + p <= q + with self.assertRaises(TypeError): + p > q + with self.assertRaises(TypeError): + p >= q + def test_bytes(self): P = self.cls message = (r"argument should be a str or an os\.PathLike object " @@ -123,8 +158,13 @@ def test_str_subclass_common(self): self._check_str_subclass('/a/b.txt') def test_with_segments_common(self): - class P(_BasePurePathSubclass, self.cls): - pass + class P(self.cls): + def __init__(self, *pathsegments, session_id): + super().__init__(*pathsegments) + self.session_id = session_id + + def with_segments(self, *pathsegments): + return type(self)(*pathsegments, session_id=self.session_id) p = P('foo', 'bar', session_id=42) self.assertEqual(42, (p / 'foo').session_id) self.assertEqual(42, ('foo' / p).session_id) @@ -702,7 +742,7 @@ def test_pickling_common(self): self.assertEqual(str(pp), str(p)) -class PurePosixPathTest(_BasePurePathTest, unittest.TestCase): +class PurePosixPathTest(PurePathTest): cls = pathlib.PurePosixPath def test_drive_root_parts(self): @@ -790,10 +830,10 @@ def test_div(self): self.assertEqual(pp, P('/c')) -class PureWindowsPathTest(_BasePurePathTest, unittest.TestCase): +class PureWindowsPathTest(PurePathTest): cls = pathlib.PureWindowsPath - equivalences = _BasePurePathTest.equivalences.copy() + equivalences = PurePathTest.equivalences.copy() equivalences.update({ './a:b': [ ('./a:b',) ], 'c:a': [ ('c:', 'a'), ('c:', 'a/'), ('.', 'c:', 'a') ], @@ -1463,45 +1503,14 @@ def test_is_reserved(self): self.assertIs(True, P('c:/baz/con/NUL').is_reserved()) self.assertIs(False, P('c:/NUL/con/baz').is_reserved()) -class PurePathTest(_BasePurePathTest, unittest.TestCase): - cls = pathlib.PurePath - - def test_concrete_class(self): - p = self.cls('a') - self.assertIs(type(p), - pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath) - - def test_different_flavours_unequal(self): - p = pathlib.PurePosixPath('a') - q = pathlib.PureWindowsPath('a') - self.assertNotEqual(p, q) - - def test_different_flavours_unordered(self): - p = pathlib.PurePosixPath('a') - q = pathlib.PureWindowsPath('a') - with self.assertRaises(TypeError): - p < q - with self.assertRaises(TypeError): - p <= q - with self.assertRaises(TypeError): - p > q - with self.assertRaises(TypeError): - p >= q - -# -# Tests for the concrete classes. -# +class PurePathSubclassTest(PurePathTest): + class cls(pathlib.PurePath): + pass -# Make sure any symbolic links in the base test path are resolved. -BASE = os.path.realpath(TESTFN) -join = lambda *x: os.path.join(BASE, *x) -rel_join = lambda *x: os.path.join(TESTFN, *x) + # repr() roundtripping is not supported in custom subclass. + test_repr_roundtrips = None -only_nt = unittest.skipIf(os.name != 'nt', - 'test requires a Windows-compatible system') -only_posix = unittest.skipIf(os.name == 'nt', - 'test requires a POSIX-compatible system') @only_posix class PosixPathAsPureTest(PurePosixPathTest): @@ -1522,9 +1531,15 @@ def test_group(self): P('c:/').group() -class _BasePathTest(object): +# +# Tests for the concrete classes. +# + +class PathTest(unittest.TestCase): """Tests for the FS-accessing functionalities of the Path classes.""" + cls = pathlib.Path + # (BASE) # | # |-- brokenLink -> non-existing @@ -1599,6 +1614,20 @@ def assertFileNotFound(self, func, *args, **kwargs): def assertEqualNormCase(self, path_a, path_b): self.assertEqual(os.path.normcase(path_a), os.path.normcase(path_b)) + def test_concrete_class(self): + if self.cls is pathlib.Path: + expected = pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath + else: + expected = self.cls + p = self.cls('a') + self.assertIs(type(p), expected) + + def test_unsupported_flavour(self): + if self.cls._flavour is os.path: + self.skipTest("path flavour is supported") + else: + self.assertRaises(NotImplementedError, self.cls) + def _test_cwd(self, p): q = self.cls(os.getcwd()) self.assertEqual(p, q) @@ -1655,8 +1684,13 @@ def test_home(self): self._test_home(self.cls.home()) def test_with_segments(self): - class P(_BasePurePathSubclass, self.cls): - pass + class P(self.cls): + def __init__(self, *pathsegments, session_id): + super().__init__(*pathsegments) + self.session_id = session_id + + def with_segments(self, *pathsegments): + return type(self)(*pathsegments, session_id=self.session_id) p = P(BASE, session_id=42) self.assertEqual(42, p.absolute().session_id) self.assertEqual(42, p.resolve().session_id) @@ -1844,6 +1878,11 @@ def _check(glob, expected): else: _check(p.glob("*/"), ["dirA", "dirB", "dirC", "dirE", "linkB"]) + def test_glob_empty_pattern(self): + p = self.cls() + with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'): + list(p.glob('')) + def test_glob_case_sensitive(self): P = self.cls def _check(path, pattern, case_sensitive, expected): @@ -2913,28 +2952,8 @@ def test_walk_above_recursion_limit(self): list(base.walk(top_down=False)) -class PathTest(_BasePathTest, unittest.TestCase): - cls = pathlib.Path - - def test_concrete_class(self): - p = self.cls('a') - self.assertIs(type(p), - pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath) - - def test_unsupported_flavour(self): - if os.name == 'nt': - self.assertRaises(NotImplementedError, pathlib.PosixPath) - else: - self.assertRaises(NotImplementedError, pathlib.WindowsPath) - - def test_glob_empty_pattern(self): - p = self.cls() - with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'): - list(p.glob('')) - - @only_posix -class PosixPathTest(_BasePathTest, unittest.TestCase): +class PosixPathTest(PathTest): cls = pathlib.PosixPath def test_absolute(self): @@ -3118,7 +3137,7 @@ def test_handling_bad_descriptor(self): @only_nt -class WindowsPathTest(_BasePathTest, unittest.TestCase): +class WindowsPathTest(PathTest): cls = pathlib.WindowsPath def test_absolute(self): @@ -3236,15 +3255,8 @@ def check(): check() -class PurePathSubclassTest(_BasePurePathTest, unittest.TestCase): - class cls(pathlib.PurePath): - pass - - # repr() roundtripping is not supported in custom subclass. - test_repr_roundtrips = None - -class PathSubclassTest(_BasePathTest, unittest.TestCase): +class PathSubclassTest(PathTest): class cls(pathlib.Path): pass