Refactor code structure for improved readability and maintainability
This commit is contained in:
parent
f68bea6056
commit
480e831b7a
82
app.py
82
app.py
|
@ -42,8 +42,12 @@ websocket_connections = set()
|
|||
# --- Globals for Tray Icon ---
|
||||
tray_icon = None
|
||||
|
||||
# --- Log batching optimization ---
|
||||
log_batch_buffer = []
|
||||
log_batch_lock = threading.Lock()
|
||||
batch_timer = None
|
||||
|
||||
|
||||
# --- Parámetros para envío directo de logs (optimizado) ---
|
||||
def _send_message_to_clients(message: str):
|
||||
"""Envía un mensaje directamente a todas las conexiones WebSocket activas."""
|
||||
if not websocket_connections:
|
||||
|
@ -59,6 +63,29 @@ def _send_message_to_clients(message: str):
|
|||
websocket_connections.difference_update(dead_connections)
|
||||
|
||||
|
||||
def _flush_log_batch():
|
||||
"""Envía todos los logs acumulados en el batch y limpia el buffer."""
|
||||
global log_batch_buffer, batch_timer
|
||||
|
||||
with log_batch_lock:
|
||||
if log_batch_buffer:
|
||||
# Unir todos los logs del batch en un solo mensaje
|
||||
batch_message = "".join(log_batch_buffer)
|
||||
_send_message_to_clients(batch_message)
|
||||
log_batch_buffer.clear()
|
||||
|
||||
batch_timer = None
|
||||
|
||||
|
||||
def _schedule_batch_flush():
|
||||
"""Programa el envío del batch de logs en 1 segundo si no está ya programado."""
|
||||
global batch_timer
|
||||
|
||||
if batch_timer is None:
|
||||
batch_timer = threading.Timer(1.0, _flush_log_batch)
|
||||
batch_timer.start()
|
||||
|
||||
|
||||
@sock.route("/ws")
|
||||
def handle_websocket(ws):
|
||||
try:
|
||||
|
@ -73,8 +100,15 @@ def handle_websocket(ws):
|
|||
websocket_connections.remove(ws)
|
||||
|
||||
|
||||
def broadcast_message(message):
|
||||
"""Envía mensajes directamente via WebSocket (optimizado)."""
|
||||
def broadcast_message(message, immediate=False):
|
||||
"""Envía mensajes via WebSocket con batching optimizado.
|
||||
|
||||
Args:
|
||||
message: El mensaje o lista de mensajes a enviar
|
||||
immediate: Si True, envía inmediatamente. Si False, usa batching
|
||||
"""
|
||||
global log_batch_buffer
|
||||
|
||||
timestamp = datetime.now().strftime("[%H:%M:%S] ")
|
||||
|
||||
# Normalizar entrada a lista de mensajes
|
||||
|
@ -98,9 +132,17 @@ def broadcast_message(message):
|
|||
# Registrar en archivo (la clase Logger añade timestamp propio)
|
||||
config_manager.append_log(raw_msg)
|
||||
|
||||
# Enviar inmediatamente via WebSocket con timestamp
|
||||
# Formatear mensaje para WebSocket
|
||||
formatted_msg_for_ws = f"{timestamp}{raw_msg}\n"
|
||||
|
||||
if immediate:
|
||||
# Envío inmediato para mensajes críticos
|
||||
_send_message_to_clients(formatted_msg_for_ws)
|
||||
else:
|
||||
# Batching para logs normales
|
||||
with log_batch_lock:
|
||||
log_batch_buffer.append(formatted_msg_for_ws)
|
||||
_schedule_batch_flush()
|
||||
|
||||
|
||||
@app.route("/api/execute_script", methods=["POST"])
|
||||
|
@ -109,15 +151,19 @@ def execute_script():
|
|||
script_group = request.json["group"]
|
||||
script_name = request.json["script"]
|
||||
|
||||
# Crear callback que usa batching para logs normales
|
||||
def batched_broadcast(message):
|
||||
return broadcast_message(message, immediate=False)
|
||||
|
||||
# Ejecutar el script y obtener resultado
|
||||
result = config_manager.execute_script(
|
||||
script_group, script_name, broadcast_message
|
||||
script_group, script_name, batched_broadcast
|
||||
)
|
||||
|
||||
return jsonify(result)
|
||||
except Exception as e:
|
||||
error_msg = f"Error ejecutando script: {str(e)}"
|
||||
broadcast_message(error_msg)
|
||||
broadcast_message(error_msg, immediate=True)
|
||||
return jsonify({"error": error_msg})
|
||||
|
||||
|
||||
|
@ -127,15 +173,19 @@ def stop_script():
|
|||
script_group = request.json["group"]
|
||||
script_name = request.json["script"]
|
||||
|
||||
# Crear callback que usa batching para logs normales
|
||||
def batched_broadcast(message):
|
||||
return broadcast_message(message, immediate=False)
|
||||
|
||||
# Detener el script en ejecución
|
||||
result = config_manager.stop_script(
|
||||
script_group, script_name, broadcast_message
|
||||
script_group, script_name, batched_broadcast
|
||||
)
|
||||
|
||||
return jsonify(result)
|
||||
except Exception as e:
|
||||
error_msg = f"Error deteniendo script: {str(e)}"
|
||||
broadcast_message(error_msg)
|
||||
broadcast_message(error_msg, immediate=True)
|
||||
return jsonify({"error": error_msg})
|
||||
|
||||
|
||||
|
@ -571,10 +621,10 @@ def update_backend_setup():
|
|||
message += f" ({len(errors)} errores)"
|
||||
|
||||
# Log del resultado
|
||||
broadcast_message(f"🔄 {message}")
|
||||
broadcast_message(f"🔄 {message}", immediate=True)
|
||||
if errors:
|
||||
for error in errors:
|
||||
broadcast_message(f"❌ {error}")
|
||||
broadcast_message(f"❌ {error}", immediate=True)
|
||||
|
||||
return jsonify(
|
||||
{
|
||||
|
@ -589,7 +639,7 @@ def update_backend_setup():
|
|||
except Exception as e:
|
||||
error_msg = f"Error en update_backend_setup: {str(e)}"
|
||||
print(error_msg)
|
||||
broadcast_message(f"❌ {error_msg}")
|
||||
broadcast_message(f"❌ {error_msg}", immediate=True)
|
||||
return jsonify({"status": "error", "message": error_msg}), 500
|
||||
|
||||
|
||||
|
@ -721,6 +771,10 @@ def stop_icon_thread():
|
|||
def shutdown_route():
|
||||
"""Internal route to shut down the application via the tray icon."""
|
||||
print("Shutdown endpoint called.")
|
||||
|
||||
# Enviar logs pendientes antes de cerrar
|
||||
_flush_log_batch()
|
||||
|
||||
# Stop the main application thread by stopping the tray icon.
|
||||
# Do this in a separate thread to allow the HTTP response to return first.
|
||||
stopper = threading.Thread(target=stop_icon_thread, daemon=True)
|
||||
|
@ -870,7 +924,7 @@ def execute_gui_script():
|
|||
return jsonify(result)
|
||||
except Exception as e:
|
||||
error_msg = f"Error ejecutando script GUI: {str(e)}"
|
||||
broadcast_message(error_msg)
|
||||
broadcast_message(error_msg, immediate=True)
|
||||
return jsonify({"error": error_msg}), 500
|
||||
|
||||
|
||||
|
@ -1151,7 +1205,7 @@ def execute_csharp_executable():
|
|||
return jsonify(result)
|
||||
except Exception as e:
|
||||
error_msg = f"Error ejecutando ejecutable C#: {str(e)}"
|
||||
broadcast_message(error_msg)
|
||||
broadcast_message(error_msg, immediate=True)
|
||||
return jsonify({"error": error_msg}), 500
|
||||
|
||||
|
||||
|
@ -1416,7 +1470,7 @@ def execute_python_script():
|
|||
return jsonify(result)
|
||||
except Exception as e:
|
||||
error_msg = f"Error ejecutando script Python: {str(e)}"
|
||||
broadcast_message(error_msg)
|
||||
broadcast_message(error_msg, immediate=True)
|
||||
return jsonify({"error": error_msg}), 500
|
||||
|
||||
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
},
|
||||
"level2": {},
|
||||
"level3": {},
|
||||
"working_directory": "D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\ExportTia"
|
||||
"working_directory": "C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giorgio in Bosco\\ExportTia"
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"path": "D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\ExportTia",
|
||||
"path": "C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giorgio in Bosco\\ExportTia",
|
||||
"history": [
|
||||
"C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giorgio in Bosco\\ExportTia",
|
||||
"D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\ExportTia",
|
||||
"C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giorgio in Bosco\\Reporte\\TiaExport",
|
||||
"C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\\Reporte\\TiaExport",
|
||||
|
|
|
@ -15,5 +15,5 @@
|
|||
"xref_source_subdir": "source"
|
||||
},
|
||||
"level3": {},
|
||||
"working_directory": "D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\ExportTia"
|
||||
"working_directory": "C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giorgio in Bosco\\ExportTia"
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script para verificar la detección de cambios basada en hash.
|
||||
|
||||
Este script demuestra cómo el sistema detecta cambios en archivos XML
|
||||
utilizando hash SHA256 en lugar de solo tiempo/tamaño de archivo.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import hashlib
|
||||
import tempfile
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def calculate_file_hash(filepath):
|
||||
"""Calcula el hash SHA256 de un archivo."""
|
||||
try:
|
||||
sha256_hash = hashlib.sha256()
|
||||
with open(filepath, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
sha256_hash.update(chunk)
|
||||
return sha256_hash.hexdigest()
|
||||
except Exception as e:
|
||||
print(f"Error calculando hash de {filepath}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def create_test_xml(content, filepath):
|
||||
"""Crea un archivo XML de prueba con el contenido especificado."""
|
||||
with open(filepath, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
|
||||
|
||||
def create_test_json(xml_filepath, json_filepath):
|
||||
"""Crea un archivo JSON de prueba con metadatos del XML."""
|
||||
xml_hash = calculate_file_hash(xml_filepath)
|
||||
xml_mtime = os.path.getmtime(xml_filepath)
|
||||
xml_size = os.path.getsize(xml_filepath)
|
||||
|
||||
json_data = {
|
||||
"block_name": "Test_Block",
|
||||
"block_type": "FC",
|
||||
"language": "LAD",
|
||||
"source_xml_mod_time": xml_mtime,
|
||||
"source_xml_size": xml_size,
|
||||
"source_xml_hash": xml_hash,
|
||||
"interface": {},
|
||||
"networks": [],
|
||||
}
|
||||
|
||||
with open(json_filepath, "w", encoding="utf-8") as f:
|
||||
json.dump(json_data, f, indent=4)
|
||||
|
||||
return json_data
|
||||
|
||||
|
||||
def test_hash_detection():
|
||||
"""Prueba la detección de cambios basada en hash."""
|
||||
print("=== Test de Detección de Cambios por Hash ===\n")
|
||||
|
||||
# Crear directorio temporal
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
xml_file = os.path.join(temp_dir, "test_block.xml")
|
||||
json_file = os.path.join(temp_dir, "test_block_processed.json")
|
||||
|
||||
# Paso 1: Crear XML original
|
||||
original_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Document>
|
||||
<SW.Blocks.FC ID="A">
|
||||
<AttributeList>
|
||||
<Name>Test_Block</Name>
|
||||
<Number>100</Number>
|
||||
<ProgrammingLanguage>LAD</ProgrammingLanguage>
|
||||
</AttributeList>
|
||||
<ObjectList>
|
||||
<NetworkSource />
|
||||
</ObjectList>
|
||||
</SW.Blocks.FC>
|
||||
</Document>"""
|
||||
|
||||
create_test_xml(original_content, xml_file)
|
||||
original_hash = calculate_file_hash(xml_file)
|
||||
print(f"1. XML original creado")
|
||||
print(f" Hash: {original_hash[:16]}...")
|
||||
print(f" Tamaño: {os.path.getsize(xml_file)} bytes")
|
||||
|
||||
# Paso 2: Crear JSON con metadatos
|
||||
json_data = create_test_json(xml_file, json_file)
|
||||
print(f"\n2. JSON con metadatos creado")
|
||||
print(f" Hash almacenado: {json_data['source_xml_hash'][:16]}...")
|
||||
|
||||
# Paso 3: Simular verificación - archivo sin cambios
|
||||
current_hash = calculate_file_hash(xml_file)
|
||||
hash_match = json_data["source_xml_hash"] == current_hash
|
||||
print(f"\n3. Verificación sin cambios:")
|
||||
print(f" Hash actual: {current_hash[:16]}...")
|
||||
print(f" ¿Hash coincide?: {hash_match}")
|
||||
print(f" → {'SALTAR procesamiento' if hash_match else 'PROCESAR archivo'}")
|
||||
|
||||
# Paso 4: Modificar archivo manteniendo mismo tamaño y tiempo
|
||||
print(f"\n4. Modificando XML (cambio sutil)...")
|
||||
modified_content = original_content.replace(
|
||||
"Test_Block", "Test_Blck"
|
||||
) # Cambio sutil
|
||||
|
||||
# Guardar tiempo original
|
||||
original_mtime = os.path.getmtime(xml_file)
|
||||
|
||||
create_test_xml(modified_content, xml_file)
|
||||
|
||||
# Restaurar tiempo original (simular que el timestamp no cambió)
|
||||
os.utime(xml_file, (original_mtime, original_mtime))
|
||||
|
||||
new_size = os.path.getsize(xml_file)
|
||||
new_mtime = os.path.getmtime(xml_file)
|
||||
new_hash = calculate_file_hash(xml_file)
|
||||
|
||||
print(f" Nuevo hash: {new_hash[:16]}...")
|
||||
print(f" Nuevo tamaño: {new_size} bytes")
|
||||
print(
|
||||
f" Tiempo modificación: {abs(new_mtime - json_data['source_xml_mod_time']) < 0.001}"
|
||||
)
|
||||
|
||||
# Paso 5: Verificar detección por diferentes métodos
|
||||
print(f"\n5. Comparación de métodos de detección:")
|
||||
|
||||
# Método tradicional (tiempo + tamaño)
|
||||
time_match = abs(new_mtime - json_data["source_xml_mod_time"]) < 0.001
|
||||
size_match = new_size == json_data["source_xml_size"]
|
||||
traditional_would_skip = time_match and size_match
|
||||
|
||||
# Método por hash
|
||||
hash_would_skip = new_hash == json_data["source_xml_hash"]
|
||||
|
||||
print(f" Método tradicional (tiempo+tamaño):")
|
||||
print(f" ¿Tiempo coincide?: {time_match}")
|
||||
print(f" ¿Tamaño coincide?: {size_match}")
|
||||
print(f" → {'SALTAR' if traditional_would_skip else 'PROCESAR'}")
|
||||
|
||||
print(f" Método por hash:")
|
||||
print(f" ¿Hash coincide?: {hash_would_skip}")
|
||||
print(f" → {'SALTAR' if hash_would_skip else 'PROCESAR'}")
|
||||
|
||||
print(f"\n6. Resultado:")
|
||||
if traditional_would_skip and not hash_would_skip:
|
||||
print(f" ✅ HASH DETECTÓ CAMBIO que el método tradicional PERDIÓ")
|
||||
print(f" 🔄 El archivo será regenerado correctamente")
|
||||
elif not traditional_would_skip and not hash_would_skip:
|
||||
print(f" ✅ Ambos métodos detectaron el cambio")
|
||||
elif traditional_would_skip and hash_would_skip:
|
||||
print(f" ✅ Ambos métodos indican que no hay cambios")
|
||||
else:
|
||||
print(f" ⚠️ Situación inesperada")
|
||||
|
||||
# Paso 6: Mostrar contenidos para verificación
|
||||
print(f"\n7. Verificación de contenido:")
|
||||
print(f" Contenido original tenía: 'Test_Block'")
|
||||
print(f" Contenido nuevo tiene: 'Test_Blck'")
|
||||
|
||||
with open(xml_file, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
has_original = "Test_Block" in content
|
||||
has_modified = "Test_Blck" in content
|
||||
print(f" ¿Contiene 'Test_Block'?: {has_original}")
|
||||
print(f" ¿Contiene 'Test_Blck'?: {has_modified}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_hash_detection()
|
|
@ -1,204 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test específico para demostrar casos donde el hash detecta cambios
|
||||
que el método tradicional (tiempo + tamaño) podría perder.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import hashlib
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
|
||||
def calculate_file_hash(filepath):
|
||||
"""Calcula el hash SHA256 de un archivo."""
|
||||
try:
|
||||
sha256_hash = hashlib.sha256()
|
||||
with open(filepath, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
sha256_hash.update(chunk)
|
||||
return sha256_hash.hexdigest()
|
||||
except Exception as e:
|
||||
print(f"Error calculando hash de {filepath}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def test_subtle_changes():
|
||||
"""Demuestra detección de cambios sutiles que mantienen el mismo tamaño."""
|
||||
print("=== Test: Cambios Sutiles con Mismo Tamaño ===\n")
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
xml_file = os.path.join(temp_dir, "test.xml")
|
||||
|
||||
# Crear contenido original de exactamente el mismo tamaño
|
||||
original = """<?xml version="1.0"?>
|
||||
<Block>
|
||||
<Name>MotorControl_01</Name>
|
||||
<Status>Active</Status>
|
||||
</Block>"""
|
||||
|
||||
# Crear contenido modificado del mismo tamaño (cambiar solo algunos caracteres)
|
||||
modified = """<?xml version="1.0"?>
|
||||
<Block>
|
||||
<Name>MotorControl_02</Name>
|
||||
<Status>Active</Status>
|
||||
</Block>"""
|
||||
|
||||
# Verificar que tienen el mismo tamaño
|
||||
assert len(original) == len(
|
||||
modified
|
||||
), "Los contenidos deben tener el mismo tamaño"
|
||||
|
||||
# Paso 1: Crear archivo original
|
||||
with open(xml_file, "w", encoding="utf-8") as f:
|
||||
f.write(original)
|
||||
|
||||
original_hash = calculate_file_hash(xml_file)
|
||||
original_size = os.path.getsize(xml_file)
|
||||
original_mtime = os.path.getmtime(xml_file)
|
||||
|
||||
print(f"1. Archivo original:")
|
||||
print(f" Contenido: MotorControl_01")
|
||||
print(f" Hash: {original_hash[:16]}...")
|
||||
print(f" Tamaño: {original_size} bytes")
|
||||
|
||||
# Simular JSON con metadatos
|
||||
json_data = {
|
||||
"source_xml_hash": original_hash,
|
||||
"source_xml_size": original_size,
|
||||
"source_xml_mod_time": original_mtime,
|
||||
}
|
||||
|
||||
# Paso 2: Esperar un poco y modificar archivo manteniendo tamaño
|
||||
time.sleep(0.1) # Pequeña pausa
|
||||
|
||||
with open(xml_file, "w", encoding="utf-8") as f:
|
||||
f.write(modified)
|
||||
|
||||
# Restaurar tiempo de modificación original
|
||||
os.utime(xml_file, (original_mtime, original_mtime))
|
||||
|
||||
new_hash = calculate_file_hash(xml_file)
|
||||
new_size = os.path.getsize(xml_file)
|
||||
new_mtime = os.path.getmtime(xml_file)
|
||||
|
||||
print(f"\n2. Archivo modificado:")
|
||||
print(f" Contenido: MotorControl_02")
|
||||
print(f" Hash: {new_hash[:16]}...")
|
||||
print(f" Tamaño: {new_size} bytes")
|
||||
print(
|
||||
f" Tiempo: {'Igual' if abs(new_mtime - original_mtime) < 0.001 else 'Diferente'}"
|
||||
)
|
||||
|
||||
# Paso 3: Comparar métodos de detección
|
||||
print(f"\n3. Detección de cambios:")
|
||||
|
||||
# Método tradicional
|
||||
time_match = abs(new_mtime - json_data["source_xml_mod_time"]) < 0.001
|
||||
size_match = new_size == json_data["source_xml_size"]
|
||||
traditional_detects_change = not (time_match and size_match)
|
||||
|
||||
# Método por hash
|
||||
hash_detects_change = new_hash != json_data["source_xml_hash"]
|
||||
|
||||
print(f" Método tradicional:")
|
||||
print(f" Tiempo coincide: {time_match}")
|
||||
print(f" Tamaño coincide: {size_match}")
|
||||
print(f" Detecta cambio: {traditional_detects_change}")
|
||||
|
||||
print(f" Método por hash:")
|
||||
print(f" Hash coincide: {new_hash == json_data['source_xml_hash']}")
|
||||
print(f" Detecta cambio: {hash_detects_change}")
|
||||
|
||||
# Resultado
|
||||
print(f"\n4. Resultado:")
|
||||
if not traditional_detects_change and hash_detects_change:
|
||||
print(f" 🎯 HASH DETECTÓ CAMBIO que método tradicional PERDIÓ")
|
||||
print(f" ✅ Sin hash: archivo NO se regeneraría (ERROR)")
|
||||
print(f" ✅ Con hash: archivo SÍ se regenerará (CORRECTO)")
|
||||
elif traditional_detects_change and hash_detects_change:
|
||||
print(f" ✅ Ambos métodos detectaron el cambio correctamente")
|
||||
else:
|
||||
print(
|
||||
f" ℹ️ Resultado: tradicional={traditional_detects_change}, hash={hash_detects_change}"
|
||||
)
|
||||
|
||||
return not traditional_detects_change and hash_detects_change
|
||||
|
||||
|
||||
def test_same_size_different_content():
|
||||
"""Test con contenidos completamente diferentes pero mismo tamaño."""
|
||||
print("\n" + "=" * 50)
|
||||
print("=== Test: Contenido Diferente, Mismo Tamaño ===\n")
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
xml_file = os.path.join(temp_dir, "test.xml")
|
||||
|
||||
# Contenidos de igual longitud pero diferentes
|
||||
content1 = "<Root><Item>AAAAAAAAAA</Item></Root>" # 33 chars
|
||||
content2 = "<Root><Item>BBBBBBBBBB</Item></Root>" # 33 chars
|
||||
|
||||
assert len(content1) == len(content2), "Deben tener igual tamaño"
|
||||
|
||||
# Crear archivo con contenido 1
|
||||
with open(xml_file, "w", encoding="utf-8") as f:
|
||||
f.write(content1)
|
||||
|
||||
hash1 = calculate_file_hash(xml_file)
|
||||
size1 = os.path.getsize(xml_file)
|
||||
mtime1 = os.path.getmtime(xml_file)
|
||||
|
||||
# Cambiar a contenido 2 manteniendo tiempo
|
||||
time.sleep(0.1)
|
||||
with open(xml_file, "w", encoding="utf-8") as f:
|
||||
f.write(content2)
|
||||
os.utime(xml_file, (mtime1, mtime1))
|
||||
|
||||
hash2 = calculate_file_hash(xml_file)
|
||||
size2 = os.path.getsize(xml_file)
|
||||
mtime2 = os.path.getmtime(xml_file)
|
||||
|
||||
print(f"Contenido 1: {content1[:20]}...")
|
||||
print(f"Contenido 2: {content2[:20]}...")
|
||||
print(f"Tamaños: {size1} = {size2} ({'✓' if size1 == size2 else '✗'})")
|
||||
print(f"Tiempos: {'iguales' if abs(mtime2 - mtime1) < 0.001 else 'diferentes'}")
|
||||
print(f"Hashes: {'iguales' if hash1 == hash2 else 'diferentes'}")
|
||||
|
||||
would_skip_traditional = (size1 == size2) and (abs(mtime2 - mtime1) < 0.001)
|
||||
would_skip_hash = hash1 == hash2
|
||||
|
||||
print(
|
||||
f"\nSin hash: {'SALTARÍA procesamiento' if would_skip_traditional else 'procesaría'}"
|
||||
)
|
||||
print(
|
||||
f"Con hash: {'saltaría procesamiento' if would_skip_hash else 'PROCESARÍA'}"
|
||||
)
|
||||
|
||||
if would_skip_traditional and not would_skip_hash:
|
||||
print("🎯 El hash evita saltar un archivo que SÍ cambió")
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Ejecutando tests de detección de cambios por hash...\n")
|
||||
|
||||
test1_result = test_subtle_changes()
|
||||
test2_result = test_same_size_different_content()
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
print("=== RESUMEN ===")
|
||||
print(
|
||||
f"Test 1 (cambios sutiles): {'HASH ÚTIL' if test1_result else 'ambos métodos iguales'}"
|
||||
)
|
||||
print(
|
||||
f"Test 2 (mismo tamaño): {'HASH ÚTIL' if test2_result else 'ambos métodos iguales'}"
|
||||
)
|
||||
|
||||
if test1_result or test2_result:
|
||||
print("\n✅ El hash SHA256 mejora la detección de cambios")
|
||||
print("✅ Evita regeneraciones innecesarias Y perdida de cambios reales")
|
||||
else:
|
||||
print("\n✓ Ambos métodos funcionaron igual en estos tests")
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"path": "D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\ExportTia",
|
||||
"path": "C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giorgio in Bosco\\ExportTia",
|
||||
"history": [
|
||||
"C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giorgio in Bosco\\ExportTia",
|
||||
"D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\ExportTia",
|
||||
"C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giorgio in Bosco\\Reporte\\TiaExport"
|
||||
]
|
||||
|
|
10188
data/log.txt
10188
data/log.txt
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue