Skip to content

Commit

Permalink
trust empty requires dist with modern metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
dimbleby committed Mar 3, 2024
1 parent b8fd4a1 commit c79181c
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 9 deletions.
50 changes: 41 additions & 9 deletions src/poetry/inspection/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import pkginfo

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
Expand Down Expand Up @@ -57,6 +58,8 @@

PEP517_META_BUILD_DEPS = ["build==1.1.1", "pyproject_hooks==1.0.0"]

DYNAMIC_METADATA_VERSION = Version.parse("2.2")


class PackageInfoError(ValueError):
def __init__(self, path: Path, *reasons: BaseException | str) -> None:
Expand Down Expand Up @@ -234,6 +237,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 @@ -244,15 +284,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.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
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?$'
20 changes: 20 additions & 0 deletions tests/inspection/test_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,26 @@ def test_info_no_setup_pkg_info_no_deps(fixture_dir: FixtureDirGetter) -> None:
assert info.requires_dist is None


def test_info_no_setup_pkg_info_no_deps_for_sure(fixture_dir: FixtureDirGetter) -> None:
info = PackageInfo.from_directory(
fixture_dir("inspection") / "demo_no_setup_pkg_info_no_deps_for_sure",
disable_build=True,
)
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_directory(
fixture_dir("inspection") / "demo_no_setup_pkg_info_no_deps_dynamic",
disable_build=True,
)
assert info.name == "demo"
assert info.version == "0.1.0"
assert info.requires_dist is None


def test_info_setup_simple(mocker: MockerFixture, demo_setup: Path) -> None:
spy = mocker.spy(VirtualEnv, "run")
info = PackageInfo.from_directory(demo_setup)
Expand Down

0 comments on commit c79181c

Please sign in to comment.