Skip to content

Commit

Permalink
repositories: deprecate default option and introduce possibility to…
Browse files Browse the repository at this point in the history
… disable PyPI explicitly
  • Loading branch information
radoering committed Jan 29, 2023
1 parent 9a0b4af commit 9121ba1
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 20 deletions.
2 changes: 1 addition & 1 deletion docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ You cannot use the name `pypi` as it is reserved for use by the default PyPI sou

#### Options

* `--default`: Set this source as the [default]({{< relref "repositories#disabling-the-pypi-repository" >}}) (disable PyPI).
* `--default`: Set this source as the default (**Deprecated**, use TODO to disable PyPI).
* `--secondary`: Set this source as a [secondary]({{< relref "repositories#install-dependencies-from-a-private-repository" >}}) source.

{{% note %}}
Expand Down
22 changes: 13 additions & 9 deletions docs/repositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ This will generate the following configuration snippet in your
[[tool.poetry.source]]
name = "foo"
url = "https://foo.bar/simple/"
default = false
secondary = false
```

Expand All @@ -129,7 +128,8 @@ Any package source not marked as `secondary` will take precedence over [PyPI](ht

{{% note %}}

If you prefer to disable [PyPI](https://pypi.org) completely, you may choose to set one of your package sources to be the [default](#default-package-source).
If you prefer to disable [PyPI](https://pypi.org) completely, TODO new command.
If you disable PyPI, you have to configure at least one other source.

If you prefer to specify a package source for a specific dependency, see [Secondary Package Sources](#secondary-package-sources).

Expand All @@ -144,20 +144,24 @@ you must declare **all** package sources to be [secondary](#secondary-package-so
{{% /warning %}}


#### Default Package Source
#### Default Package Source PyPI

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 `default = true`.
By default, Poetry configures [PyPI](https://pypi.org) as the default package source for
your project. If you configure additional sources, these are preferred to PyPI unless
they are configured as secondary. Nevertheless, packages are looked up on PyPI.

You can alter this behaviour and exclusively look up packages only
from the configured package sources by TODO new command.
Adding a **single** source with `default = true` (**deprecated**) also disables PyPI.

```bash
poetry source add --default foo https://foo.bar/simple/
poetry source TODO
```

{{% warning %}}

Configuring a custom package source as default, will effectively disable [PyPI](https://pypi.org)
as a package source for your project.
Configuring a custom package source as default (**deprecated**),
will effectively disable [PyPI](https://pypi.org) as a package source for your project.

{{% /warning %}}

Expand Down
3 changes: 1 addition & 2 deletions src/poetry/console/commands/source/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from cleo.helpers import argument
from cleo.helpers import option
from cleo.io.null_io import NullIO
from tomlkit.items import AoT

from poetry.config.source import Source
Expand Down Expand Up @@ -88,7 +87,7 @@ def handle(self) -> int:
self.poetry._pool = RepositoryPool()
try:
Factory.configure_sources(
self.poetry, sources, self.poetry.config, NullIO()
self.poetry, sources, self.poetry.config, self._io
)
self.poetry.pool.repository(name)
except ValueError as e:
Expand Down
20 changes: 19 additions & 1 deletion src/poetry/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def create_poetry(
config,
io,
disable_cache=disable_cache,
disable_pypi=poetry.local_config.get("disable-pypi", False),
)

plugin_manager = PluginManager(Plugin.group, disable_plugins=disable_plugins)
Expand All @@ -117,6 +118,8 @@ def configure_sources(
config: Config,
io: IO,
disable_cache: bool = False,
*,
disable_pypi: bool = False,
) -> None:
if disable_cache:
logger.debug("Disabling source caches")
Expand All @@ -135,13 +138,28 @@ def configure_sources(
message += " and setting it as secondary"

io.write_line(message)
if is_default:
# TODO: replace command
io.write_error_line(
"<warning>"
"The 'default' option is deprecated.\n"
" If you want to disable PyPI, TODO command\n"
" If you want to set a source as the first source to be searched"
" for packages, just make it the first source in your"
" pyproject.toml."
"</warning>"
)

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

# 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 poetry.pool.has_default() or disable_pypi:
if not sources:
raise RuntimeError(
'If no sources are configured, "disable-pypi" must not be set!'
)
if io.is_debug():
io.write_line("Deactivating the PyPI repository")
else:
Expand Down
4 changes: 4 additions & 0 deletions src/poetry/json/schemas/poetry.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
"type": "object",
"required": [],
"properties": {
"disable-pypi": {
"type": "boolean",
"description": "Whether PyPI is implicitly used to search for packages."
},
"source": {
"type": "array",
"description": "A set of additional repositories where packages can be found.",
Expand Down
3 changes: 3 additions & 0 deletions src/poetry/utils/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ def source_to_table(source: Source) -> Table:

source_table: Table = table()
for key, value in source.to_dict().items():
if key == "default" and not value:
# default is deprecated, so we don't add it if it is not set
continue
source_table.add(key, value)
source_table.add(nl())
return source_table
5 changes: 5 additions & 0 deletions tests/console/commands/source/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ def assert_source_added(
== f"Adding source with name {source_added.name}."
)
poetry.pyproject.reload()
for source_table in poetry.pyproject.poetry_config["source"]:
# "default" is deprecated and should only be written if set to True
assert "default" not in source_table or source_table["default"] is True
sources = poetry.get_sources()
assert sources == [source_existing, source_added]
assert tester.status_code == 0
Expand All @@ -55,6 +58,7 @@ def test_source_add_default(
poetry_with_source: Poetry,
):
tester.execute(f"--default {source_default.name} {source_default.url}")
assert "deprecated" in tester.io.fetch_error()
assert_source_added(tester, poetry_with_source, source_existing, source_default)


Expand Down Expand Up @@ -95,6 +99,7 @@ def test_source_add_existing(
tester.io.fetch_output().strip()
== f"Source with name {source_existing.name} already exists. Updating."
)
assert "deprecated" in tester.io.fetch_error()

poetry_with_source.pyproject.reload()
sources = poetry_with_source.get_sources()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[tool.poetry]
name = "my-package"
version = "1.2.3"
description = "Some description."
authors = [
"Your Name <you@example.com>"
]
license = "MIT"
disable-pypi = true

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

[tool.poetry.dev-dependencies]
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"
disable-pypi = true

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

[tool.poetry.dev-dependencies]

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

import pytest

from cleo.io.buffered_io import BufferedIO
from deepdiff import DeepDiff
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import parse_constraint
Expand Down Expand Up @@ -207,10 +208,25 @@ def test_create_poetry_with_multi_constraints_dependency():


def test_poetry_with_default_source(with_simple_keyring: None):
poetry = Factory().create_poetry(fixtures_dir / "with_default_source")
io = BufferedIO()
poetry = Factory().create_poetry(fixtures_dir / "with_default_source", io=io)

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

assert poetry.pool.has_default()

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

assert "deprecated" in io.fetch_error()


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

assert str(e.value) == "Only one repository can be the default."


def test_poetry_with_non_default_source(with_simple_keyring: None):
poetry = Factory().create_poetry(fixtures_dir / "with_non_default_source")
Expand All @@ -226,6 +242,19 @@ def test_poetry_with_non_default_source(with_simple_keyring: None):
assert isinstance(poetry.pool.repositories[1], PyPiRepository)


def test_poetry_with_nondefault_source_pypi_disabled(with_simple_keyring: None):
poetry = Factory().create_poetry(
fixtures_dir / "with_non_default_source_pypi_disabled"
)

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

assert not poetry.pool.has_default()

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


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

Expand Down Expand Up @@ -284,7 +313,7 @@ def test_poetry_with_non_default_multiple_sources(with_simple_keyring: None):
assert isinstance(repository, PyPiRepository)


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

assert len(poetry.pool.repositories) == 1
Expand All @@ -295,11 +324,9 @@ def test_poetry_with_no_default_source():
assert isinstance(poetry.pool.repositories[0], PyPiRepository)


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

assert str(e.value) == "Only one repository can be the default."
def test_poetry_with_no_explicit_source_pypi_disabled():
with pytest.raises(RuntimeError, match="no sources"):
Factory().create_poetry(fixtures_dir / "with_no_explicit_source_pypi_disabled")


def test_validate():
Expand Down

0 comments on commit 9121ba1

Please sign in to comment.