Skip to content
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
49 changes: 34 additions & 15 deletions src/poetry/repositories/link_sources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import TYPE_CHECKING
from typing import ClassVar

from packaging.utils import canonicalize_name
from poetry.core.constraints.version import Version
from poetry.core.packages.package import Package
from poetry.core.version.exceptions import InvalidVersionError
Expand Down Expand Up @@ -79,10 +80,18 @@ def links(self) -> Iterator[Link]:
yield from links

@classmethod
def link_package_data(cls, link: Link) -> Package | None:
def _link_package_name_and_version(
cls, link: Link
) -> tuple[NormalizedName, Version] | None:
"""Extract just the (normalized name, version) for a link.

This is the hot path used when building the link cache: it avoids the
cost of constructing a full `Package` (which initializes a large
number of attributes) when only the name and version are needed as
cache keys.
"""
name: str | None = None
version_string: str | None = None
version: Version | None = None
m = wheel_file_re.match(link.filename) or sdist_file_re.match(link.filename)

if m:
Expand All @@ -95,19 +104,29 @@ def link_package_data(cls, link: Link) -> Package | None:
name = match.group(1)
version_string = match.group(2)

if version_string:
try:
version = Version.parse(version_string)
except InvalidVersionError:
logger.debug(
"Skipping url (%s) due to invalid version (%s)", link.url, version
)
return None

pkg = None
if name and version:
pkg = Package(name, version, source_url=link.url)
return pkg
if not (name and version_string):
return None

try:
version = Version.parse(version_string)
except InvalidVersionError:
logger.debug(
"Skipping url (%s) due to invalid version (%s)",
link.url,
version_string,
)
return None

return canonicalize_name(name), version

@classmethod
def link_package_data(cls, link: Link) -> Package | None:
name_and_version = cls._link_package_name_and_version(link)
if name_and_version is None:
return None

name, version = name_and_version
return Package(name, version, source_url=link.url)

def links_for_version(
self, name: NormalizedName, version: Version
Expand Down
7 changes: 4 additions & 3 deletions src/poetry/repositories/link_sources/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ def _link_cache(self) -> LinkCache:
if link.ext not in self.SUPPORTED_FORMATS:
continue

pkg = self.link_package_data(link)
if pkg:
links[pkg.name][pkg.version].append(link)
name_and_version = self._link_package_name_and_version(link)
if name_and_version:
name, version = name_and_version
links[name][version].append(link)

return links

Expand Down
7 changes: 4 additions & 3 deletions src/poetry/repositories/link_sources/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ def _link_cache(self) -> LinkCache:
if link.ext not in self.SUPPORTED_FORMATS:
continue

pkg = self.link_package_data(link)
if pkg:
links[pkg.name][pkg.version].append(link)
name_and_version = self._link_package_name_and_version(link)
if name_and_version:
name, version = name_and_version
links[name][version].append(link)

return links

Expand Down
Loading