Skip to content

Commit

Permalink
pool: ensure sources are prioritised over PyPI
Browse files Browse the repository at this point in the history
When a project specifies non default sources, PyPI gets added as the
default source. This will prioritise packages available in PyPI when
the package exists in both index. This change ensures that PyPI is
only used as a default when no other sources are provided.

Resolves: python-poetry#1677 python-poetry#2564 python-poetry#3238
  • Loading branch information
abn committed Oct 19, 2020
1 parent 66d29f6 commit 1051e5f
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 3 deletions.
8 changes: 5 additions & 3 deletions poetry/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def create_poetry(
)

# Configuring sources
for source in poetry.local_config.get("source", []):
sources = poetry.local_config.get("source", [])
for source in sources:
repository = self.create_legacy_repository(source, config)
is_default = source.get("default", False)
is_secondary = source.get("secondary", False)
Expand All @@ -88,9 +89,10 @@ 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
# but only if we have no other default sourced
if not poetry.pool.has_default():
poetry.pool.add_repository(PyPiRepository(), True)
has_sources = bool(sources)
poetry.pool.add_repository(PyPiRepository(), not has_sources, has_sources)
else:
if io.is_debug():
io.write_line("Deactivating the PyPI repository")
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/with_non_default_source/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
My Package
==========
60 changes: 60 additions & 0 deletions tests/fixtures/with_non_default_source/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[tool.poetry]
name = "my-package"
version = "1.2.3"
description = "Some description."
authors = [
"Sébastien Eustace <sebastien@eustace.io>"
]
license = "MIT"

readme = "README.rst"

homepage = "https://python-poetry.org"
repository = "https://github.com/python-poetry/poetry"
documentation = "https://python-poetry.org/docs"

keywords = ["packaging", "dependency", "poetry"]

classifiers = [
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Libraries :: Python Modules"
]

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.6"
cleo = "^0.6"
pendulum = { git = "https://github.com/sdispater/pendulum.git", branch = "2.0" }
requests = { version = "^2.18", optional = true, extras=[ "security" ] }
pathlib2 = { version = "^2.2", python = "~2.7" }

orator = { version = "^0.9", optional = true }

# File dependency
demo = { path = "../distributions/demo-0.1.0-py2.py3-none-any.whl" }

# Dir dependency with setup.py
my-package = { path = "../project_with_setup/" }

# Dir dependency with pyproject.toml
simple-project = { path = "../simple_project/" }


[tool.poetry.extras]
db = [ "orator" ]

[tool.poetry.dev-dependencies]
pytest = "~3.4"


[tool.poetry.scripts]
my-script = "my_package:main"


[tool.poetry.plugins."blogtool.parsers"]
".rst" = "some_module::SomeClass"


[[tool.poetry.source]]
name = "foo"
url = "https://foo.bar/simple/"
27 changes: 27 additions & 0 deletions tests/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory
from poetry.repositories.legacy_repository import LegacyRepository
from poetry.repositories.pypi_repository import PyPiRepository
from poetry.utils._compat import PY2
from poetry.utils._compat import Path

Expand Down Expand Up @@ -150,6 +152,31 @@ def test_poetry_with_default_source():
assert 1 == len(poetry.pool.repositories)


def test_poetry_with_non_default_source():
poetry = Factory().create_poetry(fixtures_dir / "with_non_default_source")

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

assert not poetry.pool.has_default()

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

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


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

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

assert poetry.pool.has_default()

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


def test_poetry_with_two_default_sources():
with pytest.raises(ValueError) as e:
Factory().create_poetry(fixtures_dir / "with_two_default_sources")
Expand Down

0 comments on commit 1051e5f

Please sign in to comment.