12
12
logger = logging .getLogger (__name__ )
13
13
14
14
15
- def is_same_condition (a : Any , b : Any ) -> bool :
15
+ def get_condition (node : Any ) -> str | None :
16
+ if isinstance (node , dict ) and "if" in node :
17
+ return node ["if" ].strip ()
18
+ return None
19
+
20
+
21
+ def is_same_condition (a : str , b : str ) -> bool :
22
+ return a == b
23
+
24
+
25
+ def is_single_expression (condition : str ) -> bool :
26
+ return not any (f" { x } " in condition for x in ("and" , "or" , "if" ))
27
+
28
+
29
+ def is_negated_condition (a : str , b : str ) -> bool :
30
+ # we only handle negating trivial expressions
31
+ if not all (map (is_single_expression , (a , b ))):
32
+ return False
33
+
34
+ a_not = a .startswith ("not" )
35
+ b_not = b .startswith ("not" )
16
36
return (
17
- isinstance (a , dict )
18
- and isinstance (b , dict )
19
- and "if" in a
20
- and "if" in b
21
- and a ["if" ] == b ["if" ]
37
+ a_not != b_not
38
+ and a .removeprefix ("not" ).lstrip () == b .removeprefix ("not" ).lstrip ()
22
39
)
23
40
24
41
25
- def fold_branch (source : Any , dest : Any , branch : str ) -> None :
42
+ def fold_branch (source : Any , dest : Any , branch : str , dest_branch : str ) -> None :
26
43
if branch not in source :
27
44
return
45
+
28
46
source_l = source [branch ]
29
47
if isinstance (source_l , str ):
48
+ if dest_branch not in dest :
49
+ # special-case: do not expand a single string to list
50
+ dest [dest_branch ] = source_l
51
+ return
30
52
source_l = [source_l ]
31
53
32
- if branch not in dest :
33
- dest [branch ] = []
34
- elif isinstance (dest [branch ], str ):
35
- dest [branch ] = [dest [branch ]]
36
- dest [branch ].extend (source_l )
54
+ if dest_branch not in dest :
55
+ dest [dest_branch ] = []
56
+ elif isinstance (dest [dest_branch ], str ):
57
+ dest [dest_branch ] = [dest [dest_branch ]]
58
+ dest [dest_branch ].extend (source_l )
37
59
38
60
39
61
def combine_conditions (node : Any ):
@@ -45,9 +67,18 @@ def combine_conditions(node: Any):
45
67
# iterate in reverse order, so we can remove elements on the fly
46
68
# start at index 1, since we can only fold to the previous node
47
69
for i in reversed (range (1 , len (node ))):
48
- if is_same_condition (node [i ], node [i - 1 ]):
49
- fold_branch (node [i ], node [i - 1 ], "then" )
50
- fold_branch (node [i ], node [i - 1 ], "else" )
70
+ node_cond = get_condition (node [i ])
71
+ prev_cond = get_condition (node [i - 1 ])
72
+ if node_cond is None or prev_cond is None :
73
+ continue
74
+
75
+ if is_same_condition (node_cond , prev_cond ):
76
+ fold_branch (node [i ], node [i - 1 ], "then" , "then" )
77
+ fold_branch (node [i ], node [i - 1 ], "else" , "else" )
78
+ del node [i ]
79
+ elif is_negated_condition (node_cond , prev_cond ):
80
+ fold_branch (node [i ], node [i - 1 ], "then" , "else" )
81
+ fold_branch (node [i ], node [i - 1 ], "else" , "then" )
51
82
del node [i ]
52
83
53
84
# then we descend down the tree
0 commit comments