datalogic-py 5.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. datalogic_py-5.0.0/Cargo.toml +41 -0
  2. datalogic_py-5.0.0/PKG-INFO +253 -0
  3. datalogic_py-5.0.0/README.md +226 -0
  4. datalogic_py-5.0.0/bindings/python/.gitignore +20 -0
  5. datalogic_py-5.0.0/bindings/python/Cargo.lock +516 -0
  6. datalogic_py-5.0.0/bindings/python/Cargo.toml +56 -0
  7. datalogic_py-5.0.0/bindings/python/README.md +226 -0
  8. datalogic_py-5.0.0/bindings/python/src/conv.rs +30 -0
  9. datalogic_py-5.0.0/bindings/python/src/engine.rs +325 -0
  10. datalogic_py-5.0.0/bindings/python/src/error.rs +118 -0
  11. datalogic_py-5.0.0/bindings/python/src/lib.rs +50 -0
  12. datalogic_py-5.0.0/bindings/python/src/session.rs +142 -0
  13. datalogic_py-5.0.0/bindings/python/tests/test_apply.py +52 -0
  14. datalogic_py-5.0.0/bindings/python/tests/test_compile.py +92 -0
  15. datalogic_py-5.0.0/bindings/python/tests/test_custom_operators.py +116 -0
  16. datalogic_py-5.0.0/bindings/python/tests/test_errors.py +84 -0
  17. datalogic_py-5.0.0/bindings/python/tests/test_session.py +74 -0
  18. datalogic_py-5.0.0/crates/datalogic-rs/CHANGELOG.md +223 -0
  19. datalogic_py-5.0.0/crates/datalogic-rs/Cargo.toml +117 -0
  20. datalogic_py-5.0.0/crates/datalogic-rs/README.md +496 -0
  21. datalogic_py-5.0.0/crates/datalogic-rs/examples/README.md +41 -0
  22. datalogic_py-5.0.0/crates/datalogic-rs/examples/compile_once_evaluate_many.rs +56 -0
  23. datalogic_py-5.0.0/crates/datalogic-rs/examples/configuration.rs +135 -0
  24. datalogic_py-5.0.0/crates/datalogic-rs/examples/custom_operator.rs +222 -0
  25. datalogic_py-5.0.0/crates/datalogic-rs/examples/datetime_ops.rs +68 -0
  26. datalogic_py-5.0.0/crates/datalogic-rs/examples/error_handling.rs +61 -0
  27. datalogic_py-5.0.0/crates/datalogic-rs/examples/getting_started.rs +76 -0
  28. datalogic_py-5.0.0/crates/datalogic-rs/examples/structured_objects.rs +182 -0
  29. datalogic_py-5.0.0/crates/datalogic-rs/examples/thread_safety.rs +36 -0
  30. datalogic_py-5.0.0/crates/datalogic-rs/examples/tracing.rs +43 -0
  31. datalogic_py-5.0.0/crates/datalogic-rs/examples/zero_copy_input.rs +73 -0
  32. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/context/frame.rs +62 -0
  33. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/context/mod.rs +528 -0
  34. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/context/reference.rs +47 -0
  35. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/mod.rs +28 -0
  36. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/singletons.rs +137 -0
  37. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/util.rs +9 -0
  38. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/value/coercion.rs +91 -0
  39. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/value/conversion.rs +59 -0
  40. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/value/lookup.rs +108 -0
  41. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/value/mod.rs +47 -0
  42. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/value/strings.rs +47 -0
  43. datalogic_py-5.0.0/crates/datalogic-rs/src/arena/value/traversal.rs +152 -0
  44. datalogic_py-5.0.0/crates/datalogic-rs/src/arena_ext.rs +128 -0
  45. datalogic_py-5.0.0/crates/datalogic-rs/src/builder.rs +157 -0
  46. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/missing.rs +91 -0
  47. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/mod.rs +58 -0
  48. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/operator.rs +283 -0
  49. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/optimize/constant_fold.rs +301 -0
  50. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/optimize/dead_code.rs +324 -0
  51. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/optimize/helpers.rs +16 -0
  52. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/optimize/mod.rs +81 -0
  53. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/optimize/strength.rs +111 -0
  54. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/optimize/test_helpers.rs +30 -0
  55. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/path_segments.rs +53 -0
  56. datalogic_py-5.0.0/crates/datalogic-rs/src/compile/walker.rs +312 -0
  57. datalogic_py-5.0.0/crates/datalogic-rs/src/config.rs +383 -0
  58. datalogic_py-5.0.0/crates/datalogic-rs/src/engine/dispatch.rs +403 -0
  59. datalogic_py-5.0.0/crates/datalogic-rs/src/engine/mod.rs +682 -0
  60. datalogic_py-5.0.0/crates/datalogic-rs/src/error/kind.rs +42 -0
  61. datalogic_py-5.0.0/crates/datalogic-rs/src/error/mod.rs +416 -0
  62. datalogic_py-5.0.0/crates/datalogic-rs/src/error/path.rs +43 -0
  63. datalogic_py-5.0.0/crates/datalogic-rs/src/error/serde.rs +148 -0
  64. datalogic_py-5.0.0/crates/datalogic-rs/src/eval_input.rs +175 -0
  65. datalogic_py-5.0.0/crates/datalogic-rs/src/lib.rs +305 -0
  66. datalogic_py-5.0.0/crates/datalogic-rs/src/logic_input.rs +86 -0
  67. datalogic_py-5.0.0/crates/datalogic-rs/src/node/compile_ctx.rs +79 -0
  68. datalogic_py-5.0.0/crates/datalogic-rs/src/node/logic.rs +320 -0
  69. datalogic_py-5.0.0/crates/datalogic-rs/src/node/mod.rs +359 -0
  70. datalogic_py-5.0.0/crates/datalogic-rs/src/node/payload.rs +128 -0
  71. datalogic_py-5.0.0/crates/datalogic-rs/src/node/populate.rs +94 -0
  72. datalogic_py-5.0.0/crates/datalogic-rs/src/node_serialize.rs +157 -0
  73. datalogic_py-5.0.0/crates/datalogic-rs/src/opcode.rs +447 -0
  74. datalogic_py-5.0.0/crates/datalogic-rs/src/operator.rs +53 -0
  75. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/arithmetic/basic.rs +432 -0
  76. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/arithmetic/div_mod.rs +203 -0
  77. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/arithmetic/helpers.rs +268 -0
  78. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/arithmetic/min_max.rs +189 -0
  79. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/arithmetic/mod.rs +47 -0
  80. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/arithmetic/unary_math.rs +87 -0
  81. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/filter.rs +214 -0
  82. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/helpers.rs +518 -0
  83. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/length.rs +35 -0
  84. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/map.rs +309 -0
  85. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/merge.rs +55 -0
  86. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/mod.rs +49 -0
  87. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/quantifiers.rs +226 -0
  88. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/reduce.rs +236 -0
  89. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/slice.rs +163 -0
  90. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/array/sort.rs +270 -0
  91. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/comparison/loose.rs +143 -0
  92. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/comparison/mod.rs +406 -0
  93. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/control.rs +123 -0
  94. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/datetime/arith.rs +134 -0
  95. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/datetime/mod.rs +307 -0
  96. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/error_handling.rs +138 -0
  97. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/flagd.rs +445 -0
  98. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/inspect.rs +109 -0
  99. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/logical.rs +77 -0
  100. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/missing.rs +287 -0
  101. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/mod.rs +77 -0
  102. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/string.rs +305 -0
  103. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/truthy.rs +36 -0
  104. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/variable/exists.rs +145 -0
  105. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/variable/mod.rs +192 -0
  106. datalogic_py-5.0.0/crates/datalogic-rs/src/operators/variable/val.rs +429 -0
  107. datalogic_py-5.0.0/crates/datalogic-rs/src/path.rs +177 -0
  108. datalogic_py-5.0.0/crates/datalogic-rs/src/result_output.rs +68 -0
  109. datalogic_py-5.0.0/crates/datalogic-rs/src/serde_bridge.rs +53 -0
  110. datalogic_py-5.0.0/crates/datalogic-rs/src/session.rs +217 -0
  111. datalogic_py-5.0.0/crates/datalogic-rs/src/top_level.rs +112 -0
  112. datalogic_py-5.0.0/crates/datalogic-rs/src/trace.rs +590 -0
  113. datalogic_py-5.0.0/crates/datalogic-rs/tests/README.md +69 -0
  114. datalogic_py-5.0.0/crates/datalogic-rs/tests/arc_test.rs +67 -0
  115. datalogic_py-5.0.0/crates/datalogic-rs/tests/arena_custom_datetime_test.rs +295 -0
  116. datalogic_py-5.0.0/crates/datalogic-rs/tests/arena_operator_test.rs +291 -0
  117. datalogic_py-5.0.0/crates/datalogic-rs/tests/basic_test.rs +120 -0
  118. datalogic_py-5.0.0/crates/datalogic-rs/tests/config_test.rs +470 -0
  119. datalogic_py-5.0.0/crates/datalogic-rs/tests/error_serialization.rs +443 -0
  120. datalogic_py-5.0.0/crates/datalogic-rs/tests/overflow_test.rs +371 -0
  121. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/README.md +67 -0
  122. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/additional.json +92 -0
  123. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/abs.json +92 -0
  124. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/ceil.json +98 -0
  125. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/chain.json +131 -0
  126. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/divide.json +193 -0
  127. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/floor.json +98 -0
  128. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/max.json +261 -0
  129. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/min.json +261 -0
  130. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/minus.json +136 -0
  131. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/modulo.json +191 -0
  132. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/multiply.json +172 -0
  133. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/arithmetic/plus.json +198 -0
  134. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/array/map.json +226 -0
  135. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/array/merge.json +87 -0
  136. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/array/reduce.json +261 -0
  137. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/chained.json +68 -0
  138. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/coalesce.json +93 -0
  139. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/comparison/greaterThan.json +212 -0
  140. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/comparison/greaterThanEquals.json +170 -0
  141. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/comparison/lessThan.json +272 -0
  142. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/comparison/lessThanEquals.json +122 -0
  143. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/comparison/softEquals.json +212 -0
  144. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/comparison/softNotEquals.json +206 -0
  145. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/comparison/strictEquals.json +188 -0
  146. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/comparison/strictNotEquals.json +182 -0
  147. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/compatible.json +1895 -0
  148. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/control/and.json +155 -0
  149. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/control/if.json +283 -0
  150. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/control/or.json +155 -0
  151. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/control/switch.json +620 -0
  152. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/custom/is_night.json +183 -0
  153. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/datetime/datetime.json +170 -0
  154. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/datetime/duration.json +156 -0
  155. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/datetime/now.json +80 -0
  156. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/empty-objects.json +14 -0
  157. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/exists.json +51 -0
  158. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/flagd/fractional.json +270 -0
  159. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/flagd/sem_ver.json +296 -0
  160. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/index.json +51 -0
  161. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/iterators.extra.json +173 -0
  162. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/length.json +81 -0
  163. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/scopes.json +55 -0
  164. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/slice.json +184 -0
  165. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/sort.json +266 -0
  166. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/string/string.json +231 -0
  167. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/structured-objects.json +592 -0
  168. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/throw.json +20 -0
  169. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/truthiness.json +89 -0
  170. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/try.extra.json +17 -0
  171. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/try.json +157 -0
  172. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/type.json +174 -0
  173. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/unknown-operators.json +32 -0
  174. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/val-compat.json +665 -0
  175. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/val.extra.json +153 -0
  176. datalogic_py-5.0.0/crates/datalogic-rs/tests/suites/val.json +81 -0
  177. datalogic_py-5.0.0/crates/datalogic-rs/tests/test_jsonlogic.rs +276 -0
  178. datalogic_py-5.0.0/crates/datalogic-rs/tests/thread_safety_test.rs +282 -0
  179. datalogic_py-5.0.0/crates/datalogic-rs/tests/trace_test.rs +377 -0
  180. datalogic_py-5.0.0/crates/datalogic-rs/tests/v5_api_test.rs +312 -0
  181. datalogic_py-5.0.0/pyproject.toml +57 -0
@@ -0,0 +1,41 @@
1
+ [workspace]
2
+ resolver = "3"
3
+ members = [
4
+ "crates/datalogic-rs",
5
+ "tools/benchmark",
6
+ ]
7
+ # `bindings/wasm` defines its own `[workspace]` so wasm-pack can apply its
8
+ # WASM-specific `[profile.release]` (opt-level "z", lto, panic = "abort")
9
+ # without contaminating the rest of the tree. `bindings/python`,
10
+ # `bindings/c`, and `bindings/node` are excluded so contributors don't
11
+ # need a Python / Node toolchain or have to wait on cbindgen+cdylib /
12
+ # napi build codegen just to run `cargo test --workspace --all-features`
13
+ # against core. `ui` is a Node package and is invisible to Cargo regardless.
14
+ exclude = [
15
+ "bindings/wasm",
16
+ "bindings/python",
17
+ "bindings/c",
18
+ "bindings/node",
19
+ "ui",
20
+ ]
21
+
22
+ [workspace.package]
23
+ edition = "2024"
24
+ license = "Apache-2.0"
25
+ authors = ["Harishankar Narayanan <nharishankar@gmail.com>"]
26
+ repository = "https://github.com/GoPlasmatic/datalogic-rs"
27
+
28
+ # `lto = "fat"` + `codegen-units = 1` lets the compiler propagate the
29
+ # load-bearing `#[inline(always)]` decisions across crate/CGU boundaries
30
+ # in the dispatch hot path. The WASM workspace defines its own
31
+ # `[profile.release]` so it is unaffected.
32
+ [profile.release]
33
+ lto = "fat"
34
+ codegen-units = 1
35
+ # Line tables let cargo-flamegraph / samply / Instruments resolve frame
36
+ # names without bloating the binary much. Comment out for a strip-only
37
+ # release build.
38
+ debug = "line-tables-only"
39
+
40
+ [profile.bench]
41
+ inherits = "release"
@@ -0,0 +1,253 @@
1
+ Metadata-Version: 2.4
2
+ Name: datalogic-py
3
+ Version: 5.0.0
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: Apache Software License
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Rust
13
+ Classifier: Topic :: Software Development :: Libraries
14
+ Requires-Dist: pytest>=7 ; extra == 'test'
15
+ Provides-Extra: test
16
+ Summary: Python bindings for the datalogic-rs JSONLogic engine — compile-once, evaluate-many.
17
+ Keywords: jsonlogic,rules,engine,json,logic
18
+ Author-email: Harishankar Narayanan <nharishankar@gmail.com>
19
+ License: Apache-2.0
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
22
+ Project-URL: Documentation, https://github.com/GoPlasmatic/datalogic-rs/tree/main/bindings/python
23
+ Project-URL: Homepage, https://github.com/GoPlasmatic/datalogic-rs
24
+ Project-URL: Issues, https://github.com/GoPlasmatic/datalogic-rs/issues
25
+ Project-URL: Repository, https://github.com/GoPlasmatic/datalogic-rs
26
+
27
+ # datalogic-py
28
+
29
+ [![PyPI](https://img.shields.io/pypi/v/datalogic-py.svg)](https://pypi.org/project/datalogic-py/)
30
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
31
+
32
+ Python bindings for [`datalogic-rs`](https://github.com/GoPlasmatic/datalogic-rs),
33
+ a fast Rust implementation of [JSONLogic](http://jsonlogic.com). Same
34
+ rules, same semantics as the Rust crate, with the **compile-once /
35
+ evaluate-many** pattern exposed natively — compile a rule once and
36
+ evaluate it against thousands of data inputs without re-parsing.
37
+
38
+ For the cross-runtime overview and the API-tier model every binding
39
+ implements, see the
40
+ [repo README](https://github.com/GoPlasmatic/datalogic-rs#readme).
41
+
42
+ > **New in v5.** `datalogic-py` is new — there is no v4 Python package.
43
+ > If you were calling the v4 Rust crate or the v4 `@goplasmatic/datalogic`
44
+ > WASM package, the engine's v4 → v5 changes are catalogued in
45
+ > [MIGRATION.md](https://github.com/GoPlasmatic/datalogic-rs/blob/main/MIGRATION.md).
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ pip install datalogic-py
51
+ ```
52
+
53
+ Pre-built wheels are published for:
54
+
55
+ | Platform | Architectures |
56
+ |--------------------|-----------------|
57
+ | Linux (manylinux) | x86_64, aarch64 |
58
+ | Linux (musllinux) | x86_64, aarch64 |
59
+ | macOS | x86_64, arm64 |
60
+ | Windows | x86_64 |
61
+
62
+ Python 3.10 and newer are supported via
63
+ [PEP 384 stable ABI (`abi3`)](https://peps.python.org/pep-0384/) — one
64
+ wheel per platform covers every CPython 3.10+ release.
65
+
66
+ > **Naming:** `pip install datalogic-py` (PyPI distribution name) →
67
+ > `import datalogic_py` (Python module name). Python modules can't
68
+ > contain hyphens, so the underscore form is the import.
69
+
70
+ ## Quick start
71
+
72
+ ```python
73
+ from datalogic_py import apply
74
+
75
+ result = apply(
76
+ {"if": [{">": [{"var": "score"}, 50]}, "pass", "fail"]},
77
+ {"score": 75},
78
+ )
79
+ # -> "pass"
80
+ ```
81
+
82
+ ## API reference
83
+
84
+ The Python binding mirrors the Rust engine's
85
+ [API tier model](https://github.com/GoPlasmatic/datalogic-rs#choosing-your-api-five-tiers-one-engine).
86
+
87
+ | Tier | Entry point | Use when |
88
+ |--------------|------------------------------------------|---------------------------------------------------------------|
89
+ | One-shot | `apply(rule, data)` | Ad-hoc evaluation, one rule + one data shape |
90
+ | Engine | `Engine().eval(rule, data)` | Custom configuration (templating, future operator extensions) |
91
+ | Compile once | `Engine().compile(rule).evaluate(data)` | Same rule evaluated against many data inputs |
92
+ | Session | `with engine.session() as sess: …` | Hot loops — amortise arena reset across iterations |
93
+
94
+ ### One-shot — `apply(rule, data)`
95
+
96
+ ```python
97
+ from datalogic_py import apply
98
+
99
+ apply({"+": [1, 2, 3]}, {}) # 6
100
+ apply({"var": "user.age"}, {"user": {"age": 25}}) # 25
101
+ apply({"and": [{">": [{"var": "x"}, 0]}, True]}, {"x": 5}) # True
102
+ ```
103
+
104
+ Both arguments accept Python `dict` / `list` values (converted via
105
+ [`pythonize`](https://crates.io/crates/pythonize), roughly 3–10× faster
106
+ than a JSON-string round-trip). For payloads with types `pythonize`
107
+ doesn't cover, see [Type conversion](#type-conversion) below.
108
+
109
+ ### Engine — `Engine().eval(rule, data)`
110
+
111
+ Construct an `Engine` when you need templating mode or any non-default
112
+ configuration:
113
+
114
+ ```python
115
+ from datalogic_py import Engine
116
+
117
+ engine = Engine() # default config
118
+ engine.eval({"==": [1, 1]}, {}) # True
119
+
120
+ # Templating mode — multi-key objects become output templates
121
+ templating_engine = Engine(templating=True)
122
+ templating_engine.eval(
123
+ {"name": {"var": "user.name"}, "ok": {">": [{"var": "score"}, 50]}},
124
+ {"user": {"name": "Ada"}, "score": 99},
125
+ )
126
+ # {"name": "Ada", "ok": True}
127
+ ```
128
+
129
+ ### Compile once — `Engine().compile(rule)` → `Rule.evaluate(data)`
130
+
131
+ Compile the rule once when you'll evaluate it against many data inputs.
132
+
133
+ ```python
134
+ from datalogic_py import Engine
135
+
136
+ engine = Engine()
137
+ rule = engine.compile({"if": [{">": [{"var": "score"}, 50]}, "pass", "fail"]})
138
+
139
+ for payload in batch:
140
+ result = rule.evaluate(payload) # accepts a dict
141
+ fast = rule.evaluate_str(json_text) # accepts a JSON string (skips dict conversion)
142
+ ```
143
+
144
+ `Rule` is **thread-safe** — clone the reference into worker threads and
145
+ evaluate concurrently. The Rust eval call releases the GIL, so a
146
+ multi-threaded server gains real parallelism.
147
+
148
+ ### Session — hot loops
149
+
150
+ For batches where you want to amortise arena reset across iterations,
151
+ open a `Session`. The arena is reset between iterations automatically.
152
+
153
+ ```python
154
+ from datalogic_py import Engine
155
+
156
+ engine = Engine()
157
+ rule = engine.compile({"+": [{"var": "x"}, 1]})
158
+
159
+ with engine.session() as sess:
160
+ for payload in batch:
161
+ result = sess.evaluate(rule, payload)
162
+ ```
163
+
164
+ `Session` is the per-thread workhorse — open one per worker thread.
165
+ The arena that makes it fast can't be shared across threads (the same
166
+ way a database connection is per-task in a connection-pool model);
167
+ `Engine` and `Rule` are both thread-safe, so share those.
168
+
169
+ ## Error handling
170
+
171
+ All exceptions descend from `DataLogicError`:
172
+
173
+ | Exception | When |
174
+ |------------------|-------------------------------------------------------------------|
175
+ | `ParseError` | Malformed rule or data JSON, unsupported operator, or unsupported Python type |
176
+ | `EvaluateError` | Operator failure at runtime — carries `.error_type`, `.operator`, `.path` |
177
+
178
+ ```python
179
+ from datalogic_py import Engine, EvaluateError
180
+
181
+ engine = Engine()
182
+ try:
183
+ engine.eval({"var": "missing"}, {})
184
+ except EvaluateError as e:
185
+ print(e.error_type) # e.g. "VariableNotFound"
186
+ print(e.operator) # "var"
187
+ print(e.path) # JSON-pointer-style path through the compiled tree
188
+ ```
189
+
190
+ ## Threading
191
+
192
+ | Type | Pattern |
193
+ |-----------|----------------------------------------------------------------------------------|
194
+ | `Engine` | Build once; share across threads |
195
+ | `Rule` | Compile once; share across threads — `evaluate` releases the GIL for parallelism |
196
+ | `Session` | One per worker thread — the per-task workhorse |
197
+
198
+ ## Type conversion
199
+
200
+ The dict-input path uses [`pythonize`](https://crates.io/crates/pythonize):
201
+
202
+ **Supported:** `dict`, `list`, `str`, `int`, `float`, `bool`, `None`.
203
+
204
+ **Not supported** — these raise `ParseError` with a clear message:
205
+
206
+ - `datetime.datetime`, `datetime.date` — convert to ISO string at the
207
+ Python edge
208
+ - `decimal.Decimal` — convert to `float` or `str`
209
+ - `bytes`, `set`, `tuple`
210
+ - `float('nan')`, `float('inf')` — JSON spec disallows them
211
+
212
+ For payloads with exotic types, use `rule.evaluate_str(json_text)` and
213
+ bring your own JSON encoder (e.g. with `default=str`).
214
+
215
+ ## Templating mode
216
+
217
+ ```python
218
+ engine = Engine(templating=True)
219
+ rule = engine.compile({
220
+ "name": {"var": "user.name"},
221
+ "ok": {">": [{"var": "score"}, 50]},
222
+ })
223
+ rule.evaluate({"user": {"name": "Ada"}, "score": 99})
224
+ # -> {"name": "Ada", "ok": True}
225
+ ```
226
+
227
+ ## Performance
228
+
229
+ This package wraps the same Rust engine measured as `dlrs:engine` in the
230
+ [cross-library benchmark][bench] — geomean **9.7 ns/op across 44 operator
231
+ suites** in native Rust. The pyo3 boundary and `pythonize` dict
232
+ conversion add a small per-call cost on top; use
233
+ `rule.evaluate_str(json_text)` when you already have a JSON string and
234
+ want to skip the dict path. `evaluate` releases the GIL, so a
235
+ multi-threaded server gains real parallelism on top of the engine's
236
+ native speed.
237
+
238
+ [bench]: https://github.com/GoPlasmatic/datalogic-rs/blob/main/tools/benchmark/BENCHMARK.md
239
+
240
+ ## Learn more
241
+
242
+ - [Repo README](https://github.com/GoPlasmatic/datalogic-rs#readme) — cross-runtime overview, all binding READMEs
243
+ - [Rust crate README](../../crates/datalogic-rs/README.md) — engine design, custom operators, configuration knobs
244
+ - [Full documentation](https://goplasmatic.github.io/datalogic-rs/) — long-form guide, operator reference
245
+ - [Online playground](https://goplasmatic.github.io/datalogic-rs/playground/)
246
+ - [JSONLogic specification](https://jsonlogic.com/)
247
+
248
+ ## License
249
+
250
+ Apache-2.0. See the
251
+ [main repository](https://github.com/GoPlasmatic/datalogic-rs) for
252
+ source and contribution guidelines.
253
+
@@ -0,0 +1,226 @@
1
+ # datalogic-py
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/datalogic-py.svg)](https://pypi.org/project/datalogic-py/)
4
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
+
6
+ Python bindings for [`datalogic-rs`](https://github.com/GoPlasmatic/datalogic-rs),
7
+ a fast Rust implementation of [JSONLogic](http://jsonlogic.com). Same
8
+ rules, same semantics as the Rust crate, with the **compile-once /
9
+ evaluate-many** pattern exposed natively — compile a rule once and
10
+ evaluate it against thousands of data inputs without re-parsing.
11
+
12
+ For the cross-runtime overview and the API-tier model every binding
13
+ implements, see the
14
+ [repo README](https://github.com/GoPlasmatic/datalogic-rs#readme).
15
+
16
+ > **New in v5.** `datalogic-py` is new — there is no v4 Python package.
17
+ > If you were calling the v4 Rust crate or the v4 `@goplasmatic/datalogic`
18
+ > WASM package, the engine's v4 → v5 changes are catalogued in
19
+ > [MIGRATION.md](https://github.com/GoPlasmatic/datalogic-rs/blob/main/MIGRATION.md).
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ pip install datalogic-py
25
+ ```
26
+
27
+ Pre-built wheels are published for:
28
+
29
+ | Platform | Architectures |
30
+ |--------------------|-----------------|
31
+ | Linux (manylinux) | x86_64, aarch64 |
32
+ | Linux (musllinux) | x86_64, aarch64 |
33
+ | macOS | x86_64, arm64 |
34
+ | Windows | x86_64 |
35
+
36
+ Python 3.10 and newer are supported via
37
+ [PEP 384 stable ABI (`abi3`)](https://peps.python.org/pep-0384/) — one
38
+ wheel per platform covers every CPython 3.10+ release.
39
+
40
+ > **Naming:** `pip install datalogic-py` (PyPI distribution name) →
41
+ > `import datalogic_py` (Python module name). Python modules can't
42
+ > contain hyphens, so the underscore form is the import.
43
+
44
+ ## Quick start
45
+
46
+ ```python
47
+ from datalogic_py import apply
48
+
49
+ result = apply(
50
+ {"if": [{">": [{"var": "score"}, 50]}, "pass", "fail"]},
51
+ {"score": 75},
52
+ )
53
+ # -> "pass"
54
+ ```
55
+
56
+ ## API reference
57
+
58
+ The Python binding mirrors the Rust engine's
59
+ [API tier model](https://github.com/GoPlasmatic/datalogic-rs#choosing-your-api-five-tiers-one-engine).
60
+
61
+ | Tier | Entry point | Use when |
62
+ |--------------|------------------------------------------|---------------------------------------------------------------|
63
+ | One-shot | `apply(rule, data)` | Ad-hoc evaluation, one rule + one data shape |
64
+ | Engine | `Engine().eval(rule, data)` | Custom configuration (templating, future operator extensions) |
65
+ | Compile once | `Engine().compile(rule).evaluate(data)` | Same rule evaluated against many data inputs |
66
+ | Session | `with engine.session() as sess: …` | Hot loops — amortise arena reset across iterations |
67
+
68
+ ### One-shot — `apply(rule, data)`
69
+
70
+ ```python
71
+ from datalogic_py import apply
72
+
73
+ apply({"+": [1, 2, 3]}, {}) # 6
74
+ apply({"var": "user.age"}, {"user": {"age": 25}}) # 25
75
+ apply({"and": [{">": [{"var": "x"}, 0]}, True]}, {"x": 5}) # True
76
+ ```
77
+
78
+ Both arguments accept Python `dict` / `list` values (converted via
79
+ [`pythonize`](https://crates.io/crates/pythonize), roughly 3–10× faster
80
+ than a JSON-string round-trip). For payloads with types `pythonize`
81
+ doesn't cover, see [Type conversion](#type-conversion) below.
82
+
83
+ ### Engine — `Engine().eval(rule, data)`
84
+
85
+ Construct an `Engine` when you need templating mode or any non-default
86
+ configuration:
87
+
88
+ ```python
89
+ from datalogic_py import Engine
90
+
91
+ engine = Engine() # default config
92
+ engine.eval({"==": [1, 1]}, {}) # True
93
+
94
+ # Templating mode — multi-key objects become output templates
95
+ templating_engine = Engine(templating=True)
96
+ templating_engine.eval(
97
+ {"name": {"var": "user.name"}, "ok": {">": [{"var": "score"}, 50]}},
98
+ {"user": {"name": "Ada"}, "score": 99},
99
+ )
100
+ # {"name": "Ada", "ok": True}
101
+ ```
102
+
103
+ ### Compile once — `Engine().compile(rule)` → `Rule.evaluate(data)`
104
+
105
+ Compile the rule once when you'll evaluate it against many data inputs.
106
+
107
+ ```python
108
+ from datalogic_py import Engine
109
+
110
+ engine = Engine()
111
+ rule = engine.compile({"if": [{">": [{"var": "score"}, 50]}, "pass", "fail"]})
112
+
113
+ for payload in batch:
114
+ result = rule.evaluate(payload) # accepts a dict
115
+ fast = rule.evaluate_str(json_text) # accepts a JSON string (skips dict conversion)
116
+ ```
117
+
118
+ `Rule` is **thread-safe** — clone the reference into worker threads and
119
+ evaluate concurrently. The Rust eval call releases the GIL, so a
120
+ multi-threaded server gains real parallelism.
121
+
122
+ ### Session — hot loops
123
+
124
+ For batches where you want to amortise arena reset across iterations,
125
+ open a `Session`. The arena is reset between iterations automatically.
126
+
127
+ ```python
128
+ from datalogic_py import Engine
129
+
130
+ engine = Engine()
131
+ rule = engine.compile({"+": [{"var": "x"}, 1]})
132
+
133
+ with engine.session() as sess:
134
+ for payload in batch:
135
+ result = sess.evaluate(rule, payload)
136
+ ```
137
+
138
+ `Session` is the per-thread workhorse — open one per worker thread.
139
+ The arena that makes it fast can't be shared across threads (the same
140
+ way a database connection is per-task in a connection-pool model);
141
+ `Engine` and `Rule` are both thread-safe, so share those.
142
+
143
+ ## Error handling
144
+
145
+ All exceptions descend from `DataLogicError`:
146
+
147
+ | Exception | When |
148
+ |------------------|-------------------------------------------------------------------|
149
+ | `ParseError` | Malformed rule or data JSON, unsupported operator, or unsupported Python type |
150
+ | `EvaluateError` | Operator failure at runtime — carries `.error_type`, `.operator`, `.path` |
151
+
152
+ ```python
153
+ from datalogic_py import Engine, EvaluateError
154
+
155
+ engine = Engine()
156
+ try:
157
+ engine.eval({"var": "missing"}, {})
158
+ except EvaluateError as e:
159
+ print(e.error_type) # e.g. "VariableNotFound"
160
+ print(e.operator) # "var"
161
+ print(e.path) # JSON-pointer-style path through the compiled tree
162
+ ```
163
+
164
+ ## Threading
165
+
166
+ | Type | Pattern |
167
+ |-----------|----------------------------------------------------------------------------------|
168
+ | `Engine` | Build once; share across threads |
169
+ | `Rule` | Compile once; share across threads — `evaluate` releases the GIL for parallelism |
170
+ | `Session` | One per worker thread — the per-task workhorse |
171
+
172
+ ## Type conversion
173
+
174
+ The dict-input path uses [`pythonize`](https://crates.io/crates/pythonize):
175
+
176
+ **Supported:** `dict`, `list`, `str`, `int`, `float`, `bool`, `None`.
177
+
178
+ **Not supported** — these raise `ParseError` with a clear message:
179
+
180
+ - `datetime.datetime`, `datetime.date` — convert to ISO string at the
181
+ Python edge
182
+ - `decimal.Decimal` — convert to `float` or `str`
183
+ - `bytes`, `set`, `tuple`
184
+ - `float('nan')`, `float('inf')` — JSON spec disallows them
185
+
186
+ For payloads with exotic types, use `rule.evaluate_str(json_text)` and
187
+ bring your own JSON encoder (e.g. with `default=str`).
188
+
189
+ ## Templating mode
190
+
191
+ ```python
192
+ engine = Engine(templating=True)
193
+ rule = engine.compile({
194
+ "name": {"var": "user.name"},
195
+ "ok": {">": [{"var": "score"}, 50]},
196
+ })
197
+ rule.evaluate({"user": {"name": "Ada"}, "score": 99})
198
+ # -> {"name": "Ada", "ok": True}
199
+ ```
200
+
201
+ ## Performance
202
+
203
+ This package wraps the same Rust engine measured as `dlrs:engine` in the
204
+ [cross-library benchmark][bench] — geomean **9.7 ns/op across 44 operator
205
+ suites** in native Rust. The pyo3 boundary and `pythonize` dict
206
+ conversion add a small per-call cost on top; use
207
+ `rule.evaluate_str(json_text)` when you already have a JSON string and
208
+ want to skip the dict path. `evaluate` releases the GIL, so a
209
+ multi-threaded server gains real parallelism on top of the engine's
210
+ native speed.
211
+
212
+ [bench]: https://github.com/GoPlasmatic/datalogic-rs/blob/main/tools/benchmark/BENCHMARK.md
213
+
214
+ ## Learn more
215
+
216
+ - [Repo README](https://github.com/GoPlasmatic/datalogic-rs#readme) — cross-runtime overview, all binding READMEs
217
+ - [Rust crate README](../../crates/datalogic-rs/README.md) — engine design, custom operators, configuration knobs
218
+ - [Full documentation](https://goplasmatic.github.io/datalogic-rs/) — long-form guide, operator reference
219
+ - [Online playground](https://goplasmatic.github.io/datalogic-rs/playground/)
220
+ - [JSONLogic specification](https://jsonlogic.com/)
221
+
222
+ ## License
223
+
224
+ Apache-2.0. See the
225
+ [main repository](https://github.com/GoPlasmatic/datalogic-rs) for
226
+ source and contribution guidelines.
@@ -0,0 +1,20 @@
1
+ # Python build / install artifacts
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.pyd
7
+ .pytest_cache/
8
+ .mypy_cache/
9
+ .ruff_cache/
10
+
11
+ # venv (any name)
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # maturin / setuptools-rust build outputs
17
+ dist/
18
+ build/
19
+ *.egg-info/
20
+ wheels/