- Alinhado o aplicador Python de plano de edição (aplicador_de_plano_de_edicao.py) com o script apply-editorial-actions.mjs de referência: no-op de split restrito aos padrões reais do bridge, pausa entre chamadas ao MCP, tolerância de borda de corte usa a posição real em vez de rejeitar desvio; adicionado backup automático da sequência (duplicate_sequence) e documentado o comando python code/engine/aplicar_plano_de_edicao.py como via alternativa ao painel CEP. Resumo: - 18 arquivos alterados - 5 novos - 13 modificados - 0 removidos 13 files changed, 704 insertions(+), 133 deletions(-) Arquivos: - .jhonny/analises.db - CLAUDE.md - code/engine/aplicar_plano_de_edicao.py - code/engine/editor/__init__.py - code/engine/editor/aplicador_de_plano_de_edicao.py - code/engine/editor/escrita/escrita_no_editor.py - code/engine/integracoes/premiere/__init__.py - code/engine/integracoes/premiere/cliente_mcp.py - code/engine/testes/duplos_de_premiere.py - code/engine/testes/test_aplicador_de_plano_de_edicao.py - code/scripts/apply-editorial-actions.mjs - code/src/tools/discovery.ts - code/src/tools/timeline.ts - code/engine/editor/backup_de_sequencia.py - code/engine/integracoes/premiere/cliente_mcp_com_pausa.py - code/engine/testes/test_backup_de_sequencia.py - code/engine/testes/test_cliente_mcp_com_pausa.py - code/engine/testes/test_escrita_no_editor.py
102 lines
4.1 KiB
Python
102 lines
4.1 KiB
Python
"""Testes do decorator que espaça as chamadas ao bridge do Premiere."""
|
|
|
|
import unittest
|
|
from typing import Any
|
|
|
|
from engine.integracoes.premiere.cliente_mcp import ClienteMCP
|
|
from engine.integracoes.premiere.cliente_mcp_com_pausa import ClienteMCPComPausa
|
|
from engine.integracoes.premiere.erros_mcp import ErroDeFerramentaMCP
|
|
|
|
|
|
class _ClienteQueRegistra(ClienteMCP):
|
|
"""Dublê que só registra as chamadas recebidas e devolve um resultado fixo."""
|
|
|
|
def __init__(self, erro_a_levantar: Exception | None = None) -> None:
|
|
self.chamadas: list[tuple[str, dict[str, Any]]] = []
|
|
self.erro_a_levantar = erro_a_levantar
|
|
self.conectado = False
|
|
|
|
def conectar(self) -> None:
|
|
"""Marca o dublê como conectado."""
|
|
self.conectado = True
|
|
|
|
def desconectar(self) -> None:
|
|
"""Marca o dublê como desconectado."""
|
|
self.conectado = False
|
|
|
|
def esta_conectado(self) -> bool:
|
|
"""Estado de conexão registrado pelo dublê."""
|
|
return self.conectado
|
|
|
|
def chamar(self, nome_da_ferramenta: str, argumentos: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
"""Registra a chamada e devolve um resultado fixo, ou levanta o erro configurado."""
|
|
self.chamadas.append((nome_da_ferramenta, argumentos or {}))
|
|
if self.erro_a_levantar is not None:
|
|
raise self.erro_a_levantar
|
|
return {"ok": True}
|
|
|
|
|
|
class _EsperaFalsa:
|
|
"""Substitui ``time.sleep`` registrando as pausas pedidas, sem esperar de verdade."""
|
|
|
|
def __init__(self) -> None:
|
|
self.pausas: list[float] = []
|
|
|
|
def __call__(self, segundos: float) -> None:
|
|
"""Registra a pausa pedida."""
|
|
self.pausas.append(segundos)
|
|
|
|
|
|
class TesteClienteMCPComPausa(unittest.TestCase):
|
|
"""Garante o espaçamento entre chamadas e a transparência do decorator."""
|
|
|
|
def setUp(self):
|
|
self.interno = _ClienteQueRegistra()
|
|
self.espera = _EsperaFalsa()
|
|
self.cliente = ClienteMCPComPausa(self.interno, pausa_em_segundos=0.12, esperar=self.espera)
|
|
|
|
def test_repassa_a_chamada_ao_cliente_interno(self):
|
|
resultado = self.cliente.chamar("split_clip", {"time_seconds": 10.0})
|
|
self.assertEqual(resultado, {"ok": True})
|
|
self.assertEqual(self.interno.chamadas, [("split_clip", {"time_seconds": 10.0})])
|
|
|
|
def test_nao_pausa_antes_da_primeira_chamada(self):
|
|
# A primeira chamada não precisa esperar: não há chamada anterior
|
|
# ocupando o processo principal do Premiere.
|
|
self.cliente.chamar("get_active_sequence")
|
|
self.assertEqual(self.espera.pausas, [])
|
|
|
|
def test_pausa_entre_chamadas_consecutivas(self):
|
|
# Sem essa folga, uma rajada de round-trips síncronos de QE/ExtendScript
|
|
# trava a UI do Premiere — foi o que se viu com um plano de 17 cortes.
|
|
for _ in range(3):
|
|
self.cliente.chamar("split_clip", {"time_seconds": 1.0})
|
|
self.assertEqual(self.espera.pausas, [0.12, 0.12])
|
|
|
|
def test_pausa_tambem_depois_de_uma_chamada_que_falhou(self):
|
|
# Uma chamada que falhou ocupou o bridge do mesmo jeito; emendar a
|
|
# próxima sem folga é justamente o que derruba a UI.
|
|
interno = _ClienteQueRegistra(erro_a_levantar=ErroDeFerramentaMCP("recusado"))
|
|
espera = _EsperaFalsa()
|
|
cliente = ClienteMCPComPausa(interno, pausa_em_segundos=0.12, esperar=espera)
|
|
for _ in range(2):
|
|
with self.assertRaises(ErroDeFerramentaMCP):
|
|
cliente.chamar("split_clip", {"time_seconds": 1.0})
|
|
self.assertEqual(espera.pausas, [0.12])
|
|
|
|
def test_conexao_e_delegada_sem_pausa(self):
|
|
# Conectar/desconectar não são round-trips de edição; não precisam de folga.
|
|
self.cliente.conectar()
|
|
self.assertTrue(self.cliente.esta_conectado())
|
|
self.cliente.desconectar()
|
|
self.assertFalse(self.cliente.esta_conectado())
|
|
self.assertEqual(self.espera.pausas, [])
|
|
|
|
def test_pausa_negativa_e_recusada(self):
|
|
with self.assertRaises(ValueError):
|
|
ClienteMCPComPausa(self.interno, pausa_em_segundos=-0.1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|