diff --git a/README.md b/README.md index e9ffb20..000d92e 100644 --- a/README.md +++ b/README.md @@ -50,5 +50,6 @@ poetry export -f requirements.txt --output requirements.txt * `--default`: Only export the main dependencies. (**Deprecated**) * `--dev`: Include development dependencies. (**Deprecated**) * `--extras (-E)`: Extra sets of dependencies to include. +* `--all-extras`: Include all sets of extra dependencies. * `--without-hashes`: Exclude hashes from the exported file. * `--with-credentials`: Include credentials for extra indices. diff --git a/docs/_index.md b/docs/_index.md index cd34c3d..0837c86 100644 --- a/docs/_index.md +++ b/docs/_index.md @@ -73,5 +73,6 @@ poetry export --only test,docs * `--default`: Only export the main dependencies. (**Deprecated**) * {{< option name="dev" deprecated=true >}}Include development dependencies.{{< /option >}} * `--extras (-E)`: Extra sets of dependencies to include. +* `--all-extras`: Include all sets of extra dependencies. * `--without-hashes`: Exclude hashes from the exported file. * `--with-credentials`: Include credentials for extra indices. diff --git a/src/poetry_plugin_export/command.py b/src/poetry_plugin_export/command.py index 854493f..06ca162 100644 --- a/src/poetry_plugin_export/command.py +++ b/src/poetry_plugin_export/command.py @@ -1,8 +1,10 @@ from __future__ import annotations from pathlib import Path +from typing import TYPE_CHECKING from cleo.helpers import option +from packaging.utils import NormalizedName from packaging.utils import canonicalize_name from poetry.console.commands.group_command import GroupCommand from poetry.core.packages.dependency_group import MAIN_GROUP @@ -10,6 +12,10 @@ from poetry_plugin_export.exporter import Exporter +if TYPE_CHECKING: + from collections.abc import Iterable + + class ExportCommand(GroupCommand): name = "export" description = "Exports the lock file to alternative formats." @@ -43,6 +49,7 @@ class ExportCommand(GroupCommand): flag=False, multiple=True, ), + option("all-extras", None, "Include all sets of extra dependencies."), option("with-credentials", None, "Include credentials for extra indices."), ] @@ -86,16 +93,28 @@ def handle(self) -> int: ) # Checking extras - extras = { - canonicalize_name(extra) - for extra_opt in self.option("extras") - for extra in extra_opt.split() - } - invalid_extras = extras - self.poetry.package.extras.keys() - if invalid_extras: - raise ValueError( - f"Extra [{', '.join(sorted(invalid_extras))}] is not specified." + if self.option("extras") and self.option("all-extras"): + self.line_error( + "You cannot specify explicit" + " `--extras` while exporting" + " using `--all-extras`." ) + return 1 + + extras: Iterable[NormalizedName] + if self.option("all-extras"): + extras = self.poetry.package.extras.keys() + else: + extras = { + canonicalize_name(extra) + for extra_opt in self.option("extras") + for extra in extra_opt.split() + } + invalid_extras = extras - self.poetry.package.extras.keys() + if invalid_extras: + raise ValueError( + f"Extra [{', '.join(sorted(invalid_extras))}] is not specified." + ) exporter = Exporter(self.poetry, self.io) exporter.only_groups(list(self.activated_groups)) diff --git a/tests/command/test_command_export.py b/tests/command/test_command_export.py index 6f37fe3..9e72175 100644 --- a/tests/command/test_command_export.py +++ b/tests/command/test_command_export.py @@ -220,6 +220,24 @@ def test_export_reports_invalid_extras(tester: CommandTester, do_lock: None) -> assert str(error.value) == expected +def test_export_with_all_extras(tester: CommandTester, do_lock: None) -> None: + tester.execute("--format requirements.txt --all-extras") + output = tester.io.fetch_output() + assert f"bar==1.1.0 ; {MARKER_PY}" in output + assert f"qux==1.2.0 ; {MARKER_PY}" in output + + +def test_extras_conflicts_all_extras(tester: CommandTester, do_lock: None) -> None: + tester.execute("--extras bar --all-extras") + + assert tester.status_code == 1 + assert ( + tester.io.fetch_error() + == "You cannot specify explicit `--extras` while exporting using" + " `--all-extras`.\n" + ) + + def test_export_with_urls( monkeypatch: MonkeyPatch, tester: CommandTester, poetry: Poetry ) -> None: