Skip to content

Commit

Permalink
GH-89812: Clean up pathlib tests. (#104829)
Browse files Browse the repository at this point in the history
Clean up pathlib tests.

Merge `PurePathTest` into `_BasePurePathTest`, and `PathTest` into
`_BasePathTest`.
  • Loading branch information
barneygale committed Jun 14, 2023
1 parent b95de96 commit dab5a3e
Showing 1 changed file with 96 additions and 84 deletions.
180 changes: 96 additions & 84 deletions Lib/test/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import errno
import pathlib
import pickle
import posixpath
import socket
import stat
import tempfile
Expand All @@ -23,20 +24,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.
Expand Down Expand Up @@ -75,6 +79,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 "
Expand Down Expand Up @@ -122,8 +157,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)
Expand Down Expand Up @@ -723,7 +763,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):
Expand Down Expand Up @@ -817,10 +857,10 @@ def test_parse_windows_path(self):
self.assertEqual(p, pp)


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') ],
Expand Down Expand Up @@ -1491,45 +1531,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):
Expand All @@ -1550,9 +1559,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
Expand Down Expand Up @@ -1627,6 +1642,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)
Expand Down Expand Up @@ -1683,8 +1712,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)
Expand Down Expand Up @@ -1872,6 +1906,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):
Expand Down Expand Up @@ -3022,28 +3061,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):
Expand Down Expand Up @@ -3227,7 +3246,7 @@ def test_handling_bad_descriptor(self):


@only_nt
class WindowsPathTest(_BasePathTest, unittest.TestCase):
class WindowsPathTest(PathTest):
cls = pathlib.WindowsPath

def test_absolute(self):
Expand Down Expand Up @@ -3345,15 +3364,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

Expand Down

0 comments on commit dab5a3e

Please sign in to comment.