Skip to content

Commit

Permalink
Update the install command to support groups
Browse files Browse the repository at this point in the history
  • Loading branch information
sdispater committed Jul 23, 2021
1 parent 4b8384c commit 20589be
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 13 deletions.
83 changes: 78 additions & 5 deletions poetry/console/commands/install.py
Expand Up @@ -9,8 +9,38 @@ class InstallCommand(InstallerCommand):
description = "Installs the project dependencies."

options = [
option("no-dev", None, "Do not install the development dependencies."),
option("dev-only", None, "Only install the development dependencies."),
option(
"without",
None,
"The dependency groups to ignore for installation.",
flag=False,
multiple=True,
),
option(
"with",
None,
"The optional dependency groups to include for installation.",
flag=False,
multiple=True,
),
option("default", None, "Only install the default dependencies."),
option(
"only",
None,
"The only dependency groups to install.",
flag=False,
multiple=True,
),
option(
"no-dev",
None,
"Do not install the development dependencies. (<warning>Deprecated</warning>)",
),
option(
"dev-only",
None,
"Only install the development dependencies. (<warning>Deprecated</warning>)",
),
option(
"no-root", None, "Do not install the root package (the current project)."
),
Expand Down Expand Up @@ -66,8 +96,51 @@ def handle(self) -> int:
extras.append(extra)

self._installer.extras(extras)
self._installer.dev_mode(not self.option("no-dev"))
self._installer.dev_only(self.option("dev-only"))

excluded_groups = []
included_groups = []
only_groups = []
if self.option("no-dev"):
self.line(
"<warning>The `<fg=yellow;options=bold>--no-dev</>` option is deprecated,"
"use the `<fg=yellow;options=bold>--without dev</>` notation instead.</warning>"
)
excluded_groups.append("dev")
elif self.option("dev-only"):
self.line(
"<warning>The `<fg=yellow;options=bold>--dev-only</>` option is deprecated,"
"use the `<fg=yellow;options=bold>--only dev</>` notation instead.</warning>"
)
only_groups.append("dev")

excluded_groups.extend(
[
group.strip()
for groups in self.option("without")
for group in groups.split(",")
]
)
included_groups.extend(
[
group.strip()
for groups in self.option("with")
for group in groups.split(",")
]
)
only_groups.extend(
[
group.strip()
for groups in self.option("only")
for group in groups.split(",")
]
)

if self.option("default"):
only_groups.append("default")

self._installer.only_groups(only_groups)
self._installer.without_groups(excluded_groups)
self._installer.with_groups(included_groups)
self._installer.dry_run(self.option("dry-run"))
self._installer.remove_untracked(self.option("remove-untracked"))
self._installer.verbose(self._io.is_verbose())
Expand All @@ -77,7 +150,7 @@ def handle(self) -> int:
if return_code != 0:
return return_code

if self.option("no-root") or self.option("dev-only"):
if self.option("no-root") or self.option("only"):
return 0

try:
Expand Down
6 changes: 3 additions & 3 deletions poetry/installation/installer.py
Expand Up @@ -286,10 +286,10 @@ def _do_install(self, local_repo: Repository) -> int:

if self._without_groups or self._with_groups or self._only_groups:
if self._with_groups:
# Default dependencies and opt-in optional dependencies
root = self._package.without_dependency_groups(self._with_groups)
# Default dependencies and opted-in optional dependencies
root = self._package.with_dependency_groups(self._with_groups)
elif self._without_groups:
# Default dependencies without elected groups
# Default dependencies without selected groups
root = self._package.without_dependency_groups(self._without_groups)
else:
# Only selected groups
Expand Down
19 changes: 19 additions & 0 deletions tests/console/commands/test_install.py
@@ -0,0 +1,19 @@
import pytest


@pytest.fixture
def tester(command_tester_factory):
return command_tester_factory("install")


def test_group_options_are_passed_to_the_installer(tester, mocker):
"""
Group options are passed properly to the installer.
"""
mocker.patch.object(tester.command.installer, "run", return_value=1)

tester.execute("--with foo,bar --without baz --without bim --only bam")

assert tester.command.installer._with_groups == ["foo", "bar"]
assert tester.command.installer._without_groups == ["baz", "bim"]
assert tester.command.installer._only_groups == ["bam"]
41 changes: 38 additions & 3 deletions tests/installation/test_installer.py
Expand Up @@ -15,6 +15,7 @@
from cleo.io.outputs.output import Verbosity
from deepdiff import DeepDiff

from poetry.core.packages.dependency_group import DependencyGroup
from poetry.core.packages.package import Package
from poetry.core.packages.project_package import ProjectPackage
from poetry.core.toml.file import TOMLFile
Expand Down Expand Up @@ -277,7 +278,9 @@ def test_run_update_after_removing_dependencies(
assert 1 == installer.executor.removals_count


def _configure_run_install_dev(locker, repo, package, installed):
def _configure_run_install_dev(
locker, repo, package, installed, with_optional_group=False
):
"""
Perform common test setup for `test_run_install_*dev*()` methods.
"""
Expand Down Expand Up @@ -334,13 +337,16 @@ def _configure_run_install_dev(locker, repo, package, installed):

package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "~1.1"))
package.add_dependency(Factory.create_dependency("C", "~1.2", groups=["dev"]))

group = DependencyGroup("dev", optional=with_optional_group)
group.add_dependency(Factory.create_dependency("C", "~1.2", groups=["dev"]))
package.add_dependency_group(group)


def test_run_install_no_group(installer, locker, repo, package, installed):
_configure_run_install_dev(locker, repo, package, installed)

installer.with_groups(["dev"])
installer.without_groups(["dev"])
installer.run()

assert 0 == installer.executor.installations_count
Expand All @@ -359,6 +365,35 @@ def test_run_install_group_only(installer, locker, repo, package, installed):
assert 2 == installer.executor.removals_count


def test_run_install_with_optional_group_not_selected(
installer, locker, repo, package, installed
):
_configure_run_install_dev(
locker, repo, package, installed, with_optional_group=True
)

installer.run()

assert 0 == installer.executor.installations_count
assert 0 == installer.executor.updates_count
assert 1 == installer.executor.removals_count


def test_run_install_with_optional_group_selected(
installer, locker, repo, package, installed
):
_configure_run_install_dev(
locker, repo, package, installed, with_optional_group=True
)

installer.with_groups(["dev"])
installer.run()

assert 0 == installer.executor.installations_count
assert 0 == installer.executor.updates_count
assert 0 == installer.executor.removals_count


@pytest.mark.parametrize(
"managed_reserved_package_names",
[
Expand Down
4 changes: 2 additions & 2 deletions tests/installation/test_installer_old.py
Expand Up @@ -227,7 +227,7 @@ def test_run_update_after_removing_dependencies(
assert len(removals) == 1


def test_run_install_no_dev(installer, locker, repo, package, installed):
def test_run_install_no_group(installer, locker, repo, package, installed):
locker.locked(True)
locker.mock_lock_data(
{
Expand Down Expand Up @@ -283,7 +283,7 @@ def test_run_install_no_dev(installer, locker, repo, package, installed):
package.add_dependency(Factory.create_dependency("B", "~1.1"))
package.add_dependency(Factory.create_dependency("C", "~1.2", groups=["dev"]))

installer.with_groups(["dev"])
installer.without_groups(["dev"])
installer.run()

installs = installer.installer.installs
Expand Down

0 comments on commit 20589be

Please sign in to comment.