Skip to main content

JASIL

License Release PyPI version PyPI downloads Python Docs Stars

Just Another Substrate & Infrastructure Library — a framework-agnostic infrastructure substrate for Python services: swappable capability backends, an event pipeline, durable jobs, and observability.

Status: 0.4.0 - the API is still settling. Expect breaking changes on minor versions until 1.0.0.


What it gives you

Layer What it does
Providers Small composable protocols - state, storage, events, lock, clock, geocoding - that domain code depends on instead of Redis, S3, or Postgres. Complete aggregate protocols keep URI-selected backends interchangeable.
Backends A working implementation of each, selected by URI: memory:// or redis://, local:// or s3://, noop:// or postgres-advisory://.
Deployment profiles local runs single-process with zero extra infrastructure. distributed requires shared backends and refuses to guess them.
Event pipeline One envelope, one publish seam, payload schema versioning that survives a rolling deploy.
Durable jobs A transactional outbox relayed into leased per-subscriber jobs, with exponential backoff and a dead-letter queue.
Observability An event lifecycle log and bounded retention pruning for every table it owns.

A core install depends on sqlalchemy and pydantic only. Every backend client lives behind an extra and is imported lazily, so a single-process deployment never loads redis, boto3, or requests.

JASIL is synchronous. Every provider, subscriber, and the durable-jobs layer is blocking Python, and the ORM integration expects a synchronous sessionmaker — there is no AsyncSession support. On an async framework, call into JASIL from a worker thread (a def FastAPI route or dependency does this for you). See the docs.

Installation

pip install jasil                    # core: memory / local disk / in-process
pip install "jasil[redis,s3]"        # distributed state, events and storage
pip install "jasil[all]"             # every optional backend
Extra Enables
redis Redis state store and Redis-Streams event bus
s3 S3-compatible object storage
postgres PostgreSQL advisory locks
jobs Durable-job scheduling
fastapi Depends helpers exposing the providers to routes
geocoding HTTP reverse geocoding
migrations Packaged Alembic revisions

Verifying a release

Releases are built and published by this repository's release workflow through PyPI Trusted Publishing, with PEP 740 attestations. You can confirm a downloaded artifact came from that workflow and was not substituted:

uvx pypi-attestations verify pypi \
  --repository https://github.com/endurain-project/jasil \
  pypi:jasil-<version>-py3-none-any.whl

A successful run prints OK: <filename>. Provenance for file ... was not found means the artifact predates attested publishing rather than that verification failed.

Each release run also produces a CycloneDX SBOM and SHA256SUMS, generated from a clean install of the built wheel. These are retained as workflow artifacts on the release run rather than published to PyPI.

Quick start

JASIL never reads your environment, creates your engine, or owns your declarative base — the host supplies all three.

from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, sessionmaker

import jasil.orm as jasil_orm
import jasil.settings as jasil_settings
from jasil.container import build_platform
from jasil.runtime import set_active_platform


class Base(DeclarativeBase):
    """Your application's declarative base."""


# 1. Map JASIL's tables into your registry, before any database use.
jasil_orm.map_models(Base)

# 2. Hand JASIL a session factory bound to your engine.
engine = create_engine("postgresql+psycopg://...")
jasil_orm.configure_sessionmaker(sessionmaker(bind=engine))

# 3. Configure, build, publish.
jasil_settings.configure(jasil_settings.JasilSettings(data_dir="/srv/data"))
set_active_platform(build_platform())

Then depend on capabilities, not on infrastructure:

from jasil.runtime import get_active_platform

platform = get_active_platform()
platform.state.set("session:abc", b"...", ttl_seconds=3600)
platform.storage.save("thumbnails", "42.webp", image_bytes)

with platform.lock.try_acquire("nightly-backfill") as acquired:
    if acquired:
        run_backfill()

Publishing an event goes through one seam, so switching from best-effort delivery to a transactional outbox is a configuration change, not a rewrite:

from jasil.publisher import publish

publish("activity.created", {"activity_id": 42}, source="api:store_activity", db=db)

Going distributed

Change the profile and point the capability URIs at real infrastructure:

jasil_settings.configure(
    jasil_settings.JasilSettings(
        profile=jasil.DeploymentProfile.DISTRIBUTED,
        state_uri="redis://cache:6379/0",
        events_uri="redis://cache:6379/1",
        storage_uri="s3://my-bucket",
        lock_uri="postgres-advisory://",
    )
)

The distributed profile refuses to start if a capability URI is unset. A silent fallback to a process-local backend across replicas is the failure the profile system exists to prevent.

Development

uv sync --all-extras --group dev
uv run pytest              # tests + coverage gate
uv run ruff check .        # lint
uv run mypy                # type check
uv run lint-imports        # architectural import contracts

Documentation

Full documentation is available at the JASIL docs site.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions welcome! See Contributing Guidelines for guidelines.

Built with ❤️ from Portugal | Part of the Endurain ecosystem

Download files

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

Source Distribution

jasil-0.4.0.tar.gz (116.1 kB view details)

Uploaded Source

Built Distribution

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

jasil-0.4.0-py3-none-any.whl (137.1 kB view details)

Uploaded Python 3

File details

Details for the file jasil-0.4.0.tar.gz.

File metadata

  • Download URL: jasil-0.4.0.tar.gz
  • Upload date:
  • Size: 116.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","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 jasil-0.4.0.tar.gz
Algorithm Hash digest
SHA256 03e6d231d0eaf832cfae9eda8b7550abfba4d168f7cfe7bc06bc769c831874ce
MD5 e865620ef1dfcd606bca5c140385fb17
BLAKE2b-256 4e74c8d220410fcf1adf6f0aa499cf743ffe02b28e8af5712f3ac9ad5bb4d42c

See more details on using hashes here.

File details

Details for the file jasil-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: jasil-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 137.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","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 jasil-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7de8ad5424fa9f3611bf7e8548f032db3ba3b2fcd284556e22e997a78b453c0c
MD5 8f29d2a44de64358c23cc037981022ea
BLAKE2b-256 bdbfab602d06ac2cab103d0f1c4ae4f4e65cc3ee07c652580cc596ec01aae0e3

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.0

2 files

This release

0.4.0 This release

2 files

0.3.0

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 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