From 9d861ff6c11d55c7ce500149b8331f3b5a3914f4 Mon Sep 17 00:00:00 2001 From: finswimmer Date: Thu, 21 May 2020 08:17:57 +0200 Subject: [PATCH 1/8] new: check if existing pyproject.toml contains a poetry or build-system section. If not prepend data on init. --- poetry/console/commands/init.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/poetry/console/commands/init.py b/poetry/console/commands/init.py index 606dad2870a..6d0b1f3d8d6 100644 --- a/poetry/console/commands/init.py +++ b/poetry/console/commands/init.py @@ -10,6 +10,8 @@ from typing import Tuple from typing import Union +import tomlkit + from cleo import option from tomlkit import inline_table @@ -22,7 +24,6 @@ class InitCommand(Command): - name = "init" description = ( "Creates a basic pyproject.toml file in the current directory." @@ -67,9 +68,26 @@ def handle(self): from poetry.utils._compat import Path from poetry.utils.env import SystemEnv + original_toml = None + if (Path.cwd() / "pyproject.toml").exists(): - self.line("A pyproject.toml file already exists.") - return 1 + with (Path.cwd() / "pyproject.toml").open() as toml_file: + original_toml = tomlkit.loads(toml_file.read()) + + try: + if original_toml["tool"]["poetry"]: + self.line( + "A pyproject.toml file with a poetry section already exists." + ) + return 1 + except KeyError: + pass + + if original_toml.get("build-system"): + self.line( + "A pyproject.toml file with a defined build-system already exists." + ) + return 1 vcs_config = GitConfig() @@ -213,6 +231,10 @@ def handle(self): with (Path.cwd() / "pyproject.toml").open("w", encoding="utf-8") as f: f.write(content) + if original_toml: + f.write("\n") + f.write(tomlkit.dumps(original_toml)) + def _determine_requirements( self, requires, allow_prereleases=False, source=None ): # type: (List[str], bool) -> List[Dict[str, str]] From 08f490eda49a95bf7e042b1f136d6e428496e86d Mon Sep 17 00:00:00 2001 From: finswimmer Date: Sun, 24 May 2020 15:09:15 +0200 Subject: [PATCH 2/8] append original toml during creation of poetry_content --- poetry/console/commands/init.py | 19 ++++++------------- poetry/layouts/layout.py | 9 +++++++-- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/poetry/console/commands/init.py b/poetry/console/commands/init.py index 6d0b1f3d8d6..3c66c46a837 100644 --- a/poetry/console/commands/init.py +++ b/poetry/console/commands/init.py @@ -74,14 +74,11 @@ def handle(self): with (Path.cwd() / "pyproject.toml").open() as toml_file: original_toml = tomlkit.loads(toml_file.read()) - try: - if original_toml["tool"]["poetry"]: - self.line( - "A pyproject.toml file with a poetry section already exists." - ) - return 1 - except KeyError: - pass + if original_toml.get("tool", {}).get("poetry"): + self.line( + "A pyproject.toml file with a poetry section already exists." + ) + return 1 if original_toml.get("build-system"): self.line( @@ -216,7 +213,7 @@ def handle(self): dev_dependencies=dev_requirements, ) - content = layout_.generate_poetry_content() + content = layout_.generate_poetry_content(original_toml) if self.io.is_interactive(): self.line("Generated file") self.line("") @@ -231,10 +228,6 @@ def handle(self): with (Path.cwd() / "pyproject.toml").open("w", encoding="utf-8") as f: f.write(content) - if original_toml: - f.write("\n") - f.write(tomlkit.dumps(original_toml)) - def _determine_requirements( self, requires, allow_prereleases=False, source=None ): # type: (List[str], bool) -> List[Dict[str, str]] diff --git a/poetry/layouts/layout.py b/poetry/layouts/layout.py index a7378c67c4c..dfe0db330ca 100644 --- a/poetry/layouts/layout.py +++ b/poetry/layouts/layout.py @@ -81,7 +81,7 @@ def create(self, path, with_tests=True): self._write_poetry(path) - def generate_poetry_content(self): + def generate_poetry_content(self, original_toml): template = POETRY_DEFAULT if self._license: template = POETRY_WITH_LICENSE @@ -114,7 +114,12 @@ def generate_poetry_content(self): content.add("build-system", build_system) - return dumps(content) + content = dumps(content) + + if original_toml: + content += "\n" + dumps(original_toml) + + return content def _create_default(self, path, src=True): raise NotImplementedError() From b16064bfa38f29eb612e0912c0a393d430b3dfa9 Mon Sep 17 00:00:00 2001 From: finswimmer Date: Sat, 6 Jun 2020 07:38:15 +0200 Subject: [PATCH 3/8] append instead of prepend --- poetry/layouts/layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poetry/layouts/layout.py b/poetry/layouts/layout.py index dfe0db330ca..4da0406b9e0 100644 --- a/poetry/layouts/layout.py +++ b/poetry/layouts/layout.py @@ -117,7 +117,7 @@ def generate_poetry_content(self, original_toml): content = dumps(content) if original_toml: - content += "\n" + dumps(original_toml) + content = dumps(original_toml) + "\n" + content return content From 45dcc2480cf35549f3e34b2dc0b7918ef8b891df Mon Sep 17 00:00:00 2001 From: finswimmer Date: Mon, 28 Sep 2020 06:27:29 +0200 Subject: [PATCH 4/8] new (console.commands.test_init): tests for init if pyproject.toml exists --- tests/console/commands/test_init.py | 82 ++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 18 deletions(-) diff --git a/tests/console/commands/test_init.py b/tests/console/commands/test_init.py index d367fbc8b8e..c64bc23316a 100644 --- a/tests/console/commands/test_init.py +++ b/tests/console/commands/test_init.py @@ -3,14 +3,19 @@ import pytest from poetry.utils._compat import Path +from poetry.utils._compat import decode from tests.helpers import get_package +@pytest.fixture +def source_dir(tmp_path): # type: (Path) -> Path + yield Path(tmp_path.as_posix()) + + @pytest.fixture(autouse=True) -def patches(mocker, mocked_open_files): - mocked_open_files.append("pyproject.toml") +def patches(mocker, source_dir): patch = mocker.patch("poetry.utils._compat.Path.cwd") - patch.return_value = Path(__file__).parent + patch.return_value = source_dir @pytest.fixture @@ -18,21 +23,26 @@ def tester(command_tester_factory): return command_tester_factory("init") -def test_basic_interactive(tester): - inputs = [ - "my-package", # Package name - "1.2.3", # Version - "This is a description", # Description - "n", # Author - "MIT", # License - "~2.7 || ^3.6", # Python - "n", # Interactive packages - "n", # Interactive dev packages - "\n", # Generate - ] - tester.execute(inputs="\n".join(inputs)) +@pytest.fixture +def init_basic_inputs(): + return "\n".join( + [ + "my-package", # Package name + "1.2.3", # Version + "This is a description", # Description + "n", # Author + "MIT", # License + "~2.7 || ^3.6", # Python + "n", # Interactive packages + "n", # Interactive dev packages + "\n", # Generate + ] + ) - expected = """\ + +@pytest.fixture() +def init_basic_toml(): + return """\ [tool.poetry] name = "my-package" version = "1.2.3" @@ -46,7 +56,10 @@ def test_basic_interactive(tester): [tool.poetry.dev-dependencies] """ - assert expected in tester.io.fetch_output() + +def test_basic_interactive(tester, init_basic_inputs, init_basic_toml): + tester.execute(inputs=init_basic_inputs) + assert init_basic_toml in tester.io.fetch_output() def test_interactive_with_dependencies(tester, repo): @@ -565,3 +578,36 @@ def test_add_package_with_extras_and_whitespace(tester): assert len(result[0]["extras"]) == 2 assert "postgresql" in result[0]["extras"] assert "sqlite" in result[0]["extras"] + + +def test_init_existing_pyproject_simple( + tester, source_dir, init_basic_inputs, init_basic_toml +): + pyproject_file = source_dir / "pyproject.toml" + existing_section = """ +[tool.black] +line-length = 88 +""" + pyproject_file.write_text(decode(existing_section)) + tester.execute(inputs=init_basic_inputs) + assert ( + "{}\n{}".format(existing_section, init_basic_toml) in pyproject_file.read_text() + ) + + +def test_init_existing_pyproject_with_build_system_fails( + tester, source_dir, init_basic_inputs +): + pyproject_file = source_dir / "pyproject.toml" + existing_section = """ +[build-system] +requires = ["setuptools >= 40.6.0", "wheel"] +build-backend = "setuptools.build_meta" +""" + pyproject_file.write_text(decode(existing_section)) + tester.execute(inputs=init_basic_inputs) + assert ( + tester.io.fetch_output().strip() + == "A pyproject.toml file with a defined build-system already exists." + ) + assert "{}".format(existing_section) in pyproject_file.read_text() From 744e18d89f44222a74f0cc9eebb44fb367a37b13 Mon Sep 17 00:00:00 2001 From: finswimmer Date: Tue, 29 Sep 2020 21:30:17 +0200 Subject: [PATCH 5/8] change (console.commands.test_init): make use of TOMLFile and PyProjectToml --- poetry/console/commands/init.py | 34 ++++++++++++++++----------------- poetry/layouts/layout.py | 11 ++++++++--- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/poetry/console/commands/init.py b/poetry/console/commands/init.py index 3c66c46a837..d8b70db3a18 100644 --- a/poetry/console/commands/init.py +++ b/poetry/console/commands/init.py @@ -10,11 +10,11 @@ from typing import Tuple from typing import Union -import tomlkit - from cleo import option from tomlkit import inline_table +from poetry.core.pyproject.toml import PyProjectTOML +from poetry.core.toml.file import TOMLFile from poetry.utils._compat import OrderedDict from poetry.utils._compat import Path from poetry.utils._compat import urlparse @@ -23,6 +23,9 @@ from .env_command import EnvCommand +# import tomlkit + + class InitCommand(Command): name = "init" description = ( @@ -68,23 +71,20 @@ def handle(self): from poetry.utils._compat import Path from poetry.utils.env import SystemEnv - original_toml = None + original_toml = TOMLFile(Path.cwd() / "pyproject.toml") - if (Path.cwd() / "pyproject.toml").exists(): - with (Path.cwd() / "pyproject.toml").open() as toml_file: - original_toml = tomlkit.loads(toml_file.read()) - - if original_toml.get("tool", {}).get("poetry"): - self.line( - "A pyproject.toml file with a poetry section already exists." - ) - return 1 + if original_toml.exists(): + if PyProjectTOML(original_toml.path).is_poetry_project(): + self.line( + "A pyproject.toml file with a poetry section already exists." + ) + return 1 - if original_toml.get("build-system"): - self.line( - "A pyproject.toml file with a defined build-system already exists." - ) - return 1 + if original_toml.read().get("build-system"): + self.line( + "A pyproject.toml file with a defined build-system already exists." + ) + return 1 vcs_config = GitConfig() diff --git a/poetry/layouts/layout.py b/poetry/layouts/layout.py index 4da0406b9e0..27afacca315 100644 --- a/poetry/layouts/layout.py +++ b/poetry/layouts/layout.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING + from tomlkit import dumps from tomlkit import loads from tomlkit import table @@ -5,6 +7,9 @@ from poetry.utils.helpers import module_name +if TYPE_CHECKING: + from poetry.core.toml.file import TOMLFile + TESTS_DEFAULT = u"""from {package_name} import __version__ @@ -81,7 +86,7 @@ def create(self, path, with_tests=True): self._write_poetry(path) - def generate_poetry_content(self, original_toml): + def generate_poetry_content(self, original_toml): # type: ("TOMLFile") -> str template = POETRY_DEFAULT if self._license: template = POETRY_WITH_LICENSE @@ -116,8 +121,8 @@ def generate_poetry_content(self, original_toml): content = dumps(content) - if original_toml: - content = dumps(original_toml) + "\n" + content + if original_toml.exists(): + content = dumps(original_toml.read()) + "\n" + content return content From 4b9ccb692893afd7ff0ba6a8151531a5109be6de Mon Sep 17 00:00:00 2001 From: finswimmer Date: Tue, 29 Sep 2020 21:31:45 +0200 Subject: [PATCH 6/8] fix (console.commands.test_init): remove commented out code --- poetry/console/commands/init.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/poetry/console/commands/init.py b/poetry/console/commands/init.py index d8b70db3a18..ccdd3bb3732 100644 --- a/poetry/console/commands/init.py +++ b/poetry/console/commands/init.py @@ -23,9 +23,6 @@ from .env_command import EnvCommand -# import tomlkit - - class InitCommand(Command): name = "init" description = ( From d49317ff9cb8c195511fb8bf1ab4e0eb3c56b644 Mon Sep 17 00:00:00 2001 From: finswimmer Date: Tue, 29 Sep 2020 21:42:41 +0200 Subject: [PATCH 7/8] fix (console.commands.init): use PyProjectToml only --- poetry/console/commands/init.py | 9 ++++----- poetry/layouts/layout.py | 8 ++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/poetry/console/commands/init.py b/poetry/console/commands/init.py index ccdd3bb3732..1d60e947a67 100644 --- a/poetry/console/commands/init.py +++ b/poetry/console/commands/init.py @@ -14,7 +14,6 @@ from tomlkit import inline_table from poetry.core.pyproject.toml import PyProjectTOML -from poetry.core.toml.file import TOMLFile from poetry.utils._compat import OrderedDict from poetry.utils._compat import Path from poetry.utils._compat import urlparse @@ -68,16 +67,16 @@ def handle(self): from poetry.utils._compat import Path from poetry.utils.env import SystemEnv - original_toml = TOMLFile(Path.cwd() / "pyproject.toml") + original_toml = PyProjectTOML(Path.cwd() / "pyproject.toml") - if original_toml.exists(): - if PyProjectTOML(original_toml.path).is_poetry_project(): + if original_toml.file.exists(): + if original_toml.is_poetry_project(): self.line( "A pyproject.toml file with a poetry section already exists." ) return 1 - if original_toml.read().get("build-system"): + if original_toml.data.get("build-system"): self.line( "A pyproject.toml file with a defined build-system already exists." ) diff --git a/poetry/layouts/layout.py b/poetry/layouts/layout.py index 27afacca315..1d0feccc224 100644 --- a/poetry/layouts/layout.py +++ b/poetry/layouts/layout.py @@ -8,7 +8,7 @@ if TYPE_CHECKING: - from poetry.core.toml.file import TOMLFile + from poetry.core.pyproject.toml import PyProjectTOML TESTS_DEFAULT = u"""from {package_name} import __version__ @@ -86,7 +86,7 @@ def create(self, path, with_tests=True): self._write_poetry(path) - def generate_poetry_content(self, original_toml): # type: ("TOMLFile") -> str + def generate_poetry_content(self, original_toml): # type: ("PyProjectTOML") -> str template = POETRY_DEFAULT if self._license: template = POETRY_WITH_LICENSE @@ -121,8 +121,8 @@ def generate_poetry_content(self, original_toml): # type: ("TOMLFile") -> str content = dumps(content) - if original_toml.exists(): - content = dumps(original_toml.read()) + "\n" + content + if original_toml.file.exists(): + content = dumps(original_toml.data) + "\n" + content return content From b70231ce25f1d7de9fbaeb6eb5e8f3453c6019bc Mon Sep 17 00:00:00 2001 From: finswimmer Date: Tue, 29 Sep 2020 22:05:27 +0200 Subject: [PATCH 8/8] change (console.commands.init): rename original_toml to pyproject --- poetry/console/commands/init.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry/console/commands/init.py b/poetry/console/commands/init.py index 1d60e947a67..8f96b12ca18 100644 --- a/poetry/console/commands/init.py +++ b/poetry/console/commands/init.py @@ -67,16 +67,16 @@ def handle(self): from poetry.utils._compat import Path from poetry.utils.env import SystemEnv - original_toml = PyProjectTOML(Path.cwd() / "pyproject.toml") + pyproject = PyProjectTOML(Path.cwd() / "pyproject.toml") - if original_toml.file.exists(): - if original_toml.is_poetry_project(): + if pyproject.file.exists(): + if pyproject.is_poetry_project(): self.line( "A pyproject.toml file with a poetry section already exists." ) return 1 - if original_toml.data.get("build-system"): + if pyproject.data.get("build-system"): self.line( "A pyproject.toml file with a defined build-system already exists." ) @@ -209,7 +209,7 @@ def handle(self): dev_dependencies=dev_requirements, ) - content = layout_.generate_poetry_content(original_toml) + content = layout_.generate_poetry_content(pyproject) if self.io.is_interactive(): self.line("Generated file") self.line("")