relationalai 0.13.0__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 (836) hide show
  1. relationalai/__init__.py +1 -256
  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 -771
  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/__init__.py +5 -0
  72. v0/relationalai/clients/azure.py +477 -0
  73. v0/relationalai/clients/client.py +912 -0
  74. v0/relationalai/clients/config.py +673 -0
  75. v0/relationalai/clients/direct_access_client.py +118 -0
  76. v0/relationalai/clients/hash_util.py +31 -0
  77. v0/relationalai/clients/local.py +571 -0
  78. v0/relationalai/clients/profile_polling.py +73 -0
  79. v0/relationalai/clients/result_helpers.py +420 -0
  80. v0/relationalai/clients/snowflake.py +3869 -0
  81. v0/relationalai/clients/types.py +113 -0
  82. v0/relationalai/clients/use_index_poller.py +980 -0
  83. v0/relationalai/clients/util.py +356 -0
  84. v0/relationalai/debugging.py +389 -0
  85. v0/relationalai/dsl.py +1749 -0
  86. v0/relationalai/early_access/builder/__init__.py +30 -0
  87. v0/relationalai/early_access/builder/builder/__init__.py +35 -0
  88. v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
  89. v0/relationalai/early_access/builder/std/__init__.py +25 -0
  90. v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  91. v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
  92. v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
  93. v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
  94. v0/relationalai/early_access/devtools/__init__.py +12 -0
  95. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  96. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  97. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  98. v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  99. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  100. v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  101. v0/relationalai/early_access/dsl/bindings/common.py +402 -0
  102. v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
  103. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  104. v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  105. v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
  106. v0/relationalai/early_access/dsl/codegen/common.py +79 -0
  107. v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
  108. v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
  109. v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
  110. v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  111. v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
  112. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  113. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  114. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  115. v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  116. v0/relationalai/early_access/dsl/core/context.py +13 -0
  117. v0/relationalai/early_access/dsl/core/cset.py +132 -0
  118. v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  119. v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  120. v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  121. v0/relationalai/early_access/dsl/core/instances.py +44 -0
  122. v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  123. v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  124. v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
  125. v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
  126. v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
  127. v0/relationalai/early_access/dsl/core/relations.py +276 -0
  128. v0/relationalai/early_access/dsl/core/rules.py +112 -0
  129. v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
  130. v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  131. v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
  132. v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
  133. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  134. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  135. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  136. v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
  137. v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  138. v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
  139. v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
  140. v0/relationalai/early_access/dsl/ir/executor.py +260 -0
  141. v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  142. v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
  143. v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
  144. v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  145. v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
  146. v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  147. v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
  148. v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  149. v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
  150. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  151. v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  152. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  153. v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  154. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  155. v0/relationalai/early_access/dsl/orm/models.py +256 -0
  156. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  157. v0/relationalai/early_access/dsl/orm/printer.py +469 -0
  158. v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
  159. v0/relationalai/early_access/dsl/orm/relations.py +19 -0
  160. v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
  161. v0/relationalai/early_access/dsl/orm/types.py +42 -0
  162. v0/relationalai/early_access/dsl/orm/utils.py +79 -0
  163. v0/relationalai/early_access/dsl/orm/verb.py +204 -0
  164. v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  165. v0/relationalai/early_access/dsl/relations.py +170 -0
  166. v0/relationalai/early_access/dsl/rulesets.py +69 -0
  167. v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
  168. v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
  169. v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  170. v0/relationalai/early_access/dsl/schemas/components.py +203 -0
  171. v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
  172. v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
  173. v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
  174. v0/relationalai/early_access/dsl/serialization.py +79 -0
  175. v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
  176. v0/relationalai/early_access/dsl/snow/api.py +104 -0
  177. v0/relationalai/early_access/dsl/snow/common.py +76 -0
  178. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  179. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  180. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  181. v0/relationalai/early_access/dsl/types/__init__.py +40 -0
  182. v0/relationalai/early_access/dsl/types/concepts.py +12 -0
  183. v0/relationalai/early_access/dsl/types/entities.py +135 -0
  184. v0/relationalai/early_access/dsl/types/values.py +17 -0
  185. v0/relationalai/early_access/dsl/utils.py +102 -0
  186. v0/relationalai/early_access/graphs/__init__.py +13 -0
  187. v0/relationalai/early_access/lqp/__init__.py +12 -0
  188. v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
  189. v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
  190. v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
  191. v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
  192. v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
  193. v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  194. v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
  195. v0/relationalai/early_access/lqp/types/__init__.py +12 -0
  196. v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
  197. v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
  198. v0/relationalai/early_access/metamodel/__init__.py +58 -0
  199. v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  200. v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  201. v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  202. v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
  203. v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  204. v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
  205. v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  206. v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
  207. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  208. v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
  209. v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
  210. v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  211. v0/relationalai/early_access/rel/__init__.py +12 -0
  212. v0/relationalai/early_access/rel/executor/__init__.py +12 -0
  213. v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  214. v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
  215. v0/relationalai/early_access/solvers/__init__.py +19 -0
  216. v0/relationalai/early_access/sql/__init__.py +11 -0
  217. v0/relationalai/early_access/sql/executor/__init__.py +3 -0
  218. v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
  219. v0/relationalai/early_access/tests/logging/__init__.py +12 -0
  220. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  221. v0/relationalai/early_access/tests/utils/__init__.py +12 -0
  222. v0/relationalai/environments/__init__.py +35 -0
  223. v0/relationalai/environments/base.py +381 -0
  224. v0/relationalai/environments/colab.py +14 -0
  225. v0/relationalai/environments/generic.py +71 -0
  226. v0/relationalai/environments/ipython.py +68 -0
  227. v0/relationalai/environments/jupyter.py +9 -0
  228. v0/relationalai/environments/snowbook.py +169 -0
  229. v0/relationalai/errors.py +2455 -0
  230. v0/relationalai/experimental/SF.py +38 -0
  231. v0/relationalai/experimental/inspect.py +47 -0
  232. v0/relationalai/experimental/pathfinder/__init__.py +158 -0
  233. v0/relationalai/experimental/pathfinder/api.py +160 -0
  234. v0/relationalai/experimental/pathfinder/automaton.py +584 -0
  235. v0/relationalai/experimental/pathfinder/bridge.py +226 -0
  236. v0/relationalai/experimental/pathfinder/compiler.py +416 -0
  237. v0/relationalai/experimental/pathfinder/datalog.py +214 -0
  238. v0/relationalai/experimental/pathfinder/diagnostics.py +56 -0
  239. v0/relationalai/experimental/pathfinder/filter.py +236 -0
  240. v0/relationalai/experimental/pathfinder/glushkov.py +439 -0
  241. v0/relationalai/experimental/pathfinder/options.py +265 -0
  242. v0/relationalai/experimental/pathfinder/rpq.py +344 -0
  243. v0/relationalai/experimental/pathfinder/transition.py +200 -0
  244. v0/relationalai/experimental/pathfinder/utils.py +26 -0
  245. v0/relationalai/experimental/paths/api.py +143 -0
  246. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  247. v0/relationalai/experimental/paths/examples/basic_example.py +40 -0
  248. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  249. v0/relationalai/experimental/paths/examples/movie_example.py +77 -0
  250. v0/relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  251. v0/relationalai/experimental/paths/examples/paths_example.py +116 -0
  252. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  253. v0/relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  254. v0/relationalai/experimental/paths/graph.py +185 -0
  255. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  256. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  257. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  258. v0/relationalai/experimental/paths/path_algorithms/single.py +59 -0
  259. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  260. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  261. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  262. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  263. v0/relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  264. v0/relationalai/experimental/paths/product_graph.py +93 -0
  265. v0/relationalai/experimental/paths/rpq/automaton.py +584 -0
  266. v0/relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  267. v0/relationalai/experimental/paths/rpq/rpq.py +378 -0
  268. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  269. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  270. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  271. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  272. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  273. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  274. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  275. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  276. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  277. v0/relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  278. v0/relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  279. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  280. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  281. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  282. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  283. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  284. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  285. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  286. v0/relationalai/experimental/paths/tree_agg.py +168 -0
  287. v0/relationalai/experimental/paths/utilities/iterators.py +27 -0
  288. v0/relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  289. v0/relationalai/experimental/solvers.py +1087 -0
  290. v0/relationalai/loaders/__init__.py +0 -0
  291. v0/relationalai/loaders/csv.py +195 -0
  292. v0/relationalai/loaders/loader.py +177 -0
  293. v0/relationalai/loaders/types.py +23 -0
  294. v0/relationalai/rel_emitter.py +373 -0
  295. v0/relationalai/rel_utils.py +185 -0
  296. v0/relationalai/semantics/__init__.py +29 -0
  297. v0/relationalai/semantics/devtools/benchmark_lqp.py +536 -0
  298. v0/relationalai/semantics/devtools/compilation_manager.py +294 -0
  299. v0/relationalai/semantics/devtools/extract_lqp.py +110 -0
  300. v0/relationalai/semantics/internal/internal.py +3785 -0
  301. v0/relationalai/semantics/internal/snowflake.py +324 -0
  302. v0/relationalai/semantics/lqp/builtins.py +16 -0
  303. v0/relationalai/semantics/lqp/compiler.py +22 -0
  304. v0/relationalai/semantics/lqp/constructors.py +68 -0
  305. v0/relationalai/semantics/lqp/executor.py +469 -0
  306. v0/relationalai/semantics/lqp/intrinsics.py +24 -0
  307. v0/relationalai/semantics/lqp/model2lqp.py +839 -0
  308. v0/relationalai/semantics/lqp/passes.py +680 -0
  309. v0/relationalai/semantics/lqp/primitives.py +252 -0
  310. v0/relationalai/semantics/lqp/result_helpers.py +202 -0
  311. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  312. v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  313. v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  314. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +449 -0
  315. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  316. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  317. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  318. v0/relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  319. v0/relationalai/semantics/lqp/types.py +101 -0
  320. v0/relationalai/semantics/lqp/utils.py +160 -0
  321. v0/relationalai/semantics/lqp/validators.py +57 -0
  322. v0/relationalai/semantics/metamodel/__init__.py +40 -0
  323. v0/relationalai/semantics/metamodel/builtins.py +774 -0
  324. v0/relationalai/semantics/metamodel/compiler.py +133 -0
  325. v0/relationalai/semantics/metamodel/dependency.py +862 -0
  326. v0/relationalai/semantics/metamodel/executor.py +61 -0
  327. v0/relationalai/semantics/metamodel/factory.py +287 -0
  328. v0/relationalai/semantics/metamodel/helpers.py +361 -0
  329. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  330. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  331. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  332. v0/relationalai/semantics/metamodel/rewrite/flatten.py +549 -0
  333. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  334. v0/relationalai/semantics/metamodel/typer/checker.py +353 -0
  335. v0/relationalai/semantics/metamodel/typer/typer.py +1395 -0
  336. v0/relationalai/semantics/metamodel/util.py +505 -0
  337. v0/relationalai/semantics/reasoners/__init__.py +10 -0
  338. v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
  339. v0/relationalai/semantics/reasoners/graph/core.py +9020 -0
  340. v0/relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  341. v0/relationalai/semantics/reasoners/optimization/common.py +88 -0
  342. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  343. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +1163 -0
  344. v0/relationalai/semantics/rel/builtins.py +40 -0
  345. v0/relationalai/semantics/rel/compiler.py +989 -0
  346. v0/relationalai/semantics/rel/executor.py +359 -0
  347. v0/relationalai/semantics/rel/rel.py +482 -0
  348. v0/relationalai/semantics/rel/rel_utils.py +276 -0
  349. v0/relationalai/semantics/snowflake/__init__.py +3 -0
  350. v0/relationalai/semantics/sql/compiler.py +2503 -0
  351. v0/relationalai/semantics/sql/executor/duck_db.py +52 -0
  352. v0/relationalai/semantics/sql/executor/result_helpers.py +64 -0
  353. v0/relationalai/semantics/sql/executor/snowflake.py +145 -0
  354. v0/relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  355. v0/relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  356. v0/relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  357. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  358. v0/relationalai/semantics/sql/sql.py +504 -0
  359. v0/relationalai/semantics/std/__init__.py +54 -0
  360. v0/relationalai/semantics/std/constraints.py +43 -0
  361. v0/relationalai/semantics/std/datetime.py +363 -0
  362. v0/relationalai/semantics/std/decimals.py +62 -0
  363. v0/relationalai/semantics/std/floats.py +7 -0
  364. v0/relationalai/semantics/std/integers.py +22 -0
  365. v0/relationalai/semantics/std/math.py +141 -0
  366. v0/relationalai/semantics/std/pragmas.py +11 -0
  367. v0/relationalai/semantics/std/re.py +83 -0
  368. v0/relationalai/semantics/std/std.py +14 -0
  369. v0/relationalai/semantics/std/strings.py +63 -0
  370. v0/relationalai/semantics/tests/__init__.py +0 -0
  371. v0/relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  372. v0/relationalai/semantics/tests/test_snapshot_base.py +9 -0
  373. v0/relationalai/semantics/tests/utils.py +46 -0
  374. v0/relationalai/std/__init__.py +70 -0
  375. v0/relationalai/tools/__init__.py +0 -0
  376. v0/relationalai/tools/cli.py +1940 -0
  377. v0/relationalai/tools/cli_controls.py +1826 -0
  378. v0/relationalai/tools/cli_helpers.py +390 -0
  379. v0/relationalai/tools/debugger.py +183 -0
  380. v0/relationalai/tools/debugger_client.py +109 -0
  381. v0/relationalai/tools/debugger_server.py +302 -0
  382. v0/relationalai/tools/dev.py +685 -0
  383. v0/relationalai/tools/qb_debugger.py +425 -0
  384. v0/relationalai/util/clean_up_databases.py +95 -0
  385. v0/relationalai/util/format.py +123 -0
  386. v0/relationalai/util/list_databases.py +9 -0
  387. v0/relationalai/util/otel_configuration.py +25 -0
  388. v0/relationalai/util/otel_handler.py +484 -0
  389. v0/relationalai/util/snowflake_handler.py +88 -0
  390. v0/relationalai/util/span_format_test.py +43 -0
  391. v0/relationalai/util/span_tracker.py +207 -0
  392. v0/relationalai/util/spans_file_handler.py +72 -0
  393. v0/relationalai/util/tracing_handler.py +34 -0
  394. frontend/debugger/dist/.gitignore +0 -2
  395. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  396. frontend/debugger/dist/assets/index-Cssla-O7.js +0 -208
  397. frontend/debugger/dist/assets/index-DlHsYx1V.css +0 -9
  398. frontend/debugger/dist/index.html +0 -17
  399. relationalai/clients/__init__.py +0 -18
  400. relationalai/clients/client.py +0 -912
  401. relationalai/clients/config.py +0 -673
  402. relationalai/clients/direct_access_client.py +0 -118
  403. relationalai/clients/hash_util.py +0 -31
  404. relationalai/clients/local.py +0 -571
  405. relationalai/clients/profile_polling.py +0 -73
  406. relationalai/clients/resources/__init__.py +0 -8
  407. relationalai/clients/resources/azure/azure.py +0 -477
  408. relationalai/clients/resources/snowflake/__init__.py +0 -20
  409. relationalai/clients/resources/snowflake/cli_resources.py +0 -87
  410. relationalai/clients/resources/snowflake/direct_access_resources.py +0 -711
  411. relationalai/clients/resources/snowflake/engine_state_handlers.py +0 -309
  412. relationalai/clients/resources/snowflake/error_handlers.py +0 -199
  413. relationalai/clients/resources/snowflake/export_procedure.py.jinja +0 -249
  414. relationalai/clients/resources/snowflake/resources_factory.py +0 -99
  415. relationalai/clients/resources/snowflake/snowflake.py +0 -3083
  416. relationalai/clients/resources/snowflake/use_index_poller.py +0 -1011
  417. relationalai/clients/resources/snowflake/use_index_resources.py +0 -188
  418. relationalai/clients/resources/snowflake/util.py +0 -387
  419. relationalai/clients/result_helpers.py +0 -420
  420. relationalai/clients/types.py +0 -113
  421. relationalai/clients/util.py +0 -356
  422. relationalai/debugging.py +0 -389
  423. relationalai/dsl.py +0 -1749
  424. relationalai/early_access/builder/__init__.py +0 -30
  425. relationalai/early_access/builder/builder/__init__.py +0 -35
  426. relationalai/early_access/builder/snowflake/__init__.py +0 -12
  427. relationalai/early_access/builder/std/__init__.py +0 -25
  428. relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  429. relationalai/early_access/builder/std/integers/__init__.py +0 -12
  430. relationalai/early_access/builder/std/math/__init__.py +0 -12
  431. relationalai/early_access/builder/std/strings/__init__.py +0 -14
  432. relationalai/early_access/devtools/__init__.py +0 -12
  433. relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  434. relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  435. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  436. relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  437. relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  438. relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  439. relationalai/early_access/dsl/bindings/common.py +0 -402
  440. relationalai/early_access/dsl/bindings/csv.py +0 -170
  441. relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  442. relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  443. relationalai/early_access/dsl/codegen/binder.py +0 -411
  444. relationalai/early_access/dsl/codegen/common.py +0 -79
  445. relationalai/early_access/dsl/codegen/helpers.py +0 -23
  446. relationalai/early_access/dsl/codegen/relations.py +0 -700
  447. relationalai/early_access/dsl/codegen/weaver.py +0 -417
  448. relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  449. relationalai/early_access/dsl/core/builders/logic.py +0 -19
  450. relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  451. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  452. relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  453. relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  454. relationalai/early_access/dsl/core/context.py +0 -13
  455. relationalai/early_access/dsl/core/cset.py +0 -132
  456. relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  457. relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  458. relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  459. relationalai/early_access/dsl/core/instances.py +0 -44
  460. relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  461. relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  462. relationalai/early_access/dsl/core/logic/exists.py +0 -223
  463. relationalai/early_access/dsl/core/logic/helper.py +0 -163
  464. relationalai/early_access/dsl/core/namespaces.py +0 -32
  465. relationalai/early_access/dsl/core/relations.py +0 -276
  466. relationalai/early_access/dsl/core/rules.py +0 -112
  467. relationalai/early_access/dsl/core/std/__init__.py +0 -45
  468. relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  469. relationalai/early_access/dsl/core/types/__init__.py +0 -270
  470. relationalai/early_access/dsl/core/types/concepts.py +0 -128
  471. relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  472. relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  473. relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  474. relationalai/early_access/dsl/core/types/standard.py +0 -92
  475. relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  476. relationalai/early_access/dsl/core/types/variables.py +0 -203
  477. relationalai/early_access/dsl/ir/compiler.py +0 -318
  478. relationalai/early_access/dsl/ir/executor.py +0 -260
  479. relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  480. relationalai/early_access/dsl/ontologies/export.py +0 -30
  481. relationalai/early_access/dsl/ontologies/models.py +0 -453
  482. relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  483. relationalai/early_access/dsl/ontologies/readings.py +0 -60
  484. relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  485. relationalai/early_access/dsl/ontologies/roles.py +0 -87
  486. relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  487. relationalai/early_access/dsl/orm/constraints.py +0 -438
  488. relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  489. relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  490. relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  491. relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  492. relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  493. relationalai/early_access/dsl/orm/models.py +0 -256
  494. relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  495. relationalai/early_access/dsl/orm/printer.py +0 -469
  496. relationalai/early_access/dsl/orm/reasoners.py +0 -480
  497. relationalai/early_access/dsl/orm/relations.py +0 -19
  498. relationalai/early_access/dsl/orm/relationships.py +0 -251
  499. relationalai/early_access/dsl/orm/types.py +0 -42
  500. relationalai/early_access/dsl/orm/utils.py +0 -79
  501. relationalai/early_access/dsl/orm/verb.py +0 -204
  502. relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  503. relationalai/early_access/dsl/relations.py +0 -170
  504. relationalai/early_access/dsl/rulesets.py +0 -69
  505. relationalai/early_access/dsl/schemas/__init__.py +0 -450
  506. relationalai/early_access/dsl/schemas/builder.py +0 -48
  507. relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  508. relationalai/early_access/dsl/schemas/components.py +0 -203
  509. relationalai/early_access/dsl/schemas/contexts.py +0 -156
  510. relationalai/early_access/dsl/schemas/exprs.py +0 -89
  511. relationalai/early_access/dsl/schemas/fragments.py +0 -464
  512. relationalai/early_access/dsl/serialization.py +0 -79
  513. relationalai/early_access/dsl/serialize/exporter.py +0 -163
  514. relationalai/early_access/dsl/snow/api.py +0 -105
  515. relationalai/early_access/dsl/snow/common.py +0 -76
  516. relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  517. relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  518. relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  519. relationalai/early_access/dsl/types/__init__.py +0 -40
  520. relationalai/early_access/dsl/types/concepts.py +0 -12
  521. relationalai/early_access/dsl/types/entities.py +0 -135
  522. relationalai/early_access/dsl/types/values.py +0 -17
  523. relationalai/early_access/dsl/utils.py +0 -102
  524. relationalai/early_access/graphs/__init__.py +0 -13
  525. relationalai/early_access/lqp/__init__.py +0 -12
  526. relationalai/early_access/lqp/compiler/__init__.py +0 -12
  527. relationalai/early_access/lqp/constructors/__init__.py +0 -18
  528. relationalai/early_access/lqp/executor/__init__.py +0 -12
  529. relationalai/early_access/lqp/ir/__init__.py +0 -12
  530. relationalai/early_access/lqp/passes/__init__.py +0 -12
  531. relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  532. relationalai/early_access/lqp/primitives/__init__.py +0 -12
  533. relationalai/early_access/lqp/types/__init__.py +0 -12
  534. relationalai/early_access/lqp/utils/__init__.py +0 -12
  535. relationalai/early_access/lqp/validators/__init__.py +0 -12
  536. relationalai/early_access/metamodel/__init__.py +0 -58
  537. relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  538. relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  539. relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  540. relationalai/early_access/metamodel/factory/__init__.py +0 -17
  541. relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  542. relationalai/early_access/metamodel/ir/__init__.py +0 -14
  543. relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  544. relationalai/early_access/metamodel/typer/__init__.py +0 -3
  545. relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  546. relationalai/early_access/metamodel/types/__init__.py +0 -15
  547. relationalai/early_access/metamodel/util/__init__.py +0 -15
  548. relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  549. relationalai/early_access/rel/__init__.py +0 -12
  550. relationalai/early_access/rel/executor/__init__.py +0 -12
  551. relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  552. relationalai/early_access/rel/rewrite/__init__.py +0 -7
  553. relationalai/early_access/solvers/__init__.py +0 -19
  554. relationalai/early_access/sql/__init__.py +0 -11
  555. relationalai/early_access/sql/executor/__init__.py +0 -3
  556. relationalai/early_access/sql/rewrite/__init__.py +0 -3
  557. relationalai/early_access/tests/logging/__init__.py +0 -12
  558. relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  559. relationalai/early_access/tests/utils/__init__.py +0 -12
  560. relationalai/environments/__init__.py +0 -35
  561. relationalai/environments/base.py +0 -381
  562. relationalai/environments/colab.py +0 -14
  563. relationalai/environments/generic.py +0 -71
  564. relationalai/environments/ipython.py +0 -68
  565. relationalai/environments/jupyter.py +0 -9
  566. relationalai/environments/snowbook.py +0 -169
  567. relationalai/errors.py +0 -2478
  568. relationalai/experimental/SF.py +0 -38
  569. relationalai/experimental/inspect.py +0 -47
  570. relationalai/experimental/pathfinder/__init__.py +0 -158
  571. relationalai/experimental/pathfinder/api.py +0 -160
  572. relationalai/experimental/pathfinder/automaton.py +0 -584
  573. relationalai/experimental/pathfinder/bridge.py +0 -226
  574. relationalai/experimental/pathfinder/compiler.py +0 -416
  575. relationalai/experimental/pathfinder/datalog.py +0 -214
  576. relationalai/experimental/pathfinder/diagnostics.py +0 -56
  577. relationalai/experimental/pathfinder/filter.py +0 -236
  578. relationalai/experimental/pathfinder/glushkov.py +0 -439
  579. relationalai/experimental/pathfinder/options.py +0 -265
  580. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
  581. relationalai/experimental/pathfinder/rpq.py +0 -344
  582. relationalai/experimental/pathfinder/transition.py +0 -200
  583. relationalai/experimental/pathfinder/utils.py +0 -26
  584. relationalai/experimental/paths/README.md +0 -107
  585. relationalai/experimental/paths/api.py +0 -143
  586. relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  587. relationalai/experimental/paths/code_organization.md +0 -2
  588. relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
  589. relationalai/experimental/paths/examples/basic_example.py +0 -40
  590. relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  591. relationalai/experimental/paths/examples/movie_example.py +0 -77
  592. relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
  593. relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
  594. relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
  595. relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
  596. relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
  597. relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
  598. relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
  599. relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
  600. relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  601. relationalai/experimental/paths/examples/paths_example.py +0 -116
  602. relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  603. relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  604. relationalai/experimental/paths/graph.py +0 -185
  605. relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  606. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  607. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  608. relationalai/experimental/paths/path_algorithms/single.py +0 -59
  609. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  610. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  611. relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  612. relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  613. relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  614. relationalai/experimental/paths/product_graph.py +0 -93
  615. relationalai/experimental/paths/rpq/automaton.py +0 -584
  616. relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  617. relationalai/experimental/paths/rpq/rpq.py +0 -378
  618. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  619. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  620. relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  621. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  622. relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  623. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  624. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  625. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  626. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  627. relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  628. relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  629. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  630. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  631. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  632. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  633. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  634. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  635. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  636. relationalai/experimental/paths/tree_agg.py +0 -168
  637. relationalai/experimental/paths/utilities/iterators.py +0 -27
  638. relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  639. relationalai/experimental/solvers.py +0 -1087
  640. relationalai/loaders/csv.py +0 -195
  641. relationalai/loaders/loader.py +0 -177
  642. relationalai/loaders/types.py +0 -23
  643. relationalai/rel_emitter.py +0 -373
  644. relationalai/rel_utils.py +0 -185
  645. relationalai/semantics/designs/query_builder/identify_by.md +0 -106
  646. relationalai/semantics/devtools/benchmark_lqp.py +0 -535
  647. relationalai/semantics/devtools/compilation_manager.py +0 -294
  648. relationalai/semantics/devtools/extract_lqp.py +0 -110
  649. relationalai/semantics/internal/internal.py +0 -3785
  650. relationalai/semantics/internal/snowflake.py +0 -325
  651. relationalai/semantics/lqp/README.md +0 -34
  652. relationalai/semantics/lqp/builtins.py +0 -16
  653. relationalai/semantics/lqp/compiler.py +0 -22
  654. relationalai/semantics/lqp/constructors.py +0 -68
  655. relationalai/semantics/lqp/executor.py +0 -469
  656. relationalai/semantics/lqp/intrinsics.py +0 -24
  657. relationalai/semantics/lqp/model2lqp.py +0 -877
  658. relationalai/semantics/lqp/passes.py +0 -680
  659. relationalai/semantics/lqp/primitives.py +0 -252
  660. relationalai/semantics/lqp/result_helpers.py +0 -202
  661. relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -57
  662. relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  663. relationalai/semantics/lqp/rewrite/extract_common.py +0 -338
  664. relationalai/semantics/lqp/rewrite/extract_keys.py +0 -506
  665. relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  666. relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -314
  667. relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -296
  668. relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  669. relationalai/semantics/lqp/types.py +0 -101
  670. relationalai/semantics/lqp/utils.py +0 -160
  671. relationalai/semantics/lqp/validators.py +0 -57
  672. relationalai/semantics/metamodel/compiler.py +0 -133
  673. relationalai/semantics/metamodel/dependency.py +0 -862
  674. relationalai/semantics/metamodel/executor.py +0 -61
  675. relationalai/semantics/metamodel/factory.py +0 -287
  676. relationalai/semantics/metamodel/helpers.py +0 -361
  677. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  678. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -210
  679. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  680. relationalai/semantics/metamodel/rewrite/flatten.py +0 -554
  681. relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -165
  682. relationalai/semantics/metamodel/typer/checker.py +0 -353
  683. relationalai/semantics/metamodel/typer/typer.py +0 -1395
  684. relationalai/semantics/metamodel/util.py +0 -506
  685. relationalai/semantics/reasoners/__init__.py +0 -10
  686. relationalai/semantics/reasoners/graph/README.md +0 -620
  687. relationalai/semantics/reasoners/graph/__init__.py +0 -37
  688. relationalai/semantics/reasoners/graph/core.py +0 -9019
  689. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
  690. relationalai/semantics/reasoners/graph/tests/README.md +0 -21
  691. relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  692. relationalai/semantics/reasoners/optimization/common.py +0 -88
  693. relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  694. relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1163
  695. relationalai/semantics/rel/builtins.py +0 -40
  696. relationalai/semantics/rel/compiler.py +0 -989
  697. relationalai/semantics/rel/executor.py +0 -362
  698. relationalai/semantics/rel/rel.py +0 -482
  699. relationalai/semantics/rel/rel_utils.py +0 -276
  700. relationalai/semantics/snowflake/__init__.py +0 -3
  701. relationalai/semantics/sql/compiler.py +0 -2503
  702. relationalai/semantics/sql/executor/duck_db.py +0 -52
  703. relationalai/semantics/sql/executor/result_helpers.py +0 -64
  704. relationalai/semantics/sql/executor/snowflake.py +0 -149
  705. relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  706. relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  707. relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  708. relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  709. relationalai/semantics/sql/sql.py +0 -504
  710. relationalai/semantics/std/pragmas.py +0 -11
  711. relationalai/semantics/std/std.py +0 -14
  712. relationalai/semantics/tests/test_snapshot_abstract.py +0 -143
  713. relationalai/semantics/tests/test_snapshot_base.py +0 -9
  714. relationalai/semantics/tests/utils.py +0 -46
  715. relationalai/std/__init__.py +0 -70
  716. relationalai/tools/cli.py +0 -1936
  717. relationalai/tools/cli_controls.py +0 -1826
  718. relationalai/tools/cli_helpers.py +0 -398
  719. relationalai/tools/debugger_client.py +0 -109
  720. relationalai/tools/debugger_server.py +0 -302
  721. relationalai/tools/dev.py +0 -685
  722. relationalai/tools/notes +0 -7
  723. relationalai/tools/qb_debugger.py +0 -425
  724. relationalai/util/clean_up_databases.py +0 -95
  725. relationalai/util/list_databases.py +0 -9
  726. relationalai/util/otel_configuration.py +0 -26
  727. relationalai/util/otel_handler.py +0 -484
  728. relationalai/util/snowflake_handler.py +0 -88
  729. relationalai/util/span_format_test.py +0 -43
  730. relationalai/util/span_tracker.py +0 -207
  731. relationalai/util/spans_file_handler.py +0 -72
  732. relationalai/util/tracing_handler.py +0 -34
  733. relationalai-0.13.0.dist-info/METADATA +0 -74
  734. relationalai-0.13.0.dist-info/RECORD +0 -458
  735. relationalai-0.13.0.dist-info/WHEEL +0 -4
  736. relationalai-0.13.0.dist-info/entry_points.txt +0 -3
  737. relationalai-0.13.0.dist-info/licenses/LICENSE +0 -202
  738. relationalai_test_util/__init__.py +0 -4
  739. relationalai_test_util/fixtures.py +0 -229
  740. relationalai_test_util/snapshot.py +0 -252
  741. relationalai_test_util/traceback.py +0 -118
  742. /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
  743. /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
  744. /relationalai/{early_access → shims}/__init__.py +0 -0
  745. {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
  746. {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
  747. {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
  748. {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
  749. {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
  750. {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
  751. {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
  752. {relationalai → v0/relationalai}/auth/util.py +0 -0
  753. {relationalai/clients/resources/snowflake → v0/relationalai/clients}/cache_store.py +0 -0
  754. {relationalai → v0/relationalai}/compiler.py +0 -0
  755. {relationalai → v0/relationalai}/dependencies.py +0 -0
  756. {relationalai → v0/relationalai}/docutils.py +0 -0
  757. {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
  758. {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
  759. {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  760. {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  761. {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  762. {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  763. {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  764. {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  765. {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  766. {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  767. {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
  768. {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
  769. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  770. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  771. {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
  772. {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  773. {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
  774. {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
  775. {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  776. {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  777. {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
  778. {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  779. {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  780. {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  781. {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  782. {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  783. {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
  784. {relationalai/tools → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
  785. {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
  786. {relationalai → v0/relationalai}/environments/ci.py +0 -0
  787. {relationalai → v0/relationalai}/environments/hex.py +0 -0
  788. {relationalai → v0/relationalai}/environments/terminal.py +0 -0
  789. {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
  790. {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
  791. {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
  792. {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  793. {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  794. {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
  795. {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
  796. {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  797. {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
  798. {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
  799. {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
  800. {relationalai → v0/relationalai}/metagen.py +0 -0
  801. {relationalai → v0/relationalai}/metamodel.py +0 -0
  802. {relationalai → v0/relationalai}/rel.py +0 -0
  803. {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
  804. {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
  805. {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
  806. {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
  807. {relationalai → v0/relationalai}/semantics/lqp/ir.py +0 -0
  808. {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
  809. {relationalai → v0/relationalai}/semantics/lqp/rewrite/__init__.py +0 -0
  810. {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
  811. {relationalai → v0/relationalai}/semantics/metamodel/ir.py +0 -0
  812. {relationalai → v0/relationalai}/semantics/metamodel/rewrite/__init__.py +0 -0
  813. {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  814. {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
  815. {relationalai → v0/relationalai}/semantics/metamodel/visitor.py +0 -0
  816. {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  817. {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
  818. {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
  819. {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
  820. {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  821. {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
  822. {relationalai → v0/relationalai}/std/aggregates.py +0 -0
  823. {relationalai → v0/relationalai}/std/dates.py +0 -0
  824. {relationalai → v0/relationalai}/std/graphs.py +0 -0
  825. {relationalai → v0/relationalai}/std/inspect.py +0 -0
  826. {relationalai → v0/relationalai}/std/math.py +0 -0
  827. {relationalai → v0/relationalai}/std/re.py +0 -0
  828. {relationalai → v0/relationalai}/std/strings.py +0 -0
  829. {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
  830. {relationalai → v0/relationalai}/tools/constants.py +0 -0
  831. {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
  832. {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
  833. {relationalai → v0/relationalai}/util/__init__.py +0 -0
  834. {relationalai → v0/relationalai}/util/constants.py +0 -0
  835. {relationalai → v0/relationalai}/util/graph.py +0 -0
  836. {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)