Calc/setup_script.py

246 lines
7.7 KiB
Python

#!/usr/bin/env python3
"""
Script de setup e instalación para Calculadora MAV - CAS Híbrido
"""
import sys
import subprocess
import os
from pathlib import Path
import importlib.util
def check_python_version():
"""Verifica que la versión de Python sea compatible"""
if sys.version_info < (3, 8):
print("❌ Error: Se requiere Python 3.8 o superior")
print(f" Versión actual: {sys.version}")
return False
print(f"✅ Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
return True
def check_module(module_name, package_name=None, optional=False):
"""Verifica si un módulo está disponible"""
try:
importlib.import_module(module_name)
print(f"{module_name}")
return True
except ImportError:
if optional:
print(f"⚠️ {module_name} (opcional)")
else:
print(f"{module_name} - {'usar: pip install ' + (package_name or module_name)}")
return False
def install_requirements():
"""Instala las dependencias requeridas"""
print("\n=== Instalando dependencias ===")
requirements = [
"sympy>=1.12",
"matplotlib>=3.7.0",
"numpy>=1.24.0"
]
for req in requirements:
try:
print(f"Instalando {req}...")
subprocess.check_call([
sys.executable, "-m", "pip", "install", req
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print(f"{req}")
except subprocess.CalledProcessError:
print(f"❌ Error instalando {req}")
return False
return True
def check_tkinter():
"""Verifica que tkinter esté disponible"""
try:
import tkinter
print("✅ tkinter")
return True
except ImportError:
print("❌ tkinter - instalar python3-tk en Linux/Ubuntu")
print(" Ubuntu/Debian: sudo apt-get install python3-tk")
print(" CentOS/RHEL: sudo yum install tkinter")
print(" macOS: tkinter debe estar incluido con Python")
return False
def check_optional_modules():
"""Verifica módulos opcionales"""
optional_modules = [
("markdown", "markdown", True),
("tkinterweb", "tkinterweb", True),
("tkhtmlview", "tkhtmlview", True),
("pytest", "pytest", True)
]
for module_name, package_name, optional in optional_modules:
check_module(module_name, package_name, optional)
def create_desktop_shortcut():
"""Crea acceso directo en el escritorio (Linux/Windows)"""
current_dir = Path.cwd()
main_script = current_dir / "hybrid_calc_app.py"
if not main_script.exists():
print("⚠️ No se encontró hybrid_calc_app.py en el directorio actual")
return False
try:
if sys.platform.startswith('linux'):
# Linux desktop entry
desktop_dir = Path.home() / "Desktop"
if desktop_dir.exists():
shortcut_path = desktop_dir / "CalculadoraMAV.desktop"
shortcut_content = f"""[Desktop Entry]
Version=1.0
Type=Application
Name=Calculadora MAV - CAS Híbrido
Comment=Sistema de álgebra computacional híbrido
Exec={sys.executable} "{main_script}"
Icon=calculator
Terminal=false
Categories=Education;Science;Math;
"""
with open(shortcut_path, 'w') as f:
f.write(shortcut_content)
# Hacer ejecutable
os.chmod(shortcut_path, 0o755)
print(f"✅ Acceso directo creado: {shortcut_path}")
return True
elif sys.platform == 'win32':
# Windows shortcut (requiere pywin32)
try:
import win32com.client
desktop = Path.home() / "Desktop"
shortcut_path = desktop / "Calculadora MAV.lnk"
shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortCut(str(shortcut_path))
shortcut.Targetpath = sys.executable
shortcut.Arguments = f'"{main_script}"'
shortcut.WorkingDirectory = str(current_dir)
shortcut.IconLocation = sys.executable
shortcut.save()
print(f"✅ Acceso directo creado: {shortcut_path}")
return True
except ImportError:
print("⚠️ Para crear acceso directo en Windows instalar: pip install pywin32")
except Exception as e:
print(f"⚠️ Error creando acceso directo: {e}")
return False
def run_tests():
"""Ejecuta tests básicos"""
print("\n=== Ejecutando tests básicos ===")
try:
# Test de importación
from bracket_parser import BracketParser
from hybrid_base_types import Hex, Bin, IP4
from hybrid_evaluation_engine import HybridEvaluationEngine
print("✅ Importaciones básicas")
# Test de parser
parser = BracketParser()
result, info = parser.parse_line("Hex[FF]")
assert result == 'Hex("FF")', f"Parser test failed: {result}"
print("✅ Bracket parser")
# Test de clases híbridas
h = Hex("FF")
assert str(h) == "0xFF", f"Hex test failed: {h}"
print("✅ Clases híbridas")
# Test de motor de evaluación
engine = HybridEvaluationEngine()
result = engine.evaluate_line("2 + 3")
assert result.result == 5, f"Engine test failed: {result.result}"
print("✅ Motor de evaluación")
print("✅ Todos los tests básicos pasaron")
return True
except Exception as e:
print(f"❌ Error en tests: {e}")
return False
def main():
"""Función principal de setup"""
print("=== Calculadora MAV - CAS Híbrido - Setup ===\n")
# Verificar Python
if not check_python_version():
sys.exit(1)
print("\n=== Verificando dependencias ===")
# Verificar tkinter
if not check_tkinter():
print("\n❌ tkinter es requerido para la interfaz gráfica")
sys.exit(1)
# Verificar dependencias principales
deps_ok = True
deps_ok &= check_module("sympy")
deps_ok &= check_module("matplotlib")
deps_ok &= check_module("numpy")
# Si faltan dependencias, intentar instalar
if not deps_ok:
print("\n=== Faltan dependencias requeridas ===")
response = input("¿Instalar automáticamente? (s/n): ").lower().strip()
if response in ['s', 'si', 'y', 'yes']:
if not install_requirements():
print("❌ Error instalando dependencias")
sys.exit(1)
else:
print("❌ Instale las dependencias manualmente:")
print(" pip install sympy matplotlib numpy")
sys.exit(1)
# Verificar módulos opcionales
print("\n=== Módulos opcionales ===")
check_optional_modules()
# Ejecutar tests
if not run_tests():
print("❌ Tests fallaron")
sys.exit(1)
# Crear acceso directo
print("\n=== Configuración adicional ===")
response = input("¿Crear acceso directo en el escritorio? (s/n): ").lower().strip()
if response in ['s', 'si', 'y', 'yes']:
create_desktop_shortcut()
print("\n✅ ¡Setup completado exitosamente!")
print("\nPara ejecutar la calculadora:")
print(f" python {Path.cwd() / 'hybrid_calc_app.py'}")
print("\nO usa el acceso directo si lo creaste.")
if __name__ == "__main__":
main()