formkrafter (Python)
FormKrafter for Python backends. The server validates a submission with the same spec the browser renders, and
reaches the same verdict: same error keys (items[0].hs_code), same messages, same warnings as
@streamline-pulse/formkrafter-core.
pip install formkrafter # no dependency
pip install "formkrafter[pydantic]" # Pydantic models for specs built in code
from formkrafter import validate_form_data
result = validate_form_data(spec, payload, locale="fr")
if not result.valid:
# {"items[0].declared_value": "Minimum 0", "origin": "Ce champ est obligatoire"}
return 422, result.errors
What it does
| Function | Core equivalent |
|---|---|
build_validation_schema(spec, locale) |
buildValidationSchema: the same Ajv schema, key for key |
validate_form_data(spec, data, locale) |
validateFormData: empty strings and nulls count as missing, collections are validated row by row |
lint_spec(spec) |
lintSpec: keyless inputs, validations without a dataType, duplicate keys, empty collections |
register_validation_messages(locale, messages) |
registerValidationMessages |
default_form_data, iterate_bricks, iterate_schema_bricks, resolve_localized_text |
same names in camelCase |
validate_form_data returns a ValidationResult:
valid,errors(key → message) andwarnings, as in the browser;to_dict()gives the core's shape;details(key →ErrorDetail(validator, message, value)), so an API can return a stable code and let the client word it:{"items[0].declared_value": {"validator": "min", "value": 0, "message": "Minimum 0"}}.
Every function takes a plain dict or a formkrafter.models.BrickSpec.
Supported
- Validations:
required,min/max,minLength/maxLength,pattern,minItems/maxItems,email,url. - Bricks: panels, inputs, selects (multiple included), collections (data grids, nested at any depth), outputs.
On top of those,
date-rangemust not end before it starts. - Rules: rules that only disable, prefill or require a field are accepted. They do not change the verdict, in the browser either.
The details that usually make a Python port drift are reproduced:
- Ajv's
emailanduriformats, copied verbatim; - the browser's
RegExp:$never matches before a trailing newline, and\dis ASCII; String(1e-7)is1e-7;- the core compares lengths in code points;
- a schema Ajv refuses to compile enforces no rule (with a warning).
Refused
validate_form_data raises SpecNotSupported rather than half-validating a spec that needs:
- JavaScript custom validators (
validator: "custom"). They run in the browser's sandbox and are not executed server-side: move the check to the server, or to a declarative validation. - Rules that hide data-carrying fields. A hidden field's errors are dropped in the browser. json-logic evaluation is planned.
- The checks not ported yet: identity numbers (
national-id,tax-id,iban),vehicle-plate,company-registry,mrz.
build_validation_schema and lint_spec work on every spec. assert_supported(spec) checks up front, for
instance in the tests that cover the specs a backend serves.
Parity with the core
tests/parity/cases.json holds specs and data samples. The core compiles and validates them:
bun scripts/python-parity.ts # from the repository root: rewrites tests/parity/expected.json
uv run pytest # the port must reach the same schemas, lint issues and verdicts
CI regenerates the fixtures and fails when they are stale, so a change in the core shows up in the Python tests.
formkrafter.CORE_VERSION names the core release a version follows.
In your own project
formkrafter.testing checks your specs against the real core, through Node and your web app's installed
@streamline-pulse/formkrafter-core:
from formkrafter.testing import assert_matches_core
def test_served_forms_match_the_browser():
assert_matches_core(SPEC, samples=[VALID, {}, {"items": []}], locales=["fr", "en"], node_project="../web")
export_contract(spec, locales) returns the spec with its schema per locale. Write it where your web tests read
it to assert that buildValidationSchema(spec, locale) gives the same.
Metadata
Release files for formkrafter 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| formkrafter-0.1.0.tar.gz | 68.4 kB | With provenance | Details for formkrafter-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| formkrafter-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for formkrafter-0.1.0-py3-none-any.whl |
Total release size: 87.5 kB
Release files / formkrafter-0.1.0.tar.gz
| Download URL | formkrafter-0.1.0.tar.gz |
|---|---|
| Size | 68.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
30e657e4c5cadd444bd7185697df7413a9d6663ddfd0ca3099fac773de57f730
|
|
BLAKE2b-256 checksum How to use checksums |
ce90f118ec71c93c5d95db8577bb3ca92ac0a0c04be91a64188bf4d55bba358c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / formkrafter-0.1.0-py3-none-any.whl
| Download URL | formkrafter-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7a5bf378c0f5607338f0f1026baa061b5aa792f9ad66419707ee43435f6ec9c4
|
|
BLAKE2b-256 checksum How to use checksums |
8315c50abc58235ad59870b93792be2bde6a8075c16b86d8c0255f4b36ffadf5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logSecurity for formkrafter 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for formkrafter-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.