Gentoo Archives: gentoo-commits

From: Fabian Groffen <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:prefix commit in: pym/portage/dep/, pym/portage/tests/dep/, pym/_emerge/
Date: Sat, 05 Feb 2011 12:25:11
Message-Id: c9ed39f98c62760333c9fe4d4ef5b8caa06a9e16.grobian@gentoo
1 commit: c9ed39f98c62760333c9fe4d4ef5b8caa06a9e16
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Thu Feb 3 23:29:50 2011 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Thu Feb 3 23:29:50 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=c9ed39f9
7
8 REQUIRED_USE: display unsatisfied part
9
10 This will fix bug #353234.
11
12 ---
13 pym/_emerge/depgraph.py | 15 ++++-
14 pym/portage/dep/__init__.py | 92 +++++++++++++++++++++++--
15 pym/portage/tests/dep/testCheckRequiredUse.py | 37 +++++++++-
16 3 files changed, 136 insertions(+), 8 deletions(-)
17
18 diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
19 index 8f04c44..811eda6 100644
20 --- a/pym/_emerge/depgraph.py
21 +++ b/pym/_emerge/depgraph.py
22 @@ -2593,9 +2593,22 @@ class depgraph(object):
23 noiselevel=-1)
24 writemsg_stdout("\n The following REQUIRED_USE flag constraints " + \
25 "are unsatisfied:\n", noiselevel=-1)
26 + reduced_noise = check_required_use(
27 + pkg.metadata["REQUIRED_USE"],
28 + self._pkg_use_enabled(pkg),
29 + pkg.iuse.is_valid_flag).tounicode()
30 writemsg_stdout(" %s\n" % \
31 - human_readable_required_use(pkg.metadata["REQUIRED_USE"]),
32 + human_readable_required_use(reduced_noise),
33 noiselevel=-1)
34 + normalized_required_use = \
35 + " ".join(pkg.metadata["REQUIRED_USE"].split())
36 + if reduced_noise != normalized_required_use:
37 + writemsg_stdout("\n The above constraints " + \
38 + "are a subset of the following complete expression:\n",
39 + noiselevel=-1)
40 + writemsg_stdout(" %s\n" % \
41 + human_readable_required_use(normalized_required_use),
42 + noiselevel=-1)
43 writemsg_stdout("\n", noiselevel=-1)
44
45 elif show_missing_use:
46
47 diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py
48 index ad68815..7e9a18a 100644
49 --- a/pym/portage/dep/__init__.py
50 +++ b/pym/portage/dep/__init__.py
51 @@ -2062,6 +2062,63 @@ def get_required_use_flags(required_use):
52
53 return frozenset(used_flags)
54
55 +class _RequiredUseLeaf(object):
56 +
57 + __slots__ = ('_satisfied', '_token')
58 +
59 + def __init__(self, token, satisfied):
60 + self._token = token
61 + self._satisfied = satisfied
62 +
63 + def tounicode(self):
64 + return self._token
65 +
66 +class _RequiredUseBranch(object):
67 +
68 + __slots__ = ('_children', '_operator', '_parent', '_satisfied')
69 +
70 + def __init__(self, operator=None, parent=None):
71 + self._children = []
72 + self._operator = operator
73 + self._parent = parent
74 + self._satisfied = False
75 +
76 + def __bool__(self):
77 + return self._satisfied
78 +
79 + def tounicode(self):
80 +
81 + tokens = []
82 + if self._operator is not None:
83 + tokens.append(self._operator)
84 +
85 + if self._parent is not None:
86 + tokens.append("(")
87 +
88 + complex_nesting = False
89 + node = self
90 + while node != None and not complex_nesting:
91 + if node._operator in ("||", "^^"):
92 + complex_nesting = True
93 + else:
94 + node = node._parent
95 +
96 + if complex_nesting:
97 + for child in self._children:
98 + tokens.append(child.tounicode())
99 + else:
100 + for child in self._children:
101 + if not child._satisfied:
102 + tokens.append(child.tounicode())
103 +
104 + if self._parent is not None:
105 + tokens.append(")")
106 +
107 + return " ".join(tokens)
108 +
109 + if sys.hexversion < 0x3000000:
110 + __nonzero__ = __bool__
111 +
112 def check_required_use(required_use, use, iuse_match):
113 """
114 Checks if the use flags listed in 'use' satisfy all
115 @@ -2108,10 +2165,17 @@ def check_required_use(required_use, use, iuse_match):
116 mysplit = required_use.split()
117 level = 0
118 stack = [[]]
119 + tree = _RequiredUseBranch()
120 + node = tree
121 need_bracket = False
122
123 for token in mysplit:
124 if token == "(":
125 + if not need_bracket:
126 + child = _RequiredUseBranch(parent=node)
127 + node._children.append(child)
128 + node = child
129 +
130 need_bracket = False
131 stack.append([])
132 level += 1
133 @@ -2127,18 +2191,27 @@ def check_required_use(required_use, use, iuse_match):
134 if stack[level][-1] in ("||", "^^"):
135 ignore = True
136 op = stack[level].pop()
137 - stack[level].append(is_satisfied(op, l))
138 + satisfied = is_satisfied(op, l)
139 + stack[level].append(satisfied)
140 + node._satisfied = satisfied
141 elif not isinstance(stack[level][-1], bool) and \
142 stack[level][-1][-1] == "?":
143 if is_active(stack[level][-1][:-1]):
144 op = stack[level].pop()
145 - stack[level].append(is_satisfied(op, l))
146 + satisfied = is_satisfied(op, l)
147 + stack[level].append(satisfied)
148 + node._satisfied = satisfied
149 else:
150 stack[level].pop()
151 + node._satisfied = True
152 ignore = True
153
154 if l and not ignore:
155 - stack[level].append(all(x for x in l))
156 + satisfied = False not in l
157 + stack[level].append(satisfied)
158 + node._satisfied = satisfied
159 +
160 + node = node._parent
161 else:
162 raise InvalidDependString(
163 _("malformed syntax: '%s'") % required_use)
164 @@ -2148,6 +2221,9 @@ def check_required_use(required_use, use, iuse_match):
165 _("malformed syntax: '%s'") % required_use)
166 need_bracket = True
167 stack[level].append(token)
168 + child = _RequiredUseBranch(operator=token, parent=node)
169 + node._children.append(child)
170 + node = child
171 else:
172 if need_bracket or "(" in token or ")" in token or \
173 "|" in token or "^" in token:
174 @@ -2157,14 +2233,20 @@ def check_required_use(required_use, use, iuse_match):
175 if token[-1] == "?":
176 need_bracket = True
177 stack[level].append(token)
178 + child = _RequiredUseBranch(operator=token, parent=node)
179 + node._children.append(child)
180 + node = child
181 else:
182 - stack[level].append(is_active(token))
183 + satisfied = is_active(token)
184 + stack[level].append(satisfied)
185 + node._children.append(_RequiredUseLeaf(token, satisfied))
186
187 if level != 0 or need_bracket:
188 raise InvalidDependString(
189 _("malformed syntax: '%s'") % required_use)
190
191 - return (False not in stack[0])
192 + tree._satisfied = False not in stack[0]
193 + return tree
194
195 def extract_affecting_use(mystr, atom):
196 """
197
198 diff --git a/pym/portage/tests/dep/testCheckRequiredUse.py b/pym/portage/tests/dep/testCheckRequiredUse.py
199 index 4b67d62..0f7a299 100644
200 --- a/pym/portage/tests/dep/testCheckRequiredUse.py
201 +++ b/pym/portage/tests/dep/testCheckRequiredUse.py
202 @@ -1,4 +1,4 @@
203 -# Copyright 2010 Gentoo Foundation
204 +# Copyright 2010-2011 Gentoo Foundation
205 # Distributed under the terms of the GNU General Public License v2
206
207 from portage.tests import TestCase
208 @@ -103,9 +103,42 @@ class TestCheckRequiredUse(TestCase):
209 )
210
211 for required_use, use, iuse, expected in test_cases:
212 - self.assertEqual(check_required_use(required_use, use, iuse.__contains__), \
213 + self.assertEqual(bool(check_required_use(required_use, use, iuse.__contains__)), \
214 expected, required_use + ", USE = " + " ".join(use))
215
216 for required_use, use, iuse in test_cases_xfail:
217 self.assertRaisesMsg(required_use + ", USE = " + " ".join(use), \
218 InvalidDependString, check_required_use, required_use, use, iuse.__contains__)
219 +
220 + def testCheckRequiredUseFilterSatisfied(self):
221 + """
222 + Test filtering of satisfied parts of REQUIRED_USE,
223 + in order to reduce noise for bug #353234.
224 + """
225 + test_cases = (
226 + (
227 + "bindist? ( !amr !faac !win32codecs ) cdio? ( !cdparanoia !cddb ) dvdnav? ( dvd )",
228 + ("cdio", "cdparanoia"),
229 + "cdio? ( !cdparanoia )"
230 + ),
231 + (
232 + "|| ( !amr !faac !win32codecs ) cdio? ( !cdparanoia !cddb ) ^^ ( foo bar )",
233 + ["cdio", "cdparanoia", "foo"],
234 + "cdio? ( !cdparanoia )"
235 + ),
236 + (
237 + "^^ ( || ( a b ) c )",
238 + ("a", "b", "c"),
239 + "^^ ( || ( a b ) c )"
240 + ),
241 + (
242 + "^^ ( || ( ( a b ) ) ( c ) )",
243 + ("a", "b", "c"),
244 + "^^ ( || ( ( a b ) ) ( c ) )"
245 + )
246 + )
247 + for required_use, use, expected in test_cases:
248 + result = check_required_use(required_use, use, lambda k: True).tounicode()
249 + self.assertEqual(result, expected,
250 + "REQUIRED_USE = '%s', USE = '%s', '%s' != '%s'" % \
251 + (required_use, " ".join(use), result, expected))