From 2155c63872a213c4b66aa9a893f8599eebc2e8a6 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 28 Jul 2008 05:52:08 +0000 Subject: Implement new conditional USE dep syntax: 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] ) svn path=/main/trunk/; revision=11231 --- pym/portage/dep.py | 100 ++++++++++++++++++++++-------- 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 ), -- cgit v1.2.3-1-g7c22