Calc/.doc/refactoring/debug_api_docs.md

392 lines
10 KiB
Markdown

# Simple Debug API - Calculadora MAV CAS
## Descripción
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.
---
## Uso
```bash
# Ejecutar debug
python simple_debug.py debug_input.json
# Con archivo de salida específico
python simple_debug.py debug_input.json --output debug_results.json
# Modo verboso
python simple_debug.py debug_input.json --verbose
```
---
## Formato de Entrada
### Estructura Simple
```json
{
"queries": [
{"index": 0, "type": "input", "content": "10.1.1.1 + 1"},
{"index": 1, "type": "input", "content": "16#FF + 10"},
{"index": 2, "type": "exec", "content": "engine.symbol_table"},
{"index": 3, "type": "input", "content": "x = 5"},
{"index": 4, "type": "exec", "content": "len(engine.symbol_table)"}
]
}
```
### Tipos de Query
#### Input Query
Evalúa expresiones como si las escribieras en la calculadora:
```json
{"index": 0, "type": "input", "content": "10.1.1.1 + 1"}
{"index": 1, "type": "input", "content": "mask = 255.255.0.0"}
{"index": 2, "type": "input", "content": "solve(x**2 + 1, x)"}
```
#### Exec Query
Ejecuta código Python para inspeccionar el estado interno:
```json
{"index": 3, "type": "exec", "content": "engine.symbol_table"}
{"index": 4, "type": "exec", "content": "engine.parser.get_tokenization_info()"}
{"index": 5, "type": "exec", "content": "list(engine.base_context.keys())[:10]"}
```
---
## Formato de Salida
### Estructura de Respuesta
```json
{
"execution_info": {
"timestamp": "2025-01-01T10:30:15Z",
"total_queries": 5,
"successful": 4,
"failed": 1
},
"results": [
{
"index": 0,
"input": "10.1.1.1 + 1",
"output": "10.1.1.2",
"result_type": "FourBytes",
"success": true
},
{
"index": 1,
"input": "16#FF + 10",
"output": "16#109",
"result_type": "IntBase",
"success": true
},
{
"index": 2,
"input": "engine.symbol_table",
"output": "{'x': Symbol('x'), 'mask': FourBytes('255.255.0.0')}",
"result_type": "dict",
"success": true
}
]
}
```
### Resultado Individual
```json
{
"index": 0,
"input": "10.1.1.1 + 1",
"output": "10.1.1.2",
"result_type": "FourBytes",
"success": true,
"error": null,
"display_class": "[FourBytes]"
}
```
### Resultado con Error
```json
{
"index": 3,
"input": "IP4Mask(255.240.0.3)",
"output": null,
"result_type": null,
"success": false,
"error": "ValueError: Máscara inválida: 255.240.0.3"
}
```
### Resultado de Exec
```json
{
"index": 4,
"input": "len(engine.symbol_table)",
"output": "3",
"result_type": "int",
"success": true,
"exec_result": 3
}
```
---
## Casos de Uso Comunes
### 1. Debug de Tokenización
```json
{
"queries": [
{"index": 0, "type": "input", "content": "192.168.1.1 + 16#FF"},
{"index": 1, "type": "exec", "content": "engine.parser.process_expression('192.168.1.1 + 16#FF')"},
{"index": 2, "type": "exec", "content": "engine.parser.get_tokenization_info()"}
]
}
```
### 2. Debug de Contexto
```json
{
"queries": [
{"index": 0, "type": "input", "content": "x = 5"},
{"index": 1, "type": "input", "content": "y = x + 10"},
{"index": 2, "type": "exec", "content": "engine.symbol_table"},
{"index": 3, "type": "exec", "content": "len(engine.equations)"}
]
}
```
### 3. Debug de Tipos
```json
{
"queries": [
{"index": 0, "type": "input", "content": "ip = 10.1.1.x"},
{"index": 1, "type": "exec", "content": "type(engine.symbol_table['ip'])"},
{"index": 2, "type": "exec", "content": "engine.symbol_table['ip'].has_symbols"},
{"index": 3, "type": "input", "content": "ip.substitute(x=5)"}
]
}
```
### 4. Debug de Errores
```json
{
"queries": [
{"index": 0, "type": "input", "content": "bad_mask = 255.240.0.3"},
{"index": 1, "type": "input", "content": "IP4Mask(bad_mask)"},
{"index": 2, "type": "exec", "content": "engine.last_result"}
]
}
```
### 5. Testing de Regresión
```json
{
"queries": [
{"index": 0, "type": "input", "content": "10.1.1.1 + 1"},
{"index": 1, "type": "exec", "content": "str(type(engine.last_result))"},
{"index": 2, "type": "exec", "content": "engine.last_result.original"},
{"index": 3, "type": "input", "content": "16#FF + 10"},
{"index": 4, "type": "exec", "content": "engine.last_result.base"}
]
}
```
---
## Funciones Útiles para Exec
### Estado del Motor
```python
# Contexto y variables
"engine.symbol_table" # Variables actuales
"list(engine.base_context.keys())" # Funciones disponibles
"len(engine.equations)" # Ecuaciones en el sistema
"engine.last_result" # Último resultado
# Configuración del motor
"engine.symbolic_mode" # ¿Modo simbólico?
"engine.debug" # ¿Debug habilitado?
```
### Información de Tipos
```python
# Tipos registrados
"engine.get_available_types()" # Info completa de tipos
"list(engine.registered_types_info['registered_classes'].keys())" # Tipos disponibles
"engine.registered_types_info['class_count']" # Cantidad de tipos
# Análisis de objetos
"type(engine.last_result)" # Tipo del último resultado
"engine.last_result.__class__.__name__" # Nombre de la clase
"hasattr(engine.last_result, 'has_symbols')" # ¿Tiene símbolos?
```
### Tokenización y Parsing
```python
# Tokenización
"engine.parser.get_tokenization_info()" # Info de tokenización
"engine.parser.process_expression('test')" # Procesar expresión
"len(engine.parser.tokenizer.tokenization_rules)" # Cantidad de reglas
# Análisis de expresiones
"engine._classify_line('x = 5')" # Clasificar línea
"engine._extract_variable_names('x + y')" # Extraer variables
```
### Testing de Funciones Específicas
```python
# Testing de FourBytes
"engine.last_result._numeric_value" # Valor numérico interno
"engine.last_result.has_symbols" # ¿Tiene símbolos?
"engine.last_result.original" # String original
# Testing de IntBase
"engine.last_result.base" # Base numérica
"engine.last_result.value_str" # String del valor
"engine.last_result._symbols" # Símbolos detectados
```
---
## Implementación Simple
### Estructura Mínima
```
simple_debug.py # CLI principal (~100 líneas)
debug_templates/ # Templates de ejemplo
├── basic_test.json
├── tokenization_test.json
└── regression_test.json
```
### CLI Principal (Pseudocódigo)
```python
# simple_debug.py
import json
from main_evaluation import HybridEvaluationEngine
def run_debug(input_file, output_file=None):
# Cargar queries
with open(input_file) as f:
data = json.load(f)
# Crear motor
engine = HybridEvaluationEngine()
results = []
# Ejecutar cada query
for query in data['queries']:
if query['type'] == 'input':
result = engine.evaluate_line(query['content'])
output = {
'index': query['index'],
'input': query['content'],
'output': str(result.result),
'result_type': type(result.result).__name__,
'success': not result.is_error,
'error': result.error if result.is_error else None
}
elif query['type'] == 'exec':
try:
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,
'exec_result': exec_result
}
except Exception as e:
output = {
'index': query['index'],
'input': query['content'],
'success': False,
'error': str(e)
}
results.append(output)
# Guardar resultados
final_output = {
'execution_info': {...},
'results': results
}
with open(output_file, 'w') as f:
json.dump(final_output, f, indent=2)
```
---
## Templates de Ejemplo
### basic_test.json
```json
{
"queries": [
{"index": 0, "type": "input", "content": "10.1.1.1 + 1"},
{"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"},
{"index": 2, "type": "input", "content": "16#FF"},
{"index": 3, "type": "exec", "content": "engine.last_result.base"}
]
}
```
### tokenization_test.json
```json
{
"queries": [
{"index": 0, "type": "exec", "content": "engine.parser.process_expression('192.168.1.1 + 16#FF')"},
{"index": 1, "type": "input", "content": "192.168.1.1 + 16#FF"},
{"index": 2, "type": "exec", "content": "engine.parser.get_tokenization_info()['rules'][:3]"}
]
}
```
### regression_test.json
```json
{
"queries": [
{"index": 0, "type": "input", "content": "mask=255.240.0.0"},
{"index": 1, "type": "exec", "content": "type(engine.symbol_table['mask']).__name__"},
{"index": 2, "type": "input", "content": "10.1.1.1 + 1"},
{"index": 3, "type": "exec", "content": "type(engine.last_result).__name__"},
{"index": 4, "type": "input", "content": "IP4Mask(255.255.0.0)"},
{"index": 5, "type": "exec", "content": "engine.last_result.get_prefix_int()"}
]
}
```
---
## Ventajas de este Diseño
**Simplicidad**: ~100 líneas de código total
**Sin modificaciones**: Usa el motor existente tal como está
**Flexibilidad**: Cualquier función del engine es accesible via exec
**Debugging real**: Exactamente como usar la aplicación
**Fácil testing**: JSON simple para casos de prueba
**Serialización automática**: Python maneja la conversión a string
Esta aproximación te permite debuggear efectivamente sin crear una infraestructura compleja, usando el poder del motor existente.