Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swap in tomllib/tomli for toml. #340

Merged
merged 4 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ vulture.egg-info/
.pytest_cache/
.tox/
.venv/
.vscode/
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 2.11 (2023-11-13)
sacsar marked this conversation as resolved.
Show resolved Hide resolved
* Switch to tomllib/tomli to support heterogenous arrays. (Sebastian Csar, #340)
sacsar marked this conversation as resolved.
Show resolved Hide resolved

# 2.10 (2023-10-06)

* Drop support for Python 3.7 (Jendrik Seipp, #323).
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def find_version(*parts):
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Software Development :: Quality Assurance",
],
install_requires=["toml"],
install_requires=["tomli >= 1.1.0; python_version < '3.11'"],
entry_points={"console_scripts": ["vulture = vulture.core:main"]},
python_requires=">=3.8",
packages=setuptools.find_packages(exclude=["tests"]),
Expand Down
80 changes: 67 additions & 13 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Unit tests for config file and CLI argument parsing.
"""

from io import StringIO
from io import BytesIO
from textwrap import dedent

import pytest
Expand Down Expand Up @@ -62,9 +62,10 @@ def test_toml_config():
sort_by_size=True,
verbose=True,
)
data = StringIO(
dedent(
"""\
data = BytesIO(
bytes(
dedent(
"""\
[tool.vulture]
exclude = ["file*.py", "dir/"]
ignore_decorators = ["deco1", "deco2"]
Expand All @@ -75,6 +76,50 @@ def test_toml_config():
verbose = true
paths = ["path1", "path2"]
"""
),
"utf-8",
)
)
result = _parse_toml(data)
assert isinstance(result, dict)
assert result == expected


def test_toml_config_with_heterogenous_array():
"""
Ensure parsing of TOML files results in a valid config object, even if some
other part of the file contains an array of mixed types.
"""
expected = dict(
paths=["path1", "path2"],
exclude=["file*.py", "dir/"],
ignore_decorators=["deco1", "deco2"],
ignore_names=["name1", "name2"],
make_whitelist=True,
min_confidence=10,
sort_by_size=True,
verbose=True,
)
data = BytesIO(
bytes(
dedent(
"""\
[tool.foo]
# comment for good measure
problem_array = [{ a = 1}, [2,3,4], "foo"]
sacsar marked this conversation as resolved.
Show resolved Hide resolved

[tool.vulture]
exclude = ["file*.py", "dir/"]
ignore_decorators = ["deco1", "deco2"]
ignore_names = ["name1", "name2"]
make_whitelist = true
min_confidence = 10
sort_by_size = true
verbose = true
paths = ["path1", "path2"]
"""
),
"utf-8",
)
)
result = _parse_toml(data)
Expand All @@ -87,9 +132,10 @@ def test_config_merging():
If we have both CLI args and a ``pyproject.toml`` file, the CLI args should
have precedence.
"""
toml = StringIO(
dedent(
"""\
toml = BytesIO(
jendrikseipp marked this conversation as resolved.
Show resolved Hide resolved
bytes(
dedent(
"""\
[tool.vulture]
exclude = ["toml_exclude"]
ignore_decorators = ["toml_deco"]
Expand All @@ -100,6 +146,8 @@ def test_config_merging():
verbose = false
paths = ["toml_path"]
"""
),
"utf-8",
)
)
cliargs = [
Expand Down Expand Up @@ -131,13 +179,16 @@ def test_config_merging_missing():
If we have set a boolean value in the TOML file, but not on the CLI, we
want the TOML value to be taken.
"""
toml = StringIO(
dedent(
"""\
toml = BytesIO(
bytes(
dedent(
"""\
[tool.vulture]
verbose = true
ignore_names = ["name1"]
"""
),
"utf-8",
)
)
cliargs = [
Expand All @@ -153,12 +204,15 @@ def test_config_merging_toml_paths_only():
If we have paths in the TOML but not on the CLI, the TOML paths should be
used.
"""
toml = StringIO(
dedent(
"""\
toml = BytesIO(
bytes(
dedent(
"""\
[tool.vulture]
paths = ["path1", "path2"]
"""
),
"utf-8",
)
)
cliargs = [
Expand Down
9 changes: 6 additions & 3 deletions vulture/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
import argparse
import pathlib

import toml
try:
import tomllib
except ModuleNotFoundError:
import tomli as tomllib

from .version import __version__

Expand Down Expand Up @@ -76,7 +79,7 @@ def _parse_toml(infile):
verbose = true
paths = ["path1", "path2"]
"""
data = toml.load(infile)
data = tomllib.load(infile)
settings = data.get("tool", {}).get("vulture", {})
_check_input_config(settings)
return settings
Expand Down Expand Up @@ -194,7 +197,7 @@ def make_config(argv=None, tomlfile=None):
else:
toml_path = pathlib.Path("pyproject.toml").resolve()
if toml_path.is_file():
with open(toml_path) as fconfig:
with open(toml_path, "rb") as fconfig:
config = _parse_toml(fconfig)
detected_toml_path = str(toml_path)
else:
Expand Down