summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pym/portage/dep/__init__.py52
-rw-r--r--pym/portage/tests/dep/test_use_reduce.py100
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(