5 |
5 |
6 import configparser |
6 import configparser |
7 import os |
7 import os |
8 import re |
8 import re |
9 |
9 |
|
10 from coverage import env |
10 from coverage.exceptions import ConfigError |
11 from coverage.exceptions import ConfigError |
11 from coverage.misc import import_third_party, substitute_variables |
12 from coverage.misc import import_third_party, substitute_variables |
12 |
13 |
13 # TOML support is an install-time extra option. (Import typing is here because |
14 |
14 # import_third_party will unload any module that wasn't already imported. |
15 if env.PYVERSION >= (3, 11): |
15 # tomli imports typing, and if we unload it, later it's imported again, and on |
16 import tomllib # pylint: disable=import-error |
16 # Python 3.6, this causes infinite recursion.) |
17 else: |
17 import typing # pylint: disable=unused-import, wrong-import-order |
18 # TOML support on Python 3.10 and below is an install-time extra option. |
18 tomli = import_third_party("tomli") |
19 # (Import typing is here because import_third_party will unload any module |
|
20 # that wasn't already imported. tomli imports typing, and if we unload it, |
|
21 # later it's imported again, and on Python 3.6, this causes infinite |
|
22 # recursion.) |
|
23 import typing # pylint: disable=unused-import |
|
24 tomllib = import_third_party("tomli") |
19 |
25 |
20 |
26 |
21 class TomlDecodeError(Exception): |
27 class TomlDecodeError(Exception): |
22 """An exception class that exists even when toml isn't installed.""" |
28 """An exception class that exists even when toml isn't installed.""" |
23 pass |
29 pass |
43 try: |
49 try: |
44 with open(filename, encoding='utf-8') as fp: |
50 with open(filename, encoding='utf-8') as fp: |
45 toml_text = fp.read() |
51 toml_text = fp.read() |
46 except OSError: |
52 except OSError: |
47 return [] |
53 return [] |
48 if tomli is not None: |
54 if tomllib is not None: |
49 toml_text = substitute_variables(toml_text, os.environ) |
55 toml_text = substitute_variables(toml_text, os.environ) |
50 try: |
56 try: |
51 self.data = tomli.loads(toml_text) |
57 self.data = tomllib.loads(toml_text) |
52 except tomli.TOMLDecodeError as err: |
58 except tomllib.TOMLDecodeError as err: |
53 raise TomlDecodeError(str(err)) from err |
59 raise TomlDecodeError(str(err)) from err |
54 return [filename] |
60 return [filename] |
55 else: |
61 else: |
56 has_toml = re.search(r"^\[tool\.coverage\.", toml_text, flags=re.MULTILINE) |
62 has_toml = re.search(r"^\[tool\.coverage\.", toml_text, flags=re.MULTILINE) |
57 if self.our_file or has_toml: |
63 if self.our_file or has_toml: |