-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
173 lines (137 loc) · 5.54 KB
/
Copy pathmain.py
File metadata and controls
173 lines (137 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
"""DevCheck: a command-line developer environment checker.
DevCheck scans a computer for common development tools, reports whether each
one is installed and which version it is, and can export or compare scan
results. It never installs, uninstalls, modifies, or updates any software -
it only inspects the system.
Run with:
python main.py
"""
from pathlib import Path
from typing import Dict, Optional, Tuple
from checker import EnvironmentChecker
from config import DATA_DIR_NAME, REPORTS_DIR_NAME, SCAN_HISTORY_FILENAME
from history import compare_scans, load_scan, print_comparison, save_scan
from reports import build_report, export_to_csv, export_to_json, print_scan_table
from utils import ensure_directory, get_project_root
PROJECT_ROOT = get_project_root()
DATA_DIR = PROJECT_ROOT / DATA_DIR_NAME
REPORTS_DIR = PROJECT_ROOT / REPORTS_DIR_NAME
HISTORY_PATH = DATA_DIR / SCAN_HISTORY_FILENAME
def run_full_scan(checker: EnvironmentChecker) -> Tuple[Optional[Dict], Dict]:
"""Run a full scan, print it, save it to history, and return (old, new) reports.
The report on disk *before* this scan is returned as "old" so the caller
can immediately compare it against the fresh "new" report, in addition to
it being available for comparisons in future runs of the program.
"""
previous_report = load_scan(HISTORY_PATH)
results = checker.scan_all()
current_report = build_report(results)
print()
print_scan_table(results)
ensure_directory(DATA_DIR)
save_scan(current_report, HISTORY_PATH)
return previous_report, current_report
def run_single_tool_check(checker: EnvironmentChecker) -> None:
"""Prompt for a tool name and print its individual check result."""
print()
print("Available tools:")
for index, name in enumerate(checker.list_tool_names(), start=1):
print(f" {index}. {name}")
choice = input("\nEnter the tool name to check: ").strip()
if not choice:
print("No tool name entered.")
return
result = checker.check_tool_by_name(choice)
if result is None:
print(f"'{choice}' is not in the list of known tools.")
return
print()
print(f"Tool: {result.name}")
print(f"Status: {result.status.value}")
print(f"Version: {result.version if result.version else '-'}")
print(f"Path: {result.path if result.path else '-'}")
if result.error:
print(f"Note: {result.error}")
def view_previous_scan() -> None:
"""Print the most recently saved scan from disk, if one exists."""
report = load_scan(HISTORY_PATH)
if report is None:
print("\nNo previous scan found. Run a full scan first (option 1).")
return
print()
print(f"Last scan timestamp: {report.get('timestamp', 'Unknown')}")
print(f"Operating system: {report.get('operating_system', 'Unknown')}")
print()
print(f"{'Tool':<18}{'Status':<32}{'Version'}")
for entry in report.get("results", []):
print(f"{entry['tool']:<18}{entry['status']:<32}{entry['version']}")
def compare_with_previous(previous_report: Optional[Dict], current_report: Optional[Dict]) -> None:
"""Compare the two most recent reports and print the differences."""
if current_report is None:
print("\nRun a full scan first (option 1), then use this option to compare.")
return
if previous_report is None:
print("\nThis looks like the first scan on record. Run another scan later to compare.")
return
print()
print_comparison(compare_scans(previous_report, current_report))
def export_report(checker: EnvironmentChecker) -> None:
"""Run a fresh scan and export it to JSON, CSV, or both."""
results = checker.scan_all()
report = build_report(results)
ensure_directory(REPORTS_DIR)
print("\nExport format:")
print(" 1. JSON")
print(" 2. CSV")
print(" 3. Both")
choice = input("Choose an option: ").strip()
if choice not in ("1", "2", "3"):
print("Invalid choice. No report exported.")
return
if choice in ("1", "3"):
json_path = REPORTS_DIR / "scan_report.json"
export_to_json(report, json_path)
print(f"JSON report saved to: {json_path}")
if choice in ("2", "3"):
csv_path = REPORTS_DIR / "scan_report.csv"
export_to_csv(report, csv_path)
print(f"CSV report saved to: {csv_path}")
def print_menu() -> None:
"""Print the main DevCheck menu."""
print()
print("=" * 32)
print("DEVCHECK")
print("=" * 8)
print()
print("1. Full Environment Scan")
print("2. Check a Specific Tool")
print("3. View Previous Scan")
print("4. Compare Scans")
print("5. Export Report")
print("6. Exit")
print()
def main() -> None:
"""Run the interactive DevCheck menu loop."""
checker = EnvironmentChecker()
previous_report: Optional[Dict] = None
current_report: Optional[Dict] = None
while True:
print_menu()
choice = input("Choose an option: ").strip()
if choice == "1":
previous_report, current_report = run_full_scan(checker)
elif choice == "2":
run_single_tool_check(checker)
elif choice == "3":
view_previous_scan()
elif choice == "4":
compare_with_previous(previous_report, current_report)
elif choice == "5":
export_report(checker)
elif choice == "6":
print("\nExiting DevCheck. Goodbye!")
break
else:
print("\nInvalid option. Please choose a number between 1 and 6.")
if __name__ == "__main__":
main()