Skip to content

Commit

Permalink
Add PyPI registry correctly to pool depending on other sources (pytho…
Browse files Browse the repository at this point in the history
…n-poetry#3406)

In the event where we defined sources that were set as
secondary = True, we would end up with PyPI being after this source
when it should have acted as default in that case.

The main issue stems from the fact that it's not because you have
sources configured that PyPI should not be a default. Instead, PyPI
should be default if there are no sources with secondary = False and
not default if there are sources with secondary = True.
  • Loading branch information
tomzx authored Apr 26, 2021
1 parent 494dec2 commit a3c5cf7
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 6 deletions.
13 changes: 7 additions & 6 deletions poetry/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,15 @@ def configure_sources(

poetry.pool.add_repository(repository, is_default, secondary=is_secondary)

# Always put PyPI last to prefer private repositories
# but only if we have no other default source
if not poetry.pool.has_default():
has_sources = bool(sources)
poetry.pool.add_repository(PyPiRepository(), not has_sources, has_sources)
else:
# Put PyPI last to prefer private repositories
# unless we have no default source AND no primary sources
# (default = false, secondary = false)
if poetry.pool.has_default():
if io.is_debug():
io.write_line("Deactivating the PyPI repository")
else:
default = not poetry.pool.has_primary_repositories()
poetry.pool.add_repository(PyPiRepository(), default, not default)

@classmethod
def create_legacy_repository(
Expand Down
5 changes: 5 additions & 0 deletions poetry/repositories/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(
self._lookup: Dict[str, int] = {}
self._repositories: List[Repository] = []
self._default = False
self._has_primary_repositories = False
self._secondary_start_idx = None

for repository in repositories:
Expand All @@ -41,6 +42,9 @@ def repositories(self) -> List[Repository]:
def has_default(self) -> bool:
return self._default

def has_primary_repositories(self) -> bool:
return self._has_primary_repositories

def has_repository(self, name: str) -> bool:
name = name.lower() if name is not None else None

Expand Down Expand Up @@ -84,6 +88,7 @@ def add_repository(
self._repositories.append(repository)
self._lookup[repository_name] = len(self._repositories) - 1
else:
self._has_primary_repositories = True
if self._secondary_start_idx is None:
self._repositories.append(repository)
self._lookup[repository_name] = len(self._repositories) - 1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[tool.poetry]
name = "my-package"
version = "1.2.3"
description = "Some description."
authors = [
"Your Name <you@example.com>"
]
license = "MIT"

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.6"

[tool.poetry.dev-dependencies]

[[tool.poetry.source]]
name = "foo"
url = "https://foo.bar/simple/"
secondary = true

[[tool.poetry.source]]
name = "bar"
url = "https://bar.baz/simple/"
secondary = true
23 changes: 23 additions & 0 deletions tests/fixtures/with_non_default_multiple_sources/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[tool.poetry]
name = "my-package"
version = "1.2.3"
description = "Some description."
authors = [
"Your Name <you@example.com>"
]
license = "MIT"

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.6"

[tool.poetry.dev-dependencies]

[[tool.poetry.source]]
name = "foo"
url = "https://foo.bar/simple/"
secondary = true

[[tool.poetry.source]]
name = "bar"
url = "https://bar.baz/simple/"
19 changes: 19 additions & 0 deletions tests/fixtures/with_non_default_secondary_source/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[tool.poetry]
name = "my-package"
version = "1.2.3"
description = "Some description."
authors = [
"Your Name <you@example.com>"
]
license = "MIT"

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.6"

[tool.poetry.dev-dependencies]

[[tool.poetry.source]]
name = "foo"
url = "https://foo.bar/simple/"
secondary = true
58 changes: 58 additions & 0 deletions tests/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,64 @@ def test_poetry_with_non_default_source():
assert isinstance(poetry.pool.repositories[1], PyPiRepository)


def test_poetry_with_non_default_secondary_source():
poetry = Factory().create_poetry(fixtures_dir / "with_non_default_secondary_source")

assert len(poetry.pool.repositories) == 2

assert poetry.pool.has_default()

repository = poetry.pool.repositories[0]
assert repository.name == "PyPI"
assert isinstance(repository, PyPiRepository)

repository = poetry.pool.repositories[1]
assert repository.name == "foo"
assert isinstance(repository, LegacyRepository)


def test_poetry_with_non_default_multiple_secondary_sources():
poetry = Factory().create_poetry(
fixtures_dir / "with_non_default_multiple_secondary_sources"
)

assert len(poetry.pool.repositories) == 3

assert poetry.pool.has_default()

repository = poetry.pool.repositories[0]
assert repository.name == "PyPI"
assert isinstance(repository, PyPiRepository)

repository = poetry.pool.repositories[1]
assert repository.name == "foo"
assert isinstance(repository, LegacyRepository)

repository = poetry.pool.repositories[2]
assert repository.name == "bar"
assert isinstance(repository, LegacyRepository)


def test_poetry_with_non_default_multiple_sources():
poetry = Factory().create_poetry(fixtures_dir / "with_non_default_multiple_sources")

assert len(poetry.pool.repositories) == 3

assert not poetry.pool.has_default()

repository = poetry.pool.repositories[0]
assert repository.name == "bar"
assert isinstance(repository, LegacyRepository)

repository = poetry.pool.repositories[1]
assert repository.name == "foo"
assert isinstance(repository, LegacyRepository)

repository = poetry.pool.repositories[2]
assert repository.name == "PyPI"
assert isinstance(repository, PyPiRepository)


def test_poetry_with_no_default_source():
poetry = Factory().create_poetry(fixtures_dir / "sample_project")

Expand Down

0 comments on commit a3c5cf7

Please sign in to comment.