netra-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.
Files changed (67) hide show
  1. netra_validator-0.1.0/.github/workflows/ci.yaml +47 -0
  2. netra_validator-0.1.0/.gitignore +34 -0
  3. netra_validator-0.1.0/LICENSE +21 -0
  4. netra_validator-0.1.0/PKG-INFO +334 -0
  5. netra_validator-0.1.0/README.md +312 -0
  6. netra_validator-0.1.0/benchmarks/README.md +94 -0
  7. netra_validator-0.1.0/benchmarks/__init__.py +0 -0
  8. netra_validator-0.1.0/benchmarks/configs/lofar_telemetry_odcs.yaml +173 -0
  9. netra_validator-0.1.0/benchmarks/generators/base.py +74 -0
  10. netra_validator-0.1.0/benchmarks/generators/lofar_telemetry.py +274 -0
  11. netra_validator-0.1.0/benchmarks/harness/collector.py +146 -0
  12. netra_validator-0.1.0/benchmarks/harness/system.py +70 -0
  13. netra_validator-0.1.0/benchmarks/results/ec2/lofar_1B.json +121 -0
  14. netra_validator-0.1.0/benchmarks/results/ec2/lofar_1B_spill.json +87 -0
  15. netra_validator-0.1.0/benchmarks/results/ec2/lofar_2B_spill.json +87 -0
  16. netra_validator-0.1.0/benchmarks/results/ec2/lofar_3B_spill.json +87 -0
  17. netra_validator-0.1.0/benchmarks/results/latest.json +121 -0
  18. netra_validator-0.1.0/benchmarks/results/local/lofar_100M.json +121 -0
  19. netra_validator-0.1.0/benchmarks/results/local/lofar_10M.json +121 -0
  20. netra_validator-0.1.0/benchmarks/results/local/lofar_1B_spill.json +87 -0
  21. netra_validator-0.1.0/benchmarks/results/local/lofar_200M.json +121 -0
  22. netra_validator-0.1.0/benchmarks/results/local/lofar_500M.json +121 -0
  23. netra_validator-0.1.0/benchmarks/results/local/lofar_500M_spill.json +87 -0
  24. netra_validator-0.1.0/benchmarks/results/local/lofar_50M.json +121 -0
  25. netra_validator-0.1.0/benchmarks/results/local/lofar_800M_spill.json +87 -0
  26. netra_validator-0.1.0/benchmarks/run.py +350 -0
  27. netra_validator-0.1.0/benchmarks/targets/base.py +70 -0
  28. netra_validator-0.1.0/benchmarks/targets/netra.py +148 -0
  29. netra_validator-0.1.0/docs/assets/cli_showcase.png +0 -0
  30. netra_validator-0.1.0/docs/assets/error_state.png +0 -0
  31. netra_validator-0.1.0/docs/assets/risky_execution_state.png +0 -0
  32. netra_validator-0.1.0/docs/assets/warning_prompt.png +0 -0
  33. netra_validator-0.1.0/pyproject.toml +94 -0
  34. netra_validator-0.1.0/src/netra_validator/__init__.py +13 -0
  35. netra_validator-0.1.0/src/netra_validator/cli/__init.py__ +0 -0
  36. netra_validator-0.1.0/src/netra_validator/cli/auditor.py +201 -0
  37. netra_validator-0.1.0/src/netra_validator/cli/components.py +932 -0
  38. netra_validator-0.1.0/src/netra_validator/cli/console.py +197 -0
  39. netra_validator-0.1.0/src/netra_validator/cli/main.py +283 -0
  40. netra_validator-0.1.0/src/netra_validator/cli/models.py +33 -0
  41. netra_validator-0.1.0/src/netra_validator/cli/theme.py +16 -0
  42. netra_validator-0.1.0/src/netra_validator/compiler/__init.py__ +0 -0
  43. netra_validator-0.1.0/src/netra_validator/compiler/duckdb_builder.py +112 -0
  44. netra_validator-0.1.0/src/netra_validator/compiler/polars_builder.py +81 -0
  45. netra_validator-0.1.0/src/netra_validator/config.py +111 -0
  46. netra_validator-0.1.0/src/netra_validator/engine/__init.py__ +0 -0
  47. netra_validator-0.1.0/src/netra_validator/engine/duckdb_runner.py +307 -0
  48. netra_validator-0.1.0/src/netra_validator/engine/polars_runner.py +402 -0
  49. netra_validator-0.1.0/src/netra_validator/engine/validator.py +363 -0
  50. netra_validator-0.1.0/src/netra_validator/exceptions.py +89 -0
  51. netra_validator-0.1.0/src/netra_validator/parser/__init.py__ +0 -0
  52. netra_validator-0.1.0/src/netra_validator/parser/models.py +221 -0
  53. netra_validator-0.1.0/src/netra_validator/parser/reader.py +81 -0
  54. netra_validator-0.1.0/src/netra_validator/report/__init.py__ +0 -0
  55. netra_validator-0.1.0/src/netra_validator/report/generator.py +205 -0
  56. netra_validator-0.1.0/src/netra_validator/types.py +101 -0
  57. netra_validator-0.1.0/tests/__init__.py +0 -0
  58. netra_validator-0.1.0/tests/conftest.py +238 -0
  59. netra_validator-0.1.0/tests/integration/test_duckdb_runner.py +248 -0
  60. netra_validator-0.1.0/tests/integration/test_polars_runner.py +250 -0
  61. netra_validator-0.1.0/tests/integration/test_validator_e2e.py +311 -0
  62. netra_validator-0.1.0/tests/unit/__init__.py +0 -0
  63. netra_validator-0.1.0/tests/unit/test_compiler.py +140 -0
  64. netra_validator-0.1.0/tests/unit/test_config.py +152 -0
  65. netra_validator-0.1.0/tests/unit/test_parser.py +145 -0
  66. netra_validator-0.1.0/tests/unit/test_report.py +205 -0
  67. netra_validator-0.1.0/uv.lock +1352 -0
@@ -0,0 +1,47 @@
1
+ name: CI
2
+
3
+ # 1. Triggers
4
+ on:
5
+ push:
6
+ branches: [main]
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ # 2. Concurrency
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ quality-gate:
17
+ name: Code Quality & Tests
18
+ runs-on: ubuntu-latest
19
+
20
+ steps:
21
+ - name: Checkout code
22
+ uses: actions/checkout@v4
23
+
24
+ - name: Install uv
25
+ uses: astral-sh/setup-uv@v5
26
+ with:
27
+ enable-cache: true
28
+ cache-dependency-glob: "uv.lock"
29
+
30
+ - name: Set up Python 3.10
31
+ run: uv python install 3.10
32
+
33
+ - name: Install dependencies
34
+ run: uv sync --all-extras --dev
35
+
36
+ # E. Scoped Quality Checks
37
+ - name: Check Formatting
38
+ run: uv run ruff format --check src/ tests/
39
+
40
+ - name: Lint Code
41
+ run: uv run ruff check src/ tests/
42
+
43
+ - name: Static Type Check
44
+ run: uv run mypy src/ tests/
45
+
46
+ - name: Run Tests
47
+ run: uv run pytest -v
@@ -0,0 +1,34 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.so
5
+ .venv/
6
+ .env
7
+
8
+ # Distribution
9
+ dist/
10
+ build/
11
+ *.egg-info/
12
+
13
+ # Tools & Caches
14
+ .mypy_cache/
15
+ .ruff_cache/
16
+ .pytest_cache/
17
+ .hypothesis/
18
+ .coverage
19
+ htmlcov/
20
+
21
+ # Generated data
22
+ benchmarks/data/*
23
+ tests/data/*
24
+
25
+ # Editors & IDEs
26
+ .zed/
27
+ .idea/
28
+ .vscode/
29
+ *.swp
30
+ .DS_Store
31
+
32
+ # User specific source setups
33
+ # You can put anything here that needs to be done to prepare your env.
34
+ .user_env.*
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nitin Paul
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,334 @@
1
+ Metadata-Version: 2.5
2
+ Name: netra-validator
3
+ Version: 0.1.0
4
+ Summary: High-performance out-of-core data validation tool built with Polars and DuckDB.
5
+ Project-URL: Homepage, https://github.com/netrabase/netra-validator
6
+ Project-URL: Repository, https://github.com/netrabase/netra-validator
7
+ Project-URL: Issues, https://github.com/netrabase/netra-validator/issues
8
+ Author-email: Nitin Paul <nitinpaul.dev@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: duckdb>=1.5.4
13
+ Requires-Dist: netra-core>=0.1.0
14
+ Requires-Dist: polars>=1.0.0
15
+ Requires-Dist: psutil>=7.2.2; sys_platform == 'win32'
16
+ Requires-Dist: pyarrow>=14.0.0
17
+ Requires-Dist: pydantic>=2.7.0
18
+ Requires-Dist: pyyaml>=6.0.3
19
+ Requires-Dist: rich>=14.3.1
20
+ Requires-Dist: typer>=0.24.0
21
+ Description-Content-Type: text/markdown
22
+
23
+ # Netra Validator
24
+
25
+ [![PyPI version](https://img.shields.io/pypi/v/netra-validator.svg?color=blue)](https://pypi.org/project/netra-validator/)
26
+ [![CI/CD](https://github.com/netrabase/netra-validator/actions/workflows/ci.yaml/badge.svg)](https://github.com/netrabase/netra-validator/actions)
27
+
28
+
29
+ ### High-performance data validator built with Polars and DuckDB
30
+
31
+ Netra Validator is a high-performance, out-of-core data validation engine and pipeline firewall built with [Polars](https://github.com/pola-rs/polars) and [DuckDB](https://github.com/duckdb/duckdb). It validates datasets against **Open Data Contract Standard (ODCS v3.1.0)** YAML contracts (authored manually or auto-generated via [Netra Profiler](https://github.com/netrabase/netra-profiler)), separates clean and quarantined records, and produces a strictly typed audit report.
32
+
33
+ Traditional validation frameworks either load entire datasets into memory (crashing on large files) or require distributed clusters like Apache Spark. Netra Validator maximizes your [Data Quality Envelope](#data-quality-envelope) by combining Polars' multi-threaded streaming engine with DuckDB's out-of-core SQL capability, allowing you to validate large-scale datasets (e.g., 16.5 GB Parquet, 12 columns, 1 billion rows) locally on a single node such as a 32 GB laptop (see [Performance Benchmarks](#performance-benchmarks) below).
34
+
35
+ ## Data Quality Envelope
36
+
37
+ The **Data Quality Envelope** is the maximum size and complexity of data your pipeline can profile, validate and quarantine within your hardware limits and compute budget.
38
+
39
+ As data volumes grow, teams are typically forced to either water down their quality checks (relying on rough samples or skipping expensive operations) or migrate to costly cloud instances or spin up multi-node distributed clusters just to run routine data quality checks. Netra Validator is designed to be a **value multiplier** for your existing hardware, allowing you to:
40
+
41
+ - **Stay Local Longer:** Run comprehensive quality checks on larger-than-memory datasets directly on your laptop or on-premise workstation without migrating to an HPC or cloud platform.
42
+ - **Scale Vertically, Not Horizontally:** Fully saturate the CPU cores and RAM of a single compute node, eliminating the operational and network shuffle overhead of distributed frameworks.
43
+ - **Control Compute & Energy Costs:** Avoid public cloud elasticity markups and reduce cluster energy consumption for predictable, recurring data health checks.
44
+
45
+ ## Performance Benchmarks
46
+
47
+ > *Note: All scripts used to generate the synthetic datasets, run the benchmarks, and collect the results can be found in the [`benchmarks/`](https://github.com/netrabase/netra-validator/tree/main/benchmarks) directory.*
48
+
49
+ ### Methodology
50
+
51
+ To evaluate Netra Validator under realistic scientific and industrial workloads, we designed a synthetic **LOFAR Radio Telescope Station Telemetry** dataset based on the system architecture and antenna anomaly taxonomy described in [*"Real-time station monitor and stationtest pipelines for LOFAR 2.0, Wang et al. (2025)"*](https://arxiv.org/abs/2503.02425):
52
+
53
+ - **Schema (12 Columns):** Models station receiver unit (RCU) telemetry combining 64-bit timestamps (`timestamp_utc`), categorical identifiers and state flags (`station_id`, `antenna_type`, `hardware_status`, `gps_sync_status`, `firmware_version`), 64-bit sensor floats (`frequency_mhz`, `signal_power_db`, `ambient_temp_c`, `packet_drop_rate`), 32-bit integers (`rcu_id`), and boolean flags (`rfi_flag`).
54
+ - **Contract Complexity:** Every benchmark run executes the [`lofar_telemetry_odcs.yaml`](https://github.com/netrabase/netra-validator/blob/main/benchmarks/configs/lofar_telemetry_odcs.yaml) contract end-to-end:
55
+ 1. **16 Row-Level Constraints:** Completeness (`required`) checks on all columns, numeric range bounds, categorical set membership (`invalidValues`), and **two regular expression checks** (`station_id` and `firmware_version`) evaluated across every row.
56
+ 2. **Physical Data Partitioning:** Compresses and writes **~99.15% of the dataset** to disk as clean records (Snappy Parquet) and **~0.85%** to disk as quarantined records.
57
+ 3. **4 Global SQL Rules:** Three cross-column anomaly checks (automatically fused into a single table scan) plus a **3-column composite Primary Key uniqueness check** (`GROUP BY timestamp_utc, station_id, rcu_id`) across the entire dataset.
58
+ - **Measurement Protocol:** In-memory scaling benchmarks execute **1 warmup run followed by 3 timed iterations**, reporting the **median** and run-to-run standard deviation (`± std`). Out-of-core (`spill_to_disk`) envelope runs execute a **single cold-start pass** (`--warmup 0 --iterations 1`) to measure maximum single-node capacity without cumulative thermal throttling or SSD write-cache saturation.
59
+ - **On-Disk vs. In-Memory Footprint:** All dataset sizes listed below reflect compressed Snappy Parquet files on disk. Because Parquet applies dictionary encoding (`RLE_DICTIONARY`) and Snappy compression to repeated categorical strings ([Apache Parquet Encodings](https://parquet.apache.org/docs/file-format/data-pages/encodings/)), the 16.5 GB, 1-billion-row file expands to **~85.8 GB in uncompressed Apache Arrow memory (~5.2x larger)** when materialized ([Apache Arrow Columnar Format](https://arrow.apache.org/docs/format/Columnar.html)).
60
+
61
+ ### A. Single-Node Execution (10 Million to 1 Billion Rows)
62
+
63
+ All local benchmarks were executed on a standard consumer laptop:
64
+
65
+ - **CPU:** Intel(R) Core(TM) i7-10750H @ 2.60GHz (6 Physical / 12 Logical Cores)
66
+ - **RAM:** 31.16 GB (32 GB Physical)
67
+ - **OS:** Ubuntu 24.04.4 LTS (Linux 7.0)
68
+ - **Storage:** 512 GB NVMe SSD
69
+
70
+ #### 1. In-Memory Execution (10 Million to 500 Million Rows)
71
+
72
+ In default (in-memory) mode, all 12 logical CPU threads are utilized:
73
+
74
+ | Scale | Compressed Size (In-Memory Size) | Execution Time | Peak RAM |
75
+ | :--- | :--- | :--- | :--- |
76
+ | **10M** | 0.16 GB (~0.8 GB) | **3.49s** (±0.14s) | 2.19 GB |
77
+ | **50M** | 0.82 GB (~4.2 GB) | **18.43s** (±1.40s) | 6.91 GB |
78
+ | **100M** | 1.65 GB (~8.6 GB) | **32.11s** (±1.20s) | 10.59 GB |
79
+ | **200M** | 3.30 GB (~17.2 GB) | **65.44s (~1.1m)** (±3.21s) | 13.29 GB |
80
+ | **500M** | 8.25 GB (~42.9 GB) | **196.66s (~3.3m)** (±10.56s) | **27.58 GB** |
81
+
82
+ **Key Takeaways:**
83
+ - **Zero Startup Overhead:** At 10 million rows, Netra validates 16 column rules, writes partitioned Parquet files, and evaluates 4 global SQL rules in **3.49 seconds**, finishing before a distributed cluster can initialize.
84
+ - **Sub-Linear Memory Growth:** Increasing the dataset size by **50x** (from 10M to 500M rows) increases peak memory usage by only **12.6x** (`2.19 GB` to `27.58 GB`).
85
+ - **Validating Larger-Than-Memory Datasets Locally:** At 500 million rows, the dataset represents **~42.9 GB of uncompressed data**, exceeding the laptop's 32 GB of physical RAM. Netra validates and partitions the entire file in **3.3 minutes** within `27.58 GB` of RAM.
86
+
87
+ #### 2. Out-of-Core Envelope Expansion (500 Million to 1 Billion Rows)
88
+
89
+ On a 32 GB laptop, in-memory mode reaches its practical ceiling at 500 million rows (`27.58 GB` RAM), and larger workloads (`800M` and `1B` rows) exceed available system memory. Enabling `spill_to_disk` bounds memory consumption by processing data in smaller chunks (`50,000` rows) and spilling intermediate state to disk (`16 GB` engine memory limit, `4` active threads):
90
+
91
+ | Scale | Compressed Size (In-Memory Size) | Execution Time | Peak RAM |
92
+ | :--- | :--- | :--- | :--- |
93
+ | **500M** | 8.25 GB (~42.9 GB) | **229.91s (~3.8m)** | **16.91 GB** |
94
+ | **800M** | 13.20 GB (~68.6 GB) | **378.65s (~6.3m)** | **21.14 GB** |
95
+ | **1B** | 16.50 GB (~85.8 GB) | **506.21s (~8.4m)** | **28.79 GB** |
96
+
97
+ **Key Takeaways:**
98
+ - **10.67 GB RAM Reduction at `500M` Rows:** Compared to in-memory mode (`27.58 GB` in `196.66s`), enabling `spill_to_disk` at 500M rows cuts peak memory down to **`16.91 GB` (-38.7%)** for a modest `+33.25s` (+16.9%) trade-off in execution time, keeping roughly half of the laptop's RAM free for the OS and other applications.
99
+ - **2x Local Data Quality Envelope:** Out-of-core execution doubles the maximum dataset size the 32 GB laptop can handle, validating **1 Billion rows (~85.8 GB of uncompressed data)** and writing 991.5 million clean rows and 8.5 million quarantined rows to disk in **8.4 minutes**.
100
+
101
+ ### B. Cloud Scale-Up (1 Billion to 3 Billion Rows)
102
+
103
+ In LOFAR 2.0, each station's Local Control Unit (LCU) is equipped with a **16-core / 32-thread processor and 64 GB of RAM** ([Wang et al., 2025, Sec. 5](https://arxiv.org/abs/2503.02425)). To benchmark Netra Validator on a similar hardware profile, we tested 1-billion to 3-billion-row datasets on an equivalent AWS EC2 compute node:
104
+
105
+ - **Instance:** AWS EC2 `c8id.8xlarge`
106
+ - **CPU:** Intel(R) Xeon(R) 6975P-C (16 Physical / 32 Logical vCPUs)
107
+ - **RAM:** 61.77 GB (64 GB Instance Class)
108
+ - **OS:** Ubuntu 24.04.1 LTS (Linux 7.0 AWS)
109
+ - **Storage:** Attached Nitro NVMe SSD
110
+
111
+ We evaluated both **In-Memory Mode** (`32` Polars threads / `32` DuckDB threads) and **Out-of-Core Mode** (`32` Polars threads / `8` DuckDB threads, `250,000`-row Polars batches, `32 GB` engine memory limit):
112
+
113
+ | Scale | Compressed Size (In-Memory Size) | In-Memory (Time / RAM) | Out-of-Core (Time / RAM<sup>†</sup>) |
114
+ | :--- | :--- | :--- | :--- |
115
+ | **1B** | 16.50 GB (~85.8 GB) | **198.47s (~3.3m)** / 56.05 GB | **278.64s (~4.6m)** / **34.01 GB** |
116
+ | **2B** | 33.00 GB (~171.6 GB) | *Exceeds 64 GB RAM* | **575.74s (~9.6m)** / **35.16 GB** |
117
+ | **3B** | 49.50 GB (~257.4 GB) | *Exceeds 64 GB RAM* | **858.14s (~14.3m)** / **61.41 GB** |
118
+
119
+ <sup>†</sup> *Note on Peak RAM (`peak_rss_mb`): `memory_limit_mb` (`16 GB` on Laptop, `32 GB` on EC2) caps the SQL engine's working buffer during disk spilling. Total process RAM reported by the OS (`getrusage`) can rise above this cap on massive datasets due to OS file caching and the index overhead required to track hundreds of millions of spilled records on disk.*
120
+
121
+ **Key Takeaways:**
122
+
123
+ - **From Disk Spilling to In-Memory (`1B` Rows):** A 1-Billion-row workload that requires out-of-core disk spilling on a 32 GB laptop (`506.21s`) runs **entirely in memory in 3.3 minutes (`198.47s`)** on a 64 GB node.
124
+ - **3x Server Envelope Expansion (`1B` to `3B` Rows):** On a 64 GB machine, in-memory mode reaches its limit at 1 billion rows (`56.05 GB` RAM). Enabling `spill_to_disk` expands the single-node **Data Quality Envelope by 3x**, validating **2 billion rows** in **9.6 minutes** and **3 billion rows** (49.50 GB Parquet / ~257.4 GB uncompressed) in **14.3 minutes** without requiring a multi-node cluster.
125
+ - **Memory Behavior Across Scale (`1B` vs. `3B`):** At `1B` and `2B` rows, out-of-core mode holds total RAM steady at **`34.01 GB` – `35.16 GB`** (saving `22.04 GB` of RAM at `1B` compared to in-memory mode). At `3B` rows, the index overhead required to track 3 billion unique keys across temporary disk files pushes total process memory to **`61.41 GB`**, reaching the practical ceiling of a 64 GB node.
126
+
127
+ ### C. Throughput & Execution Stability
128
+
129
+ As datasets grow from millions to billions of rows, Netra maintains steady processing speed in both execution modes without hitting a performance cliff:
130
+
131
+ #### 1. In-Memory Mode (3 Timed Iterations + 1 Warmup)
132
+
133
+ | Environment | Scale Range | Row Velocity (Median) | Disk Throughput (Median) | Run-to-Run Std Dev (`± std`) |
134
+ | :--- | :--- | :--- | :--- | :--- |
135
+ | **Laptop (32 GB)** | 10M – 500M | **2.54M – 3.11M rows/s** | 40.0 – 49.0 MB/s | ±0.14s (10M) to ±10.56s (500M) |
136
+ | **EC2 `c8id.8xlarge` (64 GB)** | 1B | **5.04M rows/s** | **79.3 MB/s** | **±2.13s** |
137
+
138
+ #### 2. Out-of-Core Mode (Single Cold-Start Pass)
139
+
140
+ | Environment | Scale Range | Row Velocity | Disk Throughput | Execution Time Scaling |
141
+ | :--- | :--- | :--- | :--- | :--- |
142
+ | **Laptop (32 GB)** | 500M – 1B | **1.98M – 2.17M rows/s** | 31.1 – 34.2 MB/s | `229.91s` (500M) ➔ `506.21s` (1B) |
143
+ | **EC2 `c8id.8xlarge` (64 GB)** | 1B – 3B | **3.47M – 3.59M rows/s** | **54.7 – 56.5 MB/s** | `278.64s` (1B) ➔ `858.14s` (3B) |
144
+
145
+ **Key Takeaways:**
146
+ - **Linear O(N) Scaling at Multi-Billion-Row Scale:** On the 32-vCPU server, doubling the out-of-core workload from **1B to 2B rows** increases execution time by **2.07x** (`278.64s` to `575.74s`), and tripling it to **3B rows** increases execution time by **3.08x** (`858.14s`).
147
+ - **No Throughput Degradation:** Processing velocity varies by less than **2.5%** across a 3x volume increase on the server (`3.59M rows/s` at 1B vs. `3.50M rows/s` at 3B) and less than **9%** across a 2x volume increase on the laptop (`2.17M rows/s` at 500M vs. `1.98M rows/s` at 1B).
148
+
149
+ ## Features
150
+
151
+ - **Native ODCS v3.1.0 Support:** Validates datasets against any compliant [Open Data Contract Standard (v3.1.0)](https://bitol-io.github.io/open-data-contract-standard/v3.1.0/) YAML file—whether from an existing data catalog, written by hand, or generated automatically with [`netra-profiler`](https://github.com/netrabase/netra-profiler).
152
+ - **Automated Data Quarantine:** Automatically splits your input dataset into clean (`validated`) and corrupted (`quarantined`) Parquet files, ensuring bad data never enters downstream tables.
153
+ - **Single-Pass SQL Rule Batching:** Automatically combines multiple `SELECT COUNT(*) FROM {object} WHERE ...` contract rules into a single DuckDB table scan, with automatic per-rule fallback if a query contains a syntax error.
154
+ - **Configurable Global Target (`raw` vs. `validated`):** Choose whether Pass 2 Global/SQL rules evaluate the original raw dataset or only the clean rows that survived Pass 1 (`global_target`).
155
+ - **Out-of-Core Execution:** Process larger-than-memory datasets under strict RAM budgets using configurable disk spilling, micro-batch sizing, pre-flight free-space checks, and automatic thread clamping.
156
+ - **Container-Aware Thread Budgeting:** Automatically detects CPU limits via environment variables (`NETRA_POLARS_THREADS`, `NETRA_DUCKDB_THREADS`), Linux `cgroup` container quotas (Docker/Kubernetes), or physical core counts.
157
+ - **CI/CD Quality Gates:** Enforce strict pipeline governance with `--fail-on-critical` and `--fail-on-warnings` flags for GitHub Actions, GitLab CI, Airflow, and Dagster.
158
+ - **Rich CLI & Headless JSON Mode:** View validation summaries and rule diagnostics in the terminal, or pass `--json` for strictly typed JSON output in automated pipelines.
159
+
160
+ ### Supported Validation Capabilities
161
+
162
+ | Validation Layer | Rule / Constraint | ODCS v3.1.0 Property |
163
+ | :--- | :--- | :--- |
164
+ | **Column / Row-Level** | Null / Completeness Check | `required: true` |
165
+ | | Numeric Lower & Upper Bounds | `logicalTypeOptions.minimum` / `maximum` |
166
+ | | String Length Bounds | `logicalTypeOptions.minLength` / `maxLength` |
167
+ | | Regular Expression Matching | `logicalTypeOptions.pattern` |
168
+ | | Allowed Categorical Values | `quality.metric: invalidValues` (`validValues`) |
169
+ | **Table / Global** | Primary Key Uniqueness | `primaryKey: true` |
170
+ | | Custom Column SQL Rules | `quality.type: sql` (`{object}`, `{property}`) |
171
+ | | Custom Table & Cross-Column SQL | `schema.quality.type: sql` (`{object}`) |
172
+ | | Mathematical SQL Boundaries | `mustBeEqual`, `mustBe`, `mustBeLessThan`, `mustBeGreaterThan` |
173
+
174
+ ## Installation
175
+
176
+ We recommend installing Netra Validator with [uv](https://github.com/astral-sh/uv):
177
+
178
+ ```bash
179
+ uv pip install netra-validator
180
+ ```
181
+
182
+ Or with standard `pip`:
183
+
184
+ ```bash
185
+ pip install netra-validator
186
+ ```
187
+
188
+ ## Quickstart
189
+
190
+ ### 1. Command Line
191
+
192
+ Validate any dataset against an ODCS v3.1.0 YAML contract directly from your terminal:
193
+
194
+ ```bash
195
+ # Optional: Auto-generate a baseline ODCS v3.1.0 contract with netra-profiler
196
+ netra profile dataset.parquet --json > profile.json
197
+ netra contract profile.json > contract.yaml
198
+
199
+ # Validate the dataset against the contract
200
+ netra validate dataset.parquet contract.yaml
201
+ ```
202
+
203
+ ![Netra Validator CLI](https://github.com/netrabase/netra-validator/blob/main/docs/assets/cli_showcase.png)
204
+
205
+ <details>
206
+ <summary><b>More Screenshots</b></summary>
207
+ <br>
208
+
209
+ **Out-Of-Memory Risk Warning:**
210
+ ![Netra Validator Warning State](https://github.com/netrabase/netra-validator/blob/main/docs/assets/warning_prompt.png)
211
+
212
+ **"Risky Execution" State:**
213
+ ![Netra Validator Risky Execution State](https://github.com/netrabase/netra-validator/blob/main/docs/assets/risky_execution_state.png)
214
+
215
+ **Data Contract Error:**
216
+ ![Netra Validator Preflight Failure State](https://github.com/netrabase/netra-validator/blob/main/docs/assets/error_state.png)
217
+
218
+ </details>
219
+
220
+ #### CLI Options & Quality Gates
221
+
222
+ - `-o, --valid <path>`: Custom output path for rows that pass all row-level checks (defaults to `validated_<dataset>`).
223
+ - `-q, --quarantine <path>`: Custom output path for rows that fail one or more row-level checks (defaults to `quarantined_<dataset>`).
224
+ - `--global-target [raw|validated]`: Choose whether Pass 2 DuckDB SQL rules run against the `raw` input dataset (default) or the `validated` clean output from Pass 1.
225
+ - `-c, --config <path>`: Path to a custom `netra_config.yaml` file.
226
+ - `--fail-on-critical`: Enable the CI/CD Quality Gate and exit with code `1` if any `CRITICAL` anomalies (row quarantines or critical SQL failures) are detected.
227
+ - `--fail-on-warnings`: Enable the strictest CI/CD Quality Gate and exit with code `1` if **any** anomalies (`WARNING` or `CRITICAL`) are detected.
228
+ - `-y, --force`: Bypass interactive confirmation prompts when pre-flight hardware warnings are triggered.
229
+ - `--json`: Disable the interactive terminal UI and print the validation report as formatted JSON to `stdout`.
230
+ - `-V, --version`: Show the netra-validator version and exit.
231
+
232
+ ### 2. Python API
233
+
234
+ Netra Validator provides a fully typed Python API for integration into Airflow, Dagster, Prefect, or custom data engineering services:
235
+
236
+ ```python
237
+ from netra_validator.config import ValidatorConfig
238
+ from netra_validator.engine.validator import Validator
239
+
240
+ # 1. Configure quality gates and validator execution settings
241
+ # (Or load directly from disk via `ValidatorConfig.from_yaml("netra_config.yaml")`)
242
+ config = ValidatorConfig(
243
+ {
244
+ "pipeline": {
245
+ "fail_on_critical": True,
246
+ "fail_on_warnings": False,
247
+ },
248
+ "validator": {
249
+ "global_target": "validated", # Run Pass 2 SQL checks on clean Pass 1 output
250
+ "spill_to_disk": {
251
+ "enabled": True,
252
+ "memory_limit_mb": 16384, # 16 GB RAM ceiling for DuckDB Pass 2
253
+ "chunk_size": 50_000,
254
+ "temp_directory": "/tmp/netra_spill",
255
+ },
256
+ },
257
+ }
258
+ )
259
+
260
+ # 2. Initialize and run the Validator
261
+ validator = Validator(
262
+ contract_path="contracts/lofar_telemetry_odcs.yaml",
263
+ dataset_path="data/lofar_telemetry.parquet",
264
+ output_path="output/validated_telemetry.parquet",
265
+ quarantine_path="output/quarantined_telemetry.parquet",
266
+ config=config,
267
+ )
268
+
269
+ report = validator.run()
270
+
271
+ # 3. Inspect the strictly typed ValidationReport
272
+ summary = report["dataset"]
273
+ print(f"Total Evaluated: {summary['total_rows_evaluated']:,}")
274
+ print(f"Valid Rows: {summary['valid_rows']:,}")
275
+ print(f"Quarantined Rows: {summary['quarantined_rows']:,}")
276
+ print(f"Pipeline Status: {report['pipeline_status']}")
277
+
278
+ # 4. Enforce CI/CD Quality Gate programmatically
279
+ pipeline_ctx = report["_meta"]["pipeline_context"]
280
+ if pipeline_ctx and pipeline_ctx["exit_code"] != 0:
281
+ raise RuntimeError(
282
+ f"Data contract validation failed: {pipeline_ctx['reason']}"
283
+ )
284
+ ```
285
+
286
+ ### 3. Universal Configuration (`netra_config.yaml`)
287
+
288
+ Netra uses a centralized `netra_config.yaml` file to manage CI/CD quality gates and engine execution settings across the Netra suite. Global `pipeline` rules apply by default and can be overridden specifically for the validator under the `validator` block:
289
+
290
+ ```yaml
291
+ # ---------------------------------------------------------
292
+ # PIPELINE: Global CI/CD Quality Gate Defaults
293
+ # ---------------------------------------------------------
294
+ pipeline:
295
+ fail_on_critical: true # Exit with code 1 if CRITICAL anomalies are detected
296
+ fail_on_warnings: false # Exit with code 1 if ANY anomalies (Warning or Critical) are detected
297
+
298
+ # ---------------------------------------------------------
299
+ # VALIDATOR: Contract Execution & Out-of-Core Settings
300
+ # ---------------------------------------------------------
301
+ validator:
302
+ global_target: "raw" # Evaluate Pass 2 SQL rules on "raw" input or "validated" output
303
+
304
+ # Optional: Override global `pipeline` gates specifically for `netra validate`
305
+ pipeline:
306
+ fail_on_critical: true
307
+ fail_on_warnings: true
308
+
309
+ spill_to_disk:
310
+ enabled: false # Enable micro-batching and DuckDB disk spilling
311
+ memory_limit_mb: 16384 # Maximum RAM ceiling for DuckDB Pass 2 (16 GB default)
312
+ chunk_size: 50000 # Polars Pass 1 micro-batch row count when spilling is enabled
313
+ temp_directory: "/tmp/netra_spill"
314
+ min_spill_space_gb: 10 # Pre-flight disk free space requirement before starting a run
315
+ ```
316
+
317
+ Netra Validator automatically looks for `netra_config.yaml` in your current working directory. You can also pass it explicitly via CLI flag or environment variable:
318
+
319
+ ##### Using Command Line Flag
320
+
321
+ ```bash
322
+ netra validate dataset.parquet contract.yaml --config path/to/custom_config.yaml
323
+ ```
324
+
325
+ #### Environment Variable Overrides
326
+
327
+ To control CPU core allocation in shared or containerized environments, set the following environment variables before running Netra Validator:
328
+
329
+ ```bash
330
+ export NETRA_CONFIG="/etc/netra/production_config.yaml"
331
+ export NETRA_POLARS_THREADS=8
332
+ export NETRA_DUCKDB_THREADS=8
333
+ netra validate dataset.parquet contract.yaml
334
+ ```