Skip to content

Validate package name in create - #119

Open
kunalKumar-13 wants to merge 2 commits into
plone:masterfrom
kunalKumar-13:fix/72-validate-package-name
Open

Validate package name in create#119
kunalKumar-13 wants to merge 2 commits into
plone:masterfrom
kunalKumar-13:fix/72-validate-package-name

Conversation

@kunalKumar-13

Copy link
Copy Markdown

Closes #72.

plonecli create addon collective.new-testcase generated a package that could not be installed — each dotted part becomes a Python package directory, so a dash produced an invalid module name and buildout failed later with an opaque EntryPoint error.

create now rejects the name up front:

Error: Invalid value for NAME: 'collective.new-testcase' is not a valid package name:
'new-testcase' is not a valid Python identifier. Try 'collective.new_testcase'.

The underscore suggestion only appears when it would actually produce a valid name, so collective.2foo gets the error without a misleading hint.

Went with rejecting rather than normalising, per the issue title — silently rewriting the name the user typed seemed worse than telling them. Happy to switch to normalisation if you'd rather have that.

One thing worth flagging: NAME can be a target path, not just a bare name — the existing tests pass things like /tmp/.../my.addon. Validation therefore only checks the last path component. I only found this because the existing suite caught it.

14 tests added. Full suite: 230 passed, 16 skipped. ruff check and ruff format --check clean on both files.

Each dotted part becomes a Python package directory, so a dash or a leading
digit produced a package that could not be installed. Fail with a clear
message instead, suggesting the underscore form where that would be valid.

Only the last path component is checked, since NAME may be a target path.

Closes plone#72
Copilot AI lite review requested due to automatic review settings September 2, 2026 18:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The new validation’s error message is inaccurate for keyword-based failures (and awkward for multiple invalid parts), which is user-facing and should be corrected before release.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR adds upfront validation for plonecli create package names to prevent generating projects whose dotted components can’t become importable Python package directories (e.g., components containing -, starting with digits, or being Python keywords), addressing issue #72.

Changes:

  • Add _validate_package_name() and invoke it at the start of the create command.
  • Provide a targeted underscore suggestion only when it results in a valid dotted name.
  • Add a dedicated test module covering valid/invalid names, path inputs, and suggestion behavior; update CHANGES.md.
File summaries
File Description
plonecli/cli.py Introduces and wires in package-name validation for create, including improved CLI error feedback.
tests/test_package_name_validation.py Adds unit tests for name/path validation and messaging behavior.
CHANGES.md Documents the behavior change for the upcoming release.
Review details

Suppressed comments (1)

plonecli/cli.py:118

  • The error message says the offending parts "is not a valid Python identifier", but bad also includes reserved keywords (e.g. class), which are valid identifiers. Also, if multiple parts are invalid, the singular wording becomes grammatically incorrect; consider building the message with proper pluralization and explicit keyword mention.
    raise click.BadParameter(
        f"{name!r} is not a valid package name: "
        f"{', '.join(repr(p) for p in bad)} is not a valid Python identifier.{hint}",
        param_hint="NAME",
    )
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread plonecli/cli.py Outdated


def _validate_package_name(name):
"""Reject names whose dotted parts are not valid Python identifiers.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch, fixed in 2a39588. The message now distinguishes the two cases: when every offending part is a keyword it says 'class' is a Python keyword rather than calling it an invalid identifier, which was misleading because class is a valid identifier and only reserved. The docstring says "a dash, a leading digit or a reserved word" now, and there's a test pinning the wording.

Same commit also fixes something bigger that the scaffolding job was catching: NAME is the output directory, not always a package name. backend_addon asks a package_name question defaulting to dst_path.name, but zope-setup asks project_name, where a hyphen is ordinary — plonecli create zope-setup my-project is in the README and this PR was rejecting it. The validator now checks the value that actually becomes the package name (an explicit -d package_name= when given, the directory otherwise) and only for templates that declare such a question, read from their copier.yml rather than a hardcoded list.

evals/scaffolding --quick went from 21 failures to 0.

NAME is the output directory -- run_create() takes it as target_name and hands
it to copier as dst_path. Only some templates turn it into a Python package:
backend_addon asks a package_name question defaulting to dst_path.name, and
addon is a composite that includes it. zope-setup asks project_name instead,
where a hyphen is ordinary and documented (`plonecli create zope-setup
my-project`, README).

Validating NAME unconditionally therefore rejected legitimate input. It refused
that README example, and it failed 21 of the scaffolding evaluations in --quick
and 26 in --ci-validation, every one of which scaffolds into a hyphenated
workspace directory.

Validate the value that will actually become the package name -- an explicit
`-d package_name=` when given, the directory name otherwise -- and only for
templates that ask for one. Whether a template asks is read from its copier.yml
rather than hardcoded, so a template added later is classified by what it
declares. A template that cannot be read is treated as not asking: refusing to
scaffold because a lookup failed is worse than the bug this guards against.

Issue plone#72's case is unaffected -- `create addon collective.new-testcase` is
still rejected.

Also: say "is a Python keyword" rather than "is not a valid Python identifier"
when every offending part is a keyword. `class` IS a valid identifier, it is
reserved, and the old wording sent the reader looking for a typo that was not
there.

evals --quick: 21 failures before, 0 after. 235 tests pass, ruff clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Disallow or Warn '-' in addon names

2 participants