# Source code for tensorplay.package.glob_group Source: https://www.tensorplay.cn/docs/_modules/tensorplay/package/glob_group.html ``` # mypy: allow-untyped-defs from __future__ import annotations import re from collections.abc import Iterable GlobPattern = str | Iterable[str] [docs] class GlobGroup: """A set of patterns that candidate strings will be matched against. A candidate is composed of a list of segments separated by ``separator``, e.g. ``"foo.bar.baz"``. A pattern contains one or more segments. Segments can be: - A literal string (e.g. ``"foo"``), which matches exactly. - A string containing a wildcard (e.g. ``"tensorplay*"``, or ``"foo*baz*"``). The wildcard matches any string, including the empty string. - A double wildcard (``"**"``). This matches against zero or more complete segments. Examples: ``tensorplay.**``: matches ``tensorplay`` and all its submodules, e.g. ``tensorplay.nn`` and ``tensorplay.nn.functional``. ``tensorplay.*``: matches ``tensorplay.nn`` or ``tensorplay.utils``, but not ``tensorplay.nn.functional``. ``tensorplay*.**``: matches ``tensorplay``, ``tensorplay_vision``, and all their submodules. A candidate will match the ``GlobGroup`` if it matches any of the ``include`` patterns and none of the ``exclude`` patterns. Args: include (str | Iterable[str]): A string or list of strings, each representing a pattern to be matched against. A candidate will match if it matches *any* include pattern exclude (str | Iterable[str]): A string or list of strings, each representing a pattern to be matched against. A candidate will be excluded from matching if it matches *any* exclude pattern. separator (str): A string that delimits segments in candidates and patterns. By default this is "." which corresponds to how modules are named in Python. Another common value for this is "/", which is the Unix path separator. """ def __init__( self, include: GlobPattern, *, exclude: GlobPattern = (), separator: str = "." ): self._dbg = f"GlobGroup(include={include}, exclude={exclude})" self.include = GlobGroup._glob_list(include, separator) self.exclude = GlobGroup._glob_list(exclude, separator) self.separator = separator def __str__(self): return self._dbg def __repr__(self): return self._dbg def matches(self, candidate: str) -> bool: candidate = self.separator + candidate return any(p.fullmatch(candidate) for p in self.include) and all( not p.fullmatch(candidate) for p in self.exclude ) @staticmethod def _glob_list(elems: GlobPattern, separator: str = "."): if isinstance(elems, str): return [GlobGroup._glob_to_re(elems, separator)] else: return [GlobGroup._glob_to_re(e, separator) for e in elems] @staticmethod def _glob_to_re(pattern: str, separator: str = "."): # To avoid corner cases for the first component, the candidate string # is prefixed with the separator so that e.g. `import tensorplay` # matches against `.tensorplay` (assuming '.' is the separator). def component_to_re(component): if "**" in component: if component == "**": return "(" + re.escape(separator) + "[^" + separator + "]+)*" else: raise ValueError("** can only appear as an entire path segment") else: return re.escape(separator) + ("[^" + separator + "]*").join( re.escape(x) for x in component.split("*") ) result = "".join(component_to_re(c) for c in pattern.split(separator)) return re.compile(result) ```