# # 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")