diff --git a/src/poetry/console/commands/install.py b/src/poetry/console/commands/install.py index cc6e22eb624..8e716caa2b0 100644 --- a/src/poetry/console/commands/install.py +++ b/src/poetry/console/commands/install.py @@ -155,14 +155,6 @@ def handle(self) -> int: if self.option("no-root"): return 0 - try: - builder = EditableBuilder(self.poetry, self.env, self.io) - except ModuleOrPackageNotFound: - # This is likely due to the fact that the project is an application - # not following the structure expected by Poetry - # If this is a true error it will be picked up later by build anyway. - return 0 - log_install = ( "Installing the current project:" f" {self.poetry.package.pretty_name}" @@ -178,7 +170,26 @@ def handle(self) -> int: self.line("") return 0 - builder.build() + # Prior to https://github.com/python-poetry/poetry-core/pull/629 + # the existence of a module/package was checked when creating the + # EditableBuilder. Afterwards, the existence is checked after + # executing the build script (if there is one), + # i.e. during EditableBuilder.build(). + try: + builder = EditableBuilder(self.poetry, self.env, self.io) + builder.build() + except (ModuleOrPackageNotFound, FileNotFoundError) as e: + # This is likely due to the fact that the project is an application + # not following the structure expected by Poetry. + # No need for an editable install in this case. + self.line("") + self.line_error( + f"The current project could not be installed: {e}\n" + "If you do not want to install the current project" + " use --no-root", + style="warning", + ) + return 0 if overwrite: self.overwrite(log_install.format(tag="success")) diff --git a/tests/console/commands/test_install.py b/tests/console/commands/test_install.py index bf3c819552a..bf0789c8616 100644 --- a/tests/console/commands/test_install.py +++ b/tests/console/commands/test_install.py @@ -33,7 +33,6 @@ "Python Poetry " ] license = "MIT" -readme = "README.rst" [tool.poetry.dependencies] python = "~2.7 || ^3.4" @@ -348,9 +347,9 @@ def test_remove_untracked_outputs_deprecation_warning( assert tester.status_code == 0 assert ( - tester.io.fetch_error() - == "The `--remove-untracked` option is deprecated, use the `--sync` option" + "The `--remove-untracked` option is deprecated, use the `--sync` option" " instead.\n" + in tester.io.fetch_error() ) @@ -417,6 +416,38 @@ def test_install_logs_output_decorated( assert tester.io.fetch_output() == expected +@pytest.mark.parametrize("with_root", [True]) +@pytest.mark.parametrize("error", ["module", "readme", ""]) +def test_install_warning_corrupt_root( + command_tester_factory: CommandTesterFactory, + project_factory: ProjectFactory, + with_root: bool, + error: str, +) -> None: + name = "corrupt" + content = f"""\ +[tool.poetry] +name = "{name}" +version = "1.2.3" +description = "" +authors = [] +""" + if error == "readme": + content += 'readme = "missing_readme.md"\n' + poetry = project_factory(name=name, pyproject_content=content) + if error != "module": + (poetry.pyproject_path.parent / f"{name}.py").touch() + + tester = command_tester_factory("install", poetry=poetry) + tester.execute("" if with_root else "--no-root") + + assert tester.status_code == 0 + if with_root and error: + assert "The current project could not be installed: " in tester.io.fetch_error() + else: + assert tester.io.fetch_error() == "" + + @pytest.mark.parametrize("options", ["", "--without dev"]) @pytest.mark.parametrize( "project", ["missing_directory_dependency", "missing_file_dependency"]