diff options
| author | Ulf Magnusson <ulfalizer@gmail.com> | 2017-10-28 00:46:00 +0200 |
|---|---|---|
| committer | Ulf Magnusson <ulfalizer@gmail.com> | 2017-10-28 00:57:36 +0200 |
| commit | 481bfd60d0b283f30b906d2edf8228aeb82e8492 (patch) | |
| tree | 0e2451c219de37e71f4478596c9da32de545005a | |
| parent | 9b1cc0dbad8e19930d5e1c6365745e14c7fa6076 (diff) | |
Nearly finalize API
Probably just some usability tweaks left. Having to do STR_TO_TRI[] for
comparisons against 'assignable' values is kinda ugly and confusing.
| -rw-r--r-- | examples/allnoconfig.py | 4 | ||||
| -rw-r--r-- | examples/allyesconfig.py | 10 | ||||
| -rw-r--r-- | kconfiglib.py | 617 | ||||
| -rw-r--r-- | testsuite.py | 561 |
4 files changed, 582 insertions, 610 deletions
diff --git a/examples/allnoconfig.py b/examples/allnoconfig.py index 8d41912..2348da4 100644 --- a/examples/allnoconfig.py +++ b/examples/allnoconfig.py @@ -8,7 +8,7 @@ # # $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig.py -from kconfiglib import Config, Symbol, tri_less +from kconfiglib import Config, Symbol, STR_TO_TRI import sys def do_allnoconfig(node): @@ -27,7 +27,7 @@ def do_allnoconfig(node): if (sym.choice is None and not sym.is_allnoconfig_y and sym.assignable and - tri_less(sym.assignable[0], sym.value)): + STR_TO_TRI[sym.assignable[0]] < sym.tri_value): # Yup, lower it sym.set_value(sym.assignable[0]) diff --git a/examples/allyesconfig.py b/examples/allyesconfig.py index 32b302c..f91b6d7 100644 --- a/examples/allyesconfig.py +++ b/examples/allyesconfig.py @@ -18,7 +18,7 @@ # # $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allyesconfig.py -from kconfiglib import Config, Choice, tri_less +from kconfiglib import Config, Choice, STR_TO_TRI import sys conf = Config(sys.argv[1]) @@ -70,7 +70,7 @@ while 1: for sym in non_choice_syms: # See allnoconfig example. [-1] gives the last (highest) assignable # value. - if sym.assignable and tri_less(sym.value, sym.assignable[-1]): + if sym.assignable and sym.tri_value < STR_TO_TRI[sym.assignable[-1]]: sym.set_value(sym.assignable[-1]) no_changes = False @@ -79,7 +79,7 @@ while 1: for choice in choices: # Handle a choice whose visibility allows it to be in "y" mode - if choice.visibility == "y": + if choice.visibility == 2: selection = choice.default_selection # Does the choice have a default selection that we haven't already @@ -95,12 +95,12 @@ while 1: # This might happen if a choice depends on a symbol that can only be # "m", for example. - elif choice.visibility == "m": + elif choice.visibility == 1: for sym in choice.symbols: # Does the choice have a symbol that can be "m" that we haven't # already set to "m"? - if sym.user_value != "m" and "m" in sym.assignable: + if sym.user_tri_value != 1 and "m" in sym.assignable: # Yup, set it sym.set_value("m") diff --git a/kconfiglib.py b/kconfiglib.py index d0c46c6..25bb380 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -338,7 +338,8 @@ class Config(object): sym.name = nmy sym.is_constant = True sym._type = TRISTATE - sym._cached_val = nmy + sym._cached_tri_val = STR_TO_TRI[nmy] + sym._cached_str_val = nmy self.const_syms[nmy] = sym @@ -416,9 +417,10 @@ class Config(object): """ if self.defconfig_list is None: return None + for filename, cond_expr in self.defconfig_list.defaults: - if eval_expr(cond_expr) != "n": - filename = self._expand_sym_refs(filename.value) + if eval_expr(cond_expr): + filename = self._expand_sym_refs(filename.str_value) try: with self._open(filename) as f: return f.name @@ -474,6 +476,7 @@ class Config(object): self._warn("malformed string literal", filename, linenr) continue + # Strip quotes and remove escapings. The unescaping # procedure should be safe since " can only appear as # \" inside the string. @@ -481,7 +484,7 @@ class Config(object): .replace("\\\\", "\\") if sym.choice is not None: - mode = sym.choice.user_value + mode = sym.choice.user_str_value if mode is not None and mode != val: self._warn("assignment to {} changes mode of " 'containing choice from "{}" to "{}".' @@ -504,10 +507,10 @@ class Config(object): # Done parsing the assignment. Set the value. - if sym.user_value is not None: + if sym.user_str_value is not None: self._warn('{} set more than once. Old value: "{}", new ' 'value: "{}".' - .format(name, sym.user_value, val), + .format(name, sym.user_str_value, val), filename, linenr) sym._set_value_no_invalidate(val, True) @@ -542,7 +545,7 @@ class Config(object): returns "y". This function always yields a tristate value. To get the value of - non-bool, non-tristate symbols, use Symbol.value. + non-bool, non-tristate symbols, use Symbol.str_value. The result of this function is consistent with how evaluation works for conditional ('if ...') expressions in the configuration (as well as in @@ -571,11 +574,12 @@ class Config(object): for sym in self.defined_syms: # We're iterating over all symbols, so no need for symbols to # invalidate their dependent symbols - sym.user_value = None + sym.user_str_value = sym.user_tri_value = None sym._invalidate() for choice in self._choices: - choice.user_value = choice.user_selection = None + choice.user_str_value = choice.user_tri_value = \ + choice.user_selection = None choice._invalidate() def enable_warnings(self): @@ -616,7 +620,7 @@ class Config(object): 'config symbol prefix "{}"'.format(self.config_prefix), "warnings " + ("enabled" if self._print_warnings else "disabled"), "undef. symbol assignment warnings " + - ("enabled" if self._print_undef_assign else "disabled") + ("enabled" if self._print_undef_assign else "disabled"), ) return "<{}>".format(", ".join(fields)) @@ -1007,10 +1011,7 @@ class Config(object): prev_node.next = prev_node = node elif t0 == _T_SOURCE: - kconfig_file = self._next_token() - exp_kconfig_file = self._expand_sym_refs(kconfig_file) - - self._enter_file(exp_kconfig_file) + self._enter_file(self._expand_sym_refs(self._next_token())) prev_node = self._parse_block(None, # end_token parent, visible_if_deps, @@ -1030,8 +1031,7 @@ class Config(object): node.parent = parent node.filename = self._filename node.linenr = self._linenr - node.dep = \ - self._make_and(parent.dep, self._parse_expr(True)) + node.dep = self._make_and(parent.dep, self._parse_expr(True)) self._parse_block(_T_ENDIF, node, # parent @@ -1259,16 +1259,10 @@ class Config(object): node.item.env_var = env_var if env_var not in os.environ: - self._warn("the symbol {0} references the " - "non-existent environment variable {1} " - "(meaning the 'option env=\"{1}\"' will " - "have no effect). If you're using " - "Kconfiglib via 'make (i)scriptconfig', it " - "should have set up the environment " - "correctly for you. If you still got this " - "message, that might be an error, and you " - "should email ulfalizer a.t Google's email " - "service.".format(node.item.name, env_var), + self._warn("'option env=\"{0}\"' on symbol {1} will " + "have no effect, because the environment " + "variable {0} is not set" + .format(node.item.name, env_var), self._filename, self._linenr) else: defaults.append( @@ -1565,9 +1559,9 @@ class Config(object): add_fn(config_string) sym._already_written = True - elif (node.item == MENU and eval_expr(node.dep) != "n" and - eval_expr(node.visibility) != "n") or \ - (node.item == COMMENT and eval_expr(node.dep) != "n"): + elif eval_expr(node.dep) and \ + ((node.item == MENU and eval_expr(node.visibility)) or + node.item == COMMENT): add_fn("\n#\n# {}\n#\n".format(node.prompt[0])) @@ -1669,13 +1663,13 @@ class Config(object): while 1: sym_ref_match = _sym_ref_re_search(s) - if sym_ref_match is None: + if not sym_ref_match: return s sym = self.syms.get(sym_ref_match.group(1)) s = s[:sym_ref_match.start()] + \ - (sym.value if sym is not None else "") + \ + (sym.str_value if sym is not None else "") + \ s[sym_ref_match.end():] # @@ -1772,10 +1766,14 @@ class Symbol(object): menuconfig-like functionality. (Check the implementation of the property if you need to get the original type.) - value: + str_value: + TODO The current value of the symbol. Automatically recalculated as dependencies change. + tri_value: + TODO + assignable: A string containing the tristate values that can be assigned to the symbol, ordered from lowest (n) to highest (y). This corresponds to the @@ -1819,13 +1817,23 @@ class Symbol(object): dependencies) are propagated to the prompt dependencies. Additional dependencies can be specified with e.g. 'bool "foo" if <cond>". - user_value: - The value assigned with Symbol.set_value(), or None if no value has been - assigned. This won't necessarily match 'value' even if set, as - dependencies and prompt visibility take precedence. + user_str_value: + The string value assigned with Symbol.set_value(), or None if no value + has been assigned. This won't necessarily match 'str_value' even if set, + as dependencies and prompt visibility take precedence. + + Note that you should use Symbol.set_value() to change this value (which + will also change user_tri_value). Changing the value directly will break + things, as Kconfiglib might need to invalidate other symbols. Properties + are always read-only. + + The string value is only used in comparisons (e.g. + 'depends on SYMBOL = "foo"'). See user_tri_value. - Note that you should use Symbol.set_value() to change this value. - Properties are always read-only. + user_tri_value: + The tristate value corresponding to user_str_value. The rule is that "n", + "m", and "y" correspond to 0, 1, and 2 for BOOL and TRISTATE symbols. + Other symbol types always evaluate to 0 (n) in a tristate sense. config_string: The .config assignment string that would get written out for the symbol @@ -1917,7 +1925,8 @@ class Symbol(object): "_already_written", "_cached_assignable", "_cached_deps", - "_cached_val", + "_cached_str_val", + "_cached_tri_val", "_cached_vis", "_direct_dependents", "_type", @@ -1935,7 +1944,8 @@ class Symbol(object): "ranges", "rev_dep", "selects", - "user_value", + "user_str_value", + "user_tri_value", "weak_rev_dep", ) @@ -1950,138 +1960,79 @@ class Symbol(object): """ if self._type == TRISTATE and \ - ((self.choice is not None and self.choice.value == "y") or - self.config.modules.value == "n"): + ((self.choice is not None and self.choice.tri_value == 2) or + not self.config.modules.tri_value): return BOOL return self._type @property - def value(self): + def str_value(self): """ See the class documentation. """ - if self._cached_val is not None: - return self._cached_val + if self._cached_str_val is not None: + return self._cached_str_val + + if self._type in (BOOL, TRISTATE): + self._cached_str_val = TRI_TO_STR[self.tri_value] + return self._cached_str_val # As a quirk of Kconfig, undefined symbols get their name as their - # value. This is why things like "FOO = bar" work for seeing if FOO has - # the value "bar". + # string value. This is why things like "FOO = bar" work for seeing if + # FOO has the value "bar". if self._type == UNKNOWN: - self._cached_val = self.name + self._cached_str_val = self.name return self.name - # This will hold the value at the end of the function - val = _DEFAULT_VALUE[self._type] - + val = "" vis = self.visibility - if self._type in (BOOL, TRISTATE): - if self.choice is None: - self._write_to_conf = (vis != "n") + self._write_to_conf = (vis != 0) - if vis != "n" and self.user_value is not None: - # If the symbol is visible and has a user value, we use - # that - val = _tri_min(self.user_value, vis) - - else: - # Otherwise, we look at defaults and weak reverse - # dependencies (implies) - - for default, cond in self.defaults: - cond_val = eval_expr(cond) - if cond_val != "n": - self._write_to_conf = True - val = _tri_min(eval_expr(default), cond_val) - break - - # Weak reverse dependencies are only considered if our - # direct dependencies are met - if eval_expr(self.direct_dep) != "n": - weak_rev_dep_val = \ - eval_expr(self.weak_rev_dep) - if weak_rev_dep_val != "n": - self._write_to_conf = True - val = _tri_max(val, weak_rev_dep_val) - - # Reverse (select-related) dependencies take precedence - rev_dep_val = eval_expr(self.rev_dep) - if rev_dep_val != "n": - self._write_to_conf = True - val = _tri_max(val, rev_dep_val) - - else: - # (bool/tristate) symbol in choice. See _get_visibility() for - # more choice-related logic. - - # Initially - self._write_to_conf = False - - if vis != "n": - mode = self.choice.value - - if mode != "n": - self._write_to_conf = True - - if mode == "y": - val = "y" if self.choice.selection is self else "n" - elif self.user_value in ("m", "y"): - # mode == "m" and self.user_value is not None or - # "n" - val = "m" - - # "m" is promoted to "y" in two circumstances: - # 1) If our type is boolean - # 2) If our weak_rev_dep (from IMPLY) is "y" - if val == "m" and \ - (self.type == BOOL or eval_expr(self.weak_rev_dep) == "y"): - val = "y" - - elif self._type in (INT, HEX): + if self._type in (INT, HEX): base = _TYPE_TO_BASE[self._type] # Check if a range is in effect for low_expr, high_expr, cond_expr in self.ranges: - if eval_expr(cond_expr) != "n": + if eval_expr(cond_expr): has_active_range = True - low = int(low_expr.value, base) if \ - _is_base_n(low_expr.value, base) else 0 - high = int(high_expr.value, base) if \ - _is_base_n(high_expr.value, base) else 0 + low = int(low_expr.str_value, base) if \ + _is_base_n(low_expr.str_value, base) else 0 + high = int(high_expr.str_value, base) if \ + _is_base_n(high_expr.str_value, base) else 0 break else: has_active_range = False - self._write_to_conf = (vis != "n") - - if vis != "n" and self.user_value is not None and \ - _is_base_n(self.user_value, base) and \ + if vis and self.user_str_value is not None and \ + _is_base_n(self.user_str_value, base) and \ (not has_active_range or - low <= int(self.user_value, base) <= high): + low <= int(self.user_str_value, base) <= high): # If the user value is well-formed and satisfies range # contraints, it is stored in exactly the same form as # specified in the assignment (with or without "0x", etc.) - val = self.user_value + val = self.user_str_value else: # No user value or invalid user value. Look at defaults. for val_expr, cond_expr in self.defaults: - if eval_expr(cond_expr) != "n": + if eval_expr(cond_expr): self._write_to_conf = True # Similarly to above, well-formed defaults are # preserved as is. Defaults that do not satisfy a range # constraints are clamped and take on a standard form. - val = val_expr.value + val = val_expr.str_value if _is_base_n(val, base): val_num = int(val, base) + # TODO: move outside? if has_active_range: clamped_val = None @@ -2105,18 +2056,93 @@ class Symbol(object): val = (hex(low) if self._type == HEX else str(low)) elif self._type == STRING: - self._write_to_conf = (vis != "n") - - if vis != "n" and self.user_value is not None: - val = self.user_value + if vis and self.user_str_value is not None: + val = self.user_str_value else: for val_expr, cond_expr in self.defaults: - if eval_expr(cond_expr) != "n": + if eval_expr(cond_expr): self._write_to_conf = True - val = val_expr.value + val = val_expr.str_value break - self._cached_val = val + self._cached_str_val = val + return val + + @property + def tri_value(self): + """ + See the class documentation. + """ + + if self._cached_tri_val is not None: + return self._cached_tri_val + + if self._type not in (BOOL, TRISTATE): + self._cached_tri_val = 0 + return self._cached_tri_val + + val = 0 + vis = self.visibility + + if self.choice is None: + self._write_to_conf = (vis != 0) + + if vis and self.user_tri_value is not None: + # If the symbol is visible and has a user value, we use that + val = min(self.user_tri_value, vis) + + else: + # Otherwise, we look at defaults and weak reverse dependencies + # (implies) + + for default, cond in self.defaults: + cond_val = eval_expr(cond) + if cond_val: + val = min(cond_val, eval_expr(default)) + self._write_to_conf = True + break + + # Weak reverse dependencies are only considered if our + # direct dependencies are met + if eval_expr(self.direct_dep): + weak_rev_dep_val = eval_expr(self.weak_rev_dep) + if weak_rev_dep_val: + val = max(weak_rev_dep_val, val) + self._write_to_conf = True + + # Reverse (select-related) dependencies take precedence + rev_dep_val = eval_expr(self.rev_dep) + if rev_dep_val: + val = max(rev_dep_val, val) + self._write_to_conf = True + + else: + # (bool/tristate) symbol in choice. See _get_visibility() for + # more choice-related logic. + + # Initially + self._write_to_conf = False + + if vis: + mode = self.choice.tri_value + + if mode: + self._write_to_conf = True + + if mode == 2: + val = 2 if self.choice.selection is self else 0 + elif self.user_tri_value: + # mode == 1, user value available and not 0 + val = 1 + + # m is promoted to y in two circumstances: + # 1) If our type is boolean + # 2) If our weak_rev_dep (from IMPLY) is y + if val == 1 and \ + (self.type == BOOL or eval_expr(self.weak_rev_dep) == 2): + val = 2 + + self._cached_tri_val = val return val @property @@ -2152,8 +2178,9 @@ class Symbol(object): # corresponds to the SYMBOL_AUTO flag in the C implementation. return None - # Note: _write_to_conf is determined when the value is calculated - val = self.value + # Note: _write_to_conf is determined when the value is calculated. This + # is a hidden function call due to property magic. + val = self.str_value if not self._write_to_conf: return None @@ -2184,10 +2211,11 @@ class Symbol(object): Equal in effect to assigning the value to the symbol within a .config file. Use the 'assignable' attribute to check which values can currently be assigned. Setting values outside 'assignable' will cause - Symbol.user_value to differ from Symbol.value (be truncated down or - up). Values that are invalid for the type (such as "foo" or "m" for a - BOOL) are ignored (and won't be stored in Symbol.user_value). A warning - is printed for attempts to assign invalid values. + Symbol.user_str/tri_value to differ from Symbol.str/tri_value (be + truncated down or up). Values that are invalid for the type (such as + "foo" or "m" for a BOOL) are ignored (and won't be stored in + Symbol.user_str/tri_value). A warning is printed for attempts to assign + invalid values. The values of other symbols that depend on this symbol are automatically recalculated to reflect the new value. @@ -2208,7 +2236,7 @@ class Symbol(object): Resets the user value of the symbol, as if the symbol had never gotten a user value via Config.load_config() or Symbol.set_value(). """ - self.user_value = None + self.user_str_value = self.user_tri_value = None self._rec_invalidate() def __str__(self): @@ -2229,17 +2257,17 @@ class Symbol(object): def __repr__(self): """ Prints some information about the symbol (including its name, value, - and visibility) when it is evaluated. + visibility, and location(s)) when it is evaluated. """ fields = [ "symbol " + self.name, _TYPENAME[self.type], - 'value "{}"'.format(self.value), - "visibility {}".format(self.visibility) + 'value "{}"'.format(self.str_value), + "visibility " + TRI_TO_STR[self.visibility], ] - if self.user_value is not None: - fields.append('user value "{}"'.format(self.user_value)) + if self.user_str_value is not None: + fields.append('user value "{}"'.format(self.user_str_value)) if self.choice is not None: fields.append("choice symbol") @@ -2256,11 +2284,13 @@ class Symbol(object): if self is self.config.modules: fields.append("is the modules symbol") - fields.append("direct deps " + eval_expr(self.direct_dep)) + fields.append("direct deps " + TRI_TO_STR[eval_expr(self.direct_dep)]) - fields.append("{} menu node{}" - .format(len(self.nodes), - "" if len(self.nodes) == 1 else "s")) + if self.nodes: + for node in self.nodes: + fields.append("{}:{}".format(node.filename, node.linenr)) + else: + fields.append("undefined") return "<{}>".format(", ".join(fields)) @@ -2292,7 +2322,7 @@ class Symbol(object): self.nodes = [] - self.user_value = None + self.user_str_value = self.user_tri_value = None # Populated in Config._build_dep() after parsing. Links the symbol to # the symbols that immediately depend on it (in a caching/invalidation @@ -2302,15 +2332,8 @@ class Symbol(object): # Cached values - # Caches the calculated value - self._cached_val = None - # Caches the visibility - self._cached_vis = None - # Caches the total list of dependent symbols. Calculated in - # _get_dependent(). - self._cached_deps = None - # Caches the 'assignable' attribute - self._cached_assignable = None + self._cached_str_val = self._cached_tri_val = self._cached_vis = \ + self._cached_deps = self._cached_assignable = None # Flags @@ -2332,35 +2355,35 @@ class Symbol(object): vis = self.visibility - if vis == "n": + if not vis: return "" rev_dep_val = eval_expr(self.rev_dep) - if vis == "y": - if rev_dep_val == "n": - if self.type == BOOL or eval_expr(self.weak_rev_dep) == "y": + if vis == 2: + if not rev_dep_val: + if self.type == BOOL or eval_expr(self.weak_rev_dep) == 2: return "ny" return "nmy" - if rev_dep_val == "y": + if rev_dep_val == 2: return "y" - # rev_dep_val == "m" + # rev_dep_val == 1 - if self.type == BOOL or eval_expr(self.weak_rev_dep) == "y": + if self.type == BOOL or eval_expr(self.weak_rev_dep) == 2: return "y" return "my" - # vis == "m" + # vis == 1 - if rev_dep_val == "n": - return "m" if eval_expr(self.weak_rev_dep) != "y" else "y" + if not rev_dep_val: + return "m" if eval_expr(self.weak_rev_dep) != 2 else "y" - if rev_dep_val == "y": + if rev_dep_val == 2: return "y" - # vis == "m", rev_dep == "m" (rare) + # vis == rev_dep_val == 1 return "m" @@ -2399,20 +2422,29 @@ class Symbol(object): "promptless symbol {} will have no effect" .format(value, self.name)) - self.user_value = value + self.user_str_value = value + self.user_tri_value = \ + STR_TO_TRI[value] \ + if self._type in (BOOL, TRISTATE) else \ + 0 + + # TODO: assigning automatically changes choice yada yada - if self.choice is not None and self._type in (BOOL, TRISTATE): - if value == "y": - self.choice.user_value = "y" + if self.choice is not None: + if self.user_tri_value == 2: + self.choice.user_str_value = "y" + self.choice.user_tri_value = 2 self.choice.user_selection = self - elif value == "m": - self.choice.user_value = "m" + elif self.user_tri_value == 1: + self.choice.user_str_value = "m" + self.choice.user_tri_value = 1 def _invalidate(self): """ Marks the symbol as needing to be recalculated. """ - self._cached_val = self._cached_vis = self._cached_assignable = None + self._cached_str_val = self._cached_tri_val = self._cached_vis = \ + self._cached_assignable = None def _rec_invalidate(self): """ @@ -2531,10 +2563,13 @@ class Choice(object): The symbol that would be selected by default, had the user not selected any symbol. Can be None for the same reasons as 'selected'. - user_value: + user_str_value: TODO The value (mode) selected by the user (by assigning some choice symbol or calling Choice.set_value()). This does not necessarily match Choice.value - for the same reasons that Symbol.user_value might not match Symbol.value. + for the same reasons that Symbol.user_str_value might not match + Symbol.value. + + user_tri_value: TODO user_selection: The symbol selected by the user (by setting it to "y"). Ignored if the @@ -2585,7 +2620,8 @@ class Choice(object): "nodes", "syms", "user_selection", - "user_value", + "user_str_value", + "user_tri_value", ) # @@ -2595,25 +2631,32 @@ class Choice(object): @property def type(self): """Returns the type of the choice. See Symbol.type.""" - if self._type == TRISTATE and self.config.modules.value == "n": + if self._type == TRISTATE and not self.config.modules.tri_value: return BOOL return self._type @property - def value(self): + def str_value(self): """ See the class documentation. """ - if self.user_value is not None: - val = _tri_min(self.user_value, self.visibility) + return TRI_TO_STR[self.tri_value] + + @property + def tri_value(self): + """ + See the class documentation. + """ + if self.user_tri_value is not None: + val = min(self.user_tri_value, self.visibility) else: - val = "n" + val = 0 - if val == "n" and not self.is_optional: - val = "m" + if not val and not self.is_optional: + val = 1 # Promote "m" to "y" for boolean choices - return "y" if val == "m" and self.type == BOOL else val + return 2 if val == 1 and self.type == BOOL else val @property def assignable(self): @@ -2645,13 +2688,13 @@ class Choice(object): if self._cached_selection is not _NO_CACHED_SELECTION: return self._cached_selection - if self.value != "y": + if self.tri_value != 2: self._cached_selection = None return None # User choice available? if self.user_selection is not None and \ - self.user_selection.visibility == "y": + self.user_selection.visibility == 2: self._cached_selection = self.user_selection return self.user_selection @@ -2666,14 +2709,12 @@ class Choice(object): See the class documentation. """ for sym, cond_expr in self.defaults: - if (eval_expr(cond_expr) != "n" and - # Must be visible too - sym.visibility != "n"): + if eval_expr(cond_expr) and sym.visibility: return sym # Otherwise, pick the first visible symbol, if any for sym in self.syms: - if sym.visibility != "n": + if sym.visibility: return sym # Couldn't find a default @@ -2692,7 +2733,8 @@ class Choice(object): "which has type {}. Assignment ignored" .format(value, _TYPENAME[self._type])) - self.user_value = value + self.user_str_value = value + self.user_tri_value = STR_TO_TRI[value] if self.syms: # Hackish way to invalidate the choice and all the choice symbols @@ -2703,7 +2745,7 @@ class Choice(object): Resets the user value (mode) and user selection of the Choice, as if the user had never touched the mode or any of the choice symbols. """ - self.user_value = self.user_selection = None + self.user_str_value = self.user_tri_value = self.user_selection = None if self.syms: # Hackish way to invalidate the choice and all the choice symbols self.syms[0]._rec_invalidate() @@ -2716,11 +2758,14 @@ class Choice(object): return _sym_choice_str(self) def __repr__(self): + """ + TODO + """ fields = [ "choice" if self.name is None else "choice " + self.name, _TYPENAME[self.type], - "mode " + self.value, - "visibility " + self.visibility + "mode " + self.str_value, + "visibility " + TRI_TO_STR[self.visibility], ] if self.is_optional: @@ -2729,13 +2774,11 @@ class Choice(object): if self.selection is not None: fields.append("{} selected".format(self.selection.name)) - fields.append("{} menu node{}" - .format(len(self.nodes), - "" if len(self.nodes) == 1 else "s")) + for node in self.nodes: + fields.append("{}:{}".format(node.filename, node.linenr)) return "<{}>".format(", ".join(fields)) - # # Private methods # @@ -2757,17 +2800,15 @@ class Choice(object): self.nodes = [] - self.user_value = None - self.user_selection = None + self.user_str_value = self.user_tri_value = self.user_selection = None # The prompts and default values without any dependencies from # enclosing menus and ifs propagated self.defaults = [] # Cached values + self._cached_vis = self._cached_assignable = None self._cached_selection = _NO_CACHED_SELECTION - self._cached_vis = None - self._cached_assignable = None self.is_optional = False @@ -2778,21 +2819,21 @@ class Choice(object): vis = self.visibility - if vis == "n": + if not vis: return "" - if vis == "y": + if vis == 2: if not self.is_optional: return "y" if self.type == BOOL else "my" return "y" - # vis == "m" + # vis == 1 return "nm" if self.is_optional else "m" def _invalidate(self): - self._cached_selection = _NO_CACHED_SELECTION self._cached_vis = self._cached_assignable = None + self._cached_selection = _NO_CACHED_SELECTION class MenuNode(object): """ @@ -2920,15 +2961,17 @@ class MenuNode(object): if self.prompt is not None: fields.append('prompt "{}" (visibility {})' - .format(self.prompt[0], eval_expr(self.prompt[1]))) + .format(self.prompt[0], + TRI_TO_STR[eval_expr(self.prompt[1])])) if isinstance(self.item, Symbol) and self.is_menuconfig: fields.append("is menuconfig") - fields.append("deps " + eval_expr(self.dep)) + fields.append("deps " + TRI_TO_STR[eval_expr(self.dep)]) if self.item == MENU: - fields.append("'visible if' deps " + eval_expr(self.visibility)) + fields.append("'visible if' deps " + \ + TRI_TO_STR[eval_expr(self.visibility)]) if isinstance(self.item, (Symbol, Choice)) and self.help is not None: fields.append("has help") @@ -2957,65 +3000,26 @@ class InternalError(Exception): # Public functions # -def tri_less(v1, v2): - """ - Returns True if the tristate v1 is less than the tristate v2, where "n", - "m" and "y" are ordered from lowest to highest. - """ - return _TRI_TO_INT[v1] < _TRI_TO_INT[v2] - -def tri_less_eq(v1, v2): - """ - Returns True if the tristate v1 is less than or equal to the tristate v2, - where "n", "m" and "y" are ordered from lowest to highest. - """ - return _TRI_TO_INT[v1] <= _TRI_TO_INT[v2] - -def tri_greater(v1, v2): - """ - Returns True if the tristate v1 is greater than the tristate v2, where "n", - "m" and "y" are ordered from lowest to highest. - """ - return _TRI_TO_INT[v1] > _TRI_TO_INT[v2] - -def tri_greater_eq(v1, v2): - """ - Returns True if the tristate v1 is greater than or equal to the tristate - v2, where "n", "m" and "y" are ordered from lowest to highest. - """ - return _TRI_TO_INT[v1] >= _TRI_TO_INT[v2] - -# Expression evaluation - def eval_expr(expr): """ - Evaluates an expression to "n", "m", or "y". + TODO """ - if isinstance(expr, Symbol): - # Non-bool/tristate symbols are always "n" in a tristate sense, - # regardless of their value - return expr.value if expr._type in (BOOL, TRISTATE) else "n" + return expr.tri_value if expr[0] == AND: - ev1 = eval_expr(expr[1]) - - # Short-circuit the ev1 == "n" case - return "n" if ev1 == "n" else \ - _tri_min(ev1, eval_expr(expr[2])) + v1 = eval_expr(expr[1]) + # Short-circuit the n case as an optimization (~5% faster + # allnoconfig.py and allyesconfig.py, as of writing) + return 0 if not v1 else min(v1, eval_expr(expr[2])) if expr[0] == OR: - ev1 = eval_expr(expr[1]) - - # Short-circuit the ev1 == "y" case - return "y" if ev1 == "y" else \ - _tri_max(ev1, eval_expr(expr[2])) + v1 = eval_expr(expr[1]) + # Short-circuit the y case as an optimization + return 2 if v1 == 2 else max(v1, eval_expr(expr[2])) if expr[0] == NOT: - ev = eval_expr(expr[1]) - return "n" if ev == "y" else \ - "y" if ev == "n" else \ - "m" + return 2 - eval_expr(expr[1]) if expr[0] in _RELATIONS: # Implements <, <=, >, >= comparisons as well. These were added to @@ -3030,16 +3034,16 @@ def eval_expr(expr): # If both operands are strings... if op1._type == STRING and op2._type == STRING: # ...then compare them lexicographically - comp = _strcmp(op1.value, op2.value) + comp = _strcmp(op1.str_value, op2.str_value) else: # Otherwise, try to compare them as numbers... try: - comp = int(op1.value, _TYPE_TO_BASE[op1._type]) - \ - int(op2.value, _TYPE_TO_BASE[op2._type]) + comp = int(op1.str_value, _TYPE_TO_BASE[op1._type]) - \ + int(op2.str_value, _TYPE_TO_BASE[op2._type]) except ValueError: # Fall back on a lexicographic comparison if the operands don't # parse as numbers - comp = _strcmp(op1.value, op2.value) + comp = _strcmp(op1.str_value, op2.str_value) if oper == EQUAL: res = comp == 0 elif oper == UNEQUAL: res = comp != 0 @@ -3048,12 +3052,15 @@ def eval_expr(expr): elif oper == GREATER: res = comp > 0 elif oper == GREATER_EQUAL: res = comp >= 0 - return "y" if res else "n" + return 2*res _internal_error("Internal error while evaluating expression: " "unknown operation {}.".format(expr[0])) def expr_str(expr): + """ + TODO + """ if isinstance(expr, Symbol): return expr.name if not expr.is_constant else '"{}"'.format(expr.name) @@ -3085,47 +3092,35 @@ def _get_visibility(sc): 'make menuconfig'. This function calculates the visibility for the Symbol or Choice 'sc' -- the logic is nearly identical. """ - vis = "n" + vis = 0 for node in sc.nodes: if node.prompt: - vis = _tri_max(vis, eval_expr(node.prompt[1])) + vis = max(vis, eval_expr(node.prompt[1])) if isinstance(sc, Symbol) and sc.choice is not None: if sc.choice._type == TRISTATE and sc._type != TRISTATE and \ - sc.choice.value != "y": + sc.choice.tri_value != 2: # Non-tristate choice symbols in tristate choices depend on the # choice being in mode "y" - return "n" + return 0 - if sc._type == TRISTATE and vis == "m" and sc.choice.value == "y": + if sc._type == TRISTATE and vis == 1 and sc.choice.tri_value == 2: # Choice symbols with visibility "m" are not visible if the # choice has mode "y" - return "n" + return 0 - vis = _tri_min(vis, sc.choice.visibility) + vis = min(vis, sc.choice.visibility) - # Promote "m" to "y" if we're dealing with a non-tristate. This might lead - # to infinite recursion if something really weird is done with MODULES, but + # Promote m to y if we're dealing with a non-tristate. This might lead to + # infinite recursion if something really weird is done with MODULES, but # it's not a problem in practice. - if vis == "m" and \ - (sc._type != TRISTATE or sc.config.modules.value == "n"): - return "y" + if vis == 1 and \ + (sc._type != TRISTATE or not sc.config.modules.tri_value): + return 2 return vis -def _tri_min(v1, v2): - """ - Returns the smallest tristate value among v1 and v2. - """ - return v1 if _TRI_TO_INT[v1] <= _TRI_TO_INT[v2] else v2 - -def _tri_max(v1, v2): - """ - Returns the largest tristate value among v1 and v2. - """ - return v1 if _TRI_TO_INT[v1] >= _TRI_TO_INT[v2] else v2 - def _make_depend_on(sym, expr): """ Adds 'sym' as a dependency to all symbols in 'expr'. Constant symbols in @@ -3192,10 +3187,8 @@ def _strcmp(s1, s2): return (s1 > s2) - (s1 < s2) def _stderr_msg(msg, filename, linenr): - if filename is None: - s = msg - else: - s = "{}:{}: ".format(filename, linenr) + if filename is not None: + msg = "{}:{}: {}".format(filename, linenr, msg) sys.stderr.write(msg + "\n") @@ -3509,6 +3502,18 @@ def _finalize_tree(node): COMMENT, ) = range(2) +TRI_TO_STR = { + 0: "n", + 1: "m", + 2: "y", +} + +STR_TO_TRI = { + "n": 0, + "m": 1, + "y": 2, +} + # # Internal global constants # @@ -3643,12 +3648,12 @@ _sym_ref_re_search = re.compile(r"\$([A-Za-z0-9_]+)").search # Strings to use for types _TYPENAME = { - UNKNOWN: "unknown", - BOOL: "bool", + UNKNOWN: "unknown", + BOOL: "bool", TRISTATE: "tristate", - STRING: "string", - HEX: "hex", - INT: "int", + STRING: "string", + HEX: "hex", + INT: "int", } # Token to type mapping @@ -3662,16 +3667,6 @@ _TOKEN_TO_TYPE = { _T_TRISTATE: TRISTATE, } -# Default values for symbols of different types (the value the symbol gets if -# it is not assigned a user value and none of its 'default' clauses kick in) -_DEFAULT_VALUE = { - BOOL: "n", - TRISTATE: "n", - HEX: "", - INT: "", - STRING: "", -} - # Constant representing that there's no cached choice selection. This is # distinct from a cached None (no selection). We create a unique object (any # will do) for it so we can test with 'is'. diff --git a/testsuite.py b/testsuite.py index e81ba1d..711a0fb 100644 --- a/testsuite.py +++ b/testsuite.py @@ -168,9 +168,9 @@ def run_selftests(): Verifies that a symbol has a particular value. """ sym = c.syms[sym_name] - verify(sym.value == val, + verify(sym.str_value == val, 'expected {} to have the value "{}", had the value "{}"' - .format(sym_name, val, sym.value)) + .format(sym_name, val, sym.str_value)) def assign_and_verify_value(sym_name, val, new_val): """ @@ -178,13 +178,13 @@ def run_selftests(): 'new_val'. """ sym = c.syms[sym_name] - old_val = sym.value + old_val = sym.str_value sym.set_value(val) - verify(sym.value == new_val, + verify(sym.str_value == new_val, 'expected {} to have the value "{}" after being assigned the ' 'value "{}". Instead, the value is "{}". The old value was ' '"{}".' - .format(sym_name, new_val, val, sym.value, old_val)) + .format(sym_name, new_val, val, sym.str_value, old_val)) def assign_and_verify(sym_name, user_val): """ @@ -197,51 +197,19 @@ def run_selftests(): """Assigns a user value to the symbol and verifies the new user value.""" sym = c.syms[sym_name] - sym_old_user_val = sym.user_value + sym_old_user_val = sym.user_str_value sym.set_value(val) - verify(sym.user_value == user_val, + verify(sym.user_str_value == user_val, "{} should have the user value '{}' after being assigned " "the user value '{}'. Instead, the new user value was '{}'. " "The old user value was '{}'." - .format(sym_name, user_val, user_val, sym.user_value, + .format(sym_name, user_val, user_val, sym.user_str_value, sym_old_user_val)) # # Selftests # - print("Testing tristate comparisons") - - def verify_truth_table(comp_fn, *table): - for (x, y), expected in zip((("n", "n"), ("n", "m"), ("n", "y"), - ("m", "n"), ("m", "m"), ("m", "y"), - ("y", "n"), ("y", "m"), ("y", "y")), - table): - verify(comp_fn(x, y) == expected, - "expected {} on ('{}', '{}') to be '{}'". - format(comp_fn, x, y, expected)) - - verify_truth_table(kconfiglib.tri_less, - False, True, True, - False, False, True, - False, False, False) - - verify_truth_table(kconfiglib.tri_less_eq, - True, True, True, - False, True, True, - False, False, True) - - verify_truth_table(kconfiglib.tri_greater, - False, False, False, - True, False, False, - True, True, False) - - verify_truth_table(kconfiglib.tri_greater_eq, - True, False, False, - True, True, False, - True, True, True) - - print("Testing string literal lexing") # Dummy empty configuration just to get a Config object @@ -250,14 +218,12 @@ def run_selftests(): def verify_string_lex(s, res): """ Verifies that a constant symbol with the name 'res' is produced from - lexing 's'. Strips the first and last characters from 's' so that - readable raw strings can be used as input + lexing 's' """ - c._line = s[1:-1] - c._tokenize(True) + c.eval_string(s) verify(c._tokens[0].name == res, - 'expected {} to produced the constant symbol {}, produced {}' - .format(s, c._tokens[0].name, res)) + "expected <{}> to produced the constant symbol <{}>, " + 'produced <{}>'.format(s[1:-1], c._tokens[0].name, res)) verify_string_lex(r""" "" """, "") verify_string_lex(r""" '' """, "") @@ -293,13 +259,12 @@ def run_selftests(): first and last characters from 's' so we can use readable raw strings as input. """ - c._line = s[1:-1] try: - c._tokenize(True) + c.eval_string(s) except kconfiglib.KconfigSyntaxError: pass else: - fail("expected tokenization of {} to fail, didn't".format(s)) + fail("expected tokenization of {} to fail, didn't".format(s[1:-1])) verify_string_bad(r""" " """) verify_string_bad(r""" ' """) @@ -323,168 +288,168 @@ def run_selftests(): "'{}' evaluated to {}, expected {}".format(expr, res, val)) # No modules - verify_eval("n", "n") - verify_eval("m", "n") - verify_eval("y", "y") - verify_eval("'n'", "n") - verify_eval("'m'", "n") - verify_eval("'y'", "y") - verify_eval("M", "y") + verify_eval("n", 0) + verify_eval("m", 0) + verify_eval("y", 2) + verify_eval("'n'", 0) + verify_eval("'m'", 0) + verify_eval("'y'", 2) + verify_eval("M", 2) # Modules - c.syms["MODULES"].set_value("y") - verify_eval("n", "n") - verify_eval("m", "m") - verify_eval("y", "y") - verify_eval("'n'", "n") - verify_eval("'m'", "m") - verify_eval("'y'", "y") - verify_eval("M", "m") - verify_eval("(Y || N) && (m && y)", "m") + c.modules.set_value("y") + verify_eval("n", 0) + verify_eval("m", 1) + verify_eval("y", 2) + verify_eval("'n'", 0) + verify_eval("'m'", 1) + verify_eval("'y'", 2) + verify_eval("M", 1) + verify_eval("(Y || N) && (m && y)", 1) # Non-bool/non-tristate symbols are always "n" in a tristate sense - verify_eval("Y_STRING", "n") - verify_eval("Y_STRING || m", "m") + verify_eval("Y_STRING", 0) + verify_eval("Y_STRING || m", 1) # As are all constants besides "y" and "m" - verify_eval('"foo"', "n") - verify_eval('"foo" || "bar"', "n") - verify_eval('"foo" || m', "m") + verify_eval('"foo"', 0) + verify_eval('"foo" || "bar"', 0) + verify_eval('"foo" || m', 1) # Test equality for symbols - verify_eval("N = N", "y") - verify_eval("N = n", "y") - verify_eval("N = 'n'", "y") - verify_eval("N != N", "n") - verify_eval("N != n", "n") - verify_eval("N != 'n'", "n") - - verify_eval("M = M", "y") - verify_eval("M = m", "y") - verify_eval("M = 'm'", "y") - verify_eval("M != M", "n") - verify_eval("M != m", "n") - verify_eval("M != 'm'", "n") - - verify_eval("Y = Y", "y") - verify_eval("Y = y", "y") - verify_eval("Y = 'y'", "y") - verify_eval("Y != Y", "n") - verify_eval("Y != y", "n") - verify_eval("Y != 'y'", "n") - - verify_eval("N != M", "y") - verify_eval("N != Y", "y") - verify_eval("M != Y", "y") - - verify_eval("Y_STRING = y", "y") - verify_eval("Y_STRING = 'y'", "y") - verify_eval('FOO_BAR_STRING = "foo bar"', "y") - verify_eval('FOO_BAR_STRING != "foo bar baz"', "y") - verify_eval('INT_37 = 37', "y") - verify_eval("INT_37 = '37'", "y") - verify_eval('HEX_0X37 = 0x37', "y") - verify_eval("HEX_0X37 = '0x37'", "y") + verify_eval("N = N", 2) + verify_eval("N = n", 2) + verify_eval("N = 'n'", 2) + verify_eval("N != N", 0) + verify_eval("N != n", 0) + verify_eval("N != 'n'", 0) + + verify_eval("M = M", 2) + verify_eval("M = m", 2) + verify_eval("M = 'm'", 2) + verify_eval("M != M", 0) + verify_eval("M != m", 0) + verify_eval("M != 'm'", 0) + + verify_eval("Y = Y", 2) + verify_eval("Y = y", 2) + verify_eval("Y = 'y'", 2) + verify_eval("Y != Y", 0) + verify_eval("Y != y", 0) + verify_eval("Y != 'y'", 0) + + verify_eval("N != M", 2) + verify_eval("N != Y", 2) + verify_eval("M != Y", 2) + + verify_eval("Y_STRING = y", 2) + verify_eval("Y_STRING = 'y'", 2) + verify_eval('FOO_BAR_STRING = "foo bar"', 2) + verify_eval('FOO_BAR_STRING != "foo bar baz"', 2) + verify_eval('INT_37 = 37', 2) + verify_eval("INT_37 = '37'", 2) + verify_eval('HEX_0X37 = 0x37', 2) + verify_eval("HEX_0X37 = '0x37'", 2) # These should also hold after 31847b67 (kconfig: allow use of relations # other than (in)equality) - verify_eval("HEX_0X37 = '0x037'", "y") - verify_eval("HEX_0X37 = '0x0037'", "y") + verify_eval("HEX_0X37 = '0x037'", 2) + verify_eval("HEX_0X37 = '0x0037'", 2) # Constant symbol comparisons - verify_eval('"foo" != "bar"', "y") - verify_eval('"foo" = "bar"', "n") - verify_eval('"foo" = "foo"', "y") + verify_eval('"foo" != "bar"', 2) + verify_eval('"foo" = "bar"', 0) + verify_eval('"foo" = "foo"', 2) # Undefined symbols get their name as their value c.disable_warnings() - verify_eval("'not_defined' = not_defined", "y") - verify_eval("not_defined_2 = not_defined_2", "y") - verify_eval("not_defined_1 != not_defined_2", "y") + verify_eval("'not_defined' = not_defined", 2) + verify_eval("not_defined_2 = not_defined_2", 2) + verify_eval("not_defined_1 != not_defined_2", 2) # Test less than/greater than # Basic evaluation - verify_eval("INT_37 < 38", "y") - verify_eval("38 < INT_37", "n") - verify_eval("INT_37 < '38'", "y") - verify_eval("'38' < INT_37", "n") - verify_eval("INT_37 < 138", "y") - verify_eval("138 < INT_37", "n") - verify_eval("INT_37 < '138'", "y") - verify_eval("'138' < INT_37", "n") - verify_eval("INT_37 < -138", "n") - verify_eval("-138 < INT_37", "y") - verify_eval("INT_37 < '-138'", "n") - verify_eval("'-138' < INT_37", "y") - verify_eval("INT_37 < 37", "n") - verify_eval("37 < INT_37", "n") - verify_eval("INT_37 < 36", "n") - verify_eval("36 < INT_37", "y") + verify_eval("INT_37 < 38", 2) + verify_eval("38 < INT_37", 0) + verify_eval("INT_37 < '38'", 2) + verify_eval("'38' < INT_37", 0) + verify_eval("INT_37 < 138", 2) + verify_eval("138 < INT_37", 0) + verify_eval("INT_37 < '138'", 2) + verify_eval("'138' < INT_37", 0) + verify_eval("INT_37 < -138", 0) + verify_eval("-138 < INT_37", 2) + verify_eval("INT_37 < '-138'", 0) + verify_eval("'-138' < INT_37", 2) + verify_eval("INT_37 < 37", 0) + verify_eval("37 < INT_37", 0) + verify_eval("INT_37 < 36", 0) + verify_eval("36 < INT_37", 2) # Different formats in comparison - verify_eval("INT_37 < 0x26", "y") # 38 - verify_eval("INT_37 < 0x25", "n") # 37 - verify_eval("INT_37 < 0x24", "n") # 36 - verify_eval("HEX_0X37 < 56", "y") # 0x38 - verify_eval("HEX_0X37 < 55", "n") # 0x37 - verify_eval("HEX_0X37 < 54", "n") # 0x36 + verify_eval("INT_37 < 0x26", 2) # 38 + verify_eval("INT_37 < 0x25", 0) # 37 + verify_eval("INT_37 < 0x24", 0) # 36 + verify_eval("HEX_0X37 < 56", 2) # 0x38 + verify_eval("HEX_0X37 < 55", 0) # 0x37 + verify_eval("HEX_0X37 < 54", 0) # 0x36 # Other int comparisons - verify_eval("INT_37 <= 38", "y") - verify_eval("INT_37 <= 37", "y") - verify_eval("INT_37 <= 36", "n") - verify_eval("INT_37 > 38", "n") - verify_eval("INT_37 > 37", "n") - verify_eval("INT_37 > 36", "y") - verify_eval("INT_37 >= 38", "n") - verify_eval("INT_37 >= 37", "y") - verify_eval("INT_37 >= 36", "y") + verify_eval("INT_37 <= 38", 2) + verify_eval("INT_37 <= 37", 2) + verify_eval("INT_37 <= 36", 0) + verify_eval("INT_37 > 38", 0) + verify_eval("INT_37 > 37", 0) + verify_eval("INT_37 > 36", 2) + verify_eval("INT_37 >= 38", 0) + verify_eval("INT_37 >= 37", 2) + verify_eval("INT_37 >= 36", 2) # Other hex comparisons - verify_eval("HEX_0X37 <= 0x38", "y") - verify_eval("HEX_0X37 <= 0x37", "y") - verify_eval("HEX_0X37 <= 0x36", "n") - verify_eval("HEX_0X37 > 0x38", "n") - verify_eval("HEX_0X37 > 0x37", "n") - verify_eval("HEX_0X37 > 0x36", "y") - verify_eval("HEX_0X37 >= 0x38", "n") - verify_eval("HEX_0X37 >= 0x37", "y") - verify_eval("HEX_0X37 >= 0x36", "y") + verify_eval("HEX_0X37 <= 0x38", 2) + verify_eval("HEX_0X37 <= 0x37", 2) + verify_eval("HEX_0X37 <= 0x36", 0) + verify_eval("HEX_0X37 > 0x38", 0) + verify_eval("HEX_0X37 > 0x37", 0) + verify_eval("HEX_0X37 > 0x36", 2) + verify_eval("HEX_0X37 >= 0x38", 0) + verify_eval("HEX_0X37 >= 0x37", 2) + verify_eval("HEX_0X37 >= 0x36", 2) # A hex holding a value without a "0x" prefix should still be treated as # hexadecimal - verify_eval("HEX_37 < 0x38", "y") - verify_eval("HEX_37 < 0x37", "n") - verify_eval("HEX_37 < 0x36", "n") + verify_eval("HEX_37 < 0x38", 2) + verify_eval("HEX_37 < 0x37", 0) + verify_eval("HEX_37 < 0x36", 0) # Symbol comparisons - verify_eval("INT_37 < HEX_0X37", "y") - verify_eval("INT_37 > HEX_0X37", "n") - verify_eval("HEX_0X37 < INT_37 ", "n") - verify_eval("HEX_0X37 > INT_37 ", "y") - verify_eval("INT_37 < INT_37 ", "n") - verify_eval("INT_37 <= INT_37 ", "y") - verify_eval("INT_37 > INT_37 ", "n") - verify_eval("INT_37 <= INT_37 ", "y") + verify_eval("INT_37 < HEX_0X37", 2) + verify_eval("INT_37 > HEX_0X37", 0) + verify_eval("HEX_0X37 < INT_37 ", 0) + verify_eval("HEX_0X37 > INT_37 ", 2) + verify_eval("INT_37 < INT_37 ", 0) + verify_eval("INT_37 <= INT_37 ", 2) + verify_eval("INT_37 > INT_37 ", 0) + verify_eval("INT_37 <= INT_37 ", 2) # Strings compare lexicographically - verify_eval("'aa' < 'ab'", "y") - verify_eval("'aa' > 'ab'", "n") - verify_eval("'ab' < 'aa'", "n") - verify_eval("'ab' > 'aa'", "y") + verify_eval("'aa' < 'ab'", 2) + verify_eval("'aa' > 'ab'", 0) + verify_eval("'ab' < 'aa'", 0) + verify_eval("'ab' > 'aa'", 2) # Comparisons where one of the operands doesn't parse as a number also give # a lexicographic comparison - verify_eval("INT_37 < '37a' ", "y") - verify_eval("'37a' > INT_37", "y") - verify_eval("INT_37 <= '37a' ", "y") - verify_eval("'37a' >= INT_37", "y") - verify_eval("INT_37 >= '37a' ", "n") - verify_eval("INT_37 > '37a' ", "n") - verify_eval("'37a' < INT_37", "n") - verify_eval("'37a' <= INT_37", "n") + verify_eval("INT_37 < '37a' ", 2) + verify_eval("'37a' > INT_37", 2) + verify_eval("INT_37 <= '37a' ", 2) + verify_eval("'37a' >= INT_37", 2) + verify_eval("INT_37 >= '37a' ", 0) + verify_eval("INT_37 > '37a' ", 0) + verify_eval("'37a' < INT_37", 0) + verify_eval("'37a' <= INT_37", 0) def verify_eval_bad(expr): try: @@ -519,6 +484,8 @@ def run_selftests(): c = kconfiglib.Config("Kconfiglib/tests/Kstr", warn=False) + c.modules.set_value("y") + verify_str(c.syms["UNDEFINED"], """ """) @@ -582,8 +549,10 @@ config INT # We still hardcode the modules symbol. Otherwise OPTIONS would have made # more sense as a name here. - verify_str(c.syms["MODULES"], """ + verify_str(c.modules, """ config MODULES + bool + prompt "MODULES" option modules """) @@ -619,59 +588,58 @@ choice c = kconfiglib.Config("Kconfiglib/tests/Krepr", warn=False) verify_repr(c.syms["UNDEFINED"], """ -<symbol UNDEFINED, unknown, value "UNDEFINED", visibility n, direct deps n, 0 menu nodes> +<symbol UNDEFINED, unknown, value "UNDEFINED", visibility n, direct deps n, undefined> """) verify_repr(c.syms["BASIC"], """ -<symbol BASIC, bool, value "y", visibility n, direct deps y, 1 menu node> +<symbol BASIC, bool, value "y", visibility n, direct deps y, Kconfiglib/tests/Krepr:9> """) verify_repr(c.syms["VISIBLE"], """ -<symbol VISIBLE, bool, value "n", visibility y, direct deps y, 1 menu node> +<symbol VISIBLE, bool, value "n", visibility y, direct deps y, Kconfiglib/tests/Krepr:14> """) verify_repr(c.syms["DIR_DEP_N"], """ -<symbol DIR_DEP_N, unknown, value "DIR_DEP_N", visibility n, direct deps n, 1 menu node> +<symbol DIR_DEP_N, unknown, value "DIR_DEP_N", visibility n, direct deps n, Kconfiglib/tests/Krepr:17> """) verify_repr(c.syms["OPTIONS"], """ -<symbol OPTIONS, unknown, value "OPTIONS", visibility n, allnoconfig_y, is the defconfig_list symbol, from environment variable ENV, direct deps y, 1 menu node> +<symbol OPTIONS, unknown, value "OPTIONS", visibility n, allnoconfig_y, is the defconfig_list symbol, from environment variable ENV, direct deps y, Kconfiglib/tests/Krepr:20> """) verify_repr(c.syms["MULTI_DEF"], """ -<symbol MULTI_DEF, unknown, value "MULTI_DEF", visibility n, direct deps y, 2 menu nodes> +<symbol MULTI_DEF, unknown, value "MULTI_DEF", visibility n, direct deps y, Kconfiglib/tests/Krepr:25, Kconfiglib/tests/Krepr:26> """) verify_repr(c.syms["CHOICE_1"], """ -<symbol CHOICE_1, tristate, value "n", visibility y, choice symbol, direct deps y, 1 menu node> +<symbol CHOICE_1, tristate, value "n", visibility y, choice symbol, direct deps y, Kconfiglib/tests/Krepr:33> """) - verify_repr(c.syms["MODULES"], """ -<symbol MODULES, bool, value "y", visibility n, is the modules symbol, direct deps y, 1 menu node> + verify_repr(c.modules, """ +<symbol MODULES, bool, value "y", visibility n, is the modules symbol, direct deps y, Kconfiglib/tests/Krepr:1> """) - print("Testing Choice.__repr__()") verify_repr(c.named_choices["CHOICE"], """ -<choice CHOICE, tristate, mode m, visibility y, 1 menu node> +<choice CHOICE, tristate, mode m, visibility y, Kconfiglib/tests/Krepr:30> """) c.named_choices["CHOICE"].set_value("y") verify_repr(c.named_choices["CHOICE"], """ -<choice CHOICE, tristate, mode y, visibility y, CHOICE_1 selected, 1 menu node> +<choice CHOICE, tristate, mode y, visibility y, CHOICE_1 selected, Kconfiglib/tests/Krepr:30> """) c.syms["CHOICE_2"].set_value("y") verify_repr(c.named_choices["CHOICE"], """ -<choice CHOICE, tristate, mode y, visibility y, CHOICE_2 selected, 1 menu node> +<choice CHOICE, tristate, mode y, visibility y, CHOICE_2 selected, Kconfiglib/tests/Krepr:30> """) verify_repr(c.syms["CHOICE_HOOK"].nodes[0].next.item, """ -<choice, tristate, mode n, visibility n, optional, 1 menu node> +<choice, tristate, mode n, visibility n, optional, Kconfiglib/tests/Krepr:43> """) @@ -830,13 +798,13 @@ g c = kconfiglib.Config("Kconfiglib/tests/Kvisibility") def verify_visibility(item, no_module_vis, module_vis): - c.syms["MODULES"].set_value("n") + c.modules.set_value("n") verify(item.visibility == no_module_vis, "expected {} to have visibility {} without modules, had " "visibility {}". format(repr(item), no_module_vis, item.visibility)) - c.syms["MODULES"].set_value("y") + c.modules.set_value("y") verify(item.visibility == module_vis, "expected {} to have visibility {} with modules, had " "visibility {}". @@ -844,72 +812,70 @@ g # Symbol visibility - verify_visibility(c.syms["NO_PROMPT"], "n", "n") - verify_visibility(c.syms["BOOL_N"], "n", "n") - verify_visibility(c.syms["BOOL_M"], "n", "y") - verify_visibility(c.syms["BOOL_MOD"], "y", "y") - verify_visibility(c.syms["BOOL_Y"], "y", "y") - verify_visibility(c.syms["TRISTATE_M"], "n", "m") - verify_visibility(c.syms["TRISTATE_MOD"], "y", "m") - verify_visibility(c.syms["TRISTATE_Y"], "y", "y") - verify_visibility(c.syms["BOOL_IF_N"], "n", "n") - verify_visibility(c.syms["BOOL_IF_M"], "n", "y") - verify_visibility(c.syms["BOOL_IF_Y"], "y", "y") - verify_visibility(c.syms["BOOL_MENU_N"], "n", "n") - verify_visibility(c.syms["BOOL_MENU_M"], "n", "y") - verify_visibility(c.syms["BOOL_MENU_Y"], "y", "y") - verify_visibility(c.syms["BOOL_CHOICE_N"], "n", "n") + verify_visibility(c.syms["NO_PROMPT"], 0, 0) + verify_visibility(c.syms["BOOL_N"], 0, 0) + verify_visibility(c.syms["BOOL_M"], 0, 2) + verify_visibility(c.syms["BOOL_MOD"], 2, 2) + verify_visibility(c.syms["BOOL_Y"], 2, 2) + verify_visibility(c.syms["TRISTATE_M"], 0, 1) + verify_visibility(c.syms["TRISTATE_MOD"], 2, 1) + verify_visibility(c.syms["TRISTATE_Y"], 2, 2) + verify_visibility(c.syms["BOOL_IF_N"], 0, 0) + verify_visibility(c.syms["BOOL_IF_M"], 0, 2) + verify_visibility(c.syms["BOOL_IF_Y"], 2, 2) + verify_visibility(c.syms["BOOL_MENU_N"], 0, 0) + verify_visibility(c.syms["BOOL_MENU_M"], 0, 2) + verify_visibility(c.syms["BOOL_MENU_Y"], 2, 2) + verify_visibility(c.syms["BOOL_CHOICE_N"], 0, 0) # Non-tristate symbols in tristate choices are only visible if the choice - # is in "y" mode - verify_visibility(c.syms["BOOL_CHOICE_M"], "n", "n") + # is in 2 mode + verify_visibility(c.syms["BOOL_CHOICE_M"], 0, 0) - # Tristate choices start out in "m" mode. When running without modules, - # their type gets adjusted to bool. - verify_visibility(c.syms["BOOL_CHOICE_Y"], "y", "n") + # Tristate choices start out in m mode. When running without modules, their + # type gets adjusted to bool. + verify_visibility(c.syms["BOOL_CHOICE_Y"], 2, 0) c.syms["TRISTATE_CHOICE_M"].set_value("y") c.syms["TRISTATE_CHOICE_Y"].set_value("y") # Still limited by the visibility of the choice - verify_visibility(c.syms["BOOL_CHOICE_M"], "n", "n") + verify_visibility(c.syms["BOOL_CHOICE_M"], 0, 0) # This one should become visible now - verify_visibility(c.syms["BOOL_CHOICE_Y"], "y", "y") - - verify_visibility(c.syms["TRISTATE_IF_N"], "n", "n") - verify_visibility(c.syms["TRISTATE_IF_M"], "n", "m") - verify_visibility(c.syms["TRISTATE_IF_Y"], "y", "y") - verify_visibility(c.syms["TRISTATE_MENU_N"], "n", "n") - verify_visibility(c.syms["TRISTATE_MENU_M"], "n", "m") - verify_visibility(c.syms["TRISTATE_MENU_Y"], "y", "y") - verify_visibility(c.syms["TRISTATE_CHOICE_N"], "n", "n") - verify_visibility(c.syms["TRISTATE_CHOICE_M"], "n", "m") - verify_visibility(c.syms["TRISTATE_CHOICE_Y"], "y", "y") - - verify_visibility(c.named_choices["BOOL_CHOICE_N"], "n", "n") - verify_visibility(c.named_choices["BOOL_CHOICE_M"], "n", "y") - verify_visibility(c.named_choices["BOOL_CHOICE_Y"], "y", "y") - verify_visibility(c.named_choices["TRISTATE_CHOICE_N"], "n", "n") - verify_visibility(c.named_choices["TRISTATE_CHOICE_M"], "n", "m") - verify_visibility(c.named_choices["TRISTATE_CHOICE_Y"], "y", "y") - - verify_visibility(c.named_choices["TRISTATE_CHOICE_IF_M_AND_Y"], - "n", "m") - verify_visibility(c.named_choices["TRISTATE_CHOICE_MENU_N_AND_Y"], - "n", "n") + verify_visibility(c.syms["BOOL_CHOICE_Y"], 2, 2) + + verify_visibility(c.syms["TRISTATE_IF_N"], 0, 0) + verify_visibility(c.syms["TRISTATE_IF_M"], 0, 1) + verify_visibility(c.syms["TRISTATE_IF_Y"], 2, 2) + verify_visibility(c.syms["TRISTATE_MENU_N"], 0, 0) + verify_visibility(c.syms["TRISTATE_MENU_M"], 0, 1) + verify_visibility(c.syms["TRISTATE_MENU_Y"], 2, 2) + verify_visibility(c.syms["TRISTATE_CHOICE_N"], 0, 0) + verify_visibility(c.syms["TRISTATE_CHOICE_M"], 0, 1) + verify_visibility(c.syms["TRISTATE_CHOICE_Y"], 2, 2) + + verify_visibility(c.named_choices["BOOL_CHOICE_N"], 0, 0) + verify_visibility(c.named_choices["BOOL_CHOICE_M"], 0, 2) + verify_visibility(c.named_choices["BOOL_CHOICE_Y"], 2, 2) + verify_visibility(c.named_choices["TRISTATE_CHOICE_N"], 0, 0) + verify_visibility(c.named_choices["TRISTATE_CHOICE_M"], 0, 1) + verify_visibility(c.named_choices["TRISTATE_CHOICE_Y"], 2, 2) + + verify_visibility(c.named_choices["TRISTATE_CHOICE_IF_M_AND_Y"], 0, 1) + verify_visibility(c.named_choices["TRISTATE_CHOICE_MENU_N_AND_Y"], 0, 0) # Menu visibility def verify_menu_visibility(menu, no_module_vis, module_vis): - c["MODULES"].set_value("n") + c.modules.set_value("n") menu_vis = kconfiglib.eval_expr(menu.node.dep) verify(menu_vis == no_module_vis, "menu \"{}\" should have visibility '{}' without modules, " "has visibility '{}'" .format(menu.title, no_module_vis, menu_vis)) - c["MODULES"].set_value("y") + c.modules.set_value("y") menu_vis = kconfiglib.eval_expr(menu.node.dep) verify(menu_vis == module_vis, "menu \"{}\" should have visibility '{}' with modules, " @@ -935,14 +901,14 @@ g menu_visible_if_m_2 = get_menus(c)[13:] def verify_visible_if_visibility(menu, no_module_vis, module_vis): - c["MODULES"].set_value("n") + c.modules.set_value("n") menu_vis = menu.get_visible_if_visibility() verify(menu_vis == no_module_vis, "menu \"{}\" should have 'visible if' visibility '{}' " "without modules, has 'visible if' visibility '{}'". format(menu.title, no_module_vis, menu_vis)) - c["MODULES"].set_value("y") + c.modules.set_value("y") menu_vis = menu.get_visible_if_visibility() verify(menu_vis == module_vis, "menu \"{}\" should have 'visible if' visibility '{}' " @@ -963,15 +929,15 @@ g #verify_visible_if_visibility(menu_visible_if_m_2, "n", "m") # Verify that 'visible if' visibility gets propagated to prompts - verify_visibility(c.syms["VISIBLE_IF_N"], "n", "n") - verify_visibility(c.syms["VISIBLE_IF_M"], "n", "m") - verify_visibility(c.syms["VISIBLE_IF_Y"], "y", "y") - verify_visibility(c.syms["VISIBLE_IF_M_2"], "n", "m") + verify_visibility(c.syms["VISIBLE_IF_N"], 0, 0) + verify_visibility(c.syms["VISIBLE_IF_M"], 0, 1) + verify_visibility(c.syms["VISIBLE_IF_Y"], 2, 2) + verify_visibility(c.syms["VISIBLE_IF_M_2"], 0, 1) # Comment visibility def verify_comment_visibility(comment, no_module_vis, module_vis): - c["MODULES"].set_value("n") + c.modules.set_value("n") # TODO: uninternalize comment_vis = kconfiglib.eval_expr(comment.node.dep) verify(comment_vis == no_module_vis, @@ -979,7 +945,7 @@ g "modules, has visibility '{}'". format(comment.text, no_module_vis, comment_vis)) - c["MODULES"].set_value("y") + c.modules.set_value("y") comment_vis = kconfiglib.eval_expr(comment.node.dep) verify(comment_vis == module_vis, "comment \"{}\" should have visibility '{}' with " @@ -1251,7 +1217,7 @@ g ("BOOL", "TRISTATE", "STRING", "INT", "HEX")] for sym in syms: - verify(sym.user_value is None, + verify(sym.user_str_value is None and sym.user_tri_value is None, "{} should not have a user value to begin with") # Assign valid values for the types @@ -1278,7 +1244,7 @@ g for s in syms: s.unset_value() - verify(s.user_value is None, + verify(s.user_str_value is None and s.user_tri_value is None, "{} should not have a user value after being reset". format(s.name)) @@ -1399,7 +1365,7 @@ g # .config # - print("Testing .config...") + print("Testing Config separation...") c1 = kconfiglib.Config("Kconfiglib/tests/Kmisc", warn=False) c2 = kconfiglib.Config("Kconfiglib/tests/Kmisc", warn=False) @@ -1547,9 +1513,8 @@ g def select_and_verify(sym): choice = get_parent(sym) sym.set_value("y") - verify(choice.value == "y", - 'The mode of the choice should be "y" after selecting a ' - "symbol") + verify(choice.str_value == "y", + "The mode of the choice should be y after selecting a symbol") verify(sym.choice.selection is sym, "{} should be the selected choice symbol" .format(sym.name)) @@ -1568,25 +1533,24 @@ g select_and_verify(choice.syms[i]) def verify_mode(choice, no_modules_mode, modules_mode): - c.syms["MODULES"].set_value("n") - choice_mode = choice.value + c.modules.set_value("n") + choice_mode = choice.tri_value verify(choice_mode == no_modules_mode, - 'Wrong mode for choice {} with no modules. Expected "{}", ' - 'got "{}".'.format(choice.name, no_modules_mode, choice_mode)) + 'Wrong mode for choice {} with no modules. Expected {}, got {}.' + .format(choice.name, no_modules_mode, choice_mode)) - c.syms["MODULES"].set_value("y") - choice_mode = choice.value + c.modules.set_value("y") + choice_mode = choice.tri_value verify(choice_mode == modules_mode, - 'Wrong mode for choice {} with modules. Expected "{}", ' - 'got "{}".'.format(choice.name, modules_mode, - choice_mode)) + 'Wrong mode for choice {} with modules. Expected {}, got {}.' + .format(choice.name, modules_mode, choice_mode)) - verify_mode(choice_bool, "y", "y") - verify_mode(choice_bool_opt, "n", "n") - verify_mode(choice_tristate, "y", "m") - verify_mode(choice_tristate_opt, "n", "n") - verify_mode(choice_bool_m, "y", "y") - verify_mode(choice_tristate_m, "y", "m") + verify_mode(choice_bool, 2, 2) + verify_mode(choice_bool_opt, 0, 0) + verify_mode(choice_tristate, 2, 1) + verify_mode(choice_tristate_opt, 0, 0) + verify_mode(choice_bool_m, 2, 2) + verify_mode(choice_tristate_m, 2, 1) # Test defaults @@ -1606,7 +1570,7 @@ g # Test "y" mode selection - c.syms["MODULES"].set_value("y") + c.modules.set_value("y") select_and_verify_all(choice_bool) select_and_verify_all(choice_bool_opt) @@ -1621,12 +1585,12 @@ g for sym_name in ("T_1", "T_2"): assign_and_verify_value(sym_name, "m", "m") - verify(choice_tristate.value == "m", + verify(choice_tristate.tri_value == 1, 'Selecting {} to "m" should have changed the mode of the ' 'choice to "m"'.format(sym_name)) assign_and_verify_value(sym_name, "y", "y") - verify(choice_tristate.value == "y" and + verify(choice_tristate.tri_value == 2 and choice_tristate.selection is c.syms[sym_name], 'Selecting {} to "y" should have changed the mode of the ' 'choice to "y" and made it the selection'.format(sym_name)) @@ -1638,7 +1602,7 @@ g assign_and_verify_value(sym_name, "n", "n") # "y" should be truncated assign_and_verify_value(sym_name, "y", "m") - verify(choice_tristate_m.value == "m", + verify(choice_tristate_m.tri_value == 1, 'A choice that can only be in "m" mode was not') # Verify that choices with no explicitly specified type get the type of the @@ -1746,8 +1710,10 @@ g "\nSome selftests failed\n") def run_compatibility_tests(): - """Runs tests on configurations from the kernel. Tests compability with the - C implementation by comparing outputs.""" + """ + Runs tests on configurations from the kernel. Tests compability with the + C implementation by comparing outputs. + """ os.environ.pop("ARCH", None) os.environ.pop("SRCARCH", None) @@ -1798,9 +1764,9 @@ def run_compatibility_tests(): if compare_configs: if equal_confs(): - print(" {:14}OK".format(arch)) + print("{:14}OK".format(arch)) else: - print(" {:14}FAIL".format(arch)) + print("{:14}FAIL".format(arch)) fail() if all_passed: @@ -1810,8 +1776,9 @@ def run_compatibility_tests(): print("Some tests failed") def get_arch_srcarch_list(): - """Returns a list of (ARCH, SRCARCH) tuples to test.""" - + """ + Returns a list of (ARCH, SRCARCH) tuples to test. + """ res = [] def add_arch(arch): @@ -1837,16 +1804,17 @@ def get_arch_srcarch_list(): return res def test_load(conf, arch): - """Load all arch Kconfigs to make sure we don't throw any errors""" - print(" {:14}OK".format(arch)) + """ + Load all arch Kconfigs to make sure we don't throw any errors + """ + print("{:14}OK".format(arch)) -# The weird docstring formatting is to get the format right when we print the -# docstring ourselves def test_all_no(conf, arch): """ Verify that our examples/allnoconfig.py script generates the same .config as 'make allnoconfig', for each architecture. Runs the script via - 'make scriptconfig', so kinda slow even in speedy mode.""" + 'make scriptconfig', so kinda slow even in speedy mode. + """ # TODO: Support speedy mode for running the script shell("make scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig.py " @@ -1861,7 +1829,8 @@ def test_all_no_simpler(conf, arch): """ Verify that our examples/allnoconfig_simpler.py script generates the same .config as 'make allnoconfig', for each architecture. Runs the script via - 'make scriptconfig', so kinda slow even in speedy mode.""" + 'make scriptconfig', so kinda slow even in speedy mode. + """ # TODO: Support speedy mode for running the script shell("make scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig_simpler.py " @@ -1876,7 +1845,8 @@ def test_all_yes(conf, arch): """ Verify that our examples/allyesconfig.py script generates the same .config as 'make allyesconfig', for each architecture. Runs the script via - 'make scriptconfig', so kinda slow even in speedy mode.""" + 'make scriptconfig', so kinda slow even in speedy mode. + """ # TODO: Support speedy mode for running the script shell("make scriptconfig SCRIPT=Kconfiglib/examples/allyesconfig.py " @@ -1889,11 +1859,12 @@ def test_all_yes(conf, arch): def test_call_all(conf, arch): """ - Call all public methods on all symbols, menus, choices, and comments for + Call all public methods on all symbols, choices, and TODO menu nodes for all architectures to make sure we never crash or hang. (Nearly all public methods: some are hard to test like this, but are exercised by other - tests.)""" - print(" For {}...".format(arch)) + tests.) + """ + print("For {}...".format(arch)) conf.defconfig_filename conf.mainmenu_text @@ -1909,7 +1880,8 @@ def test_call_all(conf, arch): s.__repr__() s.assignable s.type - s.value + s.str_value + s.tri_value s.visibility s.unset_value() @@ -1933,7 +1905,8 @@ def test_call_all(conf, arch): for c in conf._choices: c.__str__() c.__repr__() - c.value + c.str_value + c.tri_value c.assignable c.selection c.default_selection @@ -1943,7 +1916,8 @@ def test_call_all(conf, arch): def test_config_absent(conf, arch): """ Verify that Kconfiglib generates the same .config as 'make alldefconfig', - for each architecture""" + for each architecture + """ conf.write_config("._config") if speedy: shell("scripts/kconfig/conf --alldefconfig Kconfig") @@ -1959,7 +1933,8 @@ def test_defconfig(conf, arch): run. With logging enabled, this test appends any failures to a file - test_defconfig_fails in the root.""" + test_defconfig_fails in the root. + """ global nconfigs defconfigs = [] @@ -2037,8 +2012,10 @@ def test_defconfig(conf, arch): # def rm_configs(): - """Delete any old ".config" (generated by the C implementation) and - "._config" (generated by us), if present.""" + """ + Delete any old ".config" (generated by the C implementation) and + "._config" (generated by us), if present. + """ def rm_if_exists(f): if os.path.exists(f): os.remove(f) |
