Skip to main content

A modern pure ASGI/WSGI Python framework for building schema-first REST and JSON-RPC APIs with SQLAlchemy models, typed validation, lifecycle hooks, and engine extension support.

Project description

Tigrbl Logo

PyPI - Downloads Hits PyPI - Python Version PyPI - License PyPI - tigrbl


Tigrbl ๐Ÿ…๐Ÿ‚

A high-leverage ASGI meta-framework that turns plain SQLAlchemy models into a fully-featured REST+RPC surface with near-zero boilerplate. ๐Ÿš€

Features โœจ

  • โšก Zero-boilerplate CRUD for SQLAlchemy models
  • ๐Ÿ”Œ Unified REST and RPC endpoints from a single definition
  • ๐Ÿช Hookable phase system for deep customization
  • ๐Ÿงฉ Pluggable engine and provider abstractions
  • ๐Ÿš€ Built as an ASGI-native framework with Pydantic-powered schema generation

Terminology ๐Ÿ“š

  • Tenant ๐Ÿข โ€“ a namespace used to group related resources.
  • Principal ๐Ÿ‘ค โ€“ an owner of resources, such as an individual user or an organization.
  • Resource ๐Ÿ“ฆ โ€“ a logical collection of data or functionality exposed by the API.
  • Engine โš™๏ธ โ€“ the database connection and transaction manager backing a resource.
  • Model / Table ๐Ÿงฑ โ€“ the ORM or database representation of a resource's records.
  • Column ๐Ÿ“ โ€“ a field on a model that maps to a table column.
  • Operation ๐Ÿ› ๏ธ โ€“ a verb-driven action executed against a resource.
  • Hook ๐Ÿช โ€“ a callback that runs during a phase to customize behavior.
  • Phase โฑ๏ธ โ€“ a step in the request lifecycle where hooks may run.
  • Verb ๐Ÿ”ค โ€“ the canonical name of an operation such as create or read.
  • Runtime ๐Ÿง  โ€“ orchestrates phases and hooks while processing a request.
  • Kernel ๐Ÿงฉ โ€“ the core dispatcher invoked by the runtime to handle operations.
  • Schema ๐Ÿงฌ โ€“ the structured shape of request or response data.
  • Request ๐Ÿ“ฅ โ€“ inbound data and context provided to an operation.
  • Response ๐Ÿ“ค โ€“ outbound result returned after an operation completes.

Built-in Verbs ๐Ÿงฐ

Tigrbl exposes a canonical set of operations that surface as both REST and RPC endpoints. The table below summarizes the default REST routes, RPC methods, arity, and the expected input and output shapes for each verb. {resource} stands for the collection path and {id} is the primary key placeholder.

Verb REST route RPC method Arity Input type Output type
create โž• POST /{resource} Model.create collection dict dict
read ๐Ÿ” GET /{resource}/{id} Model.read member โ€“ dict
update โœ๏ธ PATCH /{resource}/{id} Model.update member dict dict
replace โ™ป๏ธ PUT /{resource}/{id} Model.replace member dict dict
merge ๐Ÿงฌ PATCH /{resource}/{id} Model.merge member dict dict
delete ๐Ÿ—‘๏ธ DELETE /{resource}/{id} Model.delete member โ€“ dict
list ๐Ÿ“ƒ GET /{resource} Model.list collection dict array
clear ๐Ÿงน DELETE /{resource} Model.clear collection dict dict
bulk_create ๐Ÿ“ฆโž• POST /{resource} Model.bulk_create collection array array
bulk_update ๐Ÿ“ฆโœ๏ธ PATCH /{resource} Model.bulk_update collection array array
bulk_replace ๐Ÿ“ฆโ™ป๏ธ PUT /{resource} Model.bulk_replace collection array array
bulk_merge ๐Ÿ“ฆ๐Ÿงฌ PATCH /{resource} Model.bulk_merge collection array array
bulk_delete ๐Ÿ“ฆ๐Ÿ—‘๏ธ DELETE /{resource} Model.bulk_delete collection dict dict
bulk_read โ€“ โ€“ โ€“ โ€“ โ€“ โ€“

Update, Merge, and Replace ๐Ÿ”„

update applies a shallow PATCH: only the supplied fields change and missing fields are left untouched. merge performs a deep merge with upsert semanticsโ€”if the target row is absent it is created, and nested mapping fields are merged rather than replaced. replace follows PUT semantics, overwriting the entire record and nulling any omitted attributes.

Verb Overrides ๐Ÿงญ

Because create and bulk_create share the same collection POST route, enabling bulk_create removes the REST create endpoint; the Model.create RPC method remains available. Likewise, bulk_delete supersedes clear by claiming the collection DELETE route. Only one of each conflicting pair can be exposed at a time. Other verbs coexist without conflict because they operate on distinct paths or HTTP methods.

Phase Lifecycle โ›“๏ธ

Tigrbl operations execute through a fixed sequence of phases. Hook chains can attach handlers at any phase to customize behavior or enforce policy.

Phase Description
PRE_TX_BEGIN โณ Pre-transaction checks before a database session is used.
START_TX ๐Ÿšฆ Open a new transaction when one is not already active.
PRE_HANDLER ๐Ÿงน Validate the request and prepare resources for the handler.
HANDLER โ–ถ๏ธ Execute the core operation logic within the transaction.
POST_HANDLER ๐Ÿ”ง Post-processing while still inside the transaction.
PRE_COMMIT โœ… Final verification before committing; writes are frozen.
END_TX ๐Ÿงพ Commit and close the transaction.
POST_COMMIT ๐Ÿ“Œ Steps that run after commit but before the response is returned.
POST_RESPONSE ๐Ÿ“ฎ Fire-and-forget work after the response has been sent.
ON_ERROR ๐Ÿ›‘ Fallback error handler when no phase-specific chain matches.
ON_PRE_TX_BEGIN_ERROR ๐Ÿงฏ Handle errors raised during PRE_TX_BEGIN.
ON_START_TX_ERROR ๐Ÿงฏ Handle errors raised during START_TX.
ON_PRE_HANDLER_ERROR ๐Ÿงฏ Handle errors raised during PRE_HANDLER.
ON_HANDLER_ERROR ๐Ÿงฏ Handle errors raised during HANDLER.
ON_POST_HANDLER_ERROR ๐Ÿงฏ Handle errors raised during POST_HANDLER.
ON_PRE_COMMIT_ERROR ๐Ÿงฏ Handle errors raised during PRE_COMMIT.
ON_END_TX_ERROR ๐Ÿงฏ Handle errors raised during END_TX.
ON_POST_COMMIT_ERROR ๐Ÿงฏ Handle errors raised during POST_COMMIT.
ON_POST_RESPONSE_ERROR ๐Ÿงฏ Handle errors raised during POST_RESPONSE.
ON_ROLLBACK โ†ฉ๏ธ Run when the transaction rolls back to perform cleanup.

Happy-path flow


PRE\_TX\_BEGIN
|
START\_TX
|
PRE\_HANDLER
|
HANDLER
|
POST\_HANDLER
|
PRE\_COMMIT
|
END\_TX
|
POST\_COMMIT
|
POST\_RESPONSE

If a phase raises an exception, control transfers to the matching ON_<PHASE>_ERROR chain or falls back to ON_ERROR, with ON_ROLLBACK executing when the transaction is rolled back.

Request โ†’ Response Flow Examples ๐Ÿ”€

REST example


Client
|
v
HTTP Request
|
v
ASGI Router
|
v
Tigrbl Runtime
|
v
Operation Handler
|
v
HTTP Response

RPC example


Client
|
v
JSON-RPC Request
|
v
RPC Dispatcher
|
v
Tigrbl Runtime
|
v
Operation Handler
|
v
JSON-RPC Response

Hooks ๐Ÿช

Hooks allow you to plug custom logic into any phase of a verb. Use the hook_ctx decorator to declare context-only hooks:

from tigrbl import Base, hook_ctx

class Item(Base):
    __tablename__ = "items"

    @hook_ctx(ops="create", phase="PRE_HANDLER")
    async def validate(cls, ctx):
        if ctx["request"].payload.get("name") == "bad":
            raise ValueError("invalid name")

The function runs during the PRE_HANDLER phase of create. The ctx mapping provides request and response objects, a database session, and values from earlier hooks.

Hooks can also be registered imperatively:

async def audit(ctx):
    ...

class Item(Base):
    __tigrbl_hooks__ = {"delete": {"POST_COMMIT": [audit]}}

Running apps expose a /system/hookz route that lists all registered hooks. ๐Ÿ“‹

Step Types ๐Ÿงฑ

Tigrbl orders work into labeled steps that control how phases run:

  • secdeps ๐Ÿ” โ€“ security dependencies executed before other checks. Downstream applications declare these to enforce auth or policy.
  • deps ๐Ÿงฉ โ€“ general dependencies resolved ahead of phase handlers. Downstream code provides these to inject request context or resources.
  • sys ๐Ÿ—๏ธ โ€“ system steps bundled with Tigrbl that drive core behavior. Maintainers own these and downstream packages should not modify them.
  • atoms โš›๏ธ โ€“ built-in runtime units such as schema collectors or wire validators. These are maintained by the core team.
  • hooks ๐Ÿช โ€“ extension points that downstream packages register to customize phase behavior.

Only secdeps, deps, and hooks are expected to be configured downstream; sys and atom steps are maintained by the Tigrbl maintainers.

Kernelz Labeling ๐Ÿ”Ž

Running apps expose a /system/kernelz diagnostics endpoint that returns the kernel's phase plan for each model and operation. Every entry is prefixed by its phase and a descriptive label, for example:

PRE_TX:secdep:myapp.auth.require_user
HANDLER:hook:wire:myapp.handlers.audit@HANDLER
END_TX:hook:sys:txn:commit@END_TX
POST_HANDLER:atom:wire:dump@POST_HANDLER

The token after the phase identifies the step type:

  • secdep and dep โ€“ security and general dependencies as PRE_TX:secdep:<callable> and PRE_TX:dep:<callable>.
  • hook:sys โ€“ built-in system hooks shipped with Tigrbl.
  • hook:wire โ€“ default label for user hooks including module/function name + phase.
  • atom:{domain}:{subject} โ€“ runtime atoms, e.g. atom:wire:dump.

These labels allow downstream services to inspect execution order and debug how work is scheduled. ๐Ÿงญ

Configuration Overview โš™๏ธ

Operation Config Precedence ๐Ÿงฎ

When merging configuration for a given operation, Tigrbl layers settings in increasing order of precedence:

  1. defaults
  2. app config
  3. API config
  4. table config
  5. column .cfg entries
  6. operation spec
  7. per-request overrides

Later entries override earlier ones, so request overrides win over all other sources. This can be summarized as overrides > opspec > colspecs > tabspec > apispec > appspec > defaults.

Schema Config Precedence ๐Ÿงฌ

Tigrbl merges schema configuration from several scopes. Later layers override earlier ones, with the precedence order:

  1. defaults (lowest)
  2. app configuration
  3. API configuration
  4. table configuration
  5. column-level cfg values
  6. op-specific cfg
  7. per-request overrides (highest)

This hierarchy ensures that the most specific settings always win. ๐Ÿฅ‡

Table-Level ๐Ÿงพ

  • __tigrbl_request_extras__ โ€“ verb-scoped virtual request fields.
  • __tigrbl_response_extras__ โ€“ verb-scoped virtual response fields.
  • __tigrbl_register_hooks__ โ€“ hook registration entry point.
  • __tigrbl_nested_paths__ โ€“ nested REST path segments.
  • __tigrbl_allow_anon__ โ€“ verbs permitted without auth.
  • __tigrbl_owner_policy__ / __tigrbl_tenant_policy__ โ€“ server vs client field injection.
  • __tigrbl_verb_aliases__ & __tigrbl_verb_alias_policy__ โ€“ custom verb names.

Routing ๐Ÿงญ

  • __tigrbl_nested_paths__ for hierarchical routing.
  • __tigrbl_verb_aliases__ for custom verbs.
  • __tigrbl_verb_alias_policy__ to scope alias application.

Persistence ๐Ÿ’พ

  • Mixins such as Upsertable, Bootstrappable, GUIDPk, Timestamped.
  • Policies __tigrbl_owner_policy__ and __tigrbl_tenant_policy__.
  • transactional decorator for atomic RPC + REST endpoints.

Security ๐Ÿ”

  • Pluggable AuthNProvider interface.
  • __tigrbl_allow_anon__ to permit anonymous access.

Default Precedence ๐Ÿ”ง

When assembling values for persistence, defaults are resolved in this order:

  1. Client-supplied value
  2. API default_factory
  3. ORM default
  4. Database server_default
  5. HTTP 422 if the field is required and still missing

Database Guards ๐Ÿ›ก๏ธ

Tigrbl executes each phase under database guards that temporarily replace commit and flush on the SQLAlchemy session. Guards prevent writes or commits outside their allowed phases and only permit commits when Tigrbl owns the transaction. See the runtime documentation for the full matrix of phase policies.

The START_TX phase opens a transaction and disables session.flush, allowing validation and hooks to run before any statements hit the database. Once the transaction exists, PRE_HANDLER, HANDLER, and POST_HANDLER phases permit flushes so pending writes reach the database without committing. The workflow concludes in END_TX, which performs a final flush and commits the transaction when the runtime owns it. โœ…

Response and Template Specs ๐Ÿ“‘

Customize outbound responses with ResponseSpec and TemplateSpec. These dataclasses control headers, status codes, and optional template rendering. See tigrbl/v3/response/README.md for field descriptions and examples.

Dependencies ๐Ÿ“ฆ

  • SQLAlchemy for ORM integration.
  • Pydantic for schema generation.
  • ASGI-native routing and dependency injection.

Best Design Practices โœ…

The following practices are the canonical, production-ready patterns for building on Tigrbl. Each rule is explained and demonstrated with approved usage. These are not optionalโ€”adhering to them keeps the runtime predictable, preserves hook lifecycle guarantees, and ensures schema consistency across REST and RPC surfaces.

1) Never import SQLAlchemy directly or bypass Tigrbl APIs

Why: Direct imports bypass Tigrbl's compatibility layer and make it harder to evolve internal dependencies. Use the Tigrbl exports so your code stays aligned with the frameworkโ€™s versioned ASGI API.

โœ… Preferred:

from tigrbl import Base, TigrblApp, TigrblApi
from tigrbl.types import Integer, String, Mapped
from tigrbl.types import Depends, HTTPException, Request

๐Ÿšซ Avoid:

from sqlalchemy import Integer, String
from some_framework import Depends

2) Do not coerce UUIDs manually

Why: Tigrbl schemas and types already normalize UUIDs. Manual coercion creates inconsistent behavior across engines and breaks schema-level validation.

โœ… Preferred:

from tigrbl.types import PgUUID, uuid4, Mapped

class Item(Table):
    __tablename__ = "items"
    id: Mapped[PgUUID] = acol(primary_key=True, default=uuid4)

๐Ÿšซ Avoid:

from uuid import UUID

item_id = UUID(str(payload["id"]))

3) Use engine specs for persistence, not ad-hoc engines

Why: Engine specs make persistence declarative, testable, and compatible with engine resolution across app, API, table, and op scopes.

โœ… Preferred:

from tigrbl.engine.shortcuts import engine_spec
from tigrbl.engine.decorators import engine_ctx

spec = engine_spec(kind="postgres", async_=True, host="db", name="app_db")

@engine_ctx(spec)
class App:
    ...

๐Ÿšซ Avoid:

from sqlalchemy.ext.asyncio import create_async_engine

engine = create_async_engine("postgresql+asyncpg://...")

4) Never call DB session methods directly

Why: Direct calls bypass the hook lifecycle and the database guards. Use model handlers or app.<Model>.handlers.<op> so hooks, policies, and schema enforcement run consistently.

โœ… Preferred:

result = await Item.handlers.create(payload, ctx=request_ctx)
# or from a Tigrbl app instance:
result = await app.Item.handlers.create(payload, ctx=request_ctx)

๐Ÿšซ Avoid:

db.add(item)
await db.execute(statement)

5) Always use encapsulated payloads as inputs and outputs

Why: Tigrbl expects request/response envelopes to preserve metadata, support policy enforcement, and keep REST/RPC in lockstep.

โœ… Preferred:

from tigrbl import get_schema

CreateIn = get_schema(Item, "create", "in")
CreateOut = get_schema(Item, "create", "out")

payload = CreateIn(name="Widget")
result = await Item.handlers.create(payload, ctx=request_ctx)
response = CreateOut(result=result)

๐Ÿšซ Avoid:

payload = {"name": "Widget"}
result = await Item.handlers.create(payload)

6) Encapsulation must use get_schema(...)

Why: get_schema guarantees the envelope is aligned to the configured schema and respects schema overrides, request extras, and response extras.

โœ… Preferred:

ListIn = get_schema(Item, "list", "in")
ListOut = get_schema(Item, "list", "out")

๐Ÿšซ Avoid:

from pydantic import BaseModel

class ListIn(BaseModel):
    payload: dict

7) Table must be the first inherited class for all models

Why: Tigrbl inspects base classes for lifecycle and configuration. Putting Table first preserves deterministic MRO behavior.

โœ… Preferred:

from tigrbl.orm.tables import Table
from tigrbl.orm.mixins import Timestamped

class Item(Table, Timestamped):
    __tablename__ = "items"

๐Ÿšซ Avoid:

class Item(Timestamped, Table):
    __tablename__ = "items"

8) Never call db.flush() or db.commit()

Why: The hook lifecycle owns transactional boundaries. Manual flush or commit short-circuits phase guards and can corrupt the request lifecycle.

โœ… Preferred:

@hook_ctx(ops="create", phase="HANDLER")
async def handler(ctx):
    await Item.handlers.create(ctx["request"].payload, ctx=ctx)

๐Ÿšซ Avoid:

db.flush()
db.commit()

9) Use ops for new REST/RPC methodsโ€”never add ad-hoc framework routes

Why: Ops keep routing, schemas, hooks, and policies unified. Custom custom framework routes bypass these guarantees.

โœ… Preferred:

from tigrbl import op_ctx

@op_ctx(name="rotate_keys", method="POST", path="/keys/rotate")
async def rotate_keys(payload, *, ctx):
    return await Key.handlers.rotate(payload, ctx=ctx)

๐Ÿšซ Avoid:

from some_framework import APIRouter

router = APIRouter()

@router.post("/keys/rotate")
async def rotate_keys(payload):
    ...

10) Use context decorators where appropriate

Why: Context decorators (engine_ctx, schema_ctx, op_ctx, hook_ctx) provide explicit, declarative binding of behavior and are resolved deterministically by the runtime.

โœ… Preferred:

from tigrbl import hook_ctx, op_ctx, schema_ctx
from tigrbl.engine.decorators import engine_ctx

@engine_ctx(kind="sqlite", mode="memory")
class Item(Table):
    __tablename__ = "items"

@schema_ctx(ops="create", cfg={"exclude": {"id"}})
class ItemCreateSchema:
    model = Item

@op_ctx(name="export", method="GET", path="/items/export")
async def export_items(payload, *, ctx):
    return await Item.handlers.list(payload, ctx=ctx)

@hook_ctx(ops="create", phase="PRE_HANDLER")
async def validate(ctx):
    ...

Engine & Provider examples ๐Ÿ› ๏ธ

from tigrbl.engine.shortcuts import engine_spec, prov
from tigrbl.engine._engine import Engine, Provider

# Build an EngineSpec from a DSN string
spec = engine_spec("sqlite://:memory:")

# Or from keyword arguments
spec_pg = engine_spec(kind="postgres", async_=True, host="db", name="app_db")

# Lazy Provider from the spec
provider = prov(spec)            # same as Provider(spec)
with provider.session() as session:
    session.execute("SELECT 1")

# Engine faรงade wrapping a Provider
eng = Engine(spec_pg)
async with eng.asession() as session:
    await session.execute("SELECT 1")

# Direct Provider construction is also supported
provider_pg = Provider(spec_pg)

Attaching engine contexts ๐Ÿ”Œ

engine_ctx binds database configuration to different layers. It accepts a DSN string, a mapping, an EngineSpec, a Provider, or an Engine. The resolver chooses the most specific binding in the order op > table > api > app.

Engine precedence ๐Ÿฅ‡

When engine contexts are declared at multiple scopes, Tigrbl resolves them with strict precedence:

  1. Op level โ€“ bindings attached directly to an operation take highest priority.
  2. Table/Model level โ€“ definitions on a model or table override API and app defaults.
  3. API level โ€“ bindings on the API class apply when no model-specific context exists.
  4. App level โ€“ the default engine supplied to the application is used last.

This ordering ensures that the most specific engine context always wins.

Declarative bindings ๐Ÿ“

from types import SimpleNamespace
from tigrbl.engine.shortcuts import prov, engine

app = SimpleNamespace(db=prov(kind="sqlite", mode="memory"))
alt = SimpleNamespace(db=engine(kind="sqlite", mode="memory"))

class API:
    db = {"kind": "sqlite", "memory": True}

class Item:
    __tablename__ = "items"
    table_config = {"db": {"kind": "sqlite", "memory": True}}

async def create(payload, *, db=None):
    ...

create.__tigrbl_engine_ctx__ = {
    "kind": "postgres",
    "async": True,
    "host": "db",
    "name": "op_db",
}

Decorative bindings ๐ŸŽ›๏ธ

from tigrbl.engine.decorators import engine_ctx
from tigrbl.engine.shortcuts import prov, engine

@engine_ctx(prov(kind="sqlite", mode="memory"))
class App:
    pass

@engine_ctx(engine(kind="sqlite", mode="memory"))
class DecoratedAPI:
    pass

@engine_ctx(kind="sqlite", mode="memory")
class DecoratedItem:
    __tablename__ = "items"

@engine_ctx(kind="postgres", async_=True, host="db", name="op_db")
async def decorated_create(payload, *, db=None):
    ...

Swarmauri class + Tigrbl lifecycle integration ๐Ÿงฌ

If you need to run concrete Swarmauri classes inside Tigrbl's runtime, see:

The bridge examples cover two integration styles:

  • Factory + schema-rich envelope (swarmauri_tigrbl_bridge.py)

    • Swarmauri Pydantic JSON workflows (model_validate_json, model_dump_json, model_json_schema) with HumanMessage.
    • A Swarmauri Factory invocation during PRE_HANDLER via hook_ctx.
    • Tigrbl default verbs (create, get, list, update, delete) plus a custom op.
    • engine_ctx at model and operation scope.
    • Generated OpenAPI and OpenRPC documents mounted from the same model bindings.
  • Smoother direct-model flow (swarmauri_tigrbl_bridge_smooth.py)

    • Uses hooks + default create persistence to normalize Swarmauri payloads.
    • Adds a Conversation table with a persisted one-to-many relationship to messages.
    • Avoids extra json_schema fields in request/response payload contracts.
    • Returns HumanMessage.model_validate_json(...) directly from a custom op.
    • Uses the concrete model classes themselves to derive input/output schema docs.

Glossary ๐Ÿ“–

  1. Tables
  2. Schemas
  3. Schema Overlays (Request Extras)
  4. Phases
  5. Phase Lifecycle
  6. Request
  7. Request Ctx
  8. Default Flush
  9. Core
  10. Core_Raw

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

tigrbl-0.3.7.dev2.tar.gz (250.7 kB view details)

Uploaded Source

Built Distribution

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

tigrbl-0.3.7.dev2-py3-none-any.whl (376.7 kB view details)

Uploaded Python 3

File details

Details for the file tigrbl-0.3.7.dev2.tar.gz.

File metadata

  • Download URL: tigrbl-0.3.7.dev2.tar.gz
  • Upload date:
  • Size: 250.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","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 tigrbl-0.3.7.dev2.tar.gz
Algorithm Hash digest
SHA256 f80ffe0c41337e54b2626864af0647678934928ce6241b2c2907400cd7b349f8
MD5 142dc9aa1169550e442bde8d8571f710
BLAKE2b-256 8a01cab9df8e29794e642d5d4ff9c81715fc2f4272e0e129cd769e916fba2a2e

See more details on using hashes here.

File details

Details for the file tigrbl-0.3.7.dev2-py3-none-any.whl.

File metadata

  • Download URL: tigrbl-0.3.7.dev2-py3-none-any.whl
  • Upload date:
  • Size: 376.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","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 tigrbl-0.3.7.dev2-py3-none-any.whl
Algorithm Hash digest
SHA256 c8f4ebc49163ccbf6606269c004f99c272e3ee8009785201aab7735c1a5ab93c
MD5 712514d4c7d2903ee332ddbaeaa02ec7
BLAKE2b-256 c94d4b62881d59ec7c91e2f0ec6867c2561f234d4a614f2d37a74a2becc157da

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