Changeset cf2f109 for menu/kconfiglib.py


Ignore:
Timestamp:
06/15/2019 05:25:10 PM (5 years ago)
Author:
Pierre Labastie <pierre@…>
Branches:
ablfs-more, legacy, trunk
Children:
a4af6811
Parents:
619b313
Message:

Update to Kconfiglib version 12.4.0. This removes the need to use
".configuration.old"

File:
1 edited

Legend:

Unmodified
Added
Removed
  • menu/kconfiglib.py

    r619b313 rcf2f109  
    1313overview.
    1414
     15Since Kconfiglib 12.0.0, the library version is available in
     16kconfiglib.VERSION, which is a (<major>, <minor>, <patch>) tuple, e.g.
     17(12, 0, 0).
     18
     19
    1520Using Kconfiglib on the Linux kernel with the Makefile targets
    1621==============================================================
     
    4853----------------
    4954
    50 This target runs the curses menuconfig interface with Python 3 (Python 2 is
    51 currently not supported for the menuconfig).
     55This target runs the curses menuconfig interface with Python 3. As of
     56Kconfiglib 12.2.0, both Python 2 and Python 3 are supported (previously, only
     57Python 3 was supported, so this was a backport).
     58
     59
     60make guiconfig
     61--------------
     62
     63This target runs the Tkinter menuconfig interface. Both Python 2 and Python 3
     64are supported. To change the Python interpreter used, pass
     65PYTHONCMD=<executable> to 'make'. The default is 'python'.
    5266
    5367
     
    5771This target gives an interactive Python prompt where a Kconfig instance has
    5872been preloaded and is available in 'kconf'. To change the Python interpreter
    59 used, pass PYTHONCMD=<executable> to make. The default is "python".
     73used, pass PYTHONCMD=<executable> to 'make'. The default is 'python'.
    6074
    6175To get a feel for the API, try evaluating and printing the symbols in
     
    383397
    384398'source' and 'rsource' accept glob patterns, sourcing all matching Kconfig
    385 files. They require at least one matching file, throwing a KconfigError
     399files. They require at least one matching file, raising a KconfigError
    386400otherwise.
    387401
     
    438452    such warnings are generated.
    439453
    440     This warning can also be enabled/disabled via
    441     Kconfig.enable/disable_undef_warnings().
     454    This warning can also be enabled/disabled via the Kconfig.warn_assign_undef
     455    variable.
    442456
    443457
     
    530544# Get rid of some attribute lookups. These are obvious in context.
    531545from glob import iglob
    532 from os.path import dirname, exists, expandvars, isabs, islink, join, \
    533                     relpath, split
     546from os.path import dirname, exists, expandvars, islink, join, realpath
     547
     548
     549VERSION = (12, 4, 0)
    534550
    535551
     
    620636      appear multiple times. Use set() to get unique filenames.
    621637
    622       Note: Using this for incremental builds is redundant. Kconfig.sync_deps()
    623       already indirectly catches any file modifications that change the
    624       configuration output.
     638      Note that Kconfig.sync_deps() already indirectly catches any file
     639      modifications that change configuration output.
    625640
    626641    env_vars:
     
    692707      Variable class.
    693708
     709    warn:
     710      Set this variable to True/False to enable/disable warnings. See
     711      Kconfig.__init__().
     712
     713      When 'warn' is False, the values of the other warning-related variables
     714      are ignored.
     715
     716      This variable as well as the other warn* variables can be read to check
     717      the current warning settings.
     718
     719    warn_to_stderr:
     720      Set this variable to True/False to enable/disable warnings on stderr. See
     721      Kconfig.__init__().
     722
     723    warn_assign_undef:
     724      Set this variable to True to generate warnings for assignments to
     725      undefined symbols in configuration files.
     726
     727      This variable is False by default unless the KCONFIG_WARN_UNDEF_ASSIGN
     728      environment variable was set to 'y' when the Kconfig instance was
     729      created.
     730
     731    warn_assign_override:
     732      Set this variable to True to generate warnings for multiple assignments
     733      to the same symbol in configuration files, where the assignments set
     734      different values (e.g. CONFIG_FOO=m followed by CONFIG_FOO=y, where the
     735      last value would get used).
     736
     737      This variable is True by default. Disabling it might be useful when
     738      merging configurations.
     739
     740    warn_assign_redun:
     741      Like warn_assign_override, but for multiple assignments setting a symbol
     742      to the same value.
     743
     744      This variable is True by default. Disabling it might be useful when
     745      merging configurations.
     746
    694747    warnings:
    695       A list of strings containing all warnings that have been generated. This
    696       allows flexibility in how warnings are printed and processed.
     748      A list of strings containing all warnings that have been generated, for
     749      cases where more flexibility is needed.
    697750
    698751      See the 'warn_to_stderr' parameter to Kconfig.__init__() and the
    699       Kconfig.enable/disable_stderr_warnings() functions as well. Note that
    700       warnings still get added to Kconfig.warnings when 'warn_to_stderr' is
    701       True.
    702 
    703       Just as for warnings printed to stderr, only optional warnings that are
    704       enabled will get added to Kconfig.warnings. See the various
    705       Kconfig.enable/disable_*_warnings() functions.
     752      Kconfig.warn_to_stderr variable as well. Note that warnings still get
     753      added to Kconfig.warnings when 'warn_to_stderr' is True.
     754
     755      Just as for warnings printed to stderr, only warnings that are enabled
     756      will get added to Kconfig.warnings. See the various Kconfig.warn*
     757      variables.
    706758
    707759    missing_syms:
     
    742794        "_functions",
    743795        "_set_match",
     796        "_srctree_prefix",
    744797        "_unset_match",
    745         "_warn_for_no_prompt",
    746         "_warn_for_override",
    747         "_warn_for_redun_assign",
    748         "_warn_for_undef_assign",
    749         "_warn_to_stderr",
    750         "_warnings_enabled",
     798        "_warn_no_prompt",
    751799        "choices",
    752800        "comments",
     
    770818        "unique_defined_syms",
    771819        "variables",
     820        "warn",
     821        "warn_assign_override",
     822        "warn_assign_redun",
     823        "warn_assign_undef",
     824        "warn_to_stderr",
    772825        "warnings",
    773826        "y",
     
    801854        KCONFIG_WARN_UNDEF_ASSIGN).
    802855
    803         Raises KconfigError on syntax errors, and (possibly a subclass of)
    804         IOError on IO errors ('errno', 'strerror', and 'filename' are
     856        Raises KconfigError on syntax/semantic errors, and (possibly a subclass
     857        of) IOError on IO errors ('errno', 'strerror', and 'filename' are
    805858        available). Note that IOError can be caught as OSError on Python 3.
    806859
     
    821874        warn (default: True):
    822875          True if warnings related to this configuration should be generated.
    823           This can be changed later with Kconfig.enable/disable_warnings(). It
     876          This can be changed later by setting Kconfig.warn to True/False. It
    824877          is provided as a constructor argument since warnings might be
    825878          generated during parsing.
    826879
    827           See the other Kconfig.enable_*_warnings() functions as well, which
    828           enable or suppress certain warnings when warnings are enabled.
     880          See the other Kconfig.warn_* variables as well, which enable or
     881          suppress certain warnings when warnings are enabled.
    829882
    830883          All generated warnings are added to the Kconfig.warnings list. See
     
    835888          added to Kconfig.warnings.
    836889
    837           This can be changed later with
    838           Kconfig.enable/disable_stderr_warnings().
     890          This can be changed later by setting Kconfig.warn_to_stderr to
     891          True/False.
    839892
    840893        encoding (default: "utf-8"):
     
    853906        """
    854907        self.srctree = os.environ.get("srctree", "")
     908        # A prefix we can reliably strip from glob() results to get a filename
     909        # relative to $srctree. relpath() can cause issues for symlinks,
     910        # because it assumes symlink/../foo is the same as foo/.
     911        self._srctree_prefix = realpath(self.srctree) + os.sep
     912
    855913        self.config_prefix = os.environ.get("CONFIG_", "CONFIG_")
    856914
     
    863921        self.warnings = []
    864922
    865         self._warnings_enabled = warn
    866         self._warn_to_stderr = warn_to_stderr
    867         self._warn_for_undef_assign = \
     923        self.warn = warn
     924        self.warn_to_stderr = warn_to_stderr
     925        self.warn_assign_undef = \
    868926            os.environ.get("KCONFIG_WARN_UNDEF_ASSIGN") == "y"
    869         self._warn_for_redun_assign = self._warn_for_override = True
     927        self.warn_assign_override = self.warn_assign_redun = True
    870928
    871929
     
    10191077
    10201078
    1021         self._warn_for_no_prompt = True
     1079        self._warn_no_prompt = True
    10221080
    10231081        self.mainmenu_text = self.top_node.prompt[0]
     
    10391097        return None
    10401098
    1041     def load_config(self, filename=None, replace=True, verbose=True):
     1099    def load_config(self, filename=None, replace=True, verbose=None):
    10421100        """
    10431101        Loads symbol values from a file in the .config format. Equivalent to
     
    10871145          .config. Pass False to merge configurations.
    10881146
    1089         verbose (default: True):
    1090           If True and filename is None (automatically infer configuration
    1091           file), a message will be printed to stdout telling which file got
    1092           loaded (or that no file got loaded). This is meant to reduce
    1093           boilerplate in tools.
    1094 
    1095         Returns True if an existing configuration was loaded (that didn't come
    1096         from the 'option defconfig_list' symbol), and False otherwise. This is
    1097         mostly useful in conjunction with filename=None, as True will always be
    1098         returned otherwise.
    1099         """
    1100         loaded_existing = True
     1147        verbose (default: None):
     1148          Limited backwards compatibility to prevent crashes. A warning is
     1149          printed if anything but None is passed.
     1150
     1151          Prior to Kconfiglib 12.0.0, this option enabled printing of messages
     1152          to stdout when 'filename' was None. A message is (always) returned
     1153          now instead, which is more flexible.
     1154
     1155          Will probably be removed in some future version.
     1156
     1157        Returns a string with a message saying which file got loaded (or
     1158        possibly that no file got loaded, when 'filename' is None). This is
     1159        meant to reduce boilerplate in tools, which can do e.g.
     1160        print(kconf.load_config()). The returned message distinguishes between
     1161        loading (replace == True) and merging (replace == False).
     1162        """
     1163        if verbose is not None:
     1164            _warn_verbose_deprecated("load_config")
     1165
     1166        msg = None
    11011167        if filename is None:
    11021168            filename = standard_config_filename()
    1103             if exists(filename):
    1104                 if verbose:
    1105                     print("Using existing configuration '{}' as base"
    1106                           .format(filename))
    1107             else:
    1108                 filename = self.defconfig_filename
    1109                 if filename is None:
    1110                     if verbose:
    1111                         print("Using default symbol values as base")
    1112                     return False
    1113 
    1114                 if verbose:
    1115                     print("Using default configuration found in '{}' as "
    1116                           "base".format(filename))
    1117 
    1118                 loaded_existing = False
     1169            if not exists(filename) and \
     1170               not exists(join(self.srctree, filename)):
     1171                defconfig = self.defconfig_filename
     1172                if defconfig is None:
     1173                    return "Using default symbol values (no '{}')" \
     1174                           .format(filename)
     1175
     1176                msg = " default configuration '{}' (no '{}')" \
     1177                      .format(defconfig, filename)
     1178                filename = defconfig
     1179
     1180        if not msg:
     1181            msg = " configuration '{}'".format(filename)
    11191182
    11201183        # Disable the warning about assigning to symbols without prompts. This
    11211184        # is normal and expected within a .config file.
    1122         self._warn_for_no_prompt = False
    1123 
    1124         # This stub only exists to make sure _warn_for_no_prompt gets reenabled
     1185        self._warn_no_prompt = False
     1186
     1187        # This stub only exists to make sure _warn_no_prompt gets reenabled
    11251188        try:
    11261189            self._load_config(filename, replace)
     
    11281191            _decoding_error(e, filename)
    11291192        finally:
    1130             self._warn_for_no_prompt = True
    1131 
    1132         return loaded_existing
     1193            self._warn_no_prompt = True
     1194
     1195        return ("Loaded" if replace else "Merged") + msg
    11331196
    11341197    def _load_config(self, filename, replace):
     
    12511314                        display_user_val = sym.user_value
    12521315
    1253                     msg = '{} set more than once. Old value: "{}", new value: "{}".'.format(
     1316                    msg = '{} set more than once. Old value "{}", new value "{}".'.format(
    12541317                        _name_and_loc(sym), display_user_val, val
    12551318                    )
    12561319
    12571320                    if display_user_val == val:
    1258                         self._warn_redun_assign(msg, filename, linenr)
    1259                     else:
    1260                         self._warn_override(msg, filename, linenr)
     1321                        if self.warn_assign_redun:
     1322                            self._warn(msg, filename, linenr)
     1323                    elif self.warn_assign_override:
     1324                        self._warn(msg, filename, linenr)
    12611325
    12621326                sym.set_value(val)
     
    12781342
    12791343        self.missing_syms.append((name, val))
    1280 
    1281         if self._warn_for_undef_assign:
     1344        if self.warn_assign_undef:
    12821345            self._warn(
    12831346                "attempt to assign the value '{}' to the undefined symbol {}"
     
    12941357        table implementation as of writing, and so won't match.
    12951358
     1359        If 'filename' exists and its contents is identical to what would get
     1360        written out, it is left untouched. This avoids updating file metadata
     1361        like the modification time and possibly triggering redundant work in
     1362        build tools.
     1363
    12961364        filename:
    12971365          Self-explanatory.
     
    13021370          and include a final terminating newline.
    13031371        """
    1304         with self._open(filename, "w") as f:
    1305             f.write(header)
    1306 
    1307             for sym in self.unique_defined_syms:
    1308                 # Note: _write_to_conf is determined when the value is
    1309                 # calculated. This is a hidden function call due to
    1310                 # property magic.
    1311                 val = sym.str_value
    1312                 if sym._write_to_conf:
    1313                     if sym.orig_type in _BOOL_TRISTATE:
    1314                         if val != "n":
    1315                             f.write("#define {}{}{} 1\n"
    1316                                     .format(self.config_prefix, sym.name,
    1317                                             "_MODULE" if val == "m" else ""))
    1318 
    1319                     elif sym.orig_type is STRING:
    1320                         f.write('#define {}{} "{}"\n'
    1321                                 .format(self.config_prefix, sym.name,
    1322                                         escape(val)))
    1323 
    1324                     else:  # sym.orig_type in _INT_HEX:
    1325                         if sym.orig_type is HEX and \
    1326                            not val.startswith(("0x", "0X")):
    1327                             val = "0x" + val
    1328 
    1329                         f.write("#define {}{} {}\n"
    1330                                 .format(self.config_prefix, sym.name, val))
     1372        self._write_if_changed(filename, self._autoconf_contents(header))
     1373
     1374    def _autoconf_contents(self, header):
     1375        # write_autoconf() helper. Returns the contents to write as a string,
     1376        # with 'header' at the beginning.
     1377
     1378        # "".join()ed later
     1379        chunks = [header]
     1380        add = chunks.append
     1381
     1382        for sym in self.unique_defined_syms:
     1383            # _write_to_conf is determined when the value is calculated. This
     1384            # is a hidden function call due to property magic.
     1385            val = sym.str_value
     1386            if not sym._write_to_conf:
     1387                continue
     1388
     1389            if sym.orig_type in _BOOL_TRISTATE:
     1390                if val == "y":
     1391                    add("#define {}{} 1\n"
     1392                        .format(self.config_prefix, sym.name))
     1393                elif val == "m":
     1394                    add("#define {}{}_MODULE 1\n"
     1395                        .format(self.config_prefix, sym.name))
     1396
     1397            elif sym.orig_type is STRING:
     1398                add('#define {}{} "{}"\n'
     1399                    .format(self.config_prefix, sym.name, escape(val)))
     1400
     1401            else:  # sym.orig_type in _INT_HEX:
     1402                if sym.orig_type is HEX and \
     1403                   not val.startswith(("0x", "0X")):
     1404                    val = "0x" + val
     1405
     1406                add("#define {}{} {}\n"
     1407                    .format(self.config_prefix, sym.name, val))
     1408
     1409        return "".join(chunks)
    13311410
    13321411    def write_config(self, filename=None,
    13331412                     header="# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n",
    1334                      save_old=True, verbose=True):
     1413                     save_old=True, verbose=None):
    13351414        r"""
    13361415        Writes out symbol values in the .config format. The format matches the
     
    13451424        understand which symbols get written out.
    13461425
     1426        If 'filename' exists and its contents is identical to what would get
     1427        written out, it is left untouched. This avoids updating file metadata
     1428        like the modification time and possibly triggering redundant work in
     1429        build tools.
     1430
    13471431        filename (default: None):
    13481432          Filename to save configuration to (a string).
    13491433
    1350           If None (the default), the filename in the the environment variable
     1434          If None (the default), the filename in the environment variable
    13511435          KCONFIG_CONFIG is used if set, and ".config" otherwise. See
    13521436          standard_config_filename().
     
    13591443        save_old (default: True):
    13601444          If True and <filename> already exists, a copy of it will be saved to
    1361           .<filename>.old in the same directory before the new configuration is
    1362           written. The leading dot is added only if the filename doesn't
    1363           already start with a dot.
    1364 
    1365           Errors are silently ignored if .<filename>.old cannot be written
    1366           (e.g. due to being a directory).
    1367 
    1368         verbose (default: True):
    1369           If True and filename is None (automatically infer configuration
    1370           file), a message will be printed to stdout telling which file got
    1371           written. This is meant to reduce boilerplate in tools.
    1372         """
     1445          <filename>.old in the same directory before the new configuration is
     1446          written.
     1447
     1448          Errors are silently ignored if <filename>.old cannot be written (e.g.
     1449          due to being a directory, or <filename> being something like
     1450          /dev/null).
     1451
     1452        verbose (default: None):
     1453          Limited backwards compatibility to prevent crashes. A warning is
     1454          printed if anything but None is passed.
     1455
     1456          Prior to Kconfiglib 12.0.0, this option enabled printing of messages
     1457          to stdout when 'filename' was None. A message is (always) returned
     1458          now instead, which is more flexible.
     1459
     1460          Will probably be removed in some future version.
     1461
     1462        Returns a string with a message saying which file got saved. This is
     1463        meant to reduce boilerplate in tools, which can do e.g.
     1464        print(kconf.write_config()).
     1465        """
     1466        if verbose is not None:
     1467            _warn_verbose_deprecated("write_config")
     1468
    13731469        if filename is None:
    13741470            filename = standard_config_filename()
    1375         else:
    1376             verbose = False
     1471
     1472        contents = self._config_contents(header)
     1473        if self._contents_eq(filename, contents):
     1474            return "No change to '{}'".format(filename)
    13771475
    13781476        if save_old:
     
    13801478
    13811479        with self._open(filename, "w") as f:
    1382             f.write(header)
    1383 
    1384             for node in self.node_iter(unique_syms=True):
    1385                 item = node.item
    1386 
    1387                 if item.__class__ is Symbol:
    1388                     f.write(item.config_string)
    1389 
    1390                 elif expr_value(node.dep) and \
    1391                      ((item is MENU and expr_value(node.visibility)) or
    1392                        item is COMMENT):
    1393 
    1394                     f.write("\n#\n# {}\n#\n".format(node.prompt[0]))
    1395 
    1396         if verbose:
    1397             print("Configuration written to '{}'".format(filename))
     1480            f.write(contents)
     1481
     1482        return "Configuration saved to '{}'".format(filename)
     1483
     1484    def _config_contents(self, header):
     1485        # write_config() helper. Returns the contents to write as a string,
     1486        # with 'header' at the beginning.
     1487        #
     1488        # More memory friendly would be to 'yield' the strings and
     1489        # "".join(_config_contents()), but it was a bit slower on my system.
     1490
     1491        # node_iter() was used here before commit 3aea9f7 ("Add '# end of
     1492        # <menu>' after menus in .config"). Those comments get tricky to
     1493        # implement with it.
     1494
     1495        for sym in self.unique_defined_syms:
     1496            sym._visited = False
     1497
     1498        # Did we just print an '# end of ...' comment?
     1499        after_end_comment = False
     1500
     1501        # "".join()ed later
     1502        chunks = [header]
     1503        add = chunks.append
     1504
     1505        node = self.top_node
     1506        while 1:
     1507            # Jump to the next node with an iterative tree walk
     1508            if node.list:
     1509                node = node.list
     1510            elif node.next:
     1511                node = node.next
     1512            else:
     1513                while node.parent:
     1514                    node = node.parent
     1515
     1516                    # Add a comment when leaving visible menus
     1517                    if node.item is MENU and expr_value(node.dep) and \
     1518                       expr_value(node.visibility) and \
     1519                       node is not self.top_node:
     1520                        add("# end of {}\n".format(node.prompt[0]))
     1521                        after_end_comment = True
     1522
     1523                    if node.next:
     1524                        node = node.next
     1525                        break
     1526                else:
     1527                    # No more nodes
     1528                    return "".join(chunks)
     1529
     1530            # Generate configuration output for the node
     1531
     1532            item = node.item
     1533
     1534            if item.__class__ is Symbol:
     1535                if item._visited:
     1536                    continue
     1537                item._visited = True
     1538
     1539                conf_string = item.config_string
     1540                if not conf_string:
     1541                    continue
     1542
     1543                if after_end_comment:
     1544                    # Add a blank line before the first symbol printed after an
     1545                    # '# end of ...' comment
     1546                    after_end_comment = False
     1547                    add("\n")
     1548                add(conf_string)
     1549
     1550            elif expr_value(node.dep) and \
     1551                 ((item is MENU and expr_value(node.visibility)) or
     1552                   item is COMMENT):
     1553
     1554                add("\n#\n# {}\n#\n".format(node.prompt[0]))
     1555                after_end_comment = False
    13981556
    13991557    def write_min_config(self, filename,
     
    14171575          would usually want each line to start with '#' to make it a comment,
    14181576          and include a final terminating newline.
    1419         """
     1577
     1578        Returns a string with a message saying which file got saved. This is
     1579        meant to reduce boilerplate in tools, which can do e.g.
     1580        print(kconf.write_min_config()).
     1581        """
     1582        contents = self._min_config_contents(header)
     1583        if self._contents_eq(filename, contents):
     1584            return "No change to '{}'".format(filename)
     1585
    14201586        with self._open(filename, "w") as f:
    1421             f.write(header)
    1422 
    1423             for sym in self.unique_defined_syms:
    1424                 # Skip symbols that cannot be changed. Only check
    1425                 # non-choice symbols, as selects don't affect choice
    1426                 # symbols.
    1427                 if not sym.choice and \
    1428                    sym.visibility <= expr_value(sym.rev_dep):
    1429                     continue
    1430 
    1431                 # Skip symbols whose value matches their default
    1432                 if sym.str_value == sym._str_default():
    1433                     continue
    1434 
    1435                 # Skip symbols that would be selected by default in a
    1436                 # choice, unless the choice is optional or the symbol type
    1437                 # isn't bool (it might be possible to set the choice mode
    1438                 # to n or the symbol to m in those cases).
    1439                 if sym.choice and \
    1440                    not sym.choice.is_optional and \
    1441                    sym.choice._get_selection_from_defaults() is sym and \
    1442                    sym.orig_type is BOOL and \
    1443                    sym.tri_value == 2:
    1444                     continue
    1445 
    1446                 f.write(sym.config_string)
     1587            f.write(contents)
     1588
     1589        return "Minimal configuration saved to '{}'".format(filename)
     1590
     1591    def _min_config_contents(self, header):
     1592        # write_min_config() helper. Returns the contents to write as a string,
     1593        # with 'header' at the beginning.
     1594
     1595        chunks = [header]
     1596        add = chunks.append
     1597
     1598        for sym in self.unique_defined_syms:
     1599            # Skip symbols that cannot be changed. Only check
     1600            # non-choice symbols, as selects don't affect choice
     1601            # symbols.
     1602            if not sym.choice and \
     1603               sym.visibility <= expr_value(sym.rev_dep):
     1604                continue
     1605
     1606            # Skip symbols whose value matches their default
     1607            if sym.str_value == sym._str_default():
     1608                continue
     1609
     1610            # Skip symbols that would be selected by default in a
     1611            # choice, unless the choice is optional or the symbol type
     1612            # isn't bool (it might be possible to set the choice mode
     1613            # to n or the symbol to m in those cases).
     1614            if sym.choice and \
     1615               not sym.choice.is_optional and \
     1616               sym.choice._get_selection_from_defaults() is sym and \
     1617               sym.orig_type is BOOL and \
     1618               sym.tri_value == 2:
     1619                continue
     1620
     1621            add(sym.config_string)
     1622
     1623        return "".join(chunks)
    14471624
    14481625    def sync_deps(self, path):
     
    14851662             track of them for the next build.
    14861663
     1664             If auto.conf exists and its contents is identical to what would
     1665             get written out, it is left untouched. This avoids updating file
     1666             metadata like the modification time and possibly triggering
     1667             redundant work in build tools.
     1668
    14871669
    14881670        The last piece of the puzzle is knowing what symbols each source file
     
    15031685            os.mkdir(path, 0o755)
    15041686
    1505         # This setup makes sure that at least the current working directory
    1506         # gets reset if things fail
    1507         prev_dir = os.getcwd()
    1508         try:
    1509             # cd'ing into the symbol file directory simplifies
    1510             # _sync_deps() and saves some work
    1511             os.chdir(path)
    1512             self._sync_deps()
    1513         finally:
    1514             os.chdir(prev_dir)
    1515 
    1516     def _sync_deps(self):
    15171687        # Load old values from auto.conf, if any
    1518         self._load_old_vals()
     1688        self._load_old_vals(path)
    15191689
    15201690        for sym in self.unique_defined_syms:
    1521             # Note: _write_to_conf is determined when the value is
    1522             # calculated. This is a hidden function call due to
    1523             # property magic.
     1691            # _write_to_conf is determined when the value is calculated. This
     1692            # is a hidden function call due to property magic.
    15241693            val = sym.str_value
    15251694
    1526             # Note: n tristate values do not get written to auto.conf and
    1527             # autoconf.h, making a missing symbol logically equivalent to n
     1695            # n tristate values do not get written to auto.conf and autoconf.h,
     1696            # making a missing symbol logically equivalent to n
    15281697
    15291698            if sym._write_to_conf:
     
    15471716
    15481717            # 'sym' has a new value. Flag it.
    1549             _touch_dep_file(sym.name)
     1718            _touch_dep_file(path, sym.name)
    15501719
    15511720        # Remember the current values as the "new old" values.
     
    15541723        # putting it last means _sync_deps() can be safely rerun if it fails
    15551724        # before this point.
    1556         self._write_old_vals()
    1557 
    1558     def _write_old_vals(self):
     1725        self._write_old_vals(path)
     1726
     1727    def _load_old_vals(self, path):
     1728        # Loads old symbol values from auto.conf into a dedicated
     1729        # Symbol._old_val field. Mirrors load_config().
     1730        #
     1731        # The extra field could be avoided with some trickery involving dumping
     1732        # symbol values and restoring them later, but this is simpler and
     1733        # faster. The C tools also use a dedicated field for this purpose.
     1734
     1735        for sym in self.unique_defined_syms:
     1736            sym._old_val = None
     1737
     1738        try:
     1739            auto_conf = self._open(join(path, "auto.conf"), "r")
     1740        except IOError as e:
     1741            if e.errno == errno.ENOENT:
     1742                # No old values
     1743                return
     1744            raise
     1745
     1746        with auto_conf as f:
     1747            for line in f:
     1748                match = self._set_match(line)
     1749                if not match:
     1750                    # We only expect CONFIG_FOO=... (and possibly a header
     1751                    # comment) in auto.conf
     1752                    continue
     1753
     1754                name, val = match.groups()
     1755                if name in self.syms:
     1756                    sym = self.syms[name]
     1757
     1758                    if sym.orig_type is STRING:
     1759                        match = _conf_string_match(val)
     1760                        if not match:
     1761                            continue
     1762                        val = unescape(match.group(1))
     1763
     1764                    self.syms[name]._old_val = val
     1765                else:
     1766                    # Flag that the symbol no longer exists, in
     1767                    # case something still depends on it
     1768                    _touch_dep_file(path, name)
     1769
     1770    def _write_old_vals(self, path):
    15591771        # Helper for writing auto.conf. Basically just a simplified
    15601772        # write_config() that doesn't write any comments (including
     
    15661778        # by passing a flag to it, plus we only need to look at symbols here.
    15671779
    1568         with self._open("auto.conf", "w") as f:
    1569             for sym in self.unique_defined_syms:
    1570                 if not (sym.orig_type in _BOOL_TRISTATE and not sym.tri_value):
    1571                     f.write(sym.config_string)
    1572 
    1573     def _load_old_vals(self):
    1574         # Loads old symbol values from auto.conf into a dedicated
    1575         # Symbol._old_val field. Mirrors load_config().
    1576         #
    1577         # The extra field could be avoided with some trickery involving dumping
    1578         # symbol values and restoring them later, but this is simpler and
    1579         # faster. The C tools also use a dedicated field for this purpose.
    1580 
    1581         for sym in self.unique_defined_syms:
    1582             sym._old_val = None
    1583 
    1584         if not exists("auto.conf"):
    1585             # No old values
    1586             return
    1587 
    1588         with self._open("auto.conf", "r") as f:
    1589             for line in f:
    1590                 match = self._set_match(line)
    1591                 if not match:
    1592                     # We only expect CONFIG_FOO=... (and possibly a header
    1593                     # comment) in auto.conf
    1594                     continue
    1595 
    1596                 name, val = match.groups()
    1597                 if name in self.syms:
    1598                     sym = self.syms[name]
    1599 
    1600                     if sym.orig_type is STRING:
    1601                         match = _conf_string_match(val)
    1602                         if not match:
    1603                             continue
    1604                         val = unescape(match.group(1))
    1605 
    1606                     self.syms[name]._old_val = val
    1607                 else:
    1608                     # Flag that the symbol no longer exists, in
    1609                     # case something still depends on it
    1610                     _touch_dep_file(name)
     1780        self._write_if_changed(
     1781            os.path.join(path, "auto.conf"),
     1782            self._old_vals_contents())
     1783
     1784    def _old_vals_contents(self):
     1785        # _write_old_vals() helper. Returns the contents to write as a string.
     1786
     1787        # Temporary list instead of generator makes this a bit faster
     1788        return "".join([
     1789            sym.config_string for sym in self.unique_defined_syms
     1790                if not (sym.orig_type in _BOOL_TRISTATE and not sym.tri_value)
     1791        ])
    16111792
    16121793    def node_iter(self, unique_syms=False):
     
    16861867        self._filename = None
    16871868
    1688         # Don't include the "if " from below to avoid giving confusing error
    1689         # messages
     1869        self._tokens = self._tokenize("if " + s)
     1870        # Strip "if " to avoid giving confusing error messages
    16901871        self._line = s
    1691         self._tokens = self._tokenize("if " + s)
    16921872        self._tokens_i = 1  # Skip the 'if' token
    16931873
     
    16961876    def unset_values(self):
    16971877        """
    1698         Resets the user values of all symbols, as if Kconfig.load_config() or
    1699         Symbol.set_value() had never been called.
    1700         """
    1701         self._warn_for_no_prompt = False
     1878        Removes any user values from all symbols, as if Kconfig.load_config()
     1879        or Symbol.set_value() had never been called.
     1880        """
     1881        self._warn_no_prompt = False
    17021882        try:
    17031883            # set_value() already rejects undefined symbols, and they don't
     
    17101890                choice.unset_value()
    17111891        finally:
    1712             self._warn_for_no_prompt = True
     1892            self._warn_no_prompt = True
    17131893
    17141894    def enable_warnings(self):
    17151895        """
    1716         See Kconfig.__init__().
    1717         """
    1718         self._warnings_enabled = True
     1896        Do 'Kconfig.warn = True' instead. Maintained for backwards
     1897        compatibility.
     1898        """
     1899        self.warn = True
    17191900
    17201901    def disable_warnings(self):
    17211902        """
    1722         See Kconfig.__init__().
    1723         """
    1724         self._warnings_enabled = False
     1903        Do 'Kconfig.warn = False' instead. Maintained for backwards
     1904        compatibility.
     1905        """
     1906        self.warn = False
    17251907
    17261908    def enable_stderr_warnings(self):
    17271909        """
    1728         See Kconfig.__init__().
    1729         """
    1730         self._warn_to_stderr = True
     1910        Do 'Kconfig.warn_to_stderr = True' instead. Maintained for backwards
     1911        compatibility.
     1912        """
     1913        self.warn_to_stderr = True
    17311914
    17321915    def disable_stderr_warnings(self):
    17331916        """
    1734         See Kconfig.__init__().
    1735         """
    1736         self._warn_to_stderr = False
     1917        Do 'Kconfig.warn_to_stderr = False' instead. Maintained for backwards
     1918        compatibility.
     1919        """
     1920        self.warn_to_stderr = False
    17371921
    17381922    def enable_undef_warnings(self):
    17391923        """
    1740         Enables warnings for assignments to undefined symbols. Disabled by
    1741         default unless the KCONFIG_WARN_UNDEF_ASSIGN environment variable was
    1742         set to 'y' when the Kconfig instance was created.
    1743         """
    1744         self._warn_for_undef_assign = True
     1924        Do 'Kconfig.warn_assign_undef = True' instead. Maintained for backwards
     1925        compatibility.
     1926        """
     1927        self.warn_assign_undef = True
    17451928
    17461929    def disable_undef_warnings(self):
    17471930        """
    1748         See enable_undef_assign().
    1749         """
    1750         self._warn_for_undef_assign = False
     1931        Do 'Kconfig.warn_assign_undef = False' instead. Maintained for
     1932        backwards compatibility.
     1933        """
     1934        self.warn_assign_undef = False
    17511935
    17521936    def enable_override_warnings(self):
    17531937        """
    1754         Enables warnings for duplicated assignments in .config files that set
    1755         different values (e.g. CONFIG_FOO=m followed by CONFIG_FOO=y, where
    1756         the last value set is used).
    1757 
    1758         These warnings are enabled by default. Disabling them might be helpful
    1759         in certain cases when merging configurations.
    1760         """
    1761         self._warn_for_override = True
     1938        Do 'Kconfig.warn_assign_override = True' instead. Maintained for
     1939        backwards compatibility.
     1940        """
     1941        self.warn_assign_override = True
    17621942
    17631943    def disable_override_warnings(self):
    17641944        """
    1765         See enable_override_warnings().
    1766         """
    1767         self._warn_for_override = False
     1945        Do 'Kconfig.warn_assign_override = False' instead. Maintained for
     1946        backwards compatibility.
     1947        """
     1948        self.warn_assign_override = False
    17681949
    17691950    def enable_redun_warnings(self):
    17701951        """
    1771         Enables warnings for duplicated assignments in .config files that all
    1772         set the same value.
    1773 
    1774         These warnings are enabled by default. Disabling them might be helpful
    1775         in certain cases when merging configurations.
    1776         """
    1777         self._warn_for_redun_assign = True
     1952        Do 'Kconfig.warn_assign_redun = True' instead. Maintained for backwards
     1953        compatibility.
     1954        """
     1955        self.warn_assign_redun = True
    17781956
    17791957    def disable_redun_warnings(self):
    17801958        """
    1781         See enable_redun_warnings().
    1782         """
    1783         self._warn_for_redun_assign = False
     1959        Do 'Kconfig.warn_assign_redun = False' instead. Maintained for
     1960        backwards compatibility.
     1961        """
     1962        self.warn_assign_redun = False
    17841963
    17851964    def __repr__(self):
     
    17881967        evaluated on e.g. the interactive Python prompt.
    17891968        """
     1969        def status(flag):
     1970            return "enabled" if flag else "disabled"
     1971
    17901972        return "<{}>".format(", ".join((
    17911973            "configuration with {} symbols".format(len(self.syms)),
     
    17941976                'srctree "{}"'.format(self.srctree),
    17951977            'config symbol prefix "{}"'.format(self.config_prefix),
    1796             "warnings " +
    1797                 ("enabled" if self._warnings_enabled else "disabled"),
    1798             "printing of warnings to stderr " +
    1799                 ("enabled" if self._warn_to_stderr else "disabled"),
     1978            "warnings " + status(self.warn),
     1979            "printing of warnings to stderr " + status(self.warn_to_stderr),
    18001980            "undef. symbol assignment warnings " +
    1801                 ("enabled" if self._warn_for_undef_assign else "disabled"),
     1981                status(self.warn_assign_undef),
     1982            "overriding symbol assignment warnings " +
     1983                status(self.warn_assign_override),
    18021984            "redundant symbol assignment warnings " +
    1803                 ("enabled" if self._warn_for_redun_assign else "disabled")
     1985                status(self.warn_assign_redun)
    18041986        )))
    18051987
     
    18392021                               else "unset or blank"))
    18402022
    1841     def _enter_file(self, full_filename, rel_filename):
     2023    def _enter_file(self, filename):
    18422024        # Jumps to the beginning of a sourced Kconfig file, saving the previous
    18432025        # position and file object.
    18442026        #
    1845         # full_filename:
    1846         #   Actual path to the file.
    1847         #
    1848         # rel_filename:
    1849         #   File path with $srctree prefix stripped, stored in e.g.
    1850         #   self._filename (which makes it indirectly show up in
    1851         #   MenuNode.filename). Equals full_filename for absolute paths.
     2027        # filename:
     2028        #   Absolute path to file
     2029
     2030        # Path relative to $srctree, stored in e.g. self._filename
     2031        # (which makes it indirectly show up in MenuNode.filename). Equals
     2032        # 'filename' for absolute paths passed to 'source'.
     2033        if filename.startswith(self._srctree_prefix):
     2034            # Relative path (or a redundant absolute path to within $srctree,
     2035            # but it's probably fine to reduce those too)
     2036            rel_filename = filename[len(self._srctree_prefix):]
     2037        else:
     2038            # Absolute path
     2039            rel_filename = filename
    18522040
    18532041        self.kconfig_filenames.append(rel_filename)
     
    18842072                                      for name, linenr in self._include_path)))
    18852073
    1886         # Note: We already know that the file exists
    1887 
    18882074        try:
    1889             self._readline = self._open(full_filename, "r").readline
     2075            self._readline = self._open(filename, "r").readline
    18902076        except IOError as e:
     2077            # We already know that the file exists
    18912078            raise _KconfigIOError(
    1892                 e, "{}:{}: Could not open '{}' ({}: {})"
    1893                    .format(self._filename, self._linenr, full_filename,
     2079                e, "{}:{}: Could not open '{}' (in '{}') ({}: {})"
     2080                   .format(self._filename, self._linenr, filename,
     2081                           self._line.strip(),
    18942082                           errno.errorcode[e.errno], e.strerror))
    18952083
     
    19212109            return True
    19222110
    1923         # Note: readline() returns '' over and over at EOF, which we rely on
    1924         # for help texts at the end of files (see _line_after_help())
     2111        # readline() returns '' over and over at EOF, which we rely on for help
     2112        # texts at the end of files (see _line_after_help())
    19252113        line = self._readline()
    19262114        if not line:
     
    19332121            self._linenr += 1
    19342122
    1935         self._line = line  # Used for error reporting
    19362123        self._tokens = self._tokenize(line)
    19372124        # Initialize to 1 instead of 0 to factor out code from _parse_block()
     
    19552142            self._linenr += 1
    19562143
    1957         self._line = line
    19582144        self._tokens = self._tokenize(line)
    19592145        self._reuse_tokens = True
    19602146
     2147    def _write_if_changed(self, filename, contents):
     2148        # Writes 'contents' into 'filename', but only if it differs from the
     2149        # current contents of the file.
     2150        #
     2151        # Another variant would be write a temporary file on the same
     2152        # filesystem, compare the files, and rename() the temporary file if it
     2153        # differs, but it breaks stuff like write_config("/dev/null"), which is
     2154        # used out there to force evaluation-related warnings to be generated.
     2155        # This simple version is pretty failsafe and portable.
     2156
     2157        if not self._contents_eq(filename, contents):
     2158            with self._open(filename, "w") as f:
     2159                f.write(contents)
     2160
     2161    def _contents_eq(self, filename, contents):
     2162        # Returns True if the contents of 'filename' is 'contents' (a string),
     2163        # and False otherwise (including if 'filename' can't be opened/read)
     2164
     2165        try:
     2166            with self._open(filename, "r") as f:
     2167                # Robust re. things like encoding and line endings (mmap()
     2168                # trickery isn't)
     2169                return f.read(len(contents) + 1) == contents
     2170        except IOError:
     2171            # If the error here would prevent writing the file as well, we'll
     2172            # notice it later
     2173            return False
    19612174
    19622175    #
     
    20102223        # hotspot during parsing.
    20112224        #
    2012         # Note: It might be possible to rewrite this to 'yield' tokens instead,
    2013         # working across multiple lines. The 'option env' lookback thing below
    2014         # complicates things though.
     2225        # It might be possible to rewrite this to 'yield' tokens instead,
     2226        # working across multiple lines. Lookback and compatibility with old
     2227        # janky versions of the C tools complicate things though.
     2228
     2229        self._line = s  # Used for error reporting
    20152230
    20162231        # Initial token on the line
     
    22612476        return False
    22622477
    2263 
    22642478    #
    22652479    # Preprocessor logic
     
    25182732
    25192733        return ""
    2520 
    25212734
    25222735    #
     
    26232836                pattern = self._expect_str_and_eol()
    26242837
    2625                 # Check if the pattern is absolute and avoid stripping srctree
    2626                 # from it below in that case. We must do the check before
    2627                 # join()'ing, as srctree might be an absolute path.
    2628                 pattern_is_abs = isabs(pattern)
    2629 
    26302838                if t0 in _REL_SOURCE_TOKENS:
    26312839                    # Relative source
    26322840                    pattern = join(dirname(self._filename), pattern)
    26332841
    2634                 # Sort the glob results to ensure a consistent ordering of
    2635                 # Kconfig symbols, which indirectly ensures a consistent
    2636                 # ordering in e.g. .config files
    2637                 filenames = sorted(iglob(join(self.srctree, pattern)))
     2842                # - glob() doesn't support globbing relative to a directory, so
     2843                #   we need to prepend $srctree to 'pattern'. Use join()
     2844                #   instead of '+' so that an absolute path in 'pattern' is
     2845                #   preserved.
     2846                #
     2847                # - Sort the glob results to ensure a consistent ordering of
     2848                #   Kconfig symbols, which indirectly ensures a consistent
     2849                #   ordering in e.g. .config files
     2850                filenames = sorted(iglob(join(self._srctree_prefix, pattern)))
    26382851
    26392852                if not filenames and t0 in _OBL_SOURCE_TOKENS:
     
    26492862
    26502863                for filename in filenames:
    2651                     self._enter_file(
    2652                         filename,
    2653                         # Unless an absolute path is passed to *source, strip
    2654                         # the $srctree prefix from the filename. That way it
    2655                         # appears without a $srctree prefix in
    2656                         # MenuNode.filename, which is nice e.g. when generating
    2657                         # documentation.
    2658                         filename if pattern_is_abs else
    2659                             relpath(filename, self.srctree))
    2660 
     2864                    self._enter_file(filename)
    26612865                    prev = self._parse_block(None, parent, prev)
    2662 
    26632866                    self._leave_file()
    26642867
    26652868            elif t0 is end_token:
    2666                 # We have reached the end of the block. Terminate the final
    2667                 # node and return it.
     2869                # Reached the end of the block. Terminate the final node and
     2870                # return it.
    26682871
    26692872                if self._tokens[1] is not None:
     
    27602963            elif t0 is _T_MAINMENU:
    27612964                self.top_node.prompt = (self._expect_str_and_eol(), self.y)
    2762                 self.top_node.filename = self._filename
    2763                 self.top_node.linenr = self._linenr
    27642965
    27652966            else:
     
    29543155
    29553156    def _set_type(self, node, new_type):
    2956         # Note: UNKNOWN == 0, which is falsy
     3157        # UNKNOWN is falsy
    29573158        if node.item.orig_type and node.item.orig_type is not new_type:
    29583159            self._warn("{} defined with multiple types, {} will be used"
     
    32273428        for choice in self.unique_choices:
    32283429            choice._invalidate()
    3229 
    32303430
    32313431    #
     
    33263526        cur = node.list
    33273527        while cur:
    3328             cur.dep = dep = self._make_and(cur.dep, basedep)
    3329 
    3330             # Propagate dependencies to prompt
    3331             if cur.prompt:
    3332                 cur.prompt = (cur.prompt[0],
    3333                               self._make_and(cur.prompt[1], dep))
     3528            dep = cur.dep = self._make_and(cur.dep, basedep)
    33343529
    33353530            if cur.item.__class__ in _SYMBOL_CHOICE:
    3336                 # Propagate 'visible if' dependencies to the prompt
     3531                # Propagate 'visible if' and dependencies to the prompt
    33373532                if cur.prompt:
    33383533                    cur.prompt = (cur.prompt[0],
    3339                                   self._make_and(cur.prompt[1], visible_if))
     3534                                  self._make_and(
     3535                                      cur.prompt[1],
     3536                                      self._make_and(visible_if, dep)))
    33403537
    33413538                # Propagate dependencies to defaults
     
    33593556                                   for target, cond in cur.implies]
    33603557
     3558            elif cur.prompt:  # Not a symbol/choice
     3559                # Propagate dependencies to the prompt. 'visible if' is only
     3560                # propagated to symbols/choices.
     3561                cur.prompt = (cur.prompt[0],
     3562                              self._make_and(cur.prompt[1], dep))
    33613563
    33623564            cur = cur.next
     
    33943596                target.weak_rev_dep,
    33953597                self._make_and(sym, cond))
    3396 
    33973598
    33983599    #
     
    35713772        #   deprecated on Python 3, so play it future-safe.
    35723773        #
    3573         #   A simpler solution would be to use io.open(), which defaults to
    3574         #   universal newlines on both Python 2 and 3 (and is an alias for
    3575         #   open() on Python 3), but it's appreciably slower on Python 2:
     3774        #   io.open() defaults to universal newlines on Python 2 (and is an
     3775        #   alias for open() on Python 3), but it returns 'unicode' strings and
     3776        #   slows things down:
    35763777        #
    35773778        #     Parsing x86 Kconfigs on Python 2
     
    36373838
    36383839                msg = "undefined symbol {}:".format(sym.name)
    3639 
    36403840                for node in self.node_iter():
    36413841                    if sym in node.referenced:
    36423842                        msg += "\n\n- Referenced at {}:{}:\n\n{}" \
    36433843                               .format(node.filename, node.linenr, node)
    3644 
    36453844                self._warn(msg)
    36463845
     
    36483847        # For printing general warnings
    36493848
    3650         if self._warnings_enabled:
    3651             msg = "warning: " + msg
    3652             if filename is not None:
    3653                 msg = "{}:{}: {}".format(filename, linenr, msg)
    3654 
    3655             self.warnings.append(msg)
    3656             if self._warn_to_stderr:
    3657                 sys.stderr.write(msg + "\n")
    3658 
    3659     def _warn_override(self, msg, filename, linenr):
    3660         # See the class documentation
    3661 
    3662         if self._warn_for_override:
    3663             self._warn(msg, filename, linenr)
    3664 
    3665     def _warn_redun_assign(self, msg, filename, linenr):
    3666         # See the class documentation
    3667 
    3668         if self._warn_for_redun_assign:
    3669             self._warn(msg, filename, linenr)
     3849        if not self.warn:
     3850            return
     3851
     3852        msg = "warning: " + msg
     3853        if filename is not None:
     3854            msg = "{}:{}: {}".format(filename, linenr, msg)
     3855
     3856        self.warnings.append(msg)
     3857        if self.warn_to_stderr:
     3858            sys.stderr.write(msg + "\n")
    36703859
    36713860
     
    38294018      List of (low, high, cond) tuples for the symbol's 'range' properties. For
    38304019      example, 'range 1 2 if A' is represented as (1, 2, A). If there is no
    3831       condition, 'cond' is self.config.y.
     4020      condition, 'cond' is self.kconfig.y.
    38324021
    38334022      Note that 'depends on' and parent dependencies are propagated to 'range'
     
    38504039
    38514040    direct_dep:
    3852       The 'depends on' dependencies. If a symbol is defined in multiple
    3853       locations, the dependencies at each location are ORed together.
    3854 
    3855       Internally, this is used to implement 'imply', which only applies if the
    3856       implied symbol has expr_value(self.direct_dep) != 0. 'depends on' and
    3857       parent dependencies are automatically propagated to the conditions of
    3858       properties, so normally it's redundant to check the direct dependencies.
     4041      The direct ('depends on') dependencies for the symbol, or self.kconfig.y
     4042      if there are no direct dependencies.
     4043
     4044      This attribute includes any dependencies from surrounding menus and if's.
     4045      Those get propagated to the direct dependencies, and the resulting direct
     4046      dependencies in turn get propagated to the conditions of all properties.
     4047
     4048      If the symbol is defined in multiple locations, the dependencies from the
     4049      different locations get ORed together.
    38594050
    38604051    referenced:
     
    38624053      property conditions of the symbol.
    38634054
    3864       Also includes dependencies inherited from surrounding menus and if's.
     4055      Also includes dependencies from surrounding menus and if's, because those
     4056      get propagated to the symbol (see the 'Intro to symbol values' section in
     4057      the module docstring).
     4058
    38654059      Choices appear in the dependencies of choice symbols.
     4060
     4061      For the following definitions, only B and not C appears in A's
     4062      'referenced'. To get transitive references, you'll have to recursively
     4063      expand 'references' until no new items appear.
     4064
     4065        config A
     4066                bool
     4067                depends on B
     4068
     4069        config B
     4070                bool
     4071                depends on C
     4072
     4073        config C
     4074                bool
     4075
     4076      See the Symbol.direct_dep attribute if you're only interested in the
     4077      direct dependencies of the symbol (its 'depends on'). You can extract the
     4078      symbols in it with the global expr_items() function.
    38664079
    38674080    env_var:
     
    41794392        See the class documentation.
    41804393        """
    4181         # Note: _write_to_conf is determined when the value is calculated. This
    4182         # is a hidden function call due to property magic.
     4394        # _write_to_conf is determined when the value is calculated. This is a
     4395        # hidden function call due to property magic.
    41834396        val = self.str_value
    41844397        if not self._write_to_conf:
     
    42874500    def unset_value(self):
    42884501        """
    4289         Resets the user value of the symbol, as if the symbol had never gotten
    4290         a user value via Kconfig.load_config() or Symbol.set_value().
     4502        Removes any user value from the symbol, as if the symbol had never
     4503        gotten a user value via Kconfig.load_config() or Symbol.set_value().
    42914504        """
    42924505        if self.user_value is not None:
     
    43594572    def __str__(self):
    43604573        """
    4361         Returns a string representation of the symbol when it is printed,
    4362         matching the Kconfig format, with parent dependencies propagated.
     4574        Returns a string representation of the symbol when it is printed.
     4575        Matches the Kconfig format, with any parent dependencies propagated to
     4576        the 'depends on' condition.
    43634577
    43644578        The string is constructed by joining the strings returned by
     
    45274741                return
    45284742
    4529         if self.kconfig._warn_for_no_prompt:
     4743        if self.kconfig._warn_no_prompt:
    45304744            self.kconfig._warn(_name_and_loc(self) + " has no prompt, meaning "
    45314745                               "user values have no effect on it")
     
    47224936      List of (symbol, cond) tuples for the choice's 'defaults' properties. For
    47234937      example, 'default A if B && C' is represented as (A, (AND, B, C)). If
    4724       there is no condition, 'cond' is self.config.y.
     4938      there is no condition, 'cond' is self.kconfig.y.
    47254939
    47264940      Note that 'depends on' and parent dependencies are propagated to
     
    47344948      conditions of the choice.
    47354949
    4736       Also includes dependencies inherited from surrounding menus and if's.
     4950      Also includes dependencies from surrounding menus and if's, because those
     4951      get propagated to the choice (see the 'Intro to symbol values' section in
     4952      the module docstring).
    47374953
    47384954    is_optional:
     
    49335149    def __str__(self):
    49345150        """
    4935         Returns a string representation of the choice when it is printed,
    4936         matching the Kconfig format (though without the contained choice
    4937         symbols).
     5151        Returns a string representation of the choice when it is printed.
     5152        Matches the Kconfig format (though without the contained choice
     5153        symbols), with any parent dependencies propagated to the 'depends on'
     5154        condition.
    49385155
    49395156        The returned string does not end in a newline.
     
    51145331      Like MenuNode.defaults, for ranges.
    51155332
     5333    orig_prompt:
     5334    orig_defaults:
     5335    orig_selects:
     5336    orig_implies:
     5337    orig_ranges:
     5338      These work the like the corresponding attributes without orig_*, but omit
     5339      any dependencies propagated from 'depends on' and surrounding 'if's (the
     5340      direct dependencies, stored in MenuNode.dep).
     5341
     5342      One use for this is generating less cluttered documentation, by only
     5343      showing the direct dependencies in one place.
     5344
    51165345    help:
    51175346      The help text for the menu node for Symbols and Choices. None if there is
     
    51255354
    51265355    dep:
    5127       The 'depends on' dependencies for the menu node, or self.kconfig.y if
    5128       there are no dependencies. Parent dependencies are propagated to this
    5129       attribute, and this attribute is then in turn propagated to the
    5130       properties of symbols and choices.
     5356      The direct ('depends on') dependencies for the menu node, or
     5357      self.kconfig.y if there are no direct dependencies.
     5358
     5359      This attribute includes any dependencies from surrounding menus and if's.
     5360      Those get propagated to the direct dependencies, and the resulting direct
     5361      dependencies in turn get propagated to the conditions of all properties.
    51315362
    51325363      If a symbol or choice is defined in multiple locations, only the
     
    52115442
    52125443    @property
     5444    def orig_prompt(self):
     5445        """
     5446        See the class documentation.
     5447        """
     5448        if not self.prompt:
     5449            return None
     5450        return (self.prompt[0], self._strip_dep(self.prompt[1]))
     5451
     5452    @property
     5453    def orig_defaults(self):
     5454        """
     5455        See the class documentation.
     5456        """
     5457        return [(default, self._strip_dep(cond))
     5458                for default, cond in self.defaults]
     5459
     5460    @property
     5461    def orig_selects(self):
     5462        """
     5463        See the class documentation.
     5464        """
     5465        return [(select, self._strip_dep(cond))
     5466                for select, cond in self.selects]
     5467
     5468    @property
     5469    def orig_implies(self):
     5470        """
     5471        See the class documentation.
     5472        """
     5473        return [(imply, self._strip_dep(cond))
     5474                for imply, cond in self.implies]
     5475
     5476    @property
     5477    def orig_ranges(self):
     5478        """
     5479        See the class documentation.
     5480        """
     5481        return [(low, high, self._strip_dep(cond))
     5482                for low, high, cond in self.ranges]
     5483
     5484    @property
    52135485    def referenced(self):
    52145486        """
     
    52955567    def __str__(self):
    52965568        """
    5297         Returns a string representation of the menu node, matching the Kconfig
    5298         format.
     5569        Returns a string representation of the menu node. Matches the Kconfig
     5570        format, with any parent dependencies propagated to the 'depends on'
     5571        condition.
    52995572
    53005573        The output could (almost) be fed back into a Kconfig parser to redefine
     
    53505623            lines = ["choice " + sc.name if sc.name else "choice"]
    53515624
    5352         if sc.orig_type:  # != UNKNOWN
     5625        if sc.orig_type and not self.prompt:  # sc.orig_type != UNKNOWN
     5626            # If there's a prompt, we'll use the '<type> "prompt"' shorthand
     5627            # instead
    53535628            indent_add(TYPE_TO_STR[sc.orig_type])
    53545629
    53555630        if self.prompt:
    5356             indent_add_cond(
    5357                 'prompt "{}"'.format(escape(self.prompt[0])),
    5358                 self.prompt[1])
     5631            if sc.orig_type:
     5632                prefix = TYPE_TO_STR[sc.orig_type]
     5633            else:
     5634                # Symbol defined without a type (which generates a warning)
     5635                prefix = "prompt"
     5636
     5637            indent_add_cond(prefix + ' "{}"'.format(escape(self.prompt[0])),
     5638                            self.orig_prompt[1])
    53595639
    53605640        if sc.__class__ is Symbol:
     
    53715651                indent_add("option modules")
    53725652
    5373             for low, high, cond in self.ranges:
     5653            for low, high, cond in self.orig_ranges:
    53745654                indent_add_cond(
    53755655                    "range {} {}".format(sc_expr_str_fn(low),
     
    53775657                    cond)
    53785658
    5379         for default, cond in self.defaults:
     5659        for default, cond in self.orig_defaults:
    53805660            indent_add_cond("default " + expr_str(default, sc_expr_str_fn),
    53815661                            cond)
     
    53855665
    53865666        if sc.__class__ is Symbol:
    5387             for select, cond in self.selects:
     5667            for select, cond in self.orig_selects:
    53885668                indent_add_cond("select " + sc_expr_str_fn(select), cond)
    53895669
    5390             for imply, cond in self.implies:
     5670            for imply, cond in self.orig_implies:
    53915671                indent_add_cond("imply " + sc_expr_str_fn(imply), cond)
    53925672
     
    54015681        return "\n".join(lines)
    54025682
     5683    def _strip_dep(self, expr):
     5684        # Helper function for removing MenuNode.dep from 'expr'. Uses two
     5685        # pieces of internal knowledge: (1) Expressions are reused rather than
     5686        # copied, and (2) the direct dependencies always appear at the end.
     5687
     5688        # ... if dep -> ... if y
     5689        if self.dep is expr:
     5690            return self.kconfig.y
     5691
     5692        # (AND, X, dep) -> X
     5693        if expr.__class__ is tuple and expr[0] is AND and expr[2] is self.dep:
     5694            return expr[1]
     5695
     5696        return expr
     5697
    54035698
    54045699class Variable(object):
     
    54195714      KconfigError if the expansion seems to be stuck in a loop.
    54205715
    5421       Note: Accessing this field is the same as calling expanded_value_w_args()
    5422       with no arguments. I hadn't considered function arguments when adding it.
    5423       It is retained for backwards compatibility though.
     5716      Accessing this field is the same as calling expanded_value_w_args() with
     5717      no arguments. I hadn't considered function arguments when adding it. It
     5718      is retained for backwards compatibility though.
    54245719
    54255720    is_recursive:
     
    54585753
    54595754class KconfigError(Exception):
    5460     "Exception raised for Kconfig-related errors"
     5755    """
     5756    Exception raised for Kconfig-related errors.
     5757
     5758    KconfigError and KconfigSyntaxError are the same class. The
     5759    KconfigSyntaxError alias is only maintained for backwards compatibility.
     5760    """
    54615761
    54625762KconfigSyntaxError = KconfigError  # Backwards compatibility
     
    55535853    """
    55545854    if sc.__class__ is Symbol:
    5555         return '"{}"'.format(escape(sc.name)) if sc.is_constant else sc.name
     5855        if sc.is_constant and sc.name not in ("n", "m", "y"):
     5856            return '"{}"'.format(escape(sc.name))
     5857        return sc.name
    55565858
    55575859    # Choice
     
    57216023    .config file to load/save) if it is set, and ".config" otherwise.
    57226024
    5723     Note: Calling load_config() with filename=None might give the behavior you
    5724     want, without having to use this function.
     6025    Calling load_config() with filename=None might give the behavior you want,
     6026    without having to use this function.
    57256027    """
    57266028    return os.environ.get("KCONFIG_CONFIG", ".config")
     
    57346036
    57356037    Disables warnings for duplicated assignments within configuration files for
    5736     the duration of the call (disable_override_warnings() +
    5737     disable_redun_warnings()), and enables them at the end. The
     6038    the duration of the call (kconf.warn_assign_override/warn_assign_redun = False),
     6039    and restores the previous warning settings at the end. The
    57386040    KCONFIG_ALLCONFIG configuration file is expected to override symbols.
    57396041
     
    57496051      "allno.config", etc.
    57506052    """
     6053    allconfig = os.environ.get("KCONFIG_ALLCONFIG")
     6054    if allconfig is None:
     6055        return
     6056
    57516057    def std_msg(e):
    57526058        # "Upcasts" a _KconfigIOError to an IOError, removing the custom
     
    57546060        return IOError(e.errno, e.strerror, e.filename)
    57556061
    5756     kconf.disable_override_warnings()
    5757     kconf.disable_redun_warnings()
    5758 
    5759     allconfig = os.environ.get("KCONFIG_ALLCONFIG")
    5760     if allconfig is not None:
    5761         if allconfig in ("", "1"):
     6062    old_warn_assign_override = kconf.warn_assign_override
     6063    old_warn_assign_redun = kconf.warn_assign_redun
     6064    kconf.warn_assign_override = kconf.warn_assign_redun = False
     6065
     6066    if allconfig in ("", "1"):
     6067        try:
     6068            print(kconf.load_config(filename, False))
     6069        except IOError as e1:
    57626070            try:
    5763                 kconf.load_config(filename, False)
    5764             except IOError as e1:
    5765                 try:
    5766                     kconf.load_config("all.config", False)
    5767                 except IOError as e2:
    5768                     sys.exit("error: KCONFIG_ALLCONFIG is set, but neither {} "
    5769                              "nor all.config could be opened: {}, {}"
    5770                              .format(filename, std_msg(e1), std_msg(e2)))
    5771         else:
    5772             try:
    5773                 kconf.load_config(allconfig, False)
    5774             except IOError as e:
    5775                 sys.exit("error: KCONFIG_ALLCONFIG is set to '{}', which "
    5776                          "could not be opened: {}"
    5777                          .format(allconfig, std_msg(e)))
    5778 
    5779     # API wart: It would be nice if there was a way to query and/or push/pop
    5780     # warning settings
    5781     kconf.enable_override_warnings()
    5782     kconf.enable_redun_warnings()
     6071                print(kconf.load_config("all.config", False))
     6072            except IOError as e2:
     6073                sys.exit("error: KCONFIG_ALLCONFIG is set, but neither {} "
     6074                         "nor all.config could be opened: {}, {}"
     6075                         .format(filename, std_msg(e1), std_msg(e2)))
     6076    else:
     6077        try:
     6078            print(kconf.load_config(allconfig, False))
     6079        except IOError as e:
     6080            sys.exit("error: KCONFIG_ALLCONFIG is set to '{}', which "
     6081                     "could not be opened: {}"
     6082                     .format(allconfig, std_msg(e)))
     6083
     6084    kconf.warn_assign_override = old_warn_assign_override
     6085    kconf.warn_assign_redun = old_warn_assign_redun
    57836086
    57846087
     
    58806183
    58816184
    5882 def _touch_dep_file(sym_name):
     6185def _touch_dep_file(path, sym_name):
    58836186    # If sym_name is MY_SYM_NAME, touches my/sym/name.h. See the sync_deps()
    58846187    # docstring.
    58856188
    5886     sym_path = sym_name.lower().replace("_", os.sep) + ".h"
     6189    sym_path = path + os.sep + sym_name.lower().replace("_", os.sep) + ".h"
    58876190    sym_path_dir = dirname(sym_path)
    5888     if sym_path_dir and not exists(sym_path_dir):
     6191    if not exists(sym_path_dir):
    58896192        os.makedirs(sym_path_dir, 0o755)
    58906193
     
    58976200    # See write_config()
    58986201
    5899     dirname, basename = split(path)
    5900     backup = join(dirname,
    5901                   basename + ".old" if basename.startswith(".")
    5902                       else "." + basename + ".old")
    5903 
    5904     # os.replace() would be nice here, but it's Python 3 (3.3+) only
     6202    def copy(src, dst):
     6203        # Import as needed, to save some startup time
     6204        import shutil
     6205        shutil.copyfile(src, dst)
     6206
     6207    if islink(path):
     6208        # Preserve symlinks
     6209        copy_fn = copy
     6210    elif hasattr(os, "replace"):
     6211        # Python 3 (3.3+) only. Best choice when available, because it
     6212        # removes <filename>.old on both *nix and Windows.
     6213        copy_fn = os.replace
     6214    elif os.name == "posix":
     6215        # Removes <filename>.old on POSIX systems
     6216        copy_fn = os.rename
     6217    else:
     6218        # Fall back on copying
     6219        copy_fn = copy
     6220
    59056221    try:
    5906         # Use copyfile() if 'path' is a symlink. The intention is probably to
    5907         # overwrite the target in that case.
    5908         if os.name == "posix" and not islink(path):
    5909             # Will remove .<filename>.old if it already exists on POSIX
    5910             # systems
    5911             os.rename(path, backup)
    5912         else:
    5913             # Only import as needed, to save some startup time
    5914             import shutil
    5915             shutil.copyfile(path, backup)
    5916     except:
    5917         # Ignore errors from 'filename' missing as well as other errors. The
    5918         # backup file is more of a nice-to-have, and not worth erroring out
    5919         # over e.g. if .<filename>.old happens to be a directory.
     6222        copy_fn(path, path + ".old")
     6223    except Exception:
     6224        # Ignore errors from 'path' missing as well as other errors.
     6225        # <filename>.old file is usually more of a nice-to-have, and not worth
     6226        # erroring out over e.g. if <filename>.old happens to be a directory or
     6227        # <filename> is something like /dev/null.
    59206228        pass
    5921 
    5922 
    5923 def _decoding_error(e, filename, macro_linenr=None):
    5924     # Gives the filename and context for UnicodeDecodeError's, which are a pain
    5925     # to debug otherwise. 'e' is the UnicodeDecodeError object.
    5926     #
    5927     # If the decoding error is for the output of a $(shell,...) command,
    5928     # macro_linenr holds the line number where it was run (the exact line
    5929     # number isn't available for decoding errors in files).
    5930 
    5931     raise KconfigError(
    5932         "\n"
    5933         "Malformed {} in {}\n"
    5934         "Context: {}\n"
    5935         "Problematic data: {}\n"
    5936         "Reason: {}".format(
    5937             e.encoding,
    5938             "'{}'".format(filename) if macro_linenr is None else
    5939                 "output from macro at {}:{}".format(filename, macro_linenr),
    5940             e.object[max(e.start - 40, 0):e.end + 40],
    5941             e.object[e.start:e.end],
    5942             e.reason))
    59436229
    59446230
     
    59956281    # at node2.dep.
    59966282
    5997     # If node2 has no prompt, use its menu node dependencies instead
    59986283    return _expr_depends_on(node2.prompt[1] if node2.prompt else node2.dep,
    59996284                            node1.item)
     
    62416526
    62426527
     6528def _decoding_error(e, filename, macro_linenr=None):
     6529    # Gives the filename and context for UnicodeDecodeError's, which are a pain
     6530    # to debug otherwise. 'e' is the UnicodeDecodeError object.
     6531    #
     6532    # If the decoding error is for the output of a $(shell,...) command,
     6533    # macro_linenr holds the line number where it was run (the exact line
     6534    # number isn't available for decoding errors in files).
     6535
     6536    raise KconfigError(
     6537        "\n"
     6538        "Malformed {} in {}\n"
     6539        "Context: {}\n"
     6540        "Problematic data: {}\n"
     6541        "Reason: {}".format(
     6542            e.encoding,
     6543            "'{}'".format(filename) if macro_linenr is None else
     6544                "output from macro at {}:{}".format(filename, macro_linenr),
     6545            e.object[max(e.start - 40, 0):e.end + 40],
     6546            e.object[e.start:e.end],
     6547            e.reason))
     6548
     6549
     6550def _warn_verbose_deprecated(fn_name):
     6551    sys.stderr.write(
     6552        "Deprecation warning: {0}()'s 'verbose' argument has no effect. Since "
     6553        "Kconfiglib 12.0.0, the message is returned from {0}() instead, "
     6554        "and is always generated. Do e.g. print(kconf.{0}()) if you want to "
     6555        "want to show a message like \"Loaded configuration '.config'\" on "
     6556        "stdout. The old API required ugly hacks to reuse messages in "
     6557        "configuration interfaces.\n".format(fn_name))
     6558
     6559
    62436560# Predefined preprocessor functions
    62446561
     
    63336650    _UNAME_RELEASE = platform.uname()[2]
    63346651
    6335 # Note: The token and type constants below are safe to test with 'is', which is
    6336 # a bit faster (~30% faster on my machine, and a few % faster for total parsing
     6652# The token and type constants below are safe to test with 'is', which is a bit
     6653# faster (~30% faster on my machine, and a few % faster for total parsing
    63376654# time), even without assuming Python's small integer optimization (which
    63386655# caches small integer objects). The constants end up pointing to unique
     
    66326949# '$' is included to detect preprocessor variable assignments with macro
    66336950# expansions in the left-hand side.
    6634 _command_match = _re_match(r"\s*([$A-Za-z0-9_-]+)\s*")
     6951_command_match = _re_match(r"\s*([A-Za-z0-9_$-]+)\s*")
    66356952
    66366953# An identifier/keyword after the first token. Also eats trailing whitespace.
    66376954# '$' is included to detect identifiers containing macro expansions.
    6638 _id_keyword_match = _re_match(r"([$A-Za-z0-9_/.-]+)\s*")
     6955_id_keyword_match = _re_match(r"([A-Za-z0-9_$/.-]+)\s*")
    66396956
    66406957# A fragment in the left-hand side of a preprocessor variable assignment. These
Note: See TracChangeset for help on using the changeset viewer.