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

Make warning about disabling PyPI become true and deprecate default source #8771

Merged
merged 2 commits into from
Jan 27, 2024
Merged
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
58 changes: 39 additions & 19 deletions docs/repositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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
Expand All @@ -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*
Expand Down
10 changes: 9 additions & 1 deletion src/poetry/console/commands/source/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -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>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)}.</warning>"
)
if priority is Priority.DEFAULT:
self.line_error(
"<warning>Warning: Priority 'default' is deprecated. You can achieve"
" the same effect by changing the priority to 'primary' and putting"
" the source first.</warning>"
)

sources = AoT([])
new_source = Source(name=name, url=url, priority=priority)
Expand Down
31 changes: 11 additions & 20 deletions src/poetry/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -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: {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: {warning}</warning>")

if io.is_debug():
message = f"Adding repository {repository.name} ({repository.url})"
Expand All @@ -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>"
"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."
"</warning>"
)

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:
Expand Down
51 changes: 30 additions & 21 deletions tests/console/commands/source/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}."
Expand All @@ -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}."
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -313,16 +321,17 @@ 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)()
tester.execute(f"--priority=default {name} {source_existing.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.io.fetch_output().strip() == ""
assert tester.status_code == 1
41 changes: 19 additions & 22 deletions tests/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -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>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(
Expand Down Expand Up @@ -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(
Expand All @@ -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"}
Expand All @@ -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"}
Expand All @@ -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")
Expand All @@ -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")
Expand All @@ -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(
Expand All @@ -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(
Expand Down Expand Up @@ -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"}

Expand All @@ -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
Expand All @@ -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)
Expand Down
Loading