Spaces:
Running
Running
#!/usr/bin/env python3 | |
""" | |
Comprehensive startup validation script for Web3 Research Co-Pilot | |
Validates syntax, imports, and configurations before application startup | |
""" | |
import ast | |
import sys | |
import os | |
import json | |
import importlib.util | |
from pathlib import Path | |
from typing import List, Dict, Any, Tuple | |
def validate_python_syntax(file_path: str) -> Tuple[bool, str]: | |
"""Validate Python file syntax.""" | |
try: | |
with open(file_path, 'r', encoding='utf-8') as f: | |
source = f.read() | |
ast.parse(source) | |
return True, "OK" | |
except SyntaxError as e: | |
return False, f"Syntax error at line {e.lineno}: {e.msg}" | |
except Exception as e: | |
return False, f"Parse error: {str(e)}" | |
def validate_imports(file_path: str) -> Tuple[bool, List[str]]: | |
"""Validate that all imports in a Python file can be resolved.""" | |
issues = [] | |
try: | |
with open(file_path, 'r', encoding='utf-8') as f: | |
source = f.read() | |
tree = ast.parse(source) | |
for node in ast.walk(tree): | |
if isinstance(node, ast.Import): | |
for alias in node.names: | |
try: | |
importlib.import_module(alias.name) | |
except ImportError: | |
issues.append(f"Cannot import: {alias.name}") | |
elif isinstance(node, ast.ImportFrom): | |
if node.module: | |
try: | |
importlib.import_module(node.module) | |
except ImportError: | |
issues.append(f"Cannot import module: {node.module}") | |
return len(issues) == 0, issues | |
except Exception as e: | |
return False, [f"Import validation error: {str(e)}"] | |
def validate_json_files() -> Tuple[bool, List[str]]: | |
"""Validate JSON configuration files.""" | |
issues = [] | |
json_files = [ | |
"pyproject.toml", # Will skip if not JSON | |
"app_config.yaml" # Will skip if not JSON | |
] | |
for file_path in json_files: | |
if os.path.exists(file_path) and file_path.endswith('.json'): | |
try: | |
with open(file_path, 'r') as f: | |
json.load(f) | |
except json.JSONDecodeError as e: | |
issues.append(f"Invalid JSON in {file_path}: {str(e)}") | |
except Exception as e: | |
issues.append(f"Error reading {file_path}: {str(e)}") | |
return len(issues) == 0, issues | |
def validate_environment_variables() -> Tuple[bool, List[str]]: | |
"""Validate required environment variables.""" | |
issues = [] | |
optional_vars = [ | |
"CRYPTOCOMPARE_API_KEY", | |
"ETHERSCAN_API_KEY", | |
"COINGECKO_API_KEY" | |
] | |
for var in optional_vars: | |
if not os.getenv(var): | |
issues.append(f"Optional environment variable {var} not set (will use free tier)") | |
return True, issues # All env vars are optional | |
def main(): | |
"""Run comprehensive startup validation.""" | |
print("π Starting comprehensive validation...") | |
# Get all Python files | |
python_files = [] | |
for root, dirs, files in os.walk("."): | |
# Skip __pycache__ directories | |
dirs[:] = [d for d in dirs if d != "__pycache__"] | |
for file in files: | |
if file.endswith(".py"): | |
python_files.append(os.path.join(root, file)) | |
print(f"π Found {len(python_files)} Python files to validate") | |
all_valid = True | |
# 1. Syntax validation | |
print("\n1οΈβ£ Validating Python syntax...") | |
syntax_issues = [] | |
for file_path in python_files: | |
is_valid, message = validate_python_syntax(file_path) | |
if not is_valid: | |
syntax_issues.append(f"{file_path}: {message}") | |
all_valid = False | |
else: | |
print(f" β {file_path}") | |
if syntax_issues: | |
print("β Syntax Issues Found:") | |
for issue in syntax_issues: | |
print(f" - {issue}") | |
# 2. Critical imports validation (only for main files) | |
print("\n2οΈβ£ Validating critical imports...") | |
critical_files = ["app.py", "src/agent/research_agent.py"] | |
import_issues = [] | |
for file_path in critical_files: | |
if os.path.exists(file_path): | |
is_valid, issues = validate_imports(file_path) | |
if not is_valid: | |
for issue in issues: | |
import_issues.append(f"{file_path}: {issue}") | |
else: | |
print(f" β {file_path}") | |
# Show non-critical import issues as warnings | |
if import_issues: | |
print("β οΈ Import Warnings (may use fallbacks):") | |
for issue in import_issues: | |
print(f" - {issue}") | |
# 3. JSON validation | |
print("\n3οΈβ£ Validating configuration files...") | |
json_valid, json_issues = validate_json_files() | |
if not json_valid: | |
print("β Configuration Issues:") | |
for issue in json_issues: | |
print(f" - {issue}") | |
all_valid = False | |
else: | |
print(" β Configuration files valid") | |
# 4. Environment validation | |
print("\n4οΈβ£ Validating environment...") | |
env_valid, env_issues = validate_environment_variables() | |
if env_issues: | |
print("βΉοΈ Environment Info:") | |
for issue in env_issues: | |
print(f" - {issue}") | |
else: | |
print(" β Environment configured") | |
# Final result | |
print(f"\n{'π' if all_valid else 'β'} Validation {'PASSED' if all_valid else 'FAILED'}") | |
if not all_valid: | |
print("\nπ οΈ Please fix the issues above before starting the application") | |
sys.exit(1) | |
else: | |
print("\nβ All critical validations passed - ready to start!") | |
sys.exit(0) | |
if __name__ == "__main__": | |
main() | |