Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2 - Catch problems with [tool.poetry.scripts] entries #8898

Merged
merged 9 commits into from
Feb 10, 2024
20 changes: 19 additions & 1 deletion src/poetry/masonry/builders/editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,25 @@ def _add_scripts(self) -> list[Path]:
for script in scripts:
name, script_with_extras = script.split(" = ")
script_without_extras = script_with_extras.split("[")[0]
module, callable_ = script_without_extras.split(":")
try:
module, callable_ = script_without_extras.split(":")
except ValueError as exc:
msg = (
f"Bad script ({name}): script needs to specify a function within a"
" module like: module(.submodule):function\nInstead got:"
f" {script_with_extras}"
)
if "not enough values" in str(exc):
msg += (
"\nHint: If the script depends on module-level code, try"
" wrapping it in a main() function and modifying your script"
f' like:\n{name} = "{script_with_extras}:main"'
)
elif "too many values" in str(exc):
msg += '\nToo many ":" found!'

raise ValueError(msg)

callable_holder = callable_.split(".", 1)[0]

script_file = scripts_path.joinpath(name)
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/bad_scripts_project/no_colon/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
My Package
==========
32 changes: 32 additions & 0 deletions tests/fixtures/bad_scripts_project/no_colon/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[tool.poetry]
name = "simple-project"
version = "1.2.3"
description = "Some description."
authors = [
"Sébastien Eustace <sebastien@eustace.io>"
]
license = "MIT"

readme = ["README.rst"]

homepage = "https://python-poetry.org"
repository = "https://github.com/python-poetry/poetry"
documentation = "https://python-poetry.org/docs"

keywords = ["packaging", "dependency", "poetry"]

classifiers = [
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Libraries :: Python Modules"
]

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.4"

[tool.poetry.scripts]
foo = "bar.bin.foo"

[build-system]
requires = ["poetry-core>=1.1.0a7"]
build-backend = "poetry.core.masonry.api"
Empty file.
2 changes: 2 additions & 0 deletions tests/fixtures/bad_scripts_project/too_many_colon/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
My Package
==========
33 changes: 33 additions & 0 deletions tests/fixtures/bad_scripts_project/too_many_colon/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[tool.poetry]
name = "simple-project"
version = "1.2.3"
description = "Some description."
authors = [
"Sébastien Eustace <sebastien@eustace.io>"
]
license = "MIT"

readme = ["README.rst"]

homepage = "https://python-poetry.org"
repository = "https://github.com/python-poetry/poetry"
documentation = "https://python-poetry.org/docs"

keywords = ["packaging", "dependency", "poetry"]

classifiers = [
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Libraries :: Python Modules"
]

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.4"

[tool.poetry.scripts]
foo = "foo::bar"


[build-system]
requires = ["poetry-core>=1.1.0a7"]
build-backend = "poetry.core.masonry.api"
41 changes: 41 additions & 0 deletions tests/masonry/builders/test_editable_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ def tmp_venv(tmp_path: Path, env_manager: EnvManager) -> Iterator[VirtualEnv]:
shutil.rmtree(str(venv.path))


@pytest.fixture()
def bad_scripts_no_colon(fixture_dir: FixtureDirGetter) -> Poetry:
poetry = Factory().create_poetry(fixture_dir("bad_scripts_project/no_colon"))

return poetry


@pytest.fixture()
def bad_scripts_too_many_colon(fixture_dir: FixtureDirGetter) -> Poetry:
poetry = Factory().create_poetry(fixture_dir("bad_scripts_project/too_many_colon"))

return poetry


def test_builder_installs_proper_files_for_standard_packages(
simple_poetry: Poetry, tmp_venv: VirtualEnv
) -> None:
Expand Down Expand Up @@ -340,3 +354,30 @@ def test_builder_should_execute_build_scripts(
assert [
["python", str(extended_without_setup_poetry.file.path.parent / "build.py")]
] == env.executed


def test_builder_catches_bad_scripts_no_colon(
bad_scripts_no_colon: Poetry, tmp_venv: VirtualEnv
) -> None:
builder = EditableBuilder(bad_scripts_no_colon, tmp_venv, NullIO())
with pytest.raises(ValueError, match=r"Bad script.*") as e:
builder.build()
msg = str(e.value)
# We should print out the problematic script entry
assert "bar.bin.foo" in msg
# and some hint about what to do
assert "Hint:" in msg
assert 'foo = "bar.bin.foo:main"' in msg


def test_builder_catches_bad_scripts_too_many_colon(
bad_scripts_too_many_colon: Poetry, tmp_venv: VirtualEnv
) -> None:
builder = EditableBuilder(bad_scripts_too_many_colon, tmp_venv, NullIO())
with pytest.raises(ValueError, match=r"Bad script.*") as e:
builder.build()
msg = str(e.value)
# We should print out the problematic script entry
assert "foo::bar" in msg
# and some hint about what is wrong
assert "Too many" in msg
Loading