aflib
Helper library for business logic inside Airflows plpython3u
function bodies.
An Airflows function body is a bare Python snippet with a plpy global. It cannot import
another function body, cannot see the HTTP request, and cannot shape the HTTP response — so
every body ends up re-implementing the same parameter parsing, the same row reading and the
same result envelope. aflib is that plumbing, written once.
Status: early, and deliberately so. Nothing enters this library until it has run on a real Airflows instance — written first as a plain function body, deployed, called, and observed. One version corresponds to one proven capability, which is why the numbers start so low.
Install
Airflows resolves Python packages from public PyPI by name and version only; there is no
local-import, git or private-index route. Declare it in
models/pythonPackages/pythonPackages.airflows:
pythonPackage aflib==0.0.1
Then import it from a function body.
What 0.0.1 gives you
from aflib import BadParameter, Db, fail, ok, params
db = Db(plpy)
try:
receipt_id = params.as_int(p_id_receipt, name="p_id_receipt", required=True)
except BadParameter as exc:
return fail("invalid_param", str(exc))
row = db.query(
'SELECT id, amount FROM "Economic"."Receipt" WHERE id = $1',
[receipt_id], ["integer"],
).one()
if row is None:
return fail("not_found", "No receipt with that id")
return ok(row)
Db(plpy)—plpyis injected, never imported, because the function body is the only composition root available.db.query(...)returns aRowsyou narrow with.one()(Nonefor no row, and it refuses more than one rather than silently taking the first),.rows()for all of them, or.scalar(column)for a single named value.params.as_int/as_bool/as_decimal/as_date/as_json— every HTTP parameter arrives as text and must be declaredtext, so every body converts. These raiseBadParameter, which is the caller's fault and should become a 4xx-shaped failure rather than an uncaught exception.ok(data)/fail(code, message)— a body's only output is its return value, which the platform wraps as[{"result": …}]. There is no status code and no header, so success and failure both have to be expressed inside the value.codec.dumps/loads— JSON that raises on anything it cannot serialize instead of stringifying it.numericcolumns arrive asdecimal.Decimaland are encoded as strings, never floats, so exactness survives the round trip.
Platform constraints worth knowing before you build on it
These are observed on a live instance, not inferred from documentation. They are the reason the library has the shape it does.
- Every HTTP-facing parameter must be declared
text. Declareintegerand the platform bindsvarcharat call time, no candidate signature matches, and the endpoint fails with function does not exist — it cannot be invoked at all. This is not a casting inconvenience; the endpoint is simply unreachable. Convert inside the body instead. - Function bodies compose only through SQL —
SELECT "Schema"."fn"(…). There is no shared module and no package-local import, so a helper another body needs is a database function, not a Python one. - A body cannot see the request or shape the response. Its globals are exactly
GD,SD,args, its declared parameters andplpy: no request object, no undeclared query parameters, no body, no headers. It cannot set a status code, a header or a redirect. jsonbis never decoded — it always arrives asstr, even throughplpy.prepare.numericarrives asdecimal.Decimalandbyteaasbytes; neither is JSON-serializable by default, andnumericis every money column.- Never cache request-scoped state in
GDorSD. Consecutive calls land on different pooled backends, and the connection role varies per caller.
Tests
uv run pytest
The unit tests run against a fake plpy, which verifies control flow and nothing
transactional. Anything involving a savepoint is proven on the platform, not here.
License
MIT — see LICENSE.
Metadata
Release files for aflib 0.0.1
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 | |
|---|---|---|---|---|
| aflib-0.0.1.tar.gz | 17.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aflib-0.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.4 kB
Release files / aflib-0.0.1.tar.gz
| Download URL | aflib-0.0.1.tar.gz |
|---|---|
| Size | 17.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1e2dd4bf7c0eb17027f4844d6438cac91e1f866490f1bb60eab179aa20d8e647
|
|
BLAKE2b-256 checksum How to use checksums |
bf9c19106cd3dad88a1e69990b00756ca9dd5f54801d8782ea8b158fc9f1fc50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / aflib-0.0.1-py3-none-any.whl
| Download URL | aflib-0.0.1-py3-none-any.whl |
|---|---|
| Size | 10.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3be550da3a7946816e8c5ae1d14a82e05b2257aea10cdd386a0ffeb157de5149
|
|
BLAKE2b-256 checksum How to use checksums |
a9d108152f9dc4b209c9f57a86f9abb8c1145453b4d78f6d886cf54e045bb7bb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for aflib 0.0.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.