summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Luther <SebastianLuther@gmx.de>2010-08-18 15:33:55 +0200
committerZac Medico <zmedico@gentoo.org>2010-08-18 06:42:32 -0700
commit2296821c2b877bb70b0f04e1a621ed87fc1319a5 (patch)
tree16fc098a9a24aa411dbd8f36137f554f607c8312
parentfa03825f2827dca33ab8241004b677942be4bf46 (diff)
downloadportage-2296821c2b877bb70b0f04e1a621ed87fc1319a5.tar.gz
portage-2296821c2b877bb70b0f04e1a621ed87fc1319a5.tar.bz2
portage-2296821c2b877bb70b0f04e1a621ed87fc1319a5.zip
paren_reduce: Fix the same bug as in use_reduce
-rw-r--r--pym/portage/dep/__init__.py38
-rw-r--r--pym/portage/tests/dep/test_paren_reduce.py10
2 files changed, 38 insertions, 10 deletions
diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py
index ecce5d0c5..5b0473389 100644
--- a/pym/portage/dep/__init__.py
+++ b/pym/portage/dep/__init__.py
@@ -109,7 +109,7 @@ def paren_reduce(mystr):
level = 0
stack = [[]]
need_bracket = False
-
+
for token in mysplit:
if token == "(":
need_bracket = False
@@ -122,22 +122,46 @@ def paren_reduce(mystr):
if level > 0:
level -= 1
l = stack.pop()
+ is_single = (len(l) == 1 or (len(l)==2 and (l[0] == "||" or l[0][-1] == "?")))
+
+ def ends_in_any_of_dep(k):
+ return k>=0 and stack[k] and stack[k][-1] == "||"
+
+ def ends_in_operator(k):
+ return k>=0 and stack[k] and (stack[k][-1] == "||" or stack[k][-1][-1] == "?")
+
+ def special_append():
+ """
+ Use extend instead of append if possible. This kills all redundant brackets.
+ """
+ if is_single and (not stack[level] or not stack[level][-1][-1] == "?"):
+ if len(l) == 1 and isinstance(l[0], list):
+ # l = [[...]]
+ stack[level].extend(l[0])
+ else:
+ stack[level].extend(l)
+ else:
+ stack[level].append(l)
+
if l:
- if not stack[level] or (stack[level][-1] != "||" and not stack[level][-1][-1] == "?"):
- #Optimize: ( ( ... ) ) -> ( ... )
+ if not ends_in_any_of_dep(level-1) and not ends_in_operator(level):
+ #Optimize: ( ( ... ) ) -> ( ... ). Make sure there is no '||' hanging around.
stack[level].extend(l)
- elif len(l) == 1 and stack[level][-1] == "||":
+ elif not stack[level]:
+ #An '||' in the level above forces us to keep to brackets.
+ special_append()
+ elif len(l) == 1 and ends_in_any_of_dep(level):
#Optimize: || ( A ) -> A
stack[level].pop()
- stack[level].extend(l)
+ special_append()
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)
+ special_append()
else:
- stack[level].append(l)
+ special_append()
else:
if stack[level] and (stack[level][-1] == "||" or stack[level][-1][-1] == "?"):
stack[level].pop()
diff --git a/pym/portage/tests/dep/test_paren_reduce.py b/pym/portage/tests/dep/test_paren_reduce.py
index bd5f42584..6aac955c5 100644
--- a/pym/portage/tests/dep/test_paren_reduce.py
+++ b/pym/portage/tests/dep/test_paren_reduce.py
@@ -18,8 +18,7 @@ class TestParenReduce(TestCase):
( "|| ( A || ( B || ( C D ) E ) )", [ "||", ["A", "||", ["B", "||", ["C", "D"], "E"]] ]),
( "a? ( A )", ["a?", ["A"]]),
- ( "( || ( ( ( A ) B ) ) )", [ "||", ["A", "B"] ]),
- ( "( || ( || ( ( A ) B ) ) )", [ "||", ["A", "B"] ]),
+ ( "( || ( ( ( A ) B ) ) )", ["A", "B"]),
( "( || ( || ( ( A ) B ) ) )", [ "||", ["A", "B"] ]),
( "|| ( A )", ["A"]),
( "( || ( || ( || ( A ) foo? ( B ) ) ) )", [ "||", ["A", "foo?", ["B"] ]]),
@@ -28,6 +27,9 @@ class TestParenReduce(TestCase):
( "|| ( A ) || ( B )", ["A", "B"]),
( "foo? ( A ) foo? ( B )", ["foo?", ["A"], "foo?", ["B"]]),
+
+ ( "|| ( ( A B ) C )", [ "||", [ ["A", "B"], "C"] ]),
+ ( "|| ( ( A B ) ( C ) )", [ "||", [ ["A", "B"], "C"] ]),
)
test_cases_xfail = (
@@ -53,7 +55,9 @@ class TestParenReduce(TestCase):
)
for dep_str, expected_result in test_cases:
- self.assertEqual(paren_reduce(dep_str), expected_result)
+ self.assertEqual(paren_reduce(dep_str), expected_result,
+ "input: '%s' result: %s != %s" % (dep_str,
+ paren_reduce(dep_str), expected_result))
for dep_str in test_cases_xfail:
self.assertRaisesMsg(dep_str,