diff --git a/rsconnect/environment.py b/rsconnect/environment.py index 85bd1037..a76f14e2 100644 --- a/rsconnect/environment.py +++ b/rsconnect/environment.py @@ -140,7 +140,10 @@ def create_python_environment( _warn_on_ignored_manifest(directory) _warn_if_environment_directory(directory) - python_version_requirement = pyproject.detect_python_version_requirement(directory) + try: + python_version_requirement = pyproject.detect_python_version_requirement(directory) + except pyproject.TOMLDecodeError as err: + raise RSConnectException(f"Error reading pyproject.toml: {err}") from err _warn_on_missing_python_version(python_version_requirement) _check_requirements_file(directory, requirements_file) diff --git a/tests/test_environment.py b/tests/test_environment.py index cbf364b9..f1bef954 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -293,6 +293,16 @@ def test_is_not_executable(self): class TestPythonVersionRequirements: + def test_malformed_pyproject(self, tmp_path): + (tmp_path / "pyproject.toml").write_text('[project\nname = "x"\n') + (tmp_path / "requirements.txt").write_text("flask\n") + + with pytest.raises(RSConnectException, match="Error reading pyproject.toml:") as exc_info: + Environment.create_python_environment(str(tmp_path)) + + assert isinstance(exc_info.value.__cause__, rsconnect.environment.pyproject.TOMLDecodeError) + assert str(exc_info.value.__cause__) in str(exc_info.value) + def test_pyproject_toml(self): env = Environment.create_python_environment( os.path.join(TESTDATA, "python-project", "using_pyproject"), requirements_file=None diff --git a/tests/test_main.py b/tests/test_main.py index 94a59c2f..65dcf1e9 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -2154,6 +2154,21 @@ def test_no_package_json(self, tmp_path): class TestWriteManifestFramework: + def test_malformed_pyproject_with_requirements_file(self, tmp_path): + (tmp_path / "app.py").write_text("app = object()\n") + (tmp_path / "requirements.txt").write_text("flask\n") + (tmp_path / "pyproject.toml").write_text('[project\nname = "x"\n') + + runner = CliRunner() + result = runner.invoke(cli, ["write-manifest", "api", str(tmp_path)]) + + assert result.exit_code == 1 + assert "Error: Error reading pyproject.toml:" in result.output + assert "line 1" in result.output + assert "Traceback" not in result.output + assert "Internal error" not in result.output + assert not (tmp_path / "manifest.json").exists() + @pytest.mark.parametrize("existing_requirements", [False, True]) def test_force_generate_requirements(self, tmp_path, existing_requirements): (tmp_path / "app.py").write_text("app = object()\n")