table-validator 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- table_validator/__init__.py +46 -0
- table_validator/auth/__init__.py +1 -0
- table_validator/auth/azure_auth.py +52 -0
- table_validator/auth/databricks_auth.py +31 -0
- table_validator/cli/__init__.py +1 -0
- table_validator/cli/main.py +722 -0
- table_validator/cli/partition_prompt.py +78 -0
- table_validator/cli/summary_table.py +146 -0
- table_validator/cli/wizard.py +429 -0
- table_validator/config/__init__.py +1 -0
- table_validator/config/manager.py +84 -0
- table_validator/config/schema.py +179 -0
- table_validator/connectors/__init__.py +1 -0
- table_validator/connectors/azure_connector.py +809 -0
- table_validator/connectors/databricks_connector.py +1230 -0
- table_validator/engine/__init__.py +1 -0
- table_validator/engine/comparison_engine.py +645 -0
- table_validator/models.py +952 -0
- table_validator/reports/__init__.py +1 -0
- table_validator/reports/excel_report.py +953 -0
- table_validator/validators/__init__.py +1 -0
- table_validator/validators/blob_discovery.py +467 -0
- table_validator/validators/catalog_validator.py +1863 -0
- table_validator/validators/row_validator.py +1727 -0
- table_validator-0.1.0.dist-info/METADATA +190 -0
- table_validator-0.1.0.dist-info/RECORD +30 -0
- table_validator-0.1.0.dist-info/WHEEL +5 -0
- table_validator-0.1.0.dist-info/entry_points.txt +2 -0
- table_validator-0.1.0.dist-info/licenses/LICENSE +21 -0
- table_validator-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -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,30 @@
|
|
|
1
|
+
table_validator/__init__.py,sha256=3Hvlk-yRCL8HAwONirbtPA3POjE5qcSZz2oU_bQCN5o,1447
|
|
2
|
+
table_validator/models.py,sha256=7hr_KjxNYhJmsc0PAc9-woDf__Wp2j1XAfU2Vo5BjfQ,32116
|
|
3
|
+
table_validator/auth/__init__.py,sha256=Spncoe3HL7NI6OgaRBmIwJMKeMUdVLrP4lBaIcBNYOY,70
|
|
4
|
+
table_validator/auth/azure_auth.py,sha256=Dximt9w57P4g7MjoJBSOGdxCyowrarqyix8BCRvSqnU,1805
|
|
5
|
+
table_validator/auth/databricks_auth.py,sha256=C71kUC9ivlqgyQU-8O7PCE-dwJlmhaZ0lcsT7D5EL3k,1086
|
|
6
|
+
table_validator/cli/__init__.py,sha256=ofbwCuoGUlklWwECq86anrbcn1u6hISyKQHnlrDjdMY,67
|
|
7
|
+
table_validator/cli/main.py,sha256=1_-fSv_bVf8HvfWDc9vTDtsODfgCo0olXjegO8ydNhs,30302
|
|
8
|
+
table_validator/cli/partition_prompt.py,sha256=iyWOtHymg9nPDJnVSPoK_imLNBlVIwO3RSdPB3RA2Vo,2623
|
|
9
|
+
table_validator/cli/summary_table.py,sha256=xeIqkATlmlyuYkmpJnh5xk7cKRU-eR1lqUfkpwHS2ck,5634
|
|
10
|
+
table_validator/cli/wizard.py,sha256=8K_Z8xqnzG9Wgx5rekhmq3okq99eVo6ZIMSO-dQD86A,17601
|
|
11
|
+
table_validator/config/__init__.py,sha256=VkYHiQaykkfks5p75tA0gD8gG4wTJsZnQphmdRIT-oA,91
|
|
12
|
+
table_validator/config/manager.py,sha256=wz7htUQ5bwFg1AakG_57U3Zu9OhkPDXY0nFFCgXiOdo,2861
|
|
13
|
+
table_validator/config/schema.py,sha256=QFV4T0qPTUThbs0qXvRl8rvLq98Le63bufDAfls4E6s,6405
|
|
14
|
+
table_validator/connectors/__init__.py,sha256=W9LEtRaS6Ia2GQKMYjRdRCiDB47sEShVxIgmiH3_wrQ,91
|
|
15
|
+
table_validator/connectors/azure_connector.py,sha256=1cWb9jD2zdBHqfZg6qEKLXodyc4m4x-a6OXuIXIFETM,29306
|
|
16
|
+
table_validator/connectors/databricks_connector.py,sha256=dUwggjdJbq7H38umLCF_zwEvUq43KWna_mZzJyIZxgs,43640
|
|
17
|
+
table_validator/engine/__init__.py,sha256=6SoRLYTB6tY0uorhYkjKgBGCSzIE7IsCJw57VoTLC0Q,73
|
|
18
|
+
table_validator/engine/comparison_engine.py,sha256=fxEu4ojofugQ8rtTxjgOAoxGqovELjuw4sNzlYbGXiQ,16781
|
|
19
|
+
table_validator/reports/__init__.py,sha256=z9jtmU9c3NzeDxOFw1jTmHee10mZD2FVuFTqoOu4S1s,64
|
|
20
|
+
table_validator/reports/excel_report.py,sha256=6vZSglCvePqM5SimcKEraFwSpOwfa7CRz7EiMIAJDNQ,39940
|
|
21
|
+
table_validator/validators/__init__.py,sha256=uwh7itYLr6KQ_Fh9U0Z1OoTCdP4LIGXHNM22A2vVVHs,85
|
|
22
|
+
table_validator/validators/blob_discovery.py,sha256=kM9rjneIQt5pfR5dSmITa2kcK1FMCMvK6GjPNU7QXE8,19008
|
|
23
|
+
table_validator/validators/catalog_validator.py,sha256=UDublQOGGfrjDddylV58LqqfxR1zUUzZ4LTQsix9dSE,81635
|
|
24
|
+
table_validator/validators/row_validator.py,sha256=kpl2HkRcbHomGsXCzDaKcDuNWSTpqIkt5CtctA8N7sE,72307
|
|
25
|
+
table_validator-0.1.0.dist-info/licenses/LICENSE,sha256=6vZlKQZ-cKinHW_IxFFav-By29-j61dLdYoVAq-cVj8,1065
|
|
26
|
+
table_validator-0.1.0.dist-info/METADATA,sha256=4iuetgMdhDzTpoobejeMtZnViZmX_gpTBW2mtRJdhLU,6029
|
|
27
|
+
table_validator-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
28
|
+
table_validator-0.1.0.dist-info/entry_points.txt,sha256=2M-96rIihIW-reYiIdmNDElLfYC_PziuJKMGg_hR0KI,64
|
|
29
|
+
table_validator-0.1.0.dist-info/top_level.txt,sha256=svExNN_O7_T2bOza83z2qeBMzcmPg6RruFIRDZJbcRI,16
|
|
30
|
+
table_validator-0.1.0.dist-info/RECORD,,
|
|
@@ -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 @@
|
|
|
1
|
+
table_validator
|