Skip to content

Commit 072c3bb

Browse files
sacsarjendrikseipp
andauthored
Swap in tomllib/tomli for toml. (#340)
* Swap tomllib for toml. Fixes #339 -- the toml package does not support heterogenous arrays, which are now allowed in the toml spec. This commit swaps in tomllib from the standard library for Python >= 3.11 and its backport tomli for older versions. --------- Co-authored-by: Jendrik Seipp <[email protected]>
1 parent b6fae71 commit 072c3bb

File tree

5 files changed

+62
-9
lines changed

5 files changed

+62
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ vulture.egg-info/
1010
.pytest_cache/
1111
.tox/
1212
.venv/
13+
.vscode/

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# next (unreleased)
2+
* Switch to tomllib/tomli to support heterogeneous arrays (Sebastian Csar, #340).
3+
14
# 2.10 (2023-10-06)
25

36
* Drop support for Python 3.7 (Jendrik Seipp, #323).

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def find_version(*parts):
4747
"Programming Language :: Python :: Implementation :: PyPy",
4848
"Topic :: Software Development :: Quality Assurance",
4949
],
50-
install_requires=["toml"],
50+
install_requires=["tomli >= 1.1.0; python_version < '3.11'"],
5151
entry_points={"console_scripts": ["vulture = vulture.core:main"]},
5252
python_requires=">=3.8",
5353
packages=setuptools.find_packages(exclude=["tests"]),

tests/test_config.py

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Unit tests for config file and CLI argument parsing.
33
"""
44

5-
from io import StringIO
5+
from io import BytesIO
66
from textwrap import dedent
77

88
import pytest
@@ -17,6 +17,13 @@
1717
)
1818

1919

20+
def get_toml_bytes(toml_str: str) -> BytesIO:
21+
"""
22+
Wrap a string in BytesIO to play the role of the incoming config stream.
23+
"""
24+
return BytesIO(bytes(toml_str, "utf-8"))
25+
26+
2027
def test_cli_args():
2128
"""
2229
Ensure that CLI arguments are converted to a config object.
@@ -62,9 +69,48 @@ def test_toml_config():
6269
sort_by_size=True,
6370
verbose=True,
6471
)
65-
data = StringIO(
72+
data = get_toml_bytes(
73+
dedent(
74+
"""\
75+
[tool.vulture]
76+
exclude = ["file*.py", "dir/"]
77+
ignore_decorators = ["deco1", "deco2"]
78+
ignore_names = ["name1", "name2"]
79+
make_whitelist = true
80+
min_confidence = 10
81+
sort_by_size = true
82+
verbose = true
83+
paths = ["path1", "path2"]
84+
"""
85+
)
86+
)
87+
result = _parse_toml(data)
88+
assert isinstance(result, dict)
89+
assert result == expected
90+
91+
92+
def test_toml_config_with_heterogenous_array():
93+
"""
94+
Ensure parsing of TOML files results in a valid config object, even if some
95+
other part of the file contains an array of mixed types.
96+
"""
97+
expected = dict(
98+
paths=["path1", "path2"],
99+
exclude=["file*.py", "dir/"],
100+
ignore_decorators=["deco1", "deco2"],
101+
ignore_names=["name1", "name2"],
102+
make_whitelist=True,
103+
min_confidence=10,
104+
sort_by_size=True,
105+
verbose=True,
106+
)
107+
data = get_toml_bytes(
66108
dedent(
67109
"""\
110+
[tool.foo]
111+
# comment for good measure
112+
problem_array = [{a = 1}, [2,3,4], "foo"]
113+
68114
[tool.vulture]
69115
exclude = ["file*.py", "dir/"]
70116
ignore_decorators = ["deco1", "deco2"]
@@ -87,7 +133,7 @@ def test_config_merging():
87133
If we have both CLI args and a ``pyproject.toml`` file, the CLI args should
88134
have precedence.
89135
"""
90-
toml = StringIO(
136+
toml = get_toml_bytes(
91137
dedent(
92138
"""\
93139
[tool.vulture]
@@ -131,7 +177,7 @@ def test_config_merging_missing():
131177
If we have set a boolean value in the TOML file, but not on the CLI, we
132178
want the TOML value to be taken.
133179
"""
134-
toml = StringIO(
180+
toml = get_toml_bytes(
135181
dedent(
136182
"""\
137183
[tool.vulture]
@@ -153,7 +199,7 @@ def test_config_merging_toml_paths_only():
153199
If we have paths in the TOML but not on the CLI, the TOML paths should be
154200
used.
155201
"""
156-
toml = StringIO(
202+
toml = get_toml_bytes(
157203
dedent(
158204
"""\
159205
[tool.vulture]

vulture/config.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
import argparse
66
import pathlib
77

8-
import toml
8+
try:
9+
import tomllib
10+
except ModuleNotFoundError:
11+
import tomli as tomllib
912

1013
from .version import __version__
1114

@@ -76,7 +79,7 @@ def _parse_toml(infile):
7679
verbose = true
7780
paths = ["path1", "path2"]
7881
"""
79-
data = toml.load(infile)
82+
data = tomllib.load(infile)
8083
settings = data.get("tool", {}).get("vulture", {})
8184
_check_input_config(settings)
8285
return settings
@@ -194,7 +197,7 @@ def make_config(argv=None, tomlfile=None):
194197
else:
195198
toml_path = pathlib.Path("pyproject.toml").resolve()
196199
if toml_path.is_file():
197-
with open(toml_path) as fconfig:
200+
with open(toml_path, "rb") as fconfig:
198201
config = _parse_toml(fconfig)
199202
detected_toml_path = str(toml_path)
200203
else:

0 commit comments

Comments
 (0)