237 lines
8.2 KiB
Python
237 lines
8.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Simple Debug API - Calculadora MAV CAS
|
|
|
|
API CLI simple que usa el motor de evaluación existente para generar debug traces
|
|
sin modificar el código base. Permite debuggear "como si usaras la aplicación"
|
|
mediante archivos JSON.
|
|
|
|
Principio: texto → texto tal como se muestra en la aplicación.
|
|
No duplica lógica, solo encapsula llamadas directas.
|
|
|
|
Uso:
|
|
python simple_debug.py debug_input.json
|
|
python simple_debug.py debug_input.json --output debug_results.json
|
|
python simple_debug.py debug_input.json --verbose
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import argparse
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
# Importar motores de evaluación
|
|
from .evaluation import HybridEvaluationEngine
|
|
|
|
|
|
def run_debug(input_file: str, output_file: str = None, verbose: bool = False):
|
|
"""
|
|
Ejecuta las queries de debug desde un archivo JSON y guarda los resultados.
|
|
|
|
Args:
|
|
input_file: Archivo JSON con las queries
|
|
output_file: Archivo de salida (opcional)
|
|
verbose: Modo verboso
|
|
"""
|
|
|
|
# Cargar queries del archivo de entrada
|
|
try:
|
|
with open(input_file, 'r', encoding='utf-8') as f:
|
|
data = json.load(f)
|
|
except FileNotFoundError:
|
|
print(f"Error: No se encontró el archivo '{input_file}'")
|
|
sys.exit(1)
|
|
except json.JSONDecodeError as e:
|
|
print(f"Error: JSON inválido en '{input_file}': {e}")
|
|
sys.exit(1)
|
|
|
|
if 'queries' not in data:
|
|
print("Error: El archivo JSON debe contener una clave 'queries'")
|
|
sys.exit(1)
|
|
|
|
# Determinar qué motor usar
|
|
engine_module = data.get('engine_module', 'main_evaluation')
|
|
|
|
if verbose:
|
|
print(f"Usando motor: {engine_module}")
|
|
print("Iniciando motor de evaluación...")
|
|
|
|
# Crear motor de evaluación según el módulo especificado
|
|
if engine_module == 'main_evaluation_puro':
|
|
from .evaluation import PureAlgebraicEngine
|
|
engine = PureAlgebraicEngine()
|
|
else:
|
|
# Motor por defecto
|
|
engine = HybridEvaluationEngine()
|
|
results = []
|
|
successful = 0
|
|
failed = 0
|
|
|
|
# Ejecutar cada query
|
|
for query in data['queries']:
|
|
if verbose:
|
|
print(f"Ejecutando query {query.get('index', '?')}: {query.get('content', '')[:50]}...")
|
|
|
|
try:
|
|
if query['type'] == 'input':
|
|
# Query de tipo input: evaluar expresión como si fuera entrada del usuario
|
|
result = engine.evaluate_line(query['content'])
|
|
|
|
# Capturar resultado directo sin procesamiento
|
|
output = {
|
|
'index': query['index'],
|
|
'input': query['content'],
|
|
'output': str(result.result) if hasattr(result, 'result') else str(result),
|
|
'result_type': type(result.result).__name__ if hasattr(result, 'result') else type(result).__name__,
|
|
'success': not (hasattr(result, 'is_error') and result.is_error),
|
|
'error': result.error if hasattr(result, 'is_error') and result.is_error else None
|
|
}
|
|
|
|
if not (hasattr(result, 'is_error') and result.is_error):
|
|
successful += 1
|
|
else:
|
|
failed += 1
|
|
|
|
elif query['type'] == 'exec':
|
|
# Query de tipo exec: evaluar usando el motor adecuado
|
|
|
|
if engine_module == 'main_evaluation_puro':
|
|
# Para motor puro, evaluar directamente
|
|
result = engine.evaluate_line(query['content'])
|
|
|
|
output = {
|
|
'index': query['index'],
|
|
'input': query['content'],
|
|
'output': result.output,
|
|
'result_type': result.result_type,
|
|
'success': result.success,
|
|
'error': result.error_message
|
|
}
|
|
|
|
if result.success:
|
|
successful += 1
|
|
else:
|
|
failed += 1
|
|
else:
|
|
# Motor original: ejecutar código Python para inspeccionar el estado
|
|
exec_result = eval(query['content'], {'engine': engine})
|
|
|
|
output = {
|
|
'index': query['index'],
|
|
'input': query['content'],
|
|
'output': str(exec_result),
|
|
'result_type': type(exec_result).__name__,
|
|
'success': True,
|
|
'error': None,
|
|
'exec_result': exec_result
|
|
}
|
|
successful += 1
|
|
|
|
else:
|
|
raise ValueError(f"Tipo de query desconocido: {query['type']}")
|
|
|
|
except Exception as e:
|
|
# Manejar errores en la ejecución
|
|
output = {
|
|
'index': query['index'],
|
|
'input': query['content'],
|
|
'output': None,
|
|
'result_type': None,
|
|
'success': False,
|
|
'error': str(e)
|
|
}
|
|
failed += 1
|
|
|
|
if verbose:
|
|
print(f" Error: {str(e)}")
|
|
|
|
results.append(output)
|
|
|
|
# Preparar salida final
|
|
final_output = {
|
|
'execution_info': {
|
|
'timestamp': datetime.now().isoformat() + 'Z',
|
|
'total_queries': len(data['queries']),
|
|
'successful': successful,
|
|
'failed': failed,
|
|
'input_file': input_file
|
|
},
|
|
'results': results
|
|
}
|
|
|
|
# Determinar archivo de salida
|
|
if output_file is None:
|
|
base_name = Path(input_file).stem
|
|
output_file = f"{base_name}_results.json"
|
|
|
|
# Guardar resultados
|
|
try:
|
|
# Serialización simple con fallback a string
|
|
with open(output_file, 'w', encoding='utf-8') as f:
|
|
json.dump(final_output, f, indent=2, ensure_ascii=False, default=str)
|
|
|
|
if verbose:
|
|
print(f"\nResultados guardados en: {output_file}")
|
|
print(f"Queries exitosas: {successful}")
|
|
print(f"Queries con error: {failed}")
|
|
|
|
except Exception as e:
|
|
print(f"Error al guardar resultados: {e}")
|
|
sys.exit(1)
|
|
|
|
return final_output
|
|
|
|
|
|
def main():
|
|
"""Función principal del CLI"""
|
|
parser = argparse.ArgumentParser(
|
|
description='Simple Debug API para Calculadora MAV CAS',
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
Ejemplos de uso:
|
|
python simple_debug.py debug_input.json
|
|
python simple_debug.py debug_input.json --output custom_results.json
|
|
python simple_debug.py debug_input.json --verbose
|
|
"""
|
|
)
|
|
|
|
parser.add_argument('input_file',
|
|
help='Archivo JSON con las queries de debug')
|
|
parser.add_argument('--output', '-o',
|
|
help='Archivo de salida (por defecto: <input>_results.json)')
|
|
parser.add_argument('--verbose', '-v',
|
|
action='store_true',
|
|
help='Modo verboso')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Verificar que el archivo de entrada existe
|
|
if not Path(args.input_file).exists():
|
|
print(f"Error: El archivo '{args.input_file}' no existe")
|
|
sys.exit(1)
|
|
|
|
# Ejecutar debug
|
|
try:
|
|
results = run_debug(args.input_file, args.output, args.verbose)
|
|
|
|
# Mostrar resumen si no es modo verboso
|
|
if not args.verbose:
|
|
info = results['execution_info']
|
|
print(f"Debug completado: {info['successful']}/{info['total_queries']} exitosas")
|
|
if args.output:
|
|
print(f"Resultados en: {args.output}")
|
|
else:
|
|
base_name = Path(args.input_file).stem
|
|
print(f"Resultados en: {base_name}_results.json")
|
|
|
|
except KeyboardInterrupt:
|
|
print("\nInterrumpido por el usuario")
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"Error inesperado: {e}")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main() |