Skip to main content

An opinionated, msgspec-first ASGI micro-framework

Project description

jero

Release Build status codecov Commit activity License

An opinionated, msgspec-first ASGI micro-framework for Python 3.14.

GitHub · Documentation

What is jero?

jero is opinionated on purpose. It makes one bet: that being aggressively prescriptive — rather than flexible — is exactly what lets a framework be both extremely fast and a joy to build on. Three pillars, all non-negotiable:

  1. Speed. Introspection happens once, at startup. The request path is dict lookup → msgspec decode → call → encode, and nothing else is ever added to it.
  2. Opinionated DX. One blessed way to do each thing, encoded so you can't get it wrong. Contracts fail loud at startup with a precise WiringError, never quietly at runtime.
  3. Strict typing. Fully static under pyright-strict — the types are the contract, and the source of the coming OpenAPI spec. If you don't like typing, this isn't your framework.

And no DI container: dependencies are hand-wired in _wire; the framework adds only lifecycle — the one thing plain Python doesn't give you.

Example

from msgspec import Struct

from jero import BaseApp, Endpoint, Resource, TestClient


class Widget(Struct):
    id: str
    name: str


class WidgetResource(Resource):
    async def read_one(self, path: "WidgetPath") -> Widget:
        return Widget(id=path.widget_id, name="widget-name")


class WidgetPath(Struct):
    widget_id: str


class HealthEndpoint(Endpoint):
    async def get(self) -> Widget:
        return Widget(id="health", name="ok")


class App(BaseApp):
    async def _wire(self) -> None:
        self._include_resource(WidgetResource(), path="/widgets")
        self._include_endpoint(HealthEndpoint(), path="/healthz")


app = App()

# Test it in-process — no socket, no server:
with TestClient(app) as client:
    resp = client.get("/widgets/abc")
    assert resp.status_code == 200
    assert resp.json() == {"id": "abc", "name": "widget-name"}

Run it under any ASGI server, e.g. granian:

granian --interface asgi myapp:app

Development

task install   # create the venv and install pre-commit hooks
task check     # lock check + ruff, pyright, deptry, pylint (via prek)
task test      # run the test suite with coverage

See AGENTS.md for the design philosophy and the contract, and style-guide.md for project conventions.

Releasing a new version

Publishing uses PyPI Trusted Publishing (OIDC) — no token required.

  1. Bump version in pyproject.toml and commit it to main.
  2. Create a GitHub release tagged with the same version — a bare PEP 440 string, e.g. 0.1.0 (no v).

The release workflow verifies the tag matches pyproject.toml, builds, publishes to PyPI, and deploys the docs. A version mismatch fails the release.


Repository initiated with osprey-oss/cookiecutter-uv.

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

jero-0.0.6.tar.gz (376.9 kB view details)

Uploaded Source

Built Distribution

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

jero-0.0.6-py3-none-any.whl (24.8 kB view details)

Uploaded Python 3

File details

Details for the file jero-0.0.6.tar.gz.

File metadata

  • Download URL: jero-0.0.6.tar.gz
  • Upload date:
  • Size: 376.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for jero-0.0.6.tar.gz
Algorithm Hash digest
SHA256 747a571e11d5e65db9d77f11714c33494bf9ecd2f0c5e5e4c927e5c6a7fecf87
MD5 2a8ccbf86f304e83b92ac78c65972891
BLAKE2b-256 7e7f05babcf4976bffa4021bd3eb171b87849af3e342d680b6f7562fb4391160

See more details on using hashes here.

File details

Details for the file jero-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: jero-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 24.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for jero-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 f4db6d1e72ada5271565bdc64a58bbffad49bbcc471b51094e78dbeb24dc2123
MD5 dd88c4ab196d3ed6d4295e31f6026f99
BLAKE2b-256 cffb82f1c14c0143a99c50c7f843ace8f9fe11b9c086326085253c679826d51b

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