refactor: writer.py vira pacote, um módulo por assunto
O writer tinha 4.199 linhas, das quais 3.300 numa única classe com dezoito
assuntos dentro. Achar o trecho de zoom exigia rolar por marcadores,
velocidade e legendas.
Agora é o pacote fcpxml/writer/, com um arquivo por assunto e o
FCPXMLModifier montado por composição de mixins. Mixins, e não objetos
separados, porque todas essas operações mexem no mesmo documento e nos
mesmos índices — separá-las em objetos independentes transformaria toda
chamada interna em travessia de fronteira sem nada em troca. A divisão que
importa aqui é de leitura, não de estado.
Nenhuma mudança de comportamento e nenhuma alteração nos ~50 pontos que
importam do writer: o __init__ re-exporta tudo, inclusive os nomes com
underscore que a suíte já usava.
core 723 carga, índices, navegação na spine, save
titles 600 títulos e legendas dinâmicas
cut 333 dividir, cortar faixas, apagar
speed 297 velocidade e zoom
(+ 20 módulos menores)
Único ajuste de chamada: quatro testes faziam patch em
fcpxml.writer.subprocess, que agora mora em writer.document (ver
Engine/docs/05_EXPERIENCIAS.md #23).
Lint zerado, 1441 testes passando.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1bebee4359
commit
4f5cf94443
@@ -1228,6 +1228,33 @@ o outro; percentil entrega um punhado útil nos dois casos.
|
||||
|
||||
---
|
||||
|
||||
## 23 — 2026-08-19 — Dividir um módulo em pacote quebra quem faz `patch` nele
|
||||
|
||||
- **Sintoma:** ao transformar `fcpxml/writer.py` (4.199 linhas) no pacote
|
||||
`fcpxml/writer/`, quatro testes passaram a falhar com
|
||||
`AttributeError: module 'fcpxml.writer' has no attribute 'subprocess'` —
|
||||
embora nenhuma linha de lógica tivesse mudado.
|
||||
- **Causa raiz:** os testes usavam `@patch('fcpxml.writer.subprocess.run')`.
|
||||
Isso não depende da API pública, e sim de *onde o import mora*: com o
|
||||
módulo dividido, `subprocess` passou a ser importado por
|
||||
`fcpxml/writer/document.py`, então o alvo do patch deixou de existir.
|
||||
Re-exportar no `__init__` não resolveria — substituir
|
||||
`fcpxml.writer.subprocess` não afeta a referência que `document` já tem.
|
||||
- **Solução adotada:** apontar o patch para o módulo real
|
||||
(`fcpxml.writer.document.subprocess.run`). Duas armadilhas do tipo foram
|
||||
evitadas antes: imports relativos precisam de um ponto a mais ao descer um
|
||||
nível (`from .models` → `from ..models`), inclusive os que ficam *dentro*
|
||||
de funções, e o `__all__` precisa listar os nomes com underscore que o
|
||||
resto do projeto já importava, senão a divisão vira quebra de API.
|
||||
- **Aprendizado:** a suíte protege comportamento, não localização. Antes de
|
||||
dividir um módulo, procure por `patch('<modulo>.` e por imports relativos
|
||||
escondidos dentro de funções — são as duas coisas que uma refatoração
|
||||
puramente mecânica quebra em silêncio, e as únicas que os testes pegam
|
||||
tarde.
|
||||
- **Estado:** `resolvido`
|
||||
|
||||
---
|
||||
|
||||
## Resumo rápido (índice)
|
||||
|
||||
| # | Data | Problema | Estado |
|
||||
@@ -1252,5 +1279,6 @@ o outro; percentil entrega um punhado útil nos dois casos.
|
||||
| 20 | 2026-08-19 | `apply_voice_actions` ausente da ponte e do encadeamento do app — dava para analisar e legendar, não para cortar | `resolvido` |
|
||||
| 21 | 2026-08-19 | Teste ainda afirmava o default `zoom scale=1.3` removido do parser (agora vem do `zoom_scale` do usuário) | `resolvido` |
|
||||
| 22 | 2026-08-19 | `VideoPlayer` (AVKit) aborta em runtime no app compilado por `swiftc` — etapa 5 fechava o app; trocado por `AVPlayerLayer` | `resolvido` |
|
||||
| 23 | 2026-08-19 | Dividir `writer.py` em pacote quebrou `@patch('fcpxml.writer.subprocess')` — a suíte protege comportamento, não localização | `resolvido` |
|
||||
|
||||
> Mantenha o índice acima sempre sincronizado com as entradas mais recentes.
|
||||
|
||||
Reference in New Issue
Block a user