rowproof 0.1.2__tar.gz → 0.1.4__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.
- {rowproof-0.1.2 → rowproof-0.1.4}/PKG-INFO +4 -2
- {rowproof-0.1.2 → rowproof-0.1.4}/README.md +3 -1
- {rowproof-0.1.2 → rowproof-0.1.4}/pyproject.toml +1 -1
- rowproof-0.1.4/rowproof/__init__.py +1 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/cli/main.py +21 -4
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/cli/render.py +1 -1
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/_chwire.py +1 -1
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/_pgwire.py +1 -1
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/hashdiff.py +3 -2
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/PKG-INFO +4 -2
- rowproof-0.1.2/rowproof/__init__.py +0 -1
- {rowproof-0.1.2 → rowproof-0.1.4}/LICENSE +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/cli/__init__.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/cli/spec.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/config/__init__.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/__init__.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/_sfwire.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/base.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/clickhouse.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/postgres.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/snowflake.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/__init__.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/column_matching.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/errors.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/joindiff.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/models.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/normalisation.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/segmentation.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/report/__init__.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/report/html.py +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/SOURCES.txt +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/dependency_links.txt +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/entry_points.txt +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/requires.txt +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/top_level.txt +0 -0
- {rowproof-0.1.2 → rowproof-0.1.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rowproof
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Prove a database migration or replication didn't lose, add or change a single row.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -73,6 +73,8 @@ public.orders postgres:postgres/public.orders -> clickhouse:default/orders
|
|
|
73
73
|
result DIFFERENT exit 1
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
**Next:** the [user guide](docs/USAGE.md) covers connection strings for each database, every option with examples, checking many tables from a config file, using rowproof in CI, and troubleshooting.
|
|
77
|
+
|
|
76
78
|
## What it checks — and what it never does
|
|
77
79
|
|
|
78
80
|
- Verifies every row matches: counts, missing rows, extra rows, and changed values, down to the specific column and the exact rule that governed the comparison (a timestamp precision mismatch and a NULL-vs-empty-string mismatch are not the same bug, and rowproof tells you which one you have).
|
|
@@ -114,7 +116,7 @@ Every cross-engine type difference is governed by one of these published rules,
|
|
|
114
116
|
| BOOL-1 | boolean | `true` / `false` | Handles integer 0/1 vs boolean across engines |
|
|
115
117
|
| TS-1 | timestamp with tz | ISO 8601 UTC, `YYYY-MM-DDTHH:MM:SS.ffffffZ` | Always 6 fractional digits |
|
|
116
118
|
| TS-2 | timestamp precision differs | rounded to the pair's lower precision | e.g. Postgres µs vs ClickHouse `DateTime` (seconds) |
|
|
117
|
-
| TS-3 | timestamp without tz | rendered as-is with `Z`, assumed UTC, warns once | `--assume-tz`
|
|
119
|
+
| TS-3 | timestamp without tz | rendered as-is with `Z`, assumed UTC, warns once | Always UTC for now; `--assume-tz` other than UTC is rejected (not implemented yet) |
|
|
118
120
|
| DATE-1 | date | `YYYY-MM-DD` | |
|
|
119
121
|
| TIME-1 | time | `HH:MM:SS.ffffff` | |
|
|
120
122
|
| UUID-1 | uuid | lower-case, hyphenated | Handles a uuid stored as VARCHAR (Snowflake) |
|
|
@@ -51,6 +51,8 @@ public.orders postgres:postgres/public.orders -> clickhouse:default/orders
|
|
|
51
51
|
result DIFFERENT exit 1
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
**Next:** the [user guide](docs/USAGE.md) covers connection strings for each database, every option with examples, checking many tables from a config file, using rowproof in CI, and troubleshooting.
|
|
55
|
+
|
|
54
56
|
## What it checks — and what it never does
|
|
55
57
|
|
|
56
58
|
- Verifies every row matches: counts, missing rows, extra rows, and changed values, down to the specific column and the exact rule that governed the comparison (a timestamp precision mismatch and a NULL-vs-empty-string mismatch are not the same bug, and rowproof tells you which one you have).
|
|
@@ -92,7 +94,7 @@ Every cross-engine type difference is governed by one of these published rules,
|
|
|
92
94
|
| BOOL-1 | boolean | `true` / `false` | Handles integer 0/1 vs boolean across engines |
|
|
93
95
|
| TS-1 | timestamp with tz | ISO 8601 UTC, `YYYY-MM-DDTHH:MM:SS.ffffffZ` | Always 6 fractional digits |
|
|
94
96
|
| TS-2 | timestamp precision differs | rounded to the pair's lower precision | e.g. Postgres µs vs ClickHouse `DateTime` (seconds) |
|
|
95
|
-
| TS-3 | timestamp without tz | rendered as-is with `Z`, assumed UTC, warns once | `--assume-tz`
|
|
97
|
+
| TS-3 | timestamp without tz | rendered as-is with `Z`, assumed UTC, warns once | Always UTC for now; `--assume-tz` other than UTC is rejected (not implemented yet) |
|
|
96
98
|
| DATE-1 | date | `YYYY-MM-DD` | |
|
|
97
99
|
| TIME-1 | time | `HH:MM:SS.ffffff` | |
|
|
98
100
|
| UUID-1 | uuid | lower-case, hyphenated | Handles a uuid stored as VARCHAR (Snowflake) |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.4"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""rowproof CLI — argparse stand-in for `typer` (see docs/DEV_ENVIRONMENT.md).
|
|
1
|
+
"""rowproof CLI — argparse stand-in for `typer` (see docs/internal/DEV_ENVIRONMENT.md).
|
|
2
2
|
Flags, behavior and exit codes follow spec §7 exactly; only the argument
|
|
3
3
|
*parsing library* differs from the spec's chosen stack.
|
|
4
4
|
"""
|
|
@@ -201,12 +201,29 @@ def resolve_algorithm(requested: str, args) -> str:
|
|
|
201
201
|
return "hashdiff"
|
|
202
202
|
|
|
203
203
|
|
|
204
|
+
def _check_assume_tz(value: str) -> str:
|
|
205
|
+
"""`--assume-tz` is accepted by the parser but no connector applies it:
|
|
206
|
+
a naive (TS-3) timestamp is always rendered as if it were UTC. Passing
|
|
207
|
+
another zone used to be silently ignored while the warning still said
|
|
208
|
+
"assumed <zone>" -- rows that match in that zone were reported
|
|
209
|
+
DIFFERENT with a message claiming otherwise. Refuse loudly until the
|
|
210
|
+
conversion is actually implemented in each connector.
|
|
211
|
+
"""
|
|
212
|
+
if value.strip().upper() != "UTC":
|
|
213
|
+
raise RowProofError(
|
|
214
|
+
f"--assume-tz {value} is not supported yet: naive timestamps are always "
|
|
215
|
+
"compared as UTC. Use timestamp-with-timezone columns, or convert the "
|
|
216
|
+
"column in a view, so both sides agree on the instant."
|
|
217
|
+
)
|
|
218
|
+
return value
|
|
219
|
+
|
|
220
|
+
|
|
204
221
|
def _normalise_kwargs(args) -> dict:
|
|
205
222
|
return dict(
|
|
206
223
|
trim=args.trim,
|
|
207
224
|
case_insensitive=args.case_insensitive,
|
|
208
225
|
float_precision=args.float_precision,
|
|
209
|
-
assume_tz=args.assume_tz,
|
|
226
|
+
assume_tz=_check_assume_tz(args.assume_tz),
|
|
210
227
|
column_map=_parse_column_map(args.column_map),
|
|
211
228
|
)
|
|
212
229
|
|
|
@@ -237,7 +254,7 @@ def cmd_diff(args) -> int:
|
|
|
237
254
|
# while also asking to sample -- a clear error beats
|
|
238
255
|
# silently ignoring the flag.
|
|
239
256
|
raise RowProofError(
|
|
240
|
-
"--sample/--sample-rows
|
|
257
|
+
"--sample/--sample-rows needs the hash-based method -- "
|
|
241
258
|
"pass --algorithm hashdiff, or diff two different connections "
|
|
242
259
|
"so hashdiff is auto-selected"
|
|
243
260
|
)
|
|
@@ -391,7 +408,7 @@ def _run_one_job(job, connections: dict, verbose: bool) -> int:
|
|
|
391
408
|
key_columns=job.key, columns=job.columns, exclude=job.exclude,
|
|
392
409
|
where=job.where, where_source=job.where_source, where_target=job.where_target,
|
|
393
410
|
trim=job.trim, case_insensitive=job.case_insensitive,
|
|
394
|
-
float_precision=job.float_precision, assume_tz=job.assume_tz, column_map=job.column_map,
|
|
411
|
+
float_precision=job.float_precision, assume_tz=_check_assume_tz(job.assume_tz), column_map=job.column_map,
|
|
395
412
|
)
|
|
396
413
|
if algorithm == "joindiff":
|
|
397
414
|
result = run_joindiff(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Terminal + JSON rendering — plain-text stand-in for `rich` (see
|
|
2
|
-
docs/DEV_ENVIRONMENT.md). Behavior/content matches spec §8; only the
|
|
2
|
+
docs/internal/DEV_ENVIRONMENT.md). Behavior/content matches spec §8; only the
|
|
3
3
|
"tables and progress bars" styling is simplified.
|
|
4
4
|
"""
|
|
5
5
|
|
|
@@ -3,7 +3,7 @@ driver.
|
|
|
3
3
|
|
|
4
4
|
`ClickHouseConnector` in clickhouse.py calls only the functions below,
|
|
5
5
|
never clickhouse_connect directly. This module used to be a hand-rolled
|
|
6
|
-
stdlib `urllib` HTTP client (see git history / docs/DEV_ENVIRONMENT.md
|
|
6
|
+
stdlib `urllib` HTTP client (see git history / docs/internal/DEV_ENVIRONMENT.md
|
|
7
7
|
for why); clickhouse-connect replaces that with the real driver, which
|
|
8
8
|
speaks the same HTTP interface but also handles response decoding,
|
|
9
9
|
per-engine type mapping, and connection re-use itself instead of this
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
`PostgresConnector` in postgres.py calls only the functions below, never
|
|
4
4
|
psycopg directly, so the rest of the codebase is insulated from driver
|
|
5
5
|
specifics. This module used to shell out to the `psql` CLI binary (see
|
|
6
|
-
git history / docs/DEV_ENVIRONMENT.md for why); psycopg replaces that
|
|
6
|
+
git history / docs/internal/DEV_ENVIRONMENT.md for why); psycopg replaces that
|
|
7
7
|
with a real wire-protocol connection and hands back already-typed Python
|
|
8
8
|
values (int, Decimal, datetime, bool, ...) instead of text that has to be
|
|
9
9
|
guessed back into a type.
|
|
@@ -497,8 +497,9 @@ def _append_run_level_warnings(plan: _Plan, result: DiffResult) -> None:
|
|
|
497
497
|
if naive_cols:
|
|
498
498
|
result.warnings.append(
|
|
499
499
|
TdWarning(
|
|
500
|
-
"TS-3: naive timestamp column(s)
|
|
501
|
-
f"
|
|
500
|
+
"TS-3: naive timestamp column(s) compared as UTC "
|
|
501
|
+
f"({', '.join(naive_cols)}) — if they are really in another zone, "
|
|
502
|
+
"use timestamp-with-timezone columns or convert them in a view",
|
|
502
503
|
rule=NormalisationRule.TS_3,
|
|
503
504
|
)
|
|
504
505
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rowproof
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Prove a database migration or replication didn't lose, add or change a single row.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -73,6 +73,8 @@ public.orders postgres:postgres/public.orders -> clickhouse:default/orders
|
|
|
73
73
|
result DIFFERENT exit 1
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
**Next:** the [user guide](docs/USAGE.md) covers connection strings for each database, every option with examples, checking many tables from a config file, using rowproof in CI, and troubleshooting.
|
|
77
|
+
|
|
76
78
|
## What it checks — and what it never does
|
|
77
79
|
|
|
78
80
|
- Verifies every row matches: counts, missing rows, extra rows, and changed values, down to the specific column and the exact rule that governed the comparison (a timestamp precision mismatch and a NULL-vs-empty-string mismatch are not the same bug, and rowproof tells you which one you have).
|
|
@@ -114,7 +116,7 @@ Every cross-engine type difference is governed by one of these published rules,
|
|
|
114
116
|
| BOOL-1 | boolean | `true` / `false` | Handles integer 0/1 vs boolean across engines |
|
|
115
117
|
| TS-1 | timestamp with tz | ISO 8601 UTC, `YYYY-MM-DDTHH:MM:SS.ffffffZ` | Always 6 fractional digits |
|
|
116
118
|
| TS-2 | timestamp precision differs | rounded to the pair's lower precision | e.g. Postgres µs vs ClickHouse `DateTime` (seconds) |
|
|
117
|
-
| TS-3 | timestamp without tz | rendered as-is with `Z`, assumed UTC, warns once | `--assume-tz`
|
|
119
|
+
| TS-3 | timestamp without tz | rendered as-is with `Z`, assumed UTC, warns once | Always UTC for now; `--assume-tz` other than UTC is rejected (not implemented yet) |
|
|
118
120
|
| DATE-1 | date | `YYYY-MM-DD` | |
|
|
119
121
|
| TIME-1 | time | `HH:MM:SS.ffffff` | |
|
|
120
122
|
| UUID-1 | uuid | lower-case, hyphenated | Handles a uuid stored as VARCHAR (Snowflake) |
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|