mirror of
https://github.com/python/cpython.git
synced 2025-11-03 11:23:31 +00:00
GH-105793: Add follow_symlinks argument to pathlib.Path.is_dir() and is_file() (GH-105794)
Brings `pathlib.Path.is_dir()` and `in line with `os.DirEntry.is_dir()`, which will be important for implementing generic path walking and globbing. Likewise `is_file()`.
This commit is contained in:
parent
5d4dbf0e30
commit
219effa876
5 changed files with 59 additions and 18 deletions
|
|
@ -978,23 +978,35 @@ call fails (for example because the path doesn't exist).
|
||||||
available. In previous versions, :exc:`NotImplementedError` was raised.
|
available. In previous versions, :exc:`NotImplementedError` was raised.
|
||||||
|
|
||||||
|
|
||||||
.. method:: Path.is_dir()
|
.. method:: Path.is_dir(*, follow_symlinks=True)
|
||||||
|
|
||||||
Return ``True`` if the path points to a directory (or a symbolic link
|
Return ``True`` if the path points to a directory, ``False`` if it points
|
||||||
pointing to a directory), ``False`` if it points to another kind of file.
|
to another kind of file.
|
||||||
|
|
||||||
``False`` is also returned if the path doesn't exist or is a broken symlink;
|
``False`` is also returned if the path doesn't exist or is a broken symlink;
|
||||||
other errors (such as permission errors) are propagated.
|
other errors (such as permission errors) are propagated.
|
||||||
|
|
||||||
|
This method normally follows symlinks; to exclude symlinks to directories,
|
||||||
|
add the argument ``follow_symlinks=False``.
|
||||||
|
|
||||||
.. method:: Path.is_file()
|
.. versionchanged:: 3.13
|
||||||
|
The *follow_symlinks* parameter was added.
|
||||||
|
|
||||||
Return ``True`` if the path points to a regular file (or a symbolic link
|
|
||||||
pointing to a regular file), ``False`` if it points to another kind of file.
|
.. method:: Path.is_file(*, follow_symlinks=True)
|
||||||
|
|
||||||
|
Return ``True`` if the path points to a regular file, ``False`` if it
|
||||||
|
points to another kind of file.
|
||||||
|
|
||||||
``False`` is also returned if the path doesn't exist or is a broken symlink;
|
``False`` is also returned if the path doesn't exist or is a broken symlink;
|
||||||
other errors (such as permission errors) are propagated.
|
other errors (such as permission errors) are propagated.
|
||||||
|
|
||||||
|
This method normally follows symlinks; to exclude symlinks, add the
|
||||||
|
argument ``follow_symlinks=False``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.13
|
||||||
|
The *follow_symlinks* parameter was added.
|
||||||
|
|
||||||
|
|
||||||
.. method:: Path.is_junction()
|
.. method:: Path.is_junction()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,9 +113,10 @@ pathlib
|
||||||
* Add support for recursive wildcards in :meth:`pathlib.PurePath.match`.
|
* Add support for recursive wildcards in :meth:`pathlib.PurePath.match`.
|
||||||
(Contributed by Barney Gale in :gh:`73435`.)
|
(Contributed by Barney Gale in :gh:`73435`.)
|
||||||
|
|
||||||
* Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.glob` and
|
* Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.glob`,
|
||||||
:meth:`~pathlib.Path.rglob`.
|
:meth:`~pathlib.Path.rglob`, :meth:`~pathlib.Path.is_file`, and
|
||||||
(Contributed by Barney Gale in :gh:`77609`.)
|
:meth:`~pathlib.Path.is_dir`.
|
||||||
|
(Contributed by Barney Gale in :gh:`77609` and :gh:`105793`.)
|
||||||
|
|
||||||
traceback
|
traceback
|
||||||
---------
|
---------
|
||||||
|
|
|
||||||
|
|
@ -817,12 +817,12 @@ class Path(PurePath):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def is_dir(self):
|
def is_dir(self, *, follow_symlinks=True):
|
||||||
"""
|
"""
|
||||||
Whether this path is a directory.
|
Whether this path is a directory.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return S_ISDIR(self.stat().st_mode)
|
return S_ISDIR(self.stat(follow_symlinks=follow_symlinks).st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if not _ignore_error(e):
|
if not _ignore_error(e):
|
||||||
raise
|
raise
|
||||||
|
|
@ -833,13 +833,13 @@ class Path(PurePath):
|
||||||
# Non-encodable path
|
# Non-encodable path
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_file(self):
|
def is_file(self, *, follow_symlinks=True):
|
||||||
"""
|
"""
|
||||||
Whether this path is a regular file (also True for symlinks pointing
|
Whether this path is a regular file (also True for symlinks pointing
|
||||||
to regular files).
|
to regular files).
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return S_ISREG(self.stat().st_mode)
|
return S_ISREG(self.stat(follow_symlinks=follow_symlinks).st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if not _ignore_error(e):
|
if not _ignore_error(e):
|
||||||
raise
|
raise
|
||||||
|
|
|
||||||
|
|
@ -2191,9 +2191,22 @@ class PathTest(unittest.TestCase):
|
||||||
if os_helper.can_symlink():
|
if os_helper.can_symlink():
|
||||||
self.assertFalse((P / 'linkA').is_dir())
|
self.assertFalse((P / 'linkA').is_dir())
|
||||||
self.assertTrue((P / 'linkB').is_dir())
|
self.assertTrue((P / 'linkB').is_dir())
|
||||||
self.assertFalse((P/ 'brokenLink').is_dir(), False)
|
self.assertFalse((P/ 'brokenLink').is_dir())
|
||||||
self.assertIs((P / 'dirA\udfff').is_dir(), False)
|
self.assertFalse((P / 'dirA\udfff').is_dir())
|
||||||
self.assertIs((P / 'dirA\x00').is_dir(), False)
|
self.assertFalse((P / 'dirA\x00').is_dir())
|
||||||
|
|
||||||
|
def test_is_dir_no_follow_symlinks(self):
|
||||||
|
P = self.cls(BASE)
|
||||||
|
self.assertTrue((P / 'dirA').is_dir(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'fileA').is_dir(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'non-existing').is_dir(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'fileA' / 'bah').is_dir(follow_symlinks=False))
|
||||||
|
if os_helper.can_symlink():
|
||||||
|
self.assertFalse((P / 'linkA').is_dir(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'linkB').is_dir(follow_symlinks=False))
|
||||||
|
self.assertFalse((P/ 'brokenLink').is_dir(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'dirA\udfff').is_dir(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'dirA\x00').is_dir(follow_symlinks=False))
|
||||||
|
|
||||||
def test_is_file(self):
|
def test_is_file(self):
|
||||||
P = self.cls(BASE)
|
P = self.cls(BASE)
|
||||||
|
|
@ -2205,8 +2218,21 @@ class PathTest(unittest.TestCase):
|
||||||
self.assertTrue((P / 'linkA').is_file())
|
self.assertTrue((P / 'linkA').is_file())
|
||||||
self.assertFalse((P / 'linkB').is_file())
|
self.assertFalse((P / 'linkB').is_file())
|
||||||
self.assertFalse((P/ 'brokenLink').is_file())
|
self.assertFalse((P/ 'brokenLink').is_file())
|
||||||
self.assertIs((P / 'fileA\udfff').is_file(), False)
|
self.assertFalse((P / 'fileA\udfff').is_file())
|
||||||
self.assertIs((P / 'fileA\x00').is_file(), False)
|
self.assertFalse((P / 'fileA\x00').is_file())
|
||||||
|
|
||||||
|
def test_is_file_no_follow_symlinks(self):
|
||||||
|
P = self.cls(BASE)
|
||||||
|
self.assertTrue((P / 'fileA').is_file(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'dirA').is_file(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'non-existing').is_file(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'fileA' / 'bah').is_file(follow_symlinks=False))
|
||||||
|
if os_helper.can_symlink():
|
||||||
|
self.assertFalse((P / 'linkA').is_file(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'linkB').is_file(follow_symlinks=False))
|
||||||
|
self.assertFalse((P/ 'brokenLink').is_file(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'fileA\udfff').is_file(follow_symlinks=False))
|
||||||
|
self.assertFalse((P / 'fileA\x00').is_file(follow_symlinks=False))
|
||||||
|
|
||||||
def test_is_mount(self):
|
def test_is_mount(self):
|
||||||
P = self.cls(BASE)
|
P = self.cls(BASE)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.is_dir` and
|
||||||
|
:meth:`~pathlib.Path.is_file`, defaulting to ``True``.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue