diff --git a/docs/cli.md b/docs/cli.md index 69476c852b5..65f085a814b 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -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`: @@ -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**) diff --git a/docs/pyproject.md b/docs/pyproject.md index 7c5cc90d3af..e1d526aea02 100644 --- a/docs/pyproject.md +++ b/docs/pyproject.md @@ -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). diff --git a/src/poetry/console/commands/install.py b/src/poetry/console/commands/install.py index a7389bf28b8..e2776d4e004 100644 --- a/src/poetry/console/commands/install.py +++ b/src/poetry/console/commands/install.py @@ -52,6 +52,7 @@ class InstallCommand(InstallerCommand): flag=False, multiple=True, ), + option("all-extras", None, "Install all extra dependencies."), ] help = """The install command reads the poetry.lock file from @@ -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( + "You cannot specify explicit" + " `--extras` while installing" + " using `--all-extras`." + ) + return 1 + + 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) diff --git a/tests/console/commands/test_install.py b/tests/console/commands/test_install.py index 027b3de2f92..2be8a4a5e3c 100644 --- a/tests/console/commands/test_install.py +++ b/tests/console/commands/test_install.py @@ -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" @@ -48,6 +50,10 @@ [tool.poetry.group.bam.dependencies] bam = "^1.4" + +[tool.poetry.extras] +extras_a = [ "fizz" ] +extras_b = [ "buzz" ] """ @@ -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" + )