datahike-browser-tests 1.0.0

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 (324) hide show
  1. package/.circleci/config.yml +405 -0
  2. package/.circleci/scripts/gen_ci.clj +194 -0
  3. package/.cirrus.yml +60 -0
  4. package/.clj-kondo/babashka/sci/config.edn +1 -0
  5. package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
  6. package/.clj-kondo/config.edn +95 -0
  7. package/.dir-locals.el +2 -0
  8. package/.github/FUNDING.yml +3 -0
  9. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
  10. package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
  11. package/.github/ISSUE_TEMPLATE/config.yml +6 -0
  12. package/.github/pull_request_template.md +24 -0
  13. package/.github/workflows/native-image.yml +84 -0
  14. package/LICENSE +203 -0
  15. package/README.md +273 -0
  16. package/bb/deps.edn +9 -0
  17. package/bb/resources/github-fingerprints +3 -0
  18. package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
  19. package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
  20. package/bb/resources/native-image-tests/run-native-image-tests +74 -0
  21. package/bb/resources/native-image-tests/run-python-tests +22 -0
  22. package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
  23. package/bb/resources/native-image-tests/testconfig.edn +5 -0
  24. package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  25. package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
  26. package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
  27. package/bb/resources/template/pom.xml +22 -0
  28. package/bb/src/tools/build.clj +132 -0
  29. package/bb/src/tools/clj_kondo.clj +32 -0
  30. package/bb/src/tools/deploy.clj +26 -0
  31. package/bb/src/tools/examples.clj +19 -0
  32. package/bb/src/tools/npm.clj +100 -0
  33. package/bb/src/tools/python.clj +14 -0
  34. package/bb/src/tools/release.clj +94 -0
  35. package/bb/src/tools/test.clj +148 -0
  36. package/bb/src/tools/version.clj +47 -0
  37. package/bb.edn +269 -0
  38. package/benchmark/src/benchmark/cli.clj +195 -0
  39. package/benchmark/src/benchmark/compare.clj +157 -0
  40. package/benchmark/src/benchmark/config.clj +316 -0
  41. package/benchmark/src/benchmark/measure.clj +187 -0
  42. package/benchmark/src/benchmark/store.clj +190 -0
  43. package/benchmark/test/benchmark/measure_test.clj +156 -0
  44. package/build.clj +30 -0
  45. package/config.edn +49 -0
  46. package/deps.edn +138 -0
  47. package/dev/sandbox.clj +82 -0
  48. package/dev/sandbox.cljs +127 -0
  49. package/dev/sandbox_benchmarks.clj +27 -0
  50. package/dev/sandbox_client.clj +87 -0
  51. package/dev/sandbox_transact_bench.clj +109 -0
  52. package/dev/user.clj +79 -0
  53. package/doc/README.md +96 -0
  54. package/doc/adl/README.md +6 -0
  55. package/doc/adl/adr-000-adr.org +28 -0
  56. package/doc/adl/adr-001-attribute-references.org +15 -0
  57. package/doc/adl/adr-002-build-tooling.org +54 -0
  58. package/doc/adl/adr-003-db-meta-data.md +52 -0
  59. package/doc/adl/adr-004-github-flow.md +40 -0
  60. package/doc/adl/adr-XYZ-template.md +30 -0
  61. package/doc/adl/index.org +3 -0
  62. package/doc/assets/datahike-logo.svg +3 -0
  63. package/doc/assets/datahiking-invoice.org +85 -0
  64. package/doc/assets/hhtree2.png +0 -0
  65. package/doc/assets/network_topology.svg +624 -0
  66. package/doc/assets/perf.png +0 -0
  67. package/doc/assets/schema_mindmap.mm +132 -0
  68. package/doc/assets/schema_mindmap.svg +970 -0
  69. package/doc/assets/temporal_index.mm +74 -0
  70. package/doc/backend-development.md +78 -0
  71. package/doc/bb-pod.md +89 -0
  72. package/doc/benchmarking.md +360 -0
  73. package/doc/bindings/edn-conversion.md +383 -0
  74. package/doc/cli.md +162 -0
  75. package/doc/cljdoc.edn +27 -0
  76. package/doc/cljs-support.md +133 -0
  77. package/doc/config.md +406 -0
  78. package/doc/contributing.md +114 -0
  79. package/doc/datalog-vs-sql.md +210 -0
  80. package/doc/datomic_differences.md +109 -0
  81. package/doc/development/pull-api-ns.md +186 -0
  82. package/doc/development/pull-frame-state-diagram.jpg +0 -0
  83. package/doc/distributed.md +566 -0
  84. package/doc/entity_spec.md +92 -0
  85. package/doc/gc.md +273 -0
  86. package/doc/java-api.md +808 -0
  87. package/doc/javascript-api.md +421 -0
  88. package/doc/libdatahike.md +86 -0
  89. package/doc/logging_and_error_handling.md +43 -0
  90. package/doc/norms.md +66 -0
  91. package/doc/schema-migration.md +85 -0
  92. package/doc/schema.md +287 -0
  93. package/doc/storage-backends.md +363 -0
  94. package/doc/store-id-refactoring.md +596 -0
  95. package/doc/time_variance.md +325 -0
  96. package/doc/unstructured.md +167 -0
  97. package/doc/versioning.md +261 -0
  98. package/examples/basic/README.md +19 -0
  99. package/examples/basic/deps.edn +6 -0
  100. package/examples/basic/docker-compose.yml +13 -0
  101. package/examples/basic/src/examples/core.clj +60 -0
  102. package/examples/basic/src/examples/schema.clj +155 -0
  103. package/examples/basic/src/examples/store.clj +60 -0
  104. package/examples/basic/src/examples/time_travel.clj +185 -0
  105. package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
  106. package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  107. package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
  108. package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
  109. package/examples/java/README.md +162 -0
  110. package/examples/java/pom.xml +62 -0
  111. package/examples/java/src/main/java/examples/QuickStart.java +115 -0
  112. package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
  113. package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
  114. package/flake.lock +27 -0
  115. package/flake.nix +27 -0
  116. package/http-server/datahike/http/middleware.clj +75 -0
  117. package/http-server/datahike/http/server.clj +269 -0
  118. package/java/src/datahike/java/Database.java +274 -0
  119. package/java/src/datahike/java/Datahike.java +281 -0
  120. package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
  121. package/java/src/datahike/java/DatahikeTest.java +370 -0
  122. package/java/src/datahike/java/EDN.java +170 -0
  123. package/java/src/datahike/java/IEntity.java +11 -0
  124. package/java/src/datahike/java/Keywords.java +161 -0
  125. package/java/src/datahike/java/SchemaFlexibility.java +52 -0
  126. package/java/src/datahike/java/Util.java +219 -0
  127. package/karma.conf.js +19 -0
  128. package/libdatahike/compile-cpp +7 -0
  129. package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
  130. package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
  131. package/libdatahike/src/test_cpp.cpp +61 -0
  132. package/npm-package/PUBLISHING.md +140 -0
  133. package/npm-package/README.md +226 -0
  134. package/npm-package/package.template.json +34 -0
  135. package/npm-package/test-isomorphic.ts +281 -0
  136. package/npm-package/test.js +557 -0
  137. package/npm-package/typescript-test.ts +70 -0
  138. package/package.json +16 -0
  139. package/pydatahike/README.md +569 -0
  140. package/pydatahike/pyproject.toml +91 -0
  141. package/pydatahike/setup.py +42 -0
  142. package/pydatahike/src/datahike/__init__.py +134 -0
  143. package/pydatahike/src/datahike/_native.py +250 -0
  144. package/pydatahike/src/datahike/_version.py +2 -0
  145. package/pydatahike/src/datahike/database.py +722 -0
  146. package/pydatahike/src/datahike/edn.py +311 -0
  147. package/pydatahike/src/datahike/py.typed +0 -0
  148. package/pydatahike/tests/conftest.py +17 -0
  149. package/pydatahike/tests/test_basic.py +170 -0
  150. package/pydatahike/tests/test_database.py +51 -0
  151. package/pydatahike/tests/test_edn_conversion.py +299 -0
  152. package/pydatahike/tests/test_query.py +99 -0
  153. package/pydatahike/tests/test_schema.py +55 -0
  154. package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
  155. package/resources/example_server.edn +4 -0
  156. package/shadow-cljs.edn +56 -0
  157. package/src/data_readers.clj +7 -0
  158. package/src/datahike/api/impl.cljc +176 -0
  159. package/src/datahike/api/specification.cljc +633 -0
  160. package/src/datahike/api/types.cljc +261 -0
  161. package/src/datahike/api.cljc +41 -0
  162. package/src/datahike/array.cljc +99 -0
  163. package/src/datahike/cli.clj +166 -0
  164. package/src/datahike/cljs.cljs +6 -0
  165. package/src/datahike/codegen/cli.clj +406 -0
  166. package/src/datahike/codegen/clj_kondo.clj +291 -0
  167. package/src/datahike/codegen/java.clj +403 -0
  168. package/src/datahike/codegen/naming.cljc +33 -0
  169. package/src/datahike/codegen/native.clj +559 -0
  170. package/src/datahike/codegen/pod.clj +488 -0
  171. package/src/datahike/codegen/python.clj +838 -0
  172. package/src/datahike/codegen/report.clj +55 -0
  173. package/src/datahike/codegen/typescript.clj +262 -0
  174. package/src/datahike/codegen/validation.clj +145 -0
  175. package/src/datahike/config.cljc +294 -0
  176. package/src/datahike/connections.cljc +16 -0
  177. package/src/datahike/connector.cljc +265 -0
  178. package/src/datahike/constants.cljc +142 -0
  179. package/src/datahike/core.cljc +297 -0
  180. package/src/datahike/datom.cljc +459 -0
  181. package/src/datahike/db/interface.cljc +119 -0
  182. package/src/datahike/db/search.cljc +305 -0
  183. package/src/datahike/db/transaction.cljc +937 -0
  184. package/src/datahike/db/utils.cljc +338 -0
  185. package/src/datahike/db.cljc +956 -0
  186. package/src/datahike/experimental/unstructured.cljc +126 -0
  187. package/src/datahike/experimental/versioning.cljc +172 -0
  188. package/src/datahike/externs.js +31 -0
  189. package/src/datahike/gc.cljc +69 -0
  190. package/src/datahike/http/client.clj +188 -0
  191. package/src/datahike/http/writer.clj +79 -0
  192. package/src/datahike/impl/entity.cljc +218 -0
  193. package/src/datahike/index/interface.cljc +93 -0
  194. package/src/datahike/index/persistent_set.cljc +469 -0
  195. package/src/datahike/index/utils.cljc +44 -0
  196. package/src/datahike/index.cljc +32 -0
  197. package/src/datahike/js/api.cljs +172 -0
  198. package/src/datahike/js/api_macros.clj +22 -0
  199. package/src/datahike/js.cljs +163 -0
  200. package/src/datahike/json.cljc +209 -0
  201. package/src/datahike/lru.cljc +146 -0
  202. package/src/datahike/migrate.clj +39 -0
  203. package/src/datahike/norm/norm.clj +245 -0
  204. package/src/datahike/online_gc.cljc +252 -0
  205. package/src/datahike/pod.clj +155 -0
  206. package/src/datahike/pull_api.cljc +325 -0
  207. package/src/datahike/query.cljc +1945 -0
  208. package/src/datahike/query_stats.cljc +88 -0
  209. package/src/datahike/readers.cljc +62 -0
  210. package/src/datahike/remote.cljc +218 -0
  211. package/src/datahike/schema.cljc +228 -0
  212. package/src/datahike/schema_cache.cljc +42 -0
  213. package/src/datahike/spec.cljc +101 -0
  214. package/src/datahike/store.cljc +80 -0
  215. package/src/datahike/tools.cljc +308 -0
  216. package/src/datahike/transit.cljc +80 -0
  217. package/src/datahike/writer.cljc +239 -0
  218. package/src/datahike/writing.cljc +362 -0
  219. package/src/deps.cljs +1 -0
  220. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
  221. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
  222. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
  223. package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
  224. package/test/datahike/integration_test/config_record_file_test.clj +14 -0
  225. package/test/datahike/integration_test/config_record_test.clj +14 -0
  226. package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
  227. package/test/datahike/integration_test/return_map_test.clj +62 -0
  228. package/test/datahike/integration_test.cljc +67 -0
  229. package/test/datahike/norm/norm_test.clj +124 -0
  230. package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
  231. package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
  232. package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
  233. package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
  234. package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
  235. package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
  236. package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
  237. package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
  238. package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
  239. package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
  240. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
  241. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
  242. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
  243. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
  244. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
  245. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
  246. package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
  247. package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
  248. package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
  249. package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
  250. package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
  251. package/test/datahike/test/api_test.cljc +895 -0
  252. package/test/datahike/test/array_test.cljc +40 -0
  253. package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
  254. package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
  255. package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
  256. package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
  257. package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
  258. package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
  259. package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
  260. package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
  261. package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
  262. package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
  263. package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
  264. package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
  265. package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
  266. package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
  267. package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
  268. package/test/datahike/test/attribute_refs/utils.cljc +128 -0
  269. package/test/datahike/test/cache_test.cljc +38 -0
  270. package/test/datahike/test/components_test.cljc +92 -0
  271. package/test/datahike/test/config_test.cljc +158 -0
  272. package/test/datahike/test/core_test.cljc +105 -0
  273. package/test/datahike/test/datom_test.cljc +44 -0
  274. package/test/datahike/test/db_test.cljc +54 -0
  275. package/test/datahike/test/entity_spec_test.cljc +159 -0
  276. package/test/datahike/test/entity_test.cljc +103 -0
  277. package/test/datahike/test/explode_test.cljc +143 -0
  278. package/test/datahike/test/filter_test.cljc +75 -0
  279. package/test/datahike/test/gc_test.cljc +159 -0
  280. package/test/datahike/test/http/server_test.clj +192 -0
  281. package/test/datahike/test/http/writer_test.clj +86 -0
  282. package/test/datahike/test/ident_test.cljc +32 -0
  283. package/test/datahike/test/index_test.cljc +345 -0
  284. package/test/datahike/test/insert.cljc +125 -0
  285. package/test/datahike/test/java_bindings_test.clj +6 -0
  286. package/test/datahike/test/listen_test.cljc +41 -0
  287. package/test/datahike/test/lookup_refs_test.cljc +266 -0
  288. package/test/datahike/test/lru_test.cljc +27 -0
  289. package/test/datahike/test/migrate_test.clj +297 -0
  290. package/test/datahike/test/model/core.cljc +376 -0
  291. package/test/datahike/test/model/invariant.cljc +142 -0
  292. package/test/datahike/test/model/rng.cljc +82 -0
  293. package/test/datahike/test/model_test.clj +217 -0
  294. package/test/datahike/test/nodejs_test.cljs +262 -0
  295. package/test/datahike/test/online_gc_test.cljc +475 -0
  296. package/test/datahike/test/pod_test.clj +369 -0
  297. package/test/datahike/test/pull_api_test.cljc +474 -0
  298. package/test/datahike/test/purge_test.cljc +144 -0
  299. package/test/datahike/test/query_aggregates_test.cljc +101 -0
  300. package/test/datahike/test/query_find_specs_test.cljc +52 -0
  301. package/test/datahike/test/query_fns_test.cljc +523 -0
  302. package/test/datahike/test/query_interop_test.cljc +47 -0
  303. package/test/datahike/test/query_not_test.cljc +189 -0
  304. package/test/datahike/test/query_or_test.cljc +158 -0
  305. package/test/datahike/test/query_pull_test.cljc +147 -0
  306. package/test/datahike/test/query_rules_test.cljc +248 -0
  307. package/test/datahike/test/query_stats_test.cljc +218 -0
  308. package/test/datahike/test/query_test.cljc +984 -0
  309. package/test/datahike/test/schema_test.cljc +424 -0
  310. package/test/datahike/test/specification_test.cljc +30 -0
  311. package/test/datahike/test/store_test.cljc +78 -0
  312. package/test/datahike/test/stress_test.cljc +57 -0
  313. package/test/datahike/test/time_variance_test.cljc +518 -0
  314. package/test/datahike/test/tools_test.clj +134 -0
  315. package/test/datahike/test/transact_test.cljc +518 -0
  316. package/test/datahike/test/tuples_test.cljc +564 -0
  317. package/test/datahike/test/unstructured_test.cljc +291 -0
  318. package/test/datahike/test/upsert_impl_test.cljc +205 -0
  319. package/test/datahike/test/upsert_test.cljc +363 -0
  320. package/test/datahike/test/utils.cljc +110 -0
  321. package/test/datahike/test/validation_test.cljc +48 -0
  322. package/test/datahike/test/versioning_test.cljc +56 -0
  323. package/test/datahike/test.cljc +66 -0
  324. package/tests.edn +24 -0
@@ -0,0 +1,134 @@
1
+ """Datahike Python bindings.
2
+
3
+ This package provides Python bindings to Datahike, a durable Datalog database
4
+ powered by an efficient Datalog query engine.
5
+
6
+ High-Level API (Recommended):
7
+ >>> from datahike import Database
8
+ >>>
9
+ >>> db = Database(backend=':mem', id='example')
10
+ >>> db.create()
11
+ >>>
12
+ >>> db.transact([{"name": "Alice", "age": 30}])
13
+ >>> result = db.q('[:find ?name :where [?e :name ?name]]')
14
+ >>> print(result) # [['Alice']]
15
+ >>>
16
+ >>> db.delete()
17
+
18
+ Context Manager:
19
+ >>> from datahike import database
20
+ >>> with database(backend=':mem', id='test') as db:
21
+ ... db.transact([{'name': 'Alice'}])
22
+ ... result = db.q('[:find ?name :where [?e :name ?name]]')
23
+ ... print(result)
24
+
25
+ Time Travel:
26
+ >>> import time
27
+ >>> t = int(time.time() * 1000)
28
+ >>> past = db.as_of(t)
29
+ >>> results = past.q('[:find ?name :where [?e :name ?name]]')
30
+
31
+ EDN Helpers:
32
+ >>> from datahike import edn, kw
33
+ >>> schema = [{
34
+ ... "db/ident": edn.keyword("person/name"),
35
+ ... "db/valueType": kw.STRING,
36
+ ... "db/cardinality": kw.ONE
37
+ ... }]
38
+ >>> db.transact(schema)
39
+
40
+ Low-Level API (Advanced):
41
+ >>> from datahike import create_database, transact, q, delete_database
42
+ >>>
43
+ >>> config = '{:store {:backend :mem :id "example"}}'
44
+ >>> create_database(config)
45
+ >>> transact(config, '[{"name": "Alice"}]')
46
+ >>> result = q('[:find ?name :where [?e :name ?name]]', [('db', config)])
47
+ >>> delete_database(config)
48
+ """
49
+
50
+ from ._version import __version__
51
+ from ._native import DatahikeException
52
+
53
+ # High-level API (recommended)
54
+ from .database import Database, DatabaseSnapshot, database
55
+
56
+ # EDN helpers
57
+ from .edn import (
58
+ # Types
59
+ Keyword,
60
+ Symbol,
61
+ UUID,
62
+ Inst,
63
+ # Functions
64
+ keyword,
65
+ symbol,
66
+ uuid,
67
+ inst,
68
+ string,
69
+ # Constants
70
+ Keywords,
71
+ kw,
72
+ )
73
+
74
+ # Low-level API (for advanced use)
75
+ from .generated import (
76
+ database_exists,
77
+ create_database,
78
+ delete_database,
79
+ q,
80
+ transact,
81
+ pull,
82
+ pull_many,
83
+ entity,
84
+ datoms,
85
+ seek_datoms,
86
+ index_range,
87
+ schema,
88
+ reverse_schema,
89
+ metrics,
90
+ gc_storage,
91
+ )
92
+
93
+ __all__ = [
94
+ # Version
95
+ '__version__',
96
+
97
+ # Exception
98
+ 'DatahikeException',
99
+
100
+ # High-level API (recommended)
101
+ 'Database',
102
+ 'DatabaseSnapshot',
103
+ 'database',
104
+
105
+ # EDN helpers
106
+ 'Keyword',
107
+ 'Symbol',
108
+ 'UUID',
109
+ 'Inst',
110
+ 'keyword',
111
+ 'symbol',
112
+ 'uuid',
113
+ 'inst',
114
+ 'string',
115
+ 'Keywords',
116
+ 'kw',
117
+
118
+ # Low-level API
119
+ 'database_exists',
120
+ 'create_database',
121
+ 'delete_database',
122
+ 'q',
123
+ 'transact',
124
+ 'pull',
125
+ 'pull_many',
126
+ 'entity',
127
+ 'datoms',
128
+ 'seek_datoms',
129
+ 'index_range',
130
+ 'schema',
131
+ 'reverse_schema',
132
+ 'metrics',
133
+ 'gc_storage',
134
+ ]
@@ -0,0 +1,250 @@
1
+ """Native library interface for datahike.
2
+
3
+ This module provides the low-level ctypes interface to libdatahike.
4
+ It handles library loading, isolate initialization, and result parsing.
5
+
6
+ The callback-based architecture avoids shared mutable memory between
7
+ Python and the GraalVM native image.
8
+ """
9
+ from ctypes import (
10
+ CDLL, CFUNCTYPE, POINTER,
11
+ c_void_p, c_char_p, c_long,
12
+ byref, ARRAY
13
+ )
14
+ import os
15
+ import io
16
+ import json
17
+ import base64
18
+ import cbor2
19
+ from typing import Any, List, Tuple, Optional, Callable, Literal
20
+
21
+ # Type aliases for better documentation
22
+ OutputFormat = Literal["json", "edn", "cbor"]
23
+ InputFormat = str # "db", "history", "since:<timestamp>", "asof:<timestamp>"
24
+
25
+
26
+ class DatahikeException(Exception):
27
+ """Exception raised by Datahike operations."""
28
+ pass
29
+
30
+
31
+ # =============================================================================
32
+ # Library Loading
33
+ # =============================================================================
34
+
35
+ def _find_library() -> str:
36
+ """Find libdatahike shared library.
37
+
38
+ Returns:
39
+ Path to library
40
+
41
+ Raises:
42
+ FileNotFoundError: If library not found in any location
43
+ """
44
+ # Check environment variable first
45
+ if 'LIBDATAHIKE_PATH' in os.environ:
46
+ path = os.environ['LIBDATAHIKE_PATH']
47
+ if os.path.exists(path):
48
+ return path
49
+ raise FileNotFoundError(
50
+ f"LIBDATAHIKE_PATH points to non-existent file: {path}"
51
+ )
52
+
53
+ # Check common locations relative to this file
54
+ possible_paths = [
55
+ # Relative to datahike repo
56
+ os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
57
+ 'libdatahike', 'target', 'libdatahike.so'),
58
+ # Linux system paths
59
+ '/usr/local/lib/libdatahike.so',
60
+ '/usr/lib/libdatahike.so',
61
+ # macOS
62
+ os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
63
+ 'libdatahike', 'target', 'libdatahike.dylib'),
64
+ '/usr/local/lib/libdatahike.dylib',
65
+ ]
66
+
67
+ for path in possible_paths:
68
+ abs_path = os.path.abspath(path)
69
+ if os.path.exists(abs_path):
70
+ return abs_path
71
+
72
+ # Provide helpful error with all attempted paths
73
+ tried_paths = '\n'.join(f' - {os.path.abspath(p)}' for p in possible_paths)
74
+ raise FileNotFoundError(
75
+ f"Could not find libdatahike shared library.\n\n"
76
+ f"Tried the following locations:\n{tried_paths}\n\n"
77
+ f"To fix this:\n"
78
+ f" 1. Build the native library: cd datahike && bb ni-compile\n"
79
+ f" 2. Or set LIBDATAHIKE_PATH environment variable to the library path"
80
+ )
81
+
82
+
83
+ # Lazy initialization - don't load library at import time
84
+ _dll: Optional[CDLL] = None
85
+ _isolatethread: Optional[c_void_p] = None
86
+
87
+
88
+ def _ensure_initialized() -> None:
89
+ """Ensure native library is loaded and GraalVM isolate is initialized.
90
+
91
+ Raises:
92
+ RuntimeError: If GraalVM isolate creation fails
93
+ """
94
+ global _dll, _isolatethread
95
+
96
+ if _dll is not None:
97
+ return # Already initialized
98
+
99
+ # Find and load library
100
+ lib_path = _find_library()
101
+ _dll = CDLL(lib_path)
102
+
103
+ # Initialize GraalVM isolate
104
+ isolate = c_void_p()
105
+ _isolatethread = c_void_p()
106
+
107
+ if _dll.graal_create_isolate(None, byref(isolate), byref(_isolatethread)) != 0:
108
+ raise RuntimeError(
109
+ "Failed to initialize GraalVM isolate. "
110
+ "The native library may be corrupted. Try rebuilding: bb ni-compile"
111
+ )
112
+
113
+
114
+ # =============================================================================
115
+ # Callback Types
116
+ # =============================================================================
117
+
118
+ # Callback function type for receiving results
119
+ CALLBACK_FUNC = CFUNCTYPE(c_void_p, c_char_p)
120
+
121
+
122
+ # =============================================================================
123
+ # Result Parsing
124
+ # =============================================================================
125
+
126
+ def _cbor_tag_hook(decoder, tag, shareable_index=None):
127
+ """Handle CBOR tags (e.g., Clojure keywords)."""
128
+ # Tag 39 is used for Clojure keywords - just return the value
129
+ if tag.tag == 39:
130
+ return tag.value
131
+ return tag.value
132
+
133
+
134
+ def parse_result(data: bytes, output_format: OutputFormat) -> Any:
135
+ """Parse result bytes based on output format.
136
+
137
+ Args:
138
+ data: Raw bytes from callback
139
+ output_format: One of 'json', 'edn', 'cbor'
140
+
141
+ Returns:
142
+ Parsed result
143
+
144
+ Raises:
145
+ DatahikeException: If result is an exception
146
+ ValueError: If output_format is unknown
147
+ """
148
+ if len(data) == 0:
149
+ return None
150
+
151
+ # Check for exception
152
+ if data.startswith(b"exception:"):
153
+ raise DatahikeException(data.decode("utf8").replace("exception:", ""))
154
+
155
+ if output_format == "json":
156
+ return json.loads(data)
157
+ elif output_format == "edn":
158
+ return data.decode("utf8") # Return as string for now
159
+ elif output_format == "cbor":
160
+ # Decode from base64 string, stripping any whitespace/newlines
161
+ decoded = base64.b64decode(data.strip())
162
+ return cbor2.loads(decoded, tag_hook=_cbor_tag_hook)
163
+ else:
164
+ raise ValueError(
165
+ f"Unknown output format: {output_format!r}. "
166
+ f"Expected one of: 'json', 'edn', 'cbor'"
167
+ )
168
+
169
+
170
+ def make_callback(output_format: OutputFormat) -> Tuple[CALLBACK_FUNC, Callable[[], Any]]:
171
+ """Create a callback function and result getter.
172
+
173
+ Args:
174
+ output_format: Format for parsing results
175
+
176
+ Returns:
177
+ Tuple of (callback_func, get_result_func)
178
+ """
179
+ result = None
180
+ exception = None
181
+
182
+ def callback(data: bytes) -> None:
183
+ nonlocal result, exception
184
+ try:
185
+ result = parse_result(data, output_format)
186
+ except Exception as e:
187
+ exception = e
188
+
189
+ def get_result() -> Any:
190
+ if exception is not None:
191
+ raise exception
192
+ return result
193
+
194
+ return CALLBACK_FUNC(callback), get_result
195
+
196
+
197
+ # =============================================================================
198
+ # Query Input Helpers
199
+ # =============================================================================
200
+
201
+ def prepare_query_inputs(inputs: List[Tuple[InputFormat, str]]) -> Tuple[int, Any, Any]:
202
+ """Prepare query inputs for native call.
203
+
204
+ Args:
205
+ inputs: List of (format, value) tuples
206
+ Format can be 'db', 'history', 'since:<timestamp>', 'asof:<timestamp>', or 'param'
207
+
208
+ Returns:
209
+ Tuple of (count, formats_array, values_array)
210
+ """
211
+ n = len(inputs)
212
+ char_p_array = ARRAY(c_char_p, n)
213
+ formats = char_p_array()
214
+ values = char_p_array()
215
+
216
+ for i, (fmt, val) in enumerate(inputs):
217
+ formats[i] = fmt.encode("utf8")
218
+ values[i] = val.encode("utf8")
219
+
220
+ return n, formats, values
221
+
222
+
223
+ # =============================================================================
224
+ # Native Function Wrappers
225
+ # =============================================================================
226
+
227
+ def get_isolatethread() -> c_void_p:
228
+ """Get the current isolate thread context.
229
+
230
+ Ensures library is initialized before returning thread context.
231
+
232
+ Returns:
233
+ GraalVM isolate thread pointer
234
+ """
235
+ _ensure_initialized()
236
+ assert _isolatethread is not None
237
+ return _isolatethread
238
+
239
+
240
+ def get_dll() -> CDLL:
241
+ """Get the loaded native library.
242
+
243
+ Ensures library is initialized before returning.
244
+
245
+ Returns:
246
+ Loaded CDLL instance
247
+ """
248
+ _ensure_initialized()
249
+ assert _dll is not None
250
+ return _dll
@@ -0,0 +1,2 @@
1
+ """Auto-generated version file from config.edn."""
2
+ __version__ = "0.7.1657"