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

trust empty requires dist with modern metadata #9078

Merged
merged 1 commit into from
Mar 22, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions src/poetry/inspection/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import pkginfo

from build import BuildBackendException
from poetry.core.constraints.version import Version
from poetry.core.factory import Factory
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.package import Package
from poetry.core.pyproject.toml import PyProjectTOML
Expand All @@ -23,7 +25,6 @@
from poetry.core.version.markers import InvalidMarker
from poetry.core.version.requirements import InvalidRequirement

from poetry.factory import Factory
from poetry.utils.helpers import extractall
from poetry.utils.isolated_build import isolated_builder
from poetry.utils.setup_reader import SetupReader
Expand All @@ -39,6 +40,8 @@

logger = logging.getLogger(__name__)

DYNAMIC_METADATA_VERSION = Version.parse("2.2")


class PackageInfoError(ValueError):
def __init__(self, path: Path, *reasons: BaseException | str) -> None:
Expand Down Expand Up @@ -216,6 +219,43 @@ def to_package(

return package

@classmethod
def _requirements_from_distribution(
cls,
dist: pkginfo.BDist | pkginfo.SDist | pkginfo.Wheel,
) -> list[str] | None:
"""
Helper method to extract package requirements from a `pkginfo.Distribution`
instance.

:param dist: The distribution instance to extract requirements from.
"""
# If the distribution lists requirements, we use those.
#
# If the distribution does not list requirements, but the metadata is new enough
# to specify that this is because there definitely are none: then we return an
# empty list.
#
# If there is a requires.txt, we use that.
if dist.requires_dist:
return list(dist.requires_dist)

if dist.metadata_version is not None:
metadata_version = Version.parse(dist.metadata_version)
if (
metadata_version >= DYNAMIC_METADATA_VERSION
and "Requires-Dist" not in dist.dynamic
):
return []

requires = Path(dist.filename) / "requires.txt"
if requires.exists():
text = requires.read_text(encoding="utf-8")
requirements = parse_requires(text)
return requirements

return None

@classmethod
def _from_distribution(
cls, dist: pkginfo.BDist | pkginfo.SDist | pkginfo.Wheel
Expand All @@ -226,15 +266,7 @@ def _from_distribution(

:param dist: The distribution instance to parse information from.
"""
requirements = None

if dist.requires_dist:
requirements = list(dist.requires_dist)
else:
requires = Path(dist.filename) / "requires.txt"
if requires.exists():
text = requires.read_text(encoding="utf-8")
requirements = parse_requires(text)
requirements = cls._requirements_from_distribution(dist)

info = cls(
name=dist.name,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Metadata-Version: 2.2
Name: demo
Version: 0.1.0
Summary: Demo project.
Home-page: https://github.com/demo/demo
Author: Sébastien Eustace
Author-email: sebastien@eustace.io
License: MIT
Description: UNKNOWN
Platform: UNKNOWN
Dynamic: Requires-Dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# this was copied over and modified from orjson project's pyproject.toml
# https://github.com/ijl/orjson/blob/master/pyproject.toml
[project]
name = "demo"
repository = "https://github.com/demo/demo"

[build-system]
build-backend = "maturin"
requires = ["maturin>=0.8.1,<0.9"]

[tool.maturin]
manylinux = "off"
sdist-include = ["Cargo.lock", "json/**/*"]
strip = "on"

[tool.black]
line-length = 88
target-version = ['py36', 'py37', 'py38']
include = '\.pyi?$'
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Metadata-Version: 2.3
Name: demo
Version: 0.1.0
Summary: Demo project.
Home-page: https://github.com/demo/demo
Author: Sébastien Eustace
Author-email: sebastien@eustace.io
License: MIT
Description: UNKNOWN
Platform: UNKNOWN
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# this was copied over and modified from orjson project's pyproject.toml
# https://github.com/ijl/orjson/blob/master/pyproject.toml
[project]
name = "demo"
repository = "https://github.com/demo/demo"

[build-system]
build-backend = "maturin"
requires = ["maturin>=0.8.1,<0.9"]

[tool.maturin]
manylinux = "off"
sdist-include = ["Cargo.lock", "json/**/*"]
strip = "on"

[tool.black]
line-length = 88
target-version = ['py36', 'py37', 'py38']
include = '\.pyi?$'
26 changes: 23 additions & 3 deletions tests/inspection/test_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,30 @@ def test_info_from_setup_cfg(demo_setup_cfg: Path) -> None:


def test_info_no_setup_pkg_info_no_deps(fixture_dir: FixtureDirGetter) -> None:
info = PackageInfo.from_directory(
fixture_dir("inspection") / "demo_no_setup_pkg_info_no_deps",
disable_build=True,
info = PackageInfo.from_metadata_directory(
fixture_dir("inspection") / "demo_no_setup_pkg_info_no_deps"
)
assert info is not None
assert info.name == "demo"
assert info.version == "0.1.0"
assert info.requires_dist is None


def test_info_no_setup_pkg_info_no_deps_for_sure(fixture_dir: FixtureDirGetter) -> None:
info = PackageInfo.from_metadata_directory(
fixture_dir("inspection") / "demo_no_setup_pkg_info_no_deps_for_sure",
)
assert info is not None
assert info.name == "demo"
assert info.version == "0.1.0"
assert info.requires_dist == []


def test_info_no_setup_pkg_info_no_deps_dynamic(fixture_dir: FixtureDirGetter) -> None:
info = PackageInfo.from_metadata_directory(
fixture_dir("inspection") / "demo_no_setup_pkg_info_no_deps_dynamic",
)
assert info is not None
assert info.name == "demo"
assert info.version == "0.1.0"
assert info.requires_dist is None
Expand Down
Loading