From c09249ef31217c79606fc474c7c7bc9683e8c4c7 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Mon, 28 Jul 2008 17:48:47 +0000 Subject: [PATCH] Merged from trunk 11225:11238 | 11226 | Fix the new glep56 code to handle missing metadata.xml. | | zmedico | Thanks to jmbsvicetto for reporting. | | 11227 | Fix incorrect logging.exception() arguments. The exception | | zmedico | instance is not supposed to be passed into this function. | | 11228 | Bug #233137 - Implement Atom.split(). | | zmedico | | | 11229 | * Add support in dep_getusedeps() and isvalidatom() for | | zmedico | comma separated USE deps that only have one set of square | | | brackets. * Add test cases for the new comma separated USE | | | deps syntax. | | 11230 | Create a SlotDict constructor which can take an optional | | zmedico | positional arg that is passed to the update() method | | | (similar to the dict constructor), and also pass keyword | | | arguments into the update() method if any are given. This | | | makes it possible to use the constructor similarly to the | | | way that the _emerge.SlotObject constructor is used. | | 11231 | Implement new conditional USE dep syntax: Conditional | | zmedico | 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] ) | | 11232 | Disable the multi-bracket USE deps syntax, so only the comma | | zmedico | separated syntax is now valid. | | 11234 | Fix arg count when constructing a TypeError in the SlotDict | | zmedico | constructor. | | 11235 | Create a table to document conditional USE dependency | | zmedico | syntax. | | 11236 | Add note about support for EAPI="2_pre0". | | zmedico | | | 11238 | Remove pointless generator expression. | | zmedico | | svn path=/main/branches/prefix/; revision=11239 --- NEWS | 5 + bin/repoman | 25 ++-- doc/package/ebuild.docbook | 1 + doc/package/ebuild/eapi/2.docbook | 39 ++++++ doc/portage.docbook | 1 + pym/portage/cache/mappings.py | 13 ++ pym/portage/dep.py | 137 +++++++++++++++---- pym/portage/tests/dep/test_dep_getusedeps.py | 3 +- pym/portage/tests/dep/test_isvalidatom.py | 12 +- 9 files changed, 192 insertions(+), 44 deletions(-) create mode 100644 doc/package/ebuild/eapi/2.docbook diff --git a/NEWS b/NEWS index 4c565a514..fe6fb10ae 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,11 @@ News (mainly features/major bug fixes) portage-2.2 ------------- +* Add support for a new EAPI="2_pre0" value that can be used in ebuilds when + testing new features such as USE dependencies. This is an experimental EAPI + that will not be supported after the final EAPI 2 is defined. For more + information about experimental EAPI features, refer to the "Ebuild" chapter + of the html documentation that is installed with portage. * Add PORTAGE_IONICE_COMMAND setting for make.conf which is called to adjust IO priority on portage and it's subprocesses. * Add link level dependency awareness to emerge --depclean and --prune actions diff --git a/bin/repoman b/bin/repoman index a164b4c3f..d0d587955 100755 --- a/bin/repoman +++ b/bin/repoman @@ -570,7 +570,7 @@ try: utilities.parse_use_local_desc(f, luselist) f.close() except (IOError, OSError, ParseError), e: - logging.exception("Couldn't read from use.local.desc", e) + logging.exception("Couldn't read from use.local.desc") sys.exit(1) if portdir_overlay != portdir: @@ -581,7 +581,7 @@ if portdir_overlay != portdir: utilities.parse_use_local_desc(f, luselist) f.close() except (IOError, OSError, ParseError), e: - logging.exception("Couldn't read from '%s'" % filename, e) + logging.exception("Couldn't read from '%s'" % (filename,)) sys.exit(1) del filename @@ -596,7 +596,7 @@ try: for l in range(0, len(vardescs)): uselist.append(var.lower() + "_" + vardescs[l].split()[0]) except (IOError, OSError, ParseError), e: - logging.exception("Couldn't read USE flags from use.desc", e) + logging.exception("Couldn't read USE flags from use.desc") sys.exit(1) # retrieve a list of current licenses in portage @@ -1059,6 +1059,8 @@ for x in scanlist: fails["changelog.missing"].append(x+"/ChangeLog") #metadata.xml file check + muselist = [] + if "metadata.xml" not in checkdirlist: stats["metadata.missing"]+=1 fails["metadata.missing"].append(x+"/metadata.xml") @@ -1078,15 +1080,14 @@ for x in scanlist: stats["metadata.bad"]+=1 fails["metadata.bad"].append(x+"/metadata.xml") - #load USE flags from metadata.xml - muselist=[] - try: - f = open(os.path.join(checkdir, "metadata.xml")) - utilities.parse_metadata_use(f, muselist) - f.close() - except (IOError, OSError, ParseError), e: - logging.exception("Couldn't read from metadata.xml", e) - sys.exit(1) + #load USE flags from metadata.xml + try: + f = open(os.path.join(checkdir, "metadata.xml")) + utilities.parse_metadata_use(f, muselist) + f.close() + except (EnvironmentError, ParseError), e: + logging.exception("Couldn't read from metadata.xml") + sys.exit(1) allmasked = True diff --git a/doc/package/ebuild.docbook b/doc/package/ebuild.docbook index 4bdb8129d..fa4f75609 100644 --- a/doc/package/ebuild.docbook +++ b/doc/package/ebuild.docbook @@ -2,4 +2,5 @@ Ebuild &package_ebuild_phases; &package_ebuild_helper_functions; +&package_ebuild_eapi_2; diff --git a/doc/package/ebuild/eapi/2.docbook b/doc/package/ebuild/eapi/2.docbook new file mode 100644 index 000000000..594eceabe --- /dev/null +++ b/doc/package/ebuild/eapi/2.docbook @@ -0,0 +1,39 @@ + + EAPI 2_pre0 + + USE Dependencies + + Conditional USE Dependencies + 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] ) + + + +
+
+
+
diff --git a/doc/portage.docbook b/doc/portage.docbook index 8c29303e6..c038079a2 100644 --- a/doc/portage.docbook +++ b/doc/portage.docbook @@ -15,6 +15,7 @@ + diff --git a/pym/portage/cache/mappings.py b/pym/portage/cache/mappings.py index d0ca487f0..96e9e553b 100644 --- a/pym/portage/cache/mappings.py +++ b/pym/portage/cache/mappings.py @@ -142,6 +142,19 @@ def slot_dict_class(keys, prefix="_val_"): __slots__ = ("__weakref__",) + \ tuple(prefix + k for k in allowed_keys) + def __init__(self, *args, **kwargs): + + if len(args) > 1: + raise TypeError( + "expected at most 1 positional argument, got " + \ + repr(len(args))) + + if args: + self.update(args[0]) + + if kwargs: + self.update(kwargs) + def __iter__(self): for k, v in self.iteritems(): yield k diff --git a/pym/portage/dep.py b/pym/portage/dep.py index c2f506d4b..49f6bc045 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) + return "[%s]" % (",".join(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): @@ -416,7 +464,8 @@ class Atom(object): _atoms = weakref.WeakValueDictionary() _str_methods = ("endswith", "find", "index", "lstrip", "replace", - "startswith", "strip", "rindex", "rfind", "rstrip", "__getitem__", + "startswith", "split", "strip", + "rindex", "rfind", "rstrip", "__getitem__", "__eq__", "__hash__", "__len__", "__ne__", "__repr__", "__str__") __slots__ = ("__weakref__", "blocker", "cp", "cpv", "operator", @@ -587,16 +636,38 @@ def dep_getusedeps( depend ): use_list = [] open_bracket = depend.find('[') # -1 = failure (think c++ string::npos) + comma_separated = False + bracket_count = 0 while( open_bracket != -1 ): + bracket_count += 1 + if bracket_count > 1: + raise InvalidAtom("USE Dependency with more " + \ + "than one set of brackets: %s" % (depend,)) close_bracket = depend.find(']', open_bracket ) if close_bracket == -1: raise InvalidAtom("USE Dependency with no closing bracket: %s" % depend ) use = depend[open_bracket + 1: close_bracket] # foo[1:1] may return '' instead of None, we don't want '' in the result - if len(use): - use_list.append(use) + if not use: + raise InvalidAtom("USE Dependency with " + \ + "no use flag ([]): %s" % depend ) + if not comma_separated: + comma_separated = "," in use + + if comma_separated and bracket_count > 1: + raise InvalidAtom("USE Dependency contains a mixture of " + \ + "comma and bracket separators: %s" % depend ) + + if comma_separated: + for x in use.split(","): + if x: + use_list.append(x) + else: + raise InvalidAtom("USE Dependency with no use " + \ + "flag next to comma: %s" % depend ) else: - raise InvalidAtom("USE Dependency with no use flag ([]): %s" % depend ) + use_list.append(use) + # Find next use flag open_bracket = depend.find( '[', open_bracket+1 ) return tuple(use_list) @@ -633,6 +704,14 @@ def isvalidatom(atom, allow_blockers=False): return 0 if allow_blockers and atom.startswith("!"): atom = atom[1:] + + try: + use = dep_getusedeps(atom) + if use: + use = _use_dep(use) + except InvalidAtom: + return 0 + cpv = dep_getcpv(atom) cpv_catsplit = catsplit(cpv) mycpv_cps = None diff --git a/pym/portage/tests/dep/test_dep_getusedeps.py b/pym/portage/tests/dep/test_dep_getusedeps.py index 71b0fe290..99a17b80d 100644 --- a/pym/portage/tests/dep/test_dep_getusedeps.py +++ b/pym/portage/tests/dep/test_dep_getusedeps.py @@ -25,8 +25,7 @@ class DepGetUseDeps(TestCase): if slot: cpv += ":" + slot if isinstance(use, tuple): - for u in use: - cpv = cpv + "[" + u + "]" + cpv += "[%s]" % (",".join(use),) self.assertEqual( dep_getusedeps( cpv ), use ) else: diff --git a/pym/portage/tests/dep/test_isvalidatom.py b/pym/portage/tests/dep/test_isvalidatom.py index dfcf17898..f7cc3b844 100644 --- a/pym/portage/tests/dep/test_isvalidatom.py +++ b/pym/portage/tests/dep/test_isvalidatom.py @@ -25,7 +25,17 @@ 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[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?]", False ), + ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,-build?]", True ), + ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,-build?,]", False ), + ( "=sys-apps/portage-2.2*:foo[,bar,-baz,doc?,-build?]", False ), + ( "=sys-apps/portage-2.2*:foo[bar,-baz][doc?,-build?]", False ), + ( "=sys-apps/portage-2.2*:foo[bar][doc,build]", False ), ( ">~cate-gory/foo-1.0", False ), ( ">~category/foo-1.0", False ), ( "<~category/foo-1.0", False ), -- 2.26.2