1. Jonathan Eunice
  2. simplere


simplere / simplere / core.py

A simpler way to access and use regular expressions. As a bonus,
also simpler access to globs.

from mementos import MementoMetaclass, with_metaclass    
import sys, re, fnmatch

_PY3 = sys.version_info[0] > 2
if _PY3:
    basestring = str

class ReMatch(object):
    An easier-to-use proxy for regular expression match objects. Ideally this
    would be a subclass of the re module's match object, but their type
    ``_sre.SRE_Match`` appears to be unsubclassable
    Thus, ReMatch is a proxy exposes the match object's numeric (positional) and
    named groups through indices and attributes. If a named group has the same
    name as a match object method or property, it takes precedence. Either
    change the name of the match group or access the underlying property thus:
    def __init__(self, match):
        self._match = match
        self._groupdict = match.groupdict()
    def __getattr__(self, name):
        if name in self.__dict__:
            return self.__dict__[name]
        if name in self._groupdict:
            return self._groupdict[name]
            return getattr(self._match, name)
        except AttributeError:
            return AttributeError("no such attribute '{}'".format(name))

    def __getitem__(self, index):
        return self._match.group(index)

class Re(with_metaclass(MementoMetaclass, object)):

    # convenience copy of re flag constants
    DEBUG      = re.DEBUG
    I          = re.I
    L          = re.L
    LOCALE     = re.LOCALE
    M          = re.M
    S          = re.S
    DOTALL     = re.DOTALL
    U          = re.U
    X          = re.X
    _ = None

    def __init__(self, pattern, flags=0):
        self.pattern    = pattern
        self.flags      = flags
        self.re         = re.compile(pattern, flags)
        self.groups     = self.re.groups
        self.groupindex = self.re.groupindex
    def _regroup(self, m):
        Given an _sre.SRE_Match object, create and return a corresponding
        ReMatch object.
        result = ReMatch(m) if m else m
        Re._ = result
        return result

    def __contains__(self, item):
        if not isinstance(item, basestring):
             item = str(item)
        return self._regroup(self.re.search(item))
    ### methods that return ReMatch objects
    def search(self, *args, **kwargs):
        return self._regroup(self.re.search(*args, **kwargs))

    def match(self, *args, **kwargs):
        return self._regroup(self.re.match(*args, **kwargs))
    def finditer(self, *args, **kwargs):
        for m in self.re.finditer(*args, **kwargs):
            yield self._regroup(m)
    ### methods that don't need ReMatch objects
    def findall(self, *args, **kwargs):
        return self.re.findall(*args, **kwargs)
    def split(self, *args, **kwargs):
        return self.re.split(*args, **kwargs)
    def sub(self, *args, **kwargs):
        return self.re.sub(*args, **kwargs)
    def subn(self, *args, **kwargs):
        return self.re.subn(*args, **kwargs)
    def escape(self, *args, **kwargs):
        return self.re.escape(*args, **kwargs)

class Glob(with_metaclass(MementoMetaclass, object)):
    An item matches a Glob via Unix filesystem glob semantics.
    E.g. 'alpha' matches 'a*' and 'a????' but not 'b*'

    def __init__(self, pattern):
        self.pattern = pattern
    def __contains__(self, item):
        return fnmatch.fnmatch(str(item), self.pattern)