Add optional argument to os.path and pathlib samefile methods

This commit is contained in:
Ross Rhodes 2021-01-01 17:50:50 +00:00
parent 3bf05327c2
commit d694ea4a9d
8 changed files with 46 additions and 18 deletions

View File

@ -377,7 +377,7 @@ the :mod:`glob` module.)
Accepts a :term:`path-like object`.
.. function:: samefile(path1, path2)
.. function:: samefile(path1, path2, follow_symlinks=True)
Return ``True`` if both pathname arguments refer to the same file or directory.
This is determined by the device number and i-node number and raises an
@ -394,6 +394,9 @@ the :mod:`glob` module.)
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. versionchanged:: 3.10
Supports optional argument ``follow_symlinks``.
.. function:: sameopenfile(fp1, fp2)

View File

@ -1078,7 +1078,7 @@ call fails (for example because the path doesn't exist).
Remove this directory. The directory must be empty.
.. method:: Path.samefile(other_path)
.. method:: Path.samefile(other_path, follow_symlinks=True)
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
@ -1098,6 +1098,9 @@ call fails (for example because the path doesn't exist).
.. versionadded:: 3.5
.. versionchanged:: 3.10
Supports optional argument ``follow_symlinks``.
.. method:: Path.symlink_to(target, target_is_directory=False)

View File

@ -264,6 +264,9 @@ descriptors without copying between kernel address space and user
address space, where one of the file descriptors must refer to a
pipe. (Contributed by Pablo Galindo in :issue:`41625`.)
Added optional ``follow_symlinks`` argument to :func:`os.path.samefile`.
(Contributed by Ross Rhodes in :issue:`42778`.)
pathlib
-------
@ -274,6 +277,9 @@ Added negative indexing support to :attr:`PurePath.parents
<pathlib.PurePath.parents>`.
(Contributed by Yaroslav Pankovych in :issue:`21041`)
Added optional ``follow_symlinks`` argument to :func:`pathlib.samefile`.
(Contributed by Ross Rhodes in :issue:`42778`.)
platform
--------

View File

@ -91,14 +91,14 @@ def samestat(s1, s2):
# Are two filenames really pointing to the same file?
def samefile(f1, f2):
def samefile(f1, f2, follow_symlinks=True):
"""Test whether two pathnames reference the same actual file or directory
This is determined by the device number and i-node number and
raises an exception if an os.stat() call on either pathname fails.
"""
s1 = os.stat(f1)
s2 = os.stat(f2)
s1 = os.stat(f1, follow_symlinks=follow_symlinks)
s2 = os.stat(f2, follow_symlinks=follow_symlinks)
return samestat(s1, s2)

View File

@ -1134,15 +1134,15 @@ class Path(PurePath):
"""
return cls(cls()._flavour.gethomedir(None))
def samefile(self, other_path):
def samefile(self, other_path, follow_symlinks=True):
"""Return whether other_path is the same or not as this file
(as returned by os.path.samefile()).
"""
st = self.stat()
st = self.stat(follow_symlinks=follow_symlinks)
try:
other_st = other_path.stat()
other_st = other_path.stat(follow_symlinks=follow_symlinks)
except AttributeError:
other_st = self._accessor.stat(other_path)
other_st = self._accessor.stat(other_path, follow_symlinks=follow_symlinks)
return os.path.samestat(st, other_st)
def iterdir(self):
@ -1216,12 +1216,12 @@ class Path(PurePath):
obj._init(template=self)
return obj
def stat(self):
def stat(self, follow_symlinks=True):
"""
Return the result of the stat() system call on this path, like
os.stat() does.
"""
return self._accessor.stat(self)
return self._accessor.stat(self, follow_symlinks=follow_symlinks)
def owner(self):
"""

View File

@ -227,7 +227,8 @@ class GenericTest:
self.assertRaises(TypeError, self.pathmodule.samefile)
def _test_samefile_on_link_func(self, func):
@os_helper.skip_unless_symlink
def test_samefile_on_symlink(self):
test_fn1 = os_helper.TESTFN
test_fn2 = os_helper.TESTFN + "2"
self.addCleanup(os_helper.unlink, test_fn1)
@ -235,20 +236,32 @@ class GenericTest:
create_file(test_fn1)
func(test_fn1, test_fn2)
os.symlink(test_fn1, test_fn2)
self.assertTrue(self.pathmodule.samefile(test_fn1, test_fn2))
self.assertFalse(self.pathmodule.samefile(test_fn1, test_fn2, follow_symlinks=False))
os.remove(test_fn2)
create_file(test_fn2)
self.assertFalse(self.pathmodule.samefile(test_fn1, test_fn2))
@os_helper.skip_unless_symlink
def test_samefile_on_symlink(self):
self._test_samefile_on_link_func(os.symlink)
self.assertFalse(self.pathmodule.samefile(test_fn1, test_fn2, follow_symlinks=False))
def test_samefile_on_link(self):
try:
self._test_samefile_on_link_func(os.link)
test_fn1 = os_helper.TESTFN
test_fn2 = os_helper.TESTFN + "2"
self.addCleanup(os_helper.unlink, test_fn1)
self.addCleanup(os_helper.unlink, test_fn2)
create_file(test_fn1)
os.link(test_fn1, test_fn2)
self.assertTrue(self.pathmodule.samefile(test_fn1, test_fn2))
self.assertTrue(self.pathmodule.samefile(test_fn1, test_fn2, follow_symlinks=False))
os.remove(test_fn2)
create_file(test_fn2)
self.assertFalse(self.pathmodule.samefile(test_fn1, test_fn2))
self.assertFalse(self.pathmodule.samefile(test_fn1, test_fn2, follow_symlinks=False))
except PermissionError as e:
self.skipTest('os.link(): %s' % e)

View File

@ -1431,6 +1431,7 @@ Bernhard Reiter
Steven Reiz
Roeland Rengelink
Antoine Reversat
Ross Rhodes
Flávio Ribeiro
Francesco Ricciardi
Tim Rice

View File

@ -0,0 +1,2 @@
Add 'follow_symlinks' optional argument to os.path and pathlib samefile
methods