From 860fdf6f8c00f9ee256434cf8b52811ffa4c07b3 Mon Sep 17 00:00:00 2001 From: Sebastian Luther Date: Fri, 15 Oct 2010 10:11:00 +0200 Subject: use_reduce: Fully reduce complex || constructs. This will fix bug 340973. --- pym/portage/dep/__init__.py | 52 ++++++++++++---- pym/portage/tests/dep/test_use_reduce.py | 100 +++++++++++++++++++++++-------- 2 files changed, 116 insertions(+), 36 deletions(-) diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py index 4de9c8422..da67dd1fe 100644 --- a/pym/portage/dep/__init__.py +++ b/pym/portage/dep/__init__.py @@ -378,7 +378,10 @@ def use_reduce(depstr, uselist=[], masklist=[], matchall=False, excludeall=[], i if level > 0: level -= 1 l = stack.pop() - is_single = (len(l) == 1 or (len(l)==2 and l[0] == "||")) + + is_single = len(l) == 1 or \ + (opconvert and l and l[0] == "||") or \ + (not opconvert and len(l)==2 and l[0] == "||") ignore = False if flat: @@ -411,17 +414,45 @@ def use_reduce(depstr, uselist=[], masklist=[], matchall=False, excludeall=[], i def ends_in_any_of_dep(k): return k>=0 and stack[k] and stack[k][-1] == "||" + def starts_with_any_of_dep(k): + #'ends_in_any_of_dep' for opconvert + return k>=0 and stack[k] and stack[k][0] == "||" + + def last_any_of_operator_level(k): + #Returns the level of the last || operator if it is ineffect for + #the current level. It is not in effect, if there is a level, that + #ends in a non-operator. This is almost equivalent to stack[level][-1]=="||", + #expect that it skips empty levels. + while k>=0: + if stack[k]: + if stack[k][-1] == "||": + return k + elif stack[k][-1][-1] != "?": + return -1 + k -= 1 + return -1 + def special_append(): """ Use extend instead of append if possible. This kills all redundant brackets. """ if is_single: - if len(l) == 1 and isinstance(l[0], list): + #Either [A], [[...]] or [|| [...]] + if l[0] == "||" and ends_in_any_of_dep(level-1): + if opconvert: + stack[level].extend(l[1:]) + else: + stack[level].extend(l[1]) + elif len(l) == 1 and isinstance(l[0], list): # l = [[...]] - stack[level].extend(l[0]) + last = last_any_of_operator_level(level) + if last == -1: + stack[level].extend(l[0]) + else: + stack[level].append(l[0]) else: stack[level].extend(l) - else: + else: stack[level].append(l) if l and not ignore: @@ -437,15 +468,16 @@ def use_reduce(depstr, uselist=[], masklist=[], matchall=False, excludeall=[], i #Optimize: || ( A ) -> A, || ( || ( ... ) ) -> || ( ... ) stack[level].pop() special_append() + elif ends_in_any_of_dep(level) and ends_in_any_of_dep(level-1): + #Optimize: || ( A || ( B C ) ) -> || ( A B C ) + stack[level].pop() + stack[level].extend(l) else: - if opconvert and ends_in_any_of_dep(level): + if opconvert and starts_with_any_of_dep(level): #In opconvert mode, we have to move the operator from the level #above into the current list. - if l[0] == '||': - stack[level].extend(l[1:]) - else: - stack[level].pop() - stack[level].append(["||"] + l) + stack[level].pop() + stack[level].extend(["||"] + l) else: special_append() diff --git a/pym/portage/tests/dep/test_use_reduce.py b/pym/portage/tests/dep/test_use_reduce.py index 05c580646..83735e1fd 100644 --- a/pym/portage/tests/dep/test_use_reduce.py +++ b/pym/portage/tests/dep/test_use_reduce.py @@ -180,13 +180,13 @@ class UseReduce(TestCase): expected_result = [ "||", [ ["A", "B"], "C"] ]), UseReduceTestCase( "|| ( A || ( B C ) )", - expected_result = [ "||", ["A", "||", ["B", "C"]]]), + expected_result = [ "||", ["A", "B", "C"]]), UseReduceTestCase( "|| ( A || ( B C D ) )", - expected_result = [ "||", ["A", "||", ["B", "C", "D"]] ]), + expected_result = [ "||", ["A", "B", "C", "D"] ]), UseReduceTestCase( "|| ( A || ( B || ( C D ) E ) )", - expected_result = [ "||", ["A", "||", ["B", "||", ["C", "D"], "E"]] ]), + expected_result = [ "||", ["A", "B", "C", "D", "E"] ]), UseReduceTestCase( "( || ( ( ( A ) B ) ) )", expected_result = ["A", "B"] ), @@ -276,22 +276,22 @@ class UseReduce(TestCase): UseReduceTestCase( "|| ( A B )", opconvert = True, - expected_result = [ ["||", "A", "B"] ]), + expected_result = ["||", "A", "B"]), UseReduceTestCase( "|| ( ( A B ) C )", opconvert = True, - expected_result = [ [ "||", ["A", "B"], "C" ] ]), + expected_result = [ "||", ["A", "B"], "C" ]), UseReduceTestCase( "|| ( A || ( B C ) )", opconvert = True, - expected_result = [ ["||", "A", ["||", "B", "C"]] ]), + expected_result = ["||", "A", "B", "C"]), UseReduceTestCase( "|| ( A || ( B C D ) )", opconvert = True, - expected_result = [ ["||", "A", ["||", "B", "C", "D"]] ]), + expected_result = ["||", "A", "B", "C", "D"]), UseReduceTestCase( "|| ( A || ( B || ( C D ) E ) )", - expected_result = [ "||", ["A", "||", ["B", "||", ["C", "D"], "E"]] ]), + expected_result = [ "||", ["A", "B", "C", "D", "E"] ]), UseReduceTestCase( "( || ( ( ( A ) B ) ) )", opconvert = True, @@ -348,24 +348,72 @@ class UseReduce(TestCase): opconvert = True, expected_result = ["||", "A", "B"]), - # [['||', ['A', 'B'], '||', 'C', 'D']] != ['||', ['A', 'B'], 'C', 'D'] - #UseReduceTestCase( - # "|| ( ( A B ) foo? ( || ( C D ) ) )", - # uselist = ["foo"], - # opconvert = True, - # expected_result = ['||', ['A', 'B'], 'C', 'D']), - - # ['||', [['A', 'B'], '||', ['C', 'D']]] != ['||', [['A', 'B'], 'C', 'D']] - #UseReduceTestCase( - # "|| ( ( A B ) foo? ( || ( C D ) ) )", - # uselist = ["foo"], - # opconvert = False, - # expected_result = ['||', [['A', 'B'], 'C', 'D']]), - - # ['||', [['A', 'B'], '||', ['C', 'D']]] != ['||', [['A', 'B'], 'C', 'D']] - #UseReduceTestCase( - # "|| ( ( A B ) || ( C D ) )", - # expected_result = ['||', [['A', 'B'], 'C', 'D']]), + UseReduceTestCase( + "|| ( ( A B ) foo? ( || ( C D ) ) )", + uselist = ["foo"], + opconvert = True, + expected_result = ['||', ['A', 'B'], 'C', 'D']), + + UseReduceTestCase( + "|| ( ( A B ) foo? ( || ( C D ) ) )", + uselist = ["foo"], + opconvert = False, + expected_result = ['||', [['A', 'B'], 'C', 'D']]), + + UseReduceTestCase( + "|| ( ( A B ) || ( C D ) )", + expected_result = ['||', [['A', 'B'], 'C', 'D']]), + + UseReduceTestCase( + "|| ( ( A B ) || ( C D || ( E ( F G ) || ( H ) ) ) )", + expected_result = ['||', [['A', 'B'], 'C', 'D', 'E', ['F', 'G'], 'H']]), + + UseReduceTestCase( + "|| ( foo? ( A B ) )", + uselist = ["foo"], + expected_result = ['A', 'B']), + + UseReduceTestCase( + "|| ( || ( foo? ( A B ) ) )", + uselist = ["foo"], + expected_result = ['A', 'B']), + + UseReduceTestCase( + "|| ( || ( || ( a? ( b? ( c? ( || ( || ( || ( d? ( e? ( f? ( A B ) ) ) ) ) ) ) ) ) ) ) )", + uselist = ["a", "b", "c", "d", "e", "f"], + expected_result = ['A', 'B']), + + UseReduceTestCase( + "|| ( || ( ( || ( a? ( ( b? ( c? ( || ( || ( || ( ( d? ( e? ( f? ( A B ) ) ) ) ) ) ) ) ) ) ) ) ) ) )", + uselist = ["a", "b", "c", "d", "e", "f"], + expected_result = ['A', 'B']), + + UseReduceTestCase( + "|| ( ( A ( || ( B ) ) ) )", + expected_result = ['A', 'B']), + + UseReduceTestCase( + "|| ( ( A B ) || ( foo? ( bar? ( ( C D || ( baz? ( E ) ( F G ) || ( H ) ) ) ) ) ) )", + uselist = ["foo", "bar", "baz"], + expected_result = ['||', [['A', 'B'], 'C', 'D', '||', ['E', ['F', 'G'], 'H']]]), + + UseReduceTestCase( + "|| ( foo? ( A B ) )", + uselist = ["foo"], + opconvert=True, + expected_result = ['A', 'B']), + + UseReduceTestCase( + "|| ( || ( foo? ( A B ) ) )", + uselist = ["foo"], + opconvert=True, + expected_result = ['A', 'B']), + + UseReduceTestCase( + "|| ( || ( || ( a? ( b? ( c? ( || ( || ( || ( d? ( e? ( f? ( A B ) ) ) ) ) ) ) ) ) ) ) )", + uselist = ["a", "b", "c", "d", "e", "f"], + opconvert=True, + expected_result = ['A', 'B']), #flat test UseReduceTestCase( -- cgit v1.2.3-1-g7c22