[Python-checkins] GH-89812: Churn `pathlib.Path` test methods (#105807)

barneygale webhook-mailer at python.org
Wed Jun 14 21:31:33 EDT 2023


https://github.com/python/cpython/commit/10bf2cd404320252ef162d5699cb7ce52a970d44
commit: 10bf2cd404320252ef162d5699cb7ce52a970d44
branch: main
author: Barney Gale <barney.gale at gmail.com>
committer: barneygale <barney.gale at gmail.com>
date: 2023-06-15T01:31:30Z
summary:

GH-89812: Churn `pathlib.Path` test methods (#105807)

Re-arrange `pathlib.Path` test methods in source code. No other changes.

The test methods are arranged in two groups. The first group checks
`stat()`, `open()`, `iterdir()`, `readlink()`, and derived methods like
`exists()`, `read_text()`, `glob()` and `resolve()`. The second group
checks all other `Path` methods. To minimise the diff I've maintained the
method order within groups where possible.

This patch prepares the ground for a new `_AbstractPath` class, which will
support methods in the first group above. By churning the test methods
here, subsequent patches will be easier to review and less likely to break
things.

files:
M Lib/test/test_pathlib.py

diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py
index 46ac30e91e32..02a0f25e0bd9 100644
--- a/Lib/test/test_pathlib.py
+++ b/Lib/test/test_pathlib.py
@@ -1642,101 +1642,6 @@ 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)
-        self.assertEqualNormCase(str(p), str(q))
-        self.assertIs(type(p), type(q))
-        self.assertTrue(p.is_absolute())
-
-    def test_cwd(self):
-        p = self.cls.cwd()
-        self._test_cwd(p)
-
-    def test_absolute_common(self):
-        P = self.cls
-
-        with mock.patch("os.getcwd") as getcwd:
-            getcwd.return_value = BASE
-
-            # Simple relative paths.
-            self.assertEqual(str(P().absolute()), BASE)
-            self.assertEqual(str(P('.').absolute()), BASE)
-            self.assertEqual(str(P('a').absolute()), os.path.join(BASE, 'a'))
-            self.assertEqual(str(P('a', 'b', 'c').absolute()), os.path.join(BASE, 'a', 'b', 'c'))
-
-            # Symlinks should not be resolved.
-            self.assertEqual(str(P('linkB', 'fileB').absolute()), os.path.join(BASE, 'linkB', 'fileB'))
-            self.assertEqual(str(P('brokenLink').absolute()), os.path.join(BASE, 'brokenLink'))
-            self.assertEqual(str(P('brokenLinkLoop').absolute()), os.path.join(BASE, 'brokenLinkLoop'))
-
-            # '..' entries should be preserved and not normalised.
-            self.assertEqual(str(P('..').absolute()), os.path.join(BASE, '..'))
-            self.assertEqual(str(P('a', '..').absolute()), os.path.join(BASE, 'a', '..'))
-            self.assertEqual(str(P('..', 'b').absolute()), os.path.join(BASE, '..', 'b'))
-
-    def _test_home(self, p):
-        q = self.cls(os.path.expanduser('~'))
-        self.assertEqual(p, q)
-        self.assertEqualNormCase(str(p), str(q))
-        self.assertIs(type(p), type(q))
-        self.assertTrue(p.is_absolute())
-
-    @unittest.skipIf(
-        pwd is None, reason="Test requires pwd module to get homedir."
-    )
-    def test_home(self):
-        with os_helper.EnvironmentVarGuard() as env:
-            self._test_home(self.cls.home())
-
-            env.clear()
-            env['USERPROFILE'] = os.path.join(BASE, 'userprofile')
-            self._test_home(self.cls.home())
-
-            # bpo-38883: ignore `HOME` when set on windows
-            env['HOME'] = os.path.join(BASE, 'home')
-            self._test_home(self.cls.home())
-
-    def test_with_segments(self):
-        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)
-        if not is_wasi:  # WASI has no user accounts.
-            self.assertEqual(42, p.with_segments('~').expanduser().session_id)
-        self.assertEqual(42, (p / 'fileA').rename(p / 'fileB').session_id)
-        self.assertEqual(42, (p / 'fileB').replace(p / 'fileA').session_id)
-        if os_helper.can_symlink():
-            self.assertEqual(42, (p / 'linkA').readlink().session_id)
-        for path in p.iterdir():
-            self.assertEqual(42, path.session_id)
-        for path in p.glob('*'):
-            self.assertEqual(42, path.session_id)
-        for path in p.rglob('*'):
-            self.assertEqual(42, path.session_id)
-        for dirpath, dirnames, filenames in p.walk():
-            self.assertEqual(42, dirpath.session_id)
-
     def test_samefile(self):
         fileA_path = os.path.join(BASE, 'fileA')
         fileB_path = os.path.join(BASE, 'dirB', 'fileB')
@@ -1762,22 +1667,6 @@ def test_empty_path(self):
         p = self.cls('')
         self.assertEqual(p.stat(), os.stat('.'))
 
-    @unittest.skipIf(is_wasi, "WASI has no user accounts.")
-    def test_expanduser_common(self):
-        P = self.cls
-        p = P('~')
-        self.assertEqual(p.expanduser(), P(os.path.expanduser('~')))
-        p = P('foo')
-        self.assertEqual(p.expanduser(), p)
-        p = P('/~')
-        self.assertEqual(p.expanduser(), p)
-        p = P('../~')
-        self.assertEqual(p.expanduser(), p)
-        p = P(P('').absolute().anchor) / '~'
-        self.assertEqual(p.expanduser(), p)
-        p = P('~/a:b')
-        self.assertEqual(p.expanduser(), P(os.path.expanduser('~'), './a:b'))
-
     def test_exists(self):
         P = self.cls
         p = P(BASE)
@@ -2156,6 +2045,16 @@ def test_glob_above_recursion_limit(self):
         with set_recursion_limit(recursion_limit):
             list(base.glob('**'))
 
+    @os_helper.skip_unless_symlink
+    def test_readlink(self):
+        P = self.cls(BASE)
+        self.assertEqual((P / 'linkA').readlink(), self.cls('fileA'))
+        self.assertEqual((P / 'brokenLink').readlink(),
+                         self.cls('non-existing'))
+        self.assertEqual((P / 'linkB').readlink(), self.cls('dirB'))
+        with self.assertRaises(OSError):
+            (P / 'fileA').readlink()
+
     def _check_resolve(self, p, expected, strict=True):
         q = p.resolve(strict)
         self.assertEqual(q, expected)
@@ -2238,47 +2137,6 @@ def test_resolve_dot(self):
         # Non-strict
         self.assertEqual(r.resolve(strict=False), p / '3' / '4')
 
-    def test_resolve_nonexist_relative_issue38671(self):
-        p = self.cls('non', 'exist')
-
-        old_cwd = os.getcwd()
-        os.chdir(BASE)
-        try:
-            self.assertEqual(p.resolve(), self.cls(BASE, p))
-        finally:
-            os.chdir(old_cwd)
-
-    @os_helper.skip_unless_working_chmod
-    def test_chmod(self):
-        p = self.cls(BASE) / 'fileA'
-        mode = p.stat().st_mode
-        # Clear writable bit.
-        new_mode = mode & ~0o222
-        p.chmod(new_mode)
-        self.assertEqual(p.stat().st_mode, new_mode)
-        # Set writable bit.
-        new_mode = mode | 0o222
-        p.chmod(new_mode)
-        self.assertEqual(p.stat().st_mode, new_mode)
-
-    # On Windows, os.chmod does not follow symlinks (issue #15411)
-    @only_posix
-    @os_helper.skip_unless_working_chmod
-    def test_chmod_follow_symlinks_true(self):
-        p = self.cls(BASE) / 'linkA'
-        q = p.resolve()
-        mode = q.stat().st_mode
-        # Clear writable bit.
-        new_mode = mode & ~0o222
-        p.chmod(new_mode, follow_symlinks=True)
-        self.assertEqual(q.stat().st_mode, new_mode)
-        # Set writable bit
-        new_mode = mode | 0o222
-        p.chmod(new_mode, follow_symlinks=True)
-        self.assertEqual(q.stat().st_mode, new_mode)
-
-    # XXX also need a test for lchmod.
-
     @os_helper.skip_unless_working_chmod
     def test_stat(self):
         p = self.cls(BASE) / 'fileA'
@@ -2311,82 +2169,396 @@ def test_lstat_nosymlink(self):
         st = p.stat()
         self.assertEqual(st, p.lstat())
 
-    @unittest.skipUnless(pwd, "the pwd module is needed for this test")
-    def test_owner(self):
-        p = self.cls(BASE) / 'fileA'
-        uid = p.stat().st_uid
-        try:
-            name = pwd.getpwuid(uid).pw_name
-        except KeyError:
-            self.skipTest(
-                "user %d doesn't have an entry in the system database" % uid)
-        self.assertEqual(name, p.owner())
-
-    @unittest.skipUnless(grp, "the grp module is needed for this test")
-    def test_group(self):
-        p = self.cls(BASE) / 'fileA'
-        gid = p.stat().st_gid
-        try:
-            name = grp.getgrgid(gid).gr_name
-        except KeyError:
-            self.skipTest(
-                "group %d doesn't have an entry in the system database" % gid)
-        self.assertEqual(name, p.group())
-
-    def test_unlink(self):
-        p = self.cls(BASE) / 'fileA'
-        p.unlink()
-        self.assertFileNotFound(p.stat)
-        self.assertFileNotFound(p.unlink)
-
-    def test_unlink_missing_ok(self):
-        p = self.cls(BASE) / 'fileAAA'
-        self.assertFileNotFound(p.unlink)
-        p.unlink(missing_ok=True)
-
-    def test_rmdir(self):
-        p = self.cls(BASE) / 'dirA'
-        for q in p.iterdir():
-            q.unlink()
-        p.rmdir()
-        self.assertFileNotFound(p.stat)
-        self.assertFileNotFound(p.unlink)
-
-    @unittest.skipUnless(hasattr(os, "link"), "os.link() is not present")
-    def test_hardlink_to(self):
+    def test_is_dir(self):
         P = self.cls(BASE)
-        target = P / 'fileA'
-        size = target.stat().st_size
-        # linking to another path.
-        link = P / 'dirA' / 'fileAA'
-        link.hardlink_to(target)
-        self.assertEqual(link.stat().st_size, size)
-        self.assertTrue(os.path.samefile(target, link))
-        self.assertTrue(target.exists())
-        # Linking to a str of a relative path.
-        link2 = P / 'dirA' / 'fileAAA'
-        target2 = rel_join('fileA')
-        link2.hardlink_to(target2)
-        self.assertEqual(os.stat(target2).st_size, size)
-        self.assertTrue(link2.exists())
+        self.assertTrue((P / 'dirA').is_dir())
+        self.assertFalse((P / 'fileA').is_dir())
+        self.assertFalse((P / 'non-existing').is_dir())
+        self.assertFalse((P / 'fileA' / 'bah').is_dir())
+        if os_helper.can_symlink():
+            self.assertFalse((P / 'linkA').is_dir())
+            self.assertTrue((P / 'linkB').is_dir())
+            self.assertFalse((P/ 'brokenLink').is_dir(), False)
+        self.assertIs((P / 'dirA\udfff').is_dir(), False)
+        self.assertIs((P / 'dirA\x00').is_dir(), False)
 
-    @unittest.skipIf(hasattr(os, "link"), "os.link() is present")
-    def test_link_to_not_implemented(self):
+    def test_is_file(self):
         P = self.cls(BASE)
-        p = P / 'fileA'
-        # linking to another path.
-        q = P / 'dirA' / 'fileAA'
-        with self.assertRaises(NotImplementedError):
-            q.hardlink_to(p)
+        self.assertTrue((P / 'fileA').is_file())
+        self.assertFalse((P / 'dirA').is_file())
+        self.assertFalse((P / 'non-existing').is_file())
+        self.assertFalse((P / 'fileA' / 'bah').is_file())
+        if os_helper.can_symlink():
+            self.assertTrue((P / 'linkA').is_file())
+            self.assertFalse((P / 'linkB').is_file())
+            self.assertFalse((P/ 'brokenLink').is_file())
+        self.assertIs((P / 'fileA\udfff').is_file(), False)
+        self.assertIs((P / 'fileA\x00').is_file(), False)
 
-    def test_rename(self):
+    def test_is_mount(self):
         P = self.cls(BASE)
-        p = P / 'fileA'
-        size = p.stat().st_size
-        # Renaming to another path.
-        q = P / 'dirA' / 'fileAA'
-        renamed_p = p.rename(q)
-        self.assertEqual(renamed_p, q)
+        if os.name == 'nt':
+            R = self.cls('c:\\')
+        else:
+            R = self.cls('/')
+        self.assertFalse((P / 'fileA').is_mount())
+        self.assertFalse((P / 'dirA').is_mount())
+        self.assertFalse((P / 'non-existing').is_mount())
+        self.assertFalse((P / 'fileA' / 'bah').is_mount())
+        self.assertTrue(R.is_mount())
+        if os_helper.can_symlink():
+            self.assertFalse((P / 'linkA').is_mount())
+        self.assertIs((R / '\udfff').is_mount(), False)
+
+    def test_is_symlink(self):
+        P = self.cls(BASE)
+        self.assertFalse((P / 'fileA').is_symlink())
+        self.assertFalse((P / 'dirA').is_symlink())
+        self.assertFalse((P / 'non-existing').is_symlink())
+        self.assertFalse((P / 'fileA' / 'bah').is_symlink())
+        if os_helper.can_symlink():
+            self.assertTrue((P / 'linkA').is_symlink())
+            self.assertTrue((P / 'linkB').is_symlink())
+            self.assertTrue((P/ 'brokenLink').is_symlink())
+        self.assertIs((P / 'fileA\udfff').is_file(), False)
+        self.assertIs((P / 'fileA\x00').is_file(), False)
+        if os_helper.can_symlink():
+            self.assertIs((P / 'linkA\udfff').is_file(), False)
+            self.assertIs((P / 'linkA\x00').is_file(), False)
+
+    def test_is_fifo_false(self):
+        P = self.cls(BASE)
+        self.assertFalse((P / 'fileA').is_fifo())
+        self.assertFalse((P / 'dirA').is_fifo())
+        self.assertFalse((P / 'non-existing').is_fifo())
+        self.assertFalse((P / 'fileA' / 'bah').is_fifo())
+        self.assertIs((P / 'fileA\udfff').is_fifo(), False)
+        self.assertIs((P / 'fileA\x00').is_fifo(), False)
+
+    def test_is_socket_false(self):
+        P = self.cls(BASE)
+        self.assertFalse((P / 'fileA').is_socket())
+        self.assertFalse((P / 'dirA').is_socket())
+        self.assertFalse((P / 'non-existing').is_socket())
+        self.assertFalse((P / 'fileA' / 'bah').is_socket())
+        self.assertIs((P / 'fileA\udfff').is_socket(), False)
+        self.assertIs((P / 'fileA\x00').is_socket(), False)
+
+    def test_is_block_device_false(self):
+        P = self.cls(BASE)
+        self.assertFalse((P / 'fileA').is_block_device())
+        self.assertFalse((P / 'dirA').is_block_device())
+        self.assertFalse((P / 'non-existing').is_block_device())
+        self.assertFalse((P / 'fileA' / 'bah').is_block_device())
+        self.assertIs((P / 'fileA\udfff').is_block_device(), False)
+        self.assertIs((P / 'fileA\x00').is_block_device(), False)
+
+    def test_is_char_device_false(self):
+        P = self.cls(BASE)
+        self.assertFalse((P / 'fileA').is_char_device())
+        self.assertFalse((P / 'dirA').is_char_device())
+        self.assertFalse((P / 'non-existing').is_char_device())
+        self.assertFalse((P / 'fileA' / 'bah').is_char_device())
+        self.assertIs((P / 'fileA\udfff').is_char_device(), False)
+        self.assertIs((P / 'fileA\x00').is_char_device(), False)
+
+    def test_pickling_common(self):
+        p = self.cls(BASE, 'fileA')
+        for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
+            dumped = pickle.dumps(p, proto)
+            pp = pickle.loads(dumped)
+            self.assertEqual(pp.stat(), p.stat())
+
+    def test_parts_interning(self):
+        P = self.cls
+        p = P('/usr/bin/foo')
+        q = P('/usr/local/bin')
+        # 'usr'
+        self.assertIs(p.parts[1], q.parts[1])
+        # 'bin'
+        self.assertIs(p.parts[2], q.parts[3])
+
+    def _check_complex_symlinks(self, link0_target):
+        # Test solving a non-looping chain of symlinks (issue #19887).
+        P = self.cls(BASE)
+        self.dirlink(os.path.join('link0', 'link0'), join('link1'))
+        self.dirlink(os.path.join('link1', 'link1'), join('link2'))
+        self.dirlink(os.path.join('link2', 'link2'), join('link3'))
+        self.dirlink(link0_target, join('link0'))
+
+        # Resolve absolute paths.
+        p = (P / 'link0').resolve()
+        self.assertEqual(p, P)
+        self.assertEqualNormCase(str(p), BASE)
+        p = (P / 'link1').resolve()
+        self.assertEqual(p, P)
+        self.assertEqualNormCase(str(p), BASE)
+        p = (P / 'link2').resolve()
+        self.assertEqual(p, P)
+        self.assertEqualNormCase(str(p), BASE)
+        p = (P / 'link3').resolve()
+        self.assertEqual(p, P)
+        self.assertEqualNormCase(str(p), BASE)
+
+        # Resolve relative paths.
+        old_path = os.getcwd()
+        os.chdir(BASE)
+        try:
+            p = self.cls('link0').resolve()
+            self.assertEqual(p, P)
+            self.assertEqualNormCase(str(p), BASE)
+            p = self.cls('link1').resolve()
+            self.assertEqual(p, P)
+            self.assertEqualNormCase(str(p), BASE)
+            p = self.cls('link2').resolve()
+            self.assertEqual(p, P)
+            self.assertEqualNormCase(str(p), BASE)
+            p = self.cls('link3').resolve()
+            self.assertEqual(p, P)
+            self.assertEqualNormCase(str(p), BASE)
+        finally:
+            os.chdir(old_path)
+
+    @os_helper.skip_unless_symlink
+    def test_complex_symlinks_absolute(self):
+        self._check_complex_symlinks(BASE)
+
+    @os_helper.skip_unless_symlink
+    def test_complex_symlinks_relative(self):
+        self._check_complex_symlinks('.')
+
+    @os_helper.skip_unless_symlink
+    def test_complex_symlinks_relative_dot_dot(self):
+        self._check_complex_symlinks(os.path.join('dirA', '..'))
+
+    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)
+        self.assertEqualNormCase(str(p), str(q))
+        self.assertIs(type(p), type(q))
+        self.assertTrue(p.is_absolute())
+
+    def test_cwd(self):
+        p = self.cls.cwd()
+        self._test_cwd(p)
+
+    def test_absolute_common(self):
+        P = self.cls
+
+        with mock.patch("os.getcwd") as getcwd:
+            getcwd.return_value = BASE
+
+            # Simple relative paths.
+            self.assertEqual(str(P().absolute()), BASE)
+            self.assertEqual(str(P('.').absolute()), BASE)
+            self.assertEqual(str(P('a').absolute()), os.path.join(BASE, 'a'))
+            self.assertEqual(str(P('a', 'b', 'c').absolute()), os.path.join(BASE, 'a', 'b', 'c'))
+
+            # Symlinks should not be resolved.
+            self.assertEqual(str(P('linkB', 'fileB').absolute()), os.path.join(BASE, 'linkB', 'fileB'))
+            self.assertEqual(str(P('brokenLink').absolute()), os.path.join(BASE, 'brokenLink'))
+            self.assertEqual(str(P('brokenLinkLoop').absolute()), os.path.join(BASE, 'brokenLinkLoop'))
+
+            # '..' entries should be preserved and not normalised.
+            self.assertEqual(str(P('..').absolute()), os.path.join(BASE, '..'))
+            self.assertEqual(str(P('a', '..').absolute()), os.path.join(BASE, 'a', '..'))
+            self.assertEqual(str(P('..', 'b').absolute()), os.path.join(BASE, '..', 'b'))
+
+    def _test_home(self, p):
+        q = self.cls(os.path.expanduser('~'))
+        self.assertEqual(p, q)
+        self.assertEqualNormCase(str(p), str(q))
+        self.assertIs(type(p), type(q))
+        self.assertTrue(p.is_absolute())
+
+    @unittest.skipIf(
+        pwd is None, reason="Test requires pwd module to get homedir."
+    )
+    def test_home(self):
+        with os_helper.EnvironmentVarGuard() as env:
+            self._test_home(self.cls.home())
+
+            env.clear()
+            env['USERPROFILE'] = os.path.join(BASE, 'userprofile')
+            self._test_home(self.cls.home())
+
+            # bpo-38883: ignore `HOME` when set on windows
+            env['HOME'] = os.path.join(BASE, 'home')
+            self._test_home(self.cls.home())
+
+    @unittest.skipIf(is_wasi, "WASI has no user accounts.")
+    def test_expanduser_common(self):
+        P = self.cls
+        p = P('~')
+        self.assertEqual(p.expanduser(), P(os.path.expanduser('~')))
+        p = P('foo')
+        self.assertEqual(p.expanduser(), p)
+        p = P('/~')
+        self.assertEqual(p.expanduser(), p)
+        p = P('../~')
+        self.assertEqual(p.expanduser(), p)
+        p = P(P('').absolute().anchor) / '~'
+        self.assertEqual(p.expanduser(), p)
+        p = P('~/a:b')
+        self.assertEqual(p.expanduser(), P(os.path.expanduser('~'), './a:b'))
+
+    def test_with_segments(self):
+        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)
+        if not is_wasi:  # WASI has no user accounts.
+            self.assertEqual(42, p.with_segments('~').expanduser().session_id)
+        self.assertEqual(42, (p / 'fileA').rename(p / 'fileB').session_id)
+        self.assertEqual(42, (p / 'fileB').replace(p / 'fileA').session_id)
+        if os_helper.can_symlink():
+            self.assertEqual(42, (p / 'linkA').readlink().session_id)
+        for path in p.iterdir():
+            self.assertEqual(42, path.session_id)
+        for path in p.glob('*'):
+            self.assertEqual(42, path.session_id)
+        for path in p.rglob('*'):
+            self.assertEqual(42, path.session_id)
+        for dirpath, dirnames, filenames in p.walk():
+            self.assertEqual(42, dirpath.session_id)
+
+    def test_resolve_nonexist_relative_issue38671(self):
+        p = self.cls('non', 'exist')
+
+        old_cwd = os.getcwd()
+        os.chdir(BASE)
+        try:
+            self.assertEqual(p.resolve(), self.cls(BASE, p))
+        finally:
+            os.chdir(old_cwd)
+
+    @os_helper.skip_unless_working_chmod
+    def test_chmod(self):
+        p = self.cls(BASE) / 'fileA'
+        mode = p.stat().st_mode
+        # Clear writable bit.
+        new_mode = mode & ~0o222
+        p.chmod(new_mode)
+        self.assertEqual(p.stat().st_mode, new_mode)
+        # Set writable bit.
+        new_mode = mode | 0o222
+        p.chmod(new_mode)
+        self.assertEqual(p.stat().st_mode, new_mode)
+
+    # On Windows, os.chmod does not follow symlinks (issue #15411)
+    @only_posix
+    @os_helper.skip_unless_working_chmod
+    def test_chmod_follow_symlinks_true(self):
+        p = self.cls(BASE) / 'linkA'
+        q = p.resolve()
+        mode = q.stat().st_mode
+        # Clear writable bit.
+        new_mode = mode & ~0o222
+        p.chmod(new_mode, follow_symlinks=True)
+        self.assertEqual(q.stat().st_mode, new_mode)
+        # Set writable bit
+        new_mode = mode | 0o222
+        p.chmod(new_mode, follow_symlinks=True)
+        self.assertEqual(q.stat().st_mode, new_mode)
+
+    # XXX also need a test for lchmod.
+
+    @unittest.skipUnless(pwd, "the pwd module is needed for this test")
+    def test_owner(self):
+        p = self.cls(BASE) / 'fileA'
+        uid = p.stat().st_uid
+        try:
+            name = pwd.getpwuid(uid).pw_name
+        except KeyError:
+            self.skipTest(
+                "user %d doesn't have an entry in the system database" % uid)
+        self.assertEqual(name, p.owner())
+
+    @unittest.skipUnless(grp, "the grp module is needed for this test")
+    def test_group(self):
+        p = self.cls(BASE) / 'fileA'
+        gid = p.stat().st_gid
+        try:
+            name = grp.getgrgid(gid).gr_name
+        except KeyError:
+            self.skipTest(
+                "group %d doesn't have an entry in the system database" % gid)
+        self.assertEqual(name, p.group())
+
+    def test_unlink(self):
+        p = self.cls(BASE) / 'fileA'
+        p.unlink()
+        self.assertFileNotFound(p.stat)
+        self.assertFileNotFound(p.unlink)
+
+    def test_unlink_missing_ok(self):
+        p = self.cls(BASE) / 'fileAAA'
+        self.assertFileNotFound(p.unlink)
+        p.unlink(missing_ok=True)
+
+    def test_rmdir(self):
+        p = self.cls(BASE) / 'dirA'
+        for q in p.iterdir():
+            q.unlink()
+        p.rmdir()
+        self.assertFileNotFound(p.stat)
+        self.assertFileNotFound(p.unlink)
+
+    @unittest.skipUnless(hasattr(os, "link"), "os.link() is not present")
+    def test_hardlink_to(self):
+        P = self.cls(BASE)
+        target = P / 'fileA'
+        size = target.stat().st_size
+        # linking to another path.
+        link = P / 'dirA' / 'fileAA'
+        link.hardlink_to(target)
+        self.assertEqual(link.stat().st_size, size)
+        self.assertTrue(os.path.samefile(target, link))
+        self.assertTrue(target.exists())
+        # Linking to a str of a relative path.
+        link2 = P / 'dirA' / 'fileAAA'
+        target2 = rel_join('fileA')
+        link2.hardlink_to(target2)
+        self.assertEqual(os.stat(target2).st_size, size)
+        self.assertTrue(link2.exists())
+
+    @unittest.skipIf(hasattr(os, "link"), "os.link() is present")
+    def test_link_to_not_implemented(self):
+        P = self.cls(BASE)
+        p = P / 'fileA'
+        # linking to another path.
+        q = P / 'dirA' / 'fileAA'
+        with self.assertRaises(NotImplementedError):
+            q.hardlink_to(p)
+
+    def test_rename(self):
+        P = self.cls(BASE)
+        p = P / 'fileA'
+        size = p.stat().st_size
+        # Renaming to another path.
+        q = P / 'dirA' / 'fileAA'
+        renamed_p = p.rename(q)
+        self.assertEqual(renamed_p, q)
         self.assertEqual(q.stat().st_size, size)
         self.assertFileNotFound(p.stat)
         # Renaming to a str of a relative path.
@@ -2413,16 +2585,6 @@ def test_replace(self):
         self.assertEqual(os.stat(r).st_size, size)
         self.assertFileNotFound(q.stat)
 
-    @os_helper.skip_unless_symlink
-    def test_readlink(self):
-        P = self.cls(BASE)
-        self.assertEqual((P / 'linkA').readlink(), self.cls('fileA'))
-        self.assertEqual((P / 'brokenLink').readlink(),
-                         self.cls('non-existing'))
-        self.assertEqual((P / 'linkB').readlink(), self.cls('dirB'))
-        with self.assertRaises(OSError):
-            (P / 'fileA').readlink()
-
     def test_touch_common(self):
         P = self.cls(BASE)
         p = P / 'newfileA'
@@ -2614,63 +2776,6 @@ def test_symlink_to(self):
         self.assertTrue(link.is_dir())
         self.assertTrue(list(link.iterdir()))
 
-    def test_is_dir(self):
-        P = self.cls(BASE)
-        self.assertTrue((P / 'dirA').is_dir())
-        self.assertFalse((P / 'fileA').is_dir())
-        self.assertFalse((P / 'non-existing').is_dir())
-        self.assertFalse((P / 'fileA' / 'bah').is_dir())
-        if os_helper.can_symlink():
-            self.assertFalse((P / 'linkA').is_dir())
-            self.assertTrue((P / 'linkB').is_dir())
-            self.assertFalse((P/ 'brokenLink').is_dir(), False)
-        self.assertIs((P / 'dirA\udfff').is_dir(), False)
-        self.assertIs((P / 'dirA\x00').is_dir(), False)
-
-    def test_is_file(self):
-        P = self.cls(BASE)
-        self.assertTrue((P / 'fileA').is_file())
-        self.assertFalse((P / 'dirA').is_file())
-        self.assertFalse((P / 'non-existing').is_file())
-        self.assertFalse((P / 'fileA' / 'bah').is_file())
-        if os_helper.can_symlink():
-            self.assertTrue((P / 'linkA').is_file())
-            self.assertFalse((P / 'linkB').is_file())
-            self.assertFalse((P/ 'brokenLink').is_file())
-        self.assertIs((P / 'fileA\udfff').is_file(), False)
-        self.assertIs((P / 'fileA\x00').is_file(), False)
-
-    def test_is_mount(self):
-        P = self.cls(BASE)
-        if os.name == 'nt':
-            R = self.cls('c:\\')
-        else:
-            R = self.cls('/')
-        self.assertFalse((P / 'fileA').is_mount())
-        self.assertFalse((P / 'dirA').is_mount())
-        self.assertFalse((P / 'non-existing').is_mount())
-        self.assertFalse((P / 'fileA' / 'bah').is_mount())
-        self.assertTrue(R.is_mount())
-        if os_helper.can_symlink():
-            self.assertFalse((P / 'linkA').is_mount())
-        self.assertIs((R / '\udfff').is_mount(), False)
-
-    def test_is_symlink(self):
-        P = self.cls(BASE)
-        self.assertFalse((P / 'fileA').is_symlink())
-        self.assertFalse((P / 'dirA').is_symlink())
-        self.assertFalse((P / 'non-existing').is_symlink())
-        self.assertFalse((P / 'fileA' / 'bah').is_symlink())
-        if os_helper.can_symlink():
-            self.assertTrue((P / 'linkA').is_symlink())
-            self.assertTrue((P / 'linkB').is_symlink())
-            self.assertTrue((P/ 'brokenLink').is_symlink())
-        self.assertIs((P / 'fileA\udfff').is_file(), False)
-        self.assertIs((P / 'fileA\x00').is_file(), False)
-        if os_helper.can_symlink():
-            self.assertIs((P / 'linkA\udfff').is_file(), False)
-            self.assertIs((P / 'linkA\x00').is_file(), False)
-
     def test_is_junction(self):
         P = self.cls(BASE)
 
@@ -2678,15 +2783,6 @@ def test_is_junction(self):
             self.assertEqual(P.is_junction(), P._flavour.isjunction.return_value)
             P._flavour.isjunction.assert_called_once_with(P)
 
-    def test_is_fifo_false(self):
-        P = self.cls(BASE)
-        self.assertFalse((P / 'fileA').is_fifo())
-        self.assertFalse((P / 'dirA').is_fifo())
-        self.assertFalse((P / 'non-existing').is_fifo())
-        self.assertFalse((P / 'fileA' / 'bah').is_fifo())
-        self.assertIs((P / 'fileA\udfff').is_fifo(), False)
-        self.assertIs((P / 'fileA\x00').is_fifo(), False)
-
     @unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required")
     @unittest.skipIf(sys.platform == "vxworks",
                     "fifo requires special path on VxWorks")
@@ -2702,15 +2798,6 @@ def test_is_fifo_true(self):
         self.assertIs(self.cls(BASE, 'myfifo\udfff').is_fifo(), False)
         self.assertIs(self.cls(BASE, 'myfifo\x00').is_fifo(), False)
 
-    def test_is_socket_false(self):
-        P = self.cls(BASE)
-        self.assertFalse((P / 'fileA').is_socket())
-        self.assertFalse((P / 'dirA').is_socket())
-        self.assertFalse((P / 'non-existing').is_socket())
-        self.assertFalse((P / 'fileA' / 'bah').is_socket())
-        self.assertIs((P / 'fileA\udfff').is_socket(), False)
-        self.assertIs((P / 'fileA\x00').is_socket(), False)
-
     @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
     @unittest.skipIf(
         is_emscripten, "Unix sockets are not implemented on Emscripten."
@@ -2734,24 +2821,6 @@ def test_is_socket_true(self):
         self.assertIs(self.cls(BASE, 'mysock\udfff').is_socket(), False)
         self.assertIs(self.cls(BASE, 'mysock\x00').is_socket(), False)
 
-    def test_is_block_device_false(self):
-        P = self.cls(BASE)
-        self.assertFalse((P / 'fileA').is_block_device())
-        self.assertFalse((P / 'dirA').is_block_device())
-        self.assertFalse((P / 'non-existing').is_block_device())
-        self.assertFalse((P / 'fileA' / 'bah').is_block_device())
-        self.assertIs((P / 'fileA\udfff').is_block_device(), False)
-        self.assertIs((P / 'fileA\x00').is_block_device(), False)
-
-    def test_is_char_device_false(self):
-        P = self.cls(BASE)
-        self.assertFalse((P / 'fileA').is_char_device())
-        self.assertFalse((P / 'dirA').is_char_device())
-        self.assertFalse((P / 'non-existing').is_char_device())
-        self.assertFalse((P / 'fileA' / 'bah').is_char_device())
-        self.assertIs((P / 'fileA\udfff').is_char_device(), False)
-        self.assertIs((P / 'fileA\x00').is_char_device(), False)
-
     def test_is_char_device_true(self):
         # Under Unix, /dev/null should generally be a char device.
         P = self.cls('/dev/null')
@@ -2763,75 +2832,6 @@ def test_is_char_device_true(self):
         self.assertIs(self.cls('/dev/null\udfff').is_char_device(), False)
         self.assertIs(self.cls('/dev/null\x00').is_char_device(), False)
 
-    def test_pickling_common(self):
-        p = self.cls(BASE, 'fileA')
-        for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
-            dumped = pickle.dumps(p, proto)
-            pp = pickle.loads(dumped)
-            self.assertEqual(pp.stat(), p.stat())
-
-    def test_parts_interning(self):
-        P = self.cls
-        p = P('/usr/bin/foo')
-        q = P('/usr/local/bin')
-        # 'usr'
-        self.assertIs(p.parts[1], q.parts[1])
-        # 'bin'
-        self.assertIs(p.parts[2], q.parts[3])
-
-    def _check_complex_symlinks(self, link0_target):
-        # Test solving a non-looping chain of symlinks (issue #19887).
-        P = self.cls(BASE)
-        self.dirlink(os.path.join('link0', 'link0'), join('link1'))
-        self.dirlink(os.path.join('link1', 'link1'), join('link2'))
-        self.dirlink(os.path.join('link2', 'link2'), join('link3'))
-        self.dirlink(link0_target, join('link0'))
-
-        # Resolve absolute paths.
-        p = (P / 'link0').resolve()
-        self.assertEqual(p, P)
-        self.assertEqualNormCase(str(p), BASE)
-        p = (P / 'link1').resolve()
-        self.assertEqual(p, P)
-        self.assertEqualNormCase(str(p), BASE)
-        p = (P / 'link2').resolve()
-        self.assertEqual(p, P)
-        self.assertEqualNormCase(str(p), BASE)
-        p = (P / 'link3').resolve()
-        self.assertEqual(p, P)
-        self.assertEqualNormCase(str(p), BASE)
-
-        # Resolve relative paths.
-        old_path = os.getcwd()
-        os.chdir(BASE)
-        try:
-            p = self.cls('link0').resolve()
-            self.assertEqual(p, P)
-            self.assertEqualNormCase(str(p), BASE)
-            p = self.cls('link1').resolve()
-            self.assertEqual(p, P)
-            self.assertEqualNormCase(str(p), BASE)
-            p = self.cls('link2').resolve()
-            self.assertEqual(p, P)
-            self.assertEqualNormCase(str(p), BASE)
-            p = self.cls('link3').resolve()
-            self.assertEqual(p, P)
-            self.assertEqualNormCase(str(p), BASE)
-        finally:
-            os.chdir(old_path)
-
-    @os_helper.skip_unless_symlink
-    def test_complex_symlinks_absolute(self):
-        self._check_complex_symlinks(BASE)
-
-    @os_helper.skip_unless_symlink
-    def test_complex_symlinks_relative(self):
-        self._check_complex_symlinks('.')
-
-    @os_helper.skip_unless_symlink
-    def test_complex_symlinks_relative_dot_dot(self):
-        self._check_complex_symlinks(os.path.join('dirA', '..'))
-
     def test_passing_kwargs_deprecated(self):
         with self.assertWarns(DeprecationWarning):
             self.cls(foo="bar")



More information about the Python-checkins mailing list