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

repository: do not call secondary repositories if package is find in primary ones #5472

Closed
wants to merge 1 commit into from
Closed
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
5 changes: 3 additions & 2 deletions src/poetry/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ def configure_sources(
cls, poetry: Poetry, sources: list[dict[str, str]], config: Config, io: IO
) -> None:
for source in sources:
repository = cls.create_legacy_repository(source, config)
is_default = bool(source.get("default", False))
is_secondary = bool(source.get("secondary", False))
repository = cls.create_legacy_repository(source, config, is_secondary)
if io.is_debug():
message = f"Adding repository {repository.name} ({repository.url})"
if is_default:
Expand All @@ -154,7 +154,7 @@ def configure_sources(

@classmethod
def create_legacy_repository(
cls, source: dict[str, str], auth_config: Config
cls, source: dict[str, str], auth_config: Config, secondary: bool
) -> LegacyRepository:
from poetry.repositories.legacy_repository import LegacyRepository
from poetry.utils.helpers import get_cert
Expand All @@ -175,6 +175,7 @@ def create_legacy_repository(
config=auth_config,
cert=get_cert(auth_config, name),
client_cert=get_client_cert(auth_config, name),
secondary=secondary,
)

@classmethod
Expand Down
4 changes: 2 additions & 2 deletions src/poetry/repositories/cached.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
class CachedRepository(Repository, ABC):
CACHE_VERSION = parse_constraint("1.0.0")

def __init__(self, name: str, cache_group: str, disable_cache: bool = False):
super().__init__(name)
def __init__(self, name: str, cache_group: str, disable_cache: bool = False, secondary: bool = False):
super().__init__(name, secondary=secondary)
self._disable_cache = disable_cache
self._cache_dir = REPOSITORY_CACHE_DIR / name
self._cache = CacheManager(
Expand Down
3 changes: 2 additions & 1 deletion src/poetry/repositories/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ def __init__(
disable_cache: bool = False,
cert: Path | None = None,
client_cert: Path | None = None,
secondary: bool = False
) -> None:
super().__init__(name, "_http", disable_cache)
super().__init__(name, "_http", disable_cache, secondary)
self._url = url
self._client_cert = client_cert
self._cert = cert
Expand Down
4 changes: 2 additions & 2 deletions src/poetry/repositories/legacy_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ def __init__(
disable_cache: bool = False,
cert: Path | None = None,
client_cert: Path | None = None,
secondary: bool = False
) -> None:
if name == "pypi":
raise ValueError("The name [pypi] is reserved for repositories")

super().__init__(
name, url.rstrip("/"), config, disable_cache, cert, client_cert
name, url.rstrip("/"), config, disable_cache, cert, client_cert, secondary
)

def find_packages(self, dependency: Dependency) -> list[Package]:
Expand Down
2 changes: 2 additions & 0 deletions src/poetry/repositories/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ def find_packages(self, dependency: Dependency) -> list[Package]:

packages = []
for repo in self._repositories:
if repo.secondary and packages:
continue
packages += repo.find_packages(dependency)

return packages
Expand Down
15 changes: 7 additions & 8 deletions src/poetry/repositories/pypi_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,24 @@
from poetry.repositories.http import HTTPRepository
from poetry.utils._compat import to_str


cache_control_logger.setLevel(logging.ERROR)

logger = logging.getLogger(__name__)


if TYPE_CHECKING:
from poetry.core.packages.dependency import Dependency


class PyPiRepository(HTTPRepository):
def __init__(
self,
url: str = "https://pypi.org/",
disable_cache: bool = False,
fallback: bool = True,
self,
url: str = "https://pypi.org/",
disable_cache: bool = False,
fallback: bool = True,
secondary: bool = False,
) -> None:
super().__init__(
"PyPI", url.rstrip("/") + "/simple/", disable_cache=disable_cache
"PyPI", url.rstrip("/") + "/simple/", disable_cache=disable_cache, secondary=secondary
)

self._base_url = url
Expand Down Expand Up @@ -162,7 +161,7 @@ def find_links_for_package(self, package: Package) -> list[Link]:
return links

def _get_release_info(
self, name: str, version: str
self, name: str, version: str
) -> dict[str, str | list[str] | None]:
from poetry.inspection.info import PackageInfo

Expand Down
26 changes: 13 additions & 13 deletions src/poetry/repositories/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from poetry.core.semver.version_constraint import VersionConstraint
from poetry.core.semver.version_range import VersionRange


if TYPE_CHECKING:
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.package import Package
Expand All @@ -17,9 +16,10 @@


class Repository:
def __init__(self, name: str = None, packages: list[Package] = None) -> None:
def __init__(self, name: str = None, packages: list[Package] = None, secondary: bool = False) -> None:
self._name = name
self._packages: list[Package] = []
self.secondary = secondary

for package in packages or []:
self.add_package(package)
Expand All @@ -42,9 +42,9 @@ def find_packages(self, dependency: Dependency) -> list[Package]:
for package in self.packages:
if dependency.name == package.name:
if (
package.is_prerelease()
and not allow_prereleases
and not package.source_type
package.is_prerelease()
and not allow_prereleases
and not package.source_type
):
# If prereleases are not allowed and the package is a prerelease
# and is a standard package then we skip it
Expand All @@ -54,8 +54,8 @@ def find_packages(self, dependency: Dependency) -> list[Package]:
continue

if constraint.allows(package.version) or (
package.is_prerelease()
and constraint.allows(package.version.next_patch())
package.is_prerelease()
and constraint.allows(package.version.next_patch())
):
packages.append(package)

Expand Down Expand Up @@ -93,7 +93,7 @@ def search(self, query: str) -> list[Package]:

@staticmethod
def _get_constraints_from_dependency(
dependency: Dependency,
dependency: Dependency,
) -> tuple[VersionTypes, bool]:
constraint = dependency.constraint
if constraint is None:
Expand All @@ -104,10 +104,10 @@ def _get_constraints_from_dependency(

allow_prereleases = dependency.allows_prereleases()
if isinstance(constraint, VersionRange) and (
constraint.max is not None
and constraint.max.is_unstable()
or constraint.min is not None
and constraint.min.is_unstable()
constraint.max is not None
and constraint.max.is_unstable()
or constraint.min is not None
and constraint.min.is_unstable()
):
allow_prereleases = True

Expand All @@ -125,7 +125,7 @@ def find_links_for_package(self, package: Package) -> list[Link]:
return []

def package(
self, name: str, version: str, extras: list[str] | None = None
self, name: str, version: str, extras: list[str] | None = None
) -> Package:
name = name.lower()

Expand Down
37 changes: 37 additions & 0 deletions tests/repositories/test_pool.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from __future__ import annotations

from unittest.mock import Mock

import pytest

from poetry.repositories import Pool
from poetry.repositories import Repository
from poetry.repositories.exceptions import PackageNotFound
from poetry.repositories.legacy_repository import LegacyRepository
from poetry.core.packages.dependency import Dependency


def test_pool_raises_package_not_found_when_no_package_is_found():
Expand Down Expand Up @@ -71,3 +74,37 @@ def test_repository_with_normal_default_and_secondary_repositories():
assert pool.repository("foo") is repo1
assert pool.repository("bar") is repo2
assert pool.has_default()


def test_find_packages_do_not_call_secondary_if_primary_find_package():
secondary = LegacyRepository("secondary", "https://secondary.com", secondary=True)
repo2 = LegacyRepository("bar", "https://bar.baz")

pool = Pool()
pool.add_repository(secondary, secondary=True)
pool.add_repository(repo2)

dependency = Dependency("test", "1.0.0")

repo2.find_packages = Mock(return_value=["t"])
secondary.find_packages = Mock(return_value=["t"])
pool.find_packages(dependency)
repo2.find_packages.assert_called_once_with(dependency)
secondary.find_packages.assert_not_called()


def test_find_packages_call_secondary_if_primary_do_not_find_package():
secondary = LegacyRepository("secondary", "https://secondary.com", secondary=True)
repo2 = LegacyRepository("bar", "https://bar.baz")

pool = Pool()
pool.add_repository(secondary, secondary=True)
pool.add_repository(repo2)

dependency = Dependency("test", "1.0.0")

repo2.find_packages = Mock(return_value=[])
secondary.find_packages = Mock(return_value=["t"])
pool.find_packages(dependency)
repo2.find_packages.assert_called_once_with(dependency)
secondary.find_packages.assert_called_once_with(dependency)