diff options
| -rw-r--r-- | kconfiglib.py | 191 |
1 files changed, 103 insertions, 88 deletions
diff --git a/kconfiglib.py b/kconfiglib.py index b7b5c24..db61650 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -971,9 +971,9 @@ class Kconfig(object): if sym.orig_type in (BOOL, TRISTATE): # The C implementation only checks the first character # to the right of '=', for whatever reason - if not ((sym.orig_type == BOOL and + if not ((sym.orig_type is BOOL and val.startswith(("n", "y"))) or \ - (sym.orig_type == TRISTATE and + (sym.orig_type is TRISTATE and val.startswith(("n", "m", "y")))): self._warn("'{}' is not a valid value for the {} " "symbol {}. Assignment ignored." @@ -1000,7 +1000,7 @@ class Kconfig(object): # Set the choice's mode sym.choice.set_value(val) - elif sym.orig_type == STRING: + elif sym.orig_type is STRING: match = _conf_string_match(val) if not match: self._warn("malformed string literal in " @@ -1102,13 +1102,13 @@ class Kconfig(object): .format(self.config_prefix, sym.name, "_MODULE" if val == "m" else "")) - elif sym.orig_type == STRING: + elif sym.orig_type is STRING: f.write('#define {}{} "{}"\n' .format(self.config_prefix, sym.name, escape(val))) elif sym.orig_type in (INT, HEX): - if sym.orig_type == HEX and \ + if sym.orig_type is HEX and \ not val.startswith(("0x", "0X")): val = "0x" + val @@ -1152,8 +1152,8 @@ class Kconfig(object): f.write(item.config_string) elif expr_value(node.dep) and \ - ((item == MENU and expr_value(node.visibility)) or - item == COMMENT): + ((item is MENU and expr_value(node.visibility)) or + item is COMMENT): f.write("\n#\n# {}\n#\n".format(node.prompt[0])) @@ -1200,7 +1200,7 @@ class Kconfig(object): if sym.choice and \ not sym.choice.is_optional and \ sym.choice._get_selection_from_defaults() is sym and \ - sym.orig_type == BOOL and \ + sym.orig_type is BOOL and \ sym.tri_value == 2: continue @@ -1366,7 +1366,7 @@ class Kconfig(object): if name in self.syms: sym = self.syms[name] - if sym.orig_type == STRING: + if sym.orig_type is STRING: match = _conf_string_match(val) if not match: continue @@ -1833,7 +1833,7 @@ class Kconfig(object): # refer to a constant symbol named "FOO". token = val \ if token in _STRING_LEX or \ - tokens[0] == _T_OPTION else \ + tokens[0] is _T_OPTION else \ self._lookup_const_sym(val) elif s.startswith("&&", i): @@ -1997,7 +1997,7 @@ class Kconfig(object): def _check_token(self, token): # If the next token is 'token', removes it and returns True - if self._tokens[self._tokens_i + 1] == token: + if self._tokens[self._tokens_i + 1] is token: self._tokens_i += 1 return True return False @@ -2294,7 +2294,7 @@ class Kconfig(object): node = MenuNode() node.kconfig = self node.item = sym - node.is_menuconfig = (t0 == _T_MENUCONFIG) + node.is_menuconfig = (t0 is _T_MENUCONFIG) node.prompt = node.help = node.list = None node.parent = parent node.filename = self._filename @@ -2353,13 +2353,13 @@ class Kconfig(object): self._leave_file() - elif t0 == end_token: + elif t0 is end_token: # We have reached the end of the block. Terminate the final # node and return it. prev.next = None return prev - elif t0 == _T_IF: + elif t0 is _T_IF: node = MenuNode() node.item = node.prompt = None node.parent = parent @@ -2373,7 +2373,7 @@ class Kconfig(object): prev.next = prev = node - elif t0 == _T_MENU: + elif t0 is _T_MENU: node = MenuNode() node.kconfig = self node.item = MENU @@ -2393,7 +2393,7 @@ class Kconfig(object): prev.next = prev = node - elif t0 == _T_COMMENT: + elif t0 is _T_COMMENT: node = MenuNode() node.kconfig = self node.item = COMMENT @@ -2411,7 +2411,7 @@ class Kconfig(object): prev.next = prev = node - elif t0 == _T_CHOICE: + elif t0 is _T_CHOICE: if self._peek_token() is None: choice = Choice() choice.direct_dep = self.n @@ -2449,7 +2449,7 @@ class Kconfig(object): prev.next = prev = node - elif t0 == _T_MAINMENU: + elif t0 is _T_MAINMENU: self.top_node.prompt = (self._expect_str_and_eol(), self.y) self.top_node.filename = self._filename self.top_node.linenr = self._linenr @@ -2502,31 +2502,31 @@ class Kconfig(object): if self._peek_token() is not None: self._parse_prompt(node) - elif t0 == _T_DEPENDS: + elif t0 is _T_DEPENDS: if not self._check_token(_T_ON): self._parse_error('expected "on" after "depends"') node.dep = self._make_and(node.dep, self._expect_expr_and_eol()) - elif t0 == _T_HELP: + elif t0 is _T_HELP: self._parse_help(node) - elif t0 == _T_SELECT: + elif t0 is _T_SELECT: if not isinstance(node.item, Symbol): self._parse_error("only symbols can select") node.selects.append((self._expect_nonconst_sym(), self._parse_cond())) - elif t0 == _T_IMPLY: + elif t0 is _T_IMPLY: if not isinstance(node.item, Symbol): self._parse_error("only symbols can imply") node.implies.append((self._expect_nonconst_sym(), self._parse_cond())) - elif t0 == _T_DEFAULT: + elif t0 is _T_DEFAULT: node.defaults.append((self._parse_expr(False), self._parse_cond())) @@ -2536,15 +2536,15 @@ class Kconfig(object): node.defaults.append((self._parse_expr(False), self._parse_cond())) - elif t0 == _T_PROMPT: + elif t0 is _T_PROMPT: self._parse_prompt(node) - elif t0 == _T_RANGE: + elif t0 is _T_RANGE: node.ranges.append((self._expect_sym(), self._expect_sym(), self._parse_cond())) - elif t0 == _T_OPTION: + elif t0 is _T_OPTION: if self._check_token(_T_ENV): if not self._check_token(_T_EQUAL): self._parse_error('expected "=" after "env"') @@ -2609,14 +2609,14 @@ class Kconfig(object): else: self._parse_error("unrecognized option") - elif t0 == _T_VISIBLE: + elif t0 is _T_VISIBLE: if not self._check_token(_T_IF): self._parse_error('expected "if" after "visible"') node.visibility = self._make_and(node.visibility, self._expect_expr_and_eol()) - elif t0 == _T_OPTIONAL: + elif t0 is _T_OPTIONAL: if not isinstance(node.item, Choice): self._parse_error('"optional" is only valid for choices') @@ -2791,11 +2791,11 @@ class Kconfig(object): # EQUAL, UNEQUAL, etc., so we can just use the token directly return (self._next_token(), token, self._expect_sym()) - if token == _T_NOT: + if token is _T_NOT: # token == _T_NOT == NOT return (token, self._parse_factor(transform_m)) - if token == _T_OPEN_PAREN: + if token is _T_OPEN_PAREN: expr_parse = self._parse_expr(transform_m) if self._check_token(_T_CLOSE_PAREN): return expr_parse @@ -2917,7 +2917,7 @@ class Kconfig(object): # The menu node is a choice, menu, or if. Finalize each child in # it. - if node.item == MENU: + if node.item is MENU: visible_if = self._make_and(visible_if, node.visibility) # Propagate the menu node's dependencies to each child menu node. @@ -3415,7 +3415,7 @@ class Symbol(object): """ See the class documentation. """ - if self.orig_type == TRISTATE and \ + if self.orig_type is TRISTATE and \ ((self.choice and self.choice.tri_value == 2) or not self.kconfig.modules.tri_value): return BOOL @@ -3438,7 +3438,7 @@ class Symbol(object): # As a quirk of Kconfig, undefined symbols get their name as their # string value. This is why things like "FOO = bar" work for seeing if # FOO has the value "bar". - if self.orig_type == UNKNOWN: + if self.orig_type is UNKNOWN: self._cached_str_val = self.name return self.name @@ -3528,7 +3528,7 @@ class Symbol(object): # The value is rewritten to a standard form if it is # clamped val = str(clamp) \ - if self.orig_type == INT else \ + if self.orig_type is INT else \ hex(clamp) if has_default: @@ -3540,7 +3540,7 @@ class Symbol(object): num2str(clamp), num2str(low), num2str(high))) - elif self.orig_type == STRING: + elif self.orig_type is STRING: if vis and self.user_value is not None: # If the symbol is visible and has a user value, use that val = self.user_value @@ -3572,7 +3572,7 @@ class Symbol(object): return self._cached_tri_val if self.orig_type not in (BOOL, TRISTATE): - if self.orig_type != UNKNOWN: + if self.orig_type is not UNKNOWN: # Would take some work to give the location here self.kconfig._warn( "The {} symbol {} is being evaluated in a logical context " @@ -3627,7 +3627,7 @@ class Symbol(object): # m is promoted to y for (1) bool symbols and (2) symbols with a # weak_rev_dep (from imply) of y if val == 1 and \ - (self.type == BOOL or expr_value(self.weak_rev_dep) == 2): + (self.type is BOOL or expr_value(self.weak_rev_dep) == 2): val = 2 elif vis == 2: @@ -3685,7 +3685,7 @@ class Symbol(object): return "{}{}={}\n" \ .format(self.kconfig.config_prefix, self.name, val) - if self.orig_type == STRING: + if self.orig_type is STRING: return '{}{}="{}"\n' \ .format(self.kconfig.config_prefix, self.name, escape(val)) @@ -3740,12 +3740,12 @@ class Symbol(object): return True # Check if the value is valid for our type - if not (self.orig_type == BOOL and value in (0, 2, "n", "y") or - self.orig_type == TRISTATE and value in (0, 1, 2, "n", "m", "y") or + if not (self.orig_type is BOOL and value in (0, 2, "n", "y") or + self.orig_type is TRISTATE and value in (0, 1, 2, "n", "m", "y") or (isinstance(value, str) and - (self.orig_type == STRING or - self.orig_type == INT and _is_base_n(value, 10) or - self.orig_type == HEX and _is_base_n(value, 16) + (self.orig_type is STRING or + self.orig_type is INT and _is_base_n(value, 10) or + self.orig_type is HEX and _is_base_n(value, 16) and int(value, 16) >= 0))): # Display tristate values as n, m, y in the warning @@ -3947,7 +3947,7 @@ class Symbol(object): return (2,) if not rev_dep_val: - if self.type == BOOL or expr_value(self.weak_rev_dep) == 2: + if self.type is BOOL or expr_value(self.weak_rev_dep) == 2: return (0, 2) return (0, 1, 2) @@ -3956,7 +3956,7 @@ class Symbol(object): # rev_dep_val == 1 - if self.type == BOOL or expr_value(self.weak_rev_dep) == 2: + if self.type is BOOL or expr_value(self.weak_rev_dep) == 2: return (2,) return (1, 2) @@ -4056,7 +4056,7 @@ class Symbol(object): # Transpose mod to yes if type is bool (possibly due to modules # being disabled) - if val == 1 and self.type == BOOL: + if val == 1 and self.type is BOOL: val = 2 return TRI_TO_STR[val] @@ -4277,7 +4277,7 @@ class Choice(object): """ Returns the type of the choice. See Symbol.type. """ - if self.orig_type == TRISTATE and not self.kconfig.modules.tri_value: + if self.orig_type is TRISTATE and not self.kconfig.modules.tri_value: return BOOL return self.orig_type @@ -4307,7 +4307,7 @@ class Choice(object): val = min(val, self.visibility) # Promote m to y for boolean choices - return 2 if val == 1 and self.type == BOOL else val + return 2 if val == 1 and self.type is BOOL else val @property def assignable(self): @@ -4358,8 +4358,8 @@ class Choice(object): self._was_set = True return True - if not ((self.orig_type == BOOL and value in (0, 2, "n", "y") ) or - (self.orig_type == TRISTATE and value in (0, 1, 2, "n", "m", "y"))): + if not ((self.orig_type is BOOL and value in (0, 2, "n", "y") ) or + (self.orig_type is TRISTATE and value in (0, 1, 2, "n", "m", "y"))): # Display tristate values as n, m, y in the warning self.kconfig._warn( @@ -4508,8 +4508,8 @@ class Choice(object): if vis == 2: if not self.is_optional: - return (2,) if self.type == BOOL else (1, 2) - return (0, 2) if self.type == BOOL else (0, 1, 2) + return (2,) if self.type is BOOL else (1, 2) + return (0, 2) if self.type is BOOL else (0, 1, 2) # vis == 1 @@ -4726,7 +4726,7 @@ class MenuNode(object): if self.prompt: res |= expr_items(self.prompt[1]) - if self.item == MENU: + if self.item is MENU: res |= expr_items(self.visibility) for value, cond in self.defaults: @@ -4764,10 +4764,10 @@ class MenuNode(object): s += " " + self.item.name fields.append(s) - elif self.item == MENU: + elif self.item is MENU: fields.append("menu node for menu") - elif self.item == COMMENT: + elif self.item is COMMENT: fields.append("menu node for comment") elif self.item is None: @@ -4787,7 +4787,7 @@ class MenuNode(object): fields.append("deps " + TRI_TO_STR[expr_value(self.dep)]) - if self.item == MENU: + if self.item is MENU: fields.append("'visible if' deps " + \ TRI_TO_STR[expr_value(self.visibility)]) @@ -4830,13 +4830,13 @@ class MenuNode(object): self._sym_choice_node_str(sc_expr_str_fn) def _menu_comment_node_str(self, sc_expr_str_fn): - s = '{} "{}"\n'.format("menu" if self.item == MENU else "comment", + s = '{} "{}"\n'.format("menu" if self.item is MENU else "comment", self.prompt[0]) if self.dep is not self.kconfig.y: s += "\tdepends on {}\n".format(expr_str(self.dep, sc_expr_str_fn)) - if self.item == MENU and self.visibility is not self.kconfig.y: + if self.item is MENU and self.visibility is not self.kconfig.y: s += "\tvisible if {}\n".format(expr_str(self.visibility, sc_expr_str_fn)) @@ -4862,7 +4862,7 @@ class MenuNode(object): else: lines.append("choice " + sc.name if sc.name else "choice") - if sc.orig_type != UNKNOWN: + if sc.orig_type is not UNKNOWN: indent_add(TYPE_TO_STR[sc.orig_type]) if self.prompt: @@ -4979,18 +4979,18 @@ def expr_value(expr): if not isinstance(expr, tuple): return expr.tri_value - if expr[0] == AND: + if expr[0] is AND: v1 = expr_value(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, expr_value(expr[2])) - if expr[0] == OR: + if expr[0] is OR: v1 = expr_value(expr[1]) # Short-circuit the y case as an optimization return 2 if v1 == 2 else max(v1, expr_value(expr[2])) - if expr[0] == NOT: + if expr[0] is NOT: return 2 - expr_value(expr[1]) if expr[0] in _RELATIONS: @@ -5001,7 +5001,7 @@ def expr_value(expr): oper, op1, op2 = expr # If both operands are strings... - if op1.orig_type == STRING and op2.orig_type == STRING: + if op1.orig_type is STRING and op2.orig_type is STRING: # ...then compare them lexicographically comp = _strcmp(op1.str_value, op2.str_value) else: @@ -5013,12 +5013,12 @@ def expr_value(expr): # parse as numbers comp = _strcmp(op1.str_value, op2.str_value) - if oper == EQUAL: res = comp == 0 - elif oper == UNEQUAL: res = comp != 0 - elif oper == LESS: res = comp < 0 - elif oper == LESS_EQUAL: res = comp <= 0 - elif oper == GREATER: res = comp > 0 - elif oper == GREATER_EQUAL: res = comp >= 0 + if oper is EQUAL: res = comp == 0 + elif oper is UNEQUAL: res = comp != 0 + elif oper is LESS: res = comp < 0 + elif oper is LESS_EQUAL: res = comp <= 0 + elif oper is GREATER: res = comp > 0 + elif oper is GREATER_EQUAL: res = comp >= 0 return 2*res @@ -5059,17 +5059,17 @@ def expr_str(expr, sc_expr_str_fn=standard_sc_expr_str): if not isinstance(expr, tuple): return sc_expr_str_fn(expr) - if expr[0] == AND: + if expr[0] is AND: return "{} && {}".format(_parenthesize(expr[1], OR, sc_expr_str_fn), _parenthesize(expr[2], OR, sc_expr_str_fn)) - if expr[0] == OR: + if expr[0] is OR: # This turns A && B || C && D into "(A && B) || (C && D)", which is # redundant, but more readable return "{} || {}".format(_parenthesize(expr[1], AND, sc_expr_str_fn), _parenthesize(expr[2], AND, sc_expr_str_fn)) - if expr[0] == NOT: + if expr[0] is NOT: if isinstance(expr[1], tuple): return "!({})".format(expr_str(expr[1], sc_expr_str_fn)) return "!" + sc_expr_str_fn(expr[1]) # Symbol @@ -5096,7 +5096,7 @@ def expr_items(expr): rec(subexpr[1]) # NOTs only have a single operand - if subexpr[0] != NOT: + if subexpr[0] is not NOT: rec(subexpr[2]) else: @@ -5141,7 +5141,7 @@ def split_expr(expr, op): res = [] def rec(subexpr): - if isinstance(subexpr, tuple) and subexpr[0] == op: + if isinstance(subexpr, tuple) and subexpr[0] is op: rec(subexpr[1]) rec(subexpr[2]) else: @@ -5207,18 +5207,18 @@ def _visibility(sc): vis = max(vis, expr_value(node.prompt[1])) if isinstance(sc, Symbol) and sc.choice: - if sc.choice.orig_type == TRISTATE and sc.orig_type != TRISTATE and \ - sc.choice.tri_value != 2: + if sc.choice.orig_type is TRISTATE and \ + sc.orig_type is not TRISTATE and sc.choice.tri_value != 2: # Non-tristate choice symbols are only visible in y mode return 0 - if sc.orig_type == TRISTATE and vis == 1 and sc.choice.tri_value == 2: + if sc.orig_type is TRISTATE and vis == 1 and sc.choice.tri_value == 2: # Choice symbols with m visibility are not visible in y mode return 0 # Promote m to y if we're dealing with a non-tristate (possibly due to # modules being disabled) - if vis == 1 and sc.type != TRISTATE: + if vis == 1 and sc.type is not TRISTATE: return 2 return vis @@ -5234,7 +5234,7 @@ def _make_depend_on(sc, expr): _make_depend_on(sc, expr[1]) # NOTs only have a single operand - if expr[0] != NOT: + if expr[0] is not NOT: _make_depend_on(sc, expr[2]) elif not expr.is_constant: @@ -5244,7 +5244,7 @@ def _make_depend_on(sc, expr): def _parenthesize(expr, type_, sc_expr_str_fn): # expr_str() helper. Adds parentheses around expressions of type 'type_'. - if isinstance(expr, tuple) and expr[0] == type_: + if isinstance(expr, tuple) and expr[0] is type_: return "({})".format(expr_str(expr, sc_expr_str_fn)) return expr_str(expr, sc_expr_str_fn) @@ -5375,11 +5375,11 @@ def _expr_depends_on(expr, sym): elif left is not sym: return False - return (expr[0] == EQUAL and right is sym.kconfig.m or \ + return (expr[0] is EQUAL and right is sym.kconfig.m or \ right is sym.kconfig.y) or \ - (expr[0] == UNEQUAL and right is sym.kconfig.n) + (expr[0] is UNEQUAL and right is sym.kconfig.n) - return expr[0] == AND and \ + return expr[0] is AND and \ (_expr_depends_on(expr[1], sym) or _expr_depends_on(expr[2], sym)) @@ -5454,15 +5454,15 @@ def _finalize_choice(node): # If no type is specified for the choice, its type is that of # the first choice item with a specified type - if choice.orig_type == UNKNOWN: + if choice.orig_type is UNKNOWN: for item in choice.syms: - if item.orig_type != UNKNOWN: + if item.orig_type is not UNKNOWN: choice.orig_type = item.orig_type break # Each choice item of UNKNOWN type gets the type of the choice for sym in choice.syms: - if sym.orig_type == UNKNOWN: + if sym.orig_type is UNKNOWN: sym.orig_type = choice.orig_type def _check_dep_loop_sym(sym, ignore_choice): @@ -5654,7 +5654,7 @@ def _check_sym_sanity(sym): .format(TYPE_TO_STR[sym.orig_type], _name_and_loc(sym), expr_str(default))) - if sym.orig_type == STRING: + if sym.orig_type is STRING: if not default.is_constant and not default.nodes and \ not default.name.isupper(): # 'default foo' on a string symbol could be either a symbol @@ -5710,7 +5710,7 @@ def _int_hex_ok(sym, type_): if not sym.nodes: return _is_base_n(sym.name, _TYPE_TO_BASE[type_]) - return sym.orig_type == type_ + return sym.orig_type is type_ def _check_choice_sanity(choice): # Checks various choice properties that are handiest to check after @@ -5873,6 +5873,21 @@ STR_TO_TRI = { # constants) # +# Note: +# +# The token and type constants below are safe to test with 'is', which is a bit +# faster (~30% faster in a microbenchmark with Python 3 on my machine, and a +# few % faster for total parsing time), even without assuming Python's small +# integer optimization (which caches small integer objects). The constants end +# up pointing to unique integer objects, and since we consistently refer to +# them via the names below, we always get the same object. +# +# Client code would also need to use the names below, because the integer +# values can change e.g. when tokens get added. Client code would usually test +# with == too, which would be safe even in super obscure cases involving e.g. +# pickling (where 'is' would be a bad idea anyway) and no small-integer +# optimization. + # Are we running on Python 2? _IS_PY2 = sys.version_info[0] < 3 |
