Issues found while scaffolding the derico.todos addon with plonecli 7.0.0b9
and copier-templates @ 12bcbdb (Plone 6.1.2). Grouped by the repo that owns
the fix.
- plonecli: https://github.com/plone/plonecli
- templates: https://github.com/plone/copier-templates
Re-scaffolded derico.todos (Todos container + Todo item + views + vocabulary +
restapi_service, Plone 6.2.0). Status of the issues below in b10:
Fixed in b10 ✅
- plonecli #1 — composite
create addonnow runs non-interactively:.gitignoreisoverwrited andpyproject.toml/README.mdareskipped, noInteractiveSessionError. - templates #3 — generated
content_type/viewtests now request the correctintegrationfixture (notintegration_testing). - templates #4 —
content_typetests now usequeryUtility(IDexterityFTI, name=...)(the interface, not theDexterityFTIclass) and pass. - templates #6 —
viewhook now writes a secondbrowser:pagewith the samename="view"but a differentfor=(both Todos and Todoviews registered).
Still broken in b10 ❌
- templates #5 —
content_typetests still create the type in the portal root and ignoreglobal_allow=false. For theTodoitem (addable only insideTodos)test_factory/test_adding/test_deletingfail withInvalidParameterError: Disallowed subobject type: Todo. Fix must create aparent_content_typecontainer first and add the item inside it. - plonecli #2 / templates #2 — the
zope-setupcreate_initial_instancehook still shells out to a barecopier, which is not on PATH when plonecli is auv tool. Had to runcreatewithPATH="$(dirname $(command -v plonecli))/../...plonecli/bin:$PATH"so thecopierconsole script from plonecli's own venv is found. - notes —
plonecli test(uv run invoke test) still can't find pytest; thedevextra lacks it. Must runuv run --extra test pytest.
New finding (b10)
- templates (backend_addon) — the generated
.gitignoreignores*.pot(line ~50), but the addon shipssrc/<pkg>/locales/<domain>.potas the canonical message catalog that the per-language.pofiles derive from (i18ndudeupdate.sh). The.potshould be tracked;*.potshould be dropped from.gitignore(or the locales.potforce-added). - templates (backend_addon) — the shipped
locales/update.pyhelper trips the project's own ruff config: 3×S602(subprocess.call(..., shell=True)) and anE501long line. Either rewrite the calls withoutshell=Trueor addlocales/update.pyto[tool.ruff.lint.per-file-ignores]so a fresh addon passesruff checkout of the box.
-
plonecli create addon <name>(compositebackend_addon→zope-setup) fails non-interactively: the second step hits files the first step already wrote (.gitignore,.github/workflows/ci.yml) and copier raisesInteractiveSessionError: Consider using --overwrite. - Where:
plonecli/templates.py→run_create()/run_add()callrun_copy(...)withoutoverwrite=True;plonecli/cli.pycreate/add/setupexpose no--overwrite. - Fix options:
- Pass
overwrite=Truefor composite sub-steps (the second template legitimately layers onto the first), and/or - Add an
--overwriteflag tocreate/addand a non-interactive path (--defaults/-d/--overwrite) tosetup(it currently takes no options and only runs interactively, requiring a clean git tree).
- Pass
- Note: also see templates item #1 (
.gitignoreshould be in_skip_if_exists) — the two fixes are complementary.
- The
zope-setupcreate_initial_instancehook shells out to a barecopierexecutable. When plonecli is installed as auv tool, only plonecli's own entry point is put on PATH — thecopierconsole script from its dependencies is not — so the hook dies withFileNotFoundError: 'copier'. After installing it, a second failure appears:No module named 'copier_template_extensions'. - User intent: copier is already a library dependency of plonecli, so the
copierCLI should be guaranteed available rather than assumed on PATH. - Fix options:
- Ensure
copierandcopier-template-extensionsare declared deps and that the CLI is reachable (e.g. document / enforceuv tool install plonecli --with copier --with copier-template-extensions, or expose the script), and/or - Make the hooks invoke copier through a guaranteed interpreter instead of a bare PATH lookup — see templates item #2.
- Ensure
- Workaround used:
uv tool install copier --with copier-template-extensions.
-
zope-setup/copier.ymllists onlypyproject.tomlandREADME.mdunder_skip_if_exists, butbackend_addonalso writes.gitignoreand.github/workflows/ci.yml. Layeringzope-setupover an existingbackend_addontherefore conflicts on those files (root cause of plonecli item #1). - Fix: add
.gitignore(and the.github/workflows/ci.ymlit would overwrite) to_skip_if_exists, or otherwise reconcile the two templates' shared files.
- Where:
zope-setup/copier_hooks.py(create_initial_instance, ~L87–110) buildscmd = ["copier", "copy", "--trust", ...]andsubprocess.run(cmd). - Invoke copier in a way that does not depend on a bare
copierbeing on PATH and that includes the required Jinja extension, e.g.python -m copier ...(same interpreter) oruv run --with copier --with copier-template-extensions copier copy ....
- Where:
content_type/template/tests/test_ct_{{content_type_module}}.py.jinjaview/template/tests/test_view_{{view_module}}.py.jinja
- They use
def _setup(self, integration_testing): self.portal = integration_testing["portal"], butpytest-ploneprovides a fixture namedintegration(notintegration_testing). Tests error withfixture 'integration_testing' not found. - Fix: rename the fixture parameter/usages to
integration. - Note:
backend_addon's owntests/test_setup.pyalready uses the correctintegrationfixture — only the sub-template tests are wrong.
- Where:
content_type/template/tests/test_ct_{{content_type_module}}.py.jinja - Uses
from plone.dexterity.fti import DexterityFTIandqueryUtility(DexterityFTI, name="<Type>"), which returnsNone(DexterityFTIis the class, not the lookup interface). - Fix: use
from plone.dexterity.interfaces import IDexterityFTI+queryUtility(IDexterityFTI, name=...), orportal.portal_types.get("<Type>").
- Where:
content_type/template/tests/test_ct_{{content_type_module}}.py.jinja -
test_factory/test_adding/test_deletingalways create the type in the portal root. For a type withglobal_allow=false(added under a specific parent) this is not addable in the root and the tests fail. - Fix: when
global_allowis false, create a parent container ofparent_content_typefirst and create the item inside it (the template already knowsparent_content_type_resolved). Consider also asserting the type appears in the parent'sallowedContentTypes().
- Where:
view/copier_hooks.py→extend_configure_zcml(..., identifying_attr="name", identifying_value=view_name, ...). - Registering a second view with the same
name(e.g. two content-typeviews namedview) but a differentfor=is silently skipped:browser:page with name='view' already exists .... The second registration is never written. - Fix: dedupe by the composite key (
nameandfor) so distinctfor=registrations sharing anameare both emitted (extendextend_configure_zcmlto accept multiple identifying attributes, or pass a composite identifier from the view hook).
- The
devoptional-dependency extra only containsinvoke/watchdog, soplonecli test(uv run invoke test) fails withFailed to spawn: invokeunless that extra is synced. Either haveinvoke testrun under the right extra, or documentuv run --extra test pytest. plone_versionis asked once for the composite butbackend_addonexpects a minor (6.1) whilezope-setupexpects a full version (6.1.2); a single-d plone_version=...cannot satisfy both. Consider deriving the zope-setup full version from the backend minor (or vice versa) so the composite stays consistent.