Skip to main content

operaton-contracts

Pydantic task contracts for Robot Framework packages served as Operaton (Camunda 7) external tasks, for example by purjo.

Documentation: https://datakurre.github.io/operaton-contracts/

One model per external task topic is the source of truth for what the task accepts and returns:

  • At runtime each Robot task validates and normalizes its process variables with Validate Task Input.
  • At build time operaton-contracts generate renders one bpmn.io element template per topic from the same models, and operaton-contracts check verifies that the templates, [tool.purjo.topics], and the Robot suites agree.
uv add operaton-contracts                   # runtime: pydantic + robotframework
uv add --group dev "operaton-contracts[templates]"   # adds jsonschema for validate

Contracts

# OperatonTasks.py
from datetime import date
from typing import Any, Literal

from pydantic import Field
from OperatonContracts import TaskContract, template_hints


class RescindStudyRightsInput(TaskContract):
    study_right_ids: list[str] = Field(
        alias="studyRightIds",
        title="Study right IDs",
        min_length=1,
        json_schema_extra=template_hints(value=["${studyRightId}"]),
    )
    cancellation_date: date = Field(
        alias="cancellationDate", title="Cancellation date", strict=False
    )
    dry_run: bool = Field(alias="dryRun", title="Dry run", default=False)


class RescindStudyRightsOutput(TaskContract):
    result: dict[str, Any] = Field(alias="result", title="Result variable")

TaskContract is strict, forbids extra fields, and strips strings. Every field needs an alias (the process variable name) and a title (the template label). Use Literal[...] for choices; Enum, Optional, and nested models are not supported in template inputs. template_hints(value=..., type=...) sets template-only defaults and property types.

Robot tasks

*** Settings ***
Library     OperatonContracts    OperatonTasks

*** Variables ***
${BPMN:TASK}    local
@{studyRightIds}    @{EMPTY}
${cancellationDate}    ${EMPTY}
${dryRun}    ${False}

*** Tasks ***
Rescind Study Rights
    ${input}=    Validate Task Input    RescindStudyRightsInput
    Log    ${input}[studyRightIds]
    VAR    ${result}=    ${{{}}}    scope=${BPMN:TASK}

Validate Task Input reads ${alias} for every field, validates, and returns the values JSON-compatible (dates as YYYY-MM-DD), keyed by alias. Declare typed suite defaults (${False}, ${0}, @{EMPTY}): strict contracts reject the string "0" or "false". The library imports the contracts module from sys.path, falling back to the running suite's directory.

Element templates

# pyproject.toml of the robot package
[tool.operaton-contracts]
specs = "scripts.element_templates:TEMPLATES"   # module:attribute
icon = "scripts/logo.svg"                       # optional SVG icon
reserved-topics = ["legacy.topic"]              # optional
# schema-url = "…"                              # optional; pinned default
# scripts/element_templates.py
from OperatonContracts.templates import TaskTemplate, TemplateGroup
from OperatonTasks import RescindStudyRightsInput, RescindStudyRightsOutput

TEMPLATES = (
    TaskTemplate(
        topic="study_rights.rescind",
        template_id="org.example.study-rights-rescind",
        name="Rescind Study Rights",
        description="Rescind active study rights.",
        filename="study-rights-rescind.json",
        inputs=RescindStudyRightsInput,
        outputs=RescindStudyRightsOutput,
        groups=(TemplateGroup("main", "Rescission"),),
        input_group="main",
        output_group="main",
    ),
)
operaton-contracts generate   # write .operaton/element-templates/*.json
operaton-contracts check      # offline: drift and package consistency
operaton-contracts validate   # against the pinned upstream schema (network)

check fails when committed templates differ from the generated ones, when specs and [tool.purjo.topics] differ, when a topic is reserved or lacks process-variables = false, or when the suite defining a topic's task lacks a typed default for an input, the Validate Task Input call, or a VAR … scope=${BPMN:TASK} for an output. Names are matched the way Robot matches them, suites are collected recursively (skipping hidden directories, tests/, lib/, examples/, and test_*.robot), and a task name defined in more than one suite is an error.

Development

uv run --group dev --group docs make test check docs   # with uv
devenv shell -- make test check docs                   # or with devenv
make build

make docs-serve previews the documentation site, which is published to GitHub Pages from main by .github/workflows/docs.yml.

License

Apache License 2.0; see LICENSE.

Releases are published to PyPI by .github/workflows/release.yml with trusted publishing when a v* tag matching the project version is pushed.

Metadata

Release files for operaton-contracts 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for operaton-contracts 0.1.0
File Size Uploaded
operaton_contracts-0.1.0.tar.gz 22.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for operaton-contracts 0.1.0
File Interpreter ABI Platform
operaton_contracts-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 42.3 kB

Release files / operaton_contracts-0.1.0.tar.gz

Download URL operaton_contracts-0.1.0.tar.gz
Size 22.4 kB
Tags Source
SHA-256 checksum
How to use checksums
bebb7c1437592d54e0db1453448a66c8e42f0f9db0ba039239ce96010cc90f88
BLAKE2b-256 checksum
How to use checksums
60ac873a4ff45ee202672d97d231fb6e5f38d06322bfc5e492dbf8f4e9524bbe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.1.0 CPython/3.12.5

Release files / operaton_contracts-0.1.0-py3-none-any.whl

Download URL operaton_contracts-0.1.0-py3-none-any.whl
Size 19.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ea1183ada5d43295ed48c192220b397766f0e1bc78eb9e66516f906133646e8
BLAKE2b-256 checksum
How to use checksums
82f3d241125f53f7f936e8e8f05eea4048ab31c686d2e5dc7703dc27307f4c0e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.1.0 CPython/3.12.5

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page