From b3a9656937b18fae57a5ed53c8528bd1339cfd8d Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sat, 4 Nov 2017 06:28:24 +0100 Subject: Add menuconfig example/proof of concept Still needs documentation and some cleanup. Interface deliberately kept super simple/clunky to focus on the concepts. Not something you'd actually want to use. Sample session: $ python Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig ======== Example Kconfig configuration ======== [*] Enable loadable module support (MODULES) Bool and tristate symbols [*] Bool symbol (BOOL) [ ] Dependent bool symbol (BOOL_DEP) < > Dependent tristate symbol (TRI_DEP) [ ] First prompt (TWO_MENU_NODES) < > Tristate symbol (TRI) [ ] Second prompt (TWO_MENU_NODES) *** These are selected by TRI_DEP *** < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) String, int, and hex symbols (foo) String symbol (STRING) (747) Int symbol (INT) (0xABC) Hex symbol (HEX) Various choices -*- Bool choice (BOOL_CHOICE) --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) Bool choice sym 2 (BOOL_CHOICE_SYM_2) {M} Tristate choice (TRI_CHOICE) < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) [ ] Optional bool choice (OPT_BOOL_CHOICE) Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): BOOL Value for BOOL (available: n, y): n ======== Example Kconfig configuration ======== [*] Enable loadable module support (MODULES) Bool and tristate symbols [ ] Bool symbol (BOOL) < > Tristate symbol (TRI) [ ] Second prompt (TWO_MENU_NODES) *** These are selected by TRI_DEP *** < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) String, int, and hex symbols (foo) String symbol (STRING) (747) Int symbol (INT) (0xABC) Hex symbol (HEX) Various choices -*- Bool choice (BOOL_CHOICE) --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) Bool choice sym 2 (BOOL_CHOICE_SYM_2) {M} Tristate choice (TRI_CHOICE) < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) [ ] Optional bool choice (OPT_BOOL_CHOICE) Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): MODULES Value for MODULES (available: n, y): n ======== Example Kconfig configuration ======== [ ] Enable loadable module support (MODULES) Bool and tristate symbols [ ] Bool symbol (BOOL) [ ] Tristate symbol (TRI) [ ] Second prompt (TWO_MENU_NODES) *** These are selected by TRI_DEP *** [ ] Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) [ ] Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) String, int, and hex symbols (foo) String symbol (STRING) (747) Int symbol (INT) (0xABC) Hex symbol (HEX) Various choices -*- Bool choice (BOOL_CHOICE) --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) Bool choice sym 2 (BOOL_CHOICE_SYM_2) -*- Tristate choice (TRI_CHOICE) --> Tristate choice sym 1 (TRI_CHOICE_SYM_1) Tristate choice sym 2 (TRI_CHOICE_SYM_2) [ ] Optional bool choice (OPT_BOOL_CHOICE) Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ^D Unsetting modules demonstrates one reason why it makes sense to have .type be magic and change from TRISTATE to BOOL without modules (<> = tristate, [] = bool). The C implementation uses the same trick. (The original type is still available in .orig_type though.) Piggyback printing of tristates as n, m, y in the warning for invalid values in set_value(). --- examples/menuconfig.py | 186 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 examples/menuconfig.py (limited to 'examples/menuconfig.py') diff --git a/examples/menuconfig.py b/examples/menuconfig.py new file mode 100644 index 0000000..a77ae2d --- /dev/null +++ b/examples/menuconfig.py @@ -0,0 +1,186 @@ +# TODO: explain, screenshot + +from kconfiglib import Kconfig, \ + Symbol, Choice, MENU, COMMENT, \ + BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \ + expr_value, \ + TRI_TO_STR, STR_TO_TRI +import readline +import sys + +# Python 2/3 compatibility hack +if sys.version_info[0] < 3: + input = raw_input + +def indent_print(s, indent): + print((" " * indent) + s) + +def value_str(sc): + if sc.type in (STRING, INT, HEX): + return "({})".format(sc.str_value) + + # BOOL or TRISTATE + + if isinstance(sc, Symbol) and sc.choice and sc.choice.tri_value == 2: + # For choices in y mode, print '-->' next to the selected symbol + if sc.choice.selection is sc: + return "-->" + return " " + + val_str = {0: " ", 1: "M", 2: "*"}[sc.tri_value] + + if len(sc.assignable) == 1: + return "-{}-".format(val_str) + + if sc.type == BOOL: + return "[{}]".format(val_str) + + if sc.type == TRISTATE: + if sc.assignable[0] == 1: + return "{" + val_str + "}" # Gets a bit confusing with .format() + return "<{}>".format(val_str) + +def node_str(node): + if not node.prompt: + return "" + + prompt, prompt_cond = node.prompt + if not expr_value(prompt_cond): + return "" + + if node.item == MENU: + return " " + prompt + + if node.item == COMMENT: + return " *** {} ***".format(prompt) + + # Symbol or Choice + + sc = node.item + + if sc.type == UNKNOWN: + # Skip symbols defined without a type + return "" + + # {:3} sets the field width to three. Gives nice alignment for empty string + # values. + return "{:3} {} ({})".format(value_str(sc), prompt, sc.name) + +def print_menuconfig_nodes(node, indent): + while node is not None: + string = node_str(node) + if string: + indent_print(string, indent) + + if node.list is not None: + print_menuconfig_nodes(node.list, indent + 8) + + node = node.next + +def print_menuconfig(kconf): + # Print the expanded mainmenu text at the top. This is the same as + # kconf.top_node.prompt[0], but with variable references expanded. + print("\n======== {} ========\n".format(kconf.mainmenu_text)) + + print_menuconfig_nodes(kconf.top_node.list, 0) + print("") + +def get_value_from_user(sc): + if not sc.visibility: + print(sc.name + " is not currently visible") + return False + + prompt = "Value for {}".format(sc.name) + if sc.type in (BOOL, TRISTATE): + prompt += " (available: {})" \ + .format(", ".join([TRI_TO_STR[val] for val in sc.assignable])) + prompt += ": " + + val_str = input(prompt).strip() + if sc.type in (BOOL, TRISTATE): + if val_str not in STR_TO_TRI: + print("'{}' is not a valid tristate value".format(val_str)) + return False + + # I was thinking of having set_value() accept "n", "m", "y" as well as + # a convenience for BOOL / TRISTATE symbols. Consistently using 0, 1, 2 + # makes the format clearer though. That's the best format for + # everything except readability (where it isn't horrible either). + val = STR_TO_TRI[val_str] + else: + val = val_str + + # Automatically add a "0x" prefix for hex symbols, like the menuconfig + # interface does. This isn't done when loading .config files, hence why + # set_value() doesn't do it automatically. + if sc.type == HEX and not val.startswith(("0x", "0X")): + val = "0x" + val + + # Let Kconfiglib itself print a warning here if the value is invalid. We + # could also disable warnings temporarily with + # kconf.disable_warnings() / kconf.enable_warnings() and print our own + # warning. + return sc.set_value(val) + +if __name__ == "__main__": + if len(sys.argv) != 2: + sys.exit("usage: menuconfig.py ") + + # Load Kconfig configuration files + kconf = Kconfig(sys.argv[1]) + + # Print the initial configuration tree + print_menuconfig(kconf) + + while True: + try: + cmd = input('Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ') \ + .strip() + except EOFError: + print("") + break + + if cmd == "load_config": + config_filename = input(".config file to load: ") + + try: + kconf.load_config(config_filename) + except IOError as e: + # Print the (spammy) error from Kconfiglib itself + print(e.message + "\n") + else: + print("Configuration loaded from " + config_filename) + + print_menuconfig(kconf) + continue + + if cmd == "write_config": + config_filename = input("To this file: ") + + try: + kconf.write_config(config_filename) + except IOError as e: + print(e.message) + else: + print("Configuration written to " + config_filename) + + continue + + # Assume 'cmd' is the name of a symbol or choice if it isn't one of the + # commands above, prompt the user for a value for it, and print the new + # configuration tree + + if cmd in kconf.syms: + if get_value_from_user(kconf.syms[cmd]): + print_menuconfig(kconf) + + continue + + if cmd in kconf.named_choices: + if get_value_from_user(kconf.named_choices[cmd]): + print_menuconfig(kconf) + + continue + + print("No symbol/choice named '{}' in the configuration" + .format(cmd)) -- cgit v1.2.3 From 3d6df4e3b12e4449cc1500ade49186aea340342d Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sat, 4 Nov 2017 23:38:36 +0100 Subject: Add documentation for menuconfig example Also avoid printing (None) as the name for unnamed (normal) choices. --- examples/menuconfig.py | 184 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 173 insertions(+), 11 deletions(-) (limited to 'examples/menuconfig.py') diff --git a/examples/menuconfig.py b/examples/menuconfig.py index a77ae2d..42bdf3f 100644 --- a/examples/menuconfig.py +++ b/examples/menuconfig.py @@ -1,4 +1,121 @@ -# TODO: explain, screenshot +# Implements a simple configuration interface on top of Kconfiglib to +# demonstrate concepts for building a menuconfig-like. Emulates how the +# standard menuconfig prints menu entries. +# +# Always displays the entire Kconfig tree to keep things as simple as possible +# (all symbols, choices, menus, and comments). +# +# Usage: +# +# $ python(3) Kconfiglib/examples/menuconfig.py +# +# A sample Kconfig is available in Kconfiglib/examples/Kmenuconfig. +# +# Here's a notation guide. The notation matches the one used by menuconfig +# (scripts/kconfig/mconf): +# +# [ ] prompt - Bool +# < > prompt - Tristate +# {M} prompt - Tristate selected to m. Can only be set to m or y. +# -*- prompt - Bool/tristate selected to y, pinning it +# -M- prompt - Tristate selected to m that also has m visibility, +# pinning it to m +# (foo) prompt - String/int/hex symbol with value "foo" +# --> prompt - The selected symbol in a choice in y mode. This +# syntax is unique to this example. +# +# When modules are disabled, the .type attribute of TRISTATE symbols and +# choices automatically changes to BOOL. This trick is used by the C +# implementation as well, and gives the expected behavior without having to do +# anything extra here. The original type is available in .orig_type if needed. +# +# The Kconfiglib/examples/Kmenuconfig example uses named choices to be able to +# refer to choices by name. Named choices are supported in the C tools too, but +# I don't think I've ever seen them used in the wild. +# +# Sample session: +# +# $ python Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig +# +# ======== Example Kconfig configuration ======== +# +# [*] Enable loadable module support (MODULES) +# Bool and tristate symbols +# [*] Bool symbol (BOOL) +# [ ] Dependent bool symbol (BOOL_DEP) +# < > Dependent tristate symbol (TRI_DEP) +# [ ] First prompt (TWO_MENU_NODES) +# < > Tristate symbol (TRI) +# [ ] Second prompt (TWO_MENU_NODES) +# *** These are selected by TRI_DEP *** +# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) +# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) +# String, int, and hex symbols +# (foo) String symbol (STRING) +# (747) Int symbol (INT) +# (0xABC) Hex symbol (HEX) +# Various choices +# -*- Bool choice (BOOL_CHOICE) +# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) +# Bool choice sym 2 (BOOL_CHOICE_SYM_2) +# {M} Tristate choice (TRI_CHOICE) +# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) +# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) +# [ ] Optional bool choice (OPT_BOOL_CHOICE) +# +# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): BOOL +# Value for BOOL (available: n, y): n +# +# ======== Example Kconfig configuration ======== +# +# [*] Enable loadable module support (MODULES) +# Bool and tristate symbols +# [ ] Bool symbol (BOOL) +# < > Tristate symbol (TRI) +# [ ] Second prompt (TWO_MENU_NODES) +# *** These are selected by TRI_DEP *** +# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) +# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) +# String, int, and hex symbols +# (foo) String symbol (STRING) +# (747) Int symbol (INT) +# (0xABC) Hex symbol (HEX) +# Various choices +# -*- Bool choice (BOOL_CHOICE) +# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) +# Bool choice sym 2 (BOOL_CHOICE_SYM_2) +# {M} Tristate choice (TRI_CHOICE) +# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) +# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) +# [ ] Optional bool choice (OPT_BOOL_CHOICE) +# +# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): MODULES +# Value for MODULES (available: n, y): n +# +# ======== Example Kconfig configuration ======== +# +# [ ] Enable loadable module support (MODULES) +# Bool and tristate symbols +# [ ] Bool symbol (BOOL) +# [ ] Tristate symbol (TRI) +# [ ] Second prompt (TWO_MENU_NODES) +# *** These are selected by TRI_DEP *** +# [ ] Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) +# [ ] Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) +# String, int, and hex symbols +# (foo) String symbol (STRING) +# (747) Int symbol (INT) +# (0xABC) Hex symbol (HEX) +# Various choices +# -*- Bool choice (BOOL_CHOICE) +# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) +# Bool choice sym 2 (BOOL_CHOICE_SYM_2) +# -*- Tristate choice (TRI_CHOICE) +# --> Tristate choice sym 1 (TRI_CHOICE_SYM_1) +# Tristate choice sym 2 (TRI_CHOICE_SYM_2) +# [ ] Optional bool choice (OPT_BOOL_CHOICE) +# +# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ^D from kconfiglib import Kconfig, \ Symbol, Choice, MENU, COMMENT, \ @@ -16,34 +133,61 @@ def indent_print(s, indent): print((" " * indent) + s) def value_str(sc): + """ + Returns the value part ("[*]", "", "(foo)" etc.) of a menu entry. + + sc: Symbol or Choice. + """ if sc.type in (STRING, INT, HEX): return "({})".format(sc.str_value) # BOOL or TRISTATE - if isinstance(sc, Symbol) and sc.choice and sc.choice.tri_value == 2: + # The choice mode acts as an upper bound on the visibility of choice + # symbols, so we can check the choice symbols' own visibility to see if the + # choice is in y mode + if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2: # For choices in y mode, print '-->' next to the selected symbol if sc.choice.selection is sc: return "-->" return " " - val_str = {0: " ", 1: "M", 2: "*"}[sc.tri_value] + tri_val_str = {0: " ", 1: "M", 2: "*"}[sc.tri_value] if len(sc.assignable) == 1: - return "-{}-".format(val_str) + # Pinned to a single value + return "-{}-".format(tri_val_str) if sc.type == BOOL: - return "[{}]".format(val_str) + return "[{}]".format(tri_val_str) if sc.type == TRISTATE: - if sc.assignable[0] == 1: - return "{" + val_str + "}" # Gets a bit confusing with .format() - return "<{}>".format(val_str) + if sc.assignable[0] == 1: # m + # m and y available + return "{" + tri_val_str + "}" # Gets a bit confusing with .format() + return "<{}>".format(tri_val_str) def node_str(node): + """ + Returns the complete menu entry text for a menu node, or "" for invisible + menu nodes. Invisible menu nodes are those that lack a prompt or don't have + a satisfied prompt condition. + + Example return value: "[*] Bool symbol (BOOL)" + + The symbol name is printed in parentheses to the right of the prompt. This + is so that symbols can easily be referred to in the configuration + interface. + """ if not node.prompt: return "" + # Even for menu nodes for symbols and choices, it's wrong to check + # Symbol.visibility / Choice.visibility here. The reason is that a symbol + # (and a choice, in theory) can be defined in multiple locations, giving it + # multiple menu nodes, which do not necessarily all have the same prompt + # visibility. Symbol.visibility / Choice.visibility is calculated as the OR + # of the visibility of all the prompts. prompt, prompt_cond = node.prompt if not expr_value(prompt_cond): return "" @@ -64,9 +208,19 @@ def node_str(node): # {:3} sets the field width to three. Gives nice alignment for empty string # values. - return "{:3} {} ({})".format(value_str(sc), prompt, sc.name) + res = "{:3} {}".format(value_str(sc), prompt) + + # Don't print the name for unnamed choices (the normal kind) + if sc.name is not None: + res += " ({})".format(sc.name) + + return res def print_menuconfig_nodes(node, indent): + """ + Prints a tree with all the menu entries rooted at node. Child menu nodes + are indented. + """ while node is not None: string = node_str(node) if string: @@ -78,6 +232,9 @@ def print_menuconfig_nodes(node, indent): node = node.next def print_menuconfig(kconf): + """ + Prints all menu entries for the configurations. + """ # Print the expanded mainmenu text at the top. This is the same as # kconf.top_node.prompt[0], but with variable references expanded. print("\n======== {} ========\n".format(kconf.mainmenu_text)) @@ -86,6 +243,11 @@ def print_menuconfig(kconf): print("") def get_value_from_user(sc): + """ + Prompts the user for a value for the symbol or choice 'sc'. For + bool/tristate symbols and choices, provides a list of all the assignable + values. + """ if not sc.visibility: print(sc.name + " is not currently visible") return False @@ -104,8 +266,8 @@ def get_value_from_user(sc): # I was thinking of having set_value() accept "n", "m", "y" as well as # a convenience for BOOL / TRISTATE symbols. Consistently using 0, 1, 2 - # makes the format clearer though. That's the best format for - # everything except readability (where it isn't horrible either). + # makes the format clearer though. That's the best format in all ways + # except for readability (where it isn't horrible either). val = STR_TO_TRI[val_str] else: val = val_str -- cgit v1.2.3 From 54143e4d6a4ac4e7be9d5c9728c5ac606f5d3a2e Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sat, 4 Nov 2017 23:40:47 +0100 Subject: Fix some menuconfig.py typos --- examples/menuconfig.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples/menuconfig.py') diff --git a/examples/menuconfig.py b/examples/menuconfig.py index 42bdf3f..a4038f8 100644 --- a/examples/menuconfig.py +++ b/examples/menuconfig.py @@ -218,7 +218,7 @@ def node_str(node): def print_menuconfig_nodes(node, indent): """ - Prints a tree with all the menu entries rooted at node. Child menu nodes + Prints a tree with all the menu entries rooted at node. Child menu entries are indented. """ while node is not None: @@ -233,7 +233,7 @@ def print_menuconfig_nodes(node, indent): def print_menuconfig(kconf): """ - Prints all menu entries for the configurations. + Prints all menu entries for the configuration. """ # Print the expanded mainmenu text at the top. This is the same as # kconf.top_node.prompt[0], but with variable references expanded. -- cgit v1.2.3 From 087bc506d25b20b759a092a7490942e9cb212720 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sun, 5 Nov 2017 07:01:53 +0100 Subject: Simplify redundant 'is (not) None' tests in examples --- examples/allnoconfig.py | 4 ++-- examples/allyesconfig.py | 13 ++++++------- examples/help_grep.py | 4 ++-- examples/menuconfig.py | 4 ++-- examples/print_tree.py | 4 ++-- 5 files changed, 14 insertions(+), 15 deletions(-) (limited to 'examples/menuconfig.py') diff --git a/examples/allnoconfig.py b/examples/allnoconfig.py index 467f681..47a8026 100644 --- a/examples/allnoconfig.py +++ b/examples/allnoconfig.py @@ -18,7 +18,7 @@ def do_allnoconfig(node): # entries in the menuconfig interface, setting each to n (or the lowest # assignable value). - while node is not None: + while node: if isinstance(node.item, Symbol): sym = node.item @@ -33,7 +33,7 @@ def do_allnoconfig(node): changed = True # Recursively lower children - if node.list is not None: + if node.list: do_allnoconfig(node.list) node = node.next diff --git a/examples/allyesconfig.py b/examples/allyesconfig.py index 1c85d60..b1d2cf6 100644 --- a/examples/allyesconfig.py +++ b/examples/allyesconfig.py @@ -40,19 +40,19 @@ while 1: # template for how you can avoid recursing on both. The same logic is found # in the C implementation. - if node.list is not None: + if node.list: # Jump to child node if available node = node.list - elif node.next is not None: + elif node.next: # Otherwise, jump to next node if available node = node.next else: # Otherwise, look for parents with next nodes to jump to - while node.parent is not None: + while node.parent: node = node.parent - if node.next is not None: + if node.next: node = node.next break else: @@ -60,7 +60,7 @@ while 1: break # Collect all symbols that are not in choices -non_choice_syms = [sym for sym in conf.defined_syms if sym.choice is None] +non_choice_syms = [sym for sym in conf.defined_syms if not sym.choice] while 1: no_changes = True @@ -87,8 +87,7 @@ while 1: # Does the choice have a default selection that we haven't already # selected? - if selection is not None and \ - selection is not choice.user_selection: + if selection and selection is not choice.user_selection: # Yup, select it selection.set_value(2) diff --git a/examples/help_grep.py b/examples/help_grep.py index 6f54583..b9e1440 100644 --- a/examples/help_grep.py +++ b/examples/help_grep.py @@ -44,7 +44,7 @@ if len(sys.argv) < 3: search = re.compile(sys.argv[2], re.IGNORECASE).search def search_tree(node): - while node is not None: + while node: match = False if isinstance(node.item, (Symbol, Choice)) and \ @@ -63,7 +63,7 @@ def search_tree(node): if match: print("location: {}:{}\n".format(node.filename, node.linenr)) - if node.list is not None: + if node.list: search_tree(node.list) node = node.next diff --git a/examples/menuconfig.py b/examples/menuconfig.py index a4038f8..e98ff43 100644 --- a/examples/menuconfig.py +++ b/examples/menuconfig.py @@ -221,12 +221,12 @@ def print_menuconfig_nodes(node, indent): Prints a tree with all the menu entries rooted at node. Child menu entries are indented. """ - while node is not None: + while node: string = node_str(node) if string: indent_print(string, indent) - if node.list is not None: + if node.list: print_menuconfig_nodes(node.list, indent + 8) node = node.next diff --git a/examples/print_tree.py b/examples/print_tree.py index 9d9eac2..cda9ce2 100644 --- a/examples/print_tree.py +++ b/examples/print_tree.py @@ -45,7 +45,7 @@ def indent_print(s, indent): print((" " * indent) + s) def print_items(node, indent): - while node is not None: + while node: if isinstance(node.item, Symbol): indent_print("config " + node.item.name, indent) @@ -58,7 +58,7 @@ def print_items(node, indent): elif node.item == COMMENT: indent_print('comment "{0}"'.format(node.prompt[0]), indent) - if node.list is not None: + if node.list: print_items(node.list, indent + 2) node = node.next -- cgit v1.2.3 From fda4b31b247332f05268fb2a6544f9df36c8e559 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Tue, 7 Nov 2017 13:06:54 +0100 Subject: Test for m, y assignability in a more readable way --- examples/menuconfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/menuconfig.py') diff --git a/examples/menuconfig.py b/examples/menuconfig.py index e98ff43..375b8c8 100644 --- a/examples/menuconfig.py +++ b/examples/menuconfig.py @@ -162,7 +162,7 @@ def value_str(sc): return "[{}]".format(tri_val_str) if sc.type == TRISTATE: - if sc.assignable[0] == 1: # m + if sc.assignable == (1, 2): # m and y available return "{" + tri_val_str + "}" # Gets a bit confusing with .format() return "<{}>".format(tri_val_str) -- cgit v1.2.3