Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-89812: Clean up pathlib tests. #104829

Merged
merged 4 commits into from
Jun 14, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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