scripts/distribution_sensitivity.py
3.2 KB| 1 | #!/usr/bin/env python3 |
| 2 | """Bounded distribution, transformation, and outlier sensitivity CLI.""" |
| 3 | |
| 4 | from __future__ import annotations |
| 5 | |
| 6 | import argparse |
| 7 | |
| 8 | from _capabilities import capability_for_path |
| 9 | from _common import ( |
| 10 | DEFAULT_MAX_FILE_BYTES, |
| 11 | DEFAULT_MAX_ROWS, |
| 12 | bounded_file_limit, |
| 13 | checked_input_file, |
| 14 | emit_json, |
| 15 | run_cli, |
| 16 | ) |
| 17 | from _tabular import audit_distributions |
| 18 | |
| 19 | |
| 20 | def build_parser() -> argparse.ArgumentParser: |
| 21 | parser = argparse.ArgumentParser( |
| 22 | description=( |
| 23 | "Compare classical and robust summaries on bounded CSV/TSV data. " |
| 24 | "The command never deletes, winsorizes, transforms, or imputes source data." |
| 25 | ) |
| 26 | ) |
| 27 | parser.add_argument("input", help="Local .csv or .tsv path inside --root") |
| 28 | parser.add_argument( |
| 29 | "--root", |
| 30 | default=".", |
| 31 | help="Existing local directory that bounds all input/output paths", |
| 32 | ) |
| 33 | parser.add_argument( |
| 34 | "--max-bytes", |
| 35 | type=int, |
| 36 | default=DEFAULT_MAX_FILE_BYTES, |
| 37 | help=f"Maximum input bytes (hard ceiling: {512 * 1024 * 1024})", |
| 38 | ) |
| 39 | parser.add_argument( |
| 40 | "--max-rows", |
| 41 | type=int, |
| 42 | default=DEFAULT_MAX_ROWS, |
| 43 | help="Maximum rows to scan (hard ceiling: 1000000)", |
| 44 | ) |
| 45 | parser.add_argument( |
| 46 | "--column", |
| 47 | action="append", |
| 48 | help=( |
| 49 | "Exact numeric column identifier; repeat as needed. Without this flag, " |
| 50 | "the first 64 columns are screened." |
| 51 | ), |
| 52 | ) |
| 53 | parser.add_argument( |
| 54 | "--missing-token", |
| 55 | action="append", |
| 56 | help="Explicit additional missing code; repeat as needed", |
| 57 | ) |
| 58 | parser.add_argument( |
| 59 | "--reveal-identifiers", |
| 60 | action="store_true", |
| 61 | help="Emit sanitized column identifiers; values remain redacted", |
| 62 | ) |
| 63 | parser.add_argument("--output", help="Optional local .json output path") |
| 64 | parser.add_argument( |
| 65 | "--force", |
| 66 | action="store_true", |
| 67 | help="Allow replacement of an existing regular output file", |
| 68 | ) |
| 69 | return parser |
| 70 | |
| 71 | |
| 72 | def _main() -> None: |
| 73 | args = build_parser().parse_args() |
| 74 | max_bytes = bounded_file_limit(args.max_bytes) |
| 75 | path = checked_input_file( |
| 76 | args.input, |
| 77 | root=args.root, |
| 78 | suffixes={".csv", ".tsv"}, |
| 79 | max_bytes=max_bytes, |
| 80 | ) |
| 81 | report = { |
| 82 | "schema_version": "1.1", |
| 83 | "capability": capability_for_path(path), |
| 84 | "analysis": audit_distributions( |
| 85 | path, |
| 86 | columns=args.column, |
| 87 | max_rows=args.max_rows, |
| 88 | missing_tokens=args.missing_token, |
| 89 | reveal_identifiers=args.reveal_identifiers, |
| 90 | ), |
| 91 | "security": { |
| 92 | "local_only": True, |
| 93 | "file_text_is_untrusted_data": True, |
| 94 | "embedded_instructions_followed": False, |
| 95 | "raw_values_and_paths_emitted": False, |
| 96 | }, |
| 97 | "decisions": { |
| 98 | "automatic_outlier_deletion": False, |
| 99 | "automatic_transformation": False, |
| 100 | "automatic_imputation": False, |
| 101 | "hypothesis_tests_run": 0, |
| 102 | }, |
| 103 | } |
| 104 | emit_json( |
| 105 | report, |
| 106 | output=args.output, |
| 107 | root=args.root, |
| 108 | force=args.force, |
| 109 | ) |
| 110 | |
| 111 | |
| 112 | def main() -> int: |
| 113 | return run_cli(_main) |
| 114 | |
| 115 | |
| 116 | if __name__ == "__main__": |
| 117 | raise SystemExit(main()) |
文件内容是平台检查时读出的文本,只供查看。平台不会运行包里的任何脚本或程序。

