From b2defd1a0f0374df4e4df8ea2884979007e9502e Mon Sep 17 00:00:00 2001 From: Tom Rochette Date: Mon, 23 Nov 2020 23:46:58 -0500 Subject: [PATCH] Add PyPI registry correctly to pool depending on other sources 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. --- poetry/factory.py | 13 +++-- poetry/repositories/pool.py | 5 ++ .../pyproject.toml | 24 ++++++++ .../pyproject.toml | 23 ++++++++ .../pyproject.toml | 19 ++++++ tests/test_factory.py | 58 +++++++++++++++++++ 6 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 tests/fixtures/with_non_default_multiple_secondary_sources/pyproject.toml create mode 100644 tests/fixtures/with_non_default_multiple_sources/pyproject.toml create mode 100644 tests/fixtures/with_non_default_secondary_source/pyproject.toml diff --git a/poetry/factory.py b/poetry/factory.py index 43555eef6c3..0315c40d5e4 100644 --- a/poetry/factory.py +++ b/poetry/factory.py @@ -93,14 +93,15 @@ def create_poetry( 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) return poetry diff --git a/poetry/repositories/pool.py b/poetry/repositories/pool.py index 20579b5fdab..87b2e3bad29 100644 --- a/poetry/repositories/pool.py +++ b/poetry/repositories/pool.py @@ -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: @@ -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 @@ -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 diff --git a/tests/fixtures/with_non_default_multiple_secondary_sources/pyproject.toml b/tests/fixtures/with_non_default_multiple_secondary_sources/pyproject.toml new file mode 100644 index 00000000000..933bee96912 --- /dev/null +++ b/tests/fixtures/with_non_default_multiple_secondary_sources/pyproject.toml @@ -0,0 +1,24 @@ +[tool.poetry] +name = "my-package" +version = "1.2.3" +description = "Some description." +authors = [ + "Your Name " +] +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 diff --git a/tests/fixtures/with_non_default_multiple_sources/pyproject.toml b/tests/fixtures/with_non_default_multiple_sources/pyproject.toml new file mode 100644 index 00000000000..6cacb602e8b --- /dev/null +++ b/tests/fixtures/with_non_default_multiple_sources/pyproject.toml @@ -0,0 +1,23 @@ +[tool.poetry] +name = "my-package" +version = "1.2.3" +description = "Some description." +authors = [ + "Your Name " +] +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/" diff --git a/tests/fixtures/with_non_default_secondary_source/pyproject.toml b/tests/fixtures/with_non_default_secondary_source/pyproject.toml new file mode 100644 index 00000000000..453e3f9747f --- /dev/null +++ b/tests/fixtures/with_non_default_secondary_source/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "my-package" +version = "1.2.3" +description = "Some description." +authors = [ + "Your Name " +] +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 diff --git a/tests/test_factory.py b/tests/test_factory.py index d213d808405..10bf487337b 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -166,6 +166,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")