relationalai 0.12.13__py3-none-any.whl → 0.13.0.dev0__py3-none-any.whl

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 (825) hide show
  1. relationalai/__init__.py +1 -209
  2. relationalai/config/__init__.py +56 -0
  3. relationalai/config/config.py +289 -0
  4. relationalai/config/config_fields.py +86 -0
  5. relationalai/config/connections/__init__.py +46 -0
  6. relationalai/config/connections/base.py +23 -0
  7. relationalai/config/connections/duckdb.py +29 -0
  8. relationalai/config/connections/snowflake.py +243 -0
  9. relationalai/config/external/__init__.py +17 -0
  10. relationalai/config/external/dbt_converter.py +101 -0
  11. relationalai/config/external/dbt_models.py +93 -0
  12. relationalai/config/external/snowflake_converter.py +41 -0
  13. relationalai/config/external/snowflake_models.py +85 -0
  14. relationalai/config/external/utils.py +19 -0
  15. relationalai/semantics/__init__.py +146 -22
  16. relationalai/semantics/backends/lqp/annotations.py +11 -0
  17. relationalai/semantics/backends/sql/sql_compiler.py +327 -0
  18. relationalai/semantics/frontend/base.py +1707 -0
  19. relationalai/semantics/frontend/core.py +179 -0
  20. relationalai/semantics/frontend/front_compiler.py +1313 -0
  21. relationalai/semantics/frontend/pprint.py +408 -0
  22. relationalai/semantics/metamodel/__init__.py +6 -40
  23. relationalai/semantics/metamodel/builtins.py +205 -769
  24. relationalai/semantics/metamodel/metamodel.py +437 -0
  25. relationalai/semantics/metamodel/metamodel_analyzer.py +519 -0
  26. relationalai/semantics/metamodel/pprint.py +412 -0
  27. relationalai/semantics/metamodel/rewriter.py +266 -0
  28. relationalai/semantics/metamodel/typer.py +1378 -0
  29. relationalai/semantics/std/__init__.py +60 -40
  30. relationalai/semantics/std/aggregates.py +149 -0
  31. relationalai/semantics/std/common.py +44 -0
  32. relationalai/semantics/std/constraints.py +37 -43
  33. relationalai/semantics/std/datetime.py +246 -135
  34. relationalai/semantics/std/decimals.py +45 -52
  35. relationalai/semantics/std/floats.py +13 -5
  36. relationalai/semantics/std/integers.py +26 -11
  37. relationalai/semantics/std/math.py +183 -112
  38. relationalai/semantics/std/numbers.py +86 -0
  39. relationalai/semantics/std/re.py +80 -62
  40. relationalai/semantics/std/strings.py +117 -60
  41. relationalai/shims/executor.py +147 -0
  42. relationalai/shims/helpers.py +126 -0
  43. relationalai/shims/hoister.py +221 -0
  44. relationalai/shims/mm2v0.py +1290 -0
  45. relationalai/tools/cli/__init__.py +6 -0
  46. relationalai/tools/cli/cli.py +90 -0
  47. relationalai/tools/cli/components/__init__.py +5 -0
  48. relationalai/tools/cli/components/progress_reader.py +1524 -0
  49. relationalai/tools/cli/components/utils.py +58 -0
  50. relationalai/tools/cli/config_template.py +45 -0
  51. relationalai/tools/cli/dev.py +19 -0
  52. relationalai/tools/debugger.py +289 -183
  53. relationalai/tools/typer_debugger.py +93 -0
  54. relationalai/util/dataclasses.py +43 -0
  55. relationalai/util/docutils.py +40 -0
  56. relationalai/util/error.py +199 -0
  57. relationalai/util/format.py +48 -106
  58. relationalai/util/naming.py +145 -0
  59. relationalai/util/python.py +35 -0
  60. relationalai/util/runtime.py +156 -0
  61. relationalai/util/schema.py +197 -0
  62. relationalai/util/source.py +185 -0
  63. relationalai/util/structures.py +163 -0
  64. relationalai/util/tracing.py +261 -0
  65. relationalai-0.13.0.dev0.dist-info/METADATA +46 -0
  66. relationalai-0.13.0.dev0.dist-info/RECORD +488 -0
  67. relationalai-0.13.0.dev0.dist-info/WHEEL +5 -0
  68. relationalai-0.13.0.dev0.dist-info/entry_points.txt +3 -0
  69. relationalai-0.13.0.dev0.dist-info/top_level.txt +2 -0
  70. v0/relationalai/__init__.py +216 -0
  71. v0/relationalai/clients/azure.py +477 -0
  72. v0/relationalai/clients/client.py +912 -0
  73. v0/relationalai/clients/config.py +673 -0
  74. v0/relationalai/clients/direct_access_client.py +118 -0
  75. v0/relationalai/clients/hash_util.py +31 -0
  76. v0/relationalai/clients/local.py +571 -0
  77. v0/relationalai/clients/profile_polling.py +73 -0
  78. v0/relationalai/clients/result_helpers.py +420 -0
  79. v0/relationalai/clients/snowflake.py +3869 -0
  80. v0/relationalai/clients/types.py +113 -0
  81. v0/relationalai/clients/use_index_poller.py +980 -0
  82. v0/relationalai/clients/util.py +356 -0
  83. v0/relationalai/debugging.py +389 -0
  84. v0/relationalai/dsl.py +1749 -0
  85. v0/relationalai/early_access/builder/__init__.py +30 -0
  86. v0/relationalai/early_access/builder/builder/__init__.py +35 -0
  87. v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
  88. v0/relationalai/early_access/builder/std/__init__.py +25 -0
  89. v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  90. v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
  91. v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
  92. v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
  93. v0/relationalai/early_access/devtools/__init__.py +12 -0
  94. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  95. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  96. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  97. v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  98. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  99. v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  100. v0/relationalai/early_access/dsl/bindings/common.py +402 -0
  101. v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
  102. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  103. v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  104. v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
  105. v0/relationalai/early_access/dsl/codegen/common.py +79 -0
  106. v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
  107. v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
  108. v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
  109. v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  110. v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
  111. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  112. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  113. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  114. v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  115. v0/relationalai/early_access/dsl/core/context.py +13 -0
  116. v0/relationalai/early_access/dsl/core/cset.py +132 -0
  117. v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  118. v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  119. v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  120. v0/relationalai/early_access/dsl/core/instances.py +44 -0
  121. v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  122. v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  123. v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
  124. v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
  125. v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
  126. v0/relationalai/early_access/dsl/core/relations.py +276 -0
  127. v0/relationalai/early_access/dsl/core/rules.py +112 -0
  128. v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
  129. v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  130. v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
  131. v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
  132. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  133. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  134. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  135. v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
  136. v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  137. v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
  138. v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
  139. v0/relationalai/early_access/dsl/ir/executor.py +260 -0
  140. v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  141. v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
  142. v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
  143. v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  144. v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
  145. v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  146. v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
  147. v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  148. v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
  149. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  150. v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  151. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  152. v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  153. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  154. v0/relationalai/early_access/dsl/orm/models.py +256 -0
  155. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  156. v0/relationalai/early_access/dsl/orm/printer.py +469 -0
  157. v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
  158. v0/relationalai/early_access/dsl/orm/relations.py +19 -0
  159. v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
  160. v0/relationalai/early_access/dsl/orm/types.py +42 -0
  161. v0/relationalai/early_access/dsl/orm/utils.py +79 -0
  162. v0/relationalai/early_access/dsl/orm/verb.py +204 -0
  163. v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  164. v0/relationalai/early_access/dsl/relations.py +170 -0
  165. v0/relationalai/early_access/dsl/rulesets.py +69 -0
  166. v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
  167. v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
  168. v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  169. v0/relationalai/early_access/dsl/schemas/components.py +203 -0
  170. v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
  171. v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
  172. v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
  173. v0/relationalai/early_access/dsl/serialization.py +79 -0
  174. v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
  175. v0/relationalai/early_access/dsl/snow/api.py +104 -0
  176. v0/relationalai/early_access/dsl/snow/common.py +76 -0
  177. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  178. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  179. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  180. v0/relationalai/early_access/dsl/types/__init__.py +40 -0
  181. v0/relationalai/early_access/dsl/types/concepts.py +12 -0
  182. v0/relationalai/early_access/dsl/types/entities.py +135 -0
  183. v0/relationalai/early_access/dsl/types/values.py +17 -0
  184. v0/relationalai/early_access/dsl/utils.py +102 -0
  185. v0/relationalai/early_access/graphs/__init__.py +13 -0
  186. v0/relationalai/early_access/lqp/__init__.py +12 -0
  187. v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
  188. v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
  189. v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
  190. v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
  191. v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
  192. v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  193. v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
  194. v0/relationalai/early_access/lqp/types/__init__.py +12 -0
  195. v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
  196. v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
  197. v0/relationalai/early_access/metamodel/__init__.py +58 -0
  198. v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  199. v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  200. v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  201. v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
  202. v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  203. v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
  204. v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  205. v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
  206. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  207. v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
  208. v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
  209. v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  210. v0/relationalai/early_access/rel/__init__.py +12 -0
  211. v0/relationalai/early_access/rel/executor/__init__.py +12 -0
  212. v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  213. v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
  214. v0/relationalai/early_access/solvers/__init__.py +19 -0
  215. v0/relationalai/early_access/sql/__init__.py +11 -0
  216. v0/relationalai/early_access/sql/executor/__init__.py +3 -0
  217. v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
  218. v0/relationalai/early_access/tests/logging/__init__.py +12 -0
  219. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  220. v0/relationalai/early_access/tests/utils/__init__.py +12 -0
  221. v0/relationalai/environments/__init__.py +35 -0
  222. v0/relationalai/environments/base.py +381 -0
  223. v0/relationalai/environments/colab.py +14 -0
  224. v0/relationalai/environments/generic.py +71 -0
  225. v0/relationalai/environments/ipython.py +68 -0
  226. v0/relationalai/environments/jupyter.py +9 -0
  227. v0/relationalai/environments/snowbook.py +169 -0
  228. v0/relationalai/errors.py +2455 -0
  229. v0/relationalai/experimental/SF.py +38 -0
  230. v0/relationalai/experimental/inspect.py +47 -0
  231. v0/relationalai/experimental/pathfinder/__init__.py +158 -0
  232. v0/relationalai/experimental/pathfinder/api.py +160 -0
  233. v0/relationalai/experimental/pathfinder/automaton.py +584 -0
  234. v0/relationalai/experimental/pathfinder/bridge.py +226 -0
  235. v0/relationalai/experimental/pathfinder/compiler.py +416 -0
  236. v0/relationalai/experimental/pathfinder/datalog.py +214 -0
  237. v0/relationalai/experimental/pathfinder/diagnostics.py +56 -0
  238. v0/relationalai/experimental/pathfinder/filter.py +236 -0
  239. v0/relationalai/experimental/pathfinder/glushkov.py +439 -0
  240. v0/relationalai/experimental/pathfinder/options.py +265 -0
  241. v0/relationalai/experimental/pathfinder/rpq.py +344 -0
  242. v0/relationalai/experimental/pathfinder/transition.py +200 -0
  243. v0/relationalai/experimental/pathfinder/utils.py +26 -0
  244. v0/relationalai/experimental/paths/api.py +143 -0
  245. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  246. v0/relationalai/experimental/paths/examples/basic_example.py +40 -0
  247. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  248. v0/relationalai/experimental/paths/examples/movie_example.py +77 -0
  249. v0/relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  250. v0/relationalai/experimental/paths/examples/paths_example.py +116 -0
  251. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  252. v0/relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  253. v0/relationalai/experimental/paths/graph.py +185 -0
  254. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  255. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  256. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  257. v0/relationalai/experimental/paths/path_algorithms/single.py +59 -0
  258. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  259. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  260. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  261. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  262. v0/relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  263. v0/relationalai/experimental/paths/product_graph.py +93 -0
  264. v0/relationalai/experimental/paths/rpq/automaton.py +584 -0
  265. v0/relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  266. v0/relationalai/experimental/paths/rpq/rpq.py +378 -0
  267. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  268. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  269. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  270. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  271. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  272. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  273. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  274. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  275. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  276. v0/relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  277. v0/relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  278. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  279. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  280. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  281. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  282. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  283. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  284. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  285. v0/relationalai/experimental/paths/tree_agg.py +168 -0
  286. v0/relationalai/experimental/paths/utilities/iterators.py +27 -0
  287. v0/relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  288. v0/relationalai/experimental/solvers.py +1087 -0
  289. v0/relationalai/loaders/__init__.py +0 -0
  290. v0/relationalai/loaders/csv.py +195 -0
  291. v0/relationalai/loaders/loader.py +177 -0
  292. v0/relationalai/loaders/types.py +23 -0
  293. v0/relationalai/rel_emitter.py +373 -0
  294. v0/relationalai/rel_utils.py +185 -0
  295. v0/relationalai/semantics/__init__.py +29 -0
  296. v0/relationalai/semantics/devtools/benchmark_lqp.py +536 -0
  297. v0/relationalai/semantics/devtools/compilation_manager.py +294 -0
  298. v0/relationalai/semantics/devtools/extract_lqp.py +110 -0
  299. v0/relationalai/semantics/internal/internal.py +3785 -0
  300. v0/relationalai/semantics/internal/snowflake.py +324 -0
  301. v0/relationalai/semantics/lqp/builtins.py +16 -0
  302. v0/relationalai/semantics/lqp/compiler.py +22 -0
  303. v0/relationalai/semantics/lqp/constructors.py +68 -0
  304. v0/relationalai/semantics/lqp/executor.py +469 -0
  305. v0/relationalai/semantics/lqp/intrinsics.py +24 -0
  306. v0/relationalai/semantics/lqp/model2lqp.py +839 -0
  307. v0/relationalai/semantics/lqp/passes.py +680 -0
  308. v0/relationalai/semantics/lqp/primitives.py +252 -0
  309. v0/relationalai/semantics/lqp/result_helpers.py +202 -0
  310. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  311. v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  312. v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  313. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +449 -0
  314. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  315. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  316. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  317. v0/relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  318. v0/relationalai/semantics/lqp/types.py +101 -0
  319. v0/relationalai/semantics/lqp/utils.py +160 -0
  320. v0/relationalai/semantics/lqp/validators.py +57 -0
  321. v0/relationalai/semantics/metamodel/__init__.py +40 -0
  322. v0/relationalai/semantics/metamodel/builtins.py +774 -0
  323. v0/relationalai/semantics/metamodel/compiler.py +133 -0
  324. v0/relationalai/semantics/metamodel/dependency.py +862 -0
  325. v0/relationalai/semantics/metamodel/executor.py +61 -0
  326. v0/relationalai/semantics/metamodel/factory.py +287 -0
  327. v0/relationalai/semantics/metamodel/helpers.py +361 -0
  328. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  329. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  330. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  331. v0/relationalai/semantics/metamodel/rewrite/flatten.py +549 -0
  332. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  333. v0/relationalai/semantics/metamodel/typer/checker.py +353 -0
  334. v0/relationalai/semantics/metamodel/typer/typer.py +1395 -0
  335. v0/relationalai/semantics/reasoners/__init__.py +10 -0
  336. v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
  337. v0/relationalai/semantics/reasoners/graph/core.py +9020 -0
  338. v0/relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  339. v0/relationalai/semantics/reasoners/optimization/common.py +88 -0
  340. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  341. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +1163 -0
  342. v0/relationalai/semantics/rel/builtins.py +40 -0
  343. v0/relationalai/semantics/rel/compiler.py +989 -0
  344. v0/relationalai/semantics/rel/executor.py +359 -0
  345. v0/relationalai/semantics/rel/rel.py +482 -0
  346. v0/relationalai/semantics/rel/rel_utils.py +276 -0
  347. v0/relationalai/semantics/snowflake/__init__.py +3 -0
  348. v0/relationalai/semantics/sql/compiler.py +2503 -0
  349. v0/relationalai/semantics/sql/executor/duck_db.py +52 -0
  350. v0/relationalai/semantics/sql/executor/result_helpers.py +64 -0
  351. v0/relationalai/semantics/sql/executor/snowflake.py +145 -0
  352. v0/relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  353. v0/relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  354. v0/relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  355. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  356. v0/relationalai/semantics/sql/sql.py +504 -0
  357. v0/relationalai/semantics/std/__init__.py +54 -0
  358. v0/relationalai/semantics/std/constraints.py +43 -0
  359. v0/relationalai/semantics/std/datetime.py +363 -0
  360. v0/relationalai/semantics/std/decimals.py +62 -0
  361. v0/relationalai/semantics/std/floats.py +7 -0
  362. v0/relationalai/semantics/std/integers.py +22 -0
  363. v0/relationalai/semantics/std/math.py +141 -0
  364. v0/relationalai/semantics/std/pragmas.py +11 -0
  365. v0/relationalai/semantics/std/re.py +83 -0
  366. v0/relationalai/semantics/std/std.py +14 -0
  367. v0/relationalai/semantics/std/strings.py +63 -0
  368. v0/relationalai/semantics/tests/__init__.py +0 -0
  369. v0/relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  370. v0/relationalai/semantics/tests/test_snapshot_base.py +9 -0
  371. v0/relationalai/semantics/tests/utils.py +46 -0
  372. v0/relationalai/std/__init__.py +70 -0
  373. v0/relationalai/tools/__init__.py +0 -0
  374. v0/relationalai/tools/cli.py +1940 -0
  375. v0/relationalai/tools/cli_controls.py +1826 -0
  376. v0/relationalai/tools/cli_helpers.py +390 -0
  377. v0/relationalai/tools/debugger.py +183 -0
  378. v0/relationalai/tools/debugger_client.py +109 -0
  379. v0/relationalai/tools/debugger_server.py +302 -0
  380. v0/relationalai/tools/dev.py +685 -0
  381. v0/relationalai/tools/qb_debugger.py +425 -0
  382. v0/relationalai/util/clean_up_databases.py +95 -0
  383. v0/relationalai/util/format.py +123 -0
  384. v0/relationalai/util/list_databases.py +9 -0
  385. v0/relationalai/util/otel_configuration.py +25 -0
  386. v0/relationalai/util/otel_handler.py +484 -0
  387. v0/relationalai/util/snowflake_handler.py +88 -0
  388. v0/relationalai/util/span_format_test.py +43 -0
  389. v0/relationalai/util/span_tracker.py +207 -0
  390. v0/relationalai/util/spans_file_handler.py +72 -0
  391. v0/relationalai/util/tracing_handler.py +34 -0
  392. frontend/debugger/dist/.gitignore +0 -2
  393. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  394. frontend/debugger/dist/assets/index-Cssla-O7.js +0 -208
  395. frontend/debugger/dist/assets/index-DlHsYx1V.css +0 -9
  396. frontend/debugger/dist/index.html +0 -17
  397. relationalai/clients/azure.py +0 -477
  398. relationalai/clients/client.py +0 -912
  399. relationalai/clients/config.py +0 -673
  400. relationalai/clients/direct_access_client.py +0 -118
  401. relationalai/clients/export_procedure.py.jinja +0 -249
  402. relationalai/clients/hash_util.py +0 -31
  403. relationalai/clients/local.py +0 -571
  404. relationalai/clients/profile_polling.py +0 -73
  405. relationalai/clients/result_helpers.py +0 -420
  406. relationalai/clients/snowflake.py +0 -3869
  407. relationalai/clients/types.py +0 -113
  408. relationalai/clients/use_index_poller.py +0 -980
  409. relationalai/clients/util.py +0 -356
  410. relationalai/debugging.py +0 -389
  411. relationalai/dsl.py +0 -1749
  412. relationalai/early_access/builder/__init__.py +0 -30
  413. relationalai/early_access/builder/builder/__init__.py +0 -35
  414. relationalai/early_access/builder/snowflake/__init__.py +0 -12
  415. relationalai/early_access/builder/std/__init__.py +0 -25
  416. relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  417. relationalai/early_access/builder/std/integers/__init__.py +0 -12
  418. relationalai/early_access/builder/std/math/__init__.py +0 -12
  419. relationalai/early_access/builder/std/strings/__init__.py +0 -14
  420. relationalai/early_access/devtools/__init__.py +0 -12
  421. relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  422. relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  423. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  424. relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  425. relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  426. relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  427. relationalai/early_access/dsl/bindings/common.py +0 -402
  428. relationalai/early_access/dsl/bindings/csv.py +0 -170
  429. relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  430. relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  431. relationalai/early_access/dsl/codegen/binder.py +0 -411
  432. relationalai/early_access/dsl/codegen/common.py +0 -79
  433. relationalai/early_access/dsl/codegen/helpers.py +0 -23
  434. relationalai/early_access/dsl/codegen/relations.py +0 -700
  435. relationalai/early_access/dsl/codegen/weaver.py +0 -417
  436. relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  437. relationalai/early_access/dsl/core/builders/logic.py +0 -19
  438. relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  439. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  440. relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  441. relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  442. relationalai/early_access/dsl/core/context.py +0 -13
  443. relationalai/early_access/dsl/core/cset.py +0 -132
  444. relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  445. relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  446. relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  447. relationalai/early_access/dsl/core/instances.py +0 -44
  448. relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  449. relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  450. relationalai/early_access/dsl/core/logic/exists.py +0 -223
  451. relationalai/early_access/dsl/core/logic/helper.py +0 -163
  452. relationalai/early_access/dsl/core/namespaces.py +0 -32
  453. relationalai/early_access/dsl/core/relations.py +0 -276
  454. relationalai/early_access/dsl/core/rules.py +0 -112
  455. relationalai/early_access/dsl/core/std/__init__.py +0 -45
  456. relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  457. relationalai/early_access/dsl/core/types/__init__.py +0 -270
  458. relationalai/early_access/dsl/core/types/concepts.py +0 -128
  459. relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  460. relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  461. relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  462. relationalai/early_access/dsl/core/types/standard.py +0 -92
  463. relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  464. relationalai/early_access/dsl/core/types/variables.py +0 -203
  465. relationalai/early_access/dsl/ir/compiler.py +0 -318
  466. relationalai/early_access/dsl/ir/executor.py +0 -260
  467. relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  468. relationalai/early_access/dsl/ontologies/export.py +0 -30
  469. relationalai/early_access/dsl/ontologies/models.py +0 -453
  470. relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  471. relationalai/early_access/dsl/ontologies/readings.py +0 -60
  472. relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  473. relationalai/early_access/dsl/ontologies/roles.py +0 -87
  474. relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  475. relationalai/early_access/dsl/orm/constraints.py +0 -438
  476. relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  477. relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  478. relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  479. relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  480. relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  481. relationalai/early_access/dsl/orm/models.py +0 -256
  482. relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  483. relationalai/early_access/dsl/orm/printer.py +0 -469
  484. relationalai/early_access/dsl/orm/reasoners.py +0 -480
  485. relationalai/early_access/dsl/orm/relations.py +0 -19
  486. relationalai/early_access/dsl/orm/relationships.py +0 -251
  487. relationalai/early_access/dsl/orm/types.py +0 -42
  488. relationalai/early_access/dsl/orm/utils.py +0 -79
  489. relationalai/early_access/dsl/orm/verb.py +0 -204
  490. relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  491. relationalai/early_access/dsl/relations.py +0 -170
  492. relationalai/early_access/dsl/rulesets.py +0 -69
  493. relationalai/early_access/dsl/schemas/__init__.py +0 -450
  494. relationalai/early_access/dsl/schemas/builder.py +0 -48
  495. relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  496. relationalai/early_access/dsl/schemas/components.py +0 -203
  497. relationalai/early_access/dsl/schemas/contexts.py +0 -156
  498. relationalai/early_access/dsl/schemas/exprs.py +0 -89
  499. relationalai/early_access/dsl/schemas/fragments.py +0 -464
  500. relationalai/early_access/dsl/serialization.py +0 -79
  501. relationalai/early_access/dsl/serialize/exporter.py +0 -163
  502. relationalai/early_access/dsl/snow/api.py +0 -104
  503. relationalai/early_access/dsl/snow/common.py +0 -76
  504. relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  505. relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  506. relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  507. relationalai/early_access/dsl/types/__init__.py +0 -40
  508. relationalai/early_access/dsl/types/concepts.py +0 -12
  509. relationalai/early_access/dsl/types/entities.py +0 -135
  510. relationalai/early_access/dsl/types/values.py +0 -17
  511. relationalai/early_access/dsl/utils.py +0 -102
  512. relationalai/early_access/graphs/__init__.py +0 -13
  513. relationalai/early_access/lqp/__init__.py +0 -12
  514. relationalai/early_access/lqp/compiler/__init__.py +0 -12
  515. relationalai/early_access/lqp/constructors/__init__.py +0 -18
  516. relationalai/early_access/lqp/executor/__init__.py +0 -12
  517. relationalai/early_access/lqp/ir/__init__.py +0 -12
  518. relationalai/early_access/lqp/passes/__init__.py +0 -12
  519. relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  520. relationalai/early_access/lqp/primitives/__init__.py +0 -12
  521. relationalai/early_access/lqp/types/__init__.py +0 -12
  522. relationalai/early_access/lqp/utils/__init__.py +0 -12
  523. relationalai/early_access/lqp/validators/__init__.py +0 -12
  524. relationalai/early_access/metamodel/__init__.py +0 -58
  525. relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  526. relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  527. relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  528. relationalai/early_access/metamodel/factory/__init__.py +0 -17
  529. relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  530. relationalai/early_access/metamodel/ir/__init__.py +0 -14
  531. relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  532. relationalai/early_access/metamodel/typer/__init__.py +0 -3
  533. relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  534. relationalai/early_access/metamodel/types/__init__.py +0 -15
  535. relationalai/early_access/metamodel/util/__init__.py +0 -15
  536. relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  537. relationalai/early_access/rel/__init__.py +0 -12
  538. relationalai/early_access/rel/executor/__init__.py +0 -12
  539. relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  540. relationalai/early_access/rel/rewrite/__init__.py +0 -7
  541. relationalai/early_access/solvers/__init__.py +0 -19
  542. relationalai/early_access/sql/__init__.py +0 -11
  543. relationalai/early_access/sql/executor/__init__.py +0 -3
  544. relationalai/early_access/sql/rewrite/__init__.py +0 -3
  545. relationalai/early_access/tests/logging/__init__.py +0 -12
  546. relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  547. relationalai/early_access/tests/utils/__init__.py +0 -12
  548. relationalai/environments/__init__.py +0 -35
  549. relationalai/environments/base.py +0 -381
  550. relationalai/environments/colab.py +0 -14
  551. relationalai/environments/generic.py +0 -71
  552. relationalai/environments/ipython.py +0 -68
  553. relationalai/environments/jupyter.py +0 -9
  554. relationalai/environments/snowbook.py +0 -169
  555. relationalai/errors.py +0 -2455
  556. relationalai/experimental/SF.py +0 -38
  557. relationalai/experimental/inspect.py +0 -47
  558. relationalai/experimental/pathfinder/__init__.py +0 -158
  559. relationalai/experimental/pathfinder/api.py +0 -160
  560. relationalai/experimental/pathfinder/automaton.py +0 -584
  561. relationalai/experimental/pathfinder/bridge.py +0 -226
  562. relationalai/experimental/pathfinder/compiler.py +0 -416
  563. relationalai/experimental/pathfinder/datalog.py +0 -214
  564. relationalai/experimental/pathfinder/diagnostics.py +0 -56
  565. relationalai/experimental/pathfinder/filter.py +0 -236
  566. relationalai/experimental/pathfinder/glushkov.py +0 -439
  567. relationalai/experimental/pathfinder/options.py +0 -265
  568. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
  569. relationalai/experimental/pathfinder/rpq.py +0 -344
  570. relationalai/experimental/pathfinder/transition.py +0 -200
  571. relationalai/experimental/pathfinder/utils.py +0 -26
  572. relationalai/experimental/paths/README.md +0 -107
  573. relationalai/experimental/paths/api.py +0 -143
  574. relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  575. relationalai/experimental/paths/code_organization.md +0 -2
  576. relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
  577. relationalai/experimental/paths/examples/basic_example.py +0 -40
  578. relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  579. relationalai/experimental/paths/examples/movie_example.py +0 -77
  580. relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
  581. relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
  582. relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
  583. relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
  584. relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
  585. relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
  586. relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
  587. relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
  588. relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  589. relationalai/experimental/paths/examples/paths_example.py +0 -116
  590. relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  591. relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  592. relationalai/experimental/paths/graph.py +0 -185
  593. relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  594. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  595. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  596. relationalai/experimental/paths/path_algorithms/single.py +0 -59
  597. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  598. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  599. relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  600. relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  601. relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  602. relationalai/experimental/paths/product_graph.py +0 -93
  603. relationalai/experimental/paths/rpq/automaton.py +0 -584
  604. relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  605. relationalai/experimental/paths/rpq/rpq.py +0 -378
  606. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  607. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  608. relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  609. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  610. relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  611. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  612. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  613. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  614. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  615. relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  616. relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  617. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  618. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  619. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  620. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  621. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  622. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  623. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  624. relationalai/experimental/paths/tree_agg.py +0 -168
  625. relationalai/experimental/paths/utilities/iterators.py +0 -27
  626. relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  627. relationalai/experimental/solvers.py +0 -1087
  628. relationalai/loaders/csv.py +0 -195
  629. relationalai/loaders/loader.py +0 -177
  630. relationalai/loaders/types.py +0 -23
  631. relationalai/rel_emitter.py +0 -373
  632. relationalai/rel_utils.py +0 -185
  633. relationalai/semantics/designs/query_builder/identify_by.md +0 -106
  634. relationalai/semantics/devtools/benchmark_lqp.py +0 -536
  635. relationalai/semantics/devtools/compilation_manager.py +0 -294
  636. relationalai/semantics/devtools/extract_lqp.py +0 -110
  637. relationalai/semantics/internal/internal.py +0 -3785
  638. relationalai/semantics/internal/snowflake.py +0 -324
  639. relationalai/semantics/lqp/README.md +0 -34
  640. relationalai/semantics/lqp/builtins.py +0 -16
  641. relationalai/semantics/lqp/compiler.py +0 -22
  642. relationalai/semantics/lqp/constructors.py +0 -68
  643. relationalai/semantics/lqp/executor.py +0 -469
  644. relationalai/semantics/lqp/intrinsics.py +0 -24
  645. relationalai/semantics/lqp/model2lqp.py +0 -839
  646. relationalai/semantics/lqp/passes.py +0 -680
  647. relationalai/semantics/lqp/primitives.py +0 -252
  648. relationalai/semantics/lqp/result_helpers.py +0 -202
  649. relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -57
  650. relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  651. relationalai/semantics/lqp/rewrite/extract_common.py +0 -338
  652. relationalai/semantics/lqp/rewrite/extract_keys.py +0 -449
  653. relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  654. relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -314
  655. relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -296
  656. relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  657. relationalai/semantics/lqp/types.py +0 -101
  658. relationalai/semantics/lqp/utils.py +0 -160
  659. relationalai/semantics/lqp/validators.py +0 -57
  660. relationalai/semantics/metamodel/compiler.py +0 -133
  661. relationalai/semantics/metamodel/dependency.py +0 -862
  662. relationalai/semantics/metamodel/executor.py +0 -61
  663. relationalai/semantics/metamodel/factory.py +0 -287
  664. relationalai/semantics/metamodel/helpers.py +0 -361
  665. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  666. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -210
  667. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  668. relationalai/semantics/metamodel/rewrite/flatten.py +0 -549
  669. relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -165
  670. relationalai/semantics/metamodel/typer/checker.py +0 -353
  671. relationalai/semantics/metamodel/typer/typer.py +0 -1395
  672. relationalai/semantics/reasoners/__init__.py +0 -10
  673. relationalai/semantics/reasoners/graph/README.md +0 -620
  674. relationalai/semantics/reasoners/graph/__init__.py +0 -37
  675. relationalai/semantics/reasoners/graph/core.py +0 -9020
  676. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
  677. relationalai/semantics/reasoners/graph/tests/README.md +0 -21
  678. relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  679. relationalai/semantics/reasoners/optimization/common.py +0 -88
  680. relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  681. relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1163
  682. relationalai/semantics/rel/builtins.py +0 -40
  683. relationalai/semantics/rel/compiler.py +0 -989
  684. relationalai/semantics/rel/executor.py +0 -359
  685. relationalai/semantics/rel/rel.py +0 -482
  686. relationalai/semantics/rel/rel_utils.py +0 -276
  687. relationalai/semantics/snowflake/__init__.py +0 -3
  688. relationalai/semantics/sql/compiler.py +0 -2503
  689. relationalai/semantics/sql/executor/duck_db.py +0 -52
  690. relationalai/semantics/sql/executor/result_helpers.py +0 -64
  691. relationalai/semantics/sql/executor/snowflake.py +0 -145
  692. relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  693. relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  694. relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  695. relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  696. relationalai/semantics/sql/sql.py +0 -504
  697. relationalai/semantics/std/pragmas.py +0 -11
  698. relationalai/semantics/std/std.py +0 -14
  699. relationalai/semantics/tests/test_snapshot_abstract.py +0 -143
  700. relationalai/semantics/tests/test_snapshot_base.py +0 -9
  701. relationalai/semantics/tests/utils.py +0 -46
  702. relationalai/std/__init__.py +0 -70
  703. relationalai/tools/cli.py +0 -1940
  704. relationalai/tools/cli_controls.py +0 -1826
  705. relationalai/tools/cli_helpers.py +0 -390
  706. relationalai/tools/debugger_client.py +0 -109
  707. relationalai/tools/debugger_server.py +0 -302
  708. relationalai/tools/dev.py +0 -685
  709. relationalai/tools/notes +0 -7
  710. relationalai/tools/qb_debugger.py +0 -425
  711. relationalai/util/clean_up_databases.py +0 -95
  712. relationalai/util/list_databases.py +0 -9
  713. relationalai/util/otel_configuration.py +0 -25
  714. relationalai/util/otel_handler.py +0 -484
  715. relationalai/util/snowflake_handler.py +0 -88
  716. relationalai/util/span_format_test.py +0 -43
  717. relationalai/util/span_tracker.py +0 -207
  718. relationalai/util/spans_file_handler.py +0 -72
  719. relationalai/util/tracing_handler.py +0 -34
  720. relationalai-0.12.13.dist-info/METADATA +0 -74
  721. relationalai-0.12.13.dist-info/RECORD +0 -449
  722. relationalai-0.12.13.dist-info/WHEEL +0 -4
  723. relationalai-0.12.13.dist-info/entry_points.txt +0 -3
  724. relationalai-0.12.13.dist-info/licenses/LICENSE +0 -202
  725. relationalai_test_util/__init__.py +0 -4
  726. relationalai_test_util/fixtures.py +0 -228
  727. relationalai_test_util/snapshot.py +0 -252
  728. relationalai_test_util/traceback.py +0 -118
  729. /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
  730. /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
  731. /relationalai/{early_access → shims}/__init__.py +0 -0
  732. {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
  733. {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
  734. {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
  735. {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
  736. {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
  737. {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
  738. {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
  739. {relationalai → v0/relationalai}/auth/util.py +0 -0
  740. {relationalai → v0/relationalai}/clients/__init__.py +0 -0
  741. {relationalai → v0/relationalai}/clients/cache_store.py +0 -0
  742. {relationalai → v0/relationalai}/compiler.py +0 -0
  743. {relationalai → v0/relationalai}/dependencies.py +0 -0
  744. {relationalai → v0/relationalai}/docutils.py +0 -0
  745. {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
  746. {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
  747. {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  748. {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  749. {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  750. {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  751. {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  752. {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  753. {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  754. {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  755. {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
  756. {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
  757. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  758. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  759. {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
  760. {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  761. {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
  762. {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
  763. {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  764. {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  765. {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
  766. {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  767. {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  768. {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  769. {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  770. {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  771. {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
  772. {relationalai/tools → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
  773. {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
  774. {relationalai → v0/relationalai}/environments/ci.py +0 -0
  775. {relationalai → v0/relationalai}/environments/hex.py +0 -0
  776. {relationalai → v0/relationalai}/environments/terminal.py +0 -0
  777. {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
  778. {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
  779. {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
  780. {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  781. {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  782. {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
  783. {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
  784. {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  785. {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
  786. {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
  787. {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
  788. {relationalai → v0/relationalai}/metagen.py +0 -0
  789. {relationalai → v0/relationalai}/metamodel.py +0 -0
  790. {relationalai → v0/relationalai}/rel.py +0 -0
  791. {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
  792. {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
  793. {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
  794. {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
  795. {relationalai → v0/relationalai}/semantics/lqp/ir.py +0 -0
  796. {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
  797. {relationalai → v0/relationalai}/semantics/lqp/rewrite/__init__.py +0 -0
  798. {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
  799. {relationalai → v0/relationalai}/semantics/metamodel/ir.py +0 -0
  800. {relationalai → v0/relationalai}/semantics/metamodel/rewrite/__init__.py +0 -0
  801. {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  802. {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
  803. {relationalai → v0/relationalai}/semantics/metamodel/util.py +0 -0
  804. {relationalai → v0/relationalai}/semantics/metamodel/visitor.py +0 -0
  805. {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  806. {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
  807. {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
  808. {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
  809. {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  810. {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
  811. {relationalai → v0/relationalai}/std/aggregates.py +0 -0
  812. {relationalai → v0/relationalai}/std/dates.py +0 -0
  813. {relationalai → v0/relationalai}/std/graphs.py +0 -0
  814. {relationalai → v0/relationalai}/std/inspect.py +0 -0
  815. {relationalai → v0/relationalai}/std/math.py +0 -0
  816. {relationalai → v0/relationalai}/std/re.py +0 -0
  817. {relationalai → v0/relationalai}/std/strings.py +0 -0
  818. {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
  819. {relationalai → v0/relationalai}/tools/constants.py +0 -0
  820. {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
  821. {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
  822. {relationalai → v0/relationalai}/util/__init__.py +0 -0
  823. {relationalai → v0/relationalai}/util/constants.py +0 -0
  824. {relationalai → v0/relationalai}/util/graph.py +0 -0
  825. {relationalai → v0/relationalai}/util/timeout.py +0 -0
relationalai/dsl.py DELETED
@@ -1,1749 +0,0 @@
1
- from __future__ import annotations
2
- import base64
3
- from enum import Enum
4
- import inspect
5
- from itertools import zip_longest
6
- import re
7
- import struct
8
- import threading
9
- import typing
10
- from typing import Any, Dict, List, Optional, Set, Tuple, Union, get_type_hints
11
- from relationalai.clients.util import IdentityParser, ParseError
12
- from typing_extensions import TypeGuard
13
- import numbers
14
- import os
15
- import datetime
16
- import hashlib
17
- import traceback
18
- import rich
19
- import json
20
- import sys
21
-
22
- from pandas import DataFrame
23
-
24
- from relationalai.environments import runtime_env, SnowbookEnvironment
25
- from relationalai.tools.constants import QUERY_ATTRIBUTES_HEADER
26
-
27
- from .clients.client import Client
28
-
29
- from .metamodel import Behavior, Builtins, ActionType, Var, Task, Action, Builder, Type as mType, Property as mProperty
30
- from . import debugging, errors
31
- from .errors import FilterAsValue, Errors, InvalidPropertySetException, MultipleIdentities, NonCallablePropertyException, OutOfContextException, RAIException, ReservedPropertyException, VariableOutOfContextException, handle_missing_integration
32
-
33
- #--------------------------------------------------
34
- # Constants
35
- #--------------------------------------------------
36
-
37
- RESERVED_PROPS = ["add", "set", "persist", "unpersist"]
38
- MAX_QUERY_ATTRIBUTE_LENGTH = 255
39
-
40
- Value = Union[
41
- "Expression",
42
- "ContextSelect", # because of union/match
43
- int,
44
- float,
45
- str,
46
- bool,
47
- datetime.datetime,
48
- datetime.date,
49
- ]
50
-
51
- #--------------------------------------------------
52
- # Helpers
53
- #--------------------------------------------------
54
-
55
- # @FIXME: This should only return a Var or None but that's gonna take some doing.
56
- def to_var(x:Any) -> Any:
57
- if isinstance(x, Var):
58
- return x
59
- if getattr(x, "_to_var", None):
60
- return to_var(x._to_var())
61
- if isinstance(x, ContextSelect):
62
- return x._vars[0]
63
- if isinstance(x, mProperty):
64
- return Var(value=x)
65
- if isinstance(x, mType):
66
- return Var(value=x)
67
- if isinstance(x, Producer):
68
- x._use_var()
69
- return x._var
70
- if isinstance(x, list) or isinstance(x, tuple):
71
- return Var(Builtins.Any, value=[v for i in x if (v := to_var(i))])
72
- if isinstance(x, str):
73
- return Var(Builtins.String, None, x)
74
- if isinstance(x, numbers.Number):
75
- return Var(Builtins.Number, None, x)
76
- if isinstance(x, datetime.datetime) or isinstance(x, datetime.date):
77
- return Var(value=x)
78
- raise Exception(f"Unknown type: {type(x)}\n{x}")
79
-
80
- build = Builder(to_var)
81
-
82
- def to_list(x:Any):
83
- if isinstance(x, list):
84
- return x
85
- if isinstance(x, tuple):
86
- return list(x)
87
- return [x]
88
-
89
- def is_static(x:Any):
90
- if isinstance(x, Var):
91
- return x.value is not None
92
- if isinstance(x, Type):
93
- return True
94
- if isinstance(x, str):
95
- return True
96
- if isinstance(x, Producer):
97
- return is_static(to_var(x))
98
- if isinstance(x, numbers.Number):
99
- return True
100
- if isinstance(x, list):
101
- return all(is_static(i) for i in x)
102
- if isinstance(x, tuple):
103
- return all(is_static(i) for i in x)
104
- if isinstance(x, dict):
105
- return all(is_static(i) for i in x.values())
106
- return False
107
-
108
- def is_collection(x:Any) -> TypeGuard[Union[List, Tuple, Set]]:
109
- return isinstance(x, list) or isinstance(x, tuple) or isinstance(x, set)
110
-
111
- def rel_dict(**kwargs):
112
- return InlineRelation(get_graph(), [
113
- (Symbol(k), v) for k, v in kwargs.items()
114
- ])
115
-
116
- #--------------------------------------------------
117
- # Base
118
- #--------------------------------------------------
119
-
120
- id = 0
121
- def next_id():
122
- global id
123
- id += 1
124
- return id
125
-
126
- #--------------------------------------------------
127
- # Producer
128
- #--------------------------------------------------
129
-
130
- attributes_to_skip = {
131
- "_to_var",
132
- "__name__",
133
- "__qualname__",
134
- "_repr_html_",
135
- "_supports_binary_op",
136
- }
137
-
138
- def is_streamlit_running():
139
- # First check: Is streamlit imported?
140
- if 'streamlit' not in sys.modules:
141
- return False
142
-
143
- # Second check: Try to access session_state
144
- try:
145
- import streamlit as st #type: ignore
146
- _ = st.session_state
147
- return True
148
- except RuntimeError:
149
- return False
150
-
151
- def is_called_by_streamlit_write():
152
- if not is_streamlit_running():
153
- return False
154
-
155
- stack_frames = inspect.stack()
156
-
157
- for frame in stack_frames[1:]:
158
- if ("streamlit" in frame.filename and "write" in frame.function):
159
- return True
160
-
161
- return False
162
-
163
- class Producer():
164
- def __init__(self, graph:'Graph'):
165
- self._id = next_id()
166
- self._graph = graph
167
- self._subs = {}
168
- self._var = None
169
-
170
- def __iter__(self):
171
- if is_called_by_streamlit_write():
172
- return iter([])
173
- raise Exception("Can't iterate over a producer")
174
-
175
- def __repr__(self):
176
- if isinstance(runtime_env, SnowbookEnvironment):
177
- # suppress spurious output in Snowflake notebooks
178
- # for expressions like p.age > 18
179
- return ""
180
- else:
181
- return super().__repr__()
182
-
183
- def __getattr__(self, name: str) -> Any:
184
- if is_called_by_streamlit_write():
185
- return None
186
- if name in attributes_to_skip:
187
- return None
188
- self._subs[name] = self._make_sub(name, self._subs.get(name))
189
- return self._subs[name]
190
-
191
- def _make_sub(self, name:str, existing:Optional['Producer']=None) -> Any:
192
- raise Exception("Implement Producer._make_sub")
193
-
194
- def _use_var(self):
195
- pass
196
-
197
- #--------------------------------------------------
198
- # Boolean overloads
199
- #--------------------------------------------------
200
-
201
- def __bool__(self):
202
- # This doesn't seem to be safe as Python can call bool on Producers in lots of random cases
203
- # InvalidBoolWarning(Errors.call_source())
204
- # class_name = self.__class__.__name__
205
- # TODO: Refactor this to be Exception instead of warning, so we could directly raise it if we bring back this
206
- # raise TypeError(f"Can't convert an {class_name} to a boolean.")
207
- return True
208
-
209
- #--------------------------------------------------
210
- # Math overloads
211
- #--------------------------------------------------
212
-
213
- def _wrapped_op(self, op, left, right):
214
- # Check if an active context redefines this binary operator (e.g. for the solvers library).
215
- for s in self._graph._stack.stack:
216
- f = getattr(s, "_supports_binary_op", None)
217
- if f and f(op):
218
- return s._make_binary_op(op, left, right)
219
- return Expression(self._graph, op, [left, right])
220
-
221
- def __add__(self, other):
222
- return self._wrapped_op(Builtins.plus, self, other)
223
- def __radd__(self, other):
224
- return self._wrapped_op(Builtins.plus, other, self)
225
-
226
- def __mul__(self, other):
227
- return self._wrapped_op(Builtins.mult, self, other)
228
- def __rmul__(self, other):
229
- return self._wrapped_op(Builtins.mult, other, self)
230
-
231
- def __sub__(self, other):
232
- return self._wrapped_op(Builtins.minus, self, other)
233
- def __rsub__(self, other):
234
- return self._wrapped_op(Builtins.minus, other, self)
235
-
236
- def __truediv__(self, other):
237
- return self._wrapped_op(Builtins.div, self, other)
238
- def __rtruediv__(self, other):
239
- return self._wrapped_op(Builtins.div, other, self)
240
-
241
- def __floordiv__(self, other):
242
- return self._wrapped_op(Builtins.floor_div, self, other)
243
- def __rfloordiv__(self, other):
244
- return self._wrapped_op(Builtins.floor_div, other, self)
245
-
246
- def __pow__(self, other):
247
- return self._wrapped_op(Builtins.pow, self, other)
248
- def __rpow__(self, other):
249
- return self._wrapped_op(Builtins.pow, other, self)
250
-
251
- def __mod__(self, other):
252
- return self._wrapped_op(Builtins.mod, self, other)
253
- def __rmod__(self, other):
254
- return self._wrapped_op(Builtins.mod, other, self)
255
-
256
- def __neg__(self):
257
- return self._wrapped_op(Builtins.mult, self, -1)
258
-
259
- #--------------------------------------------------
260
- # Filter overloads
261
- #--------------------------------------------------
262
-
263
- def __gt__(self, other):
264
- return self._wrapped_op(Builtins.gt, self, other)
265
- def __ge__(self, other):
266
- return self._wrapped_op(Builtins.gte, self, other)
267
- def __lt__(self, other):
268
- return self._wrapped_op(Builtins.lt, self, other)
269
- def __le__(self, other):
270
- return self._wrapped_op(Builtins.lte, self, other)
271
- def __eq__(self, other) -> Any:
272
- return self._wrapped_op(Builtins.approx_eq, self, other)
273
- def __ne__(self, other) -> Any:
274
- return self._wrapped_op(Builtins.neq, self, other)
275
-
276
- #--------------------------------------------------
277
- # Context management
278
- #--------------------------------------------------
279
-
280
- def __enter__(self):
281
- self._graph._push(self)
282
-
283
- def __exit__(self, *args):
284
- self._graph._pop(self)
285
-
286
- #--------------------------------------------------
287
- # Context
288
- #--------------------------------------------------
289
-
290
- class TaskExecType(Enum):
291
- Query = 1
292
- Rule = 2
293
- Procedure = 3
294
- Export = 4
295
-
296
- class ContextSelect(Producer):
297
- def __init__(self, context:'Context'):
298
- super().__init__(context.graph)
299
- self._context = context
300
- self._select_len = None
301
- self._insts = []
302
- self._vars = []
303
- self._props = {}
304
-
305
- def _assign_vars(self):
306
- task = self._context._task
307
- if not len(self._vars) and self._select_len:
308
- self._insts = to_list(Vars(self._select_len))
309
- self._vars = [to_var(v) for v in self._insts]
310
- task.properties = [Builtins.Relation.properties[i] for i in range(self._select_len)]
311
- task.bindings.update({Builtins.Relation.properties[i]: v for i, v in enumerate(self._vars)})
312
-
313
- def __getattr__(self, name: str) -> Any:
314
- if name.startswith("_"):
315
- return None
316
- if name in self._props:
317
- return Instance(self._context.graph, ActionType.Get, [], {}, var=to_var(self._props[name]))
318
- else:
319
- return getattr(Instance(self._context.graph, ActionType.Get, [], {}, var=to_var(self._vars[0])), name)
320
-
321
- #--------------------------------------------------
322
- # Return handling
323
- #--------------------------------------------------
324
-
325
- def _do_return(self, args, distinct=False):
326
- graph = self._context.graph
327
- task = self._context._task
328
- if task.behavior == Behavior.Query \
329
- and self._context._exec_type in [TaskExecType.Query, TaskExecType.Procedure]:
330
- if isinstance(args[0], tuple):
331
- args = args[0]
332
- export = self._context._format == "snowpark"
333
- graph._action(build.return_(list(args), export=export, distinct=distinct))
334
- else:
335
- #TODO: good error message depending on the type of task we're dealing with
336
- raise Exception("Can't select in a non-query")
337
- return self._context
338
-
339
- def __call__(self, *args: Any) -> Any:
340
- if self._context._done:
341
- raise errors.SelectOutOfContext()
342
- return self._do_return(args)
343
-
344
- def distinct(self, *args:Any) -> Any:
345
- if self._context._done:
346
- raise errors.SelectOutOfContext()
347
- return self._do_return(args, distinct=True)
348
-
349
- #--------------------------------------------------
350
- # Add for `model.match() as m`
351
- #--------------------------------------------------
352
-
353
- def add(self, item, **kwargs):
354
- arg_len = len(kwargs) + 1
355
- if self._select_len is not None and arg_len != self._select_len:
356
- raise Exception("Add must be provided the same arguments in each branch")
357
- self._select_len = arg_len
358
- self._assign_vars()
359
- if len(self._props) and set(self._props.keys()) != set(kwargs.keys()):
360
- raise Exception("Add must be provided the same properties in each branch")
361
- elif len(self._props) == 0:
362
- for k, v in zip(kwargs.keys(), self._vars[1:]):
363
- v.name = k
364
- self._props[k] = v
365
-
366
- graph = self._context.graph
367
- graph._action(build.relation_action(ActionType.Bind, self._context._task, [item, *[kwargs[k] for k in self._props.keys()]]))
368
-
369
- class Context():
370
- def __init__(self, graph:'Graph', *args, behavior=Behavior.Query, op=None,
371
- exec_type=TaskExecType.Rule, dynamic=False, format="default",
372
- props=None, engine=None, tag=None, globalize=False, source=None,
373
- attributes=None, read_only=False, skip_invalid_data=False):
374
- self._id = next_id()
375
- self.results = DataFrame()
376
- self.graph = graph
377
- self._task = Task(behavior=behavior)
378
- self._globalize = globalize
379
- self._op = op
380
- self._args = list(args)
381
- self._exec_type = exec_type
382
- self._select_len = None
383
- self._dynamic = dynamic or any([item._dynamic for item in self.graph._stack.stack if isinstance(item, Context)])
384
- self._props = props or {}
385
- self._engine= engine
386
- self._tag = tag # for benchmark reporting
387
- self._format = self._resolve_format(format)
388
- self._done = False
389
- self._source = source
390
- self._read_only:bool = read_only
391
- self._skip_invalid_data:bool = skip_invalid_data
392
-
393
- self._validate_attributes(attributes)
394
- self._attributes = attributes
395
-
396
- def _validate_attributes(self, attributes):
397
- if attributes is None:
398
- return True
399
-
400
- for key, value in attributes.items():
401
- self._validate_attribute_item(key)
402
- self._validate_attribute_item(value)
403
-
404
- def _validate_attribute_item(self, item):
405
- assert isinstance(item, str), f"'{item}' must be a string"
406
- assert len(item) <= MAX_QUERY_ATTRIBUTE_LENGTH, f"'{item}' exceeds the maximum length of {MAX_QUERY_ATTRIBUTE_LENGTH} characters."
407
- assert re.match(r'^[a-zA-Z0-9_-]+$', item), f"'{item}' must contain only alphanumeric characters, underscores, or hyphens."
408
-
409
- def _resolve_format(self, format):
410
- if format == "default":
411
- if self.graph._format != "default":
412
- return self.graph._format
413
- if self.graph._config.get("platform") == "snowflake":
414
- # In the future we may want to default to snowpark
415
- return "pandas"
416
- return "pandas"
417
- return format
418
-
419
- def __enter__(self):
420
- debugging.set_source(self._task, self._source)
421
- self.graph._push(self)
422
- return ContextSelect(self)
423
-
424
- def __exit__(self, *args):
425
- self._done = True
426
- # If no exception info has been passed to args,
427
- # then proceed with the normal exit process.
428
- # Otherwise, return False to propagate the exception.
429
- if args[0] is None:
430
- if not self._dynamic:
431
- debugging.check_errors(self._task)
432
- try:
433
- self.graph._pop(self, globalize=self._globalize)
434
- except KeyboardInterrupt as e:
435
- print("Canceling transactions...")
436
- self.graph.resources.cancel_pending_transactions()
437
- raise e
438
- except RAIException as e:
439
- handle_missing_integration(e)
440
- raise e.clone(self.graph._config) from None
441
- else:
442
- self.graph._pop(self, exec=False)
443
- if isinstance(args[1], RAIException):
444
- raise args[1].clone(self.graph._config) from None
445
- return False
446
-
447
- def __iter__(self):
448
- if self._exec_type != TaskExecType.Query:
449
- raise Exception("Can't iterate over a non-query task")
450
- else:
451
- return self.results.itertuples(index=False)
452
-
453
- def _repr_html_(self):
454
- if self._exec_type == TaskExecType.Query:
455
- if isinstance(self.results, DataFrame):
456
- return self.results.to_html(index=False)
457
- elif getattr(self.results, "_repr_html_", None):
458
- return self.results._repr_html_()
459
- elif getattr(self.results, "show"):
460
- self.results.show()
461
- return ""
462
- else:
463
- return str(self.results)
464
-
465
- def __str__(self):
466
- if self._exec_type == TaskExecType.Query:
467
- if isinstance(self.results, DataFrame):
468
- return self.results.to_string(index=False)
469
- else:
470
- return str(self.results)
471
- return super().__str__()
472
-
473
- #--------------------------------------------------
474
- # Type
475
- #--------------------------------------------------
476
-
477
- def hash_values_sha256_truncated(args):
478
- combined = ''.join(map(str, args))
479
- combined_bytes = combined.encode('utf-8')
480
- hasher = hashlib.sha256()
481
- hasher.update(combined_bytes)
482
- hash_128_bit = hasher.digest()[:16]
483
- return hash_128_bit
484
-
485
- # @NOTE: `omit_intrinsic_type_in_hash` exists to keep node hashes (which are namespaced by their graph) stable
486
- # when new nodes are directly created via `Node.add(x = ..)` instead of marking existing entities as
487
- # nodes. Possible hash collisions between types happen to be okay in this case because of the access
488
- # paths, but it's _not_ generally safe to use it otherwise.
489
- class Type(Producer):
490
- def __init__(self, graph:'Graph', name:str, builtins:List[str] = [], scope:str="", omit_intrinsic_type_in_hash = False):
491
- super().__init__(graph)
492
- self._type = mType(scope+name)
493
- self._scope = scope
494
- self._omit_intrinsic_type_in_hash = omit_intrinsic_type_in_hash
495
- if graph._config.get("compiler.use_value_types", False):
496
- self._type.parents.append(Builtins.ValueType)
497
- install = build.install(self._type)
498
- self._graph._action(install)
499
- debugging.set_source(install)
500
-
501
- def __call__(self, *args, **kwargs):
502
- return Instance(self._graph, ActionType.Get, [self, *args], kwargs, name=self._type.name.lower(), scope=self._scope)
503
-
504
- def add(self, *args, **kwargs):
505
- inst = Instance(self._graph, ActionType.Bind, [self, *args], kwargs, name=self._type.name.lower(), is_add=True, scope=self._scope)
506
- if inst._action.entity.value is not None:
507
- pass
508
- elif is_static(args) and is_static(kwargs):
509
- params = [Var(value=t.name) for t in inst._action.types]
510
- if self._omit_intrinsic_type_in_hash:
511
- params.pop(0)
512
- params.extend(inst._action.bindings.values())
513
- inst._action.entity.value = hash_values_sha256_truncated(params)
514
- elif all([isinstance(a, Type) for a in args]):
515
- self._graph._action(build.ident(inst._action, self._omit_intrinsic_type_in_hash))
516
- inst._add_to_graph()
517
- return inst
518
-
519
- def persist(self, *args, **kwargs):
520
- inst = Instance(self._graph, ActionType.Persist, [self, *args], kwargs, name=self._type.name.lower(), is_add=True, scope=self._scope)
521
- if inst._action.entity.value is not None:
522
- pass
523
- elif is_static(args) and is_static(kwargs):
524
- params = [Var(value=t.name) for t in inst._action.types]
525
- params.extend(inst._action.bindings.values())
526
- inst._action.entity.value = hash_values_sha256_truncated(params)
527
- elif all([isinstance(a, Type) for a in args]):
528
- self._graph._action(build.ident(inst._action, self._omit_intrinsic_type_in_hash))
529
- inst._add_to_graph()
530
- return inst
531
-
532
- def extend(self, *args, **kwargs):
533
- for arg in args:
534
- if not isinstance(arg, Type):
535
- raise Exception("Can only extend a type with another type")
536
- with self._graph.rule(dynamic=True):
537
- a = arg()
538
- a.set(self)
539
- with self._graph.rule(dynamic=True):
540
- a = arg()
541
- neue = self(a)
542
- for k, v in kwargs.items():
543
- if isinstance(v, Property):
544
- v = getattr(a, v._prop.name)
545
- neue.set(**{k:v})
546
-
547
- def define(self, **kwargs):
548
- for k, v in kwargs.items():
549
- if isinstance(v, tuple):
550
- (other_type, left, right) = v
551
- with self._graph.rule():
552
- inst = other_type()
553
- me = self()
554
- getattr(inst, right) == getattr(me, left) # type: ignore
555
- if getattr(self, k).is_multi_valued:
556
- getattr(me, k).add(inst)
557
- else:
558
- me.set(**{k: inst})
559
- else:
560
- raise Exception("Define requires a tuple of (Type, left, right)")
561
- return self
562
-
563
- def keyed(self, **kwargs):
564
- return KeyedType(self, kwargs)
565
-
566
- def __or__(self, __value: Any) -> TypeUnion:
567
- if isinstance(__value, Type) or isinstance(__value, TypeIntersection):
568
- return TypeUnion(self._graph, [self, __value])
569
- if isinstance(__value, TypeUnion):
570
- return TypeUnion(self._graph, [self, *__value._types])
571
- raise Exception("Can't or a type with a non-type")
572
-
573
- def __and__(self, __value: Any) -> TypeIntersection:
574
- if isinstance(__value, Type) or isinstance(__value, TypeUnion):
575
- return TypeIntersection(self._graph, [self, __value])
576
- if isinstance(__value, TypeIntersection):
577
- return TypeIntersection(self._graph, [self, *__value._types])
578
- raise Exception("Can't & a type with a non-type")
579
-
580
- def _make_sub(self, name: str, existing=None):
581
- if existing is not None:
582
- return existing
583
- return Property(self._graph, name, [self._type], self, scope=self._scope)
584
-
585
- def known_properties(self):
586
- return [p.name.removeprefix(self._scope) for p in self._type.properties]
587
-
588
- #--------------------------------------------------
589
- # KeyedType
590
- #--------------------------------------------------
591
-
592
- class KeyedType(Producer):
593
- def __init__(self, type:Type, keys:Dict[str,Type]):
594
- super().__init__(type._graph)
595
- self._type = type
596
- self._relation = RawRelation(self._graph, type._type.name, len(keys))
597
- self._key_info = keys
598
- self._key_order = list(keys.keys())
599
- self._props = {}
600
-
601
- # declare the relation
602
- install = build.install(self._relation._type)
603
- self._graph._action(install)
604
- debugging.set_source(install)
605
-
606
- def _prop(self, name:str):
607
- if name not in self._props:
608
- self._props[name] = RawRelation(self._graph, f"{self._relation._name}_{name}", len(self._key_info)+1)
609
- return self._props[name]
610
-
611
- def extend(self, *args, **kwargs):
612
- raise errors.KeyedCantBeExtended()
613
-
614
- def _collect_keys(self, args:List[Any], kwargs:Dict[str,Any]):
615
- ks = self._key_info.keys()
616
- all_args = dict(zip(ks, args))
617
- all_args.update(kwargs)
618
- props = set(all_args.keys()) - set(ks)
619
- return all_args, {k: all_args.get(k) for k in ks if k in all_args}, {k: all_args[k] for k in props}
620
-
621
- def add(self, *args:Any, **kwargs):
622
- all_args, keys, props = self._collect_keys(list(args), kwargs)
623
- if len(keys) != len(self._key_info):
624
- raise errors.KeyedWrongArity(self._type._type.name, list(self._key_info.keys()), len(keys))
625
- self._relation.add(*keys.values())
626
- for k, v in props.items():
627
- self._prop(k).add(*keys, v)
628
- return KeyedInstance(self, list(keys), {})
629
-
630
- def __call__(self, *args, **kwargs):
631
- all_args, keys, props = self._collect_keys(list(args), kwargs)
632
- ks = self._key_info.keys()
633
- keys = [all_args.get(k, Vars(1)) for k in ks]
634
- self._relation(*keys)
635
- return KeyedInstance(self, keys, props)
636
-
637
- def __getattr__(self, name: str) -> Any:
638
- return self._props[name]
639
-
640
- class KeyedInstance(Producer):
641
- def __init__(self, keyed_type:KeyedType, keys:List[Any], kwargs:dict={}):
642
- self._keys = keys
643
- self._type = keyed_type
644
- for k, v in kwargs.items():
645
- self._type._prop(k)(*keys, v)
646
-
647
- def __getattr__(self, name:str):
648
- if name in self._type._key_order:
649
- return self._keys[self._type._key_order.index(name)]
650
- v = Vars(1)
651
- self._type._prop(name)(*self._keys, v)
652
- return v
653
-
654
- def set(self, **kwargs):
655
- for k, v in kwargs.items():
656
- self._type._prop(k).add(*self._keys, v)
657
- return self
658
-
659
- def __iter__(self):
660
- return iter(self._keys)
661
-
662
- def _to_var(self):
663
- raise Exception("KeyedTypes can't be returned directly, you can only reference properties")
664
-
665
- #--------------------------------------------------
666
- # TypeUnion
667
- #--------------------------------------------------
668
-
669
- class TypeUnion(Producer):
670
- def __init__(self, graph:'Graph', types:List[Type|TypeIntersection]):
671
- super().__init__(graph)
672
- self._types = types
673
-
674
- def __call__(self, *args, **kwargs) -> 'ContextSelect':
675
- if not len(self._graph._stack.stack):
676
- raise Exception("Can't create an instance outside of a context")
677
- graph = self._graph
678
- with graph.union(dynamic=True) as union:
679
- for t in self._types:
680
- with graph.scope():
681
- union.add(t(*args, **kwargs))
682
- return union
683
-
684
- def known_properties(self):
685
- props = []
686
- for t in self._types:
687
- for prop in t.known_properties():
688
- if prop not in props:
689
- props.append(prop)
690
- return props
691
-
692
- def __or__(self, __value: Any) -> 'TypeUnion':
693
- if isinstance(__value, Type):
694
- return TypeUnion(self._graph, [*self._types, __value])
695
- if isinstance(__value, TypeUnion):
696
- return TypeUnion(self._graph, [*self._types, *__value._types])
697
- raise Exception("Can't or a type with a non-type")
698
-
699
- def _make_sub(self, name: str, existing=None):
700
- if existing is not None:
701
- return existing
702
- return Property(self._graph, name, [t._type for t in self._types], self)
703
-
704
- #--------------------------------------------------
705
- # TypeIntersection
706
- #--------------------------------------------------
707
-
708
- class TypeIntersection(Producer):
709
- def __init__(self, graph:'Graph', types:List[Type|TypeUnion]):
710
- super().__init__(graph)
711
- self._types = types
712
-
713
- def __call__(self, *args, **kwargs) -> Producer:
714
- if not len(self._graph._stack.stack):
715
- raise Exception("Can't create an instance outside of a context")
716
- return self._types[0](*self._types[1:], *args, **kwargs)
717
-
718
- def known_properties(self):
719
- props = []
720
- for t in self._types:
721
- for prop in t.known_properties():
722
- if prop not in props:
723
- props.append(prop)
724
- return props
725
-
726
- def __and__(self, __value: Any) -> TypeIntersection:
727
- if isinstance(__value, Type):
728
- return TypeIntersection(self._graph, [*self._types, __value])
729
- if isinstance(__value, TypeIntersection):
730
- return TypeIntersection(self._graph, [*self._types, *__value._types])
731
- raise Exception("Can't & a type with a non-type")
732
-
733
- def _make_sub(self, name: str, existing=None):
734
- if existing is not None:
735
- return existing
736
- return Property(self._graph, name, [t._type for t in self._types], self)
737
-
738
- #--------------------------------------------------
739
- # Property
740
- #--------------------------------------------------
741
-
742
- class Property(Producer):
743
- def __init__(self, graph:'Graph', name:str, types:List[mType], provider:Type|TypeUnion|TypeIntersection, scope:str=""):
744
- super().__init__(graph)
745
- self._name = name
746
- self._type = types[0]
747
- self._scope = scope
748
- self._provider = provider
749
- self._prop = build.property_named(scope+name, types)
750
-
751
- def __call__(self, key:Any, value:Any):
752
- action = build.relation_action(ActionType.Get, self._prop, [key, value])
753
- self._graph._action(action)
754
-
755
- def _use_var(self):
756
- raise Exception("Support properties being used as vars")
757
-
758
- def _make_sub(self, name: str, existing=None):
759
- raise Exception("Support properties on properties?")
760
-
761
- def to_property(self):
762
- return self._prop
763
-
764
- def declare(self):
765
- self._graph._action(build.install(self._prop))
766
-
767
- def has_many(self):
768
- self.declare()
769
- self._graph._check_property(self._prop, multi_valued=True)
770
-
771
- @property
772
- def is_multi_valued(self):
773
- return self._graph._prop_is_multi.get(self._name)
774
-
775
- #--------------------------------------------------
776
- # Instance
777
- #--------------------------------------------------
778
-
779
- class Instance(Producer):
780
- def __init__(self, graph:'Graph', action_type:ActionType, positionals:List[Any], named:Dict[str,Any], var:Var|None=None, name=None, is_add=False, scope:str=""):
781
- super().__init__(graph)
782
- self._action = Action(action_type, to_var(var) if var else Var(name=name))
783
- self._actions = [self._action]
784
- self._sets = {}
785
- self._context = graph._stack.active()
786
- self._scope = scope
787
- available_types = []
788
- last_pos_var = None
789
-
790
- #--------------------------------------------------
791
- # Positionals
792
- #--------------------------------------------------
793
- has_ident = False
794
- for pos in positionals:
795
- if isinstance(pos, Type):
796
- self._action.append(pos._type)
797
- elif isinstance(pos, Instance):
798
- if has_ident:
799
- raise MultipleIdentities()
800
- has_ident = True
801
- self._action.append(to_var(pos))
802
- available_types.extend(pos._action.types)
803
- if last_pos_var:
804
- self._graph._action(build.eq(last_pos_var, self._action.entity))
805
- last_pos_var = self._action.entity
806
- elif isinstance(pos, TypeUnion) or isinstance(pos, TypeIntersection):
807
- self._action.append(to_var(pos()))
808
- available_types.extend([t._type for t in pos._types])
809
- if last_pos_var:
810
- self._graph._action(build.eq(last_pos_var, self._action.entity))
811
- last_pos_var = self._action.entity
812
- elif isinstance(pos, Producer):
813
- if has_ident:
814
- raise MultipleIdentities()
815
- has_ident = True
816
- self._action.append(to_var(pos))
817
- if last_pos_var:
818
- self._graph._action(build.eq(last_pos_var, self._action.entity))
819
- last_pos_var = self._action.entity
820
- elif isinstance(pos, (str, int)):
821
- if has_ident:
822
- raise MultipleIdentities()
823
- has_ident = True
824
- if isinstance(pos, str):
825
- try:
826
- decoded = base64.b64decode(pos + "==")
827
- if len(decoded) == 16:
828
- first_int = decoded[:8]
829
- second_int = decoded[8:]
830
- pos = struct.pack('<Q', struct.unpack('>Q', second_int)[0]) + \
831
- struct.pack('<Q', struct.unpack('>Q', first_int)[0])
832
- except Exception:
833
- pass
834
- self._action.append(Var(value=pos))
835
- last_pos_var = self._action.entity
836
- else:
837
- raise Exception(f"Unknown input type: {pos}")
838
- available_types.extend(self._action.types)
839
- if scope:
840
- available_types = [t for t in available_types if t.name.startswith(scope)]
841
-
842
- #--------------------------------------------------
843
- # Handle properties
844
- #--------------------------------------------------
845
- for name, val in named.items():
846
- prop = build.property_named(scope+name, available_types)
847
-
848
- if val is None:
849
- raise Exception(f"{prop}'s value is None, please provide a value for the property")
850
-
851
- if isinstance(val, int) and action_type == ActionType.Get:
852
- orig = val
853
- val = Vars(1)
854
- self._actions.append(build.eq(val, orig, approx=True))
855
-
856
- prop_var = to_var(val)
857
-
858
- if prop_var.isa(Builtins.ExternalInput):
859
- orig = prop_var
860
- prop_var = to_var(Vars(1))
861
- self._actions.append(build.eq(prop_var, orig, approx=True))
862
-
863
- if is_collection(prop_var.value):
864
- raise Exception("Can't set a property to a collection")
865
-
866
- if not prop_var.name:
867
- prop_var.name = prop.name
868
- if action_type.is_effect():
869
- self._graph._check_property(prop)
870
- else:
871
- self._graph._check_property(prop, unknown_cardinality=True)
872
- self._action.append(prop, prop_var)
873
-
874
- #--------------------------------------------------
875
- # Entities
876
- #--------------------------------------------------
877
- self._var = self._action.entity
878
- if self._var.type == Builtins.Unknown and len(self._action.types):
879
- self._var.type = self._action.types[0]
880
- if not is_add and (self._action.types or self._action.bindings):
881
- self._add_to_graph()
882
-
883
- def _to_var(self):
884
- if not self._graph._stack.contains(self._context):
885
- exception = VariableOutOfContextException(Errors.call_source(), self._var.name)
886
- raise exception from None
887
- return self._var
888
-
889
- def _add_to_graph(self):
890
- for action in self._actions:
891
- self._graph._action(action)
892
-
893
- def __call__(self, *args, **kwargs):
894
- pass
895
-
896
- def __setattr__(self, name: str, value: Any) -> None:
897
- if name.startswith("_"):
898
- return super().__setattr__(name, value)
899
- exception = InvalidPropertySetException(Errors.call_source(3))
900
- raise exception from None
901
-
902
- def _make_sub(self, name: str, existing=None):
903
- if self._sets.get(name) is not None:
904
- return self._sets[name]
905
- if existing is not None:
906
- inst = InstanceProperty(self._graph, self, name, var=existing._var, scope=self._scope)
907
- inst._subs = existing._subs
908
- return inst
909
- prop = build.property_named(self._scope+name, self._action.types)
910
- if self._action.bindings.get(prop):
911
- return InstanceProperty(self._graph, self, name, var=self._action.bindings[prop], scope=self._scope)
912
- return InstanceProperty(self._graph, self, name, scope=self._scope)
913
-
914
- def set(self, *args, **kwargs):
915
- if self._graph._stack.active() is self._context:
916
- self._sets.update(kwargs)
917
- Instance(self._graph, ActionType.Bind, [self, *args], kwargs, var=self._var, scope=self._scope)
918
- return self
919
-
920
- def persist(self, *args, **kwargs):
921
- Instance(self._graph, ActionType.Persist, [self, *args], kwargs, var=self._var, scope=self._scope)
922
- return self
923
-
924
- def unpersist(self, *args, **kwargs):
925
- Instance(self._graph, ActionType.Unpersist, [self, *args], kwargs, var=self._var, scope=self._scope)
926
- return self
927
-
928
- def has_value(self):
929
- return self != rel.Missing # type:ignore
930
-
931
- #--------------------------------------------------
932
- # InstanceProperty
933
- #--------------------------------------------------
934
-
935
- class InstanceProperty(Producer):
936
- def __init__(self, graph:'Graph', instance:Instance, name:str, var=None, scope:str=""):
937
- super().__init__(graph)
938
- self._instance = instance
939
-
940
- self._prop = build.property_named(scope+name, instance._action.types)
941
- self._var = var or Var(self._prop.type, name=name)
942
- self._check_context()
943
- self._scope = scope
944
- new = Instance(self._graph, ActionType.Get, [instance], {name: self._var}, scope=self._scope)
945
- self._action = new._action
946
-
947
- def _check_context(self):
948
- if not self._graph._stack.contains(self._instance._context):
949
- name = f"{self._instance._var.name}.{self._var.name}"
950
- exception = VariableOutOfContextException(Errors.call_source(), name, is_property=True)
951
- raise exception from None
952
-
953
- def __call__(self, *args, **kwargs):
954
- name = f"{self._instance._var.name}.{self._var.name}"
955
- exception = NonCallablePropertyException(Errors.call_source(), name)
956
- raise exception from None
957
-
958
- def _make_sub(self, name: str, existing=None):
959
- if existing is not None and self._graph._stack.is_active(existing._instance._context):
960
- return existing
961
- return getattr(Instance(self._graph, ActionType.Get, [self], {}), name)
962
-
963
- def _to_var(self):
964
- self._check_context()
965
- return self._var
966
-
967
- def or_(self, other):
968
- self._graph._remove_action(self._action)
969
- default = build.call(Builtins.Default, [self._prop, other, self._instance, self])
970
- self._graph._action(default)
971
- return self
972
-
973
- def in_(self, others):
974
- other_rel = InlineRelation(self._graph, [(x,) for x in others])
975
- return self == other_rel
976
-
977
- def has_value(self):
978
- return self != rel.Missing # type:ignore
979
-
980
- def _remove_if_unused(self):
981
- # When calling append/extend we aren't necessarily doing a get on the property,
982
- # but we will already have added one. If we're the only thing using this get,
983
- # we remove it so that it doesn't unnecessarily constrain the query.
984
- remove = False
985
- for item in reversed(self._graph._stack.items):
986
- if item is self._action:
987
- remove = True
988
- break
989
- elif isinstance(item, Action):
990
- if self._var in item.vars():
991
- remove = False
992
- break
993
- if remove:
994
- self._graph._remove_action(self._action)
995
-
996
- def set(self, *args, **kwargs):
997
- return Instance(self._graph, ActionType.Get, [self], {}).set(*args, **kwargs)
998
-
999
- def add(self, other):
1000
- self._remove_if_unused()
1001
- self._graph._check_property(self._prop, multi_valued=True)
1002
- rel = Action(ActionType.Bind, to_var(self._instance), [], {self._prop: to_var(other)})
1003
- self._graph._action(rel)
1004
-
1005
- def extend(self, others):
1006
- self._remove_if_unused()
1007
- self._graph._check_property(self._prop, True)
1008
- for other in others:
1009
- rel = Action(ActionType.Bind, to_var(self._instance), [], {self._prop: to_var(other)})
1010
- self._graph._action(rel)
1011
-
1012
- def choose(self, num, unique=True):
1013
- if num < 1:
1014
- raise ValueError("Must choose a positive number of items")
1015
- self._remove_if_unused()
1016
- items = [getattr(Instance(self._graph, ActionType.Get, [self._instance], {}), self._prop.name) for ix in range(num)]
1017
- if unique:
1018
- for ix in range(num-1):
1019
- items[ix] < items[ix+1]
1020
- return items
1021
-
1022
- #--------------------------------------------------
1023
- # Expression
1024
- #--------------------------------------------------
1025
-
1026
- class Expression(Producer):
1027
- def __init__(self, graph:'Graph', op:mType|Task, args:List[Any]):
1028
-
1029
- super().__init__(graph)
1030
- self._var = None
1031
- self._context = graph._stack.active()
1032
-
1033
- # For calls to tasks with known signatures, normalize their arguments by
1034
- # throwing on missing inputs or constructing vars for missing outputs
1035
- if op.properties and not op.isa(Builtins.Anonymous):
1036
- for prop, arg in zip_longest(op.properties, args):
1037
- if arg is None:
1038
- if prop.is_input:
1039
- raise TypeError(f"{op.name} is missing a required argument: '{prop.name}'")
1040
- else:
1041
- args.append(Var(prop.type, name=prop.name))
1042
-
1043
- # Expose the last output as the result, to ensure we don't double-create it in _use_var.
1044
- # @NOTE: Literal values like 1 show up here from calls like `rel.range(0, len(df), 1)`
1045
- if not op.properties[-1].is_input and isinstance(args[-1], Var):
1046
- self._var = args[-1]
1047
-
1048
- self._expr = build.call(op, args)
1049
- self._graph._action(self._expr)
1050
-
1051
- def __call__(self, *args, **kwargs):
1052
- raise Exception("Expressions can't be called")
1053
-
1054
- def _use_var(self):
1055
- if self._expr.entity.isa(Builtins.Filter):
1056
- if isinstance(runtime_env, SnowbookEnvironment):
1057
- return
1058
- raise FilterAsValue(Errors.call_source())
1059
- elif not self._var:
1060
- self._var = Var(Builtins.Unknown)
1061
- prop = build.property_named("result", self._expr.types)
1062
- self._expr.append(prop, self._var)
1063
-
1064
- if not self._graph._stack.contains(self._context):
1065
- exception = VariableOutOfContextException(Errors.call_source(), self._var.name or "a result")
1066
- raise exception from None
1067
-
1068
- def _make_sub(self, name: str, existing=None):
1069
- if existing is not None and existing._instance._context is self._graph._stack.active():
1070
- return existing
1071
- return getattr(Instance(self._graph, ActionType.Get, [self], {}), name)
1072
-
1073
- def has_value(self):
1074
- return self != rel.Missing # type:ignore
1075
-
1076
- #--------------------------------------------------
1077
- # RelationNS
1078
- #--------------------------------------------------
1079
-
1080
- unsafe_symbol_pattern = re.compile(r"[^a-zA-Z0-9_]", re.UNICODE)
1081
- def safe_symbol(name: str):
1082
- return f':"{name}"' if unsafe_symbol_pattern.search(name) else f":{name}"
1083
-
1084
- class RelationNS():
1085
- def __init__(self, ns:List[str], name:str, use_rel_namespaces=False, tags:List[mType]=[]):
1086
- if name == "getdoc":
1087
- rich.print("[red bold]GETDOC CALLED")
1088
- traceback.print_stack()
1089
- return
1090
- self._name = name
1091
- self._ns = ns
1092
- self._subs = {}
1093
- self._use_rel_namespaces = use_rel_namespaces
1094
- self._rel = self._build_rel()
1095
- self._tags = tags
1096
-
1097
- def __call__(self, *args: Any, **kwds: Any) -> Any:
1098
- op = self._rel
1099
- for t in self._tags:
1100
- tag(self, t)
1101
- self._ensure_args(len(args))
1102
- return Expression(get_graph(), op, list(args))
1103
-
1104
- def __getattr__(self, name: str) -> RelationNS:
1105
- self._subs[name] = self._make_sub(name, self._subs.get(name))
1106
- return self._subs[name]
1107
-
1108
- def _make_sub(self, name: str, existing=None):
1109
- if existing is not None:
1110
- return existing
1111
- ns = self._ns[:]
1112
- if self._name:
1113
- ns.append(self._name)
1114
- return self.__class__(ns, name, use_rel_namespaces=self._use_rel_namespaces, tags=self._tags)
1115
-
1116
- def _build_rel(self, arg_count = 0):
1117
- fqn_parts = self._ns + [self._name]
1118
- if self._use_rel_namespaces:
1119
- return build.relation('::'+'::'.join(fqn_parts), arg_count)
1120
- if len(fqn_parts) == 1:
1121
- return build.relation(fqn_parts[0], arg_count)
1122
- else:
1123
- return build.relation(f"{fqn_parts[0]}[{', '.join(safe_symbol(part) for part in fqn_parts[1:])}]", arg_count)
1124
-
1125
- def _ensure_args(self, arg_count):
1126
- if len(self._rel.properties) <= arg_count:
1127
- self._rel.properties = [Builtins.Relation.properties[i] for i in range(arg_count)]
1128
-
1129
- def add(self, *args):
1130
- op = self._rel
1131
- self._ensure_args(len(args))
1132
- get_graph()._action(build.relation_action(ActionType.Bind, op, list(args)))
1133
-
1134
- def _to_var(self):
1135
- return Var(Builtins.Relation, value=self._build_rel())
1136
-
1137
- def _tagged(self, *tags: mType):
1138
- return self.__class__(self._ns, self._name, use_rel_namespaces=self._use_rel_namespaces, tags=list(tags))
1139
-
1140
- #--------------------------------------------------
1141
- # RawRelation
1142
- #--------------------------------------------------
1143
-
1144
- class RawRelation(Producer):
1145
- def __init__(self, graph:'Graph', name:str, arity:int):
1146
- super().__init__(graph)
1147
- self._name = name
1148
- self._arity = arity
1149
- self._type = build.relation(self._name, self._arity)
1150
-
1151
- def __call__(self, *args: Any, **kwds: Any) -> Any:
1152
- return Expression(self._graph, self._type, list(args))
1153
-
1154
- def add(self, *args):
1155
- self._graph._action(build.relation_action(ActionType.Bind, self._type, list(args)))
1156
-
1157
- def _make_sub(self, name: str, existing=None):
1158
- return existing
1159
-
1160
- def _to_var(self):
1161
- return Var(Builtins.Relation, value=self._type)
1162
-
1163
- #--------------------------------------------------
1164
- # InlineRelation
1165
- #--------------------------------------------------
1166
-
1167
- class InlineRelation():
1168
- def __init__(self, graph:'Graph', data:List[Tuple]):
1169
- self._var = Var(type=Builtins.InlineRawData)
1170
- self._graph = graph
1171
- cols = [[] for _ in range(len(data[0]))]
1172
- for row in data:
1173
- for i, val in enumerate(row):
1174
- cols[i].append(to_var(val))
1175
-
1176
- params = [Var(value=col) for col in cols]
1177
- params.append(self._var)
1178
- q = build.relation_action(ActionType.Get, Builtins.InlineRawData, params)
1179
- self._graph._action(q)
1180
-
1181
- def _to_var(self):
1182
- return self._var
1183
-
1184
- #--------------------------------------------------
1185
- # Rows
1186
- #--------------------------------------------------
1187
-
1188
- class Rows():
1189
- def __init__(self, graph:'Graph', data:List[Any]):
1190
- self._graph = graph
1191
-
1192
- col_names = []
1193
- data_cols = []
1194
-
1195
- size = len(data)
1196
- warning_size = 1000
1197
- error_size = 10000
1198
- if size > error_size:
1199
- raise errors.RowLiteralTooLarge(size, max_size=error_size)
1200
- elif size > warning_size:
1201
- errors.RowLiteralTooLargeWarning(size, max_size=warning_size)
1202
-
1203
- first = data[0]
1204
- if isinstance(first, dict):
1205
- col_names = list(first.keys())
1206
- data_cols = [[] for _ in range(len(col_names))]
1207
- for row in data:
1208
- for ix, col in enumerate(col_names):
1209
- if col not in row:
1210
- raise errors.RowLiteralMismatch("keys")
1211
- data_cols[ix].append(row[col])
1212
- elif isinstance(first, tuple):
1213
- data_cols = [[] for _ in range(len(first))]
1214
- for row in data:
1215
- if len(row) != len(first):
1216
- raise errors.RowLiteralMismatch("length")
1217
- for ix, col in enumerate(row):
1218
- data_cols[ix].append(col)
1219
- elif isinstance(first, list):
1220
- data_cols = [data]
1221
- else:
1222
- raise Exception("Unsupported data type: must be a list")
1223
-
1224
- data_vars = [Var(value=col) for col in data_cols]
1225
- if col_names:
1226
- vars = [Var(name=name) for name in col_names]
1227
- else:
1228
- vars = [Var() for _ in range(len(data_vars))]
1229
-
1230
- self._fetch = build.relation_action(ActionType.Get, Builtins.RawData, [*data_vars, *vars])
1231
- self._var = vars[-1]
1232
- self._vars = vars
1233
- self._columns = col_names
1234
-
1235
- def _add_to_graph(self):
1236
- if not self._graph._in_rule():
1237
- raise errors.OutOfContextException()
1238
- self._graph._action(self._fetch, dedupe=True)
1239
-
1240
- def _to_var(self):
1241
- self._add_to_graph()
1242
- return self._var
1243
-
1244
- def __getitem__(self, index):
1245
- self._add_to_graph()
1246
- if isinstance(index, str):
1247
- return getattr(self, index)
1248
- return self._vars[index]
1249
-
1250
- def __getattr__(self, name):
1251
- if name in self._columns:
1252
- self._add_to_graph()
1253
- return self._vars[self._columns.index(name)]
1254
- raise AttributeError(f"Set has no attribute '{name}'")
1255
-
1256
- #--------------------------------------------------
1257
- # Symbol
1258
- #--------------------------------------------------
1259
-
1260
- class Symbol():
1261
- def __init__(self, name:str):
1262
- self._var = Var(Builtins.Symbol, value=name)
1263
-
1264
- def _to_var(self):
1265
- return self._var
1266
-
1267
- #--------------------------------------------------
1268
- # RelationRef
1269
- #--------------------------------------------------
1270
-
1271
- class RelationRef(Producer):
1272
- def __init__(self, graph:'Graph', rel:Task|mType, args:List[Var]):
1273
- super().__init__(graph)
1274
- self._rel = rel
1275
- self._args = args
1276
- self._var = args[-1]
1277
- self._action = build.relation_action(ActionType.Get, self._rel, self._args)
1278
-
1279
- def _use_var(self):
1280
- self._graph._action(self._action)
1281
-
1282
- def _make_sub(self, name: str, existing=None):
1283
- return getattr(Instance(self._graph, ActionType.Get, [self], {}), name)
1284
-
1285
- def __enter__(self):
1286
- super().__enter__()
1287
- self._use_var()
1288
- Instance(self._graph, ActionType.Get, [self], {}).has_value()
1289
-
1290
- #--------------------------------------------------
1291
- # Export
1292
- #--------------------------------------------------
1293
-
1294
- allowed_export_types = [Type, str, numbers.Number, datetime.datetime, datetime.date, bool]
1295
-
1296
- def check_type(name, type):
1297
- if not any(isinstance(type, t) or (inspect.isclass(type) and issubclass(type, t))
1298
- for t in allowed_export_types):
1299
- raise TypeError(f"Argument '{name}' is an unsupported type: {type}")
1300
-
1301
- def export(model, schema, kwargs):
1302
- try:
1303
- parser = IdentityParser(schema)
1304
- except ParseError as e:
1305
- raise Exception(f"Not able to parse provided schema '{schema}'. {e}")
1306
-
1307
- def decorator(func):
1308
- # Get type hints of the function
1309
- hints = get_type_hints(func)
1310
- input_types = [hints[name] for name in hints if name != 'return']
1311
- arg_names = func.__code__.co_varnames[:func.__code__.co_argcount]
1312
- for name in arg_names:
1313
- if name not in hints:
1314
- raise TypeError(f"Argument '{name}' must have a type hint")
1315
- check_type(name, hints[name])
1316
-
1317
- output_types = []
1318
- has_return_hint = 'return' in hints
1319
- if has_return_hint:
1320
- ret = hints.get('return')
1321
- if typing.get_origin(ret) is tuple:
1322
- for t in typing.get_args(ret):
1323
- check_type("return", t)
1324
- output_types.append(t)
1325
- else:
1326
- check_type("return", ret)
1327
- output_types.append(ret)
1328
- name = f"{schema}.{func.__name__}" if schema else func.__name__
1329
- props = {
1330
- "name": name if parser.entity is None else parser.identity,
1331
- "outputs": output_types if has_return_hint else None,
1332
- }
1333
-
1334
- ctx = Context(model, exec_type=TaskExecType.Procedure, props=props, format="snowpark", **kwargs)
1335
- with ctx as ret:
1336
- inputs = to_list(Vars(len(arg_names)))
1337
- for i in inputs:
1338
- i._var.type = Builtins.ExternalInput
1339
- props["inputs"] = list(zip(arg_names, [to_var(i) for i in inputs], input_types))
1340
- outs = to_list(func(*inputs))
1341
- if has_return_hint and len(outs) != len(output_types):
1342
- raise TypeError(f"Function '{func.__name__}' must return {len(output_types)} values according to the type hints")
1343
- ret(*outs)
1344
-
1345
- def wrapper():
1346
- raise Exception("Exports can't be called directly. They are exported to the underlying platform")
1347
-
1348
- return wrapper
1349
- return decorator
1350
-
1351
- #--------------------------------------------------
1352
- # RuleStack
1353
- #--------------------------------------------------
1354
-
1355
- class RuleStack():
1356
- def __init__(self, graph:'Graph'):
1357
- self.items = []
1358
- self.stack = []
1359
- self._graph = graph
1360
-
1361
- def push(self, item):
1362
- self.stack.append(item)
1363
- self.items.append(("push", item))
1364
-
1365
- def pop(self, item, globalize=False):
1366
- self.stack.pop()
1367
- self.items.append(("pop", item))
1368
- if len(self.stack) == 0:
1369
- compacted = self.compact()
1370
- self.items.clear()
1371
- if len(compacted.items):
1372
- return compacted
1373
- elif globalize:
1374
- ix = self.items.index(("push", item))
1375
- temp_items = self.items[0:ix]
1376
- self.items = self.items[ix:]
1377
- compacted = self.compact()
1378
- self.items = temp_items
1379
- if len(compacted.items):
1380
- return compacted
1381
-
1382
- def push_item(self, item):
1383
- if not len(self.stack):
1384
- raise Exception("Can't push a non-context item onto an empty stack")
1385
- self.items.append(item)
1386
-
1387
- def contains(self, item):
1388
- for i in self.stack:
1389
- if i is item:
1390
- return True
1391
-
1392
- def is_active(self, item):
1393
- if isinstance(item, Context) and item._task.behavior != Behavior.Query:
1394
- return False
1395
- return item is self.active()
1396
-
1397
- def in_context(self, item):
1398
- if isinstance(item, Context) and item._task.behavior != Behavior.Query:
1399
- return False
1400
- return self.contains(item)
1401
-
1402
- def active(self):
1403
- try:
1404
- cur = self.stack[-1]
1405
- if cur is self._graph._temp_rule:
1406
- exception = OutOfContextException(Errors.call_source())
1407
- raise exception from None
1408
- return cur
1409
- except IndexError:
1410
- exception = OutOfContextException(Errors.call_source())
1411
- raise exception from None
1412
-
1413
- def _expression_start(self, buffer, single_use_vars):
1414
- consume_from = -1
1415
- if not len(buffer):
1416
- return consume_from
1417
- # we can only pull vars if their only use is for this condition
1418
- used_vars = set(buffer[-1].requires_provides()[0] & single_use_vars)
1419
- # walk buffer in reverse collecting vars in the action until we get one
1420
- # that doesn't provide a var we care about
1421
- for action in reversed(buffer[:-1]):
1422
- if not isinstance(action, Action):
1423
- break
1424
- req, provs, _ = action.requires_provides()
1425
- # don't pull in vars the represent root entities even though they're provided
1426
- # by gets. This prevents scenarios where p = Person() would get pulled in if you
1427
- # did with p.age > 10:
1428
- provs = provs - {action.entity}
1429
- if len(used_vars.intersection(provs)):
1430
- used_vars.update(req & single_use_vars)
1431
- consume_from -= 1
1432
- else:
1433
- break
1434
- return consume_from
1435
-
1436
- def compact(self) -> Task:
1437
- stack:List[Task] = []
1438
- buffer = []
1439
-
1440
- var_uses = {}
1441
- for item in self.items:
1442
- if isinstance(item, Action):
1443
- if item.action == ActionType.Get:
1444
- for var in item.vars():
1445
- var_uses[var] = var_uses.get(var, 0) + 1
1446
- else:
1447
- for var in item.vars():
1448
- var_uses[var] = var_uses.get(var, 0) - 1
1449
-
1450
- # check for 2 refs - one create and one use
1451
- single_use_vars = set([var for var, uses in var_uses.items() if uses >= 0])
1452
-
1453
- for item in self.items:
1454
- if not isinstance(item, tuple):
1455
- buffer.append(item)
1456
- continue
1457
-
1458
- op, value = item
1459
- if op == "push":
1460
- if isinstance(value, Context):
1461
- if len(buffer):
1462
- stack[-1].items.extend(buffer)
1463
- buffer.clear()
1464
- task = value._task
1465
- elif isinstance(value, RelationRef):
1466
- if len(buffer):
1467
- stack[-1].items.extend(buffer)
1468
- buffer.clear()
1469
- task = Task()
1470
-
1471
- elif isinstance(value, Producer):
1472
- consume_from = self._expression_start(buffer, single_use_vars)
1473
- stack[-1].items.extend(buffer[:consume_from])
1474
- buffer = buffer[consume_from:]
1475
- task = Task()
1476
- else:
1477
- raise Exception(f"Unknown push type: {type(value)}")
1478
-
1479
- stack.append(task)
1480
-
1481
- elif op == "pop":
1482
- cur = stack.pop()
1483
- cur.items.extend(buffer)
1484
- buffer.clear()
1485
- if not len(stack):
1486
- return cur
1487
- if isinstance(value, Context) and value._op:
1488
- stack[-1].items.append(build.call(value._op, [Var(value=value._args), Var(Builtins.Task, value=cur)]))
1489
- else:
1490
- stack[-1].items.append(build.call(cur, list(cur.bindings.values())))
1491
-
1492
- raise Exception("No task found")
1493
-
1494
- #--------------------------------------------------
1495
- # Graph
1496
- #--------------------------------------------------
1497
-
1498
- locals = threading.local()
1499
- locals.graph_stack = []
1500
-
1501
- def get_graph() -> 'Graph':
1502
- _ensure_stack()
1503
- if not len(locals.graph_stack):
1504
- raise Exception("Outside of a model context")
1505
- return locals.graph_stack[-1]
1506
-
1507
- def _ensure_stack():
1508
- if not hasattr(locals, "graph_stack"):
1509
- locals.graph_stack = []
1510
- return locals.graph_stack
1511
-
1512
- rel = RelationNS([], "")
1513
- global_ns = RelationNS([], "", use_rel_namespaces=True)
1514
-
1515
- def alias(ref:Any, name:str):
1516
- var = to_var(ref)
1517
- var.name = name
1518
- return var
1519
-
1520
- def tag(ref:Any, tag:mType):
1521
- if isinstance(ref, RelationNS):
1522
- parents = ref._rel.parents
1523
- elif isinstance(ref, Type):
1524
- parents = ref._type.parents
1525
- elif isinstance(ref, Property):
1526
- parents = ref._type.parents
1527
- else:
1528
- return
1529
- if tag not in parents:
1530
- parents.append(tag)
1531
-
1532
- def create_var() -> Instance:
1533
- return Instance(get_graph(), ActionType.Get, [], {}, Var(Builtins.Unknown))
1534
-
1535
- def create_vars(count: int) -> List[Instance]:
1536
- return [create_var() for _ in range(count)]
1537
-
1538
- def Vars(count: int):
1539
- if count == 1:
1540
- return create_var()
1541
- return create_vars(count)
1542
-
1543
- class Graph:
1544
- def __init__(self, client:Client, name:str, format:str="default"):
1545
- self.name = name
1546
- self._executed = []
1547
- self._client = client
1548
- self._config = client.resources.config
1549
- self.resources = client.resources
1550
- self._prop_is_multi:Dict[str, bool] = {}
1551
- self._format = format
1552
- self._stack = RuleStack(self)
1553
- self._restore_temp()
1554
-
1555
- self._Error = Type(self, "Error", scope="pyrel_error_")
1556
- self._error_props = set()
1557
-
1558
-
1559
- #--------------------------------------------------
1560
- # Rule stack
1561
- #--------------------------------------------------
1562
-
1563
- def _flush_temp(self):
1564
- if self._temp_rule:
1565
- self._pop(self._temp_rule, is_temp=True)
1566
- if not len(_ensure_stack()):
1567
- _ensure_stack().append(self)
1568
- self._temp_rule = None
1569
-
1570
- def _restore_temp(self):
1571
- self._temp_rule = Context(self)
1572
- _ensure_stack().append(self)
1573
- self._stack.push(self._temp_rule)
1574
-
1575
- def _temp_is_active(self):
1576
- return self._temp_rule and len(self._stack.items) > 1
1577
-
1578
- def _in_rule(self):
1579
- return not self._temp_rule
1580
-
1581
- def _push(self, item):
1582
- _ensure_stack().append(self)
1583
- self._flush_temp()
1584
- self._stack.push(item)
1585
-
1586
- def _pop(self, item, exec=True, is_temp=False, globalize=False):
1587
- _ensure_stack().pop()
1588
- task = self._stack.pop(item, globalize=globalize)
1589
- try:
1590
- if exec and task:
1591
- self._exec(item, task)
1592
- finally:
1593
- if not is_temp and not len(self._stack.stack):
1594
- self._restore_temp()
1595
-
1596
- def _action(self, action:Action|List[Action], dedupe=False):
1597
- if isinstance(action, list):
1598
- for a in action:
1599
- self._action(a, dedupe=dedupe)
1600
- return
1601
- if dedupe and self._stack.contains(action):
1602
- return
1603
- self._stack.push_item(action)
1604
-
1605
- def _remove_action(self, action):
1606
- self._stack.items.remove(action)
1607
-
1608
- def _exec(self, context:Context, task):
1609
- props = context._props
1610
- if context._exec_type == TaskExecType.Rule:
1611
- self._client.install(f"rule{len(self._executed)}", context._task)
1612
- elif context._exec_type == TaskExecType.Query:
1613
- headers = {QUERY_ATTRIBUTES_HEADER: json.dumps(context._attributes)} if context._attributes else {}
1614
- context.results = self._client.query(context._task, tag=context._tag, format=context._format, headers=headers, read_only=context._read_only, skip_invalid_data=context._skip_invalid_data)
1615
- elif context._exec_type == TaskExecType.Procedure:
1616
- self._client.export_udf(props["name"], props["inputs"], props["outputs"], context._task, props.get("engine"), skip_invalid_data=context._skip_invalid_data)
1617
- elif context._exec_type == TaskExecType.Export:
1618
- self._client.export_table(props["name"], props["rel"], props["columns"], context._task, engine=props.get("engine"), refresh=props.get("refresh"))
1619
- self._executed.append(context)
1620
-
1621
- #--------------------------------------------------
1622
- # Property handling
1623
- #--------------------------------------------------
1624
-
1625
- def _check_property(self, prop:mProperty, multi_valued=False, unknown_cardinality=False):
1626
- name = prop.name
1627
- if name in RESERVED_PROPS:
1628
- exception = ReservedPropertyException(Errors.call_source(), name)
1629
- raise exception from None
1630
-
1631
- if unknown_cardinality:
1632
- if name in self._prop_is_multi and self._prop_is_multi[name] and Builtins.MultiValued not in prop.parents:
1633
- prop.parents.append(Builtins.MultiValued)
1634
- return
1635
-
1636
- if name in self._prop_is_multi:
1637
- if self._prop_is_multi[name] != multi_valued:
1638
- raise Exception(
1639
- f"Trying to use a property `{name}` as both singular and multi-valued. "
1640
- "This often happens when multiple types have a property with the same name, but one is single-valued and the other is multi-valued. "
1641
- "Consider using a plural name for the multi-valued property. "
1642
- "See https://relational.ai/docs/develop/core-concepts#setting-object-properties for more information."
1643
- )
1644
- elif self._prop_is_multi[name] and Builtins.MultiValued not in prop.parents:
1645
- prop.parents.append(Builtins.MultiValued)
1646
- else:
1647
- self._prop_is_multi[name] = multi_valued
1648
-
1649
- if not multi_valued and Builtins.FunctionAnnotation not in prop.parents:
1650
- prop.parents.append(Builtins.FunctionAnnotation)
1651
- elif multi_valued and Builtins.MultiValued not in prop.parents:
1652
- prop.parents.append(Builtins.MultiValued)
1653
-
1654
- #--------------------------------------------------
1655
- # Public API
1656
- #--------------------------------------------------
1657
-
1658
- def Type(self, name:str, source=None):
1659
- if source:
1660
- return self.resources.to_model_type(self, name, source)
1661
- return Type(self, name)
1662
-
1663
- def _error_like(self, message:str, kwargs:Dict[str, Any], is_error:bool):
1664
- kwargs["message"] = message
1665
- kwargs["severity"] = "error" if is_error else "warning"
1666
- source = Errors.call_source()
1667
- id = 0
1668
- if source:
1669
- id = len(errors.ModelError.error_locations)
1670
- errors.ModelError.error_locations[id] = source
1671
- kwargs["pyrel_id"] = id
1672
- for k, v in kwargs.items():
1673
- if k not in self._error_props:
1674
- self._error_props.add(k)
1675
- with self.rule():
1676
- e = self._Error()
1677
- rel.output.pyrel_error.add(e, k, getattr(e, k))
1678
- if is_error:
1679
- with self.case():
1680
- self._Error(pyrel_id=id)
1681
- rel.abort.add()
1682
- return self._Error.add(**kwargs)
1683
-
1684
- def error(self, message:str, **kwargs):
1685
- return self._error_like(message, kwargs, is_error=True)
1686
-
1687
- def warn(self, message:str, **kwargs):
1688
- return self._error_like(message, kwargs, is_error=False)
1689
-
1690
- def rule(self, **kwargs):
1691
- return Context(self, **kwargs)
1692
-
1693
- def scope(self, **kwargs):
1694
- return Context(self, **kwargs)
1695
-
1696
- def case(self, **kwargs):
1697
- return Context(self, **kwargs)
1698
-
1699
- def match(self, multiple=False, **kwargs):
1700
- if not multiple:
1701
- return Context(self, behavior=Behavior.OrderedChoice, **kwargs)
1702
- else:
1703
- return Context(self, behavior=Behavior.Union, **kwargs)
1704
-
1705
- def query(self, **kwargs):
1706
- return Context(self, exec_type=TaskExecType.Query, **kwargs)
1707
-
1708
- def export(self, object:str = "", **kwargs):
1709
- return export(self, object, kwargs)
1710
-
1711
- def found(self, **kwargs):
1712
- return Context(self, op=Builtins.Exists, **kwargs)
1713
-
1714
- def not_found(self, **kwargs):
1715
- return Context(self, op=Builtins.Not, **kwargs)
1716
-
1717
- def union(self, **kwargs):
1718
- return Context(self, behavior=Behavior.Union, **kwargs)
1719
-
1720
- def ordered_choice(self, **kwargs):
1721
- return Context(self, behavior=Behavior.OrderedChoice, **kwargs)
1722
-
1723
- def read(self, name:str, **kwargs):
1724
- from relationalai.loaders.loader import read_resource_context # We do the late import to break an dependency cycle
1725
- return read_resource_context(self, name, **kwargs)
1726
-
1727
- def load_raw(self, path:str):
1728
- if os.path.isfile(path):
1729
- if path.endswith('.rel'):
1730
- self._client.load_raw_file(path)
1731
- elif os.path.isdir(path):
1732
- for root, _, files in os.walk(path):
1733
- for file in files:
1734
- if file.endswith('.rel'):
1735
- file_path = os.path.join(root, file)
1736
- self._client.load_raw_file(file_path)
1737
-
1738
- def exec_raw(self, code:str, readonly=False, raw_results=True, abort_on_error=True, inputs={}, query_timeout_mins: Optional[int]=None):
1739
- try:
1740
- return self._client.exec_raw(code, readonly=readonly, raw_results=raw_results, inputs=inputs, abort_on_error=abort_on_error, query_timeout_mins=query_timeout_mins)
1741
- except KeyboardInterrupt as e:
1742
- print("Canceling transactions...")
1743
- self.resources.cancel_pending_transactions()
1744
- raise e
1745
- except RAIException as e:
1746
- raise e.clone(self._config) from None
1747
-
1748
- def install_raw(self, code:str, name:str|None = None, overwrite=False):
1749
- self._client.install_raw(code, name, overwrite)