aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--portage/restrictions/collapsed.py21
-rw-r--r--portage/restrictions/restriction.py81
-rw-r--r--portage/restrictions/restrictionSet.py105
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)