diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0490ae968c2..adf3f9bdc23 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -58,7 +58,7 @@ repos: - py>=1.8.2 - attrs>=19.2.0 - packaging - - types-toml + - tomli - types-pkg_resources - repo: local hooks: diff --git a/AUTHORS b/AUTHORS index 5c3610e699c..16a53d94bdf 100644 --- a/AUTHORS +++ b/AUTHORS @@ -302,6 +302,7 @@ Sven-Hendrik Haase Sylvain Marié Tadek Teleżyński Takafumi Arakaki +Taneli Hukkinen Tanvi Mehta Tarcisio Fischer Tareq Alayan diff --git a/changelog/8789.feature.rst b/changelog/8789.feature.rst new file mode 100644 index 00000000000..23215c97ef2 --- /dev/null +++ b/changelog/8789.feature.rst @@ -0,0 +1 @@ +Switch TOML parser from ``toml`` to ``tomli`` for TOML v1.0.0 support in ``pyproject.toml``. diff --git a/setup.cfg b/setup.cfg index 0e86f10e7f6..094dfed87fa 100644 --- a/setup.cfg +++ b/setup.cfg @@ -47,7 +47,7 @@ install_requires = packaging pluggy>=0.12,<1.0.0a1 py>=1.8.2 - toml + tomli>=1.0.0,<2.0.0 atomicwrites>=1.0;sys_platform=="win32" colorama;sys_platform=="win32" importlib-metadata>=0.12;python_version<"3.8" diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 7dde4b92d41..89ade5f23b9 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -64,9 +64,13 @@ def load_config_dict_from_file( # '.toml' files are considered if they contain a [tool.pytest.ini_options] table. elif filepath.suffix == ".toml": - import toml + import tomli - config = toml.load(str(filepath)) + toml_text = filepath.read_text(encoding="utf-8") + try: + config = tomli.loads(toml_text) + except tomli.TOMLDecodeError as exc: + raise UsageError(str(exc)) from exc result = config.get("tool", {}).get("pytest", {}).get("ini_options", None) if result is not None: diff --git a/testing/test_findpaths.py b/testing/test_findpaths.py index af6aeb3a56d..3a2917261a2 100644 --- a/testing/test_findpaths.py +++ b/testing/test_findpaths.py @@ -2,6 +2,7 @@ from textwrap import dedent import pytest +from _pytest.config import UsageError from _pytest.config.findpaths import get_common_ancestor from _pytest.config.findpaths import get_dirs_from_args from _pytest.config.findpaths import load_config_dict_from_file @@ -52,6 +53,13 @@ def test_unsupported_pytest_section_in_cfg_file(self, tmp_path: Path) -> None: load_config_dict_from_file(fn) def test_invalid_toml_file(self, tmp_path: Path) -> None: + """Invalid .toml files should raise `UsageError`.""" + fn = tmp_path / "myconfig.toml" + fn.write_text("]invalid toml[", encoding="utf-8") + with pytest.raises(UsageError): + load_config_dict_from_file(fn) + + def test_custom_toml_file(self, tmp_path: Path) -> None: """.toml files without [tool.pytest.ini_options] are not considered for configuration.""" fn = tmp_path / "myconfig.toml" fn.write_text( @@ -77,6 +85,7 @@ def test_valid_toml_file(self, tmp_path: Path) -> None: y = 20.0 values = ["tests", "integration"] name = "foo" + heterogeneous_array = [1, "str"] """ ), encoding="utf-8", @@ -86,6 +95,7 @@ def test_valid_toml_file(self, tmp_path: Path) -> None: "y": "20.0", "values": ["tests", "integration"], "name": "foo", + "heterogeneous_array": [1, "str"], }