diff options
Diffstat (limited to 'Lib/test/test_pathlib/test_pathlib.py')
-rw-r--r-- | Lib/test/test_pathlib/test_pathlib.py | 125 |
1 files changed, 115 insertions, 10 deletions
diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py index 51814ae970d..36fb62e53e1 100644 --- a/Lib/test/test_pathlib/test_pathlib.py +++ b/Lib/test/test_pathlib/test_pathlib.py @@ -20,9 +20,6 @@ from test.support import is_emscripten, is_wasi from test.support import infinite_recursion from test.support import os_helper from test.support.os_helper import TESTFN, FakePath -from test.test_pathlib import test_pathlib_abc -from test.test_pathlib.test_pathlib_abc import needs_posix, needs_windows - try: import fcntl except ImportError: @@ -56,7 +53,20 @@ def patch_replace(old_test): return new_test +_tests_needing_posix = set() +_tests_needing_windows = set() _tests_needing_symlinks = set() + +def needs_posix(fn): + """Decorator that marks a test as requiring a POSIX-flavoured path class.""" + _tests_needing_posix.add(fn.__name__) + return fn + +def needs_windows(fn): + """Decorator that marks a test as requiring a Windows-flavoured path class.""" + _tests_needing_windows.add(fn.__name__) + return fn + def needs_symlinks(fn): """Decorator that marks a test as requiring a path class that supports symlinks.""" _tests_needing_symlinks.add(fn.__name__) @@ -74,7 +84,7 @@ class UnsupportedOperationTest(unittest.TestCase): # Tests for the pure classes. # -class PurePathTest(test_pathlib_abc.JoinablePathTest): +class PurePathTest(unittest.TestCase): cls = pathlib.PurePath # Make sure any symbolic links in the base test path are resolved. @@ -96,6 +106,72 @@ class PurePathTest(test_pathlib_abc.JoinablePathTest): ], } + def setUp(self): + name = self.id().split('.')[-1] + if name in _tests_needing_posix and self.cls.parser is not posixpath: + self.skipTest('requires POSIX-flavoured path class') + if name in _tests_needing_windows and self.cls.parser is posixpath: + self.skipTest('requires Windows-flavoured path class') + p = self.cls('a') + self.parser = p.parser + self.sep = self.parser.sep + self.altsep = self.parser.altsep + + def _check_str_subclass(self, *args): + # Issue #21127: it should be possible to construct a PurePath object + # from a str subclass instance, and it then gets converted to + # a pure str object. + class StrSubclass(str): + pass + P = self.cls + p = P(*(StrSubclass(x) for x in args)) + self.assertEqual(p, P(*args)) + for part in p.parts: + self.assertIs(type(part), str) + + def test_str_subclass_common(self): + self._check_str_subclass('') + self._check_str_subclass('.') + self._check_str_subclass('a') + self._check_str_subclass('a/b.txt') + self._check_str_subclass('/a/b.txt') + + @needs_windows + def test_str_subclass_windows(self): + self._check_str_subclass('.\\a:b') + self._check_str_subclass('c:') + self._check_str_subclass('c:a') + self._check_str_subclass('c:a\\b.txt') + self._check_str_subclass('c:\\') + self._check_str_subclass('c:\\a') + self._check_str_subclass('c:\\a\\b.txt') + self._check_str_subclass('\\\\some\\share') + self._check_str_subclass('\\\\some\\share\\a') + self._check_str_subclass('\\\\some\\share\\a\\b.txt') + + def _check_str(self, expected, args): + p = self.cls(*args) + self.assertEqual(str(p), expected.replace('/', self.sep)) + + def test_str_common(self): + # Canonicalized paths roundtrip. + for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'): + self._check_str(pathstr, (pathstr,)) + # Other tests for str() are in test_equivalences(). + + @needs_windows + def test_str_windows(self): + p = self.cls('a/b/c') + self.assertEqual(str(p), 'a\\b\\c') + p = self.cls('c:/a/b/c') + self.assertEqual(str(p), 'c:\\a\\b\\c') + p = self.cls('//a/b') + self.assertEqual(str(p), '\\\\a\\b\\') + p = self.cls('//a/b/c') + self.assertEqual(str(p), '\\\\a\\b\\c') + p = self.cls('//a/b/c/d') + self.assertEqual(str(p), '\\\\a\\b\\c\\d') + def test_concrete_class(self): if self.cls is pathlib.PurePath: expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath @@ -1032,7 +1108,7 @@ class PurePathSubclassTest(PurePathTest): # Tests for the concrete classes. # -class PathTest(test_pathlib_abc.RWPathTest, PurePathTest): +class PathTest(PurePathTest): """Tests for the FS-accessing functionalities of the Path classes.""" cls = pathlib.Path can_symlink = os_helper.can_symlink() @@ -1042,8 +1118,6 @@ class PathTest(test_pathlib_abc.RWPathTest, PurePathTest): if name in _tests_needing_symlinks and not self.can_symlink: self.skipTest('requires symlinks') super().setUp() - - def createTestHierarchy(self): os.mkdir(self.base) os.mkdir(os.path.join(self.base, 'dirA')) os.mkdir(os.path.join(self.base, 'dirB')) @@ -1082,6 +1156,15 @@ class PathTest(test_pathlib_abc.RWPathTest, PurePathTest): os.chmod(os.path.join(self.base, 'dirE'), 0o777) os_helper.rmtree(self.base) + def assertFileNotFound(self, func, *args, **kwargs): + with self.assertRaises(FileNotFoundError) as cm: + func(*args, **kwargs) + self.assertEqual(cm.exception.errno, errno.ENOENT) + + def assertEqualNormCase(self, path_a, path_b): + normcase = self.parser.normcase + self.assertEqual(normcase(path_a), normcase(path_b)) + def tempdir(self): d = os_helper._longpath(tempfile.mkdtemp(suffix='-dirD', dir=os.getcwd())) @@ -2747,6 +2830,24 @@ class PathTest(test_pathlib_abc.RWPathTest, PurePathTest): expected = { P(self.base, 'linkB', q) for q in ['fileB', 'linkD'] } self.assertEqual(paths, expected) + @needs_posix + def test_glob_posix(self): + P = self.cls + p = P(self.base) + q = p / "FILEa" + given = set(p.glob("FILEa")) + expect = {q} if q.info.exists() else set() + self.assertEqual(given, expect) + self.assertEqual(set(p.glob("FILEa*")), set()) + + @needs_windows + def test_glob_windows(self): + P = self.cls + p = P(self.base) + self.assertEqual(set(p.glob("FILEa")), { P(self.base, "fileA") }) + self.assertEqual(set(p.glob("*a\\")), { P(self.base, "dirA/") }) + self.assertEqual(set(p.glob("F*a")), { P(self.base, "fileA") }) + def test_glob_empty_pattern(self): p = self.cls('') with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'): @@ -3335,7 +3436,7 @@ class PathTest(test_pathlib_abc.RWPathTest, PurePathTest): P('c:/').group() -class PathWalkTest(test_pathlib_abc.ReadablePathWalkTest): +class PathWalkTest(unittest.TestCase): cls = pathlib.Path base = PathTest.base can_symlink = PathTest.can_symlink @@ -3344,9 +3445,13 @@ class PathWalkTest(test_pathlib_abc.ReadablePathWalkTest): name = self.id().split('.')[-1] if name in _tests_needing_symlinks and not self.can_symlink: self.skipTest('requires symlinks') - super().setUp() + self.walk_path = self.cls(self.base, "TEST1") + self.sub1_path = self.walk_path / "SUB1" + self.sub11_path = self.sub1_path / "SUB11" + self.sub2_path = self.walk_path / "SUB2" + self.link_path = self.sub2_path / "link" + self.sub2_tree = (self.sub2_path, [], ["tmp3"]) - def createTestHierarchy(self): # Build: # TESTFN/ # TEST1/ a file kid and two directory kids |