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

Refactor to parse_requirements_from_metadata #1

Merged
merged 1 commit into from
Apr 6, 2023
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
4 changes: 2 additions & 2 deletions piptools/_compat/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from __future__ import annotations

from .pip_compat import PIP_VERSION, install_req_from_line, parse_requirements
from .pip_compat import PIP_VERSION, parse_requirements

__all__ = ["PIP_VERSION", "install_req_from_line", "parse_requirements"]
__all__ = ["PIP_VERSION", "parse_requirements"]
25 changes: 1 addition & 24 deletions piptools/_compat/pip_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@
from pip._internal.network.session import PipSession
from pip._internal.req import InstallRequirement
from pip._internal.req import parse_requirements as _parse_requirements
from pip._internal.req.constructors import (
install_req_from_parsed_requirement,
parse_req_from_line,
)
from pip._internal.req.constructors import install_req_from_parsed_requirement
from pip._vendor.packaging.version import parse as parse_version
from pip._vendor.pkg_resources import Requirement

Expand All @@ -38,26 +35,6 @@ def parse_requirements(
yield install_req_from_parsed_requirement(parsed_req, isolated=isolated)


def install_req_from_line(
name: str,
comes_from: str | InstallRequirement | None = None,
base_package: str | None = None,
base_dir: str | None = None,
) -> InstallRequirement:
parts = parse_req_from_line(name, comes_from)
if base_package and base_dir and parts.requirement.name == base_package:
name = name.replace(base_package, base_dir, 1)
parts = parse_req_from_line(name, comes_from)

return InstallRequirement(
parts.requirement,
comes_from,
link=parts.link,
markers=parts.markers,
extras=parts.extras,
)


# The Distribution interface has changed between pkg_resources and
# importlib.metadata, so this compat layer allows for a consistent access
# pattern. In pip 22.1, importlib.metadata became the default on Python 3.11
Expand Down
20 changes: 8 additions & 12 deletions piptools/scripts/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
from click.utils import LazyFile, safecall
from pip._internal.commands import create_command
from pip._internal.req import InstallRequirement
from pip._internal.req.constructors import install_req_from_line
from pip._internal.utils.misc import redact_auth_from_url

from .._compat import install_req_from_line, parse_requirements
from .._compat import parse_requirements
from ..cache import DependencyCache
from ..exceptions import NoCandidateFound, PipToolsError
from ..locations import CACHE_DIR
Expand All @@ -29,6 +30,7 @@
drop_extras,
is_pinned_requirement,
key_from_ireq,
parse_requirements_from_wheel_metadata,
)
from ..writer import OutputWriter

Expand Down Expand Up @@ -497,19 +499,13 @@ def cli(
log.error(str(e))
log.error(f"Failed to parse {os.path.abspath(src_file)}")
sys.exit(2)
package_name = metadata.get_all("Name")[0]
comes_from = f"{package_name} ({src_file})"

constraints.extend(
[
install_req_from_line(
req,
comes_from,
package_name,
os.path.dirname(os.path.abspath(src_file)),
)
for req in metadata.get_all("Requires-Dist") or []
]
parse_requirements_from_wheel_metadata(
metadata=metadata, src_file=src_file
)
)

if all_extras:
if extras:
msg = "--extra has no effect when used with --all-extras"
Expand Down
41 changes: 39 additions & 2 deletions piptools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
import os
import re
import shlex
from typing import Any, Callable, Iterable, Iterator, TypeVar, cast
from typing import TYPE_CHECKING, Any, Callable, Iterable, Iterator, TypeVar, cast

import click
from click.utils import LazyFile
from pip._internal.req import InstallRequirement
from pip._internal.req.constructors import install_req_from_line
from pip._internal.req.constructors import install_req_from_line, parse_req_from_line
from pip._internal.utils.misc import redact_auth_from_url
from pip._internal.vcs import is_url
from pip._vendor.packaging.markers import Marker
Expand All @@ -23,6 +23,12 @@

from piptools.subprocess_utils import run_python_snippet

if TYPE_CHECKING:
from typing import Protocol
else:
Protocol = object


_KT = TypeVar("_KT")
_VT = TypeVar("_VT")
_T = TypeVar("_T")
Expand Down Expand Up @@ -482,3 +488,34 @@ def copy_install_requirement(
)

return ireq


class PackageMetadata(Protocol):
def get_all(self, name: str, failobj: _T = ...) -> list[str] | _T:
...


def parse_requirements_from_wheel_metadata(
metadata: PackageMetadata, src_file: str
) -> Iterator[InstallRequirement]:
package_name = metadata.get_all("Name")[0]
comes_from = f"{package_name} ({src_file})"

for req in metadata.get_all("Requires-Dist") or []:
parts = parse_req_from_line(req, comes_from)
if parts.requirement.name == package_name:
package_dir = os.path.dirname(os.path.abspath(src_file))
# Replace package name with package directory in the requirement
# string so that pip can find the package as self-referential.
# Note the string can contain extras, so we need to replace only
# the package name, not the whole string.
replaced_package_name = req.replace(package_name, package_dir, 1)
parts = parse_req_from_line(replaced_package_name, comes_from)

yield InstallRequirement(
parts.requirement,
comes_from,
link=parts.link,
markers=parts.markers,
extras=parts.extras,
)