summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2018-06-11 17:49:49 +0200
committerUlf Magnusson <ulfalizer@gmail.com>2018-06-11 18:30:51 +0200
commit506e3fb211d22f62115ce83e9247266c5d87ea24 (patch)
tree86b41a341b3da5d527c5a85583cc9d46daebe294
parent330017a99cd7619c9eb1fe5fccbb02f5d9e7f6c5 (diff)
Add a function for getting all items in an expression
Handy e.g. when searching.
-rw-r--r--examples/find_symbol.py19
-rw-r--r--kconfiglib.py24
-rw-r--r--tests/Kexpr_items11
-rw-r--r--testsuite.py21
4 files changed, 61 insertions, 14 deletions
diff --git a/examples/find_symbol.py b/examples/find_symbol.py
index 55e6345..adc4d73 100644
--- a/examples/find_symbol.py
+++ b/examples/find_symbol.py
@@ -59,7 +59,7 @@
# config OPROFILE
# ... (tons more lines)
-from kconfiglib import Kconfig, Symbol, Choice, MENU, COMMENT, NOT
+from kconfiglib import Kconfig, Symbol, expr_items, Choice, MENU, COMMENT, NOT
import sys
def expr_contains_sym(expr, sym_name):
@@ -70,18 +70,11 @@ def expr_contains_sym(expr, sym_name):
Note that "foo" is represented as a constant symbol, like in the C
implementation.
"""
- # Choice symbols have a Choice instance propagated to the conditions of
- # their properties, so we need this test rather than
- # isinstance(expr, Symbol)
- if not isinstance(expr, tuple):
- return expr.name == sym_name
-
- if expr[0] == NOT:
- return expr_contains_sym(expr[1], sym_name)
-
- # AND, OR, or relation
- return expr_contains_sym(expr[1], sym_name) or \
- expr_contains_sym(expr[2], sym_name)
+ for item in expr_items(expr):
+ if item.name == sym_name:
+ return True
+
+ return False
def sc_references_sym(sc, sym_name):
"""
diff --git a/kconfiglib.py b/kconfiglib.py
index cee793e..82edcb6 100644
--- a/kconfiglib.py
+++ b/kconfiglib.py
@@ -4422,6 +4422,30 @@ def expr_str(expr):
_REL_TO_STR[expr[0]],
expr_str(expr[2]))
+def expr_items(expr):
+ """
+ Returns a set() of all items (symbols and choices) that appear in the
+ expression 'expr'.
+ """
+
+ deps = set()
+
+ def rec(subexpr):
+ if not isinstance(subexpr, tuple):
+ # Symbol or choice
+ deps.add(subexpr)
+
+ elif subexpr[0] == NOT:
+ rec(subexpr[1])
+
+ else:
+ # AND, OR, or relation
+ rec(subexpr[1])
+ rec(subexpr[2])
+
+ rec(expr)
+ return deps
+
def split_expr(expr, op):
"""
Returns a list containing the top-level AND or OR operands in the
diff --git a/tests/Kexpr_items b/tests/Kexpr_items
new file mode 100644
index 0000000..fb97ace
--- /dev/null
+++ b/tests/Kexpr_items
@@ -0,0 +1,11 @@
+config TEST
+ bool
+ default A && (B || !C && D = "E") || F > G || !!!H
+
+choice CHOICE
+ bool "choice"
+
+config TEST_CHOICE
+ bool "test choice" if A
+
+endchoice
diff --git a/testsuite.py b/testsuite.py
index d976c12..1f1bc32 100644
--- a/testsuite.py
+++ b/testsuite.py
@@ -45,7 +45,7 @@ from kconfiglib import Kconfig, Symbol, Choice, COMMENT, MENU, MenuNode, \
BOOL, TRISTATE, HEX, STRING, \
TRI_TO_STR, \
escape, unescape, \
- expr_str, expr_value, split_expr, \
+ expr_str, expr_value, expr_items, split_expr, \
OR, AND, \
KconfigSyntaxError
import difflib
@@ -990,6 +990,25 @@ g
"A || B || C")
+ print("Testing expr_items()")
+
+ c = Kconfig("Kconfiglib/tests/Kexpr_items")
+
+ def verify_expr_items(expr, *sym_names):
+ verify_equal(tuple(sorted(item.name for item in expr_items(expr))),
+ sym_names)
+
+ verify_expr_items(
+ c.syms["TEST"].defaults[0][0],
+ "A", "B", "C", "D", "E", "F", "G", "H"
+ )
+
+ verify_expr_items(
+ c.syms["TEST_CHOICE"].nodes[0].prompt[1],
+ "A", "CHOICE"
+ )
+
+
print("Testing split_expr()")
def verify_split(to_split, op, operand_strs):