genrest: De-spam docs by skipping direct deps. in more places
Similar deal to commit cc14c40a2d
("kconfiglib: Unclutter symbol
strings, avoid redundant writes, misc.").
Hide the direct dependencies in the defaults, selects, and implies
sections. Do the same in menuconfig/guiconfig as well.
This uses a new Kconfiglib API, so update Kconfiglib to upstream
revision 164ef007a8. This also includes some minor optimizations and
cleanups.
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
parent
465b2cf31b
commit
a570b40252
|
@ -211,7 +211,7 @@ def direct_deps_rst(sc):
|
|||
return "Direct dependencies\n" \
|
||||
"===================\n\n" \
|
||||
"{}\n\n" \
|
||||
"*(Includes any dependencies from if's and menus.)*\n\n" \
|
||||
"*(Includes any dependencies from ifs and menus.)*\n\n" \
|
||||
.format(expr_str(sc.direct_dep))
|
||||
|
||||
|
||||
|
@ -228,7 +228,7 @@ def defaults_rst(sc):
|
|||
"========\n\n"
|
||||
|
||||
if sc.defaults:
|
||||
for value, cond in sc.defaults:
|
||||
for value, cond in sc.orig_defaults:
|
||||
rst += "- " + expr_str(value)
|
||||
if cond is not sc.kconfig.y:
|
||||
rst += " if " + expr_str(cond)
|
||||
|
@ -289,8 +289,8 @@ def select_imply_rst(sym):
|
|||
|
||||
rst += "\n"
|
||||
|
||||
add_select_imply_rst("selected", sym.selects)
|
||||
add_select_imply_rst("implied", sym.implies)
|
||||
add_select_imply_rst("selected", sym.orig_selects)
|
||||
add_select_imply_rst("implied", sym.orig_implies)
|
||||
|
||||
return rst
|
||||
|
||||
|
@ -389,7 +389,7 @@ def kconfig_definition_rst(sc):
|
|||
rst += "\n\n----"
|
||||
|
||||
rst += "\n\n*(The 'depends on' condition includes propagated " \
|
||||
"dependencies from if's and menus.)*"
|
||||
"dependencies from ifs and menus.)*"
|
||||
|
||||
return rst
|
||||
|
||||
|
|
|
@ -1308,15 +1308,13 @@ def _check_valid(dialog, entry, sym, s):
|
|||
|
||||
for low_sym, high_sym, cond in sym.ranges:
|
||||
if expr_value(cond):
|
||||
low = int(low_sym.str_value, base)
|
||||
val = int(s, base)
|
||||
high = int(high_sym.str_value, base)
|
||||
low_s = low_sym.str_value
|
||||
high_s = high_sym.str_value
|
||||
|
||||
if not low <= val <= high:
|
||||
if not int(low_s, base) <= int(s, base) <= int(high_s, base):
|
||||
messagebox.showerror(
|
||||
"Value out of range",
|
||||
"{} is outside the range {}-{}".format(
|
||||
s, low_sym.str_value, high_sym.str_value),
|
||||
"{} is outside the range {}-{}".format(s, low_s, high_s),
|
||||
parent=dialog)
|
||||
entry.focus_set()
|
||||
return False
|
||||
|
@ -2123,7 +2121,7 @@ def _defaults_info(sc):
|
|||
|
||||
s = "Defaults:\n"
|
||||
|
||||
for val, cond in sc.defaults:
|
||||
for val, cond in sc.orig_defaults:
|
||||
s += " - "
|
||||
if isinstance(sc, Symbol):
|
||||
s += _expr_str(val)
|
||||
|
|
|
@ -52,8 +52,9 @@ sections.
|
|||
make kmenuconfig
|
||||
----------------
|
||||
|
||||
This target runs the curses menuconfig interface with Python 3 (Python 2 is
|
||||
currently not supported for the menuconfig).
|
||||
This target runs the curses menuconfig interface with Python 3. As of
|
||||
Kconfiglib 12.2.0, both Python 2 and Python 3 are supported (previously, only
|
||||
Python 3 was supported, so this was a backport).
|
||||
|
||||
|
||||
make guiconfig
|
||||
|
@ -545,7 +546,7 @@ from glob import iglob
|
|||
from os.path import dirname, exists, expandvars, islink, join, realpath
|
||||
|
||||
|
||||
VERSION = (12, 0, 0)
|
||||
VERSION = (12, 9, 0)
|
||||
|
||||
|
||||
# File layout:
|
||||
|
@ -903,13 +904,13 @@ class Kconfig(object):
|
|||
|
||||
Related PEP: https://www.python.org/dev/peps/pep-0538/
|
||||
"""
|
||||
self.srctree = os.environ.get("srctree", "")
|
||||
self.srctree = os.getenv("srctree", "")
|
||||
# A prefix we can reliably strip from glob() results to get a filename
|
||||
# relative to $srctree. relpath() can cause issues for symlinks,
|
||||
# because it assumes symlink/../foo is the same as foo/.
|
||||
self._srctree_prefix = realpath(self.srctree) + os.sep
|
||||
|
||||
self.config_prefix = os.environ.get("CONFIG_", "CONFIG_")
|
||||
self.config_prefix = os.getenv("CONFIG_", "CONFIG_")
|
||||
|
||||
# Regular expressions for parsing .config files
|
||||
self._set_match = _re_match(self.config_prefix + r"([^=]+)=(.*)")
|
||||
|
@ -921,8 +922,7 @@ class Kconfig(object):
|
|||
|
||||
self.warn = warn
|
||||
self.warn_to_stderr = warn_to_stderr
|
||||
self.warn_assign_undef = \
|
||||
os.environ.get("KCONFIG_WARN_UNDEF_ASSIGN") == "y"
|
||||
self.warn_assign_undef = os.getenv("KCONFIG_WARN_UNDEF_ASSIGN") == "y"
|
||||
self.warn_assign_override = self.warn_assign_redun = True
|
||||
|
||||
|
||||
|
@ -978,7 +978,7 @@ class Kconfig(object):
|
|||
try:
|
||||
self._functions.update(
|
||||
importlib.import_module(
|
||||
os.environ.get("KCONFIG_FUNCTIONS", "kconfigfunctions")
|
||||
os.getenv("KCONFIG_FUNCTIONS", "kconfigfunctions")
|
||||
).functions)
|
||||
except ImportError:
|
||||
pass
|
||||
|
@ -1056,8 +1056,8 @@ class Kconfig(object):
|
|||
|
||||
# KCONFIG_STRICT is an older alias for KCONFIG_WARN_UNDEF, supported
|
||||
# for backwards compatibility
|
||||
if os.environ.get("KCONFIG_WARN_UNDEF") == "y" or \
|
||||
os.environ.get("KCONFIG_STRICT") == "y":
|
||||
if os.getenv("KCONFIG_WARN_UNDEF") == "y" or \
|
||||
os.getenv("KCONFIG_STRICT") == "y":
|
||||
|
||||
self._check_undef_syms()
|
||||
|
||||
|
@ -1156,7 +1156,8 @@ class Kconfig(object):
|
|||
Returns a string with a message saying which file got loaded (or
|
||||
possibly that no file got loaded, when 'filename' is None). This is
|
||||
meant to reduce boilerplate in tools, which can do e.g.
|
||||
print(kconf.load_config()).
|
||||
print(kconf.load_config()). The returned message distinguishes between
|
||||
loading (replace == True) and merging (replace == False).
|
||||
"""
|
||||
if verbose is not None:
|
||||
_warn_verbose_deprecated("load_config")
|
||||
|
@ -1212,7 +1213,7 @@ class Kconfig(object):
|
|||
# Small optimizations
|
||||
set_match = self._set_match
|
||||
unset_match = self._unset_match
|
||||
syms = self.syms
|
||||
get_sym = self.syms.get
|
||||
|
||||
for linenr, line in enumerate(f, 1):
|
||||
# The C tools ignore trailing whitespace
|
||||
|
@ -1221,22 +1222,18 @@ class Kconfig(object):
|
|||
match = set_match(line)
|
||||
if match:
|
||||
name, val = match.groups()
|
||||
if name not in syms:
|
||||
self._undef_assign(name, val, filename, linenr)
|
||||
continue
|
||||
|
||||
sym = syms[name]
|
||||
if not sym.nodes:
|
||||
sym = get_sym(name)
|
||||
if not sym or not sym.nodes:
|
||||
self._undef_assign(name, val, filename, linenr)
|
||||
continue
|
||||
|
||||
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 is BOOL and
|
||||
val.startswith(("y", "n"))) or
|
||||
(sym.orig_type is TRISTATE and
|
||||
val.startswith(("y", "m", "n")))):
|
||||
if not (sym.orig_type is BOOL
|
||||
and val.startswith(("y", "n")) or
|
||||
sym.orig_type is TRISTATE
|
||||
and val.startswith(("y", "m", "n"))):
|
||||
self._warn("'{}' is not a valid value for the {} "
|
||||
"symbol {}. Assignment ignored."
|
||||
.format(val, TYPE_TO_STR[sym.orig_type],
|
||||
|
@ -1288,12 +1285,8 @@ class Kconfig(object):
|
|||
continue
|
||||
|
||||
name = match.group(1)
|
||||
if name not in syms:
|
||||
self._undef_assign(name, "n", filename, linenr)
|
||||
continue
|
||||
|
||||
sym = syms[name]
|
||||
if not sym.nodes:
|
||||
sym = get_sym(name)
|
||||
if not sym or not sym.nodes:
|
||||
self._undef_assign(name, "n", filename, linenr)
|
||||
continue
|
||||
|
||||
|
@ -1305,21 +1298,7 @@ class Kconfig(object):
|
|||
# Done parsing the assignment. Set the value.
|
||||
|
||||
if sym._was_set:
|
||||
# Use strings for bool/tristate user values in the warning
|
||||
if sym.orig_type in _BOOL_TRISTATE:
|
||||
display_user_val = TRI_TO_STR[sym.user_value]
|
||||
else:
|
||||
display_user_val = sym.user_value
|
||||
|
||||
msg = '{} set more than once. Old value "{}", new value "{}".'.format(
|
||||
_name_and_loc(sym), display_user_val, val
|
||||
)
|
||||
|
||||
if display_user_val == val:
|
||||
if self.warn_assign_redun:
|
||||
self._warn(msg, filename, linenr)
|
||||
elif self.warn_assign_override:
|
||||
self._warn(msg, filename, linenr)
|
||||
self._assigned_twice(sym, val, filename, linenr)
|
||||
|
||||
sym.set_value(val)
|
||||
|
||||
|
@ -1344,6 +1323,24 @@ class Kconfig(object):
|
|||
"attempt to assign the value '{}' to the undefined symbol {}"
|
||||
.format(val, name), filename, linenr)
|
||||
|
||||
def _assigned_twice(self, sym, new_val, filename, linenr):
|
||||
# Called when a symbol is assigned more than once in a .config file
|
||||
|
||||
# Use strings for bool/tristate user values in the warning
|
||||
if sym.orig_type in _BOOL_TRISTATE:
|
||||
user_val = TRI_TO_STR[sym.user_value]
|
||||
else:
|
||||
user_val = sym.user_value
|
||||
|
||||
msg = '{} set more than once. Old value "{}", new value "{}".'.format(
|
||||
_name_and_loc(sym), user_val, new_val)
|
||||
|
||||
if user_val == new_val:
|
||||
if self.warn_assign_redun:
|
||||
self._warn(msg, filename, linenr)
|
||||
elif self.warn_assign_override:
|
||||
self._warn(msg, filename, linenr)
|
||||
|
||||
def write_autoconf(self, filename,
|
||||
header="/* Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) */\n"):
|
||||
r"""
|
||||
|
@ -1380,6 +1377,10 @@ class Kconfig(object):
|
|||
for sym in self.unique_defined_syms:
|
||||
# _write_to_conf is determined when the value is calculated. This
|
||||
# is a hidden function call due to property magic.
|
||||
#
|
||||
# Note: In client code, you can check if sym.config_string is empty
|
||||
# instead, to avoid accessing the internal _write_to_conf variable
|
||||
# (though it's likely to keep working).
|
||||
val = sym.str_value
|
||||
if not sym._write_to_conf:
|
||||
continue
|
||||
|
@ -1688,6 +1689,10 @@ class Kconfig(object):
|
|||
for sym in self.unique_defined_syms:
|
||||
# _write_to_conf is determined when the value is calculated. This
|
||||
# is a hidden function call due to property magic.
|
||||
#
|
||||
# Note: In client code, you can check if sym.config_string is empty
|
||||
# instead, to avoid accessing the internal _write_to_conf variable
|
||||
# (though it's likely to keep working).
|
||||
val = sym.str_value
|
||||
|
||||
# n tristate values do not get written to auto.conf and autoconf.h,
|
||||
|
@ -1864,10 +1869,9 @@ class Kconfig(object):
|
|||
|
||||
self._filename = None
|
||||
|
||||
# Don't include the "if " from below to avoid giving confusing error
|
||||
# messages
|
||||
self._line = s
|
||||
self._tokens = self._tokenize("if " + s)
|
||||
# Strip "if " to avoid giving confusing error messages
|
||||
self._line = s
|
||||
self._tokens_i = 1 # Skip the 'if' token
|
||||
|
||||
return expr_value(self._expect_expr_and_eol())
|
||||
|
@ -2075,8 +2079,9 @@ class Kconfig(object):
|
|||
except IOError as e:
|
||||
# We already know that the file exists
|
||||
raise _KconfigIOError(
|
||||
e, "{}:{}: Could not open '{}' ({}: {})"
|
||||
e, "{}:{}: Could not open '{}' (in '{}') ({}: {})"
|
||||
.format(self._filename, self._linenr, filename,
|
||||
self._line.strip(),
|
||||
errno.errorcode[e.errno], e.strerror))
|
||||
|
||||
self._filename = rel_filename
|
||||
|
@ -2086,11 +2091,10 @@ class Kconfig(object):
|
|||
# Returns from a Kconfig file to the file that sourced it. See
|
||||
# _enter_file().
|
||||
|
||||
# __self__ fetches the 'file' object for the method
|
||||
self._readline.__self__.close()
|
||||
# Restore location from parent Kconfig file
|
||||
self._filename, self._linenr = self._include_path[-1]
|
||||
# Restore include path and 'file' object
|
||||
self._readline.__self__.close() # __self__ fetches the 'file' object
|
||||
self._include_path, self._readline = self._filestack.pop()
|
||||
|
||||
def _next_line(self):
|
||||
|
@ -2118,7 +2122,6 @@ class Kconfig(object):
|
|||
line = line[:-2] + self._readline()
|
||||
self._linenr += 1
|
||||
|
||||
self._line = line # Used for error reporting
|
||||
self._tokens = self._tokenize(line)
|
||||
# Initialize to 1 instead of 0 to factor out code from _parse_block()
|
||||
# and _parse_properties(). They immediately fetch self._tokens[0].
|
||||
|
@ -2140,7 +2143,6 @@ class Kconfig(object):
|
|||
line = line[:-2] + self._readline()
|
||||
self._linenr += 1
|
||||
|
||||
self._line = line
|
||||
self._tokens = self._tokenize(line)
|
||||
self._reuse_tokens = True
|
||||
|
||||
|
@ -2226,6 +2228,8 @@ class Kconfig(object):
|
|||
# working across multiple lines. Lookback and compatibility with old
|
||||
# janky versions of the C tools complicate things though.
|
||||
|
||||
self._line = s # Used for error reporting
|
||||
|
||||
# Initial token on the line
|
||||
match = _command_match(s)
|
||||
if not match:
|
||||
|
@ -2938,10 +2942,8 @@ class Kconfig(object):
|
|||
|
||||
self.choices.append(choice)
|
||||
|
||||
choice.kconfig = self
|
||||
|
||||
node = MenuNode()
|
||||
node.kconfig = self
|
||||
node.kconfig = choice.kconfig = self
|
||||
node.item = choice
|
||||
node.is_menuconfig = True
|
||||
node.prompt = node.help = None
|
||||
|
@ -3769,9 +3771,9 @@ class Kconfig(object):
|
|||
# The "U" flag would currently work for both Python 2 and 3, but it's
|
||||
# deprecated on Python 3, so play it future-safe.
|
||||
#
|
||||
# A simpler solution would be to use io.open(), which defaults to
|
||||
# universal newlines on both Python 2 and 3 (and is an alias for
|
||||
# open() on Python 3), but it's appreciably slower on Python 2:
|
||||
# io.open() defaults to universal newlines on Python 2 (and is an
|
||||
# alias for open() on Python 3), but it returns 'unicode' strings and
|
||||
# slows things down:
|
||||
#
|
||||
# Parsing x86 Kconfigs on Python 2
|
||||
#
|
||||
|
@ -4024,6 +4026,12 @@ class Symbol(object):
|
|||
than plain integers. Undefined symbols get their name as their string
|
||||
value, so this works out. The C tools work the same way.
|
||||
|
||||
orig_defaults:
|
||||
orig_selects:
|
||||
orig_implies:
|
||||
orig_ranges:
|
||||
See the corresponding attributes on the MenuNode class.
|
||||
|
||||
rev_dep:
|
||||
Reverse dependency expression from other symbols selecting this symbol.
|
||||
Multiple selections get ORed together. A condition on a select is ANDed
|
||||
|
@ -4371,7 +4379,6 @@ class Symbol(object):
|
|||
"""
|
||||
if self._cached_assignable is None:
|
||||
self._cached_assignable = self._assignable()
|
||||
|
||||
return self._cached_assignable
|
||||
|
||||
@property
|
||||
|
@ -4381,7 +4388,6 @@ class Symbol(object):
|
|||
"""
|
||||
if self._cached_vis is None:
|
||||
self._cached_vis = _visibility(self)
|
||||
|
||||
return self._cached_vis
|
||||
|
||||
@property
|
||||
|
@ -4434,6 +4440,10 @@ class Symbol(object):
|
|||
values in Kconfiglib) or as one of the strings "n"/"m"/"y". For other
|
||||
symbol types, pass a string.
|
||||
|
||||
Note that the value for an int/hex symbol is passed as a string, e.g.
|
||||
"123" or "0x0123". The format of this string is preserved in the
|
||||
output.
|
||||
|
||||
Values that are invalid for the type (such as "foo" or 1 (m) for a
|
||||
BOOL or "0x123" for an INT) are ignored and won't be stored in
|
||||
Symbol.user_value. Kconfiglib will print a warning by default for
|
||||
|
@ -4446,6 +4456,9 @@ class Symbol(object):
|
|||
value of the symbol. For other symbol types, check whether the
|
||||
visibility is non-n.
|
||||
"""
|
||||
if self.orig_type in _BOOL_TRISTATE and value in STR_TO_TRI:
|
||||
value = STR_TO_TRI[value]
|
||||
|
||||
# If the new user value matches the old, nothing changes, and we can
|
||||
# save some work.
|
||||
#
|
||||
|
@ -4458,11 +4471,11 @@ class Symbol(object):
|
|||
return True
|
||||
|
||||
# Check if the value is valid for our type
|
||||
if not (self.orig_type is BOOL and value in (2, 0, "y", "n") or
|
||||
self.orig_type is TRISTATE and value in (2, 1, 0, "y", "m", "n") or
|
||||
if not (self.orig_type is BOOL and value in (2, 0) or
|
||||
self.orig_type is TRISTATE and value in TRI_TO_STR or
|
||||
(value.__class__ is str and
|
||||
(self.orig_type is STRING or
|
||||
self.orig_type is INT and _is_base_n(value, 10) or
|
||||
(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))):
|
||||
|
||||
|
@ -4470,15 +4483,12 @@ class Symbol(object):
|
|||
self.kconfig._warn(
|
||||
"the value {} is invalid for {}, which has type {} -- "
|
||||
"assignment ignored"
|
||||
.format(TRI_TO_STR[value] if value in (0, 1, 2) else
|
||||
.format(TRI_TO_STR[value] if value in TRI_TO_STR else
|
||||
"'{}'".format(value),
|
||||
_name_and_loc(self), TYPE_TO_STR[self.orig_type]))
|
||||
|
||||
return False
|
||||
|
||||
if self.orig_type in _BOOL_TRISTATE and value in ("y", "m", "n"):
|
||||
value = STR_TO_TRI[value]
|
||||
|
||||
self.user_value = value
|
||||
self._was_set = True
|
||||
|
||||
|
@ -4511,6 +4521,34 @@ class Symbol(object):
|
|||
"""
|
||||
return {item for node in self.nodes for item in node.referenced}
|
||||
|
||||
@property
|
||||
def orig_defaults(self):
|
||||
"""
|
||||
See the class documentation.
|
||||
"""
|
||||
return [d for node in self.nodes for d in node.orig_defaults]
|
||||
|
||||
@property
|
||||
def orig_selects(self):
|
||||
"""
|
||||
See the class documentation.
|
||||
"""
|
||||
return [s for node in self.nodes for s in node.orig_selects]
|
||||
|
||||
@property
|
||||
def orig_implies(self):
|
||||
"""
|
||||
See the class documentation.
|
||||
"""
|
||||
return [i for node in self.nodes for i in node.orig_implies]
|
||||
|
||||
@property
|
||||
def orig_ranges(self):
|
||||
"""
|
||||
See the class documentation.
|
||||
"""
|
||||
return [r for node in self.nodes for r in node.orig_ranges]
|
||||
|
||||
def __repr__(self):
|
||||
"""
|
||||
Returns a string with information about the symbol (including its name,
|
||||
|
@ -4518,52 +4556,49 @@ class Symbol(object):
|
|||
interactive Python prompt.
|
||||
"""
|
||||
fields = ["symbol " + self.name, TYPE_TO_STR[self.type]]
|
||||
add = fields.append
|
||||
|
||||
for node in self.nodes:
|
||||
if node.prompt:
|
||||
fields.append('"{}"'.format(node.prompt[0]))
|
||||
add('"{}"'.format(node.prompt[0]))
|
||||
|
||||
# Only add quotes for non-bool/tristate symbols
|
||||
fields.append("value " +
|
||||
(self.str_value
|
||||
if self.orig_type in _BOOL_TRISTATE else
|
||||
'"{}"'.format(self.str_value)))
|
||||
add("value " + (self.str_value if self.orig_type in _BOOL_TRISTATE
|
||||
else '"{}"'.format(self.str_value)))
|
||||
|
||||
if not self.is_constant:
|
||||
# These aren't helpful to show for constant symbols
|
||||
|
||||
if self.user_value is not None:
|
||||
# Only add quotes for non-bool/tristate symbols
|
||||
fields.append("user value " +
|
||||
(TRI_TO_STR[self.user_value]
|
||||
if self.orig_type in _BOOL_TRISTATE else
|
||||
'"{}"'.format(self.user_value)))
|
||||
add("user value " + (TRI_TO_STR[self.user_value]
|
||||
if self.orig_type in _BOOL_TRISTATE
|
||||
else '"{}"'.format(self.user_value)))
|
||||
|
||||
fields.append("visibility " + TRI_TO_STR[self.visibility])
|
||||
add("visibility " + TRI_TO_STR[self.visibility])
|
||||
|
||||
if self.choice:
|
||||
fields.append("choice symbol")
|
||||
add("choice symbol")
|
||||
|
||||
if self.is_allnoconfig_y:
|
||||
fields.append("allnoconfig_y")
|
||||
add("allnoconfig_y")
|
||||
|
||||
if self is self.kconfig.defconfig_list:
|
||||
fields.append("is the defconfig_list symbol")
|
||||
add("is the defconfig_list symbol")
|
||||
|
||||
if self.env_var is not None:
|
||||
fields.append("from environment variable " + self.env_var)
|
||||
add("from environment variable " + self.env_var)
|
||||
|
||||
if self is self.kconfig.modules:
|
||||
fields.append("is the modules symbol")
|
||||
add("is the modules symbol")
|
||||
|
||||
fields.append("direct deps " +
|
||||
TRI_TO_STR[expr_value(self.direct_dep)])
|
||||
add("direct deps " + TRI_TO_STR[expr_value(self.direct_dep)])
|
||||
|
||||
if self.nodes:
|
||||
for node in self.nodes:
|
||||
fields.append("{}:{}".format(node.filename, node.linenr))
|
||||
add("{}:{}".format(node.filename, node.linenr))
|
||||
else:
|
||||
fields.append("constant" if self.is_constant else "undefined")
|
||||
add("constant" if self.is_constant else "undefined")
|
||||
|
||||
return "<{}>".format(", ".join(fields))
|
||||
|
||||
|
@ -4938,6 +4973,9 @@ class Choice(object):
|
|||
Note that 'depends on' and parent dependencies are propagated to
|
||||
'default' conditions.
|
||||
|
||||
orig_defaults:
|
||||
See the corresponding attribute on the MenuNode class.
|
||||
|
||||
direct_dep:
|
||||
See Symbol.direct_dep.
|
||||
|
||||
|
@ -4987,7 +5025,6 @@ class Choice(object):
|
|||
"""
|
||||
if self.orig_type is TRISTATE and not self.kconfig.modules.tri_value:
|
||||
return BOOL
|
||||
|
||||
return self.orig_type
|
||||
|
||||
@property
|
||||
|
@ -5024,7 +5061,6 @@ class Choice(object):
|
|||
"""
|
||||
if self._cached_assignable is None:
|
||||
self._cached_assignable = self._assignable()
|
||||
|
||||
return self._cached_assignable
|
||||
|
||||
@property
|
||||
|
@ -5034,7 +5070,6 @@ class Choice(object):
|
|||
"""
|
||||
if self._cached_vis is None:
|
||||
self._cached_vis = _visibility(self)
|
||||
|
||||
return self._cached_vis
|
||||
|
||||
@property
|
||||
|
@ -5044,7 +5079,6 @@ class Choice(object):
|
|||
"""
|
||||
if self._cached_selection is _NO_CACHED_SELECTION:
|
||||
self._cached_selection = self._selection()
|
||||
|
||||
return self._cached_selection
|
||||
|
||||
def set_value(self, value):
|
||||
|
@ -5105,6 +5139,13 @@ class Choice(object):
|
|||
"""
|
||||
return {item for node in self.nodes for item in node.referenced}
|
||||
|
||||
@property
|
||||
def orig_defaults(self):
|
||||
"""
|
||||
See the class documentation.
|
||||
"""
|
||||
return [d for node in self.nodes for d in node.orig_defaults]
|
||||
|
||||
def __repr__(self):
|
||||
"""
|
||||
Returns a string with information about the choice when it is evaluated
|
||||
|
@ -5112,18 +5153,19 @@ class Choice(object):
|
|||
"""
|
||||
fields = ["choice " + self.name if self.name else "choice",
|
||||
TYPE_TO_STR[self.type]]
|
||||
add = fields.append
|
||||
|
||||
for node in self.nodes:
|
||||
if node.prompt:
|
||||
fields.append('"{}"'.format(node.prompt[0]))
|
||||
add('"{}"'.format(node.prompt[0]))
|
||||
|
||||
fields.append("mode " + self.str_value)
|
||||
add("mode " + self.str_value)
|
||||
|
||||
if self.user_value is not None:
|
||||
fields.append('user mode {}'.format(TRI_TO_STR[self.user_value]))
|
||||
add('user mode {}'.format(TRI_TO_STR[self.user_value]))
|
||||
|
||||
if self.selection:
|
||||
fields.append("{} selected".format(self.selection.name))
|
||||
add("{} selected".format(self.selection.name))
|
||||
|
||||
if self.user_selection:
|
||||
user_sel_str = "{} selected by user" \
|
||||
|
@ -5132,15 +5174,15 @@ class Choice(object):
|
|||
if self.selection is not self.user_selection:
|
||||
user_sel_str += " (overridden)"
|
||||
|
||||
fields.append(user_sel_str)
|
||||
add(user_sel_str)
|
||||
|
||||
fields.append("visibility " + TRI_TO_STR[self.visibility])
|
||||
add("visibility " + TRI_TO_STR[self.visibility])
|
||||
|
||||
if self.is_optional:
|
||||
fields.append("optional")
|
||||
add("optional")
|
||||
|
||||
for node in self.nodes:
|
||||
fields.append("{}:{}".format(node.filename, node.linenr))
|
||||
add("{}:{}".format(node.filename, node.linenr))
|
||||
|
||||
return "<{}>".format(", ".join(fields))
|
||||
|
||||
|
@ -5519,46 +5561,45 @@ class MenuNode(object):
|
|||
evaluated on e.g. the interactive Python prompt.
|
||||
"""
|
||||
fields = []
|
||||
add = fields.append
|
||||
|
||||
if self.item.__class__ is Symbol:
|
||||
fields.append("menu node for symbol " + self.item.name)
|
||||
add("menu node for symbol " + self.item.name)
|
||||
|
||||
elif self.item.__class__ is Choice:
|
||||
s = "menu node for choice"
|
||||
if self.item.name is not None:
|
||||
s += " " + self.item.name
|
||||
fields.append(s)
|
||||
add(s)
|
||||
|
||||
elif self.item is MENU:
|
||||
fields.append("menu node for menu")
|
||||
add("menu node for menu")
|
||||
|
||||
else: # self.item is COMMENT
|
||||
fields.append("menu node for comment")
|
||||
add("menu node for comment")
|
||||
|
||||
if self.prompt:
|
||||
fields.append('prompt "{}" (visibility {})'
|
||||
.format(self.prompt[0],
|
||||
TRI_TO_STR[expr_value(self.prompt[1])]))
|
||||
add('prompt "{}" (visibility {})'.format(
|
||||
self.prompt[0], TRI_TO_STR[expr_value(self.prompt[1])]))
|
||||
|
||||
if self.item.__class__ is Symbol and self.is_menuconfig:
|
||||
fields.append("is menuconfig")
|
||||
add("is menuconfig")
|
||||
|
||||
fields.append("deps " + TRI_TO_STR[expr_value(self.dep)])
|
||||
add("deps " + TRI_TO_STR[expr_value(self.dep)])
|
||||
|
||||
if self.item is MENU:
|
||||
fields.append("'visible if' deps " +
|
||||
TRI_TO_STR[expr_value(self.visibility)])
|
||||
add("'visible if' deps " + TRI_TO_STR[expr_value(self.visibility)])
|
||||
|
||||
if self.item.__class__ in _SYMBOL_CHOICE and self.help is not None:
|
||||
fields.append("has help")
|
||||
add("has help")
|
||||
|
||||
if self.list:
|
||||
fields.append("has child")
|
||||
add("has child")
|
||||
|
||||
if self.next:
|
||||
fields.append("has next")
|
||||
add("has next")
|
||||
|
||||
fields.append("{}:{}".format(self.filename, self.linenr))
|
||||
add("{}:{}".format(self.filename, self.linenr))
|
||||
|
||||
return "<{}>".format(", ".join(fields))
|
||||
|
||||
|
@ -5834,12 +5875,12 @@ def expr_value(expr):
|
|||
# parse as numbers
|
||||
comp = _strcmp(v1.str_value, v2.str_value)
|
||||
|
||||
if rel is EQUAL: return 2*(comp == 0)
|
||||
if rel is UNEQUAL: return 2*(comp != 0)
|
||||
if rel is LESS: return 2*(comp < 0)
|
||||
if rel is LESS_EQUAL: return 2*(comp <= 0)
|
||||
if rel is GREATER: return 2*(comp > 0)
|
||||
return 2*(comp >= 0) # rel is GREATER_EQUAL
|
||||
return 2*(comp == 0 if rel is EQUAL else
|
||||
comp != 0 if rel is UNEQUAL else
|
||||
comp < 0 if rel is LESS else
|
||||
comp <= 0 if rel is LESS_EQUAL else
|
||||
comp > 0 if rel is GREATER else
|
||||
comp >= 0)
|
||||
|
||||
|
||||
def standard_sc_expr_str(sc):
|
||||
|
@ -5898,7 +5939,7 @@ def expr_str(expr, sc_expr_str_fn=standard_sc_expr_str):
|
|||
#
|
||||
# Relation operands are always symbols (quoted strings are constant
|
||||
# symbols)
|
||||
return "{} {} {}".format(sc_expr_str_fn(expr[1]), _REL_TO_STR[expr[0]],
|
||||
return "{} {} {}".format(sc_expr_str_fn(expr[1]), REL_TO_STR[expr[0]],
|
||||
sc_expr_str_fn(expr[2]))
|
||||
|
||||
|
||||
|
@ -6023,7 +6064,7 @@ def standard_config_filename():
|
|||
Calling load_config() with filename=None might give the behavior you want,
|
||||
without having to use this function.
|
||||
"""
|
||||
return os.environ.get("KCONFIG_CONFIG", ".config")
|
||||
return os.getenv("KCONFIG_CONFIG", ".config")
|
||||
|
||||
|
||||
def load_allconfig(kconf, filename):
|
||||
|
@ -6048,7 +6089,7 @@ def load_allconfig(kconf, filename):
|
|||
Command-specific configuration filename - "allyes.config",
|
||||
"allno.config", etc.
|
||||
"""
|
||||
allconfig = os.environ.get("KCONFIG_ALLCONFIG")
|
||||
allconfig = os.getenv("KCONFIG_ALLCONFIG")
|
||||
if allconfig is None:
|
||||
return
|
||||
|
||||
|
@ -6777,7 +6818,7 @@ LESS_EQUAL = _T_LESS_EQUAL
|
|||
GREATER = _T_GREATER
|
||||
GREATER_EQUAL = _T_GREATER_EQUAL
|
||||
|
||||
_REL_TO_STR = {
|
||||
REL_TO_STR = {
|
||||
EQUAL: "=",
|
||||
UNEQUAL: "!=",
|
||||
LESS: "<",
|
||||
|
@ -6946,11 +6987,11 @@ def _re_search(regex):
|
|||
#
|
||||
# '$' is included to detect preprocessor variable assignments with macro
|
||||
# expansions in the left-hand side.
|
||||
_command_match = _re_match(r"\s*([$A-Za-z0-9_-]+)\s*")
|
||||
_command_match = _re_match(r"\s*([A-Za-z0-9_$-]+)\s*")
|
||||
|
||||
# An identifier/keyword after the first token. Also eats trailing whitespace.
|
||||
# '$' is included to detect identifiers containing macro expansions.
|
||||
_id_keyword_match = _re_match(r"([$A-Za-z0-9_/.-]+)\s*")
|
||||
_id_keyword_match = _re_match(r"([A-Za-z0-9_$/.-]+)\s*")
|
||||
|
||||
# A fragment in the left-hand side of a preprocessor variable assignment. These
|
||||
# are the portions between macro expansions ($(foo)). Macros are supported in
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2018-2019, Nordic Semiconductor ASA and Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
@ -7,8 +7,8 @@
|
|||
Overview
|
||||
========
|
||||
|
||||
A curses-based menuconfig implementation. The interface should feel familiar to
|
||||
people used to mconf ('make menuconfig').
|
||||
A curses-based Python 2/3 menuconfig implementation. The interface should feel
|
||||
familiar to people used to mconf ('make menuconfig').
|
||||
|
||||
Supports the same keys as mconf, and also supports a set of keybindings
|
||||
inspired by Vi:
|
||||
|
@ -174,19 +174,15 @@ Other features
|
|||
Limitations
|
||||
===========
|
||||
|
||||
- Python 3 only
|
||||
Doesn't work out of the box on Windows, but can be made to work with 'pip
|
||||
install windows-curses'. See the
|
||||
https://github.com/zephyrproject-rtos/windows-curses repository.
|
||||
|
||||
This is mostly due to Python 2 not having curses.get_wch(), which is needed
|
||||
for Unicode support.
|
||||
|
||||
- Doesn't work out of the box on Windows
|
||||
|
||||
Can be made to work with 'pip install windows-curses' though. See the
|
||||
https://github.com/zephyrproject-rtos/windows-curses repository.
|
||||
|
||||
'pip install kconfiglib' on Windows automatically installs windows-curses
|
||||
to make the menuconfig usable.
|
||||
'pip install kconfiglib' on Windows automatically installs windows-curses
|
||||
to make the menuconfig usable.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import curses
|
||||
import errno
|
||||
import locale
|
||||
|
@ -208,12 +204,12 @@ from kconfiglib import Symbol, Choice, MENU, COMMENT, MenuNode, \
|
|||
# Configuration variables
|
||||
#
|
||||
|
||||
# If True, try to convert LC_CTYPE to a UTF-8 locale if it is set to the C
|
||||
# If True, try to change LC_CTYPE to a UTF-8 locale if it is set to the C
|
||||
# locale (which implies ASCII). This fixes curses Unicode I/O issues on systems
|
||||
# with bad defaults. ncurses configures itself from the locale settings.
|
||||
#
|
||||
# Related PEP: https://www.python.org/dev/peps/pep-0538/
|
||||
_CONVERT_C_LC_CTYPE_TO_UTF8 = True
|
||||
_CHANGE_C_LC_CTYPE_TO_UTF8 = True
|
||||
|
||||
# How many steps an implicit submenu will be indented. Implicit submenus are
|
||||
# created when an item depends on the symbol before it. Note that symbols
|
||||
|
@ -679,8 +675,8 @@ def menuconfig(kconf):
|
|||
locale.setlocale(locale.LC_ALL, "")
|
||||
|
||||
# Try to fix Unicode issues on systems with bad defaults
|
||||
if _CONVERT_C_LC_CTYPE_TO_UTF8:
|
||||
_convert_c_lc_ctype_to_utf8()
|
||||
if _CHANGE_C_LC_CTYPE_TO_UTF8:
|
||||
_change_c_lc_ctype_to_utf8()
|
||||
|
||||
# Get rid of the delay between pressing ESC and jumping to the parent menu,
|
||||
# unless the user has set ESCDELAY (see ncurses(3)). This makes the UI much
|
||||
|
@ -804,7 +800,7 @@ def _menuconfig(stdscr):
|
|||
curses.doupdate()
|
||||
|
||||
|
||||
c = _get_wch_compat(_menu_win)
|
||||
c = _getch_compat(_menu_win)
|
||||
|
||||
if c == curses.KEY_RESIZE:
|
||||
_resize_main()
|
||||
|
@ -957,10 +953,12 @@ def _init():
|
|||
# Looking for this in addition to KEY_BACKSPACE (which is unreliable) makes
|
||||
# backspace work with TERM=vt100. That makes it likely to work in sane
|
||||
# environments.
|
||||
#
|
||||
# erasechar() returns a 'bytes' object. Since we use get_wch(), we need to
|
||||
# decode it. Just give up and avoid crashing if it can't be decoded.
|
||||
_ERASE_CHAR = curses.erasechar().decode("utf-8", "ignore")
|
||||
_ERASE_CHAR = curses.erasechar()
|
||||
if sys.version_info[0] >= 3:
|
||||
# erasechar() returns a one-byte bytes object on Python 3. This sets
|
||||
# _ERASE_CHAR to a blank string if it can't be decoded, which should be
|
||||
# harmless.
|
||||
_ERASE_CHAR = _ERASE_CHAR.decode("utf-8", "ignore")
|
||||
|
||||
_init_styles()
|
||||
|
||||
|
@ -1717,7 +1715,7 @@ def _input_dialog(title, initial_text, info_text=None):
|
|||
curses.doupdate()
|
||||
|
||||
|
||||
c = _get_wch_compat(win)
|
||||
c = _getch_compat(win)
|
||||
|
||||
if c == curses.KEY_RESIZE:
|
||||
# Resize the main display too. The dialog floats above it.
|
||||
|
@ -1921,7 +1919,7 @@ def _key_dialog(title, text, keys):
|
|||
curses.doupdate()
|
||||
|
||||
|
||||
c = _get_wch_compat(win)
|
||||
c = _getch_compat(win)
|
||||
|
||||
if c == curses.KEY_RESIZE:
|
||||
# Resize the main display too. The dialog floats above it.
|
||||
|
@ -2019,30 +2017,29 @@ def _jump_to_dialog():
|
|||
|
||||
_safe_curs_set(2)
|
||||
|
||||
# TODO: Code duplication with _select_{next,prev}_menu_entry(). Can this be
|
||||
# factored out in some nice way?
|
||||
# Logic duplication with _select_{next,prev}_menu_entry(), except we do a
|
||||
# functional variant that returns the new (sel_node_i, scroll) values to
|
||||
# avoid 'nonlocal'. TODO: Can this be factored out in some nice way?
|
||||
|
||||
def select_next_match():
|
||||
nonlocal sel_node_i
|
||||
nonlocal scroll
|
||||
if sel_node_i == len(matches) - 1:
|
||||
return sel_node_i, scroll
|
||||
|
||||
if sel_node_i < len(matches) - 1:
|
||||
sel_node_i += 1
|
||||
if sel_node_i + 1 >= scroll + _height(matches_win) - _SCROLL_OFFSET \
|
||||
and scroll < _max_scroll(matches, matches_win):
|
||||
|
||||
if sel_node_i >= scroll + _height(matches_win) - _SCROLL_OFFSET \
|
||||
and scroll < _max_scroll(matches, matches_win):
|
||||
return sel_node_i + 1, scroll + 1
|
||||
|
||||
scroll += 1
|
||||
return sel_node_i + 1, scroll
|
||||
|
||||
def select_prev_match():
|
||||
nonlocal sel_node_i
|
||||
nonlocal scroll
|
||||
if sel_node_i == 0:
|
||||
return sel_node_i, scroll
|
||||
|
||||
if sel_node_i > 0:
|
||||
sel_node_i -= 1
|
||||
if sel_node_i - 1 < scroll + _SCROLL_OFFSET:
|
||||
return sel_node_i - 1, max(scroll - 1, 0)
|
||||
|
||||
if sel_node_i < scroll + _SCROLL_OFFSET:
|
||||
scroll = max(scroll - 1, 0)
|
||||
return sel_node_i - 1, scroll
|
||||
|
||||
while True:
|
||||
if s != prev_s:
|
||||
|
@ -2118,7 +2115,7 @@ def _jump_to_dialog():
|
|||
curses.doupdate()
|
||||
|
||||
|
||||
c = _get_wch_compat(edit_box)
|
||||
c = _getch_compat(edit_box)
|
||||
|
||||
if c == "\n":
|
||||
if matches:
|
||||
|
@ -2149,21 +2146,21 @@ def _jump_to_dialog():
|
|||
sel_node_i, scroll)
|
||||
|
||||
elif c == curses.KEY_DOWN:
|
||||
select_next_match()
|
||||
sel_node_i, scroll = select_next_match()
|
||||
|
||||
elif c == curses.KEY_UP:
|
||||
select_prev_match()
|
||||
sel_node_i, scroll = select_prev_match()
|
||||
|
||||
elif c in (curses.KEY_NPAGE, "\x04"): # Page Down/Ctrl-D
|
||||
# Keep it simple. This way we get sane behavior for small windows,
|
||||
# etc., for free.
|
||||
for _ in range(_PG_JUMP):
|
||||
select_next_match()
|
||||
sel_node_i, scroll = select_next_match()
|
||||
|
||||
# Page Up (no Ctrl-U, as it's already used by the edit box)
|
||||
elif c == curses.KEY_PPAGE:
|
||||
for _ in range(_PG_JUMP):
|
||||
select_prev_match()
|
||||
sel_node_i, scroll = select_prev_match()
|
||||
|
||||
elif c == curses.KEY_END:
|
||||
sel_node_i = len(matches) - 1
|
||||
|
@ -2383,7 +2380,7 @@ def _info_dialog(node, from_jump_to_dialog):
|
|||
curses.doupdate()
|
||||
|
||||
|
||||
c = _get_wch_compat(text_win)
|
||||
c = _getch_compat(text_win)
|
||||
|
||||
if c == curses.KEY_RESIZE:
|
||||
_resize_info_dialog(top_line_win, text_win, bot_sep_win, help_win)
|
||||
|
@ -2619,8 +2616,7 @@ def _help_info(sc):
|
|||
|
||||
for node in sc.nodes:
|
||||
if node.help is not None:
|
||||
s += "Help:\n\n{}\n\n" \
|
||||
.format(textwrap.indent(node.help, " "))
|
||||
s += "Help:\n\n{}\n\n".format(_indent(node.help, 2))
|
||||
|
||||
return s
|
||||
|
||||
|
@ -2645,7 +2641,7 @@ def _defaults_info(sc):
|
|||
|
||||
s = "Defaults:\n"
|
||||
|
||||
for val, cond in sc.defaults:
|
||||
for val, cond in sc.orig_defaults:
|
||||
s += " - "
|
||||
if isinstance(sc, Symbol):
|
||||
s += _expr_str(val)
|
||||
|
@ -2708,34 +2704,34 @@ def _select_imply_info(sym):
|
|||
# 'sym'. The selecting/implying symbols are grouped according to which
|
||||
# value they select/imply 'sym' to (n/m/y).
|
||||
|
||||
s = ""
|
||||
|
||||
def add_sis(expr, val, title):
|
||||
nonlocal s
|
||||
|
||||
def sis(expr, val, title):
|
||||
# sis = selects/implies
|
||||
sis = [si for si in split_expr(expr, OR) if expr_value(si) == val]
|
||||
if sis:
|
||||
s += title
|
||||
for si in sis:
|
||||
s += " - {}\n".format(split_expr(si, AND)[0].name)
|
||||
s += "\n"
|
||||
if not sis:
|
||||
return ""
|
||||
|
||||
res = title
|
||||
for si in sis:
|
||||
res += " - {}\n".format(split_expr(si, AND)[0].name)
|
||||
return res + "\n"
|
||||
|
||||
s = ""
|
||||
|
||||
if sym.rev_dep is not _kconf.n:
|
||||
add_sis(sym.rev_dep, 2,
|
||||
"Symbols currently y-selecting this symbol:\n")
|
||||
add_sis(sym.rev_dep, 1,
|
||||
"Symbols currently m-selecting this symbol:\n")
|
||||
add_sis(sym.rev_dep, 0,
|
||||
"Symbols currently n-selecting this symbol (no effect):\n")
|
||||
s += sis(sym.rev_dep, 2,
|
||||
"Symbols currently y-selecting this symbol:\n")
|
||||
s += sis(sym.rev_dep, 1,
|
||||
"Symbols currently m-selecting this symbol:\n")
|
||||
s += sis(sym.rev_dep, 0,
|
||||
"Symbols currently n-selecting this symbol (no effect):\n")
|
||||
|
||||
if sym.weak_rev_dep is not _kconf.n:
|
||||
add_sis(sym.weak_rev_dep, 2,
|
||||
"Symbols currently y-implying this symbol:\n")
|
||||
add_sis(sym.weak_rev_dep, 1,
|
||||
"Symbols currently m-implying this symbol:\n")
|
||||
add_sis(sym.weak_rev_dep, 0,
|
||||
"Symbols currently n-implying this symbol (no effect):\n")
|
||||
s += sis(sym.weak_rev_dep, 2,
|
||||
"Symbols currently y-implying this symbol:\n")
|
||||
s += sis(sym.weak_rev_dep, 1,
|
||||
"Symbols currently m-implying this symbol:\n")
|
||||
s += sis(sym.weak_rev_dep, 0,
|
||||
"Symbols currently n-implying this symbol (no effect):\n")
|
||||
|
||||
return s
|
||||
|
||||
|
@ -2759,7 +2755,7 @@ def _kconfig_def_info(item):
|
|||
.format(node.filename, node.linenr,
|
||||
_include_path_info(node),
|
||||
_menu_path_info(node),
|
||||
textwrap.indent(node.custom_str(_name_and_val_str), " "))
|
||||
_indent(node.custom_str(_name_and_val_str), 2))
|
||||
|
||||
return s
|
||||
|
||||
|
@ -2791,6 +2787,13 @@ def _menu_path_info(node):
|
|||
return "(Top)" + path
|
||||
|
||||
|
||||
def _indent(s, n):
|
||||
# Returns 's' with each line indented 'n' spaces. textwrap.indent() is not
|
||||
# available in Python 2 (it's 3.3+).
|
||||
|
||||
return "\n".join(n*" " + line for line in s.split("\n"))
|
||||
|
||||
|
||||
def _name_and_val_str(sc):
|
||||
# Custom symbol/choice printer that shows symbol values after symbols
|
||||
|
||||
|
@ -3074,14 +3077,12 @@ def _check_valid(sym, s):
|
|||
|
||||
for low_sym, high_sym, cond in sym.ranges:
|
||||
if expr_value(cond):
|
||||
low = int(low_sym.str_value, base)
|
||||
val = int(s, base)
|
||||
high = int(high_sym.str_value, base)
|
||||
low_s = low_sym.str_value
|
||||
high_s = high_sym.str_value
|
||||
|
||||
if not low <= val <= high:
|
||||
if not int(low_s, base) <= int(s, base) <= int(high_s, base):
|
||||
_error("{} is outside the range {}-{}"
|
||||
.format(s, low_sym.str_value, high_sym.str_value))
|
||||
|
||||
.format(s, low_s, high_s))
|
||||
return False
|
||||
|
||||
break
|
||||
|
@ -3120,7 +3121,17 @@ def _is_num(name):
|
|||
return True
|
||||
|
||||
|
||||
def _get_wch_compat(win):
|
||||
def _getch_compat(win):
|
||||
# Uses get_wch() if available (Python 3.3+) and getch() otherwise. Also
|
||||
# handles a PDCurses resizing quirk.
|
||||
|
||||
if hasattr(win, "get_wch"):
|
||||
c = win.get_wch()
|
||||
else:
|
||||
c = win.getch()
|
||||
if 0 <= c <= 255:
|
||||
c = chr(c)
|
||||
|
||||
# Decent resizing behavior on PDCurses requires calling resize_term(0, 0)
|
||||
# after receiving KEY_RESIZE, while ncurses (usually) handles terminal
|
||||
# resizing automatically in get(_w)ch() (see the end of the
|
||||
|
@ -3129,8 +3140,6 @@ def _get_wch_compat(win):
|
|||
# resize_term(0, 0) reliably fails and does nothing on ncurses, so this
|
||||
# hack gives ncurses/PDCurses compatibility for resizing. I don't know
|
||||
# whether it would cause trouble for other implementations.
|
||||
|
||||
c = win.get_wch()
|
||||
if c == curses.KEY_RESIZE:
|
||||
try:
|
||||
curses.resize_term(0, 0)
|
||||
|
@ -3219,8 +3228,8 @@ def _safe_move(win, *args):
|
|||
pass
|
||||
|
||||
|
||||
def _convert_c_lc_ctype_to_utf8():
|
||||
# See _CONVERT_C_LC_CTYPE_TO_UTF8
|
||||
def _change_c_lc_ctype_to_utf8():
|
||||
# See _CHANGE_C_LC_CTYPE_TO_UTF8
|
||||
|
||||
if _IS_WINDOWS:
|
||||
# Windows rarely has issues here, and the PEP 538 implementation avoids
|
||||
|
@ -3236,15 +3245,13 @@ def _convert_c_lc_ctype_to_utf8():
|
|||
return False
|
||||
|
||||
# Is LC_CTYPE set to the C locale?
|
||||
if locale.setlocale(locale.LC_CTYPE, None) == "C":
|
||||
if locale.setlocale(locale.LC_CTYPE) == "C":
|
||||
# This list was taken from the PEP 538 implementation in the CPython
|
||||
# code, in Python/pylifecycle.c
|
||||
for loc in "C.UTF-8", "C.utf8", "UTF-8":
|
||||
if try_set_locale(loc):
|
||||
print("Note: Your environment is configured to use ASCII. To "
|
||||
"avoid Unicode issues, LC_CTYPE was changed from the "
|
||||
"C locale to the {} locale.".format(loc))
|
||||
break
|
||||
# LC_CTYPE successfully changed
|
||||
return
|
||||
|
||||
|
||||
# Are we running on Windows?
|
||||
|
|
Loading…
Reference in a new issue