Skip to content

Commit

Permalink
trust empty requires dist with modern metadata (python-poetry#9078)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimbleby authored Mar 22, 2024
1 parent a562bd1 commit 9b3893a
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 13 deletions.
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: [email protected]
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: [email protected]
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

0 comments on commit 9b3893a

Please sign in to comment.