summaryrefslogtreecommitdiffstats
path: root/pym
diff options
context:
space:
mode:
authorSebastian Luther <SebastianLuther@gmx.de>2010-08-12 10:59:33 +0200
committerZac Medico <zmedico@gentoo.org>2010-08-12 03:40:45 -0700
commit1df3eec53768c882f8747af4bb706642c50891d0 (patch)
tree6a18bf96461b0b5796b1c6e70e3b594998e46ac2 /pym
parent22ab3600b09fd1e4741454d221b5006a1a50efb1 (diff)
downloadportage-1df3eec53768c882f8747af4bb706642c50891d0.tar.gz
portage-1df3eec53768c882f8747af4bb706642c50891d0.tar.bz2
portage-1df3eec53768c882f8747af4bb706642c50891d0.zip
Add portage.dep.extract_affecting_use()
Diffstat (limited to 'pym')
-rw-r--r--pym/portage/dep/__init__.py103
-rw-r--r--pym/portage/tests/dep/testExtractAffectingUSE.py70
2 files changed, 173 insertions, 0 deletions
diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py
index 1b89afec0..f15b8a2d9 100644
--- a/pym/portage/dep/__init__.py
+++ b/pym/portage/dep/__init__.py
@@ -1458,3 +1458,106 @@ def check_required_use(required_use, use, iuse):
_("malformed syntax: '%s'") % required_use)
return (False not in stack[0])
+
+def extract_affecting_use(mystr, atom):
+ """
+ Take a dep string and an atom and return the use flags
+ that decide if the given atom is in effect.
+
+ Example usage:
+ >>> extract_use_cond('sasl? ( dev-libs/cyrus-sasl ) \
+ !minimal? ( cxx? ( dev-libs/cyrus-sasl ) )', 'dev-libs/cyrus-sasl')
+ (['sasl', 'minimal', 'cxx'])
+
+ @param dep: The dependency string
+ @type mystr: String
+ @param atom: The atom to get into effect
+ @type atom: String
+ @rtype: Tuple of two lists of strings
+ @return: List of use flags that need to be enabled, List of use flag that need to be disabled
+ """
+ mysplit = mystr.split()
+ level = 0
+ stack = [[]]
+ need_bracket = False
+ affecting_use = set()
+ atom_seen = False
+
+ def flag(conditional):
+ if conditional[0] == "!":
+ flag = conditional[1:-1]
+ else:
+ flag = conditional[:-1]
+
+ if not flag:
+ raise portage.exception.InvalidDependString(
+ _("malformed syntax: '%s'") % mystr)
+
+ return flag
+
+ for token in mysplit:
+ if token == "(":
+ need_bracket = False
+ stack.append([])
+ level += 1
+ elif token == ")":
+ if need_bracket:
+ raise portage.exception.InvalidDependString(
+ _("malformed syntax: '%s'") % mystr)
+ if level > 0:
+ level -= 1
+ l = stack.pop()
+
+ if l:
+ if not stack[level] or (stack[level][-1] != "||" and not stack[level][-1][-1] == "?"):
+ #Optimize: ( ( ... ) ) -> ( ... )
+ stack[level].extend(l)
+ elif len(l) == 1 and stack[level][-1] == "||":
+ #Optimize: || ( A ) -> A
+ stack[level].pop()
+ stack[level].extend(l)
+ elif len(l) == 2 and (l[0] == "||" or l[0][-1] == "?") and stack[level][-1] in (l[0], "||"):
+ #Optimize: || ( || ( ... ) ) -> || ( ... )
+ # foo? ( foo? ( ... ) ) -> foo? ( ... )
+ # || ( foo? ( ... ) ) -> foo? ( ... )
+ stack[level].pop()
+ stack[level].extend(l)
+ if l[0][-1] == "?":
+ affecting_use.add(flag(l[0]))
+ else:
+ if stack[level] and stack[level][-1][-1] == "?":
+ affecting_use.add(flag(stack[level][-1]))
+ stack[level].append(l)
+ else:
+ if stack[level] and (stack[level][-1] == "||" or stack[level][-1][-1] == "?"):
+ stack[level].pop()
+ else:
+ raise portage.exception.InvalidDependString(
+ _("malformed syntax: '%s'") % mystr)
+ elif token == "||":
+ if need_bracket:
+ raise portage.exception.InvalidDependString(
+ _("malformed syntax: '%s'") % mystr)
+ need_bracket = True
+ stack[level].append(token)
+ else:
+ if need_bracket or "(" in token or ")" in token or "|" in token:
+ raise portage.exception.InvalidDependString(
+ _("malformed syntax: '%s'") % mystr)
+
+ if token[-1] == "?":
+ need_bracket = True
+ stack[level].append(token)
+ elif token == atom:
+ atom_seen = True
+ stack[level].append(token)
+
+ if level != 0 or need_bracket:
+ raise portage.exception.InvalidDependString(
+ _("malformed syntax: '%s'") % mystr)
+
+ if not atom_seen:
+ raise portage.exception.IncorrectParameter(
+ _("extract_affecting_use: atom '%s' not in dep string: '%s'") % (atom, mystr))
+
+ return affecting_use
diff --git a/pym/portage/tests/dep/testExtractAffectingUSE.py b/pym/portage/tests/dep/testExtractAffectingUSE.py
new file mode 100644
index 000000000..ba904b927
--- /dev/null
+++ b/pym/portage/tests/dep/testExtractAffectingUSE.py
@@ -0,0 +1,70 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from portage.tests import TestCase
+from portage.dep import extract_affecting_use
+from portage.exception import InvalidDependString, IncorrectParameter
+
+class TestExtractAffectingUSE(TestCase):
+
+ def testExtractAffectingUSE(self):
+ test_cases = (
+ ("a? ( A ) !b? ( B ) !c? ( C ) d? ( D )", "A", ("a",)),
+ ("a? ( A ) !b? ( B ) !c? ( C ) d? ( D )", "B", ("b",)),
+ ("a? ( A ) !b? ( B ) !c? ( C ) d? ( D )", "C", ("c",)),
+ ("a? ( A ) !b? ( B ) !c? ( C ) d? ( D )", "D", ("d",)),
+
+ ("a? ( b? ( AB ) )", "AB", ("a", "b")),
+ ("a? ( b? ( c? ( ABC ) ) )", "ABC", ("a", "b", "c")),
+
+ ("a? ( A b? ( c? ( ABC ) AB ) )", "A", ("a",)),
+ ("a? ( A b? ( c? ( ABC ) AB ) )", "AB", ("a", "b")),
+ ("a? ( A b? ( c? ( ABC ) AB ) )", "ABC", ("a", "b", "c")),
+ ("a? ( A b? ( c? ( ABC ) AB ) ) X", "X", []),
+ ("X a? ( A b? ( c? ( ABC ) AB ) )", "X", []),
+
+ ("ab? ( || ( A B ) )", "A", ("ab",)),
+ ("!ab? ( || ( A B ) )", "B", ("ab",)),
+ ("ab? ( || ( A || ( b? ( || ( B C ) ) ) ) )", "A", ("ab",)),
+ ("ab? ( || ( A || ( b? ( || ( B C ) ) ) ) )", "B", ("ab", "b")),
+ ("ab? ( || ( A || ( b? ( || ( B C ) ) ) ) )", "C", ("ab", "b")),
+
+ ("( ab? ( || ( ( A ) || ( b? ( ( ( || ( B ( C ) ) ) ) ) ) ) ) )", "A", ("ab",)),
+ ("( ab? ( || ( ( A ) || ( b? ( ( ( || ( B ( C ) ) ) ) ) ) ) ) )", "B", ("ab", "b")),
+ ("( ab? ( || ( ( A ) || ( b? ( ( ( || ( B ( C ) ) ) ) ) ) ) ) )", "C", ("ab", "b")),
+ )
+
+ test_cases_xfail = (
+ ("? ( A )", "A"),
+ ("!? ( A )", "A"),
+ ("( A", "A"),
+ ("A )", "A"),
+
+ ("||( A B )", "A"),
+ ("|| (A B )", "A"),
+ ("|| ( A B)", "A"),
+ ("|| ( A B", "A"),
+ ("|| A B )", "A"),
+ ("|| A B", "A"),
+ ("|| ( A B ) )", "A"),
+ ("|| || B C", "A"),
+ ("|| ( A B || )", "A"),
+ ("a? A", "A"),
+ ("( || ( || || ( A ) foo? ( B ) ) )", "A"),
+ ("( || ( || bar? ( A ) foo? ( B ) ) )", "A"),
+
+ ("a? ( A )", "B"),
+ )
+
+ for dep, atom, expected in test_cases:
+ expected = set(expected)
+ result = extract_affecting_use(dep, atom)
+ fail_msg = "dep: " + dep + ", atom: " + atom + ", got: " + \
+ " ".join(sorted(result)) + ", expected: " + " ".join(sorted(expected))
+ self.assertEqual(result, expected, fail_msg)
+
+ for dep, atom in test_cases_xfail:
+ fail_msg = "dep: " + dep + ", atom: " + atom + ", got: " + \
+ " ".join(sorted(result)) + ", expected: " + " ".join(sorted(expected))
+ self.assertRaisesMsg(fail_msg, \
+ (InvalidDependString, IncorrectParameter), extract_affecting_use, dep, atom)