Skip to main content

Python bindings for Reasonable, a reasonably fast OWL 2 RL reasoner

Project description

reasonable (Python bindings)

Python bindings for Reasonable — a reasonably fast OWL 2 RL reasoner implemented in Rust. This package exposes a small, typed API over rdflib terms to run materialization on RDF graphs or files.

Quick Usage

Load from files (Turtle/N3) and materialize inferred triples:

import reasonable

r = reasonable.PyReasoner()
r.load_file("../example_models/ontologies/Brick.n3")
r.load_file("../example_models/small1.n3")
out = r.reason()  # list[tuple[rdflib.term.Node, Node, Node]]
print(len(out))

Reason directly over an rdflib Graph:

import rdflib
import reasonable
from rdflib.term import URIRef

g = rdflib.Graph()
g.add((URIRef("urn:s"), URIRef("urn:p"), URIRef("urn:o")))

r = reasonable.PyReasoner()
r.from_graph(g)
triples = r.reason()

# Optionally collect into a new Graph
g_out = rdflib.Graph()
for s, p, o in triples:
    g_out.add((s, p, o))
print(len(g_out))

Incremental Reasoning with Retraction

Use update_graph() to replace the reasoner's base triples when your graph changes. The reasoner automatically computes a diff and selects incremental materialization (additions only) or full re-materialization (if removals detected):

import rdflib
import reasonable
from rdflib import URIRef, RDF

ontology = rdflib.Graph()
ontology.parse("my_ontology.ttl")

data = rdflib.Graph()
data.add((URIRef("urn:sensor1"), RDF.type, URIRef("urn:TemperatureSensor")))

r = reasonable.PyReasoner()
r.from_graph(ontology + data)
triples = r.reason()  # full materialization

# Later, data changes...
data.remove((URIRef("urn:sensor1"), RDF.type, URIRef("urn:TemperatureSensor")))
data.add((URIRef("urn:sensor2"), RDF.type, URIRef("urn:HumiditySensor")))

r.update_graph(ontology + data)  # replaces base, auto-detects diff
triples = r.reason()             # full re-mat (removals detected)

Install

  • Runtime dependency: rdflib
  • If you have a prebuilt wheel: pip install dist/reasonable-*.whl
  • Build from source (see below) if no wheel is available for your platform.

Developer Install (from source)

Using uv (recommended for local dev):

cd python
# Install project dependencies (including dev tools) into a managed venv
uv sync --group dev

# Build and develop-install the extension module
uv run maturin develop -b pyo3 --release

# Sanity check
uv run python -c "import reasonable; print(reasonable.__version__)"

Without uv (system/venv):

cd python
python -m venv .venv && . .venv/bin/activate  # or use your env
pip install -U maturin
maturin develop -b pyo3 --release
python -c "import reasonable; print(reasonable.__version__)"

API Reference

  • reasonable.PyReasoner()
    • load_file(path: str) -> None
      • Load triples from a Turtle or N3 file. Appends to existing base triples. Raises OSError on missing/invalid paths.
    • from_graph(graph_or_iterable) -> None
      • Appends triples from an rdflib Graph (or any iterable of 3-tuples) to the base. Use update_graph() instead if you need retraction support.
    • update_graph(graph_or_iterable) -> bool
      • Replaces the base triples with the contents of the given graph. Computes a diff against the current base: if only additions are found, the next reason() uses incremental materialization; if any removals are detected, it triggers a full re-materialization. Returns True if removals were detected, False otherwise.
    • reason() -> list[tuple[Node, Node, Node]]
      • Runs OWL 2 RL materialization and returns all known triples (base + inferred) as rdflib nodes. After the first call, subsequent calls are incremental (only processing newly added triples) unless removals were detected via update_graph().
    • reason_full() -> list[tuple[Node, Node, Node]]
      • Forces a full re-materialization from base triples, ignoring any incremental state. Equivalent to clear() followed by reason().
    • clear() -> None
      • Resets all inferred state while keeping base triples. The next reason() call will perform a full re-materialization.
    • get_base_triples() -> list[tuple[Node, Node, Node]]
      • Returns the current base (non-inferred) triples as rdflib nodes. Useful for debugging.

Building Wheels

Build release wheels into dist/:

cd python
uv run maturin build --release --out dist

Install the built wheel:

pip install dist/reasonable-*.whl

Requirements

  • Python 3.9+ (ABI3, built with pyo3/abi3-py39)
  • Rust toolchain (rustup, cargo) for local builds
  • maturin for building wheels
  • rdflib (runtime dependency)

Testing

Run the Python test suite (uses pytest and rdflib):

cd python
uv run pytest -q

Alternatively, with a local venv:

cd python
pip install -U maturin pytest rdflib
maturin develop -b pyo3 --release
pytest -q

Compatibility Notes

  • Python: 3.9+ is required due to the ABI3 setting in the Rust crate (abi3-py39).
  • Platforms: macOS, Linux, and Windows are supported by PyO3/maturin; building from source requires a Rust toolchain.

Troubleshooting

  • ModuleNotFoundError: No module named 'reasonable':
    • Ensure you ran maturin develop in the same environment you’re importing from.
  • Build/link errors on macOS (Xcode/SDK):
    • Install Command Line Tools: xcode-select --install.
  • OSError when calling load_file(...):
    • Check the path and file format (Turtle/N3). Use absolute paths when in doubt.

Contributing (Python bindings)

  • Keep tests under python/tests/ minimal and representative. Prefer inputs from example_models/.
  • Format/lint Python with standard tooling; Rust code follows cargo fmt/cargo clippy.
  • For broader project info (CLI, library, benchmarks), see the repository root README.md.

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

reasonable-0.3.3a4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

reasonable-0.3.3a4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

reasonable-0.3.3a4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

reasonable-0.3.3a4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

reasonable-0.3.3a4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

reasonable-0.3.3a4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

reasonable-0.3.3a4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

reasonable-0.3.3a4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.4 MB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

File details

Details for the file reasonable-0.3.3a4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for reasonable-0.3.3a4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e73eaac84944bbb6ca9b702ce3b22ad0aa78ae321c7277185ca2013eee681a25
MD5 937256c89204c735b3057433dcb014db
BLAKE2b-256 d6790aef898424b4ed43f6ec112eaada65fd2f2eee0255927ee6e1bb8ef27a25

See more details on using hashes here.

File details

Details for the file reasonable-0.3.3a4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for reasonable-0.3.3a4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7301da4517e161e3d74374cb4152da108a252518d0e36118891c536cdf0c6664
MD5 e9ce11ec918d92467ae55482f6ac5014
BLAKE2b-256 c61a7f9d90e9c62a957f694b6c7e78bae8995924ba98f7f85e56bca2facc0190

See more details on using hashes here.

File details

Details for the file reasonable-0.3.3a4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for reasonable-0.3.3a4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6a366b4e154cf5b3a283d9d33d71b9f806ca1a1d07251595b1db4b5952285c9f
MD5 065313548fd010273eab04f49ec2c8ef
BLAKE2b-256 5f25da3b3435bb028eca3d30d8432db9408dfc162ae2c9441886fd3b6126ce1f

See more details on using hashes here.

File details

Details for the file reasonable-0.3.3a4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for reasonable-0.3.3a4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4630240e4f34bbee1c9dabf6b24f96ed61152c98edabaea910a5295542827595
MD5 a6808f1ec130e6621bd0ebaea15d1c56
BLAKE2b-256 d2efd2a8cd3daa904a5a6bcc6ba7f3719d1b594eb79232e71fa4d42fbe5e0006

See more details on using hashes here.

File details

Details for the file reasonable-0.3.3a4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for reasonable-0.3.3a4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e8aef1f3369e9bd5aea1de5282e73709daf10bc4909b32ebf799c2b8bd048753
MD5 e5f6151214256f629bbaba3f701d4bd6
BLAKE2b-256 7950fb6bba862bd42b80a4c3c6a413c5d26b20075452cc9f8036666bfe5253b0

See more details on using hashes here.

File details

Details for the file reasonable-0.3.3a4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for reasonable-0.3.3a4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 acdd5c21e8589dbe131a4235b8561d3d54404866654eb3fd1bc34489ba08de84
MD5 5ba728f6fc9afbb398254536c99b9bf9
BLAKE2b-256 2fe09cfc60241744bf651627f5c34126aef851cc125a61213b7196b62baadbe9

See more details on using hashes here.

File details

Details for the file reasonable-0.3.3a4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for reasonable-0.3.3a4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0051ac55d4891101d7d685421a0673b699491cffd140a3177ea4f36e953227d2
MD5 74a05e2ed9b8527797e2a344e088ae47
BLAKE2b-256 2732e7149fccac9eb485a6d6bd5e31d30055bcb96192c439f347a6e9ee8a25db

See more details on using hashes here.

File details

Details for the file reasonable-0.3.3a4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for reasonable-0.3.3a4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 97346a2306ebed5519964febcc3926266f227aa73e37170f200e6ee18b4aedb3
MD5 7ceb7b7213f20f93a27eb8c7fd61ec37
BLAKE2b-256 c6a47b3fd123bf225d3fb4b4561766c167cbd89f3cb61b5c122efba4e0691561

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page