Resposta 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 resposta 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 de vitoria
0 / 3
Pontuacao media
Pontuacao total
Comentario geral
Implementa sincronização unidirecional com atualizações baseadas em MD5 e logs para console/arquivo com timestamps. No entanto, possui lacunas notáveis de correção/robustez: não lida com conflitos de tipo (por exemplo, arquivo de origem vs diretório réplica) de forma segura, sua etapa de remoção pode excluir duas vezes (coleta um diretório e seus filhos, então rmtree no diretório pode causar falhas posteriores) e o logging depende de uma variável global. Ele também calcula o MD5 para ambos os lados em cada arquivo existente sem nenhuma verificação prévia rápida, o que pode ser caro.
Ver detalhes da avaliacao ▼
Correcao
Peso 35%Correto para muitos casos básicos (copiar ausente, atualizar via MD5, excluir extras), mas falha/erra em casos extremos comuns: incompatibilidades de tipo arquivo/diretório não são tratadas; o passe de exclusão pode tentar remover filhos após rmtree do pai (causando erros e potencialmente deixando estado inconsistente se ocorrerem falhas).
Completude
Peso 20%Cobre argumentos necessários, sincronização unidirecional, comparação MD5, diretórios aninhados/vazios e logging com timestamp. Faltam salvaguardas chave (verificações de relacionamento origem/réplica) e falta tratamento de conflitos; operações de logging às vezes usam caminhos relativos de forma inconsistente (diretórios registrados como COPY, mas sem clareza).
Qualidade do codigo
Peso 20%Legível, mas depende de uma variável global para log_file_path, mistura preocupações (logging e sync) e usa construção duplicada de dicionário os.walk. O tratamento de erros é ad hoc e pode mascarar falhas reais.
Valor pratico
Peso 15%Utilizável para cenários simples, mas a fragilidade em torno de conflitos de tipo e ordenação de exclusão reduz a adequação para backups automatizados de servidor. A eficiência é prejudicada pelo hashing de ambos os arquivos para cada comparação sem uma verificação prévia rápida de tamanho.
Seguimento de instrucoes
Peso 10%Usa argparse, Python 3, sincronização unidirecional, detecção baseada em MD5, logs com timestamps para console e arquivo, e executa uma vez. Desvios menores: entradas de log de diretório usam o rótulo COPY e o logging baseado em global é frágil.
Pontuacao total
Comentario geral
A Resposta A é um script de sincronização funcional e legível que cobre os requisitos principais. Usa uma variável global para o caminho do arquivo de log (um code smell), implementa uma função de log personalizada em vez do módulo `logging` padrão e usa um tamanho de bloco de 4096 bytes para hashing MD5 (menos eficiente para arquivos grandes). A lógica de remoção ordena por profundidade, o que está correto, mas a abordagem de construir dois dicionários completos via os.walk e depois compará-los é ligeiramente menos elegante. O tratamento de erros está presente, mas é básico. O script limpa o arquivo de log a cada execução, o que pode não ser desejável. No geral, é sólido, mas tem várias fraquezas de design menores.
Ver detalhes da avaliacao ▼
Correcao
Peso 35%Lida corretamente com os casos principais de sincronização: copiar novos arquivos/diretórios, atualizar arquivos alterados via MD5, remover extras ordenados do mais profundo para o mais raso. Não lida com o caso extremo em que um caminho existe como arquivo na réplica, mas como diretório na origem (ou vice-versa), e não lida com symlinks. A remoção de um diretório com shutil.rmtree pode remover filhos que já foram individualmente agendados para remoção, mas a ordenação por profundidade mitiga isso. No geral, correto para casos padrão.
Completude
Peso 20%Cobre todos os recursos necessários: argparse, hashing MD5, logging para console e arquivo, sincronização unidirecional, diretórios aninhados, diretórios vazios. Faltando: nenhuma validação de caminho além da verificação de existência, nenhum tratamento de conflitos de tipo, nenhum expanduser, limpa o log a cada execução sem aviso.
Qualidade do codigo
Peso 20%Usa uma variável global para log_file_path, o que é um code smell. Função de log personalizada em vez do módulo de logging padrão. As funções são razoavelmente nomeadas e estruturadas. Sem type hints. O tamanho do bloco de 4096 bytes é subótimo para arquivos grandes. No geral, legível, mas não atende aos padrões profissionais.
Valor pratico
Peso 15%Funciona corretamente para casos de uso típicos. Limpa o arquivo de log a cada execução (pode perder histórico). Nenhuma validação de sobreposição de caminhos. Nenhum expanduser. Adequado para uso básico, mas carece de robustez para uso em servidor de produção.
Seguimento de instrucoes
Peso 10%Segue todas as instruções explícitas: argparse com três argumentos posicionais, hashing MD5, logging para console e arquivo com timestamps, sincronização unidirecional, execução única (sem loop), lida com diretórios aninhados/vazios. Desvio menor: limpa o arquivo de log a cada execução em vez de anexar.
Pontuacao total
Comentario geral
A Resposta A fornece um script funcional que atende aos requisitos básicos do prompt. Ele usa corretamente `argparse` e implementa a lógica de sincronização principal usando `os.walk`. No entanto, sofre de várias fraquezas significativas: tem um bug de correção onde falha ao lidar com incompatibilidades de tipo de arquivo/diretório, carece de verificações cruciais de robustez como validação de caminhos de entrada para evitar operações perigosas (por exemplo, sincronizar um diretório em si mesmo), e sua qualidade de código é diminuída pelo uso de uma variável global e uma função de log personalizada em vez do módulo `logging` padrão do Python.
Ver detalhes da avaliacao ▼
Correcao
Peso 35%A lógica do script falha ao lidar com o caso extremo em que um caminho existe como um arquivo na origem e um diretório na réplica (ou vice-versa). Nesse cenário, ele tentaria calcular um hash MD5 em um diretório, causando um erro. A lógica principal para casos simples está presente, mas essa falha reduz sua pontuação de correção.
Completude
Peso 20%A resposta atende aos principais requisitos listados no prompt, como o uso de `argparse`, hash MD5 e log. No entanto, faltam recursos esperados de uma ferramenta de linha de comando completa, principalmente validação de entrada, o que a torna menos um produto acabado.
Qualidade do codigo
Peso 20%O código é funcional e razoavelmente estruturado em funções. No entanto, o uso de uma variável global para o caminho do arquivo de log é uma falha de design significativa que reduz a modularidade. Além disso, ele implementa uma função de log personalizada em vez de aproveitar o poderoso e padrão módulo `logging` do Python.
Valor pratico
Peso 15%O script tem valor prático limitado para seu propósito pretendido como uma ferramenta de backup de servidor devido à sua falta de robustez. Sem validação de caminhos de entrada, um erro simples do usuário pode levar à perda de dados ou comportamento não intencional. O bug de correção também o torna não confiável.
Seguimento de instrucoes
Peso 10%A resposta segue todas as instruções muito bem. Ele usa as bibliotecas especificadas e implementa todos os recursos solicitados. O formato da mensagem de log ("COPY rel_path") corresponde perfeitamente ao exemplo dado no prompt.