Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: bin/, pym/portage/, pym/portage/dep/, pym/portage/tests/dep/, pym/_emerge/
Date: Mon, 27 Aug 2012 22:17:15
Message-Id: 1346105609.ac843c3df2210566b559dc57c5fb657e20933a58.zmedico@gentoo
1 commit: ac843c3df2210566b559dc57c5fb657e20933a58
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Mon Aug 27 22:13:29 2012 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Mon Aug 27 22:13:29 2012 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=ac843c3d
7
8 EAPI 5: REQUIRED_USE at-most-one-of ?? operator
9
10 See bug #354219 and the PMS patch:
11 http://git.overlays.gentoo.org/gitweb/?p=proj/pms.git;a=commit;h=1c2dff2df2305aff88a734e3a2716de1bb69f3b6
12
13 ---
14 bin/repoman | 2 +-
15 pym/_emerge/Package.py | 2 +-
16 pym/portage/dep/__init__.py | 47 +++++++++++++------
17 pym/portage/eapi.py | 6 ++-
18 pym/portage/tests/dep/testCheckRequiredUse.py | 16 ++++++-
19 .../tests/dep/test_get_required_use_flags.py | 4 +-
20 6 files changed, 57 insertions(+), 20 deletions(-)
21
22 diff --git a/bin/repoman b/bin/repoman
23 index b50fac8..dd065c8 100755
24 --- a/bin/repoman
25 +++ b/bin/repoman
26 @@ -2028,7 +2028,7 @@ for x in effective_scanlist:
27 " not supported with EAPI='%s'" % (eapi,))
28 try:
29 portage.dep.check_required_use(required_use, (),
30 - pkg.iuse.is_valid_flag)
31 + pkg.iuse.is_valid_flag, eapi=eapi)
32 except portage.exception.InvalidDependString as e:
33 stats["REQUIRED_USE.syntax"] = stats["REQUIRED_USE.syntax"] + 1
34 fails["REQUIRED_USE.syntax"].append(
35
36 diff --git a/pym/_emerge/Package.py b/pym/_emerge/Package.py
37 index 85fc597..2087cbf 100644
38 --- a/pym/_emerge/Package.py
39 +++ b/pym/_emerge/Package.py
40 @@ -228,7 +228,7 @@ class Package(Task):
41 else:
42 try:
43 check_required_use(v, (),
44 - self.iuse.is_valid_flag)
45 + self.iuse.is_valid_flag, eapi=eapi)
46 except InvalidDependString as e:
47 # Force unicode format string for python-2.x safety,
48 # ensuring that PortageException.__unicode__() is used
49
50 diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py
51 index e547deb..b7bb46f 100644
52 --- a/pym/portage/dep/__init__.py
53 +++ b/pym/portage/dep/__init__.py
54 @@ -2314,9 +2314,9 @@ def match_from_list(mydep, candidate_list):
55 return mylist
56
57 def human_readable_required_use(required_use):
58 - return required_use.replace("^^", "exactly-one-of").replace("||", "any-of")
59 + return required_use.replace("^^", "exactly-one-of").replace("||", "any-of").replace("??", "at-most-one-of")
60
61 -def get_required_use_flags(required_use):
62 +def get_required_use_flags(required_use, eapi=None):
63 """
64 Returns a set of use flags that are used in the given REQUIRED_USE string
65
66 @@ -2326,6 +2326,12 @@ def get_required_use_flags(required_use):
67 @return: Set of use flags that are used in the given REQUIRED_USE string
68 """
69
70 + eapi_attrs = _get_eapi_attrs(eapi)
71 + if eapi_attrs.required_use_at_most_one_of:
72 + valid_operators = ("||", "^^", "??")
73 + else:
74 + valid_operators = ("||", "^^")
75 +
76 mysplit = required_use.split()
77 level = 0
78 stack = [[]]
79 @@ -2354,7 +2360,7 @@ def get_required_use_flags(required_use):
80 l = stack.pop()
81 ignore = False
82 if stack[level]:
83 - if stack[level][-1] in ("||", "^^") or \
84 + if stack[level][-1] in valid_operators or \
85 (not isinstance(stack[level][-1], bool) and \
86 stack[level][-1][-1] == "?"):
87 ignore = True
88 @@ -2366,15 +2372,14 @@ def get_required_use_flags(required_use):
89 else:
90 raise InvalidDependString(
91 _("malformed syntax: '%s'") % required_use)
92 - elif token in ("||", "^^"):
93 + elif token in valid_operators:
94 if need_bracket:
95 raise InvalidDependString(
96 _("malformed syntax: '%s'") % required_use)
97 need_bracket = True
98 stack[level].append(token)
99 else:
100 - if need_bracket or "(" in token or ")" in token or \
101 - "|" in token or "^" in token:
102 + if need_bracket:
103 raise InvalidDependString(
104 _("malformed syntax: '%s'") % required_use)
105
106 @@ -2429,7 +2434,7 @@ class _RequiredUseBranch(object):
107 complex_nesting = False
108 node = self
109 while node != None and not complex_nesting:
110 - if node._operator in ("||", "^^"):
111 + if node._operator in ("||", "^^", "??"):
112 complex_nesting = True
113 else:
114 node = node._parent
115 @@ -2450,7 +2455,7 @@ class _RequiredUseBranch(object):
116 if sys.hexversion < 0x3000000:
117 __nonzero__ = __bool__
118
119 -def check_required_use(required_use, use, iuse_match):
120 +def check_required_use(required_use, use, iuse_match, eapi=None):
121 """
122 Checks if the use flags listed in 'use' satisfy all
123 constraints specified in 'constraints'.
124 @@ -2466,6 +2471,12 @@ def check_required_use(required_use, use, iuse_match):
125 @return: Indicates if REQUIRED_USE constraints are satisfied
126 """
127
128 + eapi_attrs = _get_eapi_attrs(eapi)
129 + if eapi_attrs.required_use_at_most_one_of:
130 + valid_operators = ("||", "^^", "??")
131 + else:
132 + valid_operators = ("||", "^^")
133 +
134 def is_active(token):
135 if token.startswith("!"):
136 flag = token[1:]
137 @@ -2475,6 +2486,11 @@ def check_required_use(required_use, use, iuse_match):
138 is_negated = False
139
140 if not flag or not iuse_match(flag):
141 + if not eapi_attrs.required_use_at_most_one_of and flag == "?":
142 + msg = _("Operator '??' is not supported with EAPI '%s'") \
143 + % (eapi,)
144 + e = InvalidData(msg, category='EAPI.incompatible')
145 + raise InvalidDependString(msg, errors=(e,))
146 msg = _("USE flag '%s' is not in IUSE") \
147 % (flag,)
148 e = InvalidData(msg, category='IUSE.missing')
149 @@ -2492,6 +2508,8 @@ def check_required_use(required_use, use, iuse_match):
150 return (True in argument)
151 elif operator == "^^":
152 return (argument.count(True) == 1)
153 + elif operator == "??":
154 + return (argument.count(True) <= 1)
155 elif operator[-1] == "?":
156 return (False not in argument)
157
158 @@ -2521,7 +2539,7 @@ def check_required_use(required_use, use, iuse_match):
159 l = stack.pop()
160 op = None
161 if stack[level]:
162 - if stack[level][-1] in ("||", "^^"):
163 + if stack[level][-1] in valid_operators:
164 op = stack[level].pop()
165 satisfied = is_satisfied(op, l)
166 stack[level].append(satisfied)
167 @@ -2550,7 +2568,7 @@ def check_required_use(required_use, use, iuse_match):
168 stack[level].append(satisfied)
169
170 if len(node._children) <= 1 or \
171 - node._parent._operator not in ("||", "^^"):
172 + node._parent._operator not in valid_operators:
173 last_node = node._parent._children.pop()
174 if last_node is not node:
175 raise AssertionError(
176 @@ -2566,7 +2584,7 @@ def check_required_use(required_use, use, iuse_match):
177 raise AssertionError(
178 "node is not last child of parent")
179
180 - elif len(node._children) == 1 and op in ("||", "^^"):
181 + elif len(node._children) == 1 and op in valid_operators:
182 last_node = node._parent._children.pop()
183 if last_node is not node:
184 raise AssertionError(
185 @@ -2576,7 +2594,7 @@ def check_required_use(required_use, use, iuse_match):
186 node._children[0]._parent = node._parent
187 node = node._children[0]
188 if node._operator is None and \
189 - node._parent._operator not in ("||", "^^"):
190 + node._parent._operator not in valid_operators:
191 last_node = node._parent._children.pop()
192 if last_node is not node:
193 raise AssertionError(
194 @@ -2590,7 +2608,7 @@ def check_required_use(required_use, use, iuse_match):
195 else:
196 raise InvalidDependString(
197 _("malformed syntax: '%s'") % required_use)
198 - elif token in ("||", "^^"):
199 + elif token in valid_operators:
200 if need_bracket:
201 raise InvalidDependString(
202 _("malformed syntax: '%s'") % required_use)
203 @@ -2600,8 +2618,7 @@ def check_required_use(required_use, use, iuse_match):
204 node._children.append(child)
205 node = child
206 else:
207 - if need_bracket or "(" in token or ")" in token or \
208 - "|" in token or "^" in token:
209 + if need_bracket:
210 raise InvalidDependString(
211 _("malformed syntax: '%s'") % required_use)
212
213
214 diff --git a/pym/portage/eapi.py b/pym/portage/eapi.py
215 index a5ef301..b701d02 100644
216 --- a/pym/portage/eapi.py
217 +++ b/pym/portage/eapi.py
218 @@ -56,6 +56,9 @@ def eapi_has_dosed_dohard(eapi):
219 def eapi_has_required_use(eapi):
220 return eapi not in ("0", "1", "2", "3")
221
222 +def eapi_has_required_use_at_most_one_of(eapi):
223 + return eapi not in ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
224 +
225 def eapi_has_use_dep_defaults(eapi):
226 return eapi not in ("0", "1", "2", "3")
227
228 @@ -70,7 +73,7 @@ def eapi_allows_dots_in_use_flags(eapi):
229
230 _eapi_attrs = collections.namedtuple('_eapi_attrs',
231 'dots_in_PN dots_in_use_flags iuse_defaults '
232 - 'repo_deps required_use slot_abi slot_deps '
233 + 'repo_deps required_use required_use_at_most_one_of slot_abi slot_deps '
234 'src_uri_arrows strong_blocks use_deps use_dep_defaults')
235
236 _eapi_attrs_cache = {}
237 @@ -97,6 +100,7 @@ def _get_eapi_attrs(eapi):
238 iuse_defaults = (eapi is None or eapi_has_iuse_defaults(eapi)),
239 repo_deps = (eapi is None or eapi_has_repo_deps(eapi)),
240 required_use = (eapi is None or eapi_has_required_use(eapi)),
241 + required_use_at_most_one_of = (eapi is None or eapi_has_required_use_at_most_one_of(eapi)),
242 slot_deps = (eapi is None or eapi_has_slot_deps(eapi)),
243 slot_abi = (eapi is None or eapi_has_slot_abi(eapi)),
244 src_uri_arrows = (eapi is None or eapi_has_src_uri_arrows(eapi)),
245
246 diff --git a/pym/portage/tests/dep/testCheckRequiredUse.py b/pym/portage/tests/dep/testCheckRequiredUse.py
247 index 54791e0..d85ad92 100644
248 --- a/pym/portage/tests/dep/testCheckRequiredUse.py
249 +++ b/pym/portage/tests/dep/testCheckRequiredUse.py
250 @@ -1,4 +1,4 @@
251 -# Copyright 2010-2011 Gentoo Foundation
252 +# Copyright 2010-2012 Gentoo Foundation
253 # Distributed under the terms of the GNU General Public License v2
254
255 from portage.tests import TestCase
256 @@ -18,6 +18,11 @@ class TestCheckRequiredUse(TestCase):
257 ( "^^ ( a b )", ["a"], ["a", "b"], True),
258 ( "^^ ( a b )", ["b"], ["a", "b"], True),
259 ( "^^ ( a b )", ["a", "b"], ["a", "b"], False),
260 + ( "?? ( a b )", ["a", "b"], ["a", "b"], False),
261 + ( "?? ( a b )", ["a"], ["a", "b"], True),
262 + ( "?? ( a b )", ["b"], ["a", "b"], True),
263 + ( "?? ( a b )", [], ["a", "b"], True),
264 + ( "?? ( )", [], [], True),
265
266 ( "^^ ( || ( a b ) c )", [], ["a", "b", "c"], False),
267 ( "^^ ( || ( a b ) c )", ["a"], ["a", "b", "c"], True),
268 @@ -102,6 +107,10 @@ class TestCheckRequiredUse(TestCase):
269 ( "^^ ( || ( a b ) ) ^^ ( b c ) )", [], ["a", "b", "c"]),
270 )
271
272 + test_cases_xfail_eapi = (
273 + ( "?? ( a b )", [], ["a", "b"], "4"),
274 + )
275 +
276 for required_use, use, iuse, expected in test_cases:
277 self.assertEqual(bool(check_required_use(required_use, use, iuse.__contains__)), \
278 expected, required_use + ", USE = " + " ".join(use))
279 @@ -110,6 +119,11 @@ class TestCheckRequiredUse(TestCase):
280 self.assertRaisesMsg(required_use + ", USE = " + " ".join(use), \
281 InvalidDependString, check_required_use, required_use, use, iuse.__contains__)
282
283 + for required_use, use, iuse, eapi in test_cases_xfail_eapi:
284 + self.assertRaisesMsg(required_use + ", USE = " + " ".join(use), \
285 + InvalidDependString, check_required_use, required_use, use,
286 + iuse.__contains__, eapi=eapi)
287 +
288 def testCheckRequiredUseFilterSatisfied(self):
289 """
290 Test filtering of satisfied parts of REQUIRED_USE,
291
292 diff --git a/pym/portage/tests/dep/test_get_required_use_flags.py b/pym/portage/tests/dep/test_get_required_use_flags.py
293 index 06f8110..90e096c 100644
294 --- a/pym/portage/tests/dep/test_get_required_use_flags.py
295 +++ b/pym/portage/tests/dep/test_get_required_use_flags.py
296 @@ -1,4 +1,4 @@
297 -# Copyright 2010 Gentoo Foundation
298 +# Copyright 2010-2012 Gentoo Foundation
299 # Distributed under the terms of the GNU General Public License v2
300
301 from portage.tests import TestCase
302 @@ -13,6 +13,8 @@ class TestCheckRequiredUse(TestCase):
303
304 ("|| ( a b c )", ["a", "b", "c"]),
305 ("^^ ( a b c )", ["a", "b", "c"]),
306 + ("?? ( a b c )", ["a", "b", "c"]),
307 + ("?? ( )", []),
308
309 ("|| ( a b ^^ ( d e f ) )", ["a", "b", "d", "e", "f"]),
310 ("^^ ( a b || ( d e f ) )", ["a", "b", "d", "e", "f"]),