This release is a pre-release and may not be stable for production use.
rowstile for Python
pip install --pre rowstile (--pre while only an alpha is published) installs the rowstile command (rowstile init, dev, migrate, review; also
python -m rowstile) and the SDK for Python apps. Extras bring the integrations' dependencies:
rowstile[fastapi], [sqlalchemy], [psycopg], [asyncpg]. Python 3.11 or newer.
The SDK for Python apps on a rowstile policy: every transaction signs in as whoever the request or
the job acts for, refused writes become a 403 with the database's reason, rows the user can't see a 404,
and the app refuses to start on a connection that skips row-level security. It holds no rowstile logic: it
calls the authz.* functions the policy made, and translates their answers.
from fastapi import FastAPI
from sqlalchemy.ext.asyncio import create_async_engine
from rowstile.fastapi import Rowstile
engine = create_async_engine("postgresql+asyncpg://app@db/app")
app = FastAPI()
Rowstile(app, engine, user=current_user) # current_user(request): its user's id, or None; before adding routes
| module | what |
|---|---|
rowstile |
acting_as(who), @job(who), Principal, Refused, NotFound, refusal(exc), error_code(exc) (rowstile's code for any database error: AZ709), act_as_sql() |
rowstile.fastapi |
Rowstile(app, engine, user=...): the request's principal, 403/404 problem bodies, the start-up check |
rowstile.sqlalchemy |
install(engine) (sync or async; SQLModel too), ids(type, perm) for where, perms_of() for a list's buttons, can() (Queries[ObjectType, Permission]() has the three taking only the generated client's names, so a misspelled one doesn't type-check), expect() for Core updates and deletes, why_stale() for the ORM's StaleDataError |
rowstile.psycopg |
transaction(conn, who), atransaction(aconn, who), expect(), aexpect() |
rowstile.asyncpg |
transaction(conn, who), expect() |
rowstile.alembic |
include_name, include_object: autogenerate leaves rowstile's objects alone |
rowstile.testing |
pytest fixtures: as_user, assert_refused, assert_not_found (awaited, with an async function), authz_owner_url, authz_app_url; database_per_worker(url): a copy of the migrated test database for each pytest-xdist worker |
Who a transaction acts for: 42 or "42" (a user), ("service", 3) (another principal type of the policy),
or None (nobody: only what anyone may see; None given to a call is nobody too, whoever the code around
it acts for). A plain id is always a user's, whatever it holds: "service:3" is the user with that id, so an
id from outside (a username, an identity provider's subject) can't name a service. Principal.parse("service:3")
reads back what str() wrote, for text your own code wrote. Every transaction signs in, even when nobody is signed in, and nothing
uses a session-level SET, so pools and poolers in transaction mode are safe; behind one that keeps no prepared
statements, turn the driver's off (Behind a pooler).
With FastAPI: user(request) runs in a middleware that Rowstile(...) adds, so give it the session or the
token to read from the request itself. What a middleware of yours puts on request.state is there only if
that middleware was added after Rowstile(...) (Starlette runs the one added last first); added before, it
hasn't run yet. user may raise an HTTPException. The start-up check runs whether or not the app has a lifespan. WebSockets
are not signed in: use rowstile.acting_as() in the endpoint. An engine in AUTOCOMMIT can't be signed in
(the sign-in lasts a transaction): its queries fail with NotSignedIn.
Policy changes ship as migrations for your tool (rowstile migrate, with tool = "alembic" in
rowstile.toml). The types and permissions of your policy are generated names (rowstile client py), so a
misspelled permission doesn't type-check.
integrations/fastapi/ is the conformance suite: a small FastAPI app on SQLAlchemy (async, asyncpg) and
Alembic, and the checks every supported stack passes (integrations/fastapi/test.sh).
Metadata
Release files for rowstile 0.1.0a5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rowstile-0.1.0a5.tar.gz | 309.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rowstile-0.1.0a5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 646.1 kB
Release files / rowstile-0.1.0a5.tar.gz
| Download URL | rowstile-0.1.0a5.tar.gz |
|---|---|
| Size | 309.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e2944019a9545e5e284025dda9c24ae733072ea9306ee2a0c598e24d4ab25c5f
|
|
BLAKE2b-256 checksum How to use checksums |
4bdb831e76285c3f76ffd87530993abf8a4dd86bca47b4a112dba1ab25b6f980
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 6, 2026.
Transparency logRelease files / rowstile-0.1.0a5-py3-none-any.whl
| Download URL | rowstile-0.1.0a5-py3-none-any.whl |
|---|---|
| Size | 336.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
253a5fb0e8c28c02e680d9e620eb1eb540238833c4abc9429edc61af1559f89a
|
|
BLAKE2b-256 checksum How to use checksums |
850da855b1d8d18b209c987af939d0e49359d8977fe2b22b2dfc1dba3188ab0a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 6, 2026.
Transparency log