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

All extras #5452

Merged
merged 8 commits into from
Jun 4, 2022
Merged
5 changes: 4 additions & 1 deletion docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,13 @@ poetry install --only dev
```

You can also specify the extras you want installed
by passing the `-E|--extras` option (See [Extras]({{< relref "pyproject#extras" >}}) for more info)
by passing the `-E|--extras` option (See [Extras]({{< relref "pyproject#extras" >}}) for more info).
Pass `--all-extras` to install all defined extras for a project.

```bash
poetry install --extras "mysql pgsql"
poetry install -E mysql -E pgsql
poetry install --all-extras
```

By default `poetry` will install your project's package every time you run `install`:
Expand Down Expand Up @@ -227,6 +229,7 @@ option is used.
* `--no-root`: Do not install the root package (your project).
* `--dry-run`: Output the operations but do not execute anything (implicitly enables --verbose).
* `--extras (-E)`: Features to install (multiple values allowed).
* `--all-extras`: Install all extra features (conflicts with --extras).
* `--no-dev`: Do not install dev dependencies. (**Deprecated**)
* `--dev-only`: Only install dev dependencies. (**Deprecated**)
* `--remove-untracked`: Remove dependencies not presented in the lock file. (**Deprecated**)
Expand Down
6 changes: 6 additions & 0 deletions docs/pyproject.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,12 @@ poetry install --extras "mysql pgsql"
poetry install -E mysql -E pgsql
```

Or, you can install all extras with the `--all-extras` option:

```bash
poetry install --all-extras
```

When installing or specifying Poetry-built packages, the extras defined in this section can be activated
as described in [PEP 508](https://www.python.org/dev/peps/pep-0508/#extras).

Expand Down
24 changes: 18 additions & 6 deletions src/poetry/console/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class InstallCommand(InstallerCommand):
flag=False,
multiple=True,
),
option("all-extras", None, "Install all extra dependencies."),
]

help = """The <info>install</info> command reads the <comment>poetry.lock</> file from
Expand Down Expand Up @@ -79,12 +80,23 @@ def handle(self) -> int:
self.poetry.config.get("experimental.new-installer", False)
)

extras = []
for extra in self.option("extras", []):
if " " in extra:
extras += [e.strip() for e in extra.split(" ")]
else:
extras.append(extra)
if self.option("extras") and self.option("all-extras"):
self.line_error(
"<error>You cannot specify explicit"
" `<fg=yellow;options=bold>--extras</>` while installing"
" using `<fg=yellow;options=bold>--all-extras</>`.</error>"
)
return 1
neersighted marked this conversation as resolved.
Show resolved Hide resolved

if self.option("all-extras"):
extras = list(self.poetry.package.extras.keys())
else:
extras = []
for extra in self.option("extras", []):
if " " in extra:
extras += [e.strip() for e in extra.split(" ")]
else:
extras.append(extra)

self._installer.extras(extras)

Expand Down
46 changes: 46 additions & 0 deletions tests/console/commands/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

[tool.poetry.dependencies]
python = "~2.7 || ^3.4"
fizz = { version = "^1.0", optional = true }
buzz = { version = "^2.0", optional = true }

[tool.poetry.group.foo.dependencies]
foo = "^1.0"
Expand All @@ -48,6 +50,10 @@

[tool.poetry.group.bam.dependencies]
bam = "^1.4"

[tool.poetry.extras]
extras_a = [ "fizz" ]
extras_b = [ "buzz" ]
"""


Expand Down Expand Up @@ -132,3 +138,43 @@ def test_sync_option_is_passed_to_the_installer(
tester.execute("--sync")

assert tester.command.installer._requires_synchronization


def test_no_all_extras_doesnt_populate_installer(
tester: CommandTester, mocker: MockerFixture
):
"""
Not passing --all-extras means the installer doesn't see any extras.
"""
mocker.patch.object(tester.command.installer, "run", return_value=1)

tester.execute()

assert not tester.command.installer._extras


def test_all_extras_populates_installer(tester: CommandTester, mocker: MockerFixture):
"""
The --all-extras option results in extras passed to the installer.
"""
mocker.patch.object(tester.command.installer, "run", return_value=1)

tester.execute("--all-extras")

assert tester.command.installer._extras == ["extras_a", "extras_b"]


def test_extras_conlicts_all_extras(tester: CommandTester, mocker: MockerFixture):
"""
The --extras doesn't make sense with --all-extras.
"""
mocker.patch.object(tester.command.installer, "run", return_value=0)

tester.execute("--extras foo --all-extras")

assert tester.status_code == 1
assert (
tester.io.fetch_error()
== "You cannot specify explicit `--extras` while installing using"
" `--all-extras`.\n"
)