Skip to content

Instantly share code, notes, and snippets.

@virtuald
Created December 8, 2017 19:27
Show Gist options
  • Save virtuald/dd0373bf3f26ec0730adf1da0fb929bb to your computer and use it in GitHub Desktop.
Save virtuald/dd0373bf3f26ec0730adf1da0fb929bb to your computer and use it in GitHub Desktop.
monkeypatch 'globmatch' function onto pathlib2
#
# monkeypatch to add 'globmatch' function to PurePath, which implements
# the same style of matching that glob supports (which is different
# from what match supports)
#
# Same license as pathlib2 (MIT license)
#
from __future__ import print_function
from pathlib2 import PurePath,PurePosixPath
# Private imports for patching
from pathlib2 import (
_make_selector,
_PreciseSelector,
_RecursiveWildcardSelector,
_TerminatingSelector,
_WildcardSelector
)
def _PreciseSelector_globmatch(self, parts, idx):
if parts[idx] != self.name:
return False
return self.successor.globmatch(parts, idx + 1)
def _RecursiveWildcardSelector_globmatch(self, parts, idx):
successor_globmatch = self.successor.globmatch
for starting_point in range(idx, len(parts)):
if successor_globmatch(parts, starting_point):
return True
return False
def _TerminatingSelector_globmatch(self, parts, idx):
return True
def _WildcardSelector_globmatch(self, parts, idx):
plen = len(parts)
if idx < plen and (not self.dironly or idx != plen - 1):
if self.pat.match(parts[idx]):
return self.successor.globmatch(parts, idx + 1)
return False
_PreciseSelector.globmatch = _PreciseSelector_globmatch
_RecursiveWildcardSelector.globmatch = _RecursiveWildcardSelector_globmatch
_TerminatingSelector.globmatch = _TerminatingSelector_globmatch
_WildcardSelector.globmatch = _WildcardSelector_globmatch
def _globmatch(self, pattern):
"""Determine if this path matches the given glob pattern.
"""
if not pattern:
raise ValueError("Unacceptable pattern: {0!r}".format(pattern))
pattern = self._flavour.casefold(pattern)
drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
if drv or root:
raise NotImplementedError("Non-relative patterns are unsupported")
selector = _make_selector(tuple(pattern_parts))
return selector.globmatch(self._cparts, 0)
PurePath.globmatch = _globmatch
if __name__ == '__main__':
tests = {
# From the pathlib2 tests
'fileA': [
('fileA', True),
('dirA/', False),
('dirB/', False),
('dirB/fileB', False),
('dirC/fileC', False),
],
'fileB': [
('fileA', False),
('dirA/', False),
('dirB/', False),
('dirB/fileB', False),
('dirC/fileC', False),
],
'dir*/file*': [
('fileA', False),
('dirA/', False),
('dirB/', False),
('dirB/fileB', True),
('dirC/fileC', True),
],
'*A': [
('fileA', True),
('dirA/', True),
('dirB/', False),
('dirB/fileB', False),
('dirC/fileC', False),
],
'*B/*': [
('fileA', False),
('dirA/', False),
('dirB/', False),
('dirB/fileB', True),
('dirC/fileC', False),
],
'*/fileB': [
('fileA', False),
('dirA/', False),
('dirB/', False),
('dirB/fileB', True),
('dirC/fileC', False),
],
# Extras
'*.a': [
('file.a', True),
('dirA/', False),
('dirA/dirB/dirC/file.a', False),
('dirA/dirB/dirC/file.b', False),
('dirB/', False),
('dirB/file.a', False),
('dirB/file.b', False),
('dirB/dirC/file.a', False),
('dirB/dirC/file.b', False),
('dirC/', False),
('dirC/file.a', False),
('dirC/file.c', False),
],
'**/*.a': [
('file.a', True),
('dirA/', False),
('dirA/dirB/dirC/file.a', True),
('dirA/dirB/dirC/file.b', False),
('dirB/', False),
('dirB/file.a', True),
('dirB/file.b', False),
('dirB/dirC/file.a', True),
('dirB/dirC/file.b', False),
('dirC/', False),
('dirC/file.a', True),
('dirC/file.c', False),
],
'**/dirC/*.a': [
('file.a', False),
('dirA/', False),
('dirA/dirB/dirC/file.a', True),
('dirA/dirB/dirC/file.b', False),
('dirB/', False),
('dirB/file.a', False),
('dirB/file.b', False),
('dirB/dirC/file.a', True),
('dirB/dirC/file.b', False),
('dirC/', False),
('dirC/file.a', True),
('dirC/file.c', False),
]
}
failures = {}
for glob in tests:
for pstr, match in tests[glob]:
p = PurePosixPath(pstr)
if p.globmatch(glob) != match:
failures.setdefault(glob, []).append(
dict(path=pstr, should_match=match)
)
if failures:
import pprint
pprint.pprint(failures)
else:
print("success")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment