Skip to content
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

GH-116380: Move pathlib-specific code from glob to pathlib._abc. #120011

Merged
merged 3 commits into from
Jun 7, 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
34 changes: 22 additions & 12 deletions Lib/glob.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -338,29 +338,37 @@ def __init__(self, sep, case_sensitive, case_pedantic=False, recursive=False):
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

Expand Down Expand Up @@ -520,7 +528,9 @@ def select_exists(self, path, exists=False):
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')
Expand Down
32 changes: 30 additions & 2 deletions Lib/pathlib/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
"""

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


Expand Down Expand Up @@ -84,6 +85,33 @@ def isabs(self, path):
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.

Expand All @@ -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
Expand Down
Loading