Skip to main content
This guide uses schwifty to validate an IBAN from Sifr. schwifty is a good first Python interop example because construction and attribute reads map cleanly onto typed opaque declarations.

Why this shape

Embedded Python interop is not “write Python inside Sifr.” Sifr embeds one uv-created CPython environment and calls installed packages through checked declarations. Four rules drive the schwifty path:
  1. The root app owns the environment. Sifr verifies a uv project (.venv, lock, interpreter). It does not run uv sync or invent a host-global Python.
  2. Import roots need trust. Declaring @python(schwifty.IBAN) creates a requirement; the root [trust].python list authorizes execution.
  3. Python objects stay opaque. An IBAN instance is not a Sifr record. Expose only the attributes and methods you need through @python.opaque and @python.attr.
  4. Failures stay in Result. Invalid IBANs and other Python exceptions become structured PythonError values. They do not unwind through Sifr user code.
Prefer typed declarations for ordinary package calls. Use dynamic Object only when a boundary cannot be declared.

Package setup

Install schwifty in the root uv project, then authorize the import root:
sifr.toml
Inspect the plan before building:

Declare the IBAN surface

@python(schwifty.IBAN) binds the constructor. Invalid input fails through PythonError instead of raising across the Sifr boundary. cleanup=drop is enough here because IBAN values do not need deterministic close semantics beyond ordinary Python object lifetime.

Validate in application code

Every public sifr.python call is @blocking_io. Keep the call on a blocking path, or offload it from async code:
Example input: "DE89 3704 0044 0532 0130 00". On success you get the country, bank, and account components after schwifty’s validation. On failure you get a checked PythonError with message, kind, exception type, traceback, and context.

Why not import schwifty like ordinary Python

Sifr application code does not execute import schwifty as host Python would. The declaration is the import plan: Sifr inventories the root, probes the selected interpreter, and embeds the verified environment into the binary. That keeps environment ownership, trust, and conversion contracts compile-time visible.

Next steps