Add a validator#
Validators in Cookieplone check user input at prompt time.
They live in cookieplone/validators/__init__.py and return bool (True means the value is valid).
Understand the contract#
A validator is a plain function that accepts a single str value and returns bool:
def my_validator(value: str) -> bool:
"""Return True if value passes the check."""
return bool(value)
Return
True→ the value is accepted.Return
False→ the prompt repeats and asks the user to try again.
Add the validator function#
Open cookieplone/validators/__init__.py.
Add the new function, following the existing pattern:
def semver(value: str) -> bool:
"""Validate that value is a valid SemVer string (MAJOR.MINOR.PATCH)."""
import re
pattern = r"^\d+\.\d+\.\d+$"
return bool(re.match(pattern, value))
If the underlying logic is non-trivial, add a helper to cookieplone/utils/validators.py and call it from here (following the pattern of hostname, python_package_name, and others).
Wire the validator to a field name (optional)#
If the new validator applies to a field that appears in many templates by name,
add it to DEFAULT_VALIDATORS in cookieplone/settings.py:
DEFAULT_VALIDATORS = {
"plone_version": "cookieplone.validators.plone_version",
"volto_version": "cookieplone.validators.volto_version",
"python_package_name": "cookieplone.validators.python_package_name",
"hostname": "cookieplone.validators.hostname",
"language_code": "cookieplone.validators.language_code",
"semver_field": "cookieplone.validators.semver", # new entry
}
Any template field named semver_field then runs semver automatically without any extra configuration.
Template authors can also reference it explicitly via the validator key in cookieplone.json:
{
"version": "2.0",
"properties": {
"api_version": {
"type": "string",
"title": "API version",
"default": "1.0.0",
"validator": "cookieplone.validators.semver"
}
}
}
Write a test#
Add a test in tests/validators/:
# tests/validators/test_semver.py
from cookieplone.validators import semver
def test_semver_valid():
assert semver("1.2.3") is True
def test_semver_invalid_missing_patch():
assert semver("1.2") is False
def test_semver_invalid_text():
assert semver("latest") is False
def test_semver_empty():
assert semver("") is False
Run the test:
uv run pytest tests/validators/test_semver.py -v
Verify the full test suite still passes#
make test
Document the validator#
Add a row for the new validator in Validators reference.
Note whether it is wired into DEFAULT_VALIDATORS.