summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2019-05-25 13:52:09 +0200
committerUlf Magnusson <ulfalizer@gmail.com>2019-05-25 16:18:29 +0200
commitbb33eed5cc6bdce2b65aa570ecd9a400bcd9c180 (patch)
treed0a1a5681a6ec5d9ac25407e9594aa6022fb5969
parente81a77bdb0687b62f91d7dc4d5b84b443808c0a7 (diff)
Strip direct deps. from property conditions in Symbol/Choice/MenuNode.__str__()
Commit e81a77b ("Consistently put direct deps. last when propagating") makes the position of the direct deps. in property conditions predictable after dependency propagation, making it easy to strip them as needed. Use this to implement MenuNode.orig_{prompt,defaults,selects,implies,ranges}, which work like the non-orig_* versions but omit the direct deps. Use those in turn to omit the direct deps in Symbol/Choice.__str__(). The direct deps. (with propagated parent deps.) can still be seen after 'depends on ...', so there is no loss of information. This unclutters Kconfig definitions shown in menuconfig/guiconfig and in any generated documentation. The old output also had duplicated dependencies, though it doesn't matter for evaluation. Before: config A bool prompt "A" if DEP default y if FOO && DEP depends on DEP After: config A bool prompt "A" default y if FOO depends on DEP
-rw-r--r--examples/find_symbol.py10
-rwxr-xr-xguiconfig.py2
-rw-r--r--kconfiglib.py95
-rwxr-xr-xmenuconfig.py2
-rw-r--r--tests/Kstr37
-rw-r--r--testsuite.py121
6 files changed, 209 insertions, 58 deletions
diff --git a/examples/find_symbol.py b/examples/find_symbol.py
index 132d45f..f747103 100644
--- a/examples/find_symbol.py
+++ b/examples/find_symbol.py
@@ -42,8 +42,8 @@
#
# config OPROFILE_EVENT_MULTIPLEX
# bool
-# prompt "OProfile multiplexing support (EXPERIMENTAL)" if OPROFILE && X86
-# default "n" if OPROFILE && X86
+# prompt "OProfile multiplexing support (EXPERIMENTAL)"
+# default "n"
# depends on OPROFILE && X86
# help
# The number of hardware counters is limited. The multiplexing
@@ -57,9 +57,9 @@
#
# config OPROFILE
# tristate
-# prompt "OProfile system profiling" if PROFILING && HAVE_OPROFILE
-# select RING_BUFFER if PROFILING && HAVE_OPROFILE
-# select RING_BUFFER_ALLOW_SWAP if PROFILING && HAVE_OPROFILE
+# prompt "OProfile system profiling"
+# select RING_BUFFER
+# select RING_BUFFER_ALLOW_SWAP
# depends on PROFILING && HAVE_OPROFILE
# help
# OProfile is a profiling system capable of profiling the
diff --git a/guiconfig.py b/guiconfig.py
index c709c4e..9563ab4 100755
--- a/guiconfig.py
+++ b/guiconfig.py
@@ -2222,7 +2222,7 @@ def _kconfig_def_info(item):
nodes = [item] if isinstance(item, MenuNode) else item.nodes
- s = "Kconfig definition{}, with propagated dependencies\n" \
+ s = "Kconfig definition{}, with parent deps. propagated to 'depends on'\n" \
.format("s" if len(nodes) > 1 else "")
s += (len(s) - 1)*"="
diff --git a/kconfiglib.py b/kconfiglib.py
index 2725787..8112e11 100644
--- a/kconfiglib.py
+++ b/kconfiglib.py
@@ -4378,8 +4378,9 @@ class Symbol(object):
def __str__(self):
"""
- Returns a string representation of the symbol when it is printed,
- matching the Kconfig format, with parent dependencies propagated.
+ Returns a string representation of the symbol when it is printed.
+ Matches the Kconfig format, with any parent dependencies propagated to
+ the 'depends on' condition.
The string is constructed by joining the strings returned by
MenuNode.__str__() for each of the symbol's menu nodes, so symbols
@@ -4954,9 +4955,10 @@ class Choice(object):
def __str__(self):
"""
- Returns a string representation of the choice when it is printed,
- matching the Kconfig format (though without the contained choice
- symbols).
+ Returns a string representation of the choice when it is printed.
+ Matches the Kconfig format (though without the contained choice
+ symbols), with any parent dependencies propagated to the 'depends on'
+ condition.
The returned string does not end in a newline.
@@ -5135,6 +5137,18 @@ class MenuNode(object):
ranges:
Like MenuNode.defaults, for ranges.
+ orig_prompt:
+ orig_defaults:
+ orig_selects:
+ orig_implies:
+ orig_ranges:
+ These work the like the corresponding attributes without orig_*, but omit
+ any dependencies propagated from 'depends on' and surrounding 'if's (the
+ direct dependencies, stored in MenuNode.dep).
+
+ One use for this is generating less cluttered documentation, by only
+ showing the direct dependencies in one place.
+
help:
The help text for the menu node for Symbols and Choices. None if there is
no help text. Always stored in the node rather than the Symbol or Choice.
@@ -5234,6 +5248,47 @@ class MenuNode(object):
self.ranges = []
@property
+ def orig_prompt(self):
+ """
+ See the class documentation.
+ """
+ if not self.prompt:
+ return None
+ return (self.prompt[0], self._strip_dep(self.prompt[1]))
+
+ @property
+ def orig_defaults(self):
+ """
+ See the class documentation.
+ """
+ return [(default, self._strip_dep(cond))
+ for default, cond in self.defaults]
+
+ @property
+ def orig_selects(self):
+ """
+ See the class documentation.
+ """
+ return [(select, self._strip_dep(cond))
+ for select, cond in self.selects]
+
+ @property
+ def orig_implies(self):
+ """
+ See the class documentation.
+ """
+ return [(imply, self._strip_dep(cond))
+ for imply, cond in self.implies]
+
+ @property
+ def orig_ranges(self):
+ """
+ See the class documentation.
+ """
+ return [(low, high, self._strip_dep(cond))
+ for low, high, cond in self.ranges]
+
+ @property
def referenced(self):
"""
See the class documentation.
@@ -5318,8 +5373,9 @@ class MenuNode(object):
def __str__(self):
"""
- Returns a string representation of the menu node, matching the Kconfig
- format.
+ Returns a string representation of the menu node. Matches the Kconfig
+ format, with any parent dependencies propagated to the 'depends on'
+ condition.
The output could (almost) be fed back into a Kconfig parser to redefine
the object associated with the menu node. See the module documentation
@@ -5379,7 +5435,7 @@ class MenuNode(object):
if self.prompt:
indent_add_cond(
'prompt "{}"'.format(escape(self.prompt[0])),
- self.prompt[1])
+ self.orig_prompt[1])
if sc.__class__ is Symbol:
if sc.is_allnoconfig_y:
@@ -5394,13 +5450,13 @@ class MenuNode(object):
if sc is sc.kconfig.modules:
indent_add("option modules")
- for low, high, cond in self.ranges:
+ for low, high, cond in self.orig_ranges:
indent_add_cond(
"range {} {}".format(sc_expr_str_fn(low),
sc_expr_str_fn(high)),
cond)
- for default, cond in self.defaults:
+ for default, cond in self.orig_defaults:
indent_add_cond("default " + expr_str(default, sc_expr_str_fn),
cond)
@@ -5408,10 +5464,10 @@ class MenuNode(object):
indent_add("optional")
if sc.__class__ is Symbol:
- for select, cond in self.selects:
+ for select, cond in self.orig_selects:
indent_add_cond("select " + sc_expr_str_fn(select), cond)
- for imply, cond in self.implies:
+ for imply, cond in self.orig_implies:
indent_add_cond("imply " + sc_expr_str_fn(imply), cond)
if self.dep is not sc.kconfig.y:
@@ -5424,6 +5480,21 @@ class MenuNode(object):
return "\n".join(lines)
+ def _strip_dep(self, expr):
+ # Helper function for removing MenuNode.dep from 'expr'. Uses two
+ # pieces of internal knowledge: (1) Expressions are reused rather than
+ # copied, and (2) the direct dependencies always appear at the end.
+
+ # ... if dep -> ... if y
+ if self.dep is expr:
+ return self.kconfig.y
+
+ # (AND, X, dep) -> X
+ if expr.__class__ is tuple and expr[0] is AND and expr[2] is self.dep:
+ return expr[1]
+
+ return expr
+
class Variable(object):
"""
diff --git a/menuconfig.py b/menuconfig.py
index 8ecf611..3dbee95 100755
--- a/menuconfig.py
+++ b/menuconfig.py
@@ -2739,7 +2739,7 @@ def _kconfig_def_info(item):
nodes = [item] if isinstance(item, MenuNode) else item.nodes
- s = "Kconfig definition{}, with propagated dependencies\n" \
+ s = "Kconfig definition{}, with parent deps. propagated to 'depends on'\n" \
.format("s" if len(nodes) > 1 else "")
s += (len(s) - 1)*"="
diff --git a/tests/Kstr b/tests/Kstr
index 58d25e6..07d7b8d 100644
--- a/tests/Kstr
+++ b/tests/Kstr
@@ -201,3 +201,40 @@ config ADVANCED_COMMENT_HOOK
comment "advanced comment"
depends on A
depends on B
+
+# Corner cases when removing direct dependencies
+
+config DEP_REM_CORNER_CASES
+ bool
+ default A
+ depends on n
+
+config DEP_REM_CORNER_CASES
+ default B if n
+
+config DEP_REM_CORNER_CASES
+ default C
+ depends on m
+
+config DEP_REM_CORNER_CASES
+ default D if A && y
+ depends on y
+
+config DEP_REM_CORNER_CASES
+ default E if !E1
+ default F if F1 = F2
+ default G if G1 || H1
+ depends on !H
+
+config DEP_REM_CORNER_CASES
+ default H
+ depends on "foo" = "bar"
+
+menu "menu"
+ visible if FOO || BAR
+
+config DEP_REM_CORNER_CASES
+ prompt "prompt"
+ depends on BAZ && QAZ
+
+endmenu
diff --git a/testsuite.py b/testsuite.py
index c1690d3..f3f2b42 100644
--- a/testsuite.py
+++ b/testsuite.py
@@ -557,7 +557,7 @@ config ADVANCED
config ADVANCED
tristate
- prompt "prompt 4" if VIS && DEP4 && DEP3
+ prompt "prompt 4" if VIS
depends on DEP4 && DEP3
""")
@@ -590,7 +590,7 @@ config ADVANCED
config ADVANCED
tristate
- prompt "prompt 4" if [VIS] && [DEP4] && [DEP3]
+ prompt "prompt 4" if [VIS]
depends on [DEP4] && [DEP3]
""")
@@ -645,39 +645,39 @@ config OPTIONS
verify_str(c.syms["CORRECT_PROP_LOCS_BOOL"], """
config CORRECT_PROP_LOCS_BOOL
bool
- prompt "prompt 1" if LOC_1
- default DEFAULT_1 if LOC_1
- default DEFAULT_2 if LOC_1
- select SELECT_1 if LOC_1
- select SELECT_2 if LOC_1
- imply IMPLY_1 if LOC_1
- imply IMPLY_2 if LOC_1
+ prompt "prompt 1"
+ default DEFAULT_1
+ default DEFAULT_2
+ select SELECT_1
+ select SELECT_2
+ imply IMPLY_1
+ imply IMPLY_2
depends on LOC_1
help
help 1
menuconfig CORRECT_PROP_LOCS_BOOL
bool
- prompt "prompt 2" if LOC_2
- default DEFAULT_3 if LOC_2
- default DEFAULT_4 if LOC_2
- select SELECT_3 if LOC_2
- select SELECT_4 if LOC_2
- imply IMPLY_3 if LOC_2
- imply IMPLY_4 if LOC_2
+ prompt "prompt 2"
+ default DEFAULT_3
+ default DEFAULT_4
+ select SELECT_3
+ select SELECT_4
+ imply IMPLY_3
+ imply IMPLY_4
depends on LOC_2
help
help 2
config CORRECT_PROP_LOCS_BOOL
bool
- prompt "prompt 3" if LOC_3
- default DEFAULT_5 if LOC_3
- default DEFAULT_6 if LOC_3
- select SELECT_5 if LOC_3
- select SELECT_6 if LOC_3
- imply IMPLY_5 if LOC_3
- imply IMPLY_6 if LOC_3
+ prompt "prompt 3"
+ default DEFAULT_5
+ default DEFAULT_6
+ select SELECT_5
+ select SELECT_6
+ imply IMPLY_5
+ imply IMPLY_6
depends on LOC_3
help
help 2
@@ -686,28 +686,28 @@ config CORRECT_PROP_LOCS_BOOL
verify_str(c.syms["CORRECT_PROP_LOCS_INT"], """
config CORRECT_PROP_LOCS_INT
int
- range 1 2 if LOC_1
- range 3 4 if LOC_1
+ range 1 2
+ range 3 4
depends on LOC_1
config CORRECT_PROP_LOCS_INT
int
- range 5 6 if LOC_2
- range 7 8 if LOC_2
+ range 5 6
+ range 7 8
depends on LOC_2
""")
verify_custom_str(c.syms["CORRECT_PROP_LOCS_INT"], """
config CORRECT_PROP_LOCS_INT
int
- range [1] [2] if [LOC_1]
- range [3] [4] if [LOC_1]
+ range [1] [2]
+ range [3] [4]
depends on [LOC_1]
config CORRECT_PROP_LOCS_INT
int
- range [5] [6] if [LOC_2]
- range [7] [8] if [LOC_2]
+ range [5] [6]
+ range [7] [8]
depends on [LOC_2]
""")
@@ -733,34 +733,34 @@ choice
verify_str(c.named_choices["CORRECT_PROP_LOCS_CHOICE"], """
choice CORRECT_PROP_LOCS_CHOICE
bool
- default CHOICE_3 if LOC_1
+ default CHOICE_3
depends on LOC_1
choice CORRECT_PROP_LOCS_CHOICE
bool
- default CHOICE_4 if LOC_2
+ default CHOICE_4
depends on LOC_2
choice CORRECT_PROP_LOCS_CHOICE
bool
- default CHOICE_5 if LOC_3
+ default CHOICE_5
depends on LOC_3
""")
verify_custom_str(c.named_choices["CORRECT_PROP_LOCS_CHOICE"], """
choice CORRECT_PROP_LOCS_CHOICE
bool
- default [CHOICE_3] if [LOC_1]
+ default [CHOICE_3]
depends on [LOC_1]
choice CORRECT_PROP_LOCS_CHOICE
bool
- default [CHOICE_4] if [LOC_2]
+ default [CHOICE_4]
depends on [LOC_2]
choice CORRECT_PROP_LOCS_CHOICE
bool
- default [CHOICE_5] if [LOC_3]
+ default [CHOICE_5]
depends on [LOC_3]
""")
@@ -798,6 +798,49 @@ comment "advanced comment"
""")
+ print("Testing MenuNode.orig_*")
+
+ # Just test some corner cases here. These are already tested above. Use
+ # MenuNode.__str__() as a proxy.
+
+ verify_str(c.syms["DEP_REM_CORNER_CASES"], """
+config DEP_REM_CORNER_CASES
+ bool
+ default A
+ depends on "n"
+
+config DEP_REM_CORNER_CASES
+ bool
+ default B if "n"
+
+config DEP_REM_CORNER_CASES
+ bool
+ default C
+ depends on "m" && MODULES
+
+config DEP_REM_CORNER_CASES
+ bool
+ default D if A
+
+config DEP_REM_CORNER_CASES
+ bool
+ default E if !E1
+ default F if F1 = F2
+ default G if G1 || H1
+ depends on !H
+
+config DEP_REM_CORNER_CASES
+ bool
+ default H
+ depends on "foo" = "bar"
+
+config DEP_REM_CORNER_CASES
+ bool
+ prompt "prompt" if FOO || BAR
+ depends on BAZ && QAZ
+""")
+
+
print("Testing Symbol.__repr__()")
def verify_repr(item, s):
@@ -2349,14 +2392,14 @@ config G
config H
bool
- prompt "H" if I && <choice>
+ prompt "H"
depends on I && <choice>
...depends on the choice symbol I (defined at Kconfiglib/tests/Kdeploop10:41), with definition...
config I
bool
- prompt "I" if <choice>
+ prompt "I"
depends on <choice>
...depends on <choice> (defined at Kconfiglib/tests/Kdeploop10:38), with definition...