Skip to content

Commit 242c749

Browse files
authored
GH-116380: Move pathlib-specific code from glob to pathlib._abc. (#120011)
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.
1 parent 90b7540 commit 242c749

File tree

2 files changed

+52
-14
lines changed

2 files changed

+52
-14
lines changed

Lib/glob.py

+22-12
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ def _compile_pattern(pat, sep, case_sensitive, recursive=True):
328328
return re.compile(regex, flags=flags).match
329329

330330

331-
class _Globber:
332-
"""Class providing shell-style pattern matching and globbing.
331+
class _GlobberBase:
332+
"""Abstract class providing shell-style pattern matching and globbing.
333333
"""
334334

335335
def __init__(self, sep, case_sensitive, case_pedantic=False, recursive=False):
@@ -338,29 +338,37 @@ def __init__(self, sep, case_sensitive, case_pedantic=False, recursive=False):
338338
self.case_pedantic = case_pedantic
339339
self.recursive = recursive
340340

341-
# Low-level methods
341+
# Abstract methods
342342

343-
lexists = operator.methodcaller('exists', follow_symlinks=False)
344-
add_slash = operator.methodcaller('joinpath', '')
343+
@staticmethod
344+
def lexists(path):
345+
"""Implements os.path.lexists().
346+
"""
347+
raise NotImplementedError
345348

346349
@staticmethod
347350
def scandir(path):
348-
"""Emulates os.scandir(), which returns an object that can be used as
349-
a context manager. This method is called by walk() and glob().
351+
"""Implements os.scandir().
352+
"""
353+
raise NotImplementedError
354+
355+
@staticmethod
356+
def add_slash(path):
357+
"""Returns a path with a trailing slash added.
350358
"""
351-
return contextlib.nullcontext(path.iterdir())
359+
raise NotImplementedError
352360

353361
@staticmethod
354362
def concat_path(path, text):
355-
"""Appends text to the given path.
363+
"""Implements path concatenation.
356364
"""
357-
return path.with_segments(path._raw_path + text)
365+
raise NotImplementedError
358366

359367
@staticmethod
360368
def parse_entry(entry):
361369
"""Returns the path of an entry yielded from scandir().
362370
"""
363-
return entry
371+
raise NotImplementedError
364372

365373
# High-level methods
366374

@@ -520,7 +528,9 @@ def select_exists(self, path, exists=False):
520528
yield path
521529

522530

523-
class _StringGlobber(_Globber):
531+
class _StringGlobber(_GlobberBase):
532+
"""Provides shell-style pattern matching and globbing for string paths.
533+
"""
524534
lexists = staticmethod(os.path.lexists)
525535
scandir = staticmethod(os.scandir)
526536
parse_entry = operator.attrgetter('path')

Lib/pathlib/_abc.py

+30-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
"""
1313

1414
import functools
15+
import operator
1516
import posixpath
16-
from glob import _Globber, _no_recurse_symlinks
17+
from glob import _GlobberBase, _no_recurse_symlinks
1718
from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
1819

1920

@@ -84,6 +85,33 @@ def isabs(self, path):
8485
raise UnsupportedOperation(self._unsupported_msg('isabs()'))
8586

8687

88+
class PathGlobber(_GlobberBase):
89+
"""
90+
Class providing shell-style globbing for path objects.
91+
"""
92+
93+
lexists = operator.methodcaller('exists', follow_symlinks=False)
94+
add_slash = operator.methodcaller('joinpath', '')
95+
96+
@staticmethod
97+
def scandir(path):
98+
"""Emulates os.scandir(), which returns an object that can be used as
99+
a context manager. This method is called by walk() and glob().
100+
"""
101+
import contextlib
102+
return contextlib.nullcontext(path.iterdir())
103+
104+
@staticmethod
105+
def concat_path(path, text):
106+
"""Appends text to the given path."""
107+
return path.with_segments(path._raw_path + text)
108+
109+
@staticmethod
110+
def parse_entry(entry):
111+
"""Returns the path of an entry yielded from scandir()."""
112+
return entry
113+
114+
87115
class PurePathBase:
88116
"""Base class for pure path objects.
89117
@@ -104,7 +132,7 @@ class PurePathBase:
104132
'_resolving',
105133
)
106134
parser = ParserBase()
107-
_globber = _Globber
135+
_globber = PathGlobber
108136

109137
def __init__(self, path, *paths):
110138
self._raw_path = self.parser.join(path, *paths) if paths else path

0 commit comments

Comments
 (0)