summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCasey Dahlin <cdahlin@redhat.com>2008-12-22 02:56:11 -0500
committerCasey Dahlin <cdahlin@redhat.com>2008-12-22 02:56:11 -0500
commit456d0c14697cf19128a58b40053fa56d1daf21f5 (patch)
treed9498f474d2a35678fd5dbb907cbd325f91d1fe8
parent8e1ee8d111b0ec5d7bf6b9e8f1dda833e35d30f2 (diff)
downloadupstate-456d0c14697cf19128a58b40053fa56d1daf21f5.tar.gz
upstate-456d0c14697cf19128a58b40053fa56d1daf21f5.tar.xz
upstate-456d0c14697cf19128a58b40053fa56d1daf21f5.zip
Add a pattern matching class
-rw-r--r--pattern.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/pattern.py b/pattern.py
new file mode 100644
index 0000000..a1919b5
--- /dev/null
+++ b/pattern.py
@@ -0,0 +1,83 @@
+__docformat__ = 'restructuredtext'
+
+class Pattern:
+ """
+ A pattern matches a string much like a regex. Our patterns have the
+ additional properties of being unionable and intersectable.
+ """
+
+ def __init__(self, positive_match, *args):
+ """
+ `args` is a series of strings the pattern should match. If
+ `positive_match` is False, then `args` is a series of strings that
+ should *not* be matched.
+ """
+ self.items = set(args)
+ self.invert = not positive_match
+
+ def match(self, str):
+ """
+ Determine if this Pattern matches `str`
+ """
+ retval = str in self.items
+ if self.invert: retval = not retval
+ return retval
+
+ def nonempty(self):
+ """
+ Returns True if this pattern will *ever* match *any* string.
+ """
+ if self.invert: return True
+ if len(self.items) > 0: return True
+ return False
+
+ def singular(self):
+ """
+ Returns True if this pattern will match *exactly one* string
+ """
+ return not self.invert and len(self.items) == 1
+
+ def complement(self):
+ """
+ Return a Pattern that matches anything this pattern *doesn't* match.
+ """
+ return Pattern(self.invert, *self.items)
+
+ def union(self, other):
+ """
+ Return a Pattern that matches anything this pattern *or* the pattern
+ `other` would match.
+ """
+ invert = True
+ if self.invert and other.invert:
+ items = self.items & other.items
+ elif not (self.invert or other.invert):
+ items = self.items | other.items
+ invert = False
+ else:
+ if self.invert:
+ items = self.items - other.items
+ else:
+ items = other.items - self.items
+ return Pattern(not invert, *items)
+
+ def intersect(self, other):
+ """
+ Return a Pattern that matches anything this pattern *and* the pattern
+ `other` would match.
+ """
+ return self.complement().union(other.complement()).complement()
+
+ def __str__(self):
+ if len(self.items) == 0:
+ if self.invert:
+ return "*"
+ else:
+ return "(-)"
+ if self.invert:
+ return "!(%s)" % "|".join(self.items)
+ else:
+ return "(%s)" % "|".join(self.items)
+
+ def __repr__(self):
+ return str(self)