Skip to content

GH-113568: Stop raising auditing events from pathlib ABCs #113571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion Lib/pathlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import ntpath
import os
import posixpath
import sys
import warnings

try:
import pwd
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -303,6 +304,46 @@ def _make_child_entry(self, entry):
# Transform an entry yielded from _scandir() into a path object.
return self._make_child_relpath(entry.name)

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.
Expand Down
29 changes: 8 additions & 21 deletions Lib/pathlib/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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().
Expand Down Expand Up @@ -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:
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_pathlib/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
13 changes: 0 additions & 13 deletions Lib/test/test_pathlib/test_pathlib_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Raise audit events from :class:`pathlib.Path` and not its private base class
``PathBase``.