diff options
-rw-r--r-- | pym/portage/dep.py | 100 | ||||
-rw-r--r-- | pym/portage/tests/dep/test_isvalidatom.py | 5 |
2 files changed, 80 insertions, 25 deletions
diff --git a/pym/portage/dep.py b/pym/portage/dep.py index 15000dd84..aa1057d82 100644 --- a/pym/portage/dep.py +++ b/pym/portage/dep.py @@ -24,6 +24,7 @@ from itertools import chain import portage.exception from portage.exception import InvalidData, InvalidAtom from portage.versions import catpkgsplit, catsplit, pkgcmp, pkgsplit, ververify +import portage.cache.mappings def cpvequal(cpv1, cpv2): """ @@ -343,54 +344,101 @@ class _use_dep(object): __slots__ = ("__weakref__", "conditional", "conditional_disabled", "conditional_enabled", "disabled", "enabled", "tokens", "required") + _conditionals_class = portage.cache.mappings.slot_dict_class( + ("disabled", "enabled", "equal", "not_equal"), prefix="") + def __init__(self, use): enabled_flags = [] disabled_flags = [] - conditional_enabled = [] - conditional_disabled = [] + conditional = self._conditionals_class() + for k in conditional.allowed_keys: + conditional[k] = [] + for x in use: - if "-" == x[:1]: - if "?" == x[-1:]: - conditional_disabled.append(x[1:-1]) + last_char = x[-1:] + if "?" == last_char: + if "-" == x[:1]: + conditional.disabled.append(x[1:-1]) else: - disabled_flags.append(x[1:]) + conditional.enabled.append(x[:-1]) + elif "=" == last_char: + if "-" == x[:1]: + raise InvalidAtom("Invalid use dep: '%s'" % (x,)) + if "!" == x[-2:-1]: + conditional.not_equal.append(x[:-2]) + else: + conditional.equal.append(x[:-1]) else: - if "?" == x[-1:]: - conditional_enabled.append(x[:-1]) + if "-" == x[:1]: + disabled_flags.append(x[1:]) else: enabled_flags.append(x) + self.tokens = use if not isinstance(self.tokens, tuple): self.tokens = tuple(self.tokens) + + self.required = frozenset(chain( + enabled_flags, + disabled_flags, + *conditional.values() + )) + self.enabled = frozenset(enabled_flags) self.disabled = frozenset(disabled_flags) - self.conditional_enabled = frozenset(conditional_enabled) - self.conditional_disabled = frozenset(conditional_disabled) - self.conditional = self.conditional_enabled.union( - self.conditional_disabled) - self.required = frozenset(chain(self.enabled, self.disabled, - self.conditional_enabled, self.conditional_disabled)) + self.conditional = None + + for v in conditional.itervalues(): + if v: + for k, v in conditional.iteritems(): + conditional[k] = frozenset(v) + self.conditional = conditional + break def __str__(self): return "".join("[%s]" % x for x in self.tokens) def evaluate_conditionals(self, use): """ - Create a new instance with conditionals evaluated as follows: + Create a new instance with conditionals evaluated. + + Conditional evaluation behavior: + + parent state conditional result + + x x? x + -x x? + x -x? + -x -x? -x + + x x= x + -x x= -x + x x!= -x + -x x!= x + + Conditional syntax examples: + + compact form equivalent expanded form + + foo[bar?] foo bar? ( foo[bar] ) + foo[-bar?] foo !bar? ( foo[-bar] ) + foo[bar=] foo bar? ( foo[bar] ) !bar? ( foo[-bar] ) + foo[bar!=] foo bar? ( foo[-bar] ) !bar? ( foo[bar] ) - parent state conditional result - x x? x - -x x? -x - x -x? -x - -x -x? x """ tokens = [] + + conditional = self.conditional tokens.extend(self.enabled) tokens.extend("-" + x for x in self.disabled) - tokens.extend(self.conditional_enabled.intersection(use)) - tokens.extend("-" + x for x in self.conditional_enabled.difference(use)) - tokens.extend("-" + x for x in self.conditional_disabled.intersection(use)) - tokens.extend(self.conditional_disabled.difference(use)) + tokens.extend(x for x in conditional.enabled if x in use) + tokens.extend("-" + x for x in conditional.disabled if x not in use) + + tokens.extend(x for x in conditional.equal if x in use) + tokens.extend("-" + x for x in conditional.equal if x not in use) + tokens.extend("-" + x for x in conditional.not_equal if x in use) + tokens.extend(x for x in conditional.not_equal if x not in use) + return _use_dep(tokens) class _AtomCache(type): @@ -655,7 +703,9 @@ def isvalidatom(atom, allow_blockers=False): atom = atom[1:] try: - dep_getusedeps(atom) + use = dep_getusedeps(atom) + if use: + use = _use_dep(use) except InvalidAtom: return 0 diff --git a/pym/portage/tests/dep/test_isvalidatom.py b/pym/portage/tests/dep/test_isvalidatom.py index d2210b8e9..397ce997b 100644 --- a/pym/portage/tests/dep/test_isvalidatom.py +++ b/pym/portage/tests/dep/test_isvalidatom.py @@ -25,6 +25,11 @@ class IsValidAtom(TestCase): ( "sys-apps/portage:foo", True ), ( "sys-apps/portage-2.1:foo", False ), ( "sys-apps/portage-2.1:", False ), + ( "=sys-apps/portage-2.2*:foo[bar?,-baz?,doc!=,build=]", True ), + ( "=sys-apps/portage-2.2*:foo[build=]", True ), + ( "=sys-apps/portage-2.2*:foo[doc!=]", True ), + ( "=sys-apps/portage-2.2*:foo[-doc!=]", False ), + ( "=sys-apps/portage-2.2*:foo[-doc=]", False ), ( "=sys-apps/portage-2.2*:foo[bar][-baz][doc?][-build?]", True ), ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,-build?]", True ), ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,-build?,]", False ), |