Source code for jammy.utils.matching

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# File   : matching.py
# Author : Jiayuan Mao
# Email  : maojiayuan@gmail.com
# Date   : 03/02/2017
#
# Qinsheng modified based on Jacinle.
# Distributed under terms of the MIT license.


import collections
import fnmatch
import re

__all__ = ["NameMatcher", "IENameMatcher"]


[docs]class NameMatcher: def __init__(self, rules=None): if rules is None: self._rules = [] elif isinstance(rules, dict): self._rules = list(rules.items()) else: assert isinstance(rules, collections.Iterable) self._rules = list(rules) self._map = {} self._compiled_rules = [] self._compiled = False self._matched = [] self._unused = set() self._last_stat = None @property def rules(self): return self._rules
[docs] def map(self): assert self._compiled return self._map
[docs] def append_rule(self, rule): self._rules.append(tuple(rule))
[docs] def insert_rule(self, index, rule): self._rules.insert(index, rule)
[docs] def pop_rule(self, index=None): self._rules.pop(index)
[docs] def begin(self, *, force_compile=False): if not self._compiled or force_compile: self.compile() self._matched = [] self._unused = set(range(len(self._compiled_rules)))
[docs] def end(self): return self._matched, {self._compiled_rules[i][0] for i in self._unused}
[docs] def match(self, k): for i, (rule_str, re_rule, rule_value) in enumerate(self._compiled_rules): if re_rule.match(k): if i in self._unused: self._unused.remove(i) self._matched.append((k, rule_str, rule_value)) return rule_value return None
[docs] def compile(self): self._map = dict() self._compiled_rules = [] for rule_str, rule_value in self._rules: self._map[rule_str] = rule_value re_rule = fnmatch.translate( rule_str ) # shell-style pattern converted to regular expression re_rule = re.compile(re_rule, flags=re.IGNORECASE) self._compiled_rules.append((rule_str, re_rule, rule_value)) self._compiled = True
def __enter__(self): self.begin() return self def __exit__(self, exc_type, exc_val, exc_tb): self._last_stat = self.end()
[docs] def get_last_stat(self): return self._last_stat
[docs]class IENameMatcher: def __init__(self, include=None, exclude=None): if include is None: self.include = None else: self.include = NameMatcher([(i, True) for i in include]) if exclude is None: self.exclude = None else: self.exclude = NameMatcher([(e, True) for e in exclude]) self._last_stat = None
[docs] def begin(self): if self.include is not None: self.include.begin() if self.exclude is not None: self.exclude.begin() self._last_stat = (set(), set())
[docs] def end(self): if self.include is not None: self.include.end() if self.exclude is not None: self.exclude.end() if len(self._last_stat[0]) < len(self._last_stat[1]): self._last_stat = ("included", self._last_stat[0]) else: self._last_stat = ("excluded", self._last_stat[1])
[docs] def match(self, k): if self.include is None: ret = True else: ret = bool(self.include.match(k)) if self.exclude is not None: ret = ret and not bool(self.exclude.match(k)) if ret: self._last_stat[0].add(k) else: self._last_stat[1].add(k) return ret
def __enter__(self): self.begin() return self def __exit__(self, exc_type, exc_val, exc_tb): self.end()
[docs] def get_last_stat(self): return self._last_stat