table-validator 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.
- table_validator-0.1.0/LICENSE +21 -0
- table_validator-0.1.0/PKG-INFO +190 -0
- table_validator-0.1.0/README.md +163 -0
- table_validator-0.1.0/pyproject.toml +44 -0
- table_validator-0.1.0/setup.cfg +4 -0
- table_validator-0.1.0/table_validator/__init__.py +46 -0
- table_validator-0.1.0/table_validator/auth/__init__.py +1 -0
- table_validator-0.1.0/table_validator/auth/azure_auth.py +52 -0
- table_validator-0.1.0/table_validator/auth/databricks_auth.py +31 -0
- table_validator-0.1.0/table_validator/cli/__init__.py +1 -0
- table_validator-0.1.0/table_validator/cli/main.py +722 -0
- table_validator-0.1.0/table_validator/cli/partition_prompt.py +78 -0
- table_validator-0.1.0/table_validator/cli/summary_table.py +146 -0
- table_validator-0.1.0/table_validator/cli/wizard.py +429 -0
- table_validator-0.1.0/table_validator/config/__init__.py +1 -0
- table_validator-0.1.0/table_validator/config/manager.py +84 -0
- table_validator-0.1.0/table_validator/config/schema.py +179 -0
- table_validator-0.1.0/table_validator/connectors/__init__.py +1 -0
- table_validator-0.1.0/table_validator/connectors/azure_connector.py +809 -0
- table_validator-0.1.0/table_validator/connectors/databricks_connector.py +1230 -0
- table_validator-0.1.0/table_validator/engine/__init__.py +1 -0
- table_validator-0.1.0/table_validator/engine/comparison_engine.py +645 -0
- table_validator-0.1.0/table_validator/models.py +952 -0
- table_validator-0.1.0/table_validator/reports/__init__.py +1 -0
- table_validator-0.1.0/table_validator/reports/excel_report.py +953 -0
- table_validator-0.1.0/table_validator/validators/__init__.py +1 -0
- table_validator-0.1.0/table_validator/validators/blob_discovery.py +467 -0
- table_validator-0.1.0/table_validator/validators/catalog_validator.py +1863 -0
- table_validator-0.1.0/table_validator/validators/row_validator.py +1727 -0
- table_validator-0.1.0/table_validator.egg-info/PKG-INFO +190 -0
- table_validator-0.1.0/table_validator.egg-info/SOURCES.txt +45 -0
- table_validator-0.1.0/table_validator.egg-info/dependency_links.txt +1 -0
- table_validator-0.1.0/table_validator.egg-info/entry_points.txt +2 -0
- table_validator-0.1.0/table_validator.egg-info/requires.txt +18 -0
- table_validator-0.1.0/table_validator.egg-info/scm_file_list.json +41 -0
- table_validator-0.1.0/table_validator.egg-info/scm_version.json +8 -0
- table_validator-0.1.0/table_validator.egg-info/top_level.txt +1 -0
- table_validator-0.1.0/tests/__init__.py +0 -0
- table_validator-0.1.0/tests/test_blob_discovery.py +404 -0
- table_validator-0.1.0/tests/test_catalog_validator.py +1398 -0
- table_validator-0.1.0/tests/test_cli.py +1086 -0
- table_validator-0.1.0/tests/test_databricks_connector.py +404 -0
- table_validator-0.1.0/tests/test_excel_report.py +417 -0
- table_validator-0.1.0/tests/test_partition_prompt.py +63 -0
- table_validator-0.1.0/tests/test_report_command.py +152 -0
- table_validator-0.1.0/tests/test_row_validator.py +274 -0
- table_validator-0.1.0/tests/test_wizard.py +504 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mourya S
|
|
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.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: table-validator
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI tool for validating data migrations between Azure (Blob Storage / SQL Database) and Databricks Delta Lake catalogs
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: typer>=0.12
|
|
10
|
+
Requires-Dist: rich>=13.0
|
|
11
|
+
Requires-Dist: questionary>=2.0
|
|
12
|
+
Requires-Dist: pydantic>=2.0
|
|
13
|
+
Requires-Dist: pyodbc>=4.0
|
|
14
|
+
Requires-Dist: databricks-sql-connector>=3.0
|
|
15
|
+
Requires-Dist: pandas>=2.0
|
|
16
|
+
Requires-Dist: numpy>=1.24
|
|
17
|
+
Requires-Dist: azure-storage-blob>=12.14
|
|
18
|
+
Requires-Dist: openpyxl>=3.1
|
|
19
|
+
Requires-Dist: pyarrow>=14.0
|
|
20
|
+
Requires-Dist: PyYAML>=6.0
|
|
21
|
+
Requires-Dist: python-dotenv>=1.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
24
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
25
|
+
Requires-Dist: black>=24.0; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# table-validator
|
|
29
|
+
|
|
30
|
+
Cross-platform data migration validator. Compares a source table against a
|
|
31
|
+
target Databricks table/catalog and reports whether the migration is
|
|
32
|
+
correct: matching schema, row counts, column statistics, and (where a
|
|
33
|
+
difference is found) the exact row/column that changed. Produces a
|
|
34
|
+
multi-sheet Excel report and a pass/fail summary.
|
|
35
|
+
|
|
36
|
+
Currently supported sources (target is always Databricks):
|
|
37
|
+
|
|
38
|
+
- Databricks catalog → Databricks catalog
|
|
39
|
+
- Azure Blob Storage (CSV / Excel / Parquet) → Databricks table
|
|
40
|
+
- Azure SQL Database → Databricks catalog
|
|
41
|
+
|
|
42
|
+
More source platforms can be added behind the same connector/validator
|
|
43
|
+
interfaces described below.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install table-validator
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
From a local checkout (the directory containing `pyproject.toml`):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For local development (editable install, so code changes take effect
|
|
58
|
+
without reinstalling):
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install -e ".[dev]"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Either way, this installs the `tablevalidator` command on your PATH.
|
|
65
|
+
|
|
66
|
+
## CLI usage
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
tablevalidator info
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Prints what the tool does and the commands below, in the order you'd
|
|
73
|
+
normally run them.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
tablevalidator configure
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Interactive wizard that walks you through:
|
|
80
|
+
|
|
81
|
+
1. Azure Storage account + container (optional, skip if you don't have a Blob source) and account key
|
|
82
|
+
2. Azure SQL server + database (optional, skip if you don't have a SQL source) and username/password
|
|
83
|
+
3. Databricks workspace URL, SQL Warehouse HTTP path, and personal access token
|
|
84
|
+
4. Source table (catalog / schema / table)
|
|
85
|
+
5. Target table (catalog / schema / table)
|
|
86
|
+
6. Which validations to run (catalog / schema / column / row)
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
tablevalidator validate
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Runs the comparison using the saved configuration and writes
|
|
93
|
+
`validation_report.xlsx` in the current directory, printing a pass/fail
|
|
94
|
+
summary to the console. Exit code is `0` if the overall result is PASS,
|
|
95
|
+
non-zero otherwise (useful in CI). Useful flags:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
tablevalidator validate --config-path /path/to/config.yaml --output /path/to/report.xlsx
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
tablevalidator open
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Opens the most recently generated report in your default spreadsheet app.
|
|
106
|
+
|
|
107
|
+
## Quickstart (Python API)
|
|
108
|
+
|
|
109
|
+
Everything the CLI does is available as a library, built from the same
|
|
110
|
+
public API exported by `table_validator/__init__.py`:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from table_validator import (
|
|
114
|
+
load_config,
|
|
115
|
+
CatalogValidator,
|
|
116
|
+
CatalogValidationRequest,
|
|
117
|
+
DatabricksConnector,
|
|
118
|
+
)
|
|
119
|
+
from table_validator.auth.databricks_auth import get_databricks_token
|
|
120
|
+
|
|
121
|
+
# Non-secret settings from ~/.table_validator/config.yaml
|
|
122
|
+
# (see `tablevalidator configure`); secrets from ~/.table_validator/.env.
|
|
123
|
+
config = load_config()
|
|
124
|
+
token = get_databricks_token(config)
|
|
125
|
+
|
|
126
|
+
# DatabricksConnector wants a bare hostname, not the full workspace URL
|
|
127
|
+
host = config.databricks.workspace_url.replace("https://", "").split("/")[0]
|
|
128
|
+
|
|
129
|
+
databricks = DatabricksConnector(
|
|
130
|
+
host=host,
|
|
131
|
+
token=token,
|
|
132
|
+
http_path=config.databricks.http_path,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
validator = CatalogValidator(databricks)
|
|
136
|
+
|
|
137
|
+
request = CatalogValidationRequest(
|
|
138
|
+
source_catalog="source_catalog_name",
|
|
139
|
+
target_catalog="target_catalog_name",
|
|
140
|
+
schemas=["sales"], # optional: restrict scope
|
|
141
|
+
primary_keys={"sales.orders": ["order_id"]}, # optional: enables row-level diffing
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
result = validator.compare_catalogs(request)
|
|
145
|
+
|
|
146
|
+
print(result.status) # PASS / FAIL / ERROR / SKIPPED
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Other public entry points exported from `table_validator`:
|
|
150
|
+
|
|
151
|
+
- `AzureCsvValidator` / `AzureSqlValidator` — the Blob-CSV and Azure-SQL
|
|
152
|
+
equivalents of `CatalogValidator`, returning the same
|
|
153
|
+
`CatalogValidationResponse` shape.
|
|
154
|
+
- `BlobCatalogValidator` — validates every file in an Azure Blob container
|
|
155
|
+
against like-named Databricks tables.
|
|
156
|
+
- `AzureConnector` / `AzureSqlConnector` — the Azure-side connectors, for
|
|
157
|
+
building your own validation flow against a connector directly.
|
|
158
|
+
- `ValidatorConfig`, `default_config`, `save_config`, `require_config`,
|
|
159
|
+
`ConfigNotFoundError` — the same config load/save layer the CLI wizard
|
|
160
|
+
uses, if you want to construct or persist configuration programmatically.
|
|
161
|
+
|
|
162
|
+
## Where config and secrets are stored
|
|
163
|
+
|
|
164
|
+
Everything lives outside the repo, under your home directory:
|
|
165
|
+
|
|
166
|
+
- `~/.table_validator/config.yaml` — non-secret configuration (table
|
|
167
|
+
references, workspace URL, which validations are enabled). Safe to
|
|
168
|
+
inspect or version-control separately if you want.
|
|
169
|
+
- `~/.table_validator/.env` — credentials (Azure Storage key, Azure SQL
|
|
170
|
+
username/password, Databricks personal access token), written in
|
|
171
|
+
plaintext and restricted to owner read/write only (`chmod 600`,
|
|
172
|
+
best-effort on Windows since NTFS doesn't map POSIX permission bits).
|
|
173
|
+
**Never commit this file or add it inside the project repo** — it isn't,
|
|
174
|
+
by construction, since it's written under your home directory rather
|
|
175
|
+
than the working directory.
|
|
176
|
+
|
|
177
|
+
A future version will replace manual credential entry with Azure CLI /
|
|
178
|
+
Service Principal auth and Databricks CLI / OAuth login, without changing
|
|
179
|
+
the config file format or any command usage above.
|
|
180
|
+
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
pip install -e ".[dev]"
|
|
185
|
+
pytest
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# table-validator
|
|
2
|
+
|
|
3
|
+
Cross-platform data migration validator. Compares a source table against a
|
|
4
|
+
target Databricks table/catalog and reports whether the migration is
|
|
5
|
+
correct: matching schema, row counts, column statistics, and (where a
|
|
6
|
+
difference is found) the exact row/column that changed. Produces a
|
|
7
|
+
multi-sheet Excel report and a pass/fail summary.
|
|
8
|
+
|
|
9
|
+
Currently supported sources (target is always Databricks):
|
|
10
|
+
|
|
11
|
+
- Databricks catalog → Databricks catalog
|
|
12
|
+
- Azure Blob Storage (CSV / Excel / Parquet) → Databricks table
|
|
13
|
+
- Azure SQL Database → Databricks catalog
|
|
14
|
+
|
|
15
|
+
More source platforms can be added behind the same connector/validator
|
|
16
|
+
interfaces described below.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install table-validator
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
From a local checkout (the directory containing `pyproject.toml`):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install .
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For local development (editable install, so code changes take effect
|
|
31
|
+
without reinstalling):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install -e ".[dev]"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Either way, this installs the `tablevalidator` command on your PATH.
|
|
38
|
+
|
|
39
|
+
## CLI usage
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
tablevalidator info
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Prints what the tool does and the commands below, in the order you'd
|
|
46
|
+
normally run them.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
tablevalidator configure
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Interactive wizard that walks you through:
|
|
53
|
+
|
|
54
|
+
1. Azure Storage account + container (optional, skip if you don't have a Blob source) and account key
|
|
55
|
+
2. Azure SQL server + database (optional, skip if you don't have a SQL source) and username/password
|
|
56
|
+
3. Databricks workspace URL, SQL Warehouse HTTP path, and personal access token
|
|
57
|
+
4. Source table (catalog / schema / table)
|
|
58
|
+
5. Target table (catalog / schema / table)
|
|
59
|
+
6. Which validations to run (catalog / schema / column / row)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
tablevalidator validate
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Runs the comparison using the saved configuration and writes
|
|
66
|
+
`validation_report.xlsx` in the current directory, printing a pass/fail
|
|
67
|
+
summary to the console. Exit code is `0` if the overall result is PASS,
|
|
68
|
+
non-zero otherwise (useful in CI). Useful flags:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
tablevalidator validate --config-path /path/to/config.yaml --output /path/to/report.xlsx
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
tablevalidator open
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Opens the most recently generated report in your default spreadsheet app.
|
|
79
|
+
|
|
80
|
+
## Quickstart (Python API)
|
|
81
|
+
|
|
82
|
+
Everything the CLI does is available as a library, built from the same
|
|
83
|
+
public API exported by `table_validator/__init__.py`:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from table_validator import (
|
|
87
|
+
load_config,
|
|
88
|
+
CatalogValidator,
|
|
89
|
+
CatalogValidationRequest,
|
|
90
|
+
DatabricksConnector,
|
|
91
|
+
)
|
|
92
|
+
from table_validator.auth.databricks_auth import get_databricks_token
|
|
93
|
+
|
|
94
|
+
# Non-secret settings from ~/.table_validator/config.yaml
|
|
95
|
+
# (see `tablevalidator configure`); secrets from ~/.table_validator/.env.
|
|
96
|
+
config = load_config()
|
|
97
|
+
token = get_databricks_token(config)
|
|
98
|
+
|
|
99
|
+
# DatabricksConnector wants a bare hostname, not the full workspace URL
|
|
100
|
+
host = config.databricks.workspace_url.replace("https://", "").split("/")[0]
|
|
101
|
+
|
|
102
|
+
databricks = DatabricksConnector(
|
|
103
|
+
host=host,
|
|
104
|
+
token=token,
|
|
105
|
+
http_path=config.databricks.http_path,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
validator = CatalogValidator(databricks)
|
|
109
|
+
|
|
110
|
+
request = CatalogValidationRequest(
|
|
111
|
+
source_catalog="source_catalog_name",
|
|
112
|
+
target_catalog="target_catalog_name",
|
|
113
|
+
schemas=["sales"], # optional: restrict scope
|
|
114
|
+
primary_keys={"sales.orders": ["order_id"]}, # optional: enables row-level diffing
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
result = validator.compare_catalogs(request)
|
|
118
|
+
|
|
119
|
+
print(result.status) # PASS / FAIL / ERROR / SKIPPED
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Other public entry points exported from `table_validator`:
|
|
123
|
+
|
|
124
|
+
- `AzureCsvValidator` / `AzureSqlValidator` — the Blob-CSV and Azure-SQL
|
|
125
|
+
equivalents of `CatalogValidator`, returning the same
|
|
126
|
+
`CatalogValidationResponse` shape.
|
|
127
|
+
- `BlobCatalogValidator` — validates every file in an Azure Blob container
|
|
128
|
+
against like-named Databricks tables.
|
|
129
|
+
- `AzureConnector` / `AzureSqlConnector` — the Azure-side connectors, for
|
|
130
|
+
building your own validation flow against a connector directly.
|
|
131
|
+
- `ValidatorConfig`, `default_config`, `save_config`, `require_config`,
|
|
132
|
+
`ConfigNotFoundError` — the same config load/save layer the CLI wizard
|
|
133
|
+
uses, if you want to construct or persist configuration programmatically.
|
|
134
|
+
|
|
135
|
+
## Where config and secrets are stored
|
|
136
|
+
|
|
137
|
+
Everything lives outside the repo, under your home directory:
|
|
138
|
+
|
|
139
|
+
- `~/.table_validator/config.yaml` — non-secret configuration (table
|
|
140
|
+
references, workspace URL, which validations are enabled). Safe to
|
|
141
|
+
inspect or version-control separately if you want.
|
|
142
|
+
- `~/.table_validator/.env` — credentials (Azure Storage key, Azure SQL
|
|
143
|
+
username/password, Databricks personal access token), written in
|
|
144
|
+
plaintext and restricted to owner read/write only (`chmod 600`,
|
|
145
|
+
best-effort on Windows since NTFS doesn't map POSIX permission bits).
|
|
146
|
+
**Never commit this file or add it inside the project repo** — it isn't,
|
|
147
|
+
by construction, since it's written under your home directory rather
|
|
148
|
+
than the working directory.
|
|
149
|
+
|
|
150
|
+
A future version will replace manual credential entry with Azure CLI /
|
|
151
|
+
Service Principal auth and Databricks CLI / OAuth login, without changing
|
|
152
|
+
the config file format or any command usage above.
|
|
153
|
+
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
pip install -e ".[dev]"
|
|
158
|
+
pytest
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "setuptools_scm>=8"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "table-validator"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "CLI tool for validating data migrations between Azure (Blob Storage / SQL Database) and Databricks Delta Lake catalogs"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
dependencies = [
|
|
13
|
+
"typer>=0.12",
|
|
14
|
+
"rich>=13.0",
|
|
15
|
+
"questionary>=2.0",
|
|
16
|
+
"pydantic>=2.0",
|
|
17
|
+
"pyodbc>=4.0",
|
|
18
|
+
"databricks-sql-connector>=3.0",
|
|
19
|
+
"pandas>=2.0",
|
|
20
|
+
"numpy>=1.24",
|
|
21
|
+
"azure-storage-blob>=12.14",
|
|
22
|
+
"openpyxl>=3.1",
|
|
23
|
+
"pyarrow>=14.0",
|
|
24
|
+
"PyYAML>=6.0",
|
|
25
|
+
"python-dotenv>=1.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
dev = [
|
|
30
|
+
"pytest>=7.0",
|
|
31
|
+
"ruff>=0.4",
|
|
32
|
+
"black>=24.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.scripts]
|
|
36
|
+
tablevalidator = "table_validator.cli.main:app"
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.packages.find]
|
|
39
|
+
include = ["table_validator", "table_validator.*"]
|
|
40
|
+
|
|
41
|
+
[tool.setuptools_scm]
|
|
42
|
+
root = ".."
|
|
43
|
+
tag_regex = "^v(?P<version>\\d+\\.\\d+\\.\\d+)$"
|
|
44
|
+
fallback_version = "0.0.0"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""table_validator: validates data migrations between Azure and Databricks Delta Lake."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("table-validator")
|
|
7
|
+
except PackageNotFoundError:
|
|
8
|
+
__version__ = "0.0.0"
|
|
9
|
+
|
|
10
|
+
from table_validator.config.manager import (
|
|
11
|
+
ConfigNotFoundError,
|
|
12
|
+
default_config,
|
|
13
|
+
load_config,
|
|
14
|
+
require_config,
|
|
15
|
+
save_config,
|
|
16
|
+
)
|
|
17
|
+
from table_validator.config.schema import ValidatorConfig
|
|
18
|
+
from table_validator.connectors.azure_connector import AzureConnector, AzureSqlConnector
|
|
19
|
+
from table_validator.connectors.databricks_connector import DatabricksConnector
|
|
20
|
+
from table_validator.models import CatalogValidationRequest, CatalogValidationResponse
|
|
21
|
+
from table_validator.validators.blob_discovery import BlobCatalogValidator
|
|
22
|
+
from table_validator.validators.catalog_validator import CatalogValidator
|
|
23
|
+
from table_validator.validators.row_validator import AzureCsvValidator, AzureSqlValidator
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"__version__",
|
|
27
|
+
# Validators
|
|
28
|
+
"CatalogValidator",
|
|
29
|
+
"AzureCsvValidator",
|
|
30
|
+
"AzureSqlValidator",
|
|
31
|
+
"BlobCatalogValidator",
|
|
32
|
+
# Connectors
|
|
33
|
+
"DatabricksConnector",
|
|
34
|
+
"AzureConnector",
|
|
35
|
+
"AzureSqlConnector",
|
|
36
|
+
# Config
|
|
37
|
+
"ValidatorConfig",
|
|
38
|
+
"ConfigNotFoundError",
|
|
39
|
+
"default_config",
|
|
40
|
+
"load_config",
|
|
41
|
+
"require_config",
|
|
42
|
+
"save_config",
|
|
43
|
+
# Core request/response models
|
|
44
|
+
"CatalogValidationRequest",
|
|
45
|
+
"CatalogValidationResponse",
|
|
46
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Auth package: credential abstractions for Azure and Databricks."""
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Azure auth abstraction.
|
|
2
|
+
|
|
3
|
+
Phase 1 auth: credentials are entered manually via the CLI wizard and
|
|
4
|
+
stored in ~/.table_validator/.env. get_azure_credential() is the single
|
|
5
|
+
place that reads them - every connector must call it instead of reading
|
|
6
|
+
os.environ directly, so only this function needs to change when a later
|
|
7
|
+
phase adds Azure CLI / Service Principal auth.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
from dotenv import dotenv_values
|
|
17
|
+
|
|
18
|
+
from table_validator.config.schema import ValidatorConfig
|
|
19
|
+
|
|
20
|
+
ENV_PATH = Path.home() / ".table_validator" / ".env"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class AzureCredential:
|
|
25
|
+
"""Resolved Azure credentials for the connectors this tool uses today.
|
|
26
|
+
|
|
27
|
+
storage_account_key authenticates AzureConnector (Blob Storage);
|
|
28
|
+
sql_username/sql_password authenticate AzureSqlConnector (Azure SQL
|
|
29
|
+
Database). Both are optional here since a given validation run may
|
|
30
|
+
only need one of the two.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
storage_account_key: Optional[str] = None
|
|
34
|
+
sql_username: Optional[str] = None
|
|
35
|
+
sql_password: Optional[str] = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_azure_credential(config: ValidatorConfig, env_path: Path = ENV_PATH) -> AzureCredential:
|
|
39
|
+
"""
|
|
40
|
+
Resolve Azure credentials for the given config.
|
|
41
|
+
|
|
42
|
+
Phase 1: reads AZURE_STORAGE_KEY / AZURE_SQL_USERNAME / AZURE_SQL_PASSWORD
|
|
43
|
+
from ~/.table_validator/.env. A later phase can swap this body for
|
|
44
|
+
Azure CLI / Service Principal auth without changing any caller.
|
|
45
|
+
"""
|
|
46
|
+
values = dotenv_values(env_path) if env_path.exists() else {}
|
|
47
|
+
|
|
48
|
+
return AzureCredential(
|
|
49
|
+
storage_account_key=values.get("AZURE_STORAGE_KEY") or None,
|
|
50
|
+
sql_username=values.get("AZURE_SQL_USERNAME") or None,
|
|
51
|
+
sql_password=values.get("AZURE_SQL_PASSWORD") or None,
|
|
52
|
+
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Databricks auth abstraction.
|
|
2
|
+
|
|
3
|
+
Phase 1 auth: the personal access token (PAT) is entered manually via the
|
|
4
|
+
CLI wizard and stored in ~/.table_validator/.env. get_databricks_token() is
|
|
5
|
+
the single place that reads it - every connector must call it instead of
|
|
6
|
+
reading os.environ directly, so only this function needs to change when a
|
|
7
|
+
later phase adds Databricks CLI / OAuth auth.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
from dotenv import dotenv_values
|
|
16
|
+
|
|
17
|
+
from table_validator.config.schema import ValidatorConfig
|
|
18
|
+
|
|
19
|
+
ENV_PATH = Path.home() / ".table_validator" / ".env"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_databricks_token(config: ValidatorConfig, env_path: Path = ENV_PATH) -> Optional[str]:
|
|
23
|
+
"""
|
|
24
|
+
Resolve the Databricks personal access token for the given config.
|
|
25
|
+
|
|
26
|
+
Phase 1: reads DATABRICKS_TOKEN from ~/.table_validator/.env. A later
|
|
27
|
+
phase can swap this body for Databricks CLI / OAuth auth without
|
|
28
|
+
changing any caller.
|
|
29
|
+
"""
|
|
30
|
+
values = dotenv_values(env_path) if env_path.exists() else {}
|
|
31
|
+
return values.get("DATABRICKS_TOKEN") or None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CLI package: Typer app and interactive configuration wizard."""
|