Skip to main content

Almasix

Laravel's application shape, in async Python.

A full-stack web framework on FastAPI and Starlette — routing, validation, an ORM, a view engine, auth, queues, mail, cache, events, a scheduler, and a first-class CLI — arranged the way Laravel arranges them, and asynchronous all the way down.

PyPI downloads CI coverage tests python docs license

Why Almasix

Python has excellent HTTP libraries and very few opinions about what an application looks like. Almasix supplies the opinions. It takes the conventions that make a Laravel codebase legible on first read — the directory layout, service providers, facades, fluent builders, Route groups, Eloquent-style models, Blade-style templates, Artisan-style commands — and implements them in modern Python. Requests, the ORM, queue workers, and the scheduler all run on asyncio, and the FastAPI application underneath is never taken away from you.

It is a parity project, not an homage. Each area of the framework is built against the corresponding page of Laravel's documentation, method by method, and every deliberate divergence is named in Almasix's own page for that feature — so Str, Collection, the query builder, and the scheduler behave the way your muscle memory expects, while async/await, type hints, context managers, and dataclasses are used where Python has the better answer.

Piece What it is
Almasix (almasix) the framework
almasix new the application installer
Smith (python smith …) the in-app CLI — prefer python smith serve / make:model / loupe; bare smith only after pip install -e . of the app

| Prism (almasix.prism) | the view engine — .prism.html templates, directives, components, stacks | | Articulate (almasix.orm) | the ORM — models, relationships, migrations, pagination, on SQLAlchemy Core |

A tour in five files

Routes are declarative and grouped, controllers are plain classes, and route names and middleware sit where you'd look for them:

# routes/web.py
from app.http.controllers.post_controller import PostController
from almasix.routing import Route

with Route.group(middleware=["web"]):
    Route.get("/posts", [PostController, "index"], name="posts.index")
    Route.get("/posts/{post}", [PostController, "show"], name="posts.show")

Models carry their own casts, scopes, and relationships:

# app/models/post.py
from app.models.user import User
from almasix.orm import Model, SoftDeletes, relation


class Post(SoftDeletes, Model):
    fillable = ("title", "body", "published")
    casts = {"published": "bool", "published_at": "datetime"}

    def scope_published(query):
        return query.where("published", True)

    @relation
    def author(self):
        return self.belongs_to(User)

Controllers read like their Laravel counterparts, with await at the edges:

# app/http/controllers/post_controller.py
from app.models.post import Post
from almasix.prism import view
from almasix.http import Controller


class PostController(Controller):
    async def index(self):
        posts = await Post.query().published().with_("author").latest().get()
        return view("posts.index", {"posts": posts})

Templates are Prism — Blade's directives, compiled to Python:

{{-- resources/views/posts/index.prism.html --}}
@extends('layouts.app')

@section('content')
  @foreach(posts as post)
    <article>
      <h2>{{ post.title }}</h2>
      <p>by {{ post.author.name }} — {{ post.created_at }}</p>
    </article>
  @endforeach
@endsection

Console commands and scheduled work are declared together, and run under smith:

# routes/console.py
from almasix.console import Artisan, schedule


def send_digest(command) -> int:
    command.info("digest sent")
    return 0


Artisan.command("digest:send", send_digest).purpose("Mail yesterday's digest")

schedule.command("digest:send").daily_at("07:00").timezone("Africa/Nairobi").without_overlapping()
schedule.command("model:prune").daily().on_one_server()

Getting started

Create an application

python -m venv .venv && source .venv/bin/activate
pip install almasix

almasix new blog
cd blog
pip install -e .        # the framework requirement is already satisfied
python smith serve      # always works; bare `smith` also works after this install

almasix new writes a complete application: app/, bootstrap/, config/, routes/, resources/views with error pages, database/migrations, storage/, a Vite config, and a root smith script. Prefer python smith … from the app root (same idea as php artisan). Installing the application (pip install -e .) also links a smith console script into that virtualenv. Installing only the framework gives you the global almasix command — not smith.

Work on the framework

git clone https://github.com/almasix-dev/almasix.git && cd almasix
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

make test          # full unit + smoke suite
make test-cov      # the same, with the coverage gate
make lint          # ruff
make docs          # the documentation site, locally

What ships today

The framework is built in milestones, each closed against a Laravel documentation page. Closed today:

  • The basics — routing and route groups, controllers, middleware and aliases, requests and responses, session, CSRF, validation with form requests, URL generation, error handling and the debug page, logging, asset bundling.
  • Prism views — layouts and sections, includes, control directives, components and slots, stacks, and a dd() dump page.
  • Articulate ORM — models with casts and serialization, the whole relationship surface, eager loading, soft deletes, pruning, migrations, seeding, pagination, and streaming reads through lazy collections.
  • Digging deeper — the Smith console with prompts and closure commands, the task scheduler (frequencies, constraints, hooks, sub-minute tasks), cache, Redis, queues and workers, mail, notifications, events, the filesystem, collections, helpers and Str, the HTTP client, localization, and encryption.
  • Security — authentication guards and providers, hashing, gates and policies, email verification, password confirmation and resets.

Every closed milestone ships four things: the implementation, tests, a documentation page, and a runnable demonstration in the living example app.

Documentation

website/ holds 54 pages of application-developer documentation (Astro Starlight), written to follow Laravel's structure page for page — including a section per method for collections, strings, and helpers. Read it at almasix-dev.github.io/almasix, or run make docs for a local copy at http://localhost:4321.

examples/progress is the living example — a real Almasix application that demonstrates each closed milestone through routes you can visit and smith progress:* commands you can run. Its /progress page is the project's milestone board.

How the project is built

docs/PLAN.md is the binding architecture and milestone document: 51 milestones, each mapped to the Laravel documentation it must match, with the parity audit and the named deviations recorded in place. docs/SMOKE.md records the exit criteria that close a milestone.

The gates are enforced in CI on Python 3.11, 3.12, and 3.13:

Gate Command
Lint + format (pinned ruff) make lint
Milestone smoke tests make smoke
Contract regressions make regression
Full suite, coverage ≥ 98% (aim 100%) make test-cov

make lint runs ruff check and ruff format --check against an exact ruff==0.16.6 pin and an explicit rule selection (E4,E7,E9,F,I,UP,B,RUF100).

Currently 1,886 tests at 99.38% coverage.

Status

M39 docs journey and M38 deployment ops closed on the stability track (after M51, M44, and the M25 Mongo audit). Package version is 0.4.0 in-tree — tag/publish when you cut the GitHub Release. Next up: M37 — API tokens. See docs/PLAN.md.

Repository layout

src/almasix/
  framework/     # Application, container, providers, bootstrap
  config/        # env + config repository
  http/          # kernel, request, response, middleware
  routing/       # Route DSL → FastAPI bridge
  validation/    # form requests, rules, messages
  orm/           # Articulate — models, relations, builder, migrations
  prism/      # Prism views — compiler, directives, components
  auth/          # guards, providers, gates and policies
  console/       # Smith commands, prompts, scheduler, loupe
  queue/         # jobs, dispatcher, workers, failed jobs
  cache/         # cache repository and stores
  mail/          # mailables and transports
  notifications/ # channels and notifiables
  events/        # dispatcher, listeners, subscribers
  filesystem/    # Storage disks
  client/        # HTTP client
  support/       # collections, helpers, Str, Number
  translation/   # __(), trans_choice(), locales
  installer/     # almasix new
  smith/         # the smith CLI
docs/            # PLAN.md, SMOKE.md — the binding project documents
website/         # the documentation site (Astro Starlight)
examples/        # the living example application
tests/           # unit, smoke, and regression suites
smith            # root script → run as `python smith …`

Contributing

Read docs/PLAN.md first — it is the source of truth for what belongs where and what parity means for the area you are touching. Work in milestone order, keep the coverage gate green, add the documentation page alongside the code, and extend examples/progress so the new surface can be demonstrated, not just claimed.

License

MIT © Almasix Contributors

Download files

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

Source Distribution

almasix-0.4.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

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

almasix-0.4.0-py3-none-any.whl (789.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: almasix-0.4.0.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for almasix-0.4.0.tar.gz
Algorithm Hash digest
SHA256 2bbc80016b6cb4421b4a62d931f1d7bf6a13fa8258e2e968c5678bc3c9f7c5a0
MD5 f0f53ca57b7e44b9104786993f70198b
BLAKE2b-256 3838fe33c16aec720630296c3c24f6aa369e66cc9de8f49205a117afe375e274

See more details on using hashes here.

Provenance

The following attestation bundles were made for almasix-0.4.0.tar.gz:

Publisher: publish.yml on almasix-dev/almasix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: almasix-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 789.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for almasix-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 472acd9b41a0e8b102a6d859b9eaade6f7b8a8a751316d579c80257ed609a7bc
MD5 b2b62d0cd7ca7c8c0430f977a6cd1ccc
BLAKE2b-256 95b21ddbd0b3683757fba1b20e9e4e80c00617488545c41135562f584eab4768

See more details on using hashes here.

Provenance

The following attestation bundles were made for almasix-0.4.0-py3-none-any.whl:

Publisher: publish.yml on almasix-dev/almasix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.9.3

2 files

0.9.2

2 files

0.9.1

2 files

0.9.0

2 files

0.8.1

2 files

0.8.0

2 files

0.7.0

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.1

2 files

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.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