https://github.com/python/cpython/commit/3c4e972d6d0945a5401377bed25b307a88b19c75
commit: 3c4e972d6d0945a5401377bed25b307a88b19c75
branch: main
author: Barney Gale <[email protected]>
committer: barneygale <[email protected]>
date: 2024-01-05T21:41:19Z
summary:
GH-113568: Stop raising auditing events from pathlib ABCs (#113571)
Raise auditing events in `pathlib.Path.glob()`, `rglob()` and `walk()`,
but not in `pathlib._abc.PathBase` methods. Also move generation of a
deprecation warning into `pathlib.Path` so it gets the right stack level.
files:
A Misc/NEWS.d/next/Library/2023-12-29-17-30-49.gh-issue-113568.UpWNAI.rst
M Lib/pathlib/__init__.py
M Lib/pathlib/_abc.py
M Lib/test/test_pathlib/test_pathlib.py
M Lib/test/test_pathlib/test_pathlib_abc.py
diff --git a/Lib/pathlib/__init__.py b/Lib/pathlib/__init__.py
index 79b8b4917f6cc4..6a94886040f95d 100644
--- a/Lib/pathlib/__init__.py
+++ b/Lib/pathlib/__init__.py
@@ -9,6 +9,8 @@
import ntpath
import os
import posixpath
+import sys
+import warnings
try:
import pwd
@@ -230,7 +232,6 @@ def _unsupported(cls, method_name):
def __init__(self, *args, **kwargs):
if kwargs:
- import warnings
msg = ("support for supplying keyword arguments to
pathlib.PurePath "
"is deprecated and scheduled for removal in Python
{remove}")
warnings._deprecated("pathlib.PurePath(**kwargs)", msg, remove=(3,
14))
@@ -309,6 +310,46 @@ def _make_child_entry(self, entry):
path._tail_cached = self._tail + [entry.name]
return path
+ def glob(self, pattern, *, case_sensitive=None, follow_symlinks=None):
+ """Iterate over this subtree and yield all existing files (of any
+ kind, including directories) matching the given relative pattern.
+ """
+ sys.audit("pathlib.Path.glob", self, pattern)
+ if pattern.endswith('**'):
+ # GH-70303: '**' only matches directories. Add trailing slash.
+ warnings.warn(
+ "Pattern ending '**' will match files and directories in a "
+ "future Python release. Add a trailing slash to match only "
+ "directories and remove this warning.",
+ FutureWarning, 2)
+ pattern = f'{pattern}/'
+ return _abc.PathBase.glob(
+ self, pattern, case_sensitive=case_sensitive,
follow_symlinks=follow_symlinks)
+
+ def rglob(self, pattern, *, case_sensitive=None, follow_symlinks=None):
+ """Recursively yield all existing files (of any kind, including
+ directories) matching the given relative pattern, anywhere in
+ this subtree.
+ """
+ sys.audit("pathlib.Path.rglob", self, pattern)
+ if pattern.endswith('**'):
+ # GH-70303: '**' only matches directories. Add trailing slash.
+ warnings.warn(
+ "Pattern ending '**' will match files and directories in a "
+ "future Python release. Add a trailing slash to match only "
+ "directories and remove this warning.",
+ FutureWarning, 2)
+ pattern = f'{pattern}/'
+ pattern = f'**/{pattern}'
+ return _abc.PathBase.glob(
+ self, pattern, case_sensitive=case_sensitive,
follow_symlinks=follow_symlinks)
+
+ def walk(self, top_down=True, on_error=None, follow_symlinks=False):
+ """Walk the directory tree from this directory, similar to
os.walk()."""
+ sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks)
+ return _abc.PathBase.walk(
+ self, top_down=top_down, on_error=on_error,
follow_symlinks=follow_symlinks)
+
def absolute(self):
"""Return an absolute version of this path
No normalization or symlink resolution is performed.
diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py
index f75b20a1d5f1e5..da8d67f624107a 100644
--- a/Lib/pathlib/_abc.py
+++ b/Lib/pathlib/_abc.py
@@ -811,18 +811,6 @@ def glob(self, pattern, *, case_sensitive=None,
follow_symlinks=None):
"""Iterate over this subtree and yield all existing files (of any
kind, including directories) matching the given relative pattern.
"""
- sys.audit("pathlib.Path.glob", self, pattern)
- return self._glob(pattern, case_sensitive, follow_symlinks)
-
- def rglob(self, pattern, *, case_sensitive=None, follow_symlinks=None):
- """Recursively yield all existing files (of any kind, including
- directories) matching the given relative pattern, anywhere in
- this subtree.
- """
- sys.audit("pathlib.Path.rglob", self, pattern)
- return self._glob(f'**/{pattern}', case_sensitive, follow_symlinks)
-
- def _glob(self, pattern, case_sensitive, follow_symlinks):
path_pattern = self.with_segments(pattern)
if path_pattern.drive or path_pattern.root:
raise NotImplementedError("Non-relative patterns are unsupported")
@@ -833,14 +821,6 @@ def _glob(self, pattern, case_sensitive, follow_symlinks):
if pattern[-1] in (self.pathmod.sep, self.pathmod.altsep):
# GH-65238: pathlib doesn't preserve trailing slash. Add it back.
pattern_parts.append('')
- if pattern_parts[-1] == '**':
- # GH-70303: '**' only matches directories. Add trailing slash.
- warnings.warn(
- "Pattern ending '**' will match files and directories in a "
- "future Python release. Add a trailing slash to match only "
- "directories and remove this warning.",
- FutureWarning, 3)
- pattern_parts.append('')
if case_sensitive is None:
# TODO: evaluate case-sensitivity of each directory in
_select_children().
@@ -895,9 +875,16 @@ def _glob(self, pattern, case_sensitive, follow_symlinks):
paths = _select_children(paths, dir_only, follow_symlinks,
match)
return paths
+ def rglob(self, pattern, *, case_sensitive=None, follow_symlinks=None):
+ """Recursively yield all existing files (of any kind, including
+ directories) matching the given relative pattern, anywhere in
+ this subtree.
+ """
+ return self.glob(
+ f'**/{pattern}', case_sensitive=case_sensitive,
follow_symlinks=follow_symlinks)
+
def walk(self, top_down=True, on_error=None, follow_symlinks=False):
"""Walk the directory tree from this directory, similar to
os.walk()."""
- sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks)
paths = [self]
while paths:
diff --git a/Lib/test/test_pathlib/test_pathlib.py
b/Lib/test/test_pathlib/test_pathlib.py
index 8f95c804f80e69..b64e6b59da5d9a 100644
--- a/Lib/test/test_pathlib/test_pathlib.py
+++ b/Lib/test/test_pathlib/test_pathlib.py
@@ -1703,6 +1703,18 @@ def test_glob_above_recursion_limit(self):
with set_recursion_limit(recursion_limit):
list(base.glob('**/'))
+ def test_glob_recursive_no_trailing_slash(self):
+ P = self.cls
+ p = P(self.base)
+ with self.assertWarns(FutureWarning):
+ p.glob('**')
+ with self.assertWarns(FutureWarning):
+ p.glob('*/**')
+ with self.assertWarns(FutureWarning):
+ p.rglob('**')
+ with self.assertWarns(FutureWarning):
+ p.rglob('*/**')
+
@only_posix
class PosixPathTest(PathTest, PurePosixPathTest):
diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py
b/Lib/test/test_pathlib/test_pathlib_abc.py
index e4a4e81e547cd1..a67235b4da3dd3 100644
--- a/Lib/test/test_pathlib/test_pathlib_abc.py
+++ b/Lib/test/test_pathlib/test_pathlib_abc.py
@@ -1266,19 +1266,6 @@ def test_glob_long_symlink(self):
bad_link.symlink_to("bad" * 200)
self.assertEqual(sorted(base.glob('**/*')), [bad_link])
- def test_glob_recursive_no_trailing_slash(self):
- P = self.cls
- p = P(self.base)
- with self.assertWarns(FutureWarning):
- p.glob('**')
- with self.assertWarns(FutureWarning):
- p.glob('*/**')
- with self.assertWarns(FutureWarning):
- p.rglob('**')
- with self.assertWarns(FutureWarning):
- p.rglob('*/**')
-
-
def test_readlink(self):
if not self.can_symlink:
self.skipTest("symlinks required")
diff --git
a/Misc/NEWS.d/next/Library/2023-12-29-17-30-49.gh-issue-113568.UpWNAI.rst
b/Misc/NEWS.d/next/Library/2023-12-29-17-30-49.gh-issue-113568.UpWNAI.rst
new file mode 100644
index 00000000000000..aaca5250184122
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-12-29-17-30-49.gh-issue-113568.UpWNAI.rst
@@ -0,0 +1,2 @@
+Raise audit events from :class:`pathlib.Path` and not its private base class
+``PathBase``.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]