public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/portage commit in: pym/portage/dep/, pym/portage/tests/dep/, pym/_emerge/
@ 2011-02-04  1:41 zmedico
  0 siblings, 0 replies; only message in thread
From: zmedico @ 2011-02-04  1:41 UTC (permalink / raw
  To: gentoo-commits

commit:     e5e330ebbbf87c5141489809200c8a1cf6a00017
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Thu Feb  3 23:29:50 2011 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Thu Feb  3 23:43:28 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=e5e330ebbbf87c5141489809200c8a1cf6a00017

REQUIRED_USE: display unsatisfied part

This will fix bug #353234.

---
 pym/_emerge/depgraph.py                       |   15 ++++-
 pym/portage/dep/__init__.py                   |   92 +++++++++++++++++++++++--
 pym/portage/tests/dep/testCheckRequiredUse.py |   37 +++++++++-
 3 files changed, 136 insertions(+), 8 deletions(-)

diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index 05f1509..8b801f5 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -2598,9 +2598,22 @@ class depgraph(object):
 				noiselevel=-1)
 			writemsg_stdout("\n  The following REQUIRED_USE flag constraints " + \
 				"are unsatisfied:\n", noiselevel=-1)
+			reduced_noise = check_required_use(
+				pkg.metadata["REQUIRED_USE"],
+				self._pkg_use_enabled(pkg),
+				pkg.iuse.is_valid_flag).tounicode()
 			writemsg_stdout("    %s\n" % \
-				human_readable_required_use(pkg.metadata["REQUIRED_USE"]),
+				human_readable_required_use(reduced_noise),
 				noiselevel=-1)
+			normalized_required_use = \
+				" ".join(pkg.metadata["REQUIRED_USE"].split())
+			if reduced_noise != normalized_required_use:
+				writemsg_stdout("\n  The above constraints " + \
+					"are a subset of the following complete expression:\n",
+					noiselevel=-1)
+				writemsg_stdout("    %s\n" % \
+					human_readable_required_use(normalized_required_use),
+					noiselevel=-1)
 			writemsg_stdout("\n", noiselevel=-1)
 
 		elif show_missing_use:

diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py
index ad68815..7e9a18a 100644
--- a/pym/portage/dep/__init__.py
+++ b/pym/portage/dep/__init__.py
@@ -2062,6 +2062,63 @@ def get_required_use_flags(required_use):
 
 	return frozenset(used_flags)
 
+class _RequiredUseLeaf(object):
+
+	__slots__ = ('_satisfied', '_token')
+
+	def __init__(self, token, satisfied):
+		self._token = token
+		self._satisfied = satisfied
+
+	def tounicode(self):
+		return self._token
+
+class _RequiredUseBranch(object):
+
+	__slots__ = ('_children', '_operator', '_parent', '_satisfied')
+
+	def __init__(self, operator=None, parent=None):
+		self._children = []
+		self._operator = operator
+		self._parent = parent
+		self._satisfied = False
+
+	def __bool__(self):
+		return self._satisfied
+
+	def tounicode(self):
+
+		tokens = []
+		if self._operator is not None:
+			tokens.append(self._operator)
+
+		if self._parent is not None:
+			tokens.append("(")
+
+		complex_nesting = False
+		node = self
+		while node != None and not complex_nesting:
+			if node._operator in ("||", "^^"):
+				complex_nesting = True
+			else:
+				node = node._parent
+
+		if complex_nesting:
+			for child in self._children:
+				tokens.append(child.tounicode())
+		else:
+			for child in self._children:
+				if not child._satisfied:
+					tokens.append(child.tounicode())
+
+		if self._parent is not None:
+			tokens.append(")")
+
+		return " ".join(tokens)
+
+	if sys.hexversion < 0x3000000:
+		__nonzero__ = __bool__
+
 def check_required_use(required_use, use, iuse_match):
 	"""
 	Checks if the use flags listed in 'use' satisfy all
@@ -2108,10 +2165,17 @@ def check_required_use(required_use, use, iuse_match):
 	mysplit = required_use.split()
 	level = 0
 	stack = [[]]
+	tree = _RequiredUseBranch()
+	node = tree
 	need_bracket = False
 
 	for token in mysplit:
 		if token == "(":
+			if not need_bracket:
+				child = _RequiredUseBranch(parent=node)
+				node._children.append(child)
+				node = child
+
 			need_bracket = False
 			stack.append([])
 			level += 1
@@ -2127,18 +2191,27 @@ def check_required_use(required_use, use, iuse_match):
 					if stack[level][-1] in ("||", "^^"):
 						ignore = True
 						op = stack[level].pop()
-						stack[level].append(is_satisfied(op, l))
+						satisfied = is_satisfied(op, l)
+						stack[level].append(satisfied)
+						node._satisfied = satisfied
 					elif not isinstance(stack[level][-1], bool) and \
 						stack[level][-1][-1] == "?":
 						if is_active(stack[level][-1][:-1]):
 							op = stack[level].pop()
-							stack[level].append(is_satisfied(op, l))
+							satisfied = is_satisfied(op, l)
+							stack[level].append(satisfied)
+							node._satisfied = satisfied
 						else:
 							stack[level].pop()
+							node._satisfied = True
 						ignore = True
 
 				if l and not ignore:
-					stack[level].append(all(x for x in l))
+					satisfied = False not in l
+					stack[level].append(satisfied)
+					node._satisfied = satisfied
+
+				node = node._parent
 			else:
 				raise InvalidDependString(
 					_("malformed syntax: '%s'") % required_use)
@@ -2148,6 +2221,9 @@ def check_required_use(required_use, use, iuse_match):
 					_("malformed syntax: '%s'") % required_use)
 			need_bracket = True
 			stack[level].append(token)
+			child = _RequiredUseBranch(operator=token, parent=node)
+			node._children.append(child)
+			node = child
 		else:
 			if need_bracket or "(" in token or ")" in token or \
 				"|" in token or "^" in token:
@@ -2157,14 +2233,20 @@ def check_required_use(required_use, use, iuse_match):
 			if token[-1] == "?":
 				need_bracket = True
 				stack[level].append(token)
+				child = _RequiredUseBranch(operator=token, parent=node)
+				node._children.append(child)
+				node = child
 			else:
-				stack[level].append(is_active(token))
+				satisfied = is_active(token)
+				stack[level].append(satisfied)
+				node._children.append(_RequiredUseLeaf(token, satisfied))
 
 	if level != 0 or need_bracket:
 		raise InvalidDependString(
 			_("malformed syntax: '%s'") % required_use)
 
-	return (False not in stack[0])
+	tree._satisfied = False not in stack[0]
+	return tree
 
 def extract_affecting_use(mystr, atom):
 	"""

diff --git a/pym/portage/tests/dep/testCheckRequiredUse.py b/pym/portage/tests/dep/testCheckRequiredUse.py
index 4b67d62..0f7a299 100644
--- a/pym/portage/tests/dep/testCheckRequiredUse.py
+++ b/pym/portage/tests/dep/testCheckRequiredUse.py
@@ -1,4 +1,4 @@
-# Copyright 2010 Gentoo Foundation
+# Copyright 2010-2011 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from portage.tests import TestCase
@@ -103,9 +103,42 @@ class TestCheckRequiredUse(TestCase):
 		)
 
 		for required_use, use, iuse, expected in test_cases:
-			self.assertEqual(check_required_use(required_use, use, iuse.__contains__), \
+			self.assertEqual(bool(check_required_use(required_use, use, iuse.__contains__)), \
 				expected, required_use + ", USE = " + " ".join(use))
 
 		for required_use, use, iuse in test_cases_xfail:
 			self.assertRaisesMsg(required_use + ", USE = " + " ".join(use), \
 				InvalidDependString, check_required_use, required_use, use, iuse.__contains__)
+
+	def testCheckRequiredUseFilterSatisfied(self):
+		"""
+		Test filtering of satisfied parts of REQUIRED_USE,
+		in order to reduce noise for bug #353234.
+		"""
+		test_cases = (
+			(
+				"bindist? ( !amr !faac !win32codecs ) cdio? ( !cdparanoia !cddb ) dvdnav? ( dvd )",
+				("cdio", "cdparanoia"),
+				"cdio? ( !cdparanoia )"
+			),
+			(
+				"|| ( !amr !faac !win32codecs ) cdio? ( !cdparanoia !cddb ) ^^ ( foo bar )",
+				["cdio", "cdparanoia", "foo"],
+				"cdio? ( !cdparanoia )"
+			),
+			(
+				"^^ ( || ( a b ) c )",
+				("a", "b", "c"),
+				"^^ ( || ( a b ) c )"
+			),
+			(
+				"^^ ( || ( ( a b ) ) ( c ) )",
+				("a", "b", "c"),
+				"^^ ( || ( ( a b ) ) ( c ) )"
+			)
+		)
+		for required_use, use, expected in test_cases:
+			result = check_required_use(required_use, use, lambda k: True).tounicode()
+			self.assertEqual(result, expected,
+				"REQUIRED_USE = '%s', USE = '%s', '%s' != '%s'" % \
+				(required_use, " ".join(use), result, expected))



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2011-02-04  1:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-04  1:41 [gentoo-commits] proj/portage commit in: pym/portage/dep/, pym/portage/tests/dep/, pym/_emerge/ zmedico

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox