]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-116380: Move pathlib-specific code from `glob` to `pathlib._abc`. (#120011)
authorBarney Gale <barney.gale@gmail.com>
Fri, 7 Jun 2024 16:59:34 +0000 (17:59 +0100)
committerGitHub <noreply@github.com>
Fri, 7 Jun 2024 16:59:34 +0000 (17:59 +0100)
In `glob._Globber`, move pathlib-specific methods to `pathlib._abc.PathGlobber` and replace them with abstract methods. Rename `glob._Globber` to `glob._GlobberBase`. As a result, the `glob` module is no longer befouled by code that can only ever apply to pathlib.

No change of behaviour.

Lib/glob.py
Lib/pathlib/_abc.py

index fbb1d35aab71faa7396cbdeed0a68c3c3a76f94c..574e5ad51b601dde974b089f3705266e21143ac2 100644 (file)
@@ -328,8 +328,8 @@ def _compile_pattern(pat, sep, case_sensitive, recursive=True):
     return re.compile(regex, flags=flags).match
 
 
-class _Globber:
-    """Class providing shell-style pattern matching and globbing.
+class _GlobberBase:
+    """Abstract class providing shell-style pattern matching and globbing.
     """
 
     def __init__(self, sep, case_sensitive, case_pedantic=False, recursive=False):
@@ -338,29 +338,37 @@ class _Globber:
         self.case_pedantic = case_pedantic
         self.recursive = recursive
 
-    # Low-level methods
+    # Abstract methods
 
-    lexists = operator.methodcaller('exists', follow_symlinks=False)
-    add_slash = operator.methodcaller('joinpath', '')
+    @staticmethod
+    def lexists(path):
+        """Implements os.path.lexists().
+        """
+        raise NotImplementedError
 
     @staticmethod
     def scandir(path):
-        """Emulates os.scandir(), which returns an object that can be used as
-        a context manager. This method is called by walk() and glob().
+        """Implements os.scandir().
+        """
+        raise NotImplementedError
+
+    @staticmethod
+    def add_slash(path):
+        """Returns a path with a trailing slash added.
         """
-        return contextlib.nullcontext(path.iterdir())
+        raise NotImplementedError
 
     @staticmethod
     def concat_path(path, text):
-        """Appends text to the given path.
+        """Implements path concatenation.
         """
-        return path.with_segments(path._raw_path + text)
+        raise NotImplementedError
 
     @staticmethod
     def parse_entry(entry):
         """Returns the path of an entry yielded from scandir().
         """
-        return entry
+        raise NotImplementedError
 
     # High-level methods
 
@@ -520,7 +528,9 @@ class _Globber:
             yield path
 
 
-class _StringGlobber(_Globber):
+class _StringGlobber(_GlobberBase):
+    """Provides shell-style pattern matching and globbing for string paths.
+    """
     lexists = staticmethod(os.path.lexists)
     scandir = staticmethod(os.scandir)
     parse_entry = operator.attrgetter('path')
index 1a74f457c3f5a7b48cc9fac1dcceb16473abfcba..ecea8e88d1a2e3ad34974c861f9065f1bd1d2cdd 100644 (file)
@@ -12,8 +12,9 @@ resemble pathlib's PurePath and Path respectively.
 """
 
 import functools
+import operator
 import posixpath
-from glob import _Globber, _no_recurse_symlinks
+from glob import _GlobberBase, _no_recurse_symlinks
 from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
 
 
@@ -84,6 +85,33 @@ class ParserBase:
         raise UnsupportedOperation(self._unsupported_msg('isabs()'))
 
 
+class PathGlobber(_GlobberBase):
+    """
+    Class providing shell-style globbing for path objects.
+    """
+
+    lexists = operator.methodcaller('exists', follow_symlinks=False)
+    add_slash = operator.methodcaller('joinpath', '')
+
+    @staticmethod
+    def scandir(path):
+        """Emulates os.scandir(), which returns an object that can be used as
+        a context manager. This method is called by walk() and glob().
+        """
+        import contextlib
+        return contextlib.nullcontext(path.iterdir())
+
+    @staticmethod
+    def concat_path(path, text):
+        """Appends text to the given path."""
+        return path.with_segments(path._raw_path + text)
+
+    @staticmethod
+    def parse_entry(entry):
+        """Returns the path of an entry yielded from scandir()."""
+        return entry
+
+
 class PurePathBase:
     """Base class for pure path objects.
 
@@ -104,7 +132,7 @@ class PurePathBase:
         '_resolving',
     )
     parser = ParserBase()
-    _globber = _Globber
+    _globber = PathGlobber
 
     def __init__(self, path, *paths):
         self._raw_path = self.parser.join(path, *paths) if paths else path