Skip to content

Commit

Permalink
init: reuse existing pyproject.toml when safe (#2448)
Browse files Browse the repository at this point in the history
At the moment a `poetry init` will fail, if a pyproject.toml already
exists. This change ensures pyproject.toml is reused if no build-system
has already been defined or poetry is not already configured.

Resolves: #1639
  • Loading branch information
finswimmer authored Sep 29, 2020
1 parent e49f093 commit 30a9b13
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 25 deletions.
21 changes: 16 additions & 5 deletions poetry/console/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from cleo import option
from tomlkit import inline_table

from poetry.core.pyproject.toml import PyProjectTOML
from poetry.utils._compat import OrderedDict
from poetry.utils._compat import Path
from poetry.utils._compat import urlparse
Expand All @@ -22,7 +23,6 @@


class InitCommand(Command):

name = "init"
description = (
"Creates a basic <comment>pyproject.toml</> file in the current directory."
Expand Down Expand Up @@ -67,9 +67,20 @@ def handle(self):
from poetry.utils._compat import Path
from poetry.utils.env import SystemEnv

if (Path.cwd() / "pyproject.toml").exists():
self.line("<error>A pyproject.toml file already exists.</error>")
return 1
pyproject = PyProjectTOML(Path.cwd() / "pyproject.toml")

if pyproject.file.exists():
if pyproject.is_poetry_project():
self.line(
"<error>A pyproject.toml file with a poetry section already exists.</error>"
)
return 1

if pyproject.data.get("build-system"):
self.line(
"<error>A pyproject.toml file with a defined build-system already exists.</error>"
)
return 1

vcs_config = GitConfig()

Expand Down Expand Up @@ -198,7 +209,7 @@ def handle(self):
dev_dependencies=dev_requirements,
)

content = layout_.generate_poetry_content()
content = layout_.generate_poetry_content(pyproject)
if self.io.is_interactive():
self.line("<info>Generated file</info>")
self.line("")
Expand Down
14 changes: 12 additions & 2 deletions poetry/layouts/layout.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from typing import TYPE_CHECKING

from tomlkit import dumps
from tomlkit import loads
from tomlkit import table

from poetry.utils.helpers import module_name


if TYPE_CHECKING:
from poetry.core.pyproject.toml import PyProjectTOML

TESTS_DEFAULT = u"""from {package_name} import __version__
Expand Down Expand Up @@ -81,7 +86,7 @@ def create(self, path, with_tests=True):

self._write_poetry(path)

def generate_poetry_content(self):
def generate_poetry_content(self, original_toml): # type: ("PyProjectTOML") -> str
template = POETRY_DEFAULT
if self._license:
template = POETRY_WITH_LICENSE
Expand Down Expand Up @@ -114,7 +119,12 @@ def generate_poetry_content(self):

content.add("build-system", build_system)

return dumps(content)
content = dumps(content)

if original_toml.file.exists():
content = dumps(original_toml.data) + "\n" + content

return content

def _create_default(self, path, src=True):
raise NotImplementedError()
Expand Down
82 changes: 64 additions & 18 deletions tests/console/commands/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,46 @@
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
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"
Expand All @@ -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):
Expand Down Expand Up @@ -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()

0 comments on commit 30a9b13

Please sign in to comment.