diff options
| author | Ulf Magnusson <ulfalizer@gmail.com> | 2019-05-25 13:52:09 +0200 |
|---|---|---|
| committer | Ulf Magnusson <ulfalizer@gmail.com> | 2019-05-25 16:18:29 +0200 |
| commit | bb33eed5cc6bdce2b65aa570ecd9a400bcd9c180 (patch) | |
| tree | d0a1a5681a6ec5d9ac25407e9594aa6022fb5969 | |
| parent | e81a77bdb0687b62f91d7dc4d5b84b443808c0a7 (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.py | 10 | ||||
| -rwxr-xr-x | guiconfig.py | 2 | ||||
| -rw-r--r-- | kconfiglib.py | 95 | ||||
| -rwxr-xr-x | menuconfig.py | 2 | ||||
| -rw-r--r-- | tests/Kstr | 37 | ||||
| -rw-r--r-- | testsuite.py | 121 |
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)*"=" @@ -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... |
