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

build: switch to tomli for TOML v1 compliant parser #336

Merged
merged 1 commit into from
Aug 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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


Expand Down
6 changes: 6 additions & 0 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
=============
Expand Down Expand Up @@ -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
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
35 changes: 30 additions & 5 deletions src/build/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
gaborbernat marked this conversation as resolved.
Show resolved Hide resolved


RunnerType = Callable[[Sequence[str], Optional[str], Optional[Mapping[str, str]]], None]
Expand Down Expand Up @@ -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')
Expand Down
1 change: 1 addition & 0 deletions tests/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions tests/test_projectbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import copy
import importlib
import os
import sys
import textwrap
Expand Down Expand Up @@ -520,3 +521,27 @@ 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_tomli_not_available(mocker):
loads = mocker.patch('tomli.loads')
mocker.patch.dict(sys.modules, {'tomli': None})
importlib.reload(build)
try:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you want

patch.dict(sys.modules, {'tomli': None})

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I did not know about it 😛

yield
finally:
loads.assert_not_called()
mocker.stopall()
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)