From 3f2ab1a5cecfb3cc700744cd6ce51b8d7aaa1359 Mon Sep 17 00:00:00 2001 From: finswimmer Date: Thu, 10 Sep 2020 19:04:04 +0200 Subject: [PATCH 1/3] * do not raise ValueError if a dependency is added via "poetry add" and this dependency is already in pyproject.toml --- poetry/console/commands/add.py | 39 +++++++++++++++++++++--------- tests/console/commands/test_add.py | 23 ++++++++++++------ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/poetry/console/commands/add.py b/poetry/console/commands/add.py index 89a6483ba44..bd115f1fa6f 100644 --- a/poetry/console/commands/add.py +++ b/poetry/console/commands/add.py @@ -1,3 +1,6 @@ +from typing import Dict +from typing import List + from cleo import argument from cleo import option @@ -86,18 +89,14 @@ def handle(self): if section not in poetry_content: poetry_content[section] = {} - for name in packages: - for key in poetry_content[section]: - if key.lower() == name.lower(): - pair = self._parse_requirements([name])[0] - if ( - "git" in pair - or "url" in pair - or pair.get("version") == "latest" - ): - continue + packages = self.remove_existing_packages_from_input( + packages, poetry_content, section + ) - raise ValueError("Package {} is already present".format(name)) + if not packages: + self.poetry.file.write(content) + self.line("Nothing to add.", style="info") + return 0 requirements = self._determine_requirements( packages, @@ -184,3 +183,21 @@ def handle(self): self.poetry.file.write(original_content) return status + + def remove_existing_packages_from_input( + self, packages, poetry_content, target_section + ): # type: (List[str], Dict, str) -> List[str] + existing_packages = [] + + for name in packages: + for key in poetry_content[target_section]: + if key.lower() == name.lower(): + existing_packages.append(name) + self.line( + "{name} is already in pyproject.toml. Skipping.".format( + name=name + ) + ) + packages = [name for name in packages if name not in existing_packages] + + return packages diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py index 3a0f3400403..5e390c398d6 100644 --- a/tests/console/commands/test_add.py +++ b/tests/console/commands/test_add.py @@ -714,7 +714,7 @@ def test_add_should_not_select_prereleases(app, repo, tester): assert content["dependencies"]["pyyaml"] == "^3.13" -def test_add_should_display_an_error_when_adding_existing_package_with_no_constraint( +def test_add_should_skip_when_adding_existing_package_with_no_constraint( app, repo, tester ): content = app.poetry.file.read() @@ -722,11 +722,14 @@ def test_add_should_display_an_error_when_adding_existing_package_with_no_constr app.poetry.file.write(content) repo.add_package(get_package("foo", "1.1.2")) + tester.execute("foo") - with pytest.raises(ValueError) as e: - tester.execute("foo") + expected = """\ +foo is already in pyproject.toml. Skipping. +Nothing to add. +""" - assert "Package foo is already present" == str(e.value) + assert expected in tester.io.fetch_output() def test_add_should_work_when_adding_existing_package_with_latest_constraint( @@ -1527,7 +1530,7 @@ def test_add_should_not_select_prereleases_old_installer( assert content["dependencies"]["pyyaml"] == "^3.13" -def test_add_should_display_an_error_when_adding_existing_package_with_no_constraint_old_installer( +def test_add_should_skip_when_adding_existing_package_with_no_constraint_old_installer( app, repo, installer, old_tester ): content = app.poetry.file.read() @@ -1536,10 +1539,14 @@ def test_add_should_display_an_error_when_adding_existing_package_with_no_constr repo.add_package(get_package("foo", "1.1.2")) - with pytest.raises(ValueError) as e: - old_tester.execute("foo") + old_tester.execute("foo") - assert "Package foo is already present" == str(e.value) + expected = """\ +foo is already in pyproject.toml. Skipping. +Nothing to add. +""" + + assert expected in old_tester.io.fetch_output() def test_add_should_work_when_adding_existing_package_with_latest_constraint_old_installer( From c4b64f57fd2eec9cabd1ec32c4e660536d1a700d Mon Sep 17 00:00:00 2001 From: finswimmer Date: Mon, 14 Sep 2020 20:21:15 +0200 Subject: [PATCH 2/3] give hint on how to update existing packages --- poetry/console/commands/add.py | 32 ++++++++++++++++++++---------- tests/console/commands/test_add.py | 16 +++++++++++---- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/poetry/console/commands/add.py b/poetry/console/commands/add.py index bd115f1fa6f..c60d6bd1db8 100644 --- a/poetry/console/commands/add.py +++ b/poetry/console/commands/add.py @@ -89,13 +89,18 @@ def handle(self): if section not in poetry_content: poetry_content[section] = {} - packages = self.remove_existing_packages_from_input( + existing_packages = self.get_existing_packages_from_input( packages, poetry_content, section ) + if existing_packages: + self.notify_about_existing_packages(existing_packages) + + packages = [name for name in packages if name not in existing_packages] + if not packages: self.poetry.file.write(content) - self.line("Nothing to add.", style="info") + self.line("Nothing to add.") return 0 requirements = self._determine_requirements( @@ -184,7 +189,7 @@ def handle(self): return status - def remove_existing_packages_from_input( + def get_existing_packages_from_input( self, packages, poetry_content, target_section ): # type: (List[str], Dict, str) -> List[str] existing_packages = [] @@ -193,11 +198,18 @@ def remove_existing_packages_from_input( for key in poetry_content[target_section]: if key.lower() == name.lower(): existing_packages.append(name) - self.line( - "{name} is already in pyproject.toml. Skipping.".format( - name=name - ) - ) - packages = [name for name in packages if name not in existing_packages] - return packages + return existing_packages + + def notify_about_existing_packages( + self, existing_packages + ): # type: (List[str]) -> None + self.line( + "The following packages are already present in the pyproject.toml and will be skipped:\n" + ) + for name in existing_packages: + self.line(" • {name}".format(name=name)) + self.line( + "\nIf you want to update it to the latest compatible version, you can use `poetry update package`.\n" + "If you prefer to upgrade it to the latest available version, you can use `poetry add package@latest`.\n" + ) diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py index 5e390c398d6..af2e093cd04 100644 --- a/tests/console/commands/test_add.py +++ b/tests/console/commands/test_add.py @@ -725,8 +725,12 @@ def test_add_should_skip_when_adding_existing_package_with_no_constraint( tester.execute("foo") expected = """\ -foo is already in pyproject.toml. Skipping. -Nothing to add. +The following packages are already present in the pyproject.toml and will be skipped: + + • foo + +If you want to update it to the latest compatible version, you can use `poetry update package`. +If you prefer to upgrade it to the latest available version, you can use `poetry add package@latest`. """ assert expected in tester.io.fetch_output() @@ -1542,8 +1546,12 @@ def test_add_should_skip_when_adding_existing_package_with_no_constraint_old_ins old_tester.execute("foo") expected = """\ -foo is already in pyproject.toml. Skipping. -Nothing to add. +The following packages are already present in the pyproject.toml and will be skipped: + + • foo + +If you want to update it to the latest compatible version, you can use `poetry update package`. +If you prefer to upgrade it to the latest available version, you can use `poetry add package@latest`. """ assert expected in old_tester.io.fetch_output() From 5aca16e4832d8ca65e5737d43cacfb7547f2f82b Mon Sep 17 00:00:00 2001 From: finswimmer Date: Mon, 14 Sep 2020 20:31:16 +0200 Subject: [PATCH 3/3] add utf-8 header --- poetry/console/commands/add.py | 1 + 1 file changed, 1 insertion(+) diff --git a/poetry/console/commands/add.py b/poetry/console/commands/add.py index c60d6bd1db8..3ad77ad686b 100644 --- a/poetry/console/commands/add.py +++ b/poetry/console/commands/add.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from typing import Dict from typing import List