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.
Files changed (36) hide show
  1. {rowproof-0.1.2 → rowproof-0.1.4}/PKG-INFO +4 -2
  2. {rowproof-0.1.2 → rowproof-0.1.4}/README.md +3 -1
  3. {rowproof-0.1.2 → rowproof-0.1.4}/pyproject.toml +1 -1
  4. rowproof-0.1.4/rowproof/__init__.py +1 -0
  5. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/cli/main.py +21 -4
  6. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/cli/render.py +1 -1
  7. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/_chwire.py +1 -1
  8. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/_pgwire.py +1 -1
  9. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/hashdiff.py +3 -2
  10. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/PKG-INFO +4 -2
  11. rowproof-0.1.2/rowproof/__init__.py +0 -1
  12. {rowproof-0.1.2 → rowproof-0.1.4}/LICENSE +0 -0
  13. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/cli/__init__.py +0 -0
  14. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/cli/spec.py +0 -0
  15. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/config/__init__.py +0 -0
  16. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/__init__.py +0 -0
  17. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/_sfwire.py +0 -0
  18. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/base.py +0 -0
  19. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/clickhouse.py +0 -0
  20. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/postgres.py +0 -0
  21. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/connectors/snowflake.py +0 -0
  22. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/__init__.py +0 -0
  23. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/column_matching.py +0 -0
  24. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/errors.py +0 -0
  25. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/joindiff.py +0 -0
  26. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/models.py +0 -0
  27. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/normalisation.py +0 -0
  28. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/core/segmentation.py +0 -0
  29. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/report/__init__.py +0 -0
  30. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof/report/html.py +0 -0
  31. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/SOURCES.txt +0 -0
  32. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/dependency_links.txt +0 -0
  33. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/entry_points.txt +0 -0
  34. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/requires.txt +0 -0
  35. {rowproof-0.1.2 → rowproof-0.1.4}/rowproof.egg-info/top_level.txt +0 -0
  36. {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.2
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` overrides |
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` overrides |
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) |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "rowproof"
3
- version = "0.1.2"
3
+ version = "0.1.4"
4
4
  description = "Prove a database migration or replication didn't lose, add or change a single row."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -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 requires hashdiff (spec §4.3) -- "
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) assumed "
501
- f"{plan.options.assume_tz} ({', '.join(naive_cols)}) — use --assume-tz to override",
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.2
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` overrides |
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