dhis2w-ql
d2ql — a pipeline query and transform language with an embedded expression language, d2path.
Pure engine, no DHIS2 required: it queries any JSON-shaped data — lists of dicts, Pydantic models,
local .json/.ndjson files — with a pushdown seam for backends that can answer parts of a query
natively.
This package is the language engine alone: tokenizer, recursive-descent parser, Pydantic AST,
expression evaluator, query planner, and execution engine over a source-agnostic DataSource
protocol. Its only dependency is pydantic. The DHIS2 binding (live DataSource, pushdown
compiler, CLI, MCP tools) lives in the query plugin in dhis2w-core; FHIR is a consumer of the
engine (d2path evaluates over any JSON, and the transform stage can emit FHIR resources)
rather than a dependency.
Install
uv add dhis2w-ql # or: pip install dhis2w-ql
Quickstart — d2path over your own JSON
d2path is the expression layer: path navigation, operators, and ~40 functions with collection
semantics.
from dhis2w_ql import Evaluator, parse_expression
facilities = [
{"name": "Ngelehun CHC", "level": 4, "tags": ["chc", "rural"]},
{"name": "Kailahun MCHP", "level": 4, "tags": ["mchp"]},
{"name": "Bo District", "level": 2, "tags": []},
]
expression = parse_expression("where(level = 4 and tags.count() > 0).name.select(upper())")
print(Evaluator().evaluate(expression, facilities))
# ['NGELEHUN CHC', 'KAILAHUN MCHP']
Quickstart — a full pipeline over in-memory rows
The pipeline layer adds stages (where, select, transform, order, paging, group by,
fold), named definitions, and sinks. InMemoryBinder maps resource names to row lists; any
backend can implement the same DataSource protocol and advertise which filters/ordering/paging
it can execute natively — the planner pushes that prefix down and runs the rest locally.
import asyncio
from dhis2w_ql import InMemoryBinder, QueryEngine, parse
program = parse("""
facilities
| where level = 4
| select name, level
| order name asc
| limit 10
""")
engine = QueryEngine(program, InMemoryBinder({"facilities": facilities}))
result = asyncio.run(engine.run_terminal())
print(result.rows)
# [{'name': 'Kailahun MCHP', 'level': 4}, {'name': 'Ngelehun CHC', 'level': 4}]
Programs can also read local files directly — read("facilities.json") or
read("events.ndjson") as the source — and end in a sink (>> "out.csv",
>> stdout as ndjson).
Language shape
define ActiveAggregates:
dataElements | where domainType = "AGGREGATE"
ActiveAggregates
| where name ~ "ANC"
| select id, name, categoryCombo.name as combo
| transform { code: id, label: name }
| order name asc
| limit 20
>> "elements.csv"
- Expression layer (
d2path): path navigation, operators, and functions with collection semantics — used insidewhere,select,order, andtransform. - Pipeline layer: stages separated by
|, optionally ending in a>>sink. - Definitions:
define NAME: ...anddefine function NAME(args): ...make a.d2qlfile a reusable library of named queries and helpers.
The pipeline | is the stage separator; collection union is the union() function (not the |
operator) to keep the two unambiguous.
Collection semantics in one minute
- Every expression evaluates to a collection; navigation (
a.b) flattens one level per hop. - A single-element collection collapses to its scalar in results.
- String functions (
upper(),lower(),length(),trim(),toChars()) operate on a singleton focus; map them over a collection withselect(...)—name.select(upper()). - Comparisons are existential over collections:
tags = "chc"is true when any element matches.
Documentation
- d2ql tutorial and reference
- d2path reference and the generated example catalog — 140 examples covering every function, each parsed and evaluated in CI against this engine
- Language semantics and the cookbook
- Runnable sample programs:
examples/d2ql/in the repository — every file is parse-tested in CI
The curated catalogs ship in the package: dhis2w_ql.SAMPLES (sample programs) and
dhis2w_ql.DOC_EXAMPLES (the evaluator-verified example catalog behind the docs page).
Metadata
Release files for dhis2w-ql 1.17.0
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 | |
|---|---|---|---|---|
| dhis2w_ql-1.17.0.tar.gz | 48.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dhis2w_ql-1.17.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 104.2 kB
Release files / dhis2w_ql-1.17.0.tar.gz
| Download URL | dhis2w_ql-1.17.0.tar.gz |
|---|---|
| Size | 48.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
15f31d46a493869b7c32c4b3f630567658018a6f19b77cb575c0dc39090727ad
|
|
BLAKE2b-256 checksum How to use checksums |
d592b43e0a9c7d06d79e442fd82a9ec3bf5c6ab5767fc94ef552c8ea6c17f3ab
|
| 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 Sep 11, 2026.
Transparency logRelease files / dhis2w_ql-1.17.0-py3-none-any.whl
| Download URL | dhis2w_ql-1.17.0-py3-none-any.whl |
|---|---|
| Size | 56.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d87a996bc3bad8487bcd047243e4777982baff3450c30c5621ed98b972ea6c72
|
|
BLAKE2b-256 checksum How to use checksums |
69565b3476bcb0d435e10d9503c377e604da8c0705706e7cb65fc17285e219e5
|
| 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 Sep 11, 2026.
Transparency logSecurity for dhis2w-ql 1.17.0
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 dhis2w_ql-1.17.0.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 Sep 11, 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.