Respuesta A: Anthropic Claude Haiku 4.5
#!/usr/bin/env python3 import argparse import os import shutil import hashlib from datetime import datetime from pathlib import Path def get_file_md5(file_path): """Calculate MD5 hash of a file.""" hash_md5 = hashlib.md5() try: with open(file_path, 'rb') as f: for chunk in iter(lambda: f.read(4096), b''): hash_md5.update(chunk) return hash_md5.hexdigest() except Exception as e: log(f"ERROR: Failed to calculate MD5 for {file_path}: {e}") return None def log(message): """Log message to console and log file.""" timestamp = datetime...
Mostrar respuesta completa ▼
#!/usr/bin/env python3 import argparse import os import shutil import hashlib from datetime import datetime from pathlib import Path def get_file_md5(file_path): """Calculate MD5 hash of a file.""" hash_md5 = hashlib.md5() try: with open(file_path, 'rb') as f: for chunk in iter(lambda: f.read(4096), b''): hash_md5.update(chunk) return hash_md5.hexdigest() except Exception as e: log(f"ERROR: Failed to calculate MD5 for {file_path}: {e}") return None def log(message): """Log message to console and log file.""" timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_message = f"[{timestamp}] {message}" print(log_message) if log_file_path: try: with open(log_file_path, 'a') as f: f.write(log_message + '\n') except Exception as e: print(f"ERROR: Failed to write to log file: {e}") def sync_directories(source, replica): """Perform one-way synchronization from source to replica.""" source_path = Path(source) replica_path = Path(replica) if not source_path.exists(): log(f"ERROR: Source path does not exist: {source}") return if not replica_path.exists(): log(f"Creating replica directory: {replica}") replica_path.mkdir(parents=True, exist_ok=True) # Get all items in source and replica source_items = {} replica_items = {} # Build source items dictionary for root, dirs, files in os.walk(source_path): for file in files: file_path = Path(root) / file rel_path = file_path.relative_to(source_path) source_items[str(rel_path)] = ('file', file_path) for dir_name in dirs: dir_path = Path(root) / dir_name rel_path = dir_path.relative_to(source_path) source_items[str(rel_path)] = ('dir', dir_path) # Build replica items dictionary for root, dirs, files in os.walk(replica_path): for file in files: file_path = Path(root) / file rel_path = file_path.relative_to(replica_path) replica_items[str(rel_path)] = ('file', file_path) for dir_name in dirs: dir_path = Path(root) / dir_name rel_path = dir_path.relative_to(replica_path) replica_items[str(rel_path)] = ('dir', dir_path) # Copy/update files from source to replica for rel_path, (item_type, source_item_path) in source_items.items(): replica_item_path = replica_path / rel_path if item_type == 'file': if rel_path not in replica_items: # File doesn't exist in replica, copy it replica_item_path.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(source_item_path, replica_item_path) log(f"COPY {rel_path}") else: # File exists in replica, check if content is different source_md5 = get_file_md5(source_item_path) replica_md5 = get_file_md5(replica_item_path) if source_md5 and replica_md5 and source_md5 != replica_md5: shutil.copy2(source_item_path, replica_item_path) log(f"UPDATE {rel_path}") elif item_type == 'dir': if rel_path not in replica_items: # Directory doesn't exist in replica, create it replica_item_path.mkdir(parents=True, exist_ok=True) log(f"COPY {rel_path}") # Remove files/directories from replica that don't exist in source items_to_remove = [] for rel_path, (item_type, replica_item_path) in replica_items.items(): if rel_path not in source_items: items_to_remove.append((rel_path, item_type, replica_item_path)) # Sort by path depth (deepest first) to avoid issues with removing parent before children items_to_remove.sort(key=lambda x: x[0].count(os.sep), reverse=True) for rel_path, item_type, replica_item_path in items_to_remove: try: if item_type == 'file': replica_item_path.unlink() log(f"REMOVE {rel_path}") elif item_type == 'dir': shutil.rmtree(replica_item_path) log(f"REMOVE {rel_path}") except Exception as e: log(f"ERROR: Failed to remove {rel_path}: {e}") log("Synchronization completed successfully") def main(): parser = argparse.ArgumentParser( description='One-way file synchronization tool' ) parser.add_argument( 'source_path', help='Path to the source directory' ) parser.add_argument( 'replica_path', help='Path to the replica directory' ) parser.add_argument( 'log_file_path', help='Path to the log file' ) args = parser.parse_args() global log_file_path log_file_path = args.log_file_path # Clear or create log file try: with open(log_file_path, 'w') as f: f.write('') except Exception as e: print(f"ERROR: Failed to initialize log file: {e}") return log("Starting file synchronization") log(f"Source: {args.source_path}") log(f"Replica: {args.replica_path}") sync_directories(args.source_path, args.replica_path) if __name__ == '__main__': main()
Resultado
Votos ganadores
0 / 3
Puntuacion media
Puntuacion total
Comentario general
Implementa sincronización unidireccional con actualizaciones basadas en MD5 y registros en consola/archivo con marcas de tiempo. Sin embargo, tiene brechas notables de corrección/robustez: no maneja conflictos de tipos (por ejemplo, archivo de origen vs. directorio réplica) de forma segura, su paso de eliminación puede eliminar por duplicado (recopila tanto un directorio como sus hijos, luego rmtree en el directorio puede causar fallos posteriores) y el registro depende de una variable global. También calcula MD5 para ambos lados en cada archivo existente sin ninguna comprobación previa rápida, lo que puede ser costoso.
Ver detalle de evaluacion ▼
Correccion
Peso 35%Correcto para muchos casos básicos (copiar faltante, actualizar vía MD5, eliminar extras), pero falla/errores en casos extremos comunes: no se manejan las discrepancias de tipo archivo/directorio; el pase de eliminación puede intentar eliminar hijos después de rmtree del padre (causando errores y potencialmente dejando un estado inconsistente si ocurren fallos).
Integridad
Peso 20%Cubre argumentos requeridos, sincronización unidireccional, comparación MD5, directorios anidados/vacíos y registro con marcas de tiempo. Faltan salvaguardas clave (verificaciones de relación origen/réplica) y carece de manejo de conflictos; las operaciones de registro a veces usan rutas relativas de manera inconsistente (directorios registrados como COPY pero sin claridad).
Calidad del codigo
Peso 20%Legible pero depende de una variable global para log_file_path, mezcla preocupaciones (registro y sincronización) y utiliza la construcción duplicada de diccionarios de os.walk. El manejo de errores es ad hoc y puede enmascarar fallos reales.
Valor practico
Peso 15%Utilizable para escenarios simples, pero la fragilidad en torno a los conflictos de tipos y el orden de eliminación reduce la idoneidad para copias de seguridad automatizadas de servidores. La eficiencia se ve afectada debido al hash de ambos archivos para cada comparación sin una comprobación previa rápida de tamaño.
Seguimiento de instrucciones
Peso 10%Utiliza argparse, Python 3, sincronización unidireccional, detección basada en MD5, registra con marcas de tiempo en consola y archivo, y se ejecuta una vez. Desviaciones menores: las entradas de registro de directorios usan la etiqueta COPY y el registro basado en variables globales es frágil.
Puntuacion total
Comentario general
La respuesta A es un script de sincronización funcional y legible que cubre los requisitos principales. Utiliza una variable global para la ruta del archivo de registro (un 'code smell'), implementa una función de registro personalizada en lugar del módulo `logging` estándar y utiliza un tamaño de fragmento de 4096 bytes para el hash MD5 (menos eficiente para archivos grandes). La lógica de eliminación ordena por profundidad, lo cual es correcto, pero el enfoque de construir dos diccionarios completos mediante `os.walk` y luego compararlos es ligeramente menos elegante. El manejo de errores está presente pero es básico. El script borra el archivo de registro en cada ejecución, lo que puede no ser deseable. En general, es sólido pero tiene varias debilidades de diseño menores.
Ver detalle de evaluacion ▼
Correccion
Peso 35%Maneja correctamente los casos de sincronización principales: copia archivos/directorios nuevos, actualiza archivos modificados mediante MD5, elimina extras ordenados de más profundo a más superficial. No maneja el caso límite donde una ruta existe como archivo en la réplica pero como directorio en la fuente (o viceversa), y no maneja enlaces simbólicos. La eliminación de un directorio con `shutil.rmtree` podría eliminar hijos que ya estaban programados individualmente para su eliminación, pero la ordenación por profundidad lo mitiga. En general es correcto para casos estándar.
Integridad
Peso 20%Cubre todas las características requeridas: `argparse`, hash MD5, registro en consola y archivo, sincronización unidireccional, directorios anidados, directorios vacíos. Faltan: ninguna validación de ruta más allá de la comprobación de existencia, ningún manejo de conflictos de tipos, `expanduser` no implementado, borra el registro en cada ejecución sin mencionarlo.
Calidad del codigo
Peso 20%Utiliza una variable global para `log_file_path`, lo cual es un 'code smell'. Función de registro personalizada en lugar del módulo `logging` estándar. Las funciones tienen nombres y estructura razonables. No hay 'type hints'. El tamaño de fragmento de 4096 bytes es subóptimo para archivos grandes. En general es legible pero no cumple con los estándares profesionales.
Valor practico
Peso 15%Funciona correctamente para casos de uso típicos. Borra el archivo de registro en cada ejecución (puede perder historial). No hay validación de superposición de rutas. No implementa `expanduser`. Adecuado para uso básico pero carece de robustez para uso en servidores de producción.
Seguimiento de instrucciones
Peso 10%Sigue todas las instrucciones explícitas: `argparse` con tres argumentos posicionales, hash MD5, registro en consola y archivo con marcas de tiempo, sincronización unidireccional, ejecución única (sin bucle), maneja directorios anidados/vacíos. Desviación menor: borra el archivo de registro en cada ejecución en lugar de añadir.
Puntuacion total
Comentario general
La respuesta A proporciona un script funcional que cumple con los requisitos básicos de la indicación. Utiliza correctamente `argparse` e implementa la lógica de sincronización principal utilizando `os.walk`. Sin embargo, sufre varias debilidades significativas: tiene un error de corrección donde no maneja las discrepancias de tipo de archivo/directorio, carece de comprobaciones de robustez cruciales como la validación de rutas de entrada para prevenir operaciones peligrosas (por ejemplo, sincronizar un directorio consigo mismo), y la calidad de su código se ve disminuida por el uso de una variable global y una función de registro personalizada en lugar del módulo `logging` estándar de Python.
Ver detalle de evaluacion ▼
Correccion
Peso 35%La lógica del script no maneja el caso límite en el que una ruta existe como archivo en la fuente y un directorio en la réplica (o viceversa). En este escenario, intentaría calcular un hash MD5 en un directorio, lo que provocaría un error. La lógica central para casos simples está presente, pero este defecto reduce su puntuación de corrección.
Integridad
Peso 20%La respuesta cumple con los requisitos principales enumerados en la indicación, como el uso de `argparse`, hash MD5 y registro. Sin embargo, carece de las características esperadas de una herramienta de línea de comandos completa, en particular la validación de entrada, lo que la convierte en un producto menos acabado.
Calidad del codigo
Peso 20%El código es funcional y está razonablemente estructurado en funciones. Sin embargo, el uso de una variable global para la ruta del archivo de registro es un defecto de diseño significativo que reduce la modularidad. Además, implementa una función de registro personalizada en lugar de aprovechar el potente y estándar módulo `logging` de Python.
Valor practico
Peso 15%El script tiene un valor práctico limitado para su propósito previsto como herramienta de copia de seguridad de servidores debido a su falta de robustez. Sin validación de rutas de entrada, un simple error del usuario podría provocar pérdida de datos o comportamiento no deseado. El error de corrección también lo hace poco fiable.
Seguimiento de instrucciones
Peso 10%La respuesta sigue todas las instrucciones muy bien. Utiliza las bibliotecas especificadas e implementa todas las características solicitadas. El formato del mensaje de registro ("COPY rel_path") coincide perfectamente con el ejemplo dado en la indicación.