contractforge-databricks 0.1.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.
- contractforge_databricks-0.1.0/.gitignore +18 -0
- contractforge_databricks-0.1.0/CHANGELOG.md +15 -0
- contractforge_databricks-0.1.0/PKG-INFO +34 -0
- contractforge_databricks-0.1.0/README.md +6 -0
- contractforge_databricks-0.1.0/pyproject.toml +45 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/__init__.py +172 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/adapter.py +69 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/annotations/__init__.py +10 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/annotations/application.py +52 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/annotations/audit.py +49 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/annotations/sql.py +142 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/api.py +65 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/bundles/__init__.py +9 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/bundles/assets.py +47 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/bundles/project.py +213 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/bundles/project_config.py +133 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/capabilities/__init__.py +17 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/capabilities/builders.py +43 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/capabilities/evaluate.py +162 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/capabilities/mapping.py +36 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/capabilities/models.py +44 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/capabilities/runtime.py +111 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/capabilities/uc.py +47 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cli.py +196 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cli_deploy.py +98 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cli_governance.py +142 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cli_io.py +91 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cli_maintenance.py +69 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/coercion.py +31 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/contract_extensions.py +70 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cost/__init__.py +11 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cost/model.py +22 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cost/report.py +65 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/cost/sql.py +136 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/dashboards/__init__.py +15 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/dashboards/control_tables.py +150 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/diagnostics/__init__.py +7 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/diagnostics/explain.py +40 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/environment.py +53 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/__init__.py +98 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/ddl.py +35 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/governance_log.py +175 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/helpers.py +29 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/ops_log.py +210 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/records.py +27 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/run_log.py +74 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/schemas.py +7 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/sql.py +144 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/tables.py +20 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/evidence/writer.py +118 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/__init__.py +70 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/delta_basic.py +57 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/hash_diff.py +126 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/hash_diff_latest.py +142 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/replace_partitions.py +40 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/results.py +5 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/retry.py +36 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/scd2.py +213 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/scd2_deletes.py +65 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/scd2_late.py +30 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/snapshot.py +77 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/sql_merge.py +85 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/tables.py +98 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/execution/windows.py +58 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/governance/__init__.py +30 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/governance/access.py +185 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/governance/application.py +93 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/governance/drift.py +49 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/governance/runtime.py +60 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/governance/sql.py +31 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/governance/validation.py +135 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/lakeflow/__init__.py +21 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/lakeflow/compatibility.py +194 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/lakeflow/rendering.py +175 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/lineage/__init__.py +7 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/lineage/openlineage.py +182 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/maintenance/__init__.py +27 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/maintenance/retention.py +90 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/maintenance/sql.py +68 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/metrics/__init__.py +19 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/metrics/history.py +21 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/metrics/write.py +63 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/operations/__init__.py +4 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/operations/application.py +38 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/operations/sql.py +95 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/parity/__init__.py +18 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/parity/catalog.py +59 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/parity/models.py +7 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/parity/scenarios.py +111 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/partitioning/__init__.py +3 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/partitioning/predicates.py +28 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/__init__.py +47 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/deduplicate.py +87 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/encoding.py +37 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/hashing.py +18 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/pyspark.py +178 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/pyspark_staging.py +70 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/shape.py +209 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/shape_validation.py +94 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/staging.py +17 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/preparation/zip_arrays.py +51 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/__init__.py +3 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/base.py +24 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/bronze.py +57 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/catalog.py +22 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/core.py +134 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/gold.py +62 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/modifiers.py +51 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/runtime.py +22 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/silver.py +101 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/presets/write_engine.py +57 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/quality/__init__.py +41 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/quality/evaluation.py +178 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/quality/persistence.py +81 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/quality/registry.py +134 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/quality/results.py +17 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/quality/sql.py +113 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/rendering/__init__.py +11 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/rendering/bundle.py +93 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/rendering/markdown.py +50 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/rendering/names.py +56 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/results.py +15 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/__init__.py +101 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/available_now.py +147 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/bundles.py +211 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/cache.py +20 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/control_tables.py +19 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/deploy.py +197 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/detection.py +114 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/dry_run.py +46 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/errors.py +54 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/file_selection.py +109 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/finalization.py +168 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/governance.py +37 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/hooks.py +45 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/http_file.py +37 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/http_retry.py +15 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/http_safety.py +9 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/json_materialization.py +97 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/lineage.py +164 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/maintenance.py +43 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/merge_validation.py +98 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/metadata.py +21 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/metrics.py +34 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/models.py +32 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/options.py +33 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/orchestration_context.py +185 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/orchestrator.py +147 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/partitioning.py +93 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/quality_quarantine.py +92 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/rest_api.py +46 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/rest_auth.py +21 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/rest_pagination.py +21 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/run_payload.py +177 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/schema.py +106 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/source_metadata.py +30 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/source_registry.py +43 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/source_schema.py +24 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/sources.py +208 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/spark.py +183 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/spark_defaults.py +35 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/storage_auth.py +132 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/streaming.py +131 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/success.py +104 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/utils.py +52 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/watermark.py +71 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/windows.py +184 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/write.py +66 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/write_flow.py +146 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/runtime/write_strategy.py +40 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/schema/__init__.py +21 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/schema/diff.py +11 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/schema/policy.py +33 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/schema/sync.py +23 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/security/__init__.py +21 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/security/errors.py +5 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/security/redaction.py +5 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/security/secrets.py +114 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/security/source_policy.py +17 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/shapes/__init__.py +3 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/shapes/sql.py +123 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/__init__.py +67 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/artifacts.py +100 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/autoloader.py +48 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/bounded_streams.py +44 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/classification.py +115 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/delta_share.py +21 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/files.py +48 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/http_file.py +46 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/interpret.py +76 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/jdbc.py +32 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/metadata.py +18 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/native_passthrough.py +33 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/rds_iam.py +15 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/rds_iam_runtime.py +191 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/rest_api.py +33 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/support.py +50 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sources/table_refs.py +65 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sql/__init__.py +4 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sql/identifiers.py +17 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/sql/literals.py +36 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/state/__init__.py +39 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/state/ddl.py +24 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/state/migrations.py +146 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/state/queries.py +149 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/state/sql.py +116 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/state/tables.py +9 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/state/writer.py +83 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/templates/__init__.py +15 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/templates/catalog.py +205 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/templates/catalog_parity.py +85 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/templates/core.py +83 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/templates/enrichment.py +175 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/transforms/__init__.py +3 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/transforms/sql.py +118 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/watermark/__init__.py +6 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/watermark/sql.py +91 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/write_modes/__init__.py +20 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/write_modes/registry.py +44 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/write_modes/sql.py +33 -0
- contractforge_databricks-0.1.0/src/contractforge_databricks/write_modes/strategy.py +192 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `contractforge-databricks` are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows Keep a Changelog, and this package follows semantic
|
|
6
|
+
versioning as described in `../../docs/specs/api-stability.md`.
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-06-08
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial public alpha release of the Databricks adapter.
|
|
13
|
+
- Databricks contract planning, SQL/artifact rendering, Asset Bundle support,
|
|
14
|
+
runtime helpers, governance, quality, evidence, lineage and operational
|
|
15
|
+
cost surfaces.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: contractforge-databricks
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Databricks adapter for ContractForge Core.
|
|
5
|
+
Project-URL: Homepage, https://github.com/marquesantero/contractforge-core/tree/main/adapters/databricks
|
|
6
|
+
Project-URL: Documentation, https://marquesantero.github.io/contractforge-core/docs/adapters/databricks
|
|
7
|
+
Project-URL: Repository, https://github.com/marquesantero/contractforge-core
|
|
8
|
+
Project-URL: Issues, https://github.com/marquesantero/contractforge-core/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/marquesantero/contractforge-core/blob/main/adapters/databricks/CHANGELOG.md
|
|
10
|
+
Author: ContractForge contributors
|
|
11
|
+
License: MIT
|
|
12
|
+
Keywords: contractforge,data-contracts,databricks,ingestion,lakehouse
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Database
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: contractforge-core<0.2,>=0.1
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# ContractForge Databricks Adapter
|
|
30
|
+
|
|
31
|
+
Databricks adapter for ContractForge.
|
|
32
|
+
|
|
33
|
+
This package depends on `contractforge-core` and translates platform-neutral
|
|
34
|
+
ingestion contracts into Databricks-native execution behavior and artifacts.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "contractforge-databricks"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Databricks adapter for ContractForge Core."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "ContractForge contributors" }]
|
|
13
|
+
keywords = ["contractforge", "databricks", "data-contracts", "ingestion", "lakehouse"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Database",
|
|
24
|
+
"Topic :: Software Development :: Libraries",
|
|
25
|
+
]
|
|
26
|
+
dependencies = ["contractforge-core>=0.1,<0.2"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/marquesantero/contractforge-core/tree/main/adapters/databricks"
|
|
30
|
+
Documentation = "https://marquesantero.github.io/contractforge-core/docs/adapters/databricks"
|
|
31
|
+
Repository = "https://github.com/marquesantero/contractforge-core"
|
|
32
|
+
Issues = "https://github.com/marquesantero/contractforge-core/issues"
|
|
33
|
+
Changelog = "https://github.com/marquesantero/contractforge-core/blob/main/adapters/databricks/CHANGELOG.md"
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
dev = ["pytest>=8"]
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
contractforge-databricks = "contractforge_databricks.cli:main"
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["src/contractforge_databricks"]
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.sdist]
|
|
45
|
+
include = ["/src/contractforge_databricks", "/README.md", "/CHANGELOG.md", "/pyproject.toml"]
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Databricks adapter package for ContractForge Core."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version as _pkg_version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = _pkg_version("contractforge-databricks")
|
|
7
|
+
except PackageNotFoundError: # pragma: no cover - editable installs without metadata
|
|
8
|
+
__version__ = "0.0.0+unknown"
|
|
9
|
+
|
|
10
|
+
from contractforge_databricks.adapter import DatabricksAdapter
|
|
11
|
+
from contractforge_databricks.api import plan_databricks_contract, render_databricks_contract
|
|
12
|
+
from contractforge_databricks.capabilities.evaluate import evaluate_databricks_capabilities
|
|
13
|
+
from contractforge_databricks.capabilities.mapping import to_core_capabilities
|
|
14
|
+
from contractforge_databricks.capabilities.models import CapabilityEvidence, DatabricksCapabilities, NativeCapability
|
|
15
|
+
from contractforge_databricks.capabilities.uc import uc_capability_issues
|
|
16
|
+
from contractforge_databricks.cost import CostModel, build_operational_cost_report, render_operational_cost_query
|
|
17
|
+
from contractforge_databricks.dashboards import render_control_dashboard_artifacts, render_control_dashboard_sql
|
|
18
|
+
from contractforge_databricks.environment import DatabricksEnvironment
|
|
19
|
+
from contractforge_databricks.bundles import render_databricks_project_bundle, render_databricks_project_bundle_yaml
|
|
20
|
+
from contractforge_databricks.governance import (
|
|
21
|
+
access_drift_report,
|
|
22
|
+
apply_access_contract,
|
|
23
|
+
apply_governance_contract,
|
|
24
|
+
check_governance_contract,
|
|
25
|
+
governance_referenced_columns,
|
|
26
|
+
render_access_sql,
|
|
27
|
+
render_governance_sql,
|
|
28
|
+
validate_governance_contract,
|
|
29
|
+
)
|
|
30
|
+
from contractforge_databricks.lakeflow import (
|
|
31
|
+
LakeflowAutoCdcArtifact,
|
|
32
|
+
LakeflowCompatibility,
|
|
33
|
+
evaluate_lakeflow_compatibility,
|
|
34
|
+
render_lakeflow_auto_cdc_artifact,
|
|
35
|
+
render_lakeflow_auto_cdc_python,
|
|
36
|
+
)
|
|
37
|
+
from contractforge_databricks.maintenance import build_control_retention_plan, execute_control_retention_plan
|
|
38
|
+
from contractforge_databricks.metrics import render_delta_history_query, resolve_write_metrics
|
|
39
|
+
from contractforge_databricks.parity import (
|
|
40
|
+
ParityMetricExpectation,
|
|
41
|
+
WriteEngineParityScenario,
|
|
42
|
+
build_write_engine_parity_plan,
|
|
43
|
+
get_write_engine_parity_scenario,
|
|
44
|
+
list_write_engine_parity_scenarios,
|
|
45
|
+
scenarios_for_engine,
|
|
46
|
+
scenarios_for_mode,
|
|
47
|
+
)
|
|
48
|
+
from contractforge_databricks.presets import apply_preset, get_preset, list_presets, preset_details, register_preset
|
|
49
|
+
from contractforge_databricks.preparation import apply_shape
|
|
50
|
+
from contractforge_databricks.quality import (
|
|
51
|
+
get_quality_rule,
|
|
52
|
+
list_quality_rules,
|
|
53
|
+
register_quality_rule,
|
|
54
|
+
unregister_quality_rule,
|
|
55
|
+
)
|
|
56
|
+
from contractforge_databricks.runtime import (
|
|
57
|
+
DatabricksIngestOptions,
|
|
58
|
+
DatabricksIngestionHooks,
|
|
59
|
+
PreparedViewInput,
|
|
60
|
+
apply_databricks_access_bundle,
|
|
61
|
+
apply_databricks_annotations_bundle,
|
|
62
|
+
apply_databricks_governance_bundle,
|
|
63
|
+
detect_databricks_capabilities,
|
|
64
|
+
deploy_databricks_bundle,
|
|
65
|
+
deploy_databricks_project,
|
|
66
|
+
get_source_resolver,
|
|
67
|
+
ingest_databricks_bundle,
|
|
68
|
+
ingest_databricks_contract,
|
|
69
|
+
list_source_resolvers,
|
|
70
|
+
register_source_resolver,
|
|
71
|
+
render_databricks_project_bundle_file,
|
|
72
|
+
resolve_source_dataframe,
|
|
73
|
+
run_available_now_stream,
|
|
74
|
+
unregister_source_resolver,
|
|
75
|
+
)
|
|
76
|
+
from contractforge_databricks.templates import (
|
|
77
|
+
contract_template_details,
|
|
78
|
+
contract_template_files,
|
|
79
|
+
get_contract_template,
|
|
80
|
+
list_contract_templates,
|
|
81
|
+
recommend_contract_templates,
|
|
82
|
+
)
|
|
83
|
+
from contractforge_databricks.write_modes.registry import (
|
|
84
|
+
get_write_mode,
|
|
85
|
+
list_write_modes,
|
|
86
|
+
register_write_mode,
|
|
87
|
+
unregister_write_mode,
|
|
88
|
+
)
|
|
89
|
+
from contractforge_databricks.write_modes.strategy import WriteStrategy, choose_write_strategy
|
|
90
|
+
|
|
91
|
+
__all__ = [
|
|
92
|
+
"CapabilityEvidence",
|
|
93
|
+
"CostModel",
|
|
94
|
+
"DatabricksAdapter",
|
|
95
|
+
"DatabricksCapabilities",
|
|
96
|
+
"DatabricksEnvironment",
|
|
97
|
+
"DatabricksIngestOptions",
|
|
98
|
+
"DatabricksIngestionHooks",
|
|
99
|
+
"LakeflowAutoCdcArtifact",
|
|
100
|
+
"LakeflowCompatibility",
|
|
101
|
+
"NativeCapability",
|
|
102
|
+
"ParityMetricExpectation",
|
|
103
|
+
"PreparedViewInput",
|
|
104
|
+
"WriteEngineParityScenario",
|
|
105
|
+
"WriteStrategy",
|
|
106
|
+
"access_drift_report",
|
|
107
|
+
"apply_access_contract",
|
|
108
|
+
"apply_databricks_access_bundle",
|
|
109
|
+
"apply_databricks_annotations_bundle",
|
|
110
|
+
"apply_databricks_governance_bundle",
|
|
111
|
+
"apply_governance_contract",
|
|
112
|
+
"apply_preset",
|
|
113
|
+
"apply_shape",
|
|
114
|
+
"build_control_retention_plan",
|
|
115
|
+
"build_operational_cost_report",
|
|
116
|
+
"build_write_engine_parity_plan",
|
|
117
|
+
"check_governance_contract",
|
|
118
|
+
"choose_write_strategy",
|
|
119
|
+
"contract_template_details",
|
|
120
|
+
"contract_template_files",
|
|
121
|
+
"detect_databricks_capabilities",
|
|
122
|
+
"deploy_databricks_bundle",
|
|
123
|
+
"deploy_databricks_project",
|
|
124
|
+
"evaluate_databricks_capabilities",
|
|
125
|
+
"evaluate_lakeflow_compatibility",
|
|
126
|
+
"execute_control_retention_plan",
|
|
127
|
+
"get_contract_template",
|
|
128
|
+
"get_preset",
|
|
129
|
+
"get_quality_rule",
|
|
130
|
+
"get_source_resolver",
|
|
131
|
+
"get_write_engine_parity_scenario",
|
|
132
|
+
"get_write_mode",
|
|
133
|
+
"governance_referenced_columns",
|
|
134
|
+
"ingest_databricks_bundle",
|
|
135
|
+
"ingest_databricks_contract",
|
|
136
|
+
"list_contract_templates",
|
|
137
|
+
"list_presets",
|
|
138
|
+
"list_quality_rules",
|
|
139
|
+
"list_source_resolvers",
|
|
140
|
+
"list_write_engine_parity_scenarios",
|
|
141
|
+
"list_write_modes",
|
|
142
|
+
"plan_databricks_contract",
|
|
143
|
+
"preset_details",
|
|
144
|
+
"recommend_contract_templates",
|
|
145
|
+
"register_preset",
|
|
146
|
+
"register_quality_rule",
|
|
147
|
+
"register_source_resolver",
|
|
148
|
+
"register_write_mode",
|
|
149
|
+
"render_access_sql",
|
|
150
|
+
"render_control_dashboard_artifacts",
|
|
151
|
+
"render_control_dashboard_sql",
|
|
152
|
+
"render_databricks_contract",
|
|
153
|
+
"render_databricks_project_bundle",
|
|
154
|
+
"render_databricks_project_bundle_file",
|
|
155
|
+
"render_databricks_project_bundle_yaml",
|
|
156
|
+
"render_delta_history_query",
|
|
157
|
+
"render_governance_sql",
|
|
158
|
+
"render_lakeflow_auto_cdc_artifact",
|
|
159
|
+
"render_lakeflow_auto_cdc_python",
|
|
160
|
+
"render_operational_cost_query",
|
|
161
|
+
"resolve_source_dataframe",
|
|
162
|
+
"resolve_write_metrics",
|
|
163
|
+
"run_available_now_stream",
|
|
164
|
+
"scenarios_for_engine",
|
|
165
|
+
"scenarios_for_mode",
|
|
166
|
+
"to_core_capabilities",
|
|
167
|
+
"uc_capability_issues",
|
|
168
|
+
"unregister_source_resolver",
|
|
169
|
+
"unregister_quality_rule",
|
|
170
|
+
"unregister_write_mode",
|
|
171
|
+
"validate_governance_contract",
|
|
172
|
+
]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""ContractForge Core adapter implementation for Databricks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from contractforge_core.adapters import RenderedArtifacts
|
|
9
|
+
from contractforge_core.capabilities import PlatformCapabilities
|
|
10
|
+
from contractforge_core.planner import ExecutionPlan, PlanningResult, plan_contract
|
|
11
|
+
from contractforge_core.semantic import SemanticContract
|
|
12
|
+
from contractforge_databricks.capabilities import DatabricksCapabilities, evaluate_databricks_capabilities, to_core_capabilities
|
|
13
|
+
from contractforge_databricks.contract_extensions import databricks_extension_warnings
|
|
14
|
+
from contractforge_databricks.environment import DatabricksEnvironment
|
|
15
|
+
from contractforge_databricks.rendering import render_databricks_artifacts
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class DatabricksAdapter:
|
|
20
|
+
"""Dry-planning Databricks adapter.
|
|
21
|
+
|
|
22
|
+
Execution belongs in a later runtime module. This adapter only declares
|
|
23
|
+
capabilities, plans via the core, and renders reviewable native artifacts.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
native_capabilities: DatabricksCapabilities
|
|
27
|
+
environment: DatabricksEnvironment = DatabricksEnvironment()
|
|
28
|
+
name: str = "databricks"
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def from_evidence(
|
|
32
|
+
cls,
|
|
33
|
+
*,
|
|
34
|
+
target_table: str | None = None,
|
|
35
|
+
runtime_type: str | None = None,
|
|
36
|
+
spark_version: str | None = None,
|
|
37
|
+
spark_conf: dict[str, str] | None = None,
|
|
38
|
+
environment: dict[str, Any] | None = None,
|
|
39
|
+
) -> "DatabricksAdapter":
|
|
40
|
+
env = DatabricksEnvironment.from_contract(environment)
|
|
41
|
+
return cls(
|
|
42
|
+
evaluate_databricks_capabilities(
|
|
43
|
+
target_table=target_table,
|
|
44
|
+
runtime_type=runtime_type or env.runtime_kind,
|
|
45
|
+
spark_version=spark_version,
|
|
46
|
+
spark_conf=spark_conf,
|
|
47
|
+
),
|
|
48
|
+
environment=env,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def capabilities(self) -> PlatformCapabilities:
|
|
52
|
+
return to_core_capabilities(self.native_capabilities)
|
|
53
|
+
|
|
54
|
+
def plan(self, contract: SemanticContract) -> PlanningResult:
|
|
55
|
+
result = plan_contract(contract, self.capabilities())
|
|
56
|
+
extension_warnings = databricks_extension_warnings(contract)
|
|
57
|
+
if not extension_warnings:
|
|
58
|
+
return result
|
|
59
|
+
warnings = result.warnings + extension_warnings
|
|
60
|
+
if result.status == "SUPPORTED":
|
|
61
|
+
return PlanningResult(status="SUPPORTED_WITH_WARNINGS", plan=result.plan, blockers=result.blockers, warnings=warnings)
|
|
62
|
+
return PlanningResult(status=result.status, plan=result.plan, blockers=result.blockers, warnings=warnings)
|
|
63
|
+
|
|
64
|
+
def render(self, plan: ExecutionPlan) -> RenderedArtifacts:
|
|
65
|
+
raise NotImplementedError("Use render_contract(contract) so Databricks artifacts include contract context.")
|
|
66
|
+
|
|
67
|
+
def render_contract(self, contract: SemanticContract) -> RenderedArtifacts:
|
|
68
|
+
planning = self.plan(contract)
|
|
69
|
+
return render_databricks_artifacts(contract, planning, self.native_capabilities, environment=self.environment)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from contractforge_databricks.annotations.application import apply_annotations_contract
|
|
2
|
+
from contractforge_databricks.annotations.audit import render_annotations_audit_insert_sql
|
|
3
|
+
from contractforge_databricks.annotations.sql import annotation_steps, render_annotations_sql
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"annotation_steps",
|
|
7
|
+
"apply_annotations_contract",
|
|
8
|
+
"render_annotations_audit_insert_sql",
|
|
9
|
+
"render_annotations_sql",
|
|
10
|
+
]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Apply Databricks annotations with an injected SQL runner."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from contractforge_core.semantic import SemanticContract
|
|
6
|
+
from contractforge_core.results import GovernanceApplyResult
|
|
7
|
+
from contractforge_databricks.annotations.sql import annotation_steps
|
|
8
|
+
from contractforge_databricks.execution.sql_merge import SqlRunner
|
|
9
|
+
from contractforge_databricks.security import exception_message
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def apply_annotations_contract(*, runner: SqlRunner, contract: SemanticContract) -> GovernanceApplyResult:
|
|
13
|
+
steps = annotation_steps(contract)
|
|
14
|
+
if not steps:
|
|
15
|
+
return GovernanceApplyResult(status="NOT_CONFIGURED")
|
|
16
|
+
policy = _policy(contract)
|
|
17
|
+
sql_preview = tuple(str(step["sql"]) for step in steps)
|
|
18
|
+
if policy == "ignore":
|
|
19
|
+
return GovernanceApplyResult(status="IGNORED", ignored=len(steps), sql_preview=sql_preview)
|
|
20
|
+
|
|
21
|
+
applied = 0
|
|
22
|
+
errors: list[str] = []
|
|
23
|
+
for statement in sql_preview:
|
|
24
|
+
try:
|
|
25
|
+
runner.sql(statement)
|
|
26
|
+
applied += 1
|
|
27
|
+
except Exception as exc:
|
|
28
|
+
errors.append(exception_message(exc))
|
|
29
|
+
if policy == "fail":
|
|
30
|
+
return GovernanceApplyResult(
|
|
31
|
+
status="FAILED",
|
|
32
|
+
applied=applied,
|
|
33
|
+
failed=len(errors),
|
|
34
|
+
sql_preview=sql_preview,
|
|
35
|
+
errors=tuple(errors),
|
|
36
|
+
)
|
|
37
|
+
if errors:
|
|
38
|
+
return GovernanceApplyResult(
|
|
39
|
+
status="WARNED",
|
|
40
|
+
applied=applied,
|
|
41
|
+
failed=len(errors),
|
|
42
|
+
sql_preview=sql_preview,
|
|
43
|
+
errors=tuple(errors),
|
|
44
|
+
)
|
|
45
|
+
return GovernanceApplyResult(status="SUCCESS", applied=applied, sql_preview=sql_preview)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _policy(contract: SemanticContract) -> str:
|
|
49
|
+
annotations = contract.governance.annotations if contract.governance else None
|
|
50
|
+
if isinstance(annotations, dict):
|
|
51
|
+
return str(annotations.get("policy", "warn"))
|
|
52
|
+
return "warn"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Render annotation audit SQL for Databricks evidence tables."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
from contractforge_core.semantic import SemanticContract
|
|
8
|
+
from contractforge_databricks.annotations.sql import annotation_steps
|
|
9
|
+
from contractforge_databricks.evidence.tables import evidence_table_names
|
|
10
|
+
from contractforge_databricks.rendering.names import target_full_name
|
|
11
|
+
from contractforge_databricks.sql import quote_table_name, sql_string
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def render_annotations_audit_insert_sql(
|
|
15
|
+
contract: SemanticContract,
|
|
16
|
+
*,
|
|
17
|
+
run_id: str = "${run_id}",
|
|
18
|
+
status: str = "PLANNED",
|
|
19
|
+
captured_at_utc: datetime | None = None,
|
|
20
|
+
catalog: str = "main",
|
|
21
|
+
schema: str = "ops",
|
|
22
|
+
) -> str:
|
|
23
|
+
steps = annotation_steps(contract)
|
|
24
|
+
if not steps:
|
|
25
|
+
return "-- No annotations intent declared.\n"
|
|
26
|
+
table = evidence_table_names(catalog, schema)["annotations"]
|
|
27
|
+
captured_at_utc = captured_at_utc or datetime(1970, 1, 1, 0, 0, 0)
|
|
28
|
+
statements = [
|
|
29
|
+
_audit_insert(table, run_id, target_full_name(contract), step, status, captured_at_utc)
|
|
30
|
+
for step in steps
|
|
31
|
+
]
|
|
32
|
+
return ";\n".join(statements) + ";\n"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _audit_insert(table: str, run_id: str, target: str, step: dict[str, object], status: str, captured_at_utc: datetime) -> str:
|
|
36
|
+
columns = "run_id, target_table, annotation_scope, annotation_type, column_name, key, value, status, applied_sql, annotation_ts_utc"
|
|
37
|
+
values = [
|
|
38
|
+
sql_string(run_id),
|
|
39
|
+
sql_string(target),
|
|
40
|
+
sql_string(step.get("annotation_scope")),
|
|
41
|
+
sql_string(step.get("annotation_type")),
|
|
42
|
+
sql_string(step.get("column_name")),
|
|
43
|
+
sql_string(step.get("key")),
|
|
44
|
+
sql_string(step.get("value")),
|
|
45
|
+
sql_string(status),
|
|
46
|
+
sql_string(step.get("sql")),
|
|
47
|
+
f"TIMESTAMP {sql_string(captured_at_utc.strftime('%Y-%m-%d %H:%M:%S'))}",
|
|
48
|
+
]
|
|
49
|
+
return f"INSERT INTO {quote_table_name(table)} ({columns}) VALUES ({', '.join(values)})"
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Render Unity Catalog annotations SQL."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from contractforge_core.semantic import SemanticContract
|
|
8
|
+
from contractforge_databricks.coercion import mapping, string_list, string_map
|
|
9
|
+
from contractforge_databricks.rendering.names import target_full_name
|
|
10
|
+
from contractforge_databricks.sql import quote_identifier, quote_table_name, sql_string
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def annotation_steps(contract: SemanticContract) -> list[dict[str, Any]]:
|
|
14
|
+
annotations = contract.governance.annotations if contract.governance else None
|
|
15
|
+
if not isinstance(annotations, dict):
|
|
16
|
+
return []
|
|
17
|
+
|
|
18
|
+
target = target_full_name(contract)
|
|
19
|
+
quoted_target = quote_table_name(target)
|
|
20
|
+
steps: list[dict[str, Any]] = []
|
|
21
|
+
table = mapping(annotations.get("table"))
|
|
22
|
+
if table.get("description"):
|
|
23
|
+
steps.append(
|
|
24
|
+
{
|
|
25
|
+
"annotation_scope": "table",
|
|
26
|
+
"annotation_type": "description",
|
|
27
|
+
"column_name": None,
|
|
28
|
+
"key": "description",
|
|
29
|
+
"value": str(table["description"]),
|
|
30
|
+
"sql": f"COMMENT ON TABLE {quoted_target} IS {sql_string(table['description'])}",
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
_append_tag_step(steps, quoted_target, None, _table_tags(table))
|
|
34
|
+
for column, config in mapping(annotations.get("columns")).items():
|
|
35
|
+
_append_column_steps(steps, quoted_target, str(column), mapping(config))
|
|
36
|
+
return steps
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def render_annotations_sql(contract: SemanticContract) -> str:
|
|
40
|
+
annotations = contract.governance.annotations if contract.governance else None
|
|
41
|
+
if not isinstance(annotations, dict):
|
|
42
|
+
return "-- No annotations intent declared.\n"
|
|
43
|
+
|
|
44
|
+
target = target_full_name(contract)
|
|
45
|
+
lines = [
|
|
46
|
+
"-- Review before execution. Unity Catalog tags require UC-enabled targets.",
|
|
47
|
+
f"-- Target: {target}",
|
|
48
|
+
"",
|
|
49
|
+
]
|
|
50
|
+
lines.extend(f"{step['sql']};" for step in annotation_steps(contract))
|
|
51
|
+
return "\n".join(lines) + "\n"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _append_column_steps(
|
|
55
|
+
steps: list[dict[str, Any]],
|
|
56
|
+
quoted_target: str,
|
|
57
|
+
column: str,
|
|
58
|
+
config: dict[str, Any],
|
|
59
|
+
) -> None:
|
|
60
|
+
quoted_column = quote_identifier(column)
|
|
61
|
+
if config.get("description"):
|
|
62
|
+
steps.append(
|
|
63
|
+
{
|
|
64
|
+
"annotation_scope": "column",
|
|
65
|
+
"annotation_type": "description",
|
|
66
|
+
"column_name": column,
|
|
67
|
+
"key": "description",
|
|
68
|
+
"value": str(config["description"]),
|
|
69
|
+
"sql": f"ALTER TABLE {quoted_target} ALTER COLUMN {quoted_column} COMMENT {sql_string(config['description'])}",
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
_append_tag_step(steps, quoted_target, column, _column_tags(config))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _append_tag_step(steps: list[dict[str, Any]], quoted_target: str, column: str | None, tags: dict[str, str]) -> None:
|
|
76
|
+
if tags:
|
|
77
|
+
sql = f"ALTER TABLE {quoted_target} SET TAGS ({_tag_sql(tags)})"
|
|
78
|
+
if column is not None:
|
|
79
|
+
sql = f"ALTER TABLE {quoted_target} ALTER COLUMN {quote_identifier(column)} SET TAGS ({_tag_sql(tags)})"
|
|
80
|
+
steps.append(
|
|
81
|
+
{
|
|
82
|
+
"annotation_scope": "column" if column else "table",
|
|
83
|
+
"annotation_type": "tags",
|
|
84
|
+
"column_name": column,
|
|
85
|
+
"key": "tags",
|
|
86
|
+
"value": _json(tags),
|
|
87
|
+
"sql": sql,
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _table_tags(table: dict[str, Any]) -> dict[str, str]:
|
|
93
|
+
return {
|
|
94
|
+
**string_map(table.get("tags")),
|
|
95
|
+
**_alias_tags(table.get("aliases")),
|
|
96
|
+
**_deprecated_tags(table.get("deprecated")),
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _column_tags(config: dict[str, Any]) -> dict[str, str]:
|
|
101
|
+
return {
|
|
102
|
+
**string_map(config.get("tags")),
|
|
103
|
+
**_alias_tags(config.get("aliases")),
|
|
104
|
+
**_pii_tags(config.get("pii")),
|
|
105
|
+
**_deprecated_tags(config.get("deprecated")),
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _alias_tags(value: object) -> dict[str, str]:
|
|
110
|
+
return {f"alias_{idx}": alias for idx, alias in enumerate(string_list(value, sep="|"), start=1)}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _deprecated_tags(value: object) -> dict[str, str]:
|
|
114
|
+
deprecated = mapping(value)
|
|
115
|
+
if not deprecated:
|
|
116
|
+
return {}
|
|
117
|
+
tags = {"deprecated": "true"}
|
|
118
|
+
for key in ("since", "replacement", "removal_date"):
|
|
119
|
+
if deprecated.get(key):
|
|
120
|
+
tags[f"deprecated_{key}"] = str(deprecated[key])
|
|
121
|
+
return tags
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _pii_tags(value: object) -> dict[str, str]:
|
|
125
|
+
pii = mapping(value)
|
|
126
|
+
if not pii:
|
|
127
|
+
return {}
|
|
128
|
+
return {
|
|
129
|
+
"pii": str(pii.get("enabled", True)).lower(),
|
|
130
|
+
"pii_type": str(pii.get("type", "unknown")),
|
|
131
|
+
"sensitivity": str(pii.get("sensitivity", "internal")),
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _tag_sql(tags: dict[str, str]) -> str:
|
|
136
|
+
return ", ".join(f"{sql_string(key)} = {sql_string(value)}" for key, value in tags.items())
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _json(value: dict[str, str]) -> str:
|
|
140
|
+
import json
|
|
141
|
+
|
|
142
|
+
return json.dumps(value, sort_keys=True, separators=(",", ":"))
|