paren_reduce: Fix the same bug as in use_reduce
authorSebastian Luther <SebastianLuther@gmx.de>
Wed, 18 Aug 2010 13:33:55 +0000 (15:33 +0200)
committerZac Medico <zmedico@gentoo.org>
Wed, 18 Aug 2010 13:42:32 +0000 (06:42 -0700)
pym/portage/dep/__init__.py
pym/portage/tests/dep/test_paren_reduce.py

index ecce5d0c52ecd8571657124b36df3d1d942d734f..5b047338918a79995db3bda0656d529be6221064 100644 (file)
@@ -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()
index bd5f42584d093db0b95e9469a17671e3d2bb9434..6aac955c59a13280e3fc71d9f7e66ce3c271425a 100644 (file)
@@ -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,