diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index ec1dc4f6168..0a2a4e3be0e 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -884,6 +884,25 @@ call fails (for example because the path doesn't exist): Remove this directory. The directory must be empty. +.. method:: Path.samefile(other_path) + + Return whether this path points to the same file as *other_path*, which + can be either a Path object, or a string. The semantics are similar + to :func:`os.path.samefile` and :func:`os.path.samestat`. + + An :exc:`OSError` can be raised if either file cannot be accessed for some + reason. + + >>> p = Path('spam') + >>> q = Path('eggs') + >>> p.samefile(q) + False + >>> p.samefile('spam') + True + + .. versionadded:: 3.5 + + .. method:: Path.symlink_to(target, target_is_directory=False) Make this path a symbolic link to *target*. Under Windows, diff --git a/Lib/pathlib.py b/Lib/pathlib.py index d3d1af8dece..03c5e6e47e5 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -961,6 +961,17 @@ class Path(PurePath): """ return cls(os.getcwd()) + def samefile(self, other_path): + """Return whether `other_file` is the same or not as this file. + (as returned by os.path.samefile(file, other_file)). + """ + st = self.stat() + try: + other_st = other_path.stat() + except AttributeError: + other_st = os.stat(other_path) + return os.path.samestat(st, other_st) + def iterdir(self): """Iterate over the files in this directory. Does not yield any result for the special paths '.' and '..'. diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 6378d8c7f9f..fd9cf232a1d 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1251,6 +1251,26 @@ class _BasePathTest(object): p = self.cls.cwd() self._test_cwd(p) + def test_samefile(self): + fileA_path = os.path.join(BASE, 'fileA') + fileB_path = os.path.join(BASE, 'dirB', 'fileB') + p = self.cls(fileA_path) + pp = self.cls(fileA_path) + q = self.cls(fileB_path) + self.assertTrue(p.samefile(fileA_path)) + self.assertTrue(p.samefile(pp)) + self.assertFalse(p.samefile(fileB_path)) + self.assertFalse(p.samefile(q)) + # Test the non-existent file case + non_existent = os.path.join(BASE, 'foo') + r = self.cls(non_existent) + self.assertRaises(FileNotFoundError, p.samefile, r) + self.assertRaises(FileNotFoundError, p.samefile, non_existent) + self.assertRaises(FileNotFoundError, r.samefile, p) + self.assertRaises(FileNotFoundError, r.samefile, non_existent) + self.assertRaises(FileNotFoundError, r.samefile, r) + self.assertRaises(FileNotFoundError, r.samefile, non_existent) + def test_empty_path(self): # The empty path points to '.' p = self.cls('') diff --git a/Misc/NEWS b/Misc/NEWS index 6c128affb21..e73f0a725d2 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,6 +84,9 @@ Core and Builtins Library ------- +- Issue #19775: Add a samefile() method to pathlib Path objects. Initial + patch by Vajrasky Kok. + - Issue #21398: Fix an unicode error in the pydoc pager when the documentation contains characters not encodable to the stdout encoding.