Skip to main content

PYRE — Flask-flavored Python on the Internet Computer: certified reads, urllib-shaped outcalls, stable-memory collections

Project description

PYRE — Python on the Internet Computer

PyPI CI MIT Python 3.10

Write recognizable Python — Flask-style routes, a data layer, an outbound HTTP call — and run it on the Internet Computer (ICP), a decentralized WASM host. No Candid, no Rust, no Motoko.

What that buys you over Flask-on-a-VPS:

  • Certified responses — clients cryptographically verify your API's answers against the network's root of trust, not "trust the server."
  • Threshold-signed JWTs — the subnet signs cooperatively; there is no private key anywhere to steal.
  • Consensus-safe randomness & audited encryption — the platform footguns are defused; the safe paths look like ordinary Python.
  • ~$0.40/month for a light backend, measured on mainnet.
from pyre import App, Request, Response, data

app = App()
app.enable_cors(origins="*")

items = data.collection("items", schema={"name": str, "qty": (int, 1)})

@app.get("/health", certified=True)     # served with a verifiable certificate
def health(req: Request) -> Response:
    return Response.json({"status": "ok"})

@app.post("/items")                     # runs as an update: writes persist
def create_item(req: Request) -> Response:
    return Response.json(items.insert(req.json()), status=201)

@app.get("/items")
def list_items(req: Request) -> Response:
    return Response.json(items.list(limit=20, after=req.query.get("after")))

Outbound HTTPS looks like urllib, but async — because on ICP it is:

from pyre.compat import urllib_request as urllib

@app.get("/quote", update=True)
async def quote(req):
    resp = await urllib.urlopen("https://api.example.com/quote",
                                max_response_bytes=8_192)
    return Response.json({"upstream_status": resp.status, "data": resp.json()})

And ICP's genuinely differentiated capabilities read like ordinary Python (every one opt-in — a plain CRUD app never meets them):

from pyre import random as prandom, time as ptime, sign
from pyre.adapters import supabase

@app.get("/id")
def new_id(req):
    return Response.json({"id": prandom.uuid4()})   # consensus-safe; naive uuid4 fails loudly

@app.get("/attest", update=True)
async def attest(req):
    token = await sign.jwt({"sub": req.caller, "iat": ptime.now()})
    return Response.json({"jwt": token})            # threshold-signed: no key to steal

@app.get("/external", update=True)
async def external(req):
    db = supabase.Client(url=SUPA_URL, anon_key=SUPA_KEY)
    return Response.json(await db.table("items").select().limit(10))

Install

pip install pyre-icp

The distribution is pyre-icp; the import package and the CLI are both pyre. To deploy canisters you also need, one time:

  • Python 3.10.7 as Kybra's build interpreter (CPython, via pyenv). It compiles your code to Wasm — it is not what runs on-chain: the canister runs RustPython (a Rust Python interpreter) plus Rust crates, so CPython 3.10's Oct-2026 EOL is a build-toolchain note, not a running-service one. (details)
  • dfx (the ICP SDK): DFXVM_INIT_YES=true sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)"
  • Kybra in your project's deploy venv: pip install kybra==0.7.1 + python -m kybra install-dfx-extension

Then:

pyre new myapp --template crud-kv     # bare-api | crud-kv | outbound-proxy
cd myapp
pyre dev src/app.py                   # instant local server, no replica needed
dfx start --background && dfx deploy  # real local canister — free, no wallet
dfx deploy --network ic               # mainnet — needs cycles (free coupon path below)

Everything up to the last line is free and needs no blockchain identity, ICP, or cycles — build and exercise the whole app locally at $0. Only a persistent mainnet canister costs anything, and there's a free cycles-faucet coupon for it. (Heads-up: a Kybra Wasm is ~27 MB, so ICP's playground / ICP Ninja "instant deploy" options don't fit it — mainnet is the public-URL path. The quickstart walks it honestly, coupon included.)

The API surface

Module What it gives you Docs
pyre.App / Request / Response Flask-style routing, path params, hooks, error handlers, CORS, certified routes api.md
pyre.data / pyre.kv Collections + KV over stable memory — survives upgrades; schemas, pagination, lazy migration api.md
pyre.validate Dict-schema request validation → clean per-field 400s api.md
pyre.auth Bearer / API-key / HTTP Basic middleware, constant-time, hash-stored creds api.md
pyre.compat.urllib_request urllib-shaped async HTTPS outcalls with determinism transforms concepts.md
pyre.random / pyre.uuid / pyre.time Consensus-safe RNG, UUIDs, timestamps (naive stdlib entropy fails loudly in-canister — by design) random-uuid-time.md
pyre.crypto AES-GCM, ChaCha20-Poly1305, sha2/sha3/blake2/blake3, HMAC — audited RustCrypto under the hood crypto.md
pyre.sign Threshold tECDSA signatures + ES256K JWTs — no private key exists api.md
pyre.oidc (1.2) Verify Google/OIDC RS256/ES256 ID tokens in-canister (JWKS cached + determinism-transformed); real sign-in without trusting a server oidc.md
pyre.static (1.2) Serve a built SPA (Vue/React/…) from the canister, certified index + chunked stable-memory assets; pyre assets push dist/ static-serving.md
pyre.adapters Supabase (PostgREST) + Upstash Redis over outcalls, amplification-safe writes adapters.md
pyre.log Structured logging retrievable via dfx canister logs observability.md
pyre CLI pyre new (templates), pyre dev (local server + footgun warnings), pyre assets push quickstart.md

All docs: quickstart · concepts · API reference · troubleshooting · stdlib support matrix · secrets & outcalls · extending with Rust · observability · LLM/agent skill file · reference app: examples/food_tracker

Give your coding agent PYRE (Claude Code skill)

This repo is a Claude Code marketplace. Teach your agent the framework — the golden rules, the Kybra build traps, the capability map — with two lines:

claude plugin marketplace add Sweet-Papa-Technologies/PYRE
claude plugin install pyre-icp@pyre

Now Claude auto-loads the PYRE skill whenever you write canister code, debug a Kybra build, or deploy. (The skill is SKILL.md — installing it just keeps it current via claude plugin update pyre-icp.)

The four ICP concepts PYRE teaches (and hides everything else)

  1. Query vs. update calls. Queries are fast, read-only, uncertified; updates go through consensus (~1–2 s) and can write. PYRE maps GET → query, writes/async → update; honesty guards raise if you write state or make outcalls from a query.
  2. Outbound HTTP is async and consensus-gated. Every replica performs your outcall independently and must agree byte-for-byte — hence await, and hence transforms.
  3. The determinism transform. Upstream responses differ per replica (Date headers, request ids). Outcalls run through a transform that canonicalizes the response before consensus; pyre dev shows you what gets stripped before you ever deploy.
  4. Canisters are long-lived actors. The interpreter boots once at install and stays warm — no cold starts, but funding (cycles) and instruction budgets are real. make budgets measures; DECISIONS.md records.

Full explanations with failure symptoms in concepts.md.

Mainnet-proven, not aspirational

Every load-bearing claim was tested against ICP mainnet (13-node subnet) and recorded in DECISIONS.md: response certification verified by the official DFINITY verifier (BLS to the NNS root key, tamper/stale rejected), outcall determinism proven across real replicas, threshold signatures externally verified (26.19B cycles ≈ 3.5¢ each), 13× write-amplification converging to single rows through the adapters, and a light backend costing ≈ $0.40/month.

Working from a clone

make setup          # venvs (Python 3.10.7 via pyenv), kybra, dfx extension
make test           # ~240 unit tests, no replica needed
make dev            # instant local server for examples/rest_api
make start deploy   # local replica + all example canisters
make e2e            # 20-check acceptance suite
make pocketic       # canister-level integration tests
make budget-gate    # instruction + wasm-size/idle-burn regression gates

CI runs the same gates on every push. See CONTRIBUTING.

Scope fences

Pure Python only — no C extensions, no Pydantic. No sockets/threads (stubbed with guidance), no websockets/streaming. Secret-bearing outcalls (calling Stripe/OpenAI with a private key) are a documented limitation until v1.2's signed proxy.

License

MIT © Sweet Papa Technologies

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyre_icp-1.3.0.tar.gz (119.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyre_icp-1.3.0-py3-none-any.whl (138.0 kB view details)

Uploaded Python 3

File details

Details for the file pyre_icp-1.3.0.tar.gz.

File metadata

  • Download URL: pyre_icp-1.3.0.tar.gz
  • Upload date:
  • Size: 119.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.7

File hashes

Hashes for pyre_icp-1.3.0.tar.gz
Algorithm Hash digest
SHA256 6a56d54437be6e2db023da057b4ee986747c4976b06e4f11fb372aa1da815a2d
MD5 6ee38f3822eca3d236535b15dd19b965
BLAKE2b-256 81fdd5d9acdfcd692c5fa1f6b9debce00a2d89030d7b56ae34d8f6bd367f19e0

See more details on using hashes here.

File details

Details for the file pyre_icp-1.3.0-py3-none-any.whl.

File metadata

  • Download URL: pyre_icp-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 138.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.7

File hashes

Hashes for pyre_icp-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0dda0a3e3915114a80d9e957a47b912fe4f034e5cade69412e077b5cb18fd9a1
MD5 ceea53d777151e79bc9c69672ccc71ed
BLAKE2b-256 10162f8d279ac936c8fc75301c490bd9fd6bdd0a7ae4a2ceb0b5a586653066bb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page