Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/poetry/console/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

from cleo.helpers import option
from packaging.utils import canonicalize_name
from poetry.core.constraints.version import parse_constraint
from poetry.core.constraints.version.exceptions import ParseConstraintError
from tomlkit import inline_table

from poetry.console.commands.command import Command
Expand Down Expand Up @@ -395,6 +397,14 @@ def _determine_requirements(
f"Using version <b>{package_constraint}</b> for"
f" <c1>{package}</c1>"
)
else:
try:
parse_constraint(package_constraint)
except ParseConstraintError:
self.line_error(
"<error>Invalid version constraint. Please enter a valid version specifier.</error>"
)
continue

constraint["version"] = package_constraint

Expand Down
35 changes: 35 additions & 0 deletions tests/console/commands/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -1215,3 +1215,38 @@ def test_init_does_not_add_readme_key_when_readme_missing(
# Assert
pyproject = (tmp_path / "pyproject.toml").read_text(encoding="utf-8")
assert "readme =" not in pyproject


def test_interactive_rejects_invalid_version_constraint(
tester: CommandTester, repo: TestRepository
) -> None:
repo.add_package(get_package("pendulum", "2.0.0"))

inputs = [
"my-package", # Package name
"1.0.0", # Version
"Desc", # Description
"n", # Author
Comment on lines +1220 to +1229
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Also assert that the flow reprompts for the version constraint after an invalid entry

The test currently checks only that an error is shown and that a valid constraint is eventually accepted. To fully cover the regression, please also assert that the version-constraint prompt (or surrounding question text) is shown again after the invalid input—e.g., by checking that it appears twice—so we verify the loop behavior, not just the error output.

Suggested implementation:

def test_interactive_rejects_invalid_version_constraint(
    tester: CommandTester, repo: TestRepository
) -> None:
    repo.add_package(get_package("pendulum", "2.0.0"))

    inputs = [
        "my-package",  # Package name
        "1.0.0",  # Version
        "Desc",  # Description
        "n",  # Author
        "MIT",  # License
        # NOTE: the rest of the input sequence (invalid constraint, valid constraint, etc.)
        # should remain as it is in the current test implementation.

To implement your review comment, you should extend the test so that it explicitly asserts that the version-constraint question is shown again after an invalid entry. The key is to assert that the prompt (or its surrounding question text) appears at least twice in the captured output.

Because I cannot see the rest of the test body (how the command is executed and how output is captured), here is the concrete code you should add after the command is run and after any existing assertions about the error message / successful acceptance of the valid constraint:

    # Existing lines, for context only – do NOT duplicate:
    # tester.execute("init", input="\n".join(inputs))
    # output = tester.io.fetch_output()
    # assert "Invalid version constraint" in output
    # assert "pendulum (^2.0.0)" in output

    # New assertion to verify the loop / re-prompt behavior:
    # We assert that the version-constraint prompt (or its surrounding question text)
    # appears at least twice in the output: once before the invalid constraint,
    # and once again after the error message when the user is re-prompted.
    output = tester.io.fetch_output()
    assert output.count("Version constraint") >= 2

You will need to adapt "Version constraint" to match the exact prompt text used by the interactive init command in this project (for example, it might be something like "Version constraint (leave blank to use latest)" or similar). The important bits are:

  1. Call tester.io.fetch_output() (or the equivalent in your test harness) after running the command.
  2. Use .count(<prompt_substring>) to assert that the prompt appears twice: assert output.count(<prompt_substring>) >= 2.
  3. Place this assertion after the existing assertions that verify the error message and that the valid constraint is eventually accepted.

If the output API is different (for example, tester.io.fetch_output() is not available), replace it with the appropriate mechanism already used elsewhere in tests/console/commands/test_init.py to inspect interactive output.

"MIT", # License
">=3.8", # Python
"", # Interactive packages
"pendulum", # Search package
"0", # Select first result
"isort", # INVALID version constraint
">=2.0.0", # VALID version constraint
"", # Stop searching for packages
"", # Interactive dev packages
"",
"\n", # Generate
]

tester.execute(inputs="\n".join(inputs))

output = tester.io.fetch_output()
error = tester.io.fetch_error()

# Must show validation error
assert "Invalid version constraint" in error

# Must use valid constraint
assert "pendulum (>=2.0.0" in output
Comment on lines +1251 to +1252
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Prefer asserting against the generated pyproject to prove the constraint is persisted correctly

In addition to checking the CLI output, please also read the generated pyproject.toml and assert that pendulum is recorded with a >=2.0.0 constraint. That will verify the validated constraint is actually persisted, not just printed.

Suggested implementation:

    # Must show validation error
    assert "Invalid version constraint" in error

    # Must use valid constraint in CLI output
    assert "pendulum (>=2.0.0" in output

    # Must persist validated constraint to pyproject.toml
    pyproject_content = (tester.path / "pyproject.toml").read_text(encoding="utf-8")
    assert 'pendulum = ">=2.0.0"' in pyproject_content
  • If the ProjectTester (or equivalent) helper does not expose the project root as tester.path, adjust the attribute to whatever is used elsewhere in the tests (for example tester.project_path or tester.tmpdir).
  • If the rest of the test suite prefers parsing pyproject.toml instead of string matching, you can replace the last assertion with something like:
    • data = tomllib.loads(pyproject_content) (or tomli.loads), then assert on the appropriate dependency table entry (e.g. data["project"]["dependencies"] or data["tool"]["poetry"]["dependencies"]["pendulum"] == ">=2.0.0"), matching existing conventions in this repo.

Loading