mirror of
https://github.com/python/cpython.git
synced 2025-08-02 16:13:13 +00:00
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.
This commit is contained in:
parent
99854ce170
commit
3c4e972d6d
5 changed files with 64 additions and 35 deletions
|
@ -9,6 +9,8 @@ import io
|
||||||
import ntpath
|
import ntpath
|
||||||
import os
|
import os
|
||||||
import posixpath
|
import posixpath
|
||||||
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pwd
|
import pwd
|
||||||
|
@ -230,7 +232,6 @@ class Path(_abc.PathBase, PurePath):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if kwargs:
|
if kwargs:
|
||||||
import warnings
|
|
||||||
msg = ("support for supplying keyword arguments to pathlib.PurePath "
|
msg = ("support for supplying keyword arguments to pathlib.PurePath "
|
||||||
"is deprecated and scheduled for removal in Python {remove}")
|
"is deprecated and scheduled for removal in Python {remove}")
|
||||||
warnings._deprecated("pathlib.PurePath(**kwargs)", msg, remove=(3, 14))
|
warnings._deprecated("pathlib.PurePath(**kwargs)", msg, remove=(3, 14))
|
||||||
|
@ -309,6 +310,46 @@ class Path(_abc.PathBase, PurePath):
|
||||||
path._tail_cached = self._tail + [entry.name]
|
path._tail_cached = self._tail + [entry.name]
|
||||||
return path
|
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):
|
def absolute(self):
|
||||||
"""Return an absolute version of this path
|
"""Return an absolute version of this path
|
||||||
No normalization or symlink resolution is performed.
|
No normalization or symlink resolution is performed.
|
||||||
|
|
|
@ -811,18 +811,6 @@ class PathBase(PurePathBase):
|
||||||
"""Iterate over this subtree and yield all existing files (of any
|
"""Iterate over this subtree and yield all existing files (of any
|
||||||
kind, including directories) matching the given relative pattern.
|
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)
|
path_pattern = self.with_segments(pattern)
|
||||||
if path_pattern.drive or path_pattern.root:
|
if path_pattern.drive or path_pattern.root:
|
||||||
raise NotImplementedError("Non-relative patterns are unsupported")
|
raise NotImplementedError("Non-relative patterns are unsupported")
|
||||||
|
@ -833,14 +821,6 @@ class PathBase(PurePathBase):
|
||||||
if pattern[-1] in (self.pathmod.sep, self.pathmod.altsep):
|
if pattern[-1] in (self.pathmod.sep, self.pathmod.altsep):
|
||||||
# GH-65238: pathlib doesn't preserve trailing slash. Add it back.
|
# GH-65238: pathlib doesn't preserve trailing slash. Add it back.
|
||||||
pattern_parts.append('')
|
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:
|
if case_sensitive is None:
|
||||||
# TODO: evaluate case-sensitivity of each directory in _select_children().
|
# TODO: evaluate case-sensitivity of each directory in _select_children().
|
||||||
|
@ -895,9 +875,16 @@ class PathBase(PurePathBase):
|
||||||
paths = _select_children(paths, dir_only, follow_symlinks, match)
|
paths = _select_children(paths, dir_only, follow_symlinks, match)
|
||||||
return paths
|
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):
|
def walk(self, top_down=True, on_error=None, follow_symlinks=False):
|
||||||
"""Walk the directory tree from this directory, similar to os.walk()."""
|
"""Walk the directory tree from this directory, similar to os.walk()."""
|
||||||
sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks)
|
|
||||||
paths = [self]
|
paths = [self]
|
||||||
|
|
||||||
while paths:
|
while paths:
|
||||||
|
|
|
@ -1703,6 +1703,18 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
|
||||||
with set_recursion_limit(recursion_limit):
|
with set_recursion_limit(recursion_limit):
|
||||||
list(base.glob('**/'))
|
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
|
@only_posix
|
||||||
class PosixPathTest(PathTest, PurePosixPathTest):
|
class PosixPathTest(PathTest, PurePosixPathTest):
|
||||||
|
|
|
@ -1266,19 +1266,6 @@ class DummyPathTest(DummyPurePathTest):
|
||||||
bad_link.symlink_to("bad" * 200)
|
bad_link.symlink_to("bad" * 200)
|
||||||
self.assertEqual(sorted(base.glob('**/*')), [bad_link])
|
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):
|
def test_readlink(self):
|
||||||
if not self.can_symlink:
|
if not self.can_symlink:
|
||||||
self.skipTest("symlinks required")
|
self.skipTest("symlinks required")
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Raise audit events from :class:`pathlib.Path` and not its private base class
|
||||||
|
``PathBase``.
|
Loading…
Add table
Add a link
Reference in a new issue