forked from im-anishraj/arnio
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck_env.py
More file actions
244 lines (207 loc) · 7.74 KB
/
Copy pathcheck_env.py
File metadata and controls
244 lines (207 loc) · 7.74 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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
"""Environment validation utility for Arnio examples and benchmarks.
-----------------------------------------------------------------
This script verifies the installation of optional development dependencies and
prints a beautifully formatted status dashboard indicating which example scripts
can be run.
"""
from __future__ import annotations
import platform
import shutil
import sys
from dataclasses import dataclass
from importlib.machinery import EXTENSION_SUFFIXES
from pathlib import Path
# Map import name to (install package name, description)
DEPENDENCIES = {
"numpy": (
"numpy",
"Required for basic array operations and benchmark data generation.",
),
"pandas": (
"pandas",
"Required for pandas DataFrame export and conversion examples.",
),
"duckdb": (
"duckdb",
"Required for high-performance database integration examples.",
),
"sklearn": (
"scikit-learn",
"Required for scikit-learn pipeline integration examples.",
),
"pytest": ("pytest", "Required for running the integration and unit test suites."),
}
@dataclass(frozen=True)
class BuildToolCheck:
"""Status for a local build tool required by Arnio's native extension."""
name: str
command: str
available: bool
detail: str
required: bool = True
# Map example script name to its list of optional dependency keys
EXAMPLES = {
"basic_usage.py": [],
"custom_step.py": ["pandas"],
"arnio_with_numpy.py": ["numpy"],
"arnio_with_pandas.py": ["pandas"],
"arnio_with_duckdb.py": ["duckdb", "pandas"],
"arnio_with_sklearn.py": ["sklearn", "pandas"],
"sklearn_pipeline.py": ["sklearn", "pandas"],
"auto_clean_tutorial.py": ["pandas"],
"arnio_with_jsonl.py": ["pandas"],
}
def check_dependencies():
"""Verify presence of optional dependencies."""
results = {}
for lib in DEPENDENCIES:
try:
__import__(lib)
results[lib] = (True, "Installed")
except ImportError as exc:
if exc.name and exc.name != lib:
results[lib] = (False, f"Import failed: missing {exc.name}")
else:
results[lib] = (False, f"Not Installed ({lib})")
except Exception as exc: # pragma: no cover - defensive diagnostic path
results[lib] = (False, f"Import failed: {type(exc).__name__}: {exc}")
return results
def check_build_tools():
"""Check whether source-build tools are visible in the current shell."""
system = platform.system()
checks = [
BuildToolCheck(
name="CMake",
command="cmake",
available=shutil.which("cmake") is not None,
detail="Required by scikit-build-core to configure the C++ extension.",
),
]
if system == "Windows":
checks.extend(
[
BuildToolCheck(
name="MSVC compiler",
command="cl",
available=shutil.which("cl") is not None,
detail=(
"Install Visual Studio Build Tools with Desktop development "
"with C++, then use a Developer Command Prompt."
),
),
BuildToolCheck(
name="NMake",
command="nmake",
available=shutil.which("nmake") is not None,
detail=(
"CMake may choose NMake on Windows; nmake must be on PATH "
"or another generator must be configured."
),
),
]
)
else:
checks.append(
BuildToolCheck(
name="C++ compiler",
command="c++",
available=any(
shutil.which(command) is not None
for command in ("c++", "g++", "clang++")
),
detail="Required to compile Arnio's native C++ extension.",
)
)
return checks
def detect_core_status():
"""Detect the native extension without importing the full arnio package."""
if "arnio._core" in sys.modules:
if sys.modules["arnio._core"] is None:
return "Not Compiled (arnio._core unavailable)", False
return "Available (C++ Accelerated)", True
for entry in sys.path:
package_dir = Path(entry or ".") / "arnio"
if not package_dir.is_dir():
continue
for suffix in EXTENSION_SUFFIXES:
if (package_dir / f"_arnio_cpp{suffix}").exists():
return "Available (C++ Accelerated)", True
return "Not Compiled (_arnio_cpp extension file not found)", False
def print_build_tool_status(build_tools):
"""Print build-tool checks and setup tips."""
print("Build Toolchain Status:")
blocked = False
for check in build_tools:
mark = "[OK]" if check.available else "[X]"
required = "required" if check.required else "optional"
print(f" - {check.name:<15} {mark:<4} {check.command:<10} ({required})")
if check.required and not check.available:
blocked = True
print(f" Tip: {check.detail}")
if blocked:
print(
'\n[BUILD BLOCKED] Source installs like `pip install -e ".[dev]"` '
"may fail until the missing build tools are available."
)
if platform.system() == "Windows":
print(
"Windows fix: install Visual Studio Build Tools 2022 with the "
"`Desktop development with C++` workload, then reopen an x64 "
"Developer Command Prompt and retry."
)
else:
print("\nBuild toolchain looks ready for a local native-extension build.")
def print_dashboard(results, build_tools=None):
"""Print a clean dashboard of the check results."""
if build_tools is None:
build_tools = check_build_tools()
print("=" * 70)
print(" ARNIO DEVELOPMENT ENVIRONMENT STATUS ")
print("=" * 70)
# Check Arnio C++ Core status
core_status, core_available = detect_core_status()
print(f"Arnio Core Module: {core_status}")
print(f"Python Version: {sys.version.split()[0]}")
print(f"Platform: {platform.platform()}")
print("-" * 70)
print(f"{'Dependency':<15} | {'Status':<15} | {'Description'}")
print("-" * 70)
for lib, (status, status_str) in results.items():
package, desc = DEPENDENCIES[lib]
mark = "[OK]" if status else "[X]"
print(f"{lib:<15} | {mark:<15} | {desc}")
if not status:
print(f"{'':<15} | {'':<15} | {status_str}")
print("-" * 70)
print_build_tool_status(build_tools)
print("-" * 70)
# Suggest runnable examples based on core status and packages found
print("Runnable Examples Status:")
for name, reqs in EXAMPLES.items():
if not core_available:
status = "[Missing arnio core]"
else:
missing_reqs = [r for r in reqs if not results[r][0]]
if missing_reqs:
status = f"[Missing {'/'.join(missing_reqs)}]"
else:
status = "[Ready]"
print(f" - {name:<26} : {status}")
missing = []
for lib, (status, _) in results.items():
if not status:
package, _ = DEPENDENCIES[lib]
missing.append(package)
if missing:
print("\n[TIP] To install all missing optional dependencies, run:")
print(f" pip install {' '.join(missing)}")
else:
print(
"\nAll optional dependencies are successfully installed! You are ready to go."
)
print("=" * 70)
def main():
results = check_dependencies()
print_dashboard(results)
if __name__ == "__main__":
main()