This release is a pre-release and may not be stable for production use.
tasgi
tasgi means Thread ASGI. It is an experimental ASGI-compatible framework/runtime that keeps transport and protocol handling on the event loop while allowing handler execution on either the asyncio loop or a thread runtime.
Runtime design goal:
- the
tasgipackage itself depends only on the Python standard library - external tools like
coverage,build, andtwineare used only for CI, testing, and packaging
Status
tasgi is currently an alpha-stage project.
- public APIs are still settling
- auth APIs are still evolving
- router/module composition is still evolving
- native HTTP/2 support is still a prototype subset
Treat the current release line as experimental, not stable.
Install
From source:
pip install -e .
tasgi does not require Poetry at runtime. The project is packaged from pyproject.toml
using the standard PEP 517 build flow, so CI and publishing use pip, build, and twine
directly instead of a Poetry-specific workflow.
After packaging to TestPyPI, the intended trial install flow is:
pip install --index-url https://test.pypi.org/simple/ tasgi
Hello World
from tasgi import TasgiApp, TextResponse
app = TasgiApp(docs=True, debug=True)
@app.route.get("/")
async def home(request):
return TextResponse("hello from tasgi")
Run it:
tasgi
Or run the bundled demo app:
python3 examples/service_api/main.py
Router Usage
tasgi now treats app.route as the main HTTP registration surface.
from tasgi import JsonResponse, Router, TasgiApp
users = Router(tags=["users"])
@users.get("/users")
def list_users(request):
return ["alice", "bob"]
app = TasgiApp()
app.include_router(users, prefix="/api")
@app.route.get("/status")
async def status(request):
return JsonResponse({"ok": True})
Core Model
tasgi is layered like this:
socket/transport
-> ASGI boundary
-> tasgi runtime
-> tasgi framework
-> user handlers
Rules:
- network I/O stays on the event loop
- HTTP protocol handling stays on the event loop
- async handlers run on the asyncio loop
- sync handlers run in the tasgi thread runtime
- worker threads never write directly to sockets
Dual Execution Model
App-level execution policy is explicit:
from tasgi import ASYNC_EXECUTION, THREAD_EXECUTION, TasgiApp
app = TasgiApp(default_execution=THREAD_EXECUTION)
@app.route.get("/cpu")
def cpu(request):
...
@app.route.get("/status", execution=ASYNC_EXECUTION)
async def status(request):
...
Request And Response Types
Main public HTTP types:
TasgiAppRouterRequestResponseTextResponseJsonResponseStreamingResponse
Handlers may return Response objects directly, or return typed values when a response model is declared.
OpenAPI And Docs
Built-in docs can be enabled from app config:
from dataclasses import dataclass
from tasgi import TasgiApp
@dataclass
class EchoIn:
message: str
@dataclass
class EchoOut:
echoed: str
app = TasgiApp(
docs=True,
title="tasgi demo",
version="0.1.0a1",
)
@app.route.post("/echo", request_model=EchoIn, response_model=EchoOut)
def echo(request, body: EchoIn) -> EchoOut:
return EchoOut(echoed=body.message)
Default docs endpoints:
/openapi.json/docs
Auth
tasgi includes an experimental pluggable auth layer.
Built-in starters:
BearerTokenBackendAPIKeyBackendBasicAuthBackendRequireAuthenticatedRequireScopeRequireRole
Example:
from tasgi import BearerTokenBackend, Identity, RequireScope, TasgiApp
def validate_token(token: str):
if token == "demo-token":
return Identity(subject="alice", scopes=frozenset({"profile"}))
if token == "admin-token":
return Identity(subject="admin", scopes=frozenset({"admin"}))
return None
app = TasgiApp(auth_backend=BearerTokenBackend(validate_token), docs=True)
@app.route.get("/public", auth=False)
async def public_route(request):
return {"public": True}
@app.route.get("/me", auth=True)
async def me(request):
return {"subject": request.identity.subject}
@app.route.get("/admin", auth=RequireScope("admin"))
async def admin(request):
return {"subject": request.identity.subject}
Auth metadata is also reflected automatically in OpenAPI for built-in auth backends.
Demo App
The bundled service example includes:
- HTTP routes
- router/module composition
- OpenAPI + Swagger UI
- auth examples
- streaming responses
- WebSocket echo
- thread-executed sync handlers
Run:
python3 examples/service_api/main.py
There is also a cleaner modular composition example:
python3 examples/modular_api/main.py
Benchmarks
The benchmark suite exercises loopback TCP requests against a dedicated benchmark app.
Run:
python3 benchmarks/run_benchmarks.py
CI And Publishing
GitHub Actions workflows are set up for both validation and releases:
CIruns on every push and pull request- the primary CI target is free-threaded CPython
3.14t - standard compatibility tests also run on Python 3.14, 3.13, 3.12, and 3.11
- coverage is reported in CI using
coverage run -m unittest discover -s tests - package builds are verified in CI with
python -m buildandpython -m twine check --strict dist/*
Publishing is separated from CI:
Publishruns only on version tags likev0.1.0a1or on published GitHub Releases- release builds run on CPython
3.14t - PyPI upload is configured for Trusted Publishing via GitHub Actions
- before enabling real PyPI releases, do one TestPyPI dry run and confirm a clean install path
Local commands:
python3 -m unittest discover -s tests -v
python3 -m pip install coverage build twine
coverage run -m unittest discover -s tests
coverage report -m
python3 -m build
python3 -m twine check --strict dist/*
Current Limits
- HTTP/2 support is prototype-grade, not production-complete
- auth API is still settling
- route registration APIs changed recently and may still evolve
- no middleware ecosystem yet
- no dependency injection container beyond explicit lightweight helpers
- no production-hardening claims
License
tasgi is licensed under Apache-2.0. See LICENSE and NOTICE.
That keeps the project free to use, including in companies, while preserving the attribution notices when the software is redistributed.
Release Notes
This repository is currently prepared for an alpha-style release, not a stable release.
Before a public non-alpha release, the project still needs:
- final public API freeze
- repository/homepage URLs in package metadata
- a TestPyPI install-and-verify pass
Metadata
Release files for tasgi 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tasgi-0.1.0a1.tar.gz | 72.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tasgi-0.1.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 134.2 kB
Release files / tasgi-0.1.0a1.tar.gz
| Download URL | tasgi-0.1.0a1.tar.gz |
|---|---|
| Size | 72.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7ec12ab1489e769ee76b4f1037cc248a8106d933d7a57813c696e31576c225a8
|
|
BLAKE2b-256 checksum How to use checksums |
8fa75a78efdf6ce2086ea375980bf49c97d82b84ce2c5cbb40aaaec35c3ab8b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 18, 2026.
Transparency logRelease files / tasgi-0.1.0a1-py3-none-any.whl
| Download URL | tasgi-0.1.0a1-py3-none-any.whl |
|---|---|
| Size | 62.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
259f7854b48ebb7b6e2bd02b422e697ba52e060791935abad458a0f4de521870
|
|
BLAKE2b-256 checksum How to use checksums |
0bae3e9ab031691d815570c2c6921db5d9e0e7f0af4aee8629d83d9533ba7547
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 18, 2026.
Transparency logSecurity for tasgi 0.1.0a1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tasgi-0.1.0a1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 18, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.