public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Fabian Groffen" <grobian@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage:prefix commit in: pym/portage/dep/, pym/portage/tests/dep/, pym/_emerge/
Date: Sat,  5 Feb 2011 12:25:03 +0000 (UTC)	[thread overview]
Message-ID: <c9ed39f98c62760333c9fe4d4ef5b8caa06a9e16.grobian@gentoo> (raw)

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

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 8f04c44..811eda6 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -2593,9 +2593,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))



                 reply	other threads:[~2011-02-05 12:25 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c9ed39f98c62760333c9fe4d4ef5b8caa06a9e16.grobian@gentoo \
    --to=grobian@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox