Skip to content

Commit

Permalink
build: add circular dependency protection
Browse files Browse the repository at this point in the history
Fixes  pypa#511.
  • Loading branch information
layday committed Sep 3, 2022
1 parent e80b433 commit 0869ebe
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 12 deletions.
13 changes: 10 additions & 3 deletions src/build/__init__.py
Expand Up @@ -176,6 +176,13 @@ def check_dependency(
import importlib_metadata

req = packaging.requirements.Requirement(req_string)
normalised_req_string = str(req)

# ``Requirement`` doesn't implement ``__eq__`` so we cannot compare reqs for
# equality directly but the string representation is stable.
if normalised_req_string in ancestral_req_strings:
# cyclical dependency, already checked.
return

if req.marker:
extras = frozenset(('',)).union(parent_extras)
Expand All @@ -190,15 +197,15 @@ def check_dependency(
dist = importlib_metadata.distribution(req.name) # type: ignore[no-untyped-call]
except importlib_metadata.PackageNotFoundError:
# dependency is not installed in the environment.
yield ancestral_req_strings + (req_string,)
yield ancestral_req_strings + (normalised_req_string,)
else:
if req.specifier and not req.specifier.contains(dist.version, prereleases=True):
# the installed version is incompatible.
yield ancestral_req_strings + (req_string,)
yield ancestral_req_strings + (normalised_req_string,)
elif dist.requires:
for other_req_string in dist.requires:
# yields transitive dependencies that are not satisfied.
yield from check_dependency(other_req_string, ancestral_req_strings + (req_string,), req.extras)
yield from check_dependency(other_req_string, ancestral_req_strings + (normalised_req_string,), req.extras)


def _find_typo(dictionary: Mapping[str, str], expected: str) -> None:
Expand Down
18 changes: 9 additions & 9 deletions tests/test_projectbuilder.py
Expand Up @@ -133,24 +133,24 @@ def read_text(self, filename):
('extras_dep[extra_without_associated_deps]', None),
(
'extras_dep[extra_with_unmet_deps]',
('extras_dep[extra_with_unmet_deps]', "unmet_dep; extra == 'extra_with_unmet_deps'"),
('extras_dep[extra_with_unmet_deps]', 'unmet_dep; extra == "extra_with_unmet_deps"'),
),
(
'extras_dep[recursive_extra_with_unmet_deps]',
(
'extras_dep[recursive_extra_with_unmet_deps]',
"recursive_dep; extra == 'recursive_extra_with_unmet_deps'",
'recursive_dep; extra == "recursive_extra_with_unmet_deps"',
'recursive_unmet_dep',
),
),
('extras_dep[extra_with_met_deps]', None),
('missing_dep; python_version>"10"', None),
('missing_dep; python_version<="1"', None),
('missing_dep; python_version>="1"', ('missing_dep; python_version>="1"',)),
('missing_dep; python_version>="1"', ('missing_dep; python_version >= "1"',)),
('extras_dep == 1.0.0', None),
('extras_dep == 2.0.0', ('extras_dep == 2.0.0',)),
('extras_dep == 2.0.0', ('extras_dep==2.0.0',)),
('extras_dep[extra_without_associated_deps] == 1.0.0', None),
('extras_dep[extra_without_associated_deps] == 2.0.0', ('extras_dep[extra_without_associated_deps] == 2.0.0',)),
('extras_dep[extra_without_associated_deps] == 2.0.0', ('extras_dep[extra_without_associated_deps]==2.0.0',)),
('prerelease_dep >= 1.0.0', None),
('circular_dep', None),
],
Expand Down Expand Up @@ -259,12 +259,12 @@ def test_check_dependencies(mocker, package_test_flit):
builder._hook.get_requires_for_build_wheel.side_effect = copy.copy(side_effects)

# requires = []
assert builder.check_dependencies('sdist') == {('flit_core >=2,<3',)}
assert builder.check_dependencies('wheel') == {('flit_core >=2,<3',)}
assert builder.check_dependencies('sdist') == {('flit_core<3,>=2',)}
assert builder.check_dependencies('wheel') == {('flit_core<3,>=2',)}

# requires = ['something']
assert builder.check_dependencies('sdist') == {('flit_core >=2,<3',), ('something',)}
assert builder.check_dependencies('wheel') == {('flit_core >=2,<3',), ('something',)}
assert builder.check_dependencies('sdist') == {('flit_core<3,>=2',), ('something',)}
assert builder.check_dependencies('wheel') == {('flit_core<3,>=2',), ('something',)}

# BackendUnavailable
with pytest.raises(build.BuildBackendException):
Expand Down

0 comments on commit 0869ebe

Please sign in to comment.