Skip to main content

A NestJS-inspired, batteries-included web framework for Python, built on top of FastAPI.

Project description

Austial icon

Austial

A NestJS-style, batteries-included web framework for Python, built on top of FastAPI.

PyPI version Latest tag Last commit MIT License Python 3.11+ Built with FastAPI Managed with uv

Austial

Austial gives Python the exact developer experience of NestJS: decorator-driven modules/controllers/providers, real constructor-based dependency injection, the full request lifecycle (guards, pipes, interceptors, exception filters, middleware), a config layer, a database layer, Terminus-style health checks, a testing module -- and a CLI so you can scaffold new projects and artifacts the same way nest new/nest generate do.

This repository (austial-py) is the framework itself -- an installable library, no bundled sample app. To see it in action, scaffold a new project with the CLI (see Quickstart below); that generated project is the "hello world" app, kept separate from the framework's own source tree.

Why

FastAPI is a fantastic ASGI toolkit, but it doesn't prescribe an application architecture. Austial is opinionated on top of FastAPI the way Nest is opinionated on top of Express/Fastify: modules own controllers and providers, providers get dependency-injected by type, and the request pipeline (guard → pipe → interceptor → handler → filter) is a first-class concept instead of something you hand-roll with dependencies everywhere.

Architecture at a glance

NestJS Austial
@Module() @Module(imports=, controllers=, providers=, exports=)
@Controller() / @Get() etc. @Controller(prefix) / @Get/@Post/@Put/@Patch/@Delete/@Options/@Head
@Injectable() @Injectable(scope=Scope.DEFAULT | Scope.TRANSIENT)
Constructor DI Container resolves __init__ type hints recursively, singleton by default
NestFactory.create(AppModule) AustialFactory.create(AppModule) -> AustialApplication
app.listen(3000) await app.listen(8000)
CanActivate / @UseGuards CanActivate ABC + ExecutionContext, @UseGuards(...)
NestInterceptor / @UseInterceptors NestInterceptor ABC (intercept(context, call_next)) + @UseInterceptors(...)
PipeTransform / ValidationPipe PipeTransform ABC + ValidationPipe
ExceptionFilter / @Catch ExceptionFilter ABC + @Catch(...), default AllExceptionsFilter
NestMiddleware, MiddlewareConsumer NestMiddleware ABC, configure(consumer) on modules
ConfigModule.forRoot() ConfigModule.for_root(env_file=".env") / ConfigService
TypeOrmModule.forRootAsync DatabaseModule.for_root_async(use_factory=, inject=) (SQLAlchemy async)
@nestjs/terminus austial.terminus.HealthCheckService + MemoryHealthIndicator, DatabaseHealthIndicator
@nestjs/testing austial.testing.Test.create_testing_module(...).compile()
nest new / nest generate austial new <name> / austial generate|g module|controller|service|resource <name>

A note on file names

Nest names files with dots (health.controller.ts) because Node resolves modules by explicit relative path strings. Python's import a.b instead resolves a as a package and b as a submodule -- a literal file health.controller.py isn't importable via a normal import statement. So Austial uses underscore suffixes instead: health_controller.py, health_service.py, health_module.py, health_dto.py. The directory layout still mirrors Nest 1:1 -- one folder per feature under src/modules/.

Quickstart

Austial is published on PyPI -- install the CLI and scaffold a new project:

uv tool install austial                 # or: pipx install austial / pip install austial
austial new my-app                      # scaffold a new project
cd my-app
uv sync
cp .env.example .env
uv run austial serve                    # http://localhost:8000, auto-reload

austial new scaffolds a small health-check "hello world" app -- GET /, GET /health, GET /health/protected, /docs (Swagger UI) -- see Using the CLI below for the full generator reference.

Developing Austial itself

git clone https://github.com/austial/austial-py
cd austial-py
uv sync --all-extras
uv run pytest

Linting, type-checking & pre-commit hooks

uv run ruff check .           # lint
uv run ruff format .          # format
uv run mypy austial tests     # type-check

uv run pre-commit install --hook-type pre-commit --hook-type pre-push
uv run pre-commit run --all-files   # run every hook once, on demand

Once installed, git commit runs formatting/linting/type-checks automatically, and git push also runs the test suite -- mirroring a typical Nest project's husky + lint-staged setup. Projects scaffolded with austial new get the same .pre-commit-config.yaml out of the box.

Using the CLI

austial new scaffolds a brand-new project exactly like nest new:

uv run austial new my-app
cd my-app
uv sync
cp .env.example .env
uv run austial serve

New projects depend on the published austial package from PyPI by default. If you're developing the framework itself, point new projects at your local checkout instead with --link: austial new my-app --link /path/to/austial-py -- this adds an editable [tool.uv.sources] entry so uv sync resolves austial from your local checkout rather than PyPI.

austial generate (alias austial g) adds artifacts to an existing project, patching src/app_module.py's imports/imports=[...] array automatically -- just like nest g:

uv run austial generate module cats        # src/modules/cats/cats_module.py
uv run austial generate controller cats    # src/modules/cats/cats_controller.py
uv run austial generate service cats       # src/modules/cats/cats_service.py
uv run austial generate resource cats      # module + full CRUD controller/service/dto/entity
uv run austial g resource cats             # same as above, short alias

Repository layout

austial-py/
├── pyproject.toml          # package "austial", console-script entry point
├── LICENSE                  # MIT
├── assets/                   # logo.svg (+ logo-dark.svg for dark mode) / icon.svg / apple-icon.png
├── austial/                 # the framework (installable library) -- this *is* the package
│   ├── common/               # decorators, guards, interceptors, pipes, filters,
│   │                         # middleware, exceptions, logger
│   ├── core/                  # metadata/reflector, DI container, router builder,
│   │                         # AustialFactory / AustialApplication
│   ├── config/                 # ConfigModule / ConfigService
│   ├── database/                # DatabaseModule (SQLAlchemy async)
│   ├── terminus/                 # HealthCheckService + health indicators
│   ├── testing/                   # Test.create_testing_module(...)
│   └── cli/                        # `austial new` / `generate` / `serve` + templates
└── tests/                    # tests for the framework itself -- no sample app needed;
    ├── unit/                   # test modules/controllers are defined inline per test file
    └── e2e/

There's deliberately no src/ here -- that's what austial new generates for your project, kept out of the framework's own repo. Test files use Nest's *.spec.ts naming convention (*_spec.py here); pyproject.toml's [tool.pytest.ini_options] is configured to discover them.

Request lifecycle

Every route runs through the same pipeline Nest uses:

guards -> pipes -> interceptors (wrapping) -> handler -> exception filters
from austial import Controller, Get, UseGuards, UseInterceptors
from austial.common.interceptors import TransformInterceptor

from .api_key_guard import ApiKeyGuard


@Controller("cats")
class CatsController:
    @Get(":id")
    @UseGuards(ApiKeyGuard)
    @UseInterceptors(TransformInterceptor())
    async def find_one(self, id: int):
        ...

Note path params use Nest's :id syntax (translated to FastAPI's {id} under the hood), so route strings read exactly like their Nest counterparts.

License

MIT

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

austial-0.1.1.tar.gz (157.1 kB view details)

Uploaded Source

Built Distribution

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

austial-0.1.1-py3-none-any.whl (65.8 kB view details)

Uploaded Python 3

File details

Details for the file austial-0.1.1.tar.gz.

File metadata

  • Download URL: austial-0.1.1.tar.gz
  • Upload date:
  • Size: 157.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.4

File hashes

Hashes for austial-0.1.1.tar.gz
Algorithm Hash digest
SHA256 31090c14b244d76b1ef7627ddb06f1fe195086aa6bd2a2797c3fc0e1de543091
MD5 a03f3e20cd81bb112d2297057ff779b3
BLAKE2b-256 42f5f8fc883cb464e7763eb3e6d229f5edbdce6cf7251233e7447b7d56975372

See more details on using hashes here.

File details

Details for the file austial-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: austial-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 65.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.4

File hashes

Hashes for austial-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c1d3beff19b33bcd46ec789361ebcc399a44cff449232b7a71fe397a35f47125
MD5 3967405745f410d30465001e3de7c6ac
BLAKE2b-256 1ee939d8287181573eb7e32c6740251c7c28b627a71fb0493a6cda9a838f388c

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