data-detective-toolkit 0.3.1__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.
- data_detective/__init__.py +0 -0
- data_detective/cli.py +108 -0
- data_detective/exceptions.py +10 -0
- data_detective/html_report.py +730 -0
- data_detective/loader.py +52 -0
- data_detective/profiler.py +443 -0
- data_detective/report.py +57 -0
- data_detective_toolkit-0.3.1.dist-info/METADATA +271 -0
- data_detective_toolkit-0.3.1.dist-info/RECORD +13 -0
- data_detective_toolkit-0.3.1.dist-info/WHEEL +5 -0
- data_detective_toolkit-0.3.1.dist-info/entry_points.txt +2 -0
- data_detective_toolkit-0.3.1.dist-info/licenses/LICENSE +21 -0
- data_detective_toolkit-0.3.1.dist-info/top_level.txt +1 -0
|
File without changes
|
data_detective/cli.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from data_detective.exceptions import DataLoadError
|
|
7
|
+
from data_detective.html_report import generate_html_report
|
|
8
|
+
from data_detective.loader import load_csv
|
|
9
|
+
from data_detective.profiler import DataProfiler
|
|
10
|
+
from data_detective.report import print_report
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# -----------------------------
|
|
14
|
+
# COMMAND HANDLER
|
|
15
|
+
# -----------------------------
|
|
16
|
+
def run_analyze(args):
|
|
17
|
+
if not args.quiet:
|
|
18
|
+
print("🔥 Data Detective starting...\n")
|
|
19
|
+
|
|
20
|
+
df = load_csv(args.file)
|
|
21
|
+
profiler = DataProfiler(df)
|
|
22
|
+
report = profiler.run_full_profile(outlier_method=args.outlier_method)
|
|
23
|
+
|
|
24
|
+
emit_html = args.html or bool(args.output_html)
|
|
25
|
+
emit_json = args.json or bool(args.output_json)
|
|
26
|
+
|
|
27
|
+
if emit_html:
|
|
28
|
+
output_html_path = args.output_html or "report.html"
|
|
29
|
+
generate_html_report(report, output_path=output_html_path)
|
|
30
|
+
|
|
31
|
+
if emit_json:
|
|
32
|
+
payload = json.dumps(report, indent=2)
|
|
33
|
+
if args.output_json:
|
|
34
|
+
Path(args.output_json).write_text(payload + "\n", encoding="utf-8")
|
|
35
|
+
elif args.json:
|
|
36
|
+
print(payload)
|
|
37
|
+
|
|
38
|
+
if emit_html or emit_json:
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
if not args.json and not args.html:
|
|
42
|
+
print_report(report)
|
|
43
|
+
|
|
44
|
+
return 0
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# -----------------------------
|
|
48
|
+
# CLI SETUP
|
|
49
|
+
# -----------------------------
|
|
50
|
+
def build_parser():
|
|
51
|
+
parser = argparse.ArgumentParser(
|
|
52
|
+
prog="data-detective",
|
|
53
|
+
description="🕵️ Data Detective - Smart Data Profiling Tool"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
subparsers = parser.add_subparsers(dest="command")
|
|
57
|
+
|
|
58
|
+
analyze_parser = subparsers.add_parser(
|
|
59
|
+
"analyze",
|
|
60
|
+
help="Analyze a CSV file"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
analyze_parser.add_argument("file", help="Path to CSV file")
|
|
64
|
+
analyze_parser.add_argument("--json", action="store_true", help="Output JSON report")
|
|
65
|
+
analyze_parser.add_argument("--html", action="store_true", help="Generate HTML report")
|
|
66
|
+
analyze_parser.add_argument("--output-json", help="Write JSON report to the given file path")
|
|
67
|
+
analyze_parser.add_argument("--output-html", help="Write HTML report to the given file path")
|
|
68
|
+
analyze_parser.add_argument(
|
|
69
|
+
"--outlier-method",
|
|
70
|
+
choices=["iqr", "mad"],
|
|
71
|
+
default="mad",
|
|
72
|
+
help="Outlier detection method used for insights (default: mad)",
|
|
73
|
+
)
|
|
74
|
+
analyze_parser.add_argument(
|
|
75
|
+
"--quiet",
|
|
76
|
+
action="store_true",
|
|
77
|
+
help="Suppress non-error progress messages",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
analyze_parser.set_defaults(func=run_analyze)
|
|
81
|
+
|
|
82
|
+
return parser
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# -----------------------------
|
|
86
|
+
# MAIN ENTRY POINT
|
|
87
|
+
# -----------------------------
|
|
88
|
+
def main():
|
|
89
|
+
parser = build_parser()
|
|
90
|
+
args = parser.parse_args()
|
|
91
|
+
|
|
92
|
+
if not hasattr(args, "func"):
|
|
93
|
+
parser.print_help()
|
|
94
|
+
return 1
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
return args.func(args)
|
|
98
|
+
except DataLoadError as e:
|
|
99
|
+
print(f"❌ {e}", file=sys.stderr)
|
|
100
|
+
return 1
|
|
101
|
+
except Exception as e:
|
|
102
|
+
print(f"❌ Unexpected error: {e}", file=sys.stderr)
|
|
103
|
+
return 1
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# REQUIRED ENTRY POINT
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
sys.exit(main())
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class DataDetectiveError(Exception):
|
|
2
|
+
"""Base exception for data-detective errors."""
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DataLoadError(DataDetectiveError):
|
|
6
|
+
"""Raised when CSV loading fails."""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EmptyDataError(DataLoadError):
|
|
10
|
+
"""Raised when the loaded dataset is empty."""
|