summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/repoman2
-rw-r--r--pym/_emerge/Package.py2
-rw-r--r--pym/portage/dep/__init__.py47
-rw-r--r--pym/portage/eapi.py6
-rw-r--r--pym/portage/tests/dep/testCheckRequiredUse.py16
-rw-r--r--pym/portage/tests/dep/test_get_required_use_flags.py4
6 files changed, 57 insertions, 20 deletions
diff --git a/bin/repoman b/bin/repoman
index b50fac82c..dd065c8d6 100755
--- a/bin/repoman
+++ b/bin/repoman
@@ -2028,7 +2028,7 @@ for x in effective_scanlist:
" not supported with EAPI='%s'" % (eapi,))
try:
portage.dep.check_required_use(required_use, (),
- pkg.iuse.is_valid_flag)
+ pkg.iuse.is_valid_flag, eapi=eapi)
except portage.exception.InvalidDependString as e:
stats["REQUIRED_USE.syntax"] = stats["REQUIRED_USE.syntax"] + 1
fails["REQUIRED_USE.syntax"].append(
diff --git a/pym/_emerge/Package.py b/pym/_emerge/Package.py
index 85fc59773..2087cbfe0 100644
--- a/pym/_emerge/Package.py
+++ b/pym/_emerge/Package.py
@@ -228,7 +228,7 @@ class Package(Task):
else:
try:
check_required_use(v, (),
- self.iuse.is_valid_flag)
+ self.iuse.is_valid_flag, eapi=eapi)
except InvalidDependString as e:
# Force unicode format string for python-2.x safety,
# ensuring that PortageException.__unicode__() is used
diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py
index e547debd4..b7bb46f75 100644
--- a/pym/portage/dep/__init__.py
+++ b/pym/portage/dep/__init__.py
@@ -2314,9 +2314,9 @@ def match_from_list(mydep, candidate_list):
return mylist
def human_readable_required_use(required_use):
- return required_use.replace("^^", "exactly-one-of").replace("||", "any-of")
+ return required_use.replace("^^", "exactly-one-of").replace("||", "any-of").replace("??", "at-most-one-of")
-def get_required_use_flags(required_use):
+def get_required_use_flags(required_use, eapi=None):
"""
Returns a set of use flags that are used in the given REQUIRED_USE string
@@ -2326,6 +2326,12 @@ def get_required_use_flags(required_use):
@return: Set of use flags that are used in the given REQUIRED_USE string
"""
+ eapi_attrs = _get_eapi_attrs(eapi)
+ if eapi_attrs.required_use_at_most_one_of:
+ valid_operators = ("||", "^^", "??")
+ else:
+ valid_operators = ("||", "^^")
+
mysplit = required_use.split()
level = 0
stack = [[]]
@@ -2354,7 +2360,7 @@ def get_required_use_flags(required_use):
l = stack.pop()
ignore = False
if stack[level]:
- if stack[level][-1] in ("||", "^^") or \
+ if stack[level][-1] in valid_operators or \
(not isinstance(stack[level][-1], bool) and \
stack[level][-1][-1] == "?"):
ignore = True
@@ -2366,15 +2372,14 @@ def get_required_use_flags(required_use):
else:
raise InvalidDependString(
_("malformed syntax: '%s'") % required_use)
- elif token in ("||", "^^"):
+ elif token in valid_operators:
if need_bracket:
raise InvalidDependString(
_("malformed syntax: '%s'") % required_use)
need_bracket = True
stack[level].append(token)
else:
- if need_bracket or "(" in token or ")" in token or \
- "|" in token or "^" in token:
+ if need_bracket:
raise InvalidDependString(
_("malformed syntax: '%s'") % required_use)
@@ -2429,7 +2434,7 @@ class _RequiredUseBranch(object):
complex_nesting = False
node = self
while node != None and not complex_nesting:
- if node._operator in ("||", "^^"):
+ if node._operator in ("||", "^^", "??"):
complex_nesting = True
else:
node = node._parent
@@ -2450,7 +2455,7 @@ class _RequiredUseBranch(object):
if sys.hexversion < 0x3000000:
__nonzero__ = __bool__
-def check_required_use(required_use, use, iuse_match):
+def check_required_use(required_use, use, iuse_match, eapi=None):
"""
Checks if the use flags listed in 'use' satisfy all
constraints specified in 'constraints'.
@@ -2466,6 +2471,12 @@ def check_required_use(required_use, use, iuse_match):
@return: Indicates if REQUIRED_USE constraints are satisfied
"""
+ eapi_attrs = _get_eapi_attrs(eapi)
+ if eapi_attrs.required_use_at_most_one_of:
+ valid_operators = ("||", "^^", "??")
+ else:
+ valid_operators = ("||", "^^")
+
def is_active(token):
if token.startswith("!"):
flag = token[1:]
@@ -2475,6 +2486,11 @@ def check_required_use(required_use, use, iuse_match):
is_negated = False
if not flag or not iuse_match(flag):
+ if not eapi_attrs.required_use_at_most_one_of and flag == "?":
+ msg = _("Operator '??' is not supported with EAPI '%s'") \
+ % (eapi,)
+ e = InvalidData(msg, category='EAPI.incompatible')
+ raise InvalidDependString(msg, errors=(e,))
msg = _("USE flag '%s' is not in IUSE") \
% (flag,)
e = InvalidData(msg, category='IUSE.missing')
@@ -2492,6 +2508,8 @@ def check_required_use(required_use, use, iuse_match):
return (True in argument)
elif operator == "^^":
return (argument.count(True) == 1)
+ elif operator == "??":
+ return (argument.count(True) <= 1)
elif operator[-1] == "?":
return (False not in argument)
@@ -2521,7 +2539,7 @@ def check_required_use(required_use, use, iuse_match):
l = stack.pop()
op = None
if stack[level]:
- if stack[level][-1] in ("||", "^^"):
+ if stack[level][-1] in valid_operators:
op = stack[level].pop()
satisfied = is_satisfied(op, l)
stack[level].append(satisfied)
@@ -2550,7 +2568,7 @@ def check_required_use(required_use, use, iuse_match):
stack[level].append(satisfied)
if len(node._children) <= 1 or \
- node._parent._operator not in ("||", "^^"):
+ node._parent._operator not in valid_operators:
last_node = node._parent._children.pop()
if last_node is not node:
raise AssertionError(
@@ -2566,7 +2584,7 @@ def check_required_use(required_use, use, iuse_match):
raise AssertionError(
"node is not last child of parent")
- elif len(node._children) == 1 and op in ("||", "^^"):
+ elif len(node._children) == 1 and op in valid_operators:
last_node = node._parent._children.pop()
if last_node is not node:
raise AssertionError(
@@ -2576,7 +2594,7 @@ def check_required_use(required_use, use, iuse_match):
node._children[0]._parent = node._parent
node = node._children[0]
if node._operator is None and \
- node._parent._operator not in ("||", "^^"):
+ node._parent._operator not in valid_operators:
last_node = node._parent._children.pop()
if last_node is not node:
raise AssertionError(
@@ -2590,7 +2608,7 @@ def check_required_use(required_use, use, iuse_match):
else:
raise InvalidDependString(
_("malformed syntax: '%s'") % required_use)
- elif token in ("||", "^^"):
+ elif token in valid_operators:
if need_bracket:
raise InvalidDependString(
_("malformed syntax: '%s'") % required_use)
@@ -2600,8 +2618,7 @@ def check_required_use(required_use, use, iuse_match):
node._children.append(child)
node = child
else:
- if need_bracket or "(" in token or ")" in token or \
- "|" in token or "^" in token:
+ if need_bracket:
raise InvalidDependString(
_("malformed syntax: '%s'") % required_use)
diff --git a/pym/portage/eapi.py b/pym/portage/eapi.py
index a5ef30143..b701d02ab 100644
--- a/pym/portage/eapi.py
+++ b/pym/portage/eapi.py
@@ -56,6 +56,9 @@ def eapi_has_dosed_dohard(eapi):
def eapi_has_required_use(eapi):
return eapi not in ("0", "1", "2", "3")
+def eapi_has_required_use_at_most_one_of(eapi):
+ return eapi not in ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
+
def eapi_has_use_dep_defaults(eapi):
return eapi not in ("0", "1", "2", "3")
@@ -70,7 +73,7 @@ def eapi_allows_dots_in_use_flags(eapi):
_eapi_attrs = collections.namedtuple('_eapi_attrs',
'dots_in_PN dots_in_use_flags iuse_defaults '
- 'repo_deps required_use slot_abi slot_deps '
+ 'repo_deps required_use required_use_at_most_one_of slot_abi slot_deps '
'src_uri_arrows strong_blocks use_deps use_dep_defaults')
_eapi_attrs_cache = {}
@@ -97,6 +100,7 @@ def _get_eapi_attrs(eapi):
iuse_defaults = (eapi is None or eapi_has_iuse_defaults(eapi)),
repo_deps = (eapi is None or eapi_has_repo_deps(eapi)),
required_use = (eapi is None or eapi_has_required_use(eapi)),
+ required_use_at_most_one_of = (eapi is None or eapi_has_required_use_at_most_one_of(eapi)),
slot_deps = (eapi is None or eapi_has_slot_deps(eapi)),
slot_abi = (eapi is None or eapi_has_slot_abi(eapi)),
src_uri_arrows = (eapi is None or eapi_has_src_uri_arrows(eapi)),
diff --git a/pym/portage/tests/dep/testCheckRequiredUse.py b/pym/portage/tests/dep/testCheckRequiredUse.py
index 54791e016..d85ad92d3 100644
--- a/pym/portage/tests/dep/testCheckRequiredUse.py
+++ b/pym/portage/tests/dep/testCheckRequiredUse.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2011 Gentoo Foundation
+# Copyright 2010-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from portage.tests import TestCase
@@ -18,6 +18,11 @@ class TestCheckRequiredUse(TestCase):
( "^^ ( a b )", ["a"], ["a", "b"], True),
( "^^ ( a b )", ["b"], ["a", "b"], True),
( "^^ ( a b )", ["a", "b"], ["a", "b"], False),
+ ( "?? ( a b )", ["a", "b"], ["a", "b"], False),
+ ( "?? ( a b )", ["a"], ["a", "b"], True),
+ ( "?? ( a b )", ["b"], ["a", "b"], True),
+ ( "?? ( a b )", [], ["a", "b"], True),
+ ( "?? ( )", [], [], True),
( "^^ ( || ( a b ) c )", [], ["a", "b", "c"], False),
( "^^ ( || ( a b ) c )", ["a"], ["a", "b", "c"], True),
@@ -102,6 +107,10 @@ class TestCheckRequiredUse(TestCase):
( "^^ ( || ( a b ) ) ^^ ( b c ) )", [], ["a", "b", "c"]),
)
+ test_cases_xfail_eapi = (
+ ( "?? ( a b )", [], ["a", "b"], "4"),
+ )
+
for required_use, use, iuse, expected in test_cases:
self.assertEqual(bool(check_required_use(required_use, use, iuse.__contains__)), \
expected, required_use + ", USE = " + " ".join(use))
@@ -110,6 +119,11 @@ class TestCheckRequiredUse(TestCase):
self.assertRaisesMsg(required_use + ", USE = " + " ".join(use), \
InvalidDependString, check_required_use, required_use, use, iuse.__contains__)
+ for required_use, use, iuse, eapi in test_cases_xfail_eapi:
+ self.assertRaisesMsg(required_use + ", USE = " + " ".join(use), \
+ InvalidDependString, check_required_use, required_use, use,
+ iuse.__contains__, eapi=eapi)
+
def testCheckRequiredUseFilterSatisfied(self):
"""
Test filtering of satisfied parts of REQUIRED_USE,
diff --git a/pym/portage/tests/dep/test_get_required_use_flags.py b/pym/portage/tests/dep/test_get_required_use_flags.py
index 06f81106a..90e096c78 100644
--- a/pym/portage/tests/dep/test_get_required_use_flags.py
+++ b/pym/portage/tests/dep/test_get_required_use_flags.py
@@ -1,4 +1,4 @@
-# Copyright 2010 Gentoo Foundation
+# Copyright 2010-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from portage.tests import TestCase
@@ -13,6 +13,8 @@ class TestCheckRequiredUse(TestCase):
("|| ( a b c )", ["a", "b", "c"]),
("^^ ( a b c )", ["a", "b", "c"]),
+ ("?? ( a b c )", ["a", "b", "c"]),
+ ("?? ( )", []),
("|| ( a b ^^ ( d e f ) )", ["a", "b", "d", "e", "f"]),
("^^ ( a b || ( d e f ) )", ["a", "b", "d", "e", "f"]),