--- a/eric7/DebugClients/Python/coverage/tomlconfig.py Fri Nov 19 19:28:47 2021 +0100 +++ b/eric7/DebugClients/Python/coverage/tomlconfig.py Sat Nov 20 16:47:38 2021 +0100 @@ -3,19 +3,19 @@ """TOML configuration support for coverage.py""" -import io +import configparser import os import re -from coverage import env -from coverage.backward import configparser, path_types -from coverage.misc import CoverageException, substitute_variables +from coverage.exceptions import CoverageException +from coverage.misc import import_third_party, substitute_variables -# TOML support is an install-time extra option. -try: - import toml -except ImportError: # pragma: not covered - toml = None +# TOML support is an install-time extra option. (Import typing is here because +# import_third_party will unload any module that wasn't already imported. +# tomli imports typing, and if we unload it, later it's imported again, and on +# Python 3.6, this causes infinite recursion.) +import typing # pylint: disable=unused-import, wrong-import-order +tomli = import_third_party("tomli") class TomlDecodeError(Exception): @@ -37,22 +37,20 @@ def read(self, filenames): # RawConfigParser takes a filename or list of filenames, but we only # ever call this with a single filename. - assert isinstance(filenames, path_types) - filename = filenames - if env.PYVERSION >= (3, 6): - filename = os.fspath(filename) + assert isinstance(filenames, (bytes, str, os.PathLike)) + filename = os.fspath(filenames) try: - with io.open(filename, encoding='utf-8') as fp: + with open(filename, encoding='utf-8') as fp: toml_text = fp.read() - except IOError: + except OSError: return [] - if toml: + if tomli is not None: toml_text = substitute_variables(toml_text, os.environ) try: - self.data = toml.loads(toml_text) - except toml.TomlDecodeError as err: - raise TomlDecodeError(*err.args) + self.data = tomli.loads(toml_text) + except tomli.TOMLDecodeError as err: + raise TomlDecodeError(str(err)) from err return [filename] else: has_toml = re.search(r"^\[tool\.coverage\.", toml_text, flags=re.MULTILINE) @@ -98,8 +96,8 @@ raise configparser.NoSectionError(section) try: return name, data[option] - except KeyError: - raise configparser.NoOptionError(option, name) + except KeyError as exc: + raise configparser.NoOptionError(option, name) from exc def has_option(self, section, option): _, data = self._get_section(section) @@ -150,9 +148,7 @@ try: re.compile(value) except re.error as e: - raise CoverageException( - "Invalid [%s].%s value %r: %s" % (name, option, value, e) - ) + raise CoverageException(f"Invalid [{name}].{option} value {value!r}: {e}") from e return values def getint(self, section, option):