datalogic-py
Part of datalogic-rs: one engine, every runtime.
Python bindings for datalogic-rs,
a Rust implementation of JSONLogic. Same rules,
same semantics as the Rust crate, with the compile-once /
evaluate-many pattern exposed natively: compile a rule once and
evaluate it against thousands of data inputs without re-parsing. Every
binding runs the same core and passes the same 2,128-case conformance
battery (66 suites).
For the cross-runtime overview and the API-tier model every binding implements, see the repo README.
New in v5. There is no v4 Python package. If you called the v4 Rust crate or the v4
@goplasmatic/datalogicWASM package, see MIGRATION.md for the engine's v4 → v5 changes.
Install
pip install datalogic-py
PyPI carries pre-built wheels for:
| Platform | Architectures |
|---|---|
| Linux (manylinux) | x86_64, aarch64 |
| Linux (musllinux) | x86_64, aarch64 |
| macOS | x86_64, arm64 |
| Windows | x86_64, arm64 |
The package supports Python 3.10 and newer through the
PEP 384 stable ABI (abi3): one
wheel per platform covers every CPython release from 3.10 on, and the
package metadata lists 3.10 through 3.14.
Every wheel ships type stubs and a py.typed marker
(PEP 561), so mypy, pyright and
IDE autocomplete see the whole API.
The PyPI distribution is datalogic-py and the module is
datalogic_py: pip install datalogic-py, then import datalogic_py.
Python module names cannot contain hyphens.
Quick start
from datalogic_py import apply
result = apply(
{"if": [{">": [{"var": "score"}, 50]}, "pass", "fail"]},
{"score": 75},
)
# -> "pass"
API reference
The Python binding mirrors the Rust engine's API tier model; the API surface table below lists every tier.
One-shot: apply(rule, data)
from datalogic_py import apply
apply({"+": [1, 2, 3]}, {}) # 6
apply({"var": "user.age"}, {"user": {"age": 25}}) # 25
apply({"and": [{">": [{"var": "x"}, 0]}, True]}, {"x": 5}) # True
Both arguments accept Python dict / list values. The binding walks
them straight into the engine's arena values, with no JSON text and no
intermediate tree, which beats a json.dumps → evaluate_str →
json.loads round trip at every payload size the boundary benchmark
measures. Conversion work scales with node count, so large payloads
cost more (see Performance). If your data is already
JSON text, call the *_str entry points (Rule.evaluate_str,
Session.evaluate_str) and skip conversion; if you evaluate the same
payload repeatedly, parse it once into a
DataHandle. For
payloads with types the walk doesn't cover, see
Type conversion below.
Engine: Engine().eval(rule, data)
Construct an Engine when you need templating mode or any non-default
configuration:
from datalogic_py import Engine
engine = Engine() # default config
engine.eval({"==": [1, 1]}, {}) # True
# Templating mode: multi-key objects become output templates
templating_engine = Engine(templating=True)
templating_engine.eval(
{"name": {"var": "user.name"}, "ok": {">": [{"var": "score"}, 50]}},
{"user": {"name": "Ada"}, "score": 99},
)
# {"name": "Ada", "ok": True}
Engine(...) takes keyword arguments only:
| Argument | Default | Effect |
|---|---|---|
templating |
False |
Multi-key objects compile as output templates (Templating mode) |
config |
None |
Evaluation semantics, as a dict or JSON str (Engine configuration) |
custom_operators |
None |
{name: callable} host operators (Custom operators) |
strict_operator_names |
False |
Refuse a custom operator named like a built-in |
template_key_escape |
None |
One character that marks a template key as a literal field |
families |
None (every family) |
The operator families the engine has besides the JSONLogic core (Operator families) |
Compile once: Engine().compile(rule) → Rule.evaluate(data)
Compile the rule once when you'll evaluate it against many data inputs.
from datalogic_py import Engine
engine = Engine()
rule = engine.compile({"if": [{">": [{"var": "score"}, 50]}, "pass", "fail"]})
for payload in batch:
result = rule.evaluate(payload) # accepts a dict
fast = rule.evaluate_str(json_text) # accepts a JSON string (skips dict conversion)
Rule is thread-safe: hand the same instance to worker threads and
evaluate concurrently. The binding releases the GIL for each Rust
evaluate call, so a multi-threaded server runs evaluations in parallel.
Compiling and check release it too, once the binding has read the
rule into Rust.
compile_template(rule) and compile_strict(rule) choose the
templating mode for one compile, whatever the engine was built with.
The engine's custom operators, template key escape and families still
apply. See Templating mode.
Checking a rule before it runs
compile accepts a rule that will fail at evaluation, such as one that
calls an operator the engine doesn't have. check reports every
problem the engine can see before the rule runs, each with an
RFC 6901 JSON Pointer into
the rule:
engine.check({"if": [True, {"vr": "x"}, {"map": [1]}]})
# [{"code": "UnknownOperator", "severity": "error", "pointer": "/if/1",
# "message": "unknown operator `vr`; did you mean `var`?", "operator": "vr"},
# {"code": "ArgumentCount", "severity": "error", "pointer": "/if/2",
# "message": "`map` takes exactly 2 arguments, not 1", "operator": "map"}]
engine.check({"a": {"var": "x"}, "b": 1}, "template") # [] (mode: "engine", "strict" or "template")
An "error" will fail; a "warning" runs but is probably a mistake
(for example an argument the operator never evaluates).
compile_checked(rule) compiles only a rule with no error diagnostic
and otherwise raises CompileError, whose .diagnostics holds the
same list:
from datalogic_py import CompileError
try:
engine.compile_checked({"vr": "x"})
except CompileError as e:
print(e.diagnostics[0]["code"]) # "UnknownOperator"
Three more calls describe rules and the engine without running anything:
rule = engine.compile({"if": [{">": [{"var": "user.age"}, 18]}, "adult", {"var": "fallback"}]})
rule.facts()
# {"reads": [["fallback"], ["user", "age"]], "computed_reads": False,
# "reads_complete": True, "reads_data": True,
# "operators": [">", "if", "val"], "custom_operators": [], "deterministic": True}
engine.operators() # one dict per built-in operator: name, aliases, family, min_args, ...
engine.truthy({}) # False: the engine's truthiness (an empty dict is falsy, like [])
engine.truthy("[]") # False: a str is JSON text
facts() lists each data path the rule reads as its segments, after
the optimizer, so a folded branch is not listed. reads_complete is
False when a path is computed at runtime or a custom operator runs,
and deterministic is False for now and any custom operator.
operators() returns a list in the schema of the
operator catalogue.
Session: hot loops
For batches, open a Session: it keeps one arena and resets it at the
start of each evaluate call, so steady-state evaluation reuses memory
instead of allocating per call.
from datalogic_py import Engine
engine = Engine()
rule = engine.compile({"+": [{"var": "x"}, 1]})
with engine.session() as sess:
for payload in batch:
result = sess.evaluate(rule, payload)
Open one Session per worker thread: only the thread that created a
session may call it. Engine and Rule are both thread-safe, so share
those.
Data handles, typed results, and batch evaluation
The ABI v2 tiers. A DataHandle is an immutable, pre-parsed JSON
document: parse a payload once and every evaluation against it skips
JSON parsing and dict conversion. Handles are engine-independent (one
handle can feed rules compiled by different engines), safe to share
across threads for reads, and not consumed by evaluation; the binding
frees the native memory when Python garbage-collects the handle.
from datalogic_py import DataHandle
data = DataHandle('{"age": 25, "status": "active"}') # raises ParseError on bad JSON
data = DataHandle({"age": 25, "status": "active"}) # or any JSON-shaped value, copied once
data.allocated_bytes # bytes held by the handle's arena
rule.evaluate_data(data) # thread-safe, like rule.evaluate
rule.evaluate_data_str(data) # same, JSON str out
sess.evaluate_data(rule, data) # hot path: session arena + no parse
sess.evaluate_data_str(rule, data)
For predicates and scalar results, the typed session evaluations skip the result conversion too:
ok = sess.evaluate_bool(rule, data) # strict JSON boolean
n = sess.evaluate_int(rule, data) # exact integer result
f = sess.evaluate_float(rule, data) # any JSON number
t = sess.evaluate_truthy(rule, data) # JSONLogic truthiness, never mismatches
evaluate_bool, evaluate_int, and evaluate_float raise
EvaluateError with error_type == "TypeMismatch" when the rule
evaluates fine but the result is not of the requested type. A datetime
or duration result counts as a string, the JSON type it serialises to,
so the message reads result is not a boolean (got string).
evaluate_truthy coerces any result through the engine's configured
truthiness rules (the same coercion if/and/or apply).
The batch entry points evaluate a whole set in one native call and report failures per item, so one bad input leaves its neighbours unaffected:
from datalogic_py import BatchItemError
# One rule, many payloads:
results = sess.evaluate_batch(rule, [d0, d1, d2])
# Many rules, one payload (the rule-set / feature-flag shape):
results = sess.evaluate_many([r0, r1], data)
for i, r in enumerate(results):
if isinstance(r, BatchItemError): # not raised; a result object
print(f"item {i} failed: {r.message} ({r.tag}, operator={r.operator})")
else:
print(f"item {i}: {r}") # the item's JSON string
Typed and batch evaluations take data handles only, and sessions stay
single-threaded. A typed call or evaluate_batch raises
EvaluateError with error_type == "InvalidArgument" when the rule
was compiled by a different engine than the session's;
evaluate_many reports such a rule as its item's BatchItemError
(tag == "InvalidArgument") and evaluates the rest.
API surface
| Tier | Entry point | Use when |
|---|---|---|
| One-shot | apply(rule, data) |
Ad-hoc evaluation, one rule + one data shape |
| Engine | Engine().eval(rule, data) |
Custom configuration (templating, custom operators, config) |
| Compile once | Engine().compile(rule).evaluate(data) |
Same rule evaluated against many data inputs |
| Compile mode | engine.compile_template(rule) / engine.compile_strict(rule) |
One rule in a templating mode other than the engine's |
| Checked | engine.check(rule, mode=None) / engine.compile_checked(rule) |
Find every problem in a rule before it runs |
| Introspection | rule.facts() / engine.operators() / engine.truthy(value) |
What a rule reads, which operators exist, the engine's truthiness |
| Session | with engine.session() as sess: … |
Hot loops: reuse one arena across evaluations |
| Data handle | DataHandle(json or value) → sess.evaluate_data(rule, data) |
Same payload evaluated many times: parse or convert once, zero work per call |
| Typed | sess.evaluate_bool/int/float/truthy(rule, data) |
Predicates and scalar results, no JSON decode on the way out |
| Batch | sess.evaluate_batch(rule, datas) / sess.evaluate_many(rules, data) |
Many evaluations per native call, per-item errors |
| Metered | engine.eval_metered(rule, data, budget=None) / rule.evaluate_metered(data, budget=None) |
The operations an evaluation charges, optionally capped |
| Traced | engine.evaluate_with_trace(logic_json, data_json, mode=None) |
Step-by-step debugging; feeds the React debugger |
datalogic_py.__version__ reports the installed version.
Custom operators
Pass custom_operators={"name": callable} to Engine(...). Each callable
receives the operator's pre-evaluated arguments as a JSON-array string and
returns a JSON string of the result:
import json
from datalogic_py import Engine
engine = Engine(custom_operators={
"double": lambda args_json: json.dumps(json.loads(args_json)[0] * 2),
})
engine.eval_str('{"double": [21]}', '{}') # "42"
Built-ins win: a custom registration of a built-in name (+, if,
var, ...) never dispatches. With strict_operator_names=True the
engine refuses such a name instead: Engine(...) raises
EvaluateError with error_type == "ConfigurationError". The option
also refuses a name that begins with the template key escape. A name
whose family you leave out with families is free for a custom
operator. Callbacks run with the GIL held.
Engine configuration
Pass config= to Engine(...) to change evaluation semantics. The value
is a dict (or a JSON string) with an optional preset plus per-field
overrides. Unknown keys and values raise EvaluateError with
error_type == "ConfigurationError":
from datalogic_py import Engine, EvaluateError
strict = Engine(config={"preset": "strict"})
try:
strict.eval({"+": ["", 1]}, {}) # strict rejects non-numeric coercion
except EvaluateError as e:
print(e.error_type) # "Thrown" (a NaN payload)
lenient = Engine(config={"division_by_zero": "return_null"})
lenient.eval({"/": [1.5, 0]}, {}) # None
| Key | Values |
|---|---|
preset |
"default", "safe_arithmetic", "strict" |
arithmetic_nan_handling |
"throw_error", "ignore_value", "coerce_to_zero", "return_null" |
division_by_zero |
"return_saturated", "throw_error", "return_null", "return_infinity" |
loose_equality_errors |
bool |
missing_var |
"null" (default: a missing variable reads as null), "error" (raises VariableNotFound) |
truthy_evaluator |
"javascript", "python", "strict_boolean" |
numeric_coercion |
object of bools: empty_string_to_zero, null_to_zero, bool_to_number, reject_non_numeric |
max_recursion_depth |
integer >= 1 |
ops_budget |
integer >= 1, or null for unbounded (caps the work one evaluation may do; crossing it raises BudgetExceeded) |
The preset applies first; the remaining keys override individual fields
on top of it. Every binding parses this JSON with the same core code,
so a config that works here works in every other binding. The Rust
crate's
EvaluationConfig
documents the full semantics of each knob.
"missing_var": "error" turns a typo in a path into an error instead
of a None that flows on. A default ({"var": ["x", 0]}), a present
null, missing, missing_some and exists are not misses, and
try catches the error:
engine = Engine(config={"missing_var": "error"})
engine.eval({"var": "user.nmae"}, {"user": {"name": "Ada"}})
# EvaluateError: Variable not found: user.nmae (error_type "VariableNotFound")
engine.eval({"var": ["user.nmae", "anon"]}, {"user": {"name": "Ada"}}) # "anon"
Operator families
families=[...] keeps the engine to the JSONLogic core plus the
families you name, using the family names of engine.operators():
"ExtString", "ExtArray", "ExtObject", "ExtMath",
"ExtControl", "ErrorHandling", "DateTime", "Tensor", "Flagd"
("Core" is always there). A family you leave out is not there for
that engine: its names compile as unknown operators, which fail at
evaluation with InvalidOperator (and are errors in check and
compile_checked), and a custom operator may take them. An unknown
family name raises EvaluateError with
error_type == "ConfigurationError".
strings_only = Engine(families=["ExtString"])
strings_only.eval({"upper": "abc"}, None) # "ABC"
strings_only.eval({"abs": -1}, None) # EvaluateError, error_type "InvalidOperator"
Metering: what a rule costs
eval_metered returns (result_json, ops): the result as a JSON str
and the operations the evaluation charged, so you can see what a rule
costs whether or not a budget is set. Rule.evaluate_metered(data, budget=None) does the same on an already-compiled rule.
engine = Engine()
engine.eval_metered({"map": [{"var": "xs"}, {"*": [{"var": ""}, 2]}]}, {"xs": [1, 2, 3]})
# ('[2,4,6]', 10)
# The optional `budget` argument caps the operations for that one call,
# overriding the engine's `ops_budget` config key.
engine.eval_metered(rule, data, budget=100_000)
One operation is one node the engine dispatches, one item an iterator
walks, or whatever an operator charges for the data it moves (the tensor
family prices itself in elements). Literals and constant-folded subtrees
cost nothing. The count is deterministic for a given rule, data and
engine version. Exceeding the budget raises
EvaluateError with .error_type == "BudgetExceeded", carrying
.budget and .spent. The engine refuses the evaluation before doing
the work, and a try in the rule cannot recover from it. A budget
of 0 raises EvaluateError with error_type == "InvalidArgument";
pass None for the engine's own budget.
Error handling
All exceptions descend from DataLogicError:
| Exception | When |
|---|---|
ParseError |
Malformed rule or data JSON, or an unsupported Python type in the input |
EvaluateError |
Every other engine failure: runtime operator errors, unknown operators (InvalidOperator), invalid configuration (ConfigurationError) |
CompileError |
compile_checked refused the rule; .diagnostics lists every problem and error_type is "CompileError" |
Every exception carries .error_type (the engine's error tag),
.operator (the innermost failing operator, or None), .node_ids
(a leaf-to-root breadcrumb of compiled-node ids) and .path (a
root-to-leaf list of step dicts with node_id, operator,
arg_index and json_pointer, or None when no compiled rule was in
scope).
Two error_type tags come from the binding itself rather than the
engine, as in the C ABI: "TypeMismatch" (a typed evaluation whose
result has the wrong type) and "InvalidArgument" (for example a rule
compiled by a different engine passed to a session's handle-based entry
points). Per-item batch failures don't raise; they surface as
BatchItemError values (.tag, .message, .operator) in the result
list.
from datalogic_py import Engine, EvaluateError
engine = Engine()
try:
engine.eval({"+": [1, {"*": ["x", 2]}]}, {}) # arithmetic on a non-numeric string
except EvaluateError as e:
print(e.error_type) # "Thrown" (a NaN payload under the default config)
print(e.operator) # "*", the innermost operator that failed
print(e.path) # [{"operator": "+", "json_pointer": "", ...},
# {"operator": "*", "json_pointer": "/+/1", ...}]
Threading
| Type | Pattern |
|---|---|
Engine |
Build once; share across threads |
Rule |
Compile once; share across threads: evaluate releases the GIL for parallelism |
Session |
One per worker thread; only its creating thread may call it |
DataHandle |
Parse once; immutable, share across threads for reads (evaluation never mutates it) |
Type conversion
The dict-input path walks Python objects into the engine's arena
representation, with a pythonize
fallback for the shapes the walk doesn't cover. Both give the same
results; only speed differs.
Fast direct walk: dict, list, tuple, str, int, float,
bool, None.
Handled by the fallback: set/frozenset (become JSON arrays, in
iteration order), container and scalar subclasses (IntEnum,
OrderedDict, …), mappings and dataclasses.
Conversion details:
float('nan')/float('inf')become JSONnull(they have no JSON encoding)- ints above
2^63 - 1up to2^64 - 1becomefloat; larger ones raiseParseError - dict keys must be
str(anything else raisesParseError), and the engine sees object keys in sorted order, so object-iteration results are deterministic - result dicts come back key-sorted
- a datetime or duration result comes back as a string
Not supported. These raise ParseError:
datetime.datetime,datetime.date: convert to ISO string at the Python edgedecimal.Decimal: convert tofloatorstrbytes,bytearray
For payloads with exotic types, use rule.evaluate_str(json_text) and
bring your own JSON encoder (for example with default=str).
Templating mode
In templating mode a multi-key object is an output template and an
unknown key an output field. Engine(templating=True) sets the mode
for every compile on that engine; compile_template and
compile_strict set it for one compile, so one engine can check a
condition strictly and build an output template:
engine = Engine()
engine.compile({"user": {"var": "name"}, "source": "api"}) # raises EvaluateError ("InvalidOperator")
engine.compile_template({"user": {"var": "name"}, "source": "api"}).evaluate({"name": "ana"})
# {"source": "api", "user": "ana"}
To emit a key that is also an operator name, set template_key_escape
to one character; a key that starts with it becomes a literal field
with the character stripped:
engine = Engine(templating=True, template_key_escape="$")
engine.eval({"$type": "user", "id": {"var": "id"}}, {"id": 7})
# {"id": 7, "type": "user"}
Execution tracing
Engine.evaluate_with_trace(logic, data, mode=None) evaluates with
step-by-step tracing and returns a JSON string envelope. The shape is
identical to the WASM binding's evaluateWithTrace, so the
React debugger component
can consume it:
import json
from datalogic_py import Engine
engine = Engine()
trace = json.loads(engine.evaluate_with_trace(
'{">": [{"var": "score"}, 50]}',
'{"score": 75}',
))
trace["result"] # True
trace["expression_tree"] # {"id", "expression", "children"} tree
trace["steps"] # per-node execution log, in evaluation order
trace["pointers"] # {"<node id>": "<JSON Pointer into the rule>", ...}
Both arguments are JSON strings. mode is "engine" (the default),
"strict" or "template", so you can trace a rule you compile with
compile_template. Runtime failures do not raise: the envelope
carries an error message and a structured_error object instead,
alongside the steps recorded up to the failure. pointers maps each
node id to the JSON Pointer of the rule value it was compiled from, and
is absent when the rule does not compile. The result keeps the key
order the rule produced. Tracing skips the optimizer so every operator
in the rule appears in the trace; use it for debugging, not hot paths.
Performance
Geomean across 51 operator benchmark suites (Apple M2 Pro, median of 3 runs; pairwise shared-suite ratios per the methodology): the native Rust core evaluates at 10.3 ns/op, 7.0× faster than json-logic-engine (compiled, the fastest JS engine), 28.1× faster than jsonlogic-rs (the closest Rust alternative), and 83.6× faster than the json-logic-js reference implementation. The WASM build under Node measures 900.5 ns geomean (88× native); on Node servers, prefer @goplasmatic/datalogic-node.
The pyo3 boundary adds a per-call marshalling cost on top of the core
numbers; the dict paths use direct Python ↔ arena walks, so that cost
scales with payload node count. Use rule.evaluate_str(json_text) when
you already have a JSON string, and a DataHandle when you evaluate the
same payload repeatedly. On the
boundary harness's
8 KB workload, session.evaluate_data_str measures about 1.4 µs/op
against about 12 µs for session.evaluate_str (the per-call JSON
parse) and about 25 µs for the dict path (the per-call conversion
walk). Every evaluate call releases the GIL, so a multi-threaded server
runs evaluations in parallel.
Building from source
The binding lives in
bindings/python/
and builds with maturin (needs a Rust
toolchain and Python 3.10+):
git clone https://github.com/GoPlasmatic/datalogic-rs
cd datalogic-rs/bindings/python
python -m venv .venv && source .venv/bin/activate
pip install maturin pytest
maturin develop --release # build + install into the venv
pytest # run the test suite
Learn more
- datalogic-rs repository
- Rust crate deep-dive
- Documentation: Python
- Online playground
- JSONLogic specification
License
Apache-2.0. See the main repository for source and contribution guidelines.
Metadata
Release files for datalogic-py 5.8.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 | |
|---|---|---|---|
| datalogic_py-5.8.1.tar.gz | 662.4 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| datalogic_py-5.8.1-cp310-abi3-win_arm64.whl | CPython 3.10 | abi3 | Windows ARM64 | Details |
| datalogic_py-5.8.1-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| datalogic_py-5.8.1-cp310-abi3-musllinux_1_2_x86_64.whl | CPython 3.10 | abi3 | Linux musl 1.2+ x86-64 | Details |
| datalogic_py-5.8.1-cp310-abi3-musllinux_1_2_aarch64.whl | CPython 3.10 | abi3 | Linux musl 1.2+ ARM64 | Details |
| datalogic_py-5.8.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| datalogic_py-5.8.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| datalogic_py-5.8.1-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| datalogic_py-5.8.1-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 20.4 MB
Release files / datalogic_py-5.8.1.tar.gz
| Download URL | datalogic_py-5.8.1.tar.gz |
|---|---|
| Size | 662.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6aad0baca9fe519634263a138b7f4c5557f18a0e623e33711c1221762251beb3
|
|
BLAKE2b-256 checksum How to use checksums |
d938776b4c7cbd436ce21a524828bc25ff34b37ea30bfe8d81a84e9a5afe024f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency logRelease files / datalogic_py-5.8.1-cp310-abi3-win_arm64.whl
| Download URL | datalogic_py-5.8.1-cp310-abi3-win_arm64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | CPython 3.10 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
82e81799053f13f1f2c9aee6d18b4c4d60585617936658651e2cc255952aa7d3
|
|
BLAKE2b-256 checksum How to use checksums |
91c92f87c41cf3cf1101b6744e6d60d776ef12ec77d6f2d7e575c0ee221eca8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency logRelease files / datalogic_py-5.8.1-cp310-abi3-win_amd64.whl
| Download URL | datalogic_py-5.8.1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 2.7 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
af5ba4631a9cb901a5d9283d14f3993930766c540d0a11f3533ad4156f9d3cb5
|
|
BLAKE2b-256 checksum How to use checksums |
0b5b85022eeabd9453ee33388005d7e1028945759f8bf2ee1b6e06753dc5c3ac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency logRelease files / datalogic_py-5.8.1-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | datalogic_py-5.8.1-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
c322de360b65427c198ec3c18b129cffcc35a79564775dba941f472ab26cf7a4
|
|
BLAKE2b-256 checksum How to use checksums |
cfc4ab19157dee95b6277eb3b716dbf5fb25fc6c8e3783c30a06864deba2beea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency logRelease files / datalogic_py-5.8.1-cp310-abi3-musllinux_1_2_aarch64.whl
| Download URL | datalogic_py-5.8.1-cp310-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.10 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
ec6c249e59c6c0ab22bdb61a0d406e8e7322ed071eb16d46657023bda4a5e80b
|
|
BLAKE2b-256 checksum How to use checksums |
53abc3b34ceba0946ca3c367b74ecb1474b556b1cd6c165a76ce4df1a75026f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency logRelease files / datalogic_py-5.8.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | datalogic_py-5.8.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.7 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
e777a9089087bee0a619067cba23306272788d82c1871ca6a8635282f85b0b39
|
|
BLAKE2b-256 checksum How to use checksums |
f858a4fc2614b51099b2517ca3c53dd45afa61de9bd5443b48201ece3df052ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency logRelease files / datalogic_py-5.8.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | datalogic_py-5.8.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
71d957877bc99bd354533adbd845b83f33f86bb0b1a2f1878b1d38bf4f8be7af
|
|
BLAKE2b-256 checksum How to use checksums |
55ac65dd1ab0b9ff4582e9bd02de8f5929b6f40c758ed64b14b3e782489cf80a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency logRelease files / datalogic_py-5.8.1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | datalogic_py-5.8.1-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
07772127c79ff255943fbd9443fd600ab07c26ce4393dbdd62a46abc14bd7602
|
|
BLAKE2b-256 checksum How to use checksums |
a00cbe55ceee22f1d9cfe092e3194bbfc0440c0c46ad0948b6268c5c8d5f4dc5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency logRelease files / datalogic_py-5.8.1-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | datalogic_py-5.8.1-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
7d03dd2dcfd1c986effedd363f242c1778e3ba0149b518d669c765bccf8da47b
|
|
BLAKE2b-256 checksum How to use checksums |
84cc78f36c4335f832de989c5cb8a3580e0b572c2a2e8a4a7677551e3563b6b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.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 Oct 8, 2026.
Transparency log