nori-rel 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. nori_rel-0.3.0/ATTRIBUTION.md +42 -0
  2. nori_rel-0.3.0/CHANGELOG.md +23 -0
  3. nori_rel-0.3.0/LICENSE +21 -0
  4. nori_rel-0.3.0/NOTICE +19 -0
  5. nori_rel-0.3.0/PKG-INFO +183 -0
  6. nori_rel-0.3.0/README.md +131 -0
  7. nori_rel-0.3.0/docs/api.md +100 -0
  8. nori_rel-0.3.0/docs/dependency-exceptions.json +310 -0
  9. nori_rel-0.3.0/docs/dependency-security.md +108 -0
  10. nori_rel-0.3.0/docs/pipeline-export.md +92 -0
  11. nori_rel-0.3.0/docs/pql.md +80 -0
  12. nori_rel-0.3.0/docs/public-api.md +56 -0
  13. nori_rel-0.3.0/docs/run-control.md +49 -0
  14. nori_rel-0.3.0/docs/support.md +48 -0
  15. nori_rel-0.3.0/docs/testing.md +82 -0
  16. nori_rel-0.3.0/docs/warehouse-connectors.md +356 -0
  17. nori_rel-0.3.0/examples/README.md +57 -0
  18. nori_rel-0.3.0/examples/databricks.sql +14 -0
  19. nori_rel-0.3.0/examples/pipeline_reload.py +108 -0
  20. nori_rel-0.3.0/examples/snowflake.sql +16 -0
  21. nori_rel-0.3.0/examples/synthetic_data.py +64 -0
  22. nori_rel-0.3.0/pyproject.toml +152 -0
  23. nori_rel-0.3.0/pyproject.toml.orig +115 -0
  24. nori_rel-0.3.0/scripts/audit_dependencies.py +395 -0
  25. nori_rel-0.3.0/scripts/public-package-files.txt +71 -0
  26. nori_rel-0.3.0/scripts/smoke_install.py +96 -0
  27. nori_rel-0.3.0/scripts/validate_artifacts.py +289 -0
  28. nori_rel-0.3.0/scripts/verify_published.py +68 -0
  29. nori_rel-0.3.0/scripts/verify_release.py +167 -0
  30. nori_rel-0.3.0/src/nori_rel/__init__.py +75 -0
  31. nori_rel-0.3.0/src/nori_rel/_checkpoint.py +89 -0
  32. nori_rel-0.3.0/src/nori_rel/_compat.py +24 -0
  33. nori_rel-0.3.0/src/nori_rel/_credentials.py +120 -0
  34. nori_rel-0.3.0/src/nori_rel/_legacy.py +80 -0
  35. nori_rel-0.3.0/src/nori_rel/_names.py +200 -0
  36. nori_rel-0.3.0/src/nori_rel/_pql_features.py +107 -0
  37. nori_rel-0.3.0/src/nori_rel/_pql_runtime.py +278 -0
  38. nori_rel-0.3.0/src/nori_rel/_runtime.py +529 -0
  39. nori_rel-0.3.0/src/nori_rel/client.py +625 -0
  40. nori_rel-0.3.0/src/nori_rel/connectors/__init__.py +51 -0
  41. nori_rel-0.3.0/src/nori_rel/connectors/base.py +100 -0
  42. nori_rel-0.3.0/src/nori_rel/connectors/databricks.py +369 -0
  43. nori_rel-0.3.0/src/nori_rel/connectors/errors.py +9 -0
  44. nori_rel-0.3.0/src/nori_rel/connectors/postgres.py +672 -0
  45. nori_rel-0.3.0/src/nori_rel/connectors/snowflake.py +526 -0
  46. nori_rel-0.3.0/src/nori_rel/connectors/warehouse.py +1017 -0
  47. nori_rel-0.3.0/src/nori_rel/contracts.py +325 -0
  48. nori_rel-0.3.0/src/nori_rel/feature/__init__.py +19 -0
  49. nori_rel-0.3.0/src/nori_rel/feature/_contract.py +89 -0
  50. nori_rel-0.3.0/src/nori_rel/feature/dfs/__init__.py +5 -0
  51. nori_rel-0.3.0/src/nori_rel/feature/dfs/_basedfs.py +11 -0
  52. nori_rel-0.3.0/src/nori_rel/feature/dfs/fastdfs.py +176 -0
  53. nori_rel-0.3.0/src/nori_rel/limits.py +26 -0
  54. nori_rel-0.3.0/src/nori_rel/pipeline/__init__.py +71 -0
  55. nori_rel-0.3.0/src/nori_rel/pipeline/artifact.py +149 -0
  56. nori_rel-0.3.0/src/nori_rel/pipeline/audit.py +78 -0
  57. nori_rel-0.3.0/src/nori_rel/pipeline/build.py +188 -0
  58. nori_rel-0.3.0/src/nori_rel/pipeline/checks.py +186 -0
  59. nori_rel-0.3.0/src/nori_rel/pipeline/details.py +36 -0
  60. nori_rel-0.3.0/src/nori_rel/pipeline/errors.py +45 -0
  61. nori_rel-0.3.0/src/nori_rel/pipeline/features.py +115 -0
  62. nori_rel-0.3.0/src/nori_rel/pipeline/manifest.py +276 -0
  63. nori_rel-0.3.0/src/nori_rel/pipeline/request.py +34 -0
  64. nori_rel-0.3.0/src/nori_rel/pipeline/task.py +30 -0
  65. nori_rel-0.3.0/src/nori_rel/pql/__init__.py +13 -0
  66. nori_rel-0.3.0/src/nori_rel/pql/_generated/PQLGrammarLexer.py +387 -0
  67. nori_rel-0.3.0/src/nori_rel/pql/_generated/PQLGrammarParser.py +1647 -0
  68. nori_rel-0.3.0/src/nori_rel/pql/_generated/__init__.py +1 -0
  69. nori_rel-0.3.0/src/nori_rel/pql/_vendor/__init__.py +1 -0
  70. nori_rel-0.3.0/src/nori_rel/pql/_vendor/kumo/LICENSE +351 -0
  71. nori_rel-0.3.0/src/nori_rel/pql/_vendor/kumo/NOTICE +38 -0
  72. nori_rel-0.3.0/src/nori_rel/pql/_vendor/kumo/PQLGrammar.g4 +216 -0
  73. nori_rel-0.3.0/src/nori_rel/pql/_vendor/kumo/SOURCE.md +42 -0
  74. nori_rel-0.3.0/src/nori_rel/pql/binding.py +167 -0
  75. nori_rel-0.3.0/src/nori_rel/pql/context_execution.py +60 -0
  76. nori_rel-0.3.0/src/nori_rel/pql/context_sql.py +150 -0
  77. nori_rel-0.3.0/src/nori_rel/pql/dialects.py +164 -0
  78. nori_rel-0.3.0/src/nori_rel/pql/grammar/CHECKSUMS.txt +3 -0
  79. nori_rel-0.3.0/src/nori_rel/pql/grammar/PQLGrammar.g4 +230 -0
  80. nori_rel-0.3.0/src/nori_rel/pql/label_sql.py +396 -0
  81. nori_rel-0.3.0/src/nori_rel/pql/limits.py +108 -0
  82. nori_rel-0.3.0/src/nori_rel/pql/parser.py +98 -0
  83. nori_rel-0.3.0/src/nori_rel/pql/relationships.py +124 -0
  84. nori_rel-0.3.0/src/nori_rel/pql/scope.py +204 -0
  85. nori_rel-0.3.0/src/nori_rel/pql/scoring_sql.py +67 -0
  86. nori_rel-0.3.0/src/nori_rel/pql/sql_expressions.py +238 -0
  87. nori_rel-0.3.0/src/nori_rel/pql/tree_access.py +205 -0
  88. nori_rel-0.3.0/src/nori_rel/pql/window.py +148 -0
  89. nori_rel-0.3.0/src/nori_rel/py.typed +0 -0
  90. nori_rel-0.3.0/src/nori_rel/run/__init__.py +71 -0
  91. nori_rel-0.3.0/src/nori_rel/run/commands.py +86 -0
  92. nori_rel-0.3.0/src/nori_rel/run/context.py +255 -0
  93. nori_rel-0.3.0/src/nori_rel/run/errors.py +54 -0
  94. nori_rel-0.3.0/src/nori_rel/run/executor.py +169 -0
  95. nori_rel-0.3.0/src/nori_rel/run/local_run.py +388 -0
  96. nori_rel-0.3.0/src/nori_rel/run/messages.py +54 -0
  97. nori_rel-0.3.0/src/nori_rel/run/models.py +144 -0
  98. nori_rel-0.3.0/src/nori_rel/run/progress.py +155 -0
  99. nori_rel-0.3.0/src/nori_rel/run/redact.py +97 -0
  100. nori_rel-0.3.0/tests/conftest.py +61 -0
  101. nori_rel-0.3.0/tests/connectors/__init__.py +1 -0
  102. nori_rel-0.3.0/tests/connectors/conftest.py +355 -0
  103. nori_rel-0.3.0/tests/connectors/test_databricks_drivers.py +543 -0
  104. nori_rel-0.3.0/tests/connectors/test_drivers.py +684 -0
  105. nori_rel-0.3.0/tests/connectors/test_warehouse_live.py +583 -0
  106. nori_rel-0.3.0/tests/connectors/test_warehouse_runtime.py +724 -0
  107. nori_rel-0.3.0/tests/feature/test_dfs.py +123 -0
  108. nori_rel-0.3.0/tests/feature/test_fastdfs_types.py +69 -0
  109. nori_rel-0.3.0/tests/feature/test_imports.py +32 -0
  110. nori_rel-0.3.0/tests/pipeline/conftest.py +9 -0
  111. nori_rel-0.3.0/tests/pipeline/pipeline_records.py +86 -0
  112. nori_rel-0.3.0/tests/pipeline/test_pipeline_artifact.py +196 -0
  113. nori_rel-0.3.0/tests/pipeline/test_pipeline_audit.py +79 -0
  114. nori_rel-0.3.0/tests/pipeline/test_pipeline_build.py +41 -0
  115. nori_rel-0.3.0/tests/pipeline/test_pipeline_checks.py +96 -0
  116. nori_rel-0.3.0/tests/pipeline/test_pipeline_features.py +93 -0
  117. nori_rel-0.3.0/tests/pipeline/test_pipeline_predictor.py +47 -0
  118. nori_rel-0.3.0/tests/pql/conftest.py +115 -0
  119. nori_rel-0.3.0/tests/pql/pipeline_child.py +50 -0
  120. nori_rel-0.3.0/tests/pql/pipeline_fakes.py +66 -0
  121. nori_rel-0.3.0/tests/pql/test_binding.py +195 -0
  122. nori_rel-0.3.0/tests/pql/test_client_e2e.py +181 -0
  123. nori_rel-0.3.0/tests/pql/test_connection_lifecycle.py +63 -0
  124. nori_rel-0.3.0/tests/pql/test_context_execution.py +185 -0
  125. nori_rel-0.3.0/tests/pql/test_context_sql.py +258 -0
  126. nori_rel-0.3.0/tests/pql/test_dialects.py +474 -0
  127. nori_rel-0.3.0/tests/pql/test_features.py +318 -0
  128. nori_rel-0.3.0/tests/pql/test_full_pipeline.py +742 -0
  129. nori_rel-0.3.0/tests/pql/test_inference.py +87 -0
  130. nori_rel-0.3.0/tests/pql/test_label_sql.py +691 -0
  131. nori_rel-0.3.0/tests/pql/test_limits.py +110 -0
  132. nori_rel-0.3.0/tests/pql/test_local_postgres.py +115 -0
  133. nori_rel-0.3.0/tests/pql/test_names.py +176 -0
  134. nori_rel-0.3.0/tests/pql/test_parser.py +137 -0
  135. nori_rel-0.3.0/tests/pql/test_pipeline_roundtrip.py +329 -0
  136. nori_rel-0.3.0/tests/pql/test_relationships.py +138 -0
  137. nori_rel-0.3.0/tests/pql/test_run_stages.py +91 -0
  138. nori_rel-0.3.0/tests/pql/test_scope.py +135 -0
  139. nori_rel-0.3.0/tests/pql/test_tree_access.py +104 -0
  140. nori_rel-0.3.0/tests/pql/test_vendored_grammar.py +74 -0
  141. nori_rel-0.3.0/tests/pql/test_window.py +45 -0
  142. nori_rel-0.3.0/tests/run/test_local_executor.py +198 -0
  143. nori_rel-0.3.0/tests/run/test_local_run.py +615 -0
  144. nori_rel-0.3.0/tests/run/test_run_context.py +276 -0
  145. nori_rel-0.3.0/tests/run/test_run_messages.py +57 -0
  146. nori_rel-0.3.0/tests/run/test_run_models.py +105 -0
  147. nori_rel-0.3.0/tests/run/test_run_progress.py +187 -0
  148. nori_rel-0.3.0/tests/run/test_run_redact.py +115 -0
  149. nori_rel-0.3.0/tests/run_control_fakes.py +21 -0
  150. nori_rel-0.3.0/tests/test_artifact_inventory.py +273 -0
  151. nori_rel-0.3.0/tests/test_checkpoint.py +28 -0
  152. nori_rel-0.3.0/tests/test_dependency_audit.py +374 -0
  153. nori_rel-0.3.0/tests/test_legacy_adapter.py +146 -0
  154. nori_rel-0.3.0/tests/test_local_inference.py +173 -0
  155. nori_rel-0.3.0/tests/test_postgres_safety.py +80 -0
  156. nori_rel-0.3.0/tests/test_relational_client.py +357 -0
  157. nori_rel-0.3.0/tests/test_relational_credentials.py +106 -0
  158. nori_rel-0.3.0/tests/test_relational_postgres.py +136 -0
  159. nori_rel-0.3.0/tests/test_relational_runtime.py +46 -0
  160. nori_rel-0.3.0/tests/test_release_validation.py +393 -0
  161. nori_rel-0.3.0/tests/test_runtime_connections.py +67 -0
@@ -0,0 +1,42 @@
1
+ # Attribution
2
+
3
+ Original Synthefy code in Nori-Rel is distributed under the [MIT License](LICENSE).
4
+ Third-party code retains its own license. The project license does not grant
5
+ rights to third-party model weights, datasets, or hosted services.
6
+
7
+ ## PQL grammar and generated parser
8
+
9
+ The PQL grammar derives from the NVIDIA Kumo Relational Client at commit
10
+ `9fcdc8a111813e67787ce143fa0fdf5871d6d8de`:
11
+
12
+ - Source: <https://github.com/kumo-ai/kumo-relational-client>
13
+ - Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES.
14
+ - License: Apache-2.0.
15
+ - Unmodified grammar, license, notice, and provenance:
16
+ [`src/nori_rel/pql/_vendor/kumo/`](src/nori_rel/pql/_vendor/kumo/).
17
+ - Modified grammar: [`src/nori_rel/pql/grammar/PQLGrammar.g4`](src/nori_rel/pql/grammar/PQLGrammar.g4).
18
+ - Derived parser: [`src/nori_rel/pql/_generated/`](src/nori_rel/pql/_generated/).
19
+
20
+ The modified grammar and generated parser retain this Apache-2.0 notice.
21
+ The pinned upstream license and notice are included unchanged. The upstream
22
+ notice covers its full distribution; it does not imply that Nori-Rel ships every
23
+ component mentioned there. Parser generation instructions and source checksums
24
+ are in the vendored `SOURCE.md`.
25
+
26
+ ## Installed dependencies
27
+
28
+ [FastDFS](https://github.com/HKUSHXLab/fastdfs) supplies the supported relational
29
+ feature implementation under Apache-2.0. It uses
30
+ [Featuretools](https://github.com/alteryx/featuretools), copyright Feature Labs,
31
+ Inc., under BSD-3-Clause. These libraries are installed as dependencies and are
32
+ not vendored in Nori-Rel. ANTLR's Python runtime is separately installed under
33
+ BSD-3-Clause. Other dependencies retain the terms in their distributions.
34
+
35
+ The local Nori runtime and downloaded model artifacts are separately distributed.
36
+ Review the selected model's license and model card before redistributing weights.
37
+
38
+ ## Examples and research
39
+
40
+ The examples on `main` generate synthetic data; they do not redistribute a
41
+ research dataset. Research code, attribution, methods, and results are maintained
42
+ privately and are outside the supported release package.
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ ## 0.3.0 — 2026-10-14
4
+
5
+ Initial public database-client release.
6
+
7
+ - Focus the distribution on PQL, FastDFS, PostgreSQL, Snowflake, Databricks,
8
+ local/hosted inference, pipeline export/reload, and prediction lifecycle.
9
+ - Exclude research adapters, experimental feature search, benchmarks, notebooks,
10
+ their extras, and the research CLI from the supported distribution.
11
+ - Add an independent `local` extra, public license/attribution, synthetic
12
+ examples, contribution/security guidance, and a documented support contract.
13
+ - Validate saved model settings when reusing a pipeline predictor.
14
+ - Add isolated package/connector checks, release certification, and protected
15
+ Trusted Publishing workflows using the tested distribution artifacts.
16
+
17
+ Migration: use `query=` PQL and `features="fastdfs"`. Research feature names,
18
+ agent programs, and research pipeline variants are outside the supported package.
19
+ Install `nori-rel[<connector>,local]` for local inference (`database` is the
20
+ PostgreSQL extra). The old research `nori-rel` command is no longer installed.
21
+
22
+ Dependency findings and their expiring, version-specific
23
+ assessments are documented in [the security review](docs/dependency-security.md).
nori_rel-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Synthefy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
nori_rel-0.3.0/NOTICE ADDED
@@ -0,0 +1,19 @@
1
+ Nori-Rel
2
+ Copyright (c) 2026 Synthefy
3
+
4
+ Original Synthefy code is licensed under the MIT License in LICENSE.
5
+ Third-party components retain their own licenses and notices.
6
+
7
+ The PQL grammar, its Synthefy modifications, and the generated parser derive
8
+ from the NVIDIA Kumo Relational Client and are subject to Apache-2.0:
9
+
10
+ Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES.
11
+
12
+ The unmodified upstream license, notice, grammar, and provenance are included
13
+ under src/nori_rel/pql/_vendor/kumo/. Synthefy's grammar modifications are
14
+ identified in src/nori_rel/pql/grammar/PQLGrammar.g4; the generated parser
15
+ headers identify this derivation. See ATTRIBUTION.md for source details.
16
+
17
+ The upstream NOTICE describes components of the full upstream distribution.
18
+ Its inclusion preserves that notice; Nori-Rel vendors only the PQL grammar
19
+ and the accompanying license/provenance files, and ships its derived parser.
@@ -0,0 +1,183 @@
1
+ Metadata-Version: 2.4
2
+ Name: nori-rel
3
+ Version: 0.3.0
4
+ Summary: Relational database prediction with Nori
5
+ Author: Synthefy
6
+ License-Expression: MIT AND Apache-2.0
7
+ License-File: ATTRIBUTION.md
8
+ License-File: LICENSE
9
+ License-File: NOTICE
10
+ License-File: src/nori_rel/pql/_vendor/kumo/LICENSE
11
+ License-File: src/nori_rel/pql/_vendor/kumo/NOTICE
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Typing :: Typed
18
+ Requires-Dist: antlr4-python3-runtime==4.13.2
19
+ Requires-Dist: numpy>=2.0
20
+ Requires-Dist: pandas>=2.3.3,<3.0
21
+ Requires-Dist: pydantic>=2.10,<3
22
+ Requires-Dist: boto3>=1.34,<2 ; extra == 'database'
23
+ Requires-Dist: fastdfs>=1.1,<2 ; extra == 'database'
24
+ Requires-Dist: psycopg[binary]>=3.2,<4 ; extra == 'database'
25
+ Requires-Dist: sqlalchemy>=2.0,<3 ; extra == 'database'
26
+ Requires-Dist: synthefy>=7.2.0,<8 ; extra == 'database'
27
+ Requires-Dist: urllib3>=2.8,<3 ; extra == 'database'
28
+ Requires-Dist: boto3>=1.34,<2 ; extra == 'databricks'
29
+ Requires-Dist: databricks-sdk>=0.151,<1 ; extra == 'databricks'
30
+ Requires-Dist: databricks-sql-connector>=4.6,<5 ; extra == 'databricks'
31
+ Requires-Dist: fastdfs>=1.1,<2 ; extra == 'databricks'
32
+ Requires-Dist: sqlalchemy>=2.0,<3 ; extra == 'databricks'
33
+ Requires-Dist: synthefy>=7.2.0,<8 ; extra == 'databricks'
34
+ Requires-Dist: urllib3>=2.8,<3 ; extra == 'databricks'
35
+ Requires-Dist: synthefy-nori==0.20.1 ; extra == 'local'
36
+ Requires-Dist: fsspec>=2026.6.0 ; extra == 'local'
37
+ Requires-Dist: boto3>=1.34,<2 ; extra == 'snowflake'
38
+ Requires-Dist: fastdfs>=1.1,<2 ; extra == 'snowflake'
39
+ Requires-Dist: snowflake-connector-python>=4.8,<5 ; extra == 'snowflake'
40
+ Requires-Dist: sqlalchemy>=2.0,<3 ; extra == 'snowflake'
41
+ Requires-Dist: synthefy>=7.2.0,<8 ; extra == 'snowflake'
42
+ Requires-Dist: urllib3>=2.8,<3 ; extra == 'snowflake'
43
+ Requires-Python: >=3.11, <3.13
44
+ Project-URL: Repository, https://github.com/Synthefy/nori-rel
45
+ Project-URL: Issues, https://github.com/Synthefy/nori-rel/issues
46
+ Project-URL: Changelog, https://github.com/Synthefy/nori-rel/blob/main/CHANGELOG.md
47
+ Provides-Extra: database
48
+ Provides-Extra: databricks
49
+ Provides-Extra: local
50
+ Provides-Extra: snowflake
51
+ Description-Content-Type: text/markdown
52
+
53
+ # Nori-Rel
54
+
55
+ Predict from relational databases with [Nori](https://docs.synthefy.com/nori).
56
+ Nori-Rel reads a bounded database snapshot, constructs historical targets and
57
+ FastDFS features, and runs local or hosted inference through one Python client.
58
+
59
+ The supported package covers PostgreSQL, Snowflake standard tables, and
60
+ Databricks Unity Catalog Delta tables. Releases come from reviewed commits on
61
+ `main`.
62
+
63
+ Review the [support contract](docs/support.md) and
64
+ [dependency security assessment](docs/dependency-security.md) before deployment.
65
+ The assessment includes scoped, expiring exceptions for upstream dependencies.
66
+
67
+ ## Install
68
+
69
+ Python 3.11 and 3.12 are supported. Install your connector and, for the default
70
+ local inference mode, the model runtime:
71
+
72
+ ```bash
73
+ python -m pip install "nori-rel[database,local]"
74
+ # Other connectors:
75
+ python -m pip install "nori-rel[snowflake,local]"
76
+ python -m pip install "nori-rel[databricks,local]"
77
+ ```
78
+
79
+ For hosted inference, omit `local` and set `SYNTHEFY_NORI_API_KEY` privately.
80
+ A hosted installation does not require the local model runtime or model weights.
81
+ See [supported capabilities](docs/support.md) for platform and target limits.
82
+
83
+ ## Predict customer spend
84
+
85
+ This example expects existing `users(user_id, created_at)` and
86
+ `orders(order_id, user_id, event_time, amount)` tables with declared primary and
87
+ foreign keys. Set `DATABASE_URL` to a TLS-enabled PostgreSQL connection string.
88
+ Use [the synthetic example](examples/README.md) for a complete disposable dataset.
89
+
90
+ ```python
91
+ from datetime import UTC, datetime
92
+
93
+ from nori_rel import EnvironmentCredential, NoriRelClient
94
+
95
+ with NoriRelClient() as client:
96
+ source = client.connect(
97
+ engine="postgresql",
98
+ credential=EnvironmentCredential(variable="DATABASE_URL"),
99
+ tables=["users", "orders"],
100
+ time_columns={"orders": "event_time"},
101
+ )
102
+ details = client.predict(
103
+ source=source,
104
+ query="PREDICT SUM(orders.amount,0,30,days) FOR EACH users.user_id",
105
+ anchor_times=[datetime(2026, 1, 1, tzinfo=UTC)],
106
+ anchor_time=datetime(2026, 3, 1, tzinfo=UTC),
107
+ observed_through=datetime(2026, 3, 1, tzinfo=UTC),
108
+ entity_created_at="created_at",
109
+ return_details=True,
110
+ )
111
+ predictions = details.predictions
112
+ print(predictions[["entity_id", "prediction"]])
113
+ ```
114
+
115
+ The query predicts each user's total order amount over the next 30 days.
116
+ `anchor_times` supplies historical examples; `anchor_time` is the scoring time.
117
+ `observed_through` is your verified data-completeness watermark, not an estimate
118
+ of completeness from the latest event. Use dates appropriate to your data and
119
+ at least 32 usable historical rows. Register every event table's timestamp;
120
+ other entity attributes must be immutable or valid at every requested anchor.
121
+ See [PQL and time semantics](docs/pql.md).
122
+
123
+ The default mode runs Nori in your process. The first local prediction downloads
124
+ model weights; subsequent predictions can use the populated cache offline.
125
+ Use `NoriRelClient(mode="hosted")` to send the generated context/query feature
126
+ matrices and labels to hosted Nori. Database connections, credentials, and raw
127
+ source tables stay in the caller's process. Generated features can still contain
128
+ sensitive information derived from those tables.
129
+
130
+ ## Save and reload
131
+
132
+ Request prediction details to obtain a pipeline, then reconnect when using it:
133
+
134
+ ```python
135
+ from nori_rel import NoriRelPipeline
136
+
137
+ if details.pipeline is None:
138
+ raise RuntimeError("This prediction cannot be exported as a pipeline")
139
+ details.pipeline.save("customer_spend.json")
140
+
141
+ pipeline = NoriRelPipeline.load("customer_spend.json")
142
+ with NoriRelClient() as client:
143
+ source = client.connect(
144
+ engine="postgresql",
145
+ credential=EnvironmentCredential(variable="DATABASE_URL"),
146
+ tables=["users", "orders"],
147
+ time_columns={"orders": "event_time"},
148
+ )
149
+ predictions = client.predict(
150
+ source=source,
151
+ pipeline=pipeline,
152
+ as_of=datetime(2026, 4, 1, tzinfo=UTC),
153
+ observed_through=datetime(2026, 4, 1, tzinfo=UTC),
154
+ )
155
+ ```
156
+
157
+ A pipeline stores the task, feature recipe, schema contract, context policy, and
158
+ model settings. Each replay reads fresh rows. It contains no credentials,
159
+ source rows, or model weights. See [pipeline export](docs/pipeline-export.md)
160
+ and the runnable [save/reload example](examples/pipeline_reload.py).
161
+
162
+ ## Operations and safety boundaries
163
+
164
+ Use the client as a context manager to close connection pools. PostgreSQL uses
165
+ TLS and read-only transactions; warehouse connectors use pinned reads and require
166
+ a dedicated identity without write privileges. Warehouse capabilities and
167
+ snapshot guarantees are documented in the [connector guide](docs/warehouse-connectors.md).
168
+
169
+ `RelationalLimits` bounds tables, rows, snapshot memory, feature size, and SQL
170
+ statement time. Exceeding an extraction limit raises an error. These limits do
171
+ not cap total warehouse billing or the process's total memory. See
172
+ [configuration and errors](docs/api.md) and [progress/cancellation](docs/run-control.md).
173
+
174
+ ## Development and licensing
175
+
176
+ See the [public API inventory](docs/public-api.md),
177
+ [CONTRIBUTING.md](CONTRIBUTING.md), [SECURITY.md](SECURITY.md), and
178
+ [RELEASING.md](RELEASING.md). Public release changes are recorded in
179
+ [CHANGELOG.md](CHANGELOG.md).
180
+
181
+ Original Synthefy code is [MIT-licensed](LICENSE). The vendored PQL grammar and
182
+ derived parser retain Apache-2.0 licensing. Dependencies, downloaded model weights,
183
+ and external datasets have their own terms; see [ATTRIBUTION.md](ATTRIBUTION.md).
@@ -0,0 +1,131 @@
1
+ # Nori-Rel
2
+
3
+ Predict from relational databases with [Nori](https://docs.synthefy.com/nori).
4
+ Nori-Rel reads a bounded database snapshot, constructs historical targets and
5
+ FastDFS features, and runs local or hosted inference through one Python client.
6
+
7
+ The supported package covers PostgreSQL, Snowflake standard tables, and
8
+ Databricks Unity Catalog Delta tables. Releases come from reviewed commits on
9
+ `main`.
10
+
11
+ Review the [support contract](docs/support.md) and
12
+ [dependency security assessment](docs/dependency-security.md) before deployment.
13
+ The assessment includes scoped, expiring exceptions for upstream dependencies.
14
+
15
+ ## Install
16
+
17
+ Python 3.11 and 3.12 are supported. Install your connector and, for the default
18
+ local inference mode, the model runtime:
19
+
20
+ ```bash
21
+ python -m pip install "nori-rel[database,local]"
22
+ # Other connectors:
23
+ python -m pip install "nori-rel[snowflake,local]"
24
+ python -m pip install "nori-rel[databricks,local]"
25
+ ```
26
+
27
+ For hosted inference, omit `local` and set `SYNTHEFY_NORI_API_KEY` privately.
28
+ A hosted installation does not require the local model runtime or model weights.
29
+ See [supported capabilities](docs/support.md) for platform and target limits.
30
+
31
+ ## Predict customer spend
32
+
33
+ This example expects existing `users(user_id, created_at)` and
34
+ `orders(order_id, user_id, event_time, amount)` tables with declared primary and
35
+ foreign keys. Set `DATABASE_URL` to a TLS-enabled PostgreSQL connection string.
36
+ Use [the synthetic example](examples/README.md) for a complete disposable dataset.
37
+
38
+ ```python
39
+ from datetime import UTC, datetime
40
+
41
+ from nori_rel import EnvironmentCredential, NoriRelClient
42
+
43
+ with NoriRelClient() as client:
44
+ source = client.connect(
45
+ engine="postgresql",
46
+ credential=EnvironmentCredential(variable="DATABASE_URL"),
47
+ tables=["users", "orders"],
48
+ time_columns={"orders": "event_time"},
49
+ )
50
+ details = client.predict(
51
+ source=source,
52
+ query="PREDICT SUM(orders.amount,0,30,days) FOR EACH users.user_id",
53
+ anchor_times=[datetime(2026, 1, 1, tzinfo=UTC)],
54
+ anchor_time=datetime(2026, 3, 1, tzinfo=UTC),
55
+ observed_through=datetime(2026, 3, 1, tzinfo=UTC),
56
+ entity_created_at="created_at",
57
+ return_details=True,
58
+ )
59
+ predictions = details.predictions
60
+ print(predictions[["entity_id", "prediction"]])
61
+ ```
62
+
63
+ The query predicts each user's total order amount over the next 30 days.
64
+ `anchor_times` supplies historical examples; `anchor_time` is the scoring time.
65
+ `observed_through` is your verified data-completeness watermark, not an estimate
66
+ of completeness from the latest event. Use dates appropriate to your data and
67
+ at least 32 usable historical rows. Register every event table's timestamp;
68
+ other entity attributes must be immutable or valid at every requested anchor.
69
+ See [PQL and time semantics](docs/pql.md).
70
+
71
+ The default mode runs Nori in your process. The first local prediction downloads
72
+ model weights; subsequent predictions can use the populated cache offline.
73
+ Use `NoriRelClient(mode="hosted")` to send the generated context/query feature
74
+ matrices and labels to hosted Nori. Database connections, credentials, and raw
75
+ source tables stay in the caller's process. Generated features can still contain
76
+ sensitive information derived from those tables.
77
+
78
+ ## Save and reload
79
+
80
+ Request prediction details to obtain a pipeline, then reconnect when using it:
81
+
82
+ ```python
83
+ from nori_rel import NoriRelPipeline
84
+
85
+ if details.pipeline is None:
86
+ raise RuntimeError("This prediction cannot be exported as a pipeline")
87
+ details.pipeline.save("customer_spend.json")
88
+
89
+ pipeline = NoriRelPipeline.load("customer_spend.json")
90
+ with NoriRelClient() as client:
91
+ source = client.connect(
92
+ engine="postgresql",
93
+ credential=EnvironmentCredential(variable="DATABASE_URL"),
94
+ tables=["users", "orders"],
95
+ time_columns={"orders": "event_time"},
96
+ )
97
+ predictions = client.predict(
98
+ source=source,
99
+ pipeline=pipeline,
100
+ as_of=datetime(2026, 4, 1, tzinfo=UTC),
101
+ observed_through=datetime(2026, 4, 1, tzinfo=UTC),
102
+ )
103
+ ```
104
+
105
+ A pipeline stores the task, feature recipe, schema contract, context policy, and
106
+ model settings. Each replay reads fresh rows. It contains no credentials,
107
+ source rows, or model weights. See [pipeline export](docs/pipeline-export.md)
108
+ and the runnable [save/reload example](examples/pipeline_reload.py).
109
+
110
+ ## Operations and safety boundaries
111
+
112
+ Use the client as a context manager to close connection pools. PostgreSQL uses
113
+ TLS and read-only transactions; warehouse connectors use pinned reads and require
114
+ a dedicated identity without write privileges. Warehouse capabilities and
115
+ snapshot guarantees are documented in the [connector guide](docs/warehouse-connectors.md).
116
+
117
+ `RelationalLimits` bounds tables, rows, snapshot memory, feature size, and SQL
118
+ statement time. Exceeding an extraction limit raises an error. These limits do
119
+ not cap total warehouse billing or the process's total memory. See
120
+ [configuration and errors](docs/api.md) and [progress/cancellation](docs/run-control.md).
121
+
122
+ ## Development and licensing
123
+
124
+ See the [public API inventory](docs/public-api.md),
125
+ [CONTRIBUTING.md](CONTRIBUTING.md), [SECURITY.md](SECURITY.md), and
126
+ [RELEASING.md](RELEASING.md). Public release changes are recorded in
127
+ [CHANGELOG.md](CHANGELOG.md).
128
+
129
+ Original Synthefy code is [MIT-licensed](LICENSE). The vendored PQL grammar and
130
+ derived parser retain Apache-2.0 licensing. Dependencies, downloaded model weights,
131
+ and external datasets have their own terms; see [ATTRIBUTION.md](ATTRIBUTION.md).
@@ -0,0 +1,100 @@
1
+ # Client configuration and errors
2
+
3
+ The public entry point is `nori_rel.NoriRelClient`. It owns connection pools and
4
+ prediction runs; use `with NoriRelClient(...) as client:` or call `close()`.
5
+ Closing is idempotent. A closed client cannot be reused. Create a new client to
6
+ pick up rotated database credentials.
7
+
8
+ ## Inference settings
9
+
10
+ | Setting | Default and behavior |
11
+ | --- | --- |
12
+ | `mode` | `"local"`; `"hosted"` opts into the hosted service. |
13
+ | `model` | `"nori-30m"`; local supports `nori-6m`, `nori-30m`, and `nori-100m`. |
14
+ | `api_key` | Hosted mode uses this value or `SYNTHEFY_NORI_API_KEY`. |
15
+ | `device` | Local only; automatic CUDA, then MPS, then CPU. An explicit PyTorch device can be supplied. |
16
+ | `features` | `"fastdfs"`, the supported built-in feature backend. |
17
+ | `timeout` | 300 seconds for inference transport configuration. |
18
+ | `max_retries` | 2 for hosted transport retries. |
19
+ | `limits` | `RelationalLimits()` for extraction/context ceilings. |
20
+
21
+ `timeout` is not a hard deadline for the complete relational workflow.
22
+ `run.result(timeout=...)` bounds the caller's wait and leaves the run active;
23
+ see [run control](run-control.md).
24
+
25
+ The optional local runtime is pinned independently of the lightweight Synthefy
26
+ SDK. Initial prediction downloads the selected weights to the Hugging Face
27
+ cache. Populate that cache first to run with `HF_HUB_OFFLINE=1`. Missing or
28
+ corrupted required weights cause an actionable failure; local mode never falls
29
+ back to a hosted call. Hardware, runtime, and source changes can affect numerical
30
+ results. Pipeline hashes detect specific source/model changes, not arbitrary
31
+ numerical nondeterminism.
32
+
33
+ ## Connections
34
+
35
+ `connect()` returns a `Database` handle. Provide `engine` and exactly one of
36
+ `database_url` or `credential`. Credential references are:
37
+
38
+ - `EnvironmentCredential(variable="DATABASE_URL")` for a PostgreSQL URL, or
39
+ a variable holding warehouse authentication JSON.
40
+ - `AwsSecret(secret_id="your-secret-name", region_name="us-west-2")` for AWS
41
+ Secrets Manager. PostgreSQL accepts a URL or standard RDS JSON fields.
42
+ - `DatabaseUrl(value=...)`, primarily for direct PostgreSQL URL use.
43
+
44
+ Each connector extra includes AWS credential support. An RDS or Aurora PostgreSQL
45
+ endpoint still uses `engine="postgresql"`; MySQL is unsupported.
46
+
47
+ Use `schema_name`, a `tables` allowlist, and `time_columns` mappings. Warehouses
48
+ require a typed `connection` object and an explicit schema. `primary_keys` and
49
+ `foreign_keys` supply relationships when warehouse metadata lacks them.
50
+ `client.test_connection(source)` checks connectivity, and `client.discover(source)`
51
+ returns the schema and connector capabilities. See [warehouse setup](warehouse-connectors.md).
52
+
53
+ ## Resource limits
54
+
55
+ ```python
56
+ from nori_rel import NoriRelClient, RelationalLimits
57
+
58
+ client = NoriRelClient(
59
+ limits=RelationalLimits(
60
+ max_rows_per_table=100_000,
61
+ max_total_rows=300_000,
62
+ max_snapshot_bytes=500_000_000,
63
+ statement_timeout_ms=60_000,
64
+ )
65
+ )
66
+ # Connect, predict, and close the client when finished.
67
+ ```
68
+
69
+ | Limit | Default |
70
+ | --- | ---: |
71
+ | Tables | 32 |
72
+ | Rows per table | 1,000,000 |
73
+ | Total snapshot rows | 3,000,000 |
74
+ | Snapshot bytes | 4,000,000,000 |
75
+ | SQL statement timeout | 300,000 ms |
76
+ | Minimum training rows | 32 |
77
+ | Maximum context rows | 60,000 |
78
+ | Feature elements | 3,000,000 |
79
+ | Features | 512 |
80
+
81
+ The per-request `max_context_rows` defaults to 5,000 and remains subject to the
82
+ resource ceilings. Snapshot limits constrain extracted data; feature building
83
+ and model inference can allocate additional memory. SQL timeouts and row limits
84
+ do not guarantee a fixed warehouse scan cost. Exceeding an extraction limit
85
+ fails the operation instead of silently truncating source data.
86
+
87
+ ## Errors and compatibility
88
+
89
+ Invalid arguments raise `ValueError` or typed validation errors. Connector
90
+ failures raise `nori_rel.connectors.errors.ConnectorError`; extraction limits raise its
91
+ `SnapshotLimitError` subclass. Prediction runs expose `PredictionCancelled`,
92
+ `PredictionFailed`, and `RunTimeout`. Saved-pipeline incompatibilities raise a
93
+ `PipelineError` subclass, described in [pipeline export](pipeline-export.md).
94
+ Inspect error types and messages rather than matching full exception strings.
95
+
96
+ The old `entity`/`target` aggregate request form is a deprecated compatibility
97
+ bridge and emits `FutureWarning`. Use `query=` PQL for new code. Direct/NEXT
98
+ legacy targets and explicit relationship-path prediction are retired. Research
99
+ feature engines and their saved pipeline variants are outside the public client
100
+ contract and are not included in this package.