diff --git a/docs/repositories.md b/docs/repositories.md index a06d45f9f46..4e57bff8d10 100644 --- a/docs/repositories.md +++ b/docs/repositories.md @@ -126,10 +126,10 @@ priority = "primary" If `priority` is undefined, the source is considered a primary source that takes precedence over PyPI, secondary, supplemental and explicit sources. Package sources are considered in the following order: -1. [default source](#default-package-source), -2. primary sources, -3. implicit PyPI (unless disabled by another [default source](#default-package-source) or configured explicitly), -4. [secondary sources](#secondary-package-sources) (DEPRECATED), +1. [default source](#default-package-source-deprecated) (DEPRECATED), +2. [primary sources](#primary-package-sources), +3. implicit PyPI (unless disabled by another [primary source](#primary-package-sources), [default source](#default-package-source-deprecated) or configured explicitly), +4. [secondary sources](#secondary-package-sources-deprecated) (DEPRECATED), 5. [supplemental sources](#supplemental-package-sources). [Explicit sources](#explicit-package-sources) are considered only for packages that explicitly [indicate their source](#package-source-constraint). @@ -145,27 +145,54 @@ poetry source add --priority=primary PyPI ``` If you prefer to disable PyPI completely, -you may choose to set one of your package sources to be the [default](#default-package-source) +just add a [primary source](#primary-package-sources) or configure PyPI as [explicit source](#explicit-package-sources). {{% /note %}} -#### Default Package Source +#### Default Package Source (DEPRECATED) -By default, Poetry configures [PyPI](https://pypi.org) as the default package source for your -project. You can alter this behaviour and exclusively look up packages only from the configured -package sources by adding a **single** source with `priority = "default"`. +*Deprecated in 1.8.0* + +{{% warning %}} + +Configuring a default package source is deprecated because it is the same +as the topmost [primary source](#primary-package-sources). +Just configure a primary package source and put it first in the list of package sources. + +{{% /warning %}} + +By default, if you have not configured any primary source, +Poetry will configure [PyPI](https://pypi.org) as the package source for your project. +You can alter this behaviour and exclusively look up packages only from the configured +package sources by adding at least one primary source (recommended) +or a **single** source with `priority = "default"` (deprecated). ```bash poetry source add --priority=default foo https://foo.bar/simple/ ``` + +#### Primary Package Sources + +All primary package sources are searched for each dependency without a [source constraint](#package-source-constraint). +If you configure at least one primary source, the implicit PyPI source is disabled. + +```bash +poetry source add --priority=primary foo https://foo.bar/simple/ +``` + +Sources without a priority are considered primary sources, too. + +```bash +poetry source add foo https://foo.bar/simple/ +``` + {{% warning %}} -In a future version of Poetry, PyPI will be disabled automatically -if at least one custom primary source is configured. -If you are using custom sources in addition to PyPI, you should configure PyPI explicitly +The implicit PyPI source is disabled automatically if at least one primary source is configured. +If you want to use PyPI in addition to a primary source, configure it explicitly with a certain priority, e.g. ```bash @@ -188,13 +215,6 @@ with Poetry, the PyPI repository cannot be configured with a given URL. Remember {{% /warning %}} -{{% warning %}} - -Configuring a custom package source as default, will effectively disable [PyPI](https://pypi.org) -as a package source for your project. - -{{% /warning %}} - #### Secondary Package Sources (DEPRECATED) *Deprecated in 1.5.0* diff --git a/src/poetry/console/commands/source/add.py b/src/poetry/console/commands/source/add.py index 5e1526f0f95..6d1ab587ee6 100644 --- a/src/poetry/console/commands/source/add.py +++ b/src/poetry/console/commands/source/add.py @@ -107,12 +107,20 @@ def handle(self) -> int: priority = Priority[priority_str.upper()] if priority is Priority.SECONDARY: - allowed_prios = (p for p in Priority if p is not Priority.SECONDARY) + allowed_prios = ( + p for p in Priority if p not in {Priority.DEFAULT, Priority.SECONDARY} + ) self.line_error( "Warning: Priority 'secondary' is deprecated. Consider" " changing the priority to one of the non-deprecated values:" f" {', '.join(repr(p.name.lower()) for p in allowed_prios)}." ) + if priority is Priority.DEFAULT: + self.line_error( + "Warning: Priority 'default' is deprecated. You can achieve" + " the same effect by changing the priority to 'primary' and putting" + " the source first." + ) sources = AoT([]) new_source = Source(name=name, url=url, priority=priority) diff --git a/src/poetry/factory.py b/src/poetry/factory.py index f4013cc2baf..16400eda356 100644 --- a/src/poetry/factory.py +++ b/src/poetry/factory.py @@ -159,6 +159,14 @@ def create_pool( f" {', '.join(repr(p.name.lower()) for p in allowed_prios)}." ) io.write_error_line(f"Warning: {warning}") + elif priority is Priority.DEFAULT: + warning = ( + "Found deprecated priority 'default' for source" + f" '{source.get('name')}' in pyproject.toml. You can achieve" + " the same effect by changing the priority to 'primary' and putting" + " the source first." + ) + io.write_error_line(f"Warning: {warning}") if io.is_debug(): message = f"Adding repository {repository.name} ({repository.url})" @@ -175,32 +183,15 @@ def create_pool( # Only add PyPI if no default repository is configured if not explicit_pypi: - if pool.has_default(): + if pool.has_default() or pool.has_primary_repositories(): if io.is_debug(): io.write_line("Deactivating the PyPI repository") else: from poetry.repositories.pypi_repository import PyPiRepository - if pool.has_primary_repositories(): - io.write_error_line( - "" - "Warning: In a future version of Poetry, PyPI will be disabled" - " automatically if at least one custom primary source is" - " configured. In order to avoid" - " a breaking change and make your pyproject.toml forward" - " compatible, add PyPI explicitly via 'poetry source add pypi'." - " By the way, this has the advantage that you can set the" - " priority of PyPI as with any other source." - "" - ) - - if pool.has_primary_repositories(): - pypi_priority = Priority.SECONDARY - else: - pypi_priority = Priority.DEFAULT - pool.add_repository( - PyPiRepository(disable_cache=disable_cache), priority=pypi_priority + PyPiRepository(disable_cache=disable_cache), + priority=Priority.PRIMARY, ) if not pool.repositories: diff --git a/tests/console/commands/source/test_add.py b/tests/console/commands/source/test_add.py index 01c24a37e1e..53ae876133a 100644 --- a/tests/console/commands/source/test_add.py +++ b/tests/console/commands/source/test_add.py @@ -22,27 +22,34 @@ def tester( return command_tester_factory("source add", poetry=poetry_with_source) +def _get_source_warning(priority: Priority) -> str: + if priority is Priority.SECONDARY: + return ( + "Warning: Priority 'secondary' is deprecated. Consider changing the" + " priority to one of the non-deprecated values: 'primary'," + " 'supplemental', 'explicit'." + ) + elif priority is Priority.DEFAULT: + return ( + "Warning: Priority 'default' is deprecated. You can achieve" + " the same effect by changing the priority to 'primary' and putting" + " the source first." + ) + return "" + + def assert_source_added_legacy( tester: CommandTester, poetry: Poetry, source_existing: Source, source_added: Source, ) -> None: - secondary_deprecated_str = ( - "" - if source_added.priority is not Priority.SECONDARY - else ( - "\nWarning: Priority 'secondary' is deprecated. Consider changing the" - " priority to one of the non-deprecated values: 'default', 'primary'," - " 'supplemental', 'explicit'." - ) - ) - assert ( - tester.io.fetch_error().strip() - == "Warning: Priority was set through a deprecated flag (--default or" - " --secondary). Consider using --priority next time." - + secondary_deprecated_str + warning = ( + "Warning: Priority was set through a deprecated flag (--default or" + " --secondary). Consider using --priority next time.\n" + + _get_source_warning(source_added.priority) ) + assert tester.io.fetch_error().strip() == warning assert ( tester.io.fetch_output().strip() == f"Adding source with name {source_added.name}." @@ -59,6 +66,7 @@ def assert_source_added( source_existing: Source, source_added: Source, ) -> None: + assert tester.io.fetch_error().strip() == _get_source_warning(source_added.priority) assert ( tester.io.fetch_output().strip() == f"Adding source with name {source_added.name}." @@ -126,9 +134,9 @@ def test_source_add_second_default_fails( tester.execute(f"--priority=default {source_default.name}1 {source_default.url}") assert ( tester.io.fetch_error().strip() - == f"Source with name {source_default.name} is already set to" - " default. Only one default source can be configured at a" - " time." + == f"{_get_source_warning(source_default.priority)}\n" + f"Source with name {source_default.name} is already set to default." + " Only one default source can be configured at a time." ) assert tester.status_code == 1 @@ -238,7 +246,7 @@ def test_source_add_existing_legacy( tester.io.fetch_error().strip() == "Warning: Priority was set through a deprecated flag" " (--default or --secondary). Consider using --priority next" - " time." + f" time.\n{_get_source_warning(Priority.DEFAULT)}" ) assert ( tester.io.fetch_output().strip() @@ -313,6 +321,7 @@ def test_source_add_existing_fails_due_to_other_default( poetry_with_source: Poetry, ) -> None: tester.execute(f"--priority=default {source_default.name} {source_default.url}") + tester.io.fetch_error() tester.io.fetch_output() name = getattr(source_existing.name, modifier)() @@ -320,9 +329,9 @@ def test_source_add_existing_fails_due_to_other_default( assert ( tester.io.fetch_error().strip() - == f"Source with name {source_default.name} is already set to" - " default. Only one default source can be configured at a" - " time." + == f"{_get_source_warning(source_default.priority)}\n" + f"Source with name {source_default.name} is already set to default." + " Only one default source can be configured at a time." ) assert tester.io.fetch_output().strip() == "" assert tester.status_code == 1 diff --git a/tests/test_factory.py b/tests/test_factory.py index ec9fda4476c..075d2dfb869 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -241,7 +241,12 @@ def test_poetry_with_default_source( poetry = Factory().create_poetry(fixture_dir("with_default_source"), io=io) assert len(poetry.pool.repositories) == 1 - assert io.fetch_error() == "" + assert ( + io.fetch_error().strip() + == "Warning: Found deprecated priority 'default' for source 'foo' in" + " pyproject.toml. You can achieve the same effect by changing the priority" + " to 'primary' and putting the source first." + ) def test_poetry_with_default_source_and_pypi( @@ -280,15 +285,11 @@ def test_poetry_with_non_default_source( poetry = Factory().create_poetry(fixture_dir(project), io=io) assert not poetry.pool.has_default() - assert poetry.pool.has_repository("PyPI") - assert poetry.pool.get_priority("PyPI") is Priority.SECONDARY - assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) + assert not poetry.pool.has_repository("PyPI") assert poetry.pool.has_repository("foo") assert poetry.pool.get_priority("foo") is Priority.PRIMARY assert isinstance(poetry.pool.repository("foo"), LegacyRepository) - assert {repo.name for repo in poetry.pool.repositories} == {"PyPI", "foo"} - error = io.fetch_error() - assert "Warning: In a future version of Poetry, PyPI will be disabled" in error + assert {repo.name for repo in poetry.pool.repositories} == {"foo"} def test_poetry_with_non_default_secondary_source_legacy( @@ -300,7 +301,7 @@ def test_poetry_with_non_default_secondary_source_legacy( assert poetry.pool.has_repository("PyPI") assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) - assert poetry.pool.get_priority("PyPI") is Priority.DEFAULT + assert poetry.pool.get_priority("PyPI") is Priority.PRIMARY assert poetry.pool.has_repository("foo") assert isinstance(poetry.pool.repository("foo"), LegacyRepository) assert {repo.name for repo in poetry.pool.repositories} == {"PyPI", "foo"} @@ -313,7 +314,7 @@ def test_poetry_with_non_default_secondary_source( assert poetry.pool.has_repository("PyPI") assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) - assert poetry.pool.get_priority("PyPI") is Priority.DEFAULT + assert poetry.pool.get_priority("PyPI") is Priority.PRIMARY assert poetry.pool.has_repository("foo") assert isinstance(poetry.pool.repository("foo"), LegacyRepository) assert {repo.name for repo in poetry.pool.repositories} == {"PyPI", "foo"} @@ -329,7 +330,7 @@ def test_poetry_with_non_default_multiple_secondary_sources_legacy( assert poetry.pool.has_repository("PyPI") assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) - assert poetry.pool.get_priority("PyPI") is Priority.DEFAULT + assert poetry.pool.get_priority("PyPI") is Priority.PRIMARY assert poetry.pool.has_repository("foo") assert isinstance(poetry.pool.repository("foo"), LegacyRepository) assert poetry.pool.has_repository("bar") @@ -346,7 +347,7 @@ def test_poetry_with_non_default_multiple_secondary_sources( assert poetry.pool.has_repository("PyPI") assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) - assert poetry.pool.get_priority("PyPI") is Priority.DEFAULT + assert poetry.pool.get_priority("PyPI") is Priority.PRIMARY assert poetry.pool.has_repository("foo") assert isinstance(poetry.pool.repository("foo"), LegacyRepository) assert poetry.pool.has_repository("bar") @@ -364,12 +365,10 @@ def test_poetry_with_non_default_multiple_sources_legacy( assert not poetry.pool.has_default() assert poetry.pool.has_repository("bar") assert isinstance(poetry.pool.repository("bar"), LegacyRepository) - assert poetry.pool.has_repository("PyPI") - assert poetry.pool.get_priority("PyPI") is Priority.SECONDARY - assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) + assert not poetry.pool.has_repository("PyPI") assert poetry.pool.has_repository("foo") assert isinstance(poetry.pool.repository("foo"), LegacyRepository) - assert {repo.name for repo in poetry.pool.repositories} == {"bar", "PyPI", "foo"} + assert {repo.name for repo in poetry.pool.repositories} == {"bar", "foo"} def test_poetry_with_non_default_multiple_sources( @@ -378,14 +377,12 @@ def test_poetry_with_non_default_multiple_sources( poetry = Factory().create_poetry(fixture_dir("with_non_default_multiple_sources")) assert not poetry.pool.has_default() - assert poetry.pool.has_repository("PyPI") - assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) - assert poetry.pool.get_priority("PyPI") is Priority.SECONDARY + assert not poetry.pool.has_repository("PyPI") assert poetry.pool.has_repository("bar") assert isinstance(poetry.pool.repository("bar"), LegacyRepository) assert poetry.pool.has_repository("foo") assert isinstance(poetry.pool.repository("foo"), LegacyRepository) - assert {repo.name for repo in poetry.pool.repositories} == {"PyPI", "bar", "foo"} + assert {repo.name for repo in poetry.pool.repositories} == {"bar", "foo"} def test_poetry_with_non_default_multiple_sources_pypi( @@ -417,7 +414,7 @@ def test_poetry_with_no_default_source(fixture_dir: FixtureDirGetter) -> None: poetry = Factory().create_poetry(fixture_dir("sample_project")) assert poetry.pool.has_repository("PyPI") - assert poetry.pool.get_priority("PyPI") is Priority.DEFAULT + assert poetry.pool.get_priority("PyPI") is Priority.PRIMARY assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) assert {repo.name for repo in poetry.pool.repositories} == {"PyPI"} @@ -429,7 +426,7 @@ def test_poetry_with_supplemental_source( poetry = Factory().create_poetry(fixture_dir("with_supplemental_source"), io=io) assert poetry.pool.has_repository("PyPI") - assert poetry.pool.get_priority("PyPI") is Priority.DEFAULT + assert poetry.pool.get_priority("PyPI") is Priority.PRIMARY assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) assert poetry.pool.has_repository("supplemental") assert poetry.pool.get_priority("supplemental") is Priority.SUPPLEMENTAL @@ -447,7 +444,7 @@ def test_poetry_with_explicit_source( assert len(poetry.pool.repositories) == 1 assert len(poetry.pool.all_repositories) == 2 assert poetry.pool.has_repository("PyPI") - assert poetry.pool.get_priority("PyPI") is Priority.DEFAULT + assert poetry.pool.get_priority("PyPI") is Priority.PRIMARY assert isinstance(poetry.pool.repository("PyPI"), PyPiRepository) assert poetry.pool.has_repository("explicit") assert isinstance(poetry.pool.repository("explicit"), LegacyRepository)