diff options
author | 2005-08-09 07:51:09 +0000 | |
---|---|---|
committer | 2005-08-09 07:51:09 +0000 | |
commit | 98cf91703147b689380e91bd869755363dc7f81d (patch) | |
tree | 749f4b2443b0fb3449bb276593e76291381e008f | |
parent | whee. (diff) | |
download | portage-cvs-98cf91703147b689380e91bd869755363dc7f81d.tar.gz portage-cvs-98cf91703147b689380e91bd869755363dc7f81d.tar.bz2 portage-cvs-98cf91703147b689380e91bd869755363dc7f81d.zip |
documentation first off (across the board)
addition of __all__ where I've decided (collapsed and restrictionset at this point)
addition of cmatch method, used for dealing with mutable configuration wrappers (ongoing)
yanked SubStringMatch, since it's covered by ContainmentMatch (fixed that beast too, since first implementation of it sucked).
-rw-r--r-- | portage/restrictions/collapsed.py | 21 | ||||
-rw-r--r-- | portage/restrictions/restriction.py | 81 | ||||
-rw-r--r-- | portage/restrictions/restrictionSet.py | 105 |
3 files changed, 140 insertions, 67 deletions
diff --git a/portage/restrictions/collapsed.py b/portage/restrictions/collapsed.py index a8c9388..32e91b4 100644 --- a/portage/restrictions/collapsed.py +++ b/portage/restrictions/collapsed.py @@ -1,14 +1,33 @@ # Copyright: 2005 Gentoo Foundation # Author(s): Brian Harring (ferringb@gentoo.org) # License: GPL2 -# $Header: /local/data/ulm/cvs/history/var/cvsroot/gentoo-src/portage/portage/restrictions/collapsed.py,v 1.2 2005/08/03 00:20:55 ferringb Exp $ +# $Header: /local/data/ulm/cvs/history/var/cvsroot/gentoo-src/portage/portage/restrictions/collapsed.py,v 1.3 2005/08/09 07:51:09 ferringb Exp $ +__all__=("DictBased") from restriction import base, AlwaysTrue from inspect import isroutine from restrictionSet import bases, OrRestrictionSet from portage.util.inheritance import check_for_base class DictBased(base): + """Restrictions are (by default) executed in a depth/breadth method; for long chains of restrictions, + this grows inneficient. For example, package.mask'ing has over 300 atoms, effectively over 1800 objects in use. + + Running the filter on each package instance returned from a repo would be exceedingly slow, a way to get as close to + constant lookup as possible is needed. + + DictBased works by using supplied functions to collapse long chains of restrictions into a dict, with key + defined by get_key_from_atom (with get_key_from_package returning the key of a pkg instance), and with the + value of that key holding the remaining restrictions (if any). + + Common usage at this point is to collapse category and package attribute restrictions into constant lookup, with + any remaining version restrictions being handed off as a val. + + Example usage of this class should be available in portage.config.domain.domain + + Aside from that, method of generating keys/collapsing restrictions is subject to change, still need to push metadata + in re: what restriction types are being collapsed; short version, api isn't declared stable yet. + """ __slots__ = tuple(["restricts_dict", "get_pkg_key", "get_atom_key"] + base.__slots__) def __init__(self, restriction_items, get_key_from_package, get_key_from_atom, *args, **kwargs): diff --git a/portage/restrictions/restriction.py b/portage/restrictions/restriction.py index c155181..60d1831 100644 --- a/portage/restrictions/restriction.py +++ b/portage/restrictions/restriction.py @@ -1,7 +1,7 @@ # Copyright: 2005 Gentoo Foundation # Author(s): Brian Harring (ferringb@gentoo.org) # License: GPL2 -# $Header: /local/data/ulm/cvs/history/var/cvsroot/gentoo-src/portage/portage/restrictions/restriction.py,v 1.7 2005/08/03 00:20:55 ferringb Exp $ +# $Header: /local/data/ulm/cvs/history/var/cvsroot/gentoo-src/portage/portage/restrictions/restriction.py,v 1.8 2005/08/09 07:51:09 ferringb Exp $ import re, logging @@ -26,6 +26,9 @@ class base(object): def match(self, *arg, **kwargs): raise NotImplementedError + def cmatch(self, *arg, **kwargs): + return self.match(*arg, **kwargs) + def intersect(self, other): return None @@ -119,43 +122,6 @@ class StrExactMatch(StrMatch): return "== "+self.exact -class StrSubstringMatch(StrMatch): - __slots__ = tuple(["substr"] + StrMatch.__slots__) - - def __init__(self, substr, CaseSensitive=True, **kwds): - super(StrSubstringMatch, self).__init__(**kwds) - if not CaseSensitive: - self.flags = re.I - self.substr = str(substr).lower() - else: - self.flags = 0 - self.substr = str(substr) - - def match(self, value): - if self.flags & re.I: value = str(value).lower() - else: value = str(value) - return (value.find(self.substr) != -1) ^ self.negate - - def intersect(self, other): - if self.negate == other.negate: - if self.substr == other.substr and self.flags == other.flags: - return self - else: - return None - s1, s2 = self.substr, other.substr - if other.flags and not self.flags: - s1 = s1.lower() - elif self.flags and not other.flags: - s2 = s2.lower() - if s1.find(s2) != -1: - return self - elif s2.find(s1) != -1: - return other - return None - - def __eq__(self, other): - return self.substr == other.substr and self.negate == other.negate and self.flags == other.flags - class StrGlobMatch(StrMatch): __slots__ = tuple(["glob"] + StrMatch.__slots__) @@ -169,9 +135,16 @@ class StrGlobMatch(StrMatch): self.glob = str(glob) def match(self, value): - value = str(value) - if self.flags & re.I: value = value.lower() - return value.startswith(self.glob) ^ self.negate + if isinstance(value, (list, tuple)): + for x in value: + print "trying %s against %s" % (x, self.glob) + if self.match(x): + return not self.negate + return self.negate + else: + value = str(value) + if self.flags & re.I: value = value.lower() + return value.startswith(self.glob) ^ self.negate def intersect(self, other): if self.match(other.glob): @@ -252,18 +225,30 @@ class PackageRestriction(base): class ContainmentMatch(base): """used for an 'in' style operation, 'x86' in ['x86','~x86'] for example""" - __slots__ = tuple(["vals"] + base.__slots__) + __slots__ = tuple(["vals", "vals_len"] + base.__slots__) - def __init__(self, vals, **kwds): + def __init__(self, *vals, **kwds): """vals must support a contaiment test""" super(ContainmentMatch, self).__init__(**kwds) - self.vals = vals - + self.vals = set(vals) + self.vals_len = len(self.vals) + def match(self, val): - return (val in self.vals) ^ self.negate + if isinstance(val, (str, unicode)): + return val in self.vals ^ self.negate + try: + # assume our lookup is faster, since we don't know if val is constant lookup or not + l = len(val) + for x in val: + if x in self.vals: + return not self.negate + return self.negate + except TypeError: + return val in self.vals ^ self.negate + def __str__(self): - if self.negate: s="not in [%s]" - else: s="in [%s]" + if self.negate: s="not contains [%s]" + else: s="contains [%s]" return s % ', '.join(map(str, self.vals)) diff --git a/portage/restrictions/restrictionSet.py b/portage/restrictions/restrictionSet.py index e93bd13..67288d1 100644 --- a/portage/restrictions/restrictionSet.py +++ b/portage/restrictions/restrictionSet.py @@ -1,14 +1,25 @@ # Copyright: 2005 Gentoo Foundation # Author(s): Brian Harring (ferringb@gentoo.org) # License: GPL2 -# $Header: /local/data/ulm/cvs/history/var/cvsroot/gentoo-src/portage/portage/restrictions/Attic/restrictionSet.py,v 1.8 2005/08/03 00:20:55 ferringb Exp $ +# $Header: /local/data/ulm/cvs/history/var/cvsroot/gentoo-src/portage/portage/restrictions/Attic/restrictionSet.py,v 1.9 2005/08/09 07:51:09 ferringb Exp $ + +""" +This module provides classes that can be used to combine arbitrary collections of restrictions in AND, NAND, OR, NOR, XOR, XNOR +style operations. +""" import restriction +from itertools import imap +__all__ = ("AndRestrictionSet", "OrRestrictionSet", "XorRestrictionSet") class RestrictionSet(restriction.base): __slots__ = tuple(["restrictions"] + restriction.base.__slots__) def __init__(self, *restrictions, **kwds): + """Optionally hand in (positionally) restrictions to use as the basis of this restriction + finalize=False, set it to True to notify this instance to internally finalize itself (no way to reverse it yet) + negate=False, controls whether matching results are negated + """ if "finalize" in kwds: finalize = kwds["finalize"] del kwds["finalize"] @@ -26,16 +37,23 @@ class RestrictionSet(restriction.base): self.restrictions = list(restrictions) - def add_restriction(self, NewRestriction, strict=True): - if strict and not isinstance(NewRestriction, restriction.base): - raise TypeError, NewRestriction - - self.restrictions.append(NewRestriction) + def add_restriction(self, *new_restrictions, **kwds): + """add restriction(s) + strict=True, set to false to disable isinstance checks to ensure all restrictions are restriction.base derivatives + """ + if len(new_restrictions) == 0: + raise TypeError("need at least one restriction handed in") + if kwds.get("strict", True): + for r in new_restrictions: + if not isinstance(r, restriction.base): + raise TypeError("instance '%s' isn't a restriction.base, and strict is on" % r) + + self.restrictions.extend(new_restrictions) def finalize(self): self.restrictions = tuple(self.restrictions) - def total_len(self): return sum(map(lambda x: x.total_len(), self.restrictions)) + 1 + def total_len(self): return sum(imap(lambda x: x.total_len(), self.restrictions)) + 1 def __len__(self): return len(self.restrictions) @@ -44,25 +62,46 @@ class RestrictionSet(restriction.base): def __getitem__(self, key): return self.restrictions[key] +def unwind_changes(pkg, pop_count, negate): + while pop_count: + pkg.pop_change() + pop_count-=1 + if negate: + return pkg + return None + class AndRestrictionSet(RestrictionSet): + """Boolean AND grouping of restrictions.""" __slots__ = tuple(RestrictionSet.__slots__) - + def match(self, packagedataInstance): for rest in self.restrictions: if not rest.match(packagedataInstance): return self.negate return not self.negate + def cmatch(self, pkg): + entry_point = pkg.changes_count() + for rest in self.restrictions: + if c.match(pkg) == False: + pkg.rollback_changes(entry_point) + if self.negate: return pkg + return self.negate -# def intersect(self, other): + # for this to be reached, things went well. + if self.negate: + pkg.rollback_changes(entry_point) + # yes, normally it's "not negate", but we no negates status already via the if + return False + return True def __str__(self): - if self.negate: s=" !& " - else: s=" && " - return '( %s )' % s.join(map(str,self.restrictions)) + if self.negate: return "not ( %s )" % " && ".join(imap(str, self.restrictions)) + return "( %s )" % " && ".join(imap(str, self.restrictions)) class OrRestrictionSet(RestrictionSet): + """Boolean OR grouping of restrictions.""" __slots__ = tuple(RestrictionSet.__slots__) def match(self, packagedataInstance): @@ -71,13 +110,27 @@ class OrRestrictionSet(RestrictionSet): return not self.negate return self.negate + def cmatch(self, pkg): + entry_point = pkg.changes_count() + for rest in self.restrictions: + if rest.cmatch(pkg) == True: + if self.negate: + pkg.rollback_changes(entry_point) + return not self.negate + else: + pkg.rollback_changes(entry_point) + + if self.negate: + pkg.rollback_changes(entry_point) + return self.negate + def __str__(self): - if self.negate: s=" !| " - else: s=" || " - return '( %s )' % s.join(map(str,self.restrictions)) + if self.negate: return "not ( %s )" % " || ".join(imap(str, self.restrictions)) + return "( %s )" % " || ".join(imap(str, self.restrictions)) class XorRestrictionSet(RestrictionSet): + """Boolean XOR grouping of restrictions.""" __slots__ = tuple(RestrictionSet.__slots__) def match(self, pkginst): @@ -89,10 +142,26 @@ class XorRestrictionSet(RestrictionSet): armed = True return armed ^ self.negate + def cmatch(self, pkg): + entry_point = None + armed = False + for ret in self.restrictions: + node_entry_point = pkg.changes_count() + if rest.cmatch(pkg): + if armed: + pkg.rollback_changes(entry_point) + return self.negate + armed = True + else: + pkg.rollback_changes(node_entry_point) + + if self.negate and entry_point != None: + pkg.rollback_changes(entry_point) + return armed ^ self.negate + def __str__(self): - if self.negate: s=" !^ " - else: s=" ^^ " - return '( %s )' % s.join(map(str,self.restrictions)) + if self.negate: return "not ( %s )" % " ^^ ".join(imap(str, self.restrictions)) + return "( %s )" % " ^^ ".join(imap(str, self.restrictions)) bases = (AndRestrictionSet, OrRestrictionSet, XorRestrictionSet) |