pyELK
pyELK is a Java-free implementation of the core reasoning behaviour of ELK Reasoner 0.6.0. It provides one typed Python API with a portable pure-Python backend and an optional Rust/PyO3 accelerator. Both backends consume the same deterministic compiled ontology and return the same canonical public values.
The distribution is pyelk-reasoner; the import package is pyelk:
python -m pip install pyelk-reasoner
The separate pyelk distribution on PyPI is an unrelated graph-layout project. A normal
install selects a compatible native wheel when one is published and otherwise installs the
universal Python wheel. Python 3.10 and 3.12 run the complete release suites; the native
module uses the CPython 3.10 limited ABI and is additionally exercised on every supported
CPython minor through 3.14.
Start with the documentation index or the
getting-started guide. The distribution is
pyelk-reasoner; do not install the unrelated pyelk graph-layout package.
Existing 0.1 users should read the 0.2 migration guide
before reusing persisted pyowl-core snapshots or custom encoded-view providers.
First classification
pyELK delegates OWL syntax, structural values, imports, and immutable snapshots to the
independent pyowl-core package. A path, bytes-like value, or caller-owned stream can be
passed directly. Streams require a stable document_iri; pyELK never closes them.
from io import BytesIO
import pyowl_core as owl
from pyelk import Reasoner
document = (
b"Prefix(:=<urn:readme#>) Ontology(<urn:readme> "
b"Declaration(Class(:A)) Declaration(Class(:B)) SubClassOf(:A :B))"
)
options = owl.LoadOptions(
format=owl.DocumentFormat.FUNCTIONAL,
imports=owl.ImportPolicy.IGNORE,
backend=owl.BackendPreference.PYTHON,
)
with Reasoner(document, load_options=options) as reasoner:
byte_result = reasoner.classify()
taxonomy = byte_result.require_complete()
assert reasoner.backend.name in {"python", "rust"}
assert taxonomy.node(owl.Class(owl.IRI("urn:readme#A"))) is not None
stream = BytesIO(document)
with Reasoner(
stream,
document_iri="urn:readme:stream",
load_options=options,
) as reasoner:
assert reasoner.classify() == byte_result
assert not stream.closed
Reasoner also accepts str/PathLike paths, OntologyDocument, every immutable
OntologyView, and SnapshotProvider. Import resolution is explicit through
LoadOptions and an optional pyowl-core ImportResolver; unresolved or intentionally
ignored imports are never silently presented as complete reasoning.
Completeness is part of every answer
Each operation returns ReasoningResult[T], containing value, complete, and canonical
reasons. complete means complete for the pinned ELK 0.6 procedure, not for arbitrary OWL.
Inspect the metadata when a partial value is useful, or call require_complete() before
using a value that must be authoritative.
import pyowl_core as owl
from pyelk import Reasoner
from pyelk.exceptions import IncompleteReasoningError
document = (
b"Prefix(:=<urn:readme#>) Ontology(<urn:readme> "
b"SubClassOf(ObjectAllValuesFrom(:p :A) :B))"
)
options = owl.LoadOptions(
format=owl.DocumentFormat.FUNCTIONAL,
imports=owl.ImportPolicy.IGNORE,
backend=owl.BackendPreference.PYTHON,
)
with Reasoner(document, load_options=options) as reasoner:
result = reasoner.classify()
assert not result.complete
assert any("OBJECT_ALL_VALUES_FROM" in issue.features for issue in result.reasons)
try:
result.require_complete()
except IncompleteReasoningError as error:
assert error.reasons == result.reasons
else:
raise AssertionError("an incomplete result was accepted")
Set ReasonerConfig(unsupported="error") when unsupported ontology constructs should fail
during construction instead of producing an explicitly incomplete result. The exact
construct, polarity, combination, per-operation monitor, and entailment-query boundary are
listed in specs/compatibility.md.
Exact-OM and shared snapshots
When a caller already owns a pyowl-core view, pass it directly. pyELK retains that exact
object, does not parse it again, and never converts public entities into a second OWL model.
An Exact-OM-style owner can expose only owl_snapshot(); it is called once. Source, target,
and bridge views can be combined as an identity-preserving OntologyComposite.
import pyowl_core as owl
from pyelk import Reasoner
options = owl.LoadOptions(
format=owl.DocumentFormat.FUNCTIONAL,
imports=owl.ImportPolicy.IGNORE,
backend=owl.BackendPreference.PYTHON,
)
source = owl.load_snapshot(
b"Prefix(:=<urn:shared#>) Ontology(SubClassOf(:A :B))",
options=options,
)
target = owl.load_snapshot(
b"Prefix(:=<urn:shared#>) Ontology(SubClassOf(:B :C))",
options=options,
)
shared = owl.compose_views(source, target, roles=("source", "target"))
class ExactModel:
def __init__(self, view: owl.OntologyView) -> None:
self.view = view
self.calls = 0
def owl_snapshot(self) -> owl.OntologyView:
self.calls += 1
return self.view
model = ExactModel(shared)
with Reasoner(model) as reasoner:
assert reasoner.ontology is shared
taxonomy = reasoner.classify().require_complete()
public_a = next(entity for entity in shared.signature() if entity.iri.value.endswith("#A"))
assert taxonomy.node(public_a).members[0] == public_a
assert model.calls == 1
pyELK imports neither Exact-OM nor any consumer-private record type. The interoperability
boundary is only pyowl-core's OntologyView/SnapshotProvider contract.
OAEI and process boundaries
For a worker process, persist the shared snapshot with pyowl-core's versioned wire format. The receiving process should verify and memory-map it before constructing the reasoner. No OWL parser runs on this path.
from pathlib import Path
from tempfile import TemporaryDirectory
import pyowl_core as owl
from pyelk import Reasoner
options = owl.LoadOptions(
format=owl.DocumentFormat.FUNCTIONAL,
imports=owl.ImportPolicy.IGNORE,
backend=owl.BackendPreference.PYTHON,
)
document = b"Prefix(:=<urn:wire#>) Ontology(SubClassOf(:A :B))"
original = owl.load_snapshot(document, options=options)
with TemporaryDirectory() as directory:
path = Path(directory) / "ontology.pyocore"
path.write_bytes(owl.encode_snapshot(original))
mapped = owl.open_snapshot(path, mmap=True, verify=True)
try:
with Reasoner(mapped) as reasoner:
assert reasoner.ontology is mapped
assert reasoner.classify().require_complete().nodes
finally:
mapped.close()
This is the supported OAEI-Bio-ML-eval handoff for timeout-isolated workers. Do not serialize private pyELK indexes or consumer records as an interchange format.
Backend selection and diagnostics
The default auto mode uses a compatible native extension when its version/ABI/IR handshake
passes, and otherwise selects Python while retaining the fallback reason. Use
ReasonerConfig(backend="python" | "rust") for a session-specific choice, or these process
controls:
PYELK_BACKEND=auto|python|rustselects the default request;PYELK_PURE_PYTHON=1forces Python and prevents even probing_native;- an explicit Rust request fails with
BackendUnavailableErrorrather than falling back.
Native class-expression queries share the immutable ontology, property closure and rule indexes. Each expression owns only new expressions, changed occurrence/index rows and its saturation contexts. Named-class queries reuse base contexts/taxonomy, and satisfiability or hierarchy queries do not initialize realization. Fresh role identity closure is query-local.
ReasonerConfig(query_cache_bytes=64 * 1024 * 1024) bounds retained native class-query
state and results using conservative allocation charges (including sparse tree-node
occupancy). Entries are evicted in least-recently-used expression order across query tasks;
zero disables retention, and an oversized entry completes uncached. This limit excludes
the one shared base, committed taxonomy/realization, active query workspace and the separate
Boolean entailment cache. It does not alter Python backend caching. Diagnostics expose
class_query_cache_bytes, class_query_cache_limit_bytes, hits, evictions and program/base
preparation counts. Eviction changes neither returned results nor session semantics.
import pyowl_core as owl
from pyelk import backend_report
report = backend_report()
assert report.selection_error is None
assert report.selected in {"python", "rust"}
assert report.core_package_version == owl.__version__
assert report.core_api_version == owl.API_VERSION
assert report.core_model_schema_version == owl.MODEL_SCHEMA_VERSION
assert report.core_wire_format_version == owl.WIRE_FORMAT_VERSION
assert report.core_adapter_protocol_version == owl.ADAPTER_PROTOCOL_VERSION
if report.selected == "python" and report.rust.reason:
print(f"native backend not selected: {report.rust.reason}")
reasoner.backend reports the immutable choice, effective worker count, native availability,
and fallback reason for a live session. reasoner.diagnostics() returns an immutable scalar
mapping. Every session reports its canonical compiler_digest, compiler-cache and private-IR
schema versions, implementation version, total consumer compile time, scalar-row materialization
count, and an exact encoded buffer/copy/segment ledger. ingestion_path is scalar-python,
scalar-wire, or encoded-native; scalar sessions report contractual zero/false encoded
counters. Encoded sessions additionally report view-publication time, native validation,
compilation, session-build, and total native-boundary durations. Recursive composite sessions
count each temporary resolved posting byte and anonymous-scope mapping pair in
encoded_staging_copy_bytes; they never label those bounded metadata copies as zero-copy.
pyelk.core.require_core_compatibility() performs the full pyowl-core package/API/model/wire/
adapter guard explicitly.
Supported reasoning surface
The public facade provides consistency, class and object-property classification, realization, class-expression satisfiability, equivalent/sub/super-class queries, instances/types, object-property views, entity enumeration, and the pinned supported entailment families. It follows OWL 2 Direct Semantics and ELK's quiet inconsistent-ontology values.
The complete fragment is deliberately “ELK 0.6 compatible,” not “all OWL 2 EL.” Named classes/properties, intersections, existential restrictions, the core class axioms, individual equality/difference, supported assertions, domains/ranges, and named property hierarchies/chains are handled according to the pinned converter. Several data constructs, cardinalities, universals, inverses, keys, and other features are ignored or partial with exact completeness reasons. Annotation axioms remain in the shared snapshot but are non-logical to pyELK.
Runtime and current limits
Installed pyELK never launches or embeds Java. Java is used only by opt-in development tools that regenerate or compare frozen ELK 0.6 oracle data; JARs and class files are rejected from release artifacts. The Python fallback also needs no Rust/C/C++ compiler at installation or runtime.
Version 0.2 sessions are immutable. Incremental reasoning, proofs/explanations/tracing, method-for-method OWL API compatibility, datatype reasoning, a CLI, and a Protégé plugin are outside scope. Input syntaxes and import retrieval are exactly those supplied by the installed compatible pyowl-core. Native availability is platform-wheel dependent; Python remains the semantic reference and fallback.
Development verification
The default suite is Java-free:
PYELK_BUILD_PURE=1 PYELK_PURE_PYTHON=1 python -m pytest
ruff format --check .
ruff check .
mypy
lint-imports
The unified frozen-corpus runner covers all 124 upstream ontologies and 138 goldens:
python tests/parity/runner.py --backend python --workers 1
python tests/parity/runner.py --backend rust --workers 1 --workers 0
Integrated benchmark metadata and commands live in benchmarks/manifest.toml
and tools/benchmark.py. Java oracle and performance gates are opt-in and pinned; ordinary
tests and installed artifacts have no Java dependency. See specs/verification.md
for the release gates and specs/traceability.md for the implemented
source-to-test map.
pyELK is an independent Apache-2.0 reimplementation informed by the pinned ELK source and
tests. Attribution and modification details are in NOTICE.pyelk.
Metadata
Release files for pyelk-reasoner 0.2.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 | Actions |
|---|---|---|---|---|
| pyelk_reasoner-0.2.1.tar.gz | 258.3 kB | With provenance | Details for pyelk_reasoner-0.2.1.tar.gz |
Built distributions (wheels)
Total release size: 9.1 MB
Release files / pyelk_reasoner-0.2.1.tar.gz
| Download URL | pyelk_reasoner-0.2.1.tar.gz |
|---|---|
| Size | 258.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cf73555c023c9926471136ee86ee73f14e057a8bd2d2be6f3eb96ab48c125245
|
|
BLAKE2b-256 checksum How to use checksums |
6e79d0458068ade810a1b42204852caa0759339c90c1ca9a50c83d52a4d1f012
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logRelease files / pyelk_reasoner-0.2.1-py3-none-any.whl
| Download URL | pyelk_reasoner-0.2.1-py3-none-any.whl |
|---|---|
| Size | 150.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bdee254ab4c0ee2f8bd6e4629f7c2fb3ca3b133917d842799edd6a03d6952ef3
|
|
BLAKE2b-256 checksum How to use checksums |
abd0101d1d4c5be7044eb4f9e021784fe43208f5f2b77d1a0b3bd68d76d84f38
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logRelease files / pyelk_reasoner-0.2.1-cp310-abi3-win_amd64.whl
| Download URL | pyelk_reasoner-0.2.1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
3a7cb1a572b94436021c6f449117ee7838e6b8024b52a6f1ecb03d7b6aecab46
|
|
BLAKE2b-256 checksum How to use checksums |
d965d0b58089304181dd213197d7f502e633430347addf3e2b8dd5496e97a03a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logRelease files / pyelk_reasoner-0.2.1-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | pyelk_reasoner-0.2.1-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
2a2a125e4670d50ebc8bed42da6b7f160925fd9a3a36e15c44d5f5649655f55e
|
|
BLAKE2b-256 checksum How to use checksums |
04ae9af91fed4091236a5ae2f46047916ba2ecb7b6485bac737a822b34b83006
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logRelease files / pyelk_reasoner-0.2.1-cp310-abi3-musllinux_1_2_aarch64.whl
| Download URL | pyelk_reasoner-0.2.1-cp310-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.10 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
c949a10b22328f18b9030700e4371c2a39c8b09cd5f3759375ea847ce485979a
|
|
BLAKE2b-256 checksum How to use checksums |
3da5c2c5f1c5b0170e0d17536afbe316e7f47d4a8f893c20742b3e86c191c3bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logRelease files / pyelk_reasoner-0.2.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | pyelk_reasoner-0.2.1-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
33de950132c5eb5b14099b7454384ce3604b7bdd95a601124099da0a48b5d546
|
|
BLAKE2b-256 checksum How to use checksums |
9e77e4c7a926f723634af25f99257eb645c53f0f311f347ce5d66cb6459018de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logRelease files / pyelk_reasoner-0.2.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | pyelk_reasoner-0.2.1-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
ab89b36e7e5d80a1779124c05feabdaf4235064b4643611a245809df34b325bd
|
|
BLAKE2b-256 checksum How to use checksums |
8bfc2cee14ecb4cc97a7f0021f63577e4e1097da5326b9bd375ca1505cc47088
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logRelease files / pyelk_reasoner-0.2.1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | pyelk_reasoner-0.2.1-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
e5bef321b74af91ea55e8c2810d8b1bbc8a67bbfb8a61025fd930b0c6c6bbfcd
|
|
BLAKE2b-256 checksum How to use checksums |
e1d2736c00ef82758198e8421fb2b07fd2fd1359532d9fbe4a99073a6875a24b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logRelease files / pyelk_reasoner-0.2.1-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | pyelk_reasoner-0.2.1-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
bed148cd0339f04f7f6ad5c25be7a8daa626c0fc1cc3236d08d9ba12497c8058
|
|
BLAKE2b-256 checksum How to use checksums |
7ee0c298160c268ffc160e181f1972bedf76aa1e09e57fff9cd6f78cf6141751
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 20, 2026.
Transparency logSecurity for pyelk-reasoner 0.2.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.
Full provenance
All 9 files in this release have been uploaded with provenance metadata.
Attestation for pyelk_reasoner-0.2.1.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 20, 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.