diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 19d4c29ab..0e7805bbc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,7 @@ Unreleased - The CLI now honnors `NO_COLOR`_ (`PR #333`_) - The CLI can now be forced to colorize the output by setting the ``FORCE_COLOR`` environment variable (`PR #335`_) - Added logging to ``build`` and ``build.env`` (`PR #333`_) +- Switch to a TOML v1 compliant parser (`PR #336`_, Fixes `#308`_) Breaking Changes @@ -19,7 +20,9 @@ Breaking Changes .. _PR #333: https://github.com/pypa/build/pull/333 .. _PR #335: https://github.com/pypa/build/pull/335 +.. _PR #336: https://github.com/pypa/build/pull/336 .. _#142: https://github.com/pypa/build/issues/142 +.. _#308: https://github.com/pypa/build/issues/308 .. _NO_COLOR: https://no-color.org diff --git a/docs/installation.rst b/docs/installation.rst index 96ce49270..e57a6c5a9 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -37,6 +37,9 @@ This package can build itself with only the ``toml`` and ``pep517`` dependencies. The ``--skip-dependency-check`` flag should be used in this case. +We have a dependency on tomli_, but toml_ can be used instead, which may make +bootstraping easier. + Compatibility ============= @@ -66,6 +69,9 @@ versions: .. _git tag: https://github.com/pypa/build/tags .. _project page: https://pypi.org/project/build/ +.. _tomli: https://github.com/hukkin/tomli +.. _toml: https://github.com/uiri/toml + .. |3DCE51D60930EBA47858BA4146F633CBB0EB4BF2| replace:: ``3DCE51D60930EBA47858BA4146F633CBB0EB4BF2`` .. _3DCE51D60930EBA47858BA4146F633CBB0EB4BF2: https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3dce51d60930eba47858ba4146f633cbb0eb4bf2 diff --git a/setup.cfg b/setup.cfg index 28d39ef10..e03d42407 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,7 +27,7 @@ packages = find: install_requires = packaging>=19.0 pep517>=0.9.1 - toml>=0.10.0 + tomli>=1.0.0 # toml can be used instead -- in case it makes bootstraping easier colorama;os_name == "nt" # not actually a runtime dependency, only supplied as there is not "recomended dependency" support importlib-metadata>=0.22;python_version < "3.8" python_requires = >=3.6 @@ -54,10 +54,10 @@ test = pytest-rerunfailures>=9.1 pytest-xdist>=1.34 setuptools>=42.0.0 + toml>=0.10.0 wheel>=0.36.0 typing = mypy==0.910 - types-toml typing-extensions>=3.7.4.3 virtualenv = virtualenv>=20.0.35 diff --git a/src/build/__init__.py b/src/build/__init__.py index 3c2f3f2dd..9d534d365 100644 --- a/src/build/__init__.py +++ b/src/build/__init__.py @@ -17,10 +17,35 @@ import zipfile from collections import OrderedDict -from typing import AbstractSet, Any, Callable, Dict, Iterator, Mapping, Optional, Sequence, Set, Tuple, Type, Union +from typing import ( + AbstractSet, + Any, + Callable, + Dict, + Iterator, + Mapping, + MutableMapping, + Optional, + Sequence, + Set, + Tuple, + Type, + Union, +) import pep517.wrappers -import toml + + +TOMLDecodeError: Type[Exception] +toml_loads: Callable[[str], MutableMapping[str, Any]] + + +try: + from tomli import TOMLDecodeError + from tomli import loads as toml_loads +except ModuleNotFoundError: # pragma: no cover + from toml import TomlDecodeError as TOMLDecodeError # type: ignore + from toml import loads as toml_loads # type: ignore RunnerType = Callable[[Sequence[str], Optional[str], Optional[Mapping[str, str]]], None] @@ -185,13 +210,13 @@ def __init__( spec_file = os.path.join(srcdir, 'pyproject.toml') try: - with open(spec_file, encoding='UTF-8') as f: - spec = toml.load(f) + with open(spec_file, 'rb') as f: + spec = toml_loads(f.read().decode()) except FileNotFoundError: spec = {} except PermissionError as e: raise BuildException(f"{e.strerror}: '{e.filename}' ") - except toml.TomlDecodeError as e: + except TOMLDecodeError as e: raise BuildException(f'Failed to parse {spec_file}: {e} ') build_system = spec.get('build-system') diff --git a/tests/constraints.txt b/tests/constraints.txt index ed0b1e7ec..d93e63772 100644 --- a/tests/constraints.txt +++ b/tests/constraints.txt @@ -2,6 +2,7 @@ importlib-metadata==0.22;python_version < "3.8" packaging==19.0 pep517==0.9.1 toml==0.10.0 +tomli==1.0.0 typing==3.5.3.0;python_version < "3" virtualenv==20.0.35;python_version < "3" setuptools==42.0.0 diff --git a/tests/test_projectbuilder.py b/tests/test_projectbuilder.py index b2f2930ef..e758ef4e1 100644 --- a/tests/test_projectbuilder.py +++ b/tests/test_projectbuilder.py @@ -2,6 +2,7 @@ import copy +import importlib import os import sys import textwrap @@ -520,3 +521,31 @@ def test_metadata_invalid_wheel(tmp_dir, test_bad_wheel_path): with pytest.raises(ValueError, match='Invalid wheel'): builder.metadata_path(tmp_dir) + + +@pytest.fixture() +def mock_no_tomli_module(mocker): + loads = mocker.patch('tomli.loads') + mocker.patch.dict(sys.modules, {'tomli': None}) + yield + loads.assert_not_called() + + +@pytest.fixture() +def mock_tomli_not_available(mocker, mock_no_tomli_module): + importlib.reload(build) + try: + yield + finally: + importlib.reload(build) + + +def test_toml_instead_of_tomli(mocker, mock_tomli_not_available, tmp_dir, test_flit_path): + mocker.patch('pep517.wrappers.Pep517HookCaller', autospec=True) + + builder = build.ProjectBuilder(test_flit_path) + builder._hook.build_sdist.return_value = 'dist.tar.gz' + + builder.build('sdist', '.') + + builder._hook.build_sdist.assert_called_with(os.path.abspath('.'), None)