rxeval
Run the logic inside an ODK/OpenRosa form — relevant, constraint,
required, calculate — from Python. The engine is Rust with no
dependencies; this is a binding to it.
A form is a small program. Until something runs it, a server can only take whatever a device sends and hope the device was right.
Python is where ODK forms are already built — pyxform is Python — so the check that matters most belongs in the script that builds the form, before it is published, rather than after a week of fieldwork.
pip install rxeval
Will this form travel?
The ODK ecosystem has two evaluation engines: JavaRosa, inside ODK
Collect and KoboCollect, and Enketo's openrosa-xpath-evaluator, inside
web forms. Neither is a superset of the other, and the gaps do not announce
themselves — an expression Collect cannot evaluate usually yields nothing
rather than an error, so the form fills in, the interview finishes, and a
column comes back empty.
check_form reads a form and says which of its rules will behave
differently, before anyone collects with it:
import rxeval
for issue in rxeval.check_form("survey.xml"):
print(issue["says"])
/data/resident[2]/name (relevant): a bare positional predicate — JavaRosa
returns nothing for [n]; use [position() = n] on Collect / KoboCollect.
Write [position() = 2] instead.
/data/total (calculate): /p/morador/maior, which this form's instance has no
node for — the path matches nothing, so the rule reads an empty node-set:
a calculation comes out 0, a comparison comes out false, and a relevant
hides its question for the whole of fieldwork, identically on both
engines. Write /data/morador/maior instead.
Each issue is a dict: path, rule, expression, construct, breaks,
effect, suggestion, and says — the whole sentence, already written.
An empty list means the form travels.
Every rule behind this was decided by putting the same expression to both reference engines and reading the two answers. Of 126 expressions in the corpus the two agree on 99 and disagree with each other on 26, each recorded with the side rxeval follows and why.
What the rules say about a submission
findings = rxeval.submission_findings("survey.xml", "submission.xml")
for f in findings:
print(f["kind"], f["path"], f["says"])
kind is constraint, required, calculation or not-evaluated. A rule
the engine could not evaluate comes back as not-evaluated, never as a
pass: a rule that did not run has not been satisfied, and reporting it as
clean would be the one failure worth avoiding.
today and now default to the submission's own metadata, so a date rule
is judged against the day the work was done — otherwise a submission that
was valid on collection starts failing later, and the report changes while
the data does not.
One expression, for working it out
rxeval.eval_expression("count(/data/resident)", "submission.xml") # '3'
An expression this engine cannot evaluate raises, rather than returning a plausible value.
Filling a form, not only judging one
s = rxeval.Session("survey.xml", today="2026-08-14", now="2026-08-14T09:00:00Z")
s.set("/data/age", "9")
out = s.recompute()
out["calculated"] # {'/data/adult': 'no', '/data/years_left': '9'}
out["relevant"] # {'/data/guardian': True, ...}
out["missing"] # ['/data/guardian']
out["invalid"] # [] — rejected answers, with the form's own message
s.add_row("/data/resident")
s.instance_xml() # what would be submitted
Calculations run in dependency order, so one feeding another settles in a single pass, and only paths whose value actually changed are reported.
Every function takes either a path or the XML itself: a caller holding XML should not have to write it to a file first, and a caller holding a path should not have to read it.
Links
- Documentation and the full story: https://milkway.github.io/rxeval/
- Source: https://github.com/milkway/rxeval
- The Rust crate: https://crates.io/crates/rxeval
- rxform, which turns an XLSForm spreadsheet into the form this runs
Licence
BSD-2-Clause.
Release files for rxeval 0.1.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 | |
|---|---|---|---|
| rxeval-0.1.1.tar.gz | 83.8 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| rxeval-0.1.1-cp38-abi3-win_amd64.whl | CPython 3.8 | abi3 | Windows x86-64 | Details |
| rxeval-0.1.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| rxeval-0.1.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| rxeval-0.1.1-cp38-abi3-macosx_11_0_arm64.whl | CPython 3.8 | abi3 | macOS 11.0+ ARM64 | Details |
| rxeval-0.1.1-cp38-abi3-macosx_10_12_x86_64.whl | CPython 3.8 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 4.0 MB
Release files / rxeval-0.1.1.tar.gz
| Download URL | rxeval-0.1.1.tar.gz |
|---|---|
| Size | 83.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2fe607ec65a8afa877f74908230c29fa7d28755fc4c39f930efc548b963fe6f1
|
|
BLAKE2b-256 checksum How to use checksums |
b4bf4e863eac7ba4a71a5ea355897fac426284f0086b5c5b09ee96a993322608
|
| 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 Aug 15, 2026.
Transparency logRelease files / rxeval-0.1.1-cp38-abi3-win_amd64.whl
| Download URL | rxeval-0.1.1-cp38-abi3-win_amd64.whl |
|---|---|
| Size | 731.3 kB |
| Tags | CPython 3.8 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
e9099ed301f3fa1fdb70f23078d0f932b5cf2077fa2b48e885254e68dc707d13
|
|
BLAKE2b-256 checksum How to use checksums |
c5e18546b5654c842ddf0f7192c91b3ab6cf2c6adfdb9df8f84d3a3162ff79de
|
| 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 Aug 15, 2026.
Transparency logRelease files / rxeval-0.1.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rxeval-0.1.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 830.6 kB |
| Tags | CPython 3.8 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
5f5d677a6a55a90c0645c1050e51c201084ce43aa12d703591cea8c957970326
|
|
BLAKE2b-256 checksum How to use checksums |
3cb96e74adde36ab286a49744f9f28b1e298b12306005730d38a3b955543eef4
|
| 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 Aug 15, 2026.
Transparency logRelease files / rxeval-0.1.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rxeval-0.1.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 787.9 kB |
| Tags | CPython 3.8 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
79b9ac10a677373aa0f77189e9b1895cbce1df22074d31bbfd544e902fb7fe50
|
|
BLAKE2b-256 checksum How to use checksums |
38577d20d7800f573d17e6df4b1495178359713667e24a3a679e3834d502ead7
|
| 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 Aug 15, 2026.
Transparency logRelease files / rxeval-0.1.1-cp38-abi3-macosx_11_0_arm64.whl
| Download URL | rxeval-0.1.1-cp38-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 743.8 kB |
| Tags | CPython 3.8 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
fd13275d7ac229501bf641de024752481f55ccee36af18f78a52e832a8e7d4dd
|
|
BLAKE2b-256 checksum How to use checksums |
bf7258d4462d70d1eabf8b47ad29220066c291b73ad510e10b780edcd3786bfe
|
| 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 Aug 15, 2026.
Transparency logRelease files / rxeval-0.1.1-cp38-abi3-macosx_10_12_x86_64.whl
| Download URL | rxeval-0.1.1-cp38-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 783.9 kB |
| Tags | CPython 3.8 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
8e3fd520f75a2507409f692604a227c0030f81b8c892bcd7539295bfa078df82
|
|
BLAKE2b-256 checksum How to use checksums |
fdfc32bf84e1bf386f9ef65b0b3f0ec657c23488096420f01e2976451e9e8adb
|
| 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 Aug 15, 2026.
Transparency log