From 897fd2278fc01b1cd5b71320f264702e46b73ef4 Mon Sep 17 00:00:00 2001 From: barneygale Date: Mon, 21 Feb 2022 01:43:37 +0000 Subject: [PATCH 1/4] bpo-42777: implement `pathlib.WindowsPath.is_mount()` --- Doc/library/pathlib.rst | 7 ++++++- Lib/pathlib.py | 21 ++----------------- Lib/test/test_pathlib.py | 6 ++++-- .../2022-02-21-01-37-00.bpo-42777.nWK3E6.rst | 1 + 4 files changed, 13 insertions(+), 22 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-02-21-01-37-00.bpo-42777.nWK3E6.rst diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 7ab603fd133b86..a27a2d3bf640e6 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -847,10 +847,15 @@ call fails (for example because the path doesn't exist). function checks whether *path*'s parent, :file:`path/..`, is on a different device than *path*, or whether :file:`path/..` and *path* point to the same i-node on the same device --- this should detect mount points for all Unix - and POSIX variants. Not implemented on Windows. + and POSIX variants. On Windows, a mount point is considered to be a drive + letter root (e.g. ``c:\``), a UNC share (e.g. ``\\server\share``), or a + volume mounted on a filesystem folder. .. versionadded:: 3.7 + .. versionchanged:: 3.11 + Windows support was added. + .. method:: Path.is_symlink() diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 4763ab54f6ba81..22c947646b41b6 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -1269,23 +1269,9 @@ def is_file(self): def is_mount(self): """ - Check if this path is a POSIX mount point + Check if this path is a mount point """ - # Need to exist and be a dir - if not self.exists() or not self.is_dir(): - return False - - try: - parent_dev = self.parent.stat().st_dev - except OSError: - return False - - dev = self.stat().st_dev - if dev != parent_dev: - return True - ino = self.stat().st_ino - parent_ino = self.parent.stat().st_ino - return ino == parent_ino + return self._flavour.pathmod.ismount(self) def is_symlink(self): """ @@ -1393,6 +1379,3 @@ class WindowsPath(Path, PureWindowsPath): On a Windows system, instantiating a Path should return this object. """ __slots__ = () - - def is_mount(self): - raise NotImplementedError("Path.is_mount() is unsupported on this system") diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index f03fcbef1b0a08..2aee5f2db3b05f 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2275,10 +2275,12 @@ def test_is_file(self): self.assertIs((P / 'fileA\udfff').is_file(), False) self.assertIs((P / 'fileA\x00').is_file(), False) - @only_posix def test_is_mount(self): P = self.cls(BASE) - R = self.cls('/') # TODO: Work out Windows. + 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()) diff --git a/Misc/NEWS.d/next/Library/2022-02-21-01-37-00.bpo-42777.nWK3E6.rst b/Misc/NEWS.d/next/Library/2022-02-21-01-37-00.bpo-42777.nWK3E6.rst new file mode 100644 index 00000000000000..24912380fb590a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-02-21-01-37-00.bpo-42777.nWK3E6.rst @@ -0,0 +1 @@ +Implement :meth:`pathlib.Path.is_mount` for Windows paths. From c61c72cb317557fedb667d5311054e286474bb70 Mon Sep 17 00:00:00 2001 From: barneygale Date: Mon, 21 Feb 2022 02:02:59 +0000 Subject: [PATCH 2/4] Fix Windows tests --- Lib/test/test_pathlib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 2aee5f2db3b05f..ca7d65cad19b85 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2288,8 +2288,8 @@ def test_is_mount(self): self.assertTrue(R.is_mount()) if os_helper.can_symlink(): self.assertFalse((P / 'linkA').is_mount()) - self.assertIs(self.cls('/\udfff').is_mount(), False) - self.assertIs(self.cls('/\x00').is_mount(), False) + self.assertIs((R / '\udfff').is_mount(), False) + self.assertIs((R / '\x00').is_mount(), False) def test_is_symlink(self): P = self.cls(BASE) From 97a9b720120b9dc3e2463bb316c7f6647de6dadb Mon Sep 17 00:00:00 2001 From: Barney Gale Date: Sat, 30 Jul 2022 18:15:08 +0100 Subject: [PATCH 3/4] Address feedback, bring up-to-date. --- Doc/library/pathlib.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 60fa3db066f300..f7d7745eef52e7 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -878,11 +878,11 @@ call fails (for example because the path doesn't exist). i-node on the same device --- this should detect mount points for all Unix and POSIX variants. On Windows, a mount point is considered to be a drive letter root (e.g. ``c:\``), a UNC share (e.g. ``\\server\share``), or a - volume mounted on a filesystem folder. + mounted filesystem directory. .. versionadded:: 3.7 - .. versionchanged:: 3.11 + .. versionchanged:: 3.12 Windows support was added. From 8749589c7efc6f0950cdd383b891925f31bf3e7b Mon Sep 17 00:00:00 2001 From: Barney Gale Date: Sun, 31 Jul 2022 01:05:41 +0100 Subject: [PATCH 4/4] Remove test that '/\x00` (posix) and 'c:\\\x00' aren't mounts. These paths are invalid on posix and windows. --- Lib/test/test_pathlib.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index bf2c0c4b8f0ad7..668af8030c0c6a 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2308,7 +2308,6 @@ def test_is_mount(self): if os_helper.can_symlink(): self.assertFalse((P / 'linkA').is_mount()) self.assertIs((R / '\udfff').is_mount(), False) - self.assertIs((R / '\x00').is_mount(), False) def test_is_symlink(self): P = self.cls(BASE)