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
@@ -0,0 +1,78 @@
|
||||
"""Inserir clipes na spine.
|
||||
|
||||
Extraído de writer.py — ver fcpxml/writer/__init__.py para o conjunto.
|
||||
"""
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class InsertMixin:
|
||||
"""Inserir clipes na spine."""
|
||||
|
||||
# INSERT CLIP OPERATIONS
|
||||
# ========================================================================
|
||||
|
||||
def insert_clip(
|
||||
self,
|
||||
position: str,
|
||||
asset_id: Optional[str] = None,
|
||||
asset_name: Optional[str] = None,
|
||||
duration: Optional[str] = None,
|
||||
in_point: Optional[str] = None,
|
||||
out_point: Optional[str] = None,
|
||||
ripple: bool = True
|
||||
) -> ET.Element:
|
||||
"""
|
||||
Insert a library clip onto the timeline.
|
||||
|
||||
Args:
|
||||
position: Where to insert - 'start', 'end', timecode, or 'after:clip_id'
|
||||
asset_id: Asset reference ID (e.g., 'r3')
|
||||
asset_name: Asset name (alternative to asset_id)
|
||||
duration: Duration of clip (if not using in/out points)
|
||||
in_point: Source in-point for subclip
|
||||
out_point: Source out-point for subclip
|
||||
ripple: Whether to shift subsequent clips
|
||||
|
||||
Returns:
|
||||
The created clip element
|
||||
"""
|
||||
asset, asset_id = self._resolve_asset(asset_id, asset_name)
|
||||
clip_duration, source_start = self._resolve_clip_duration(
|
||||
asset, duration, in_point, out_point
|
||||
)
|
||||
|
||||
# Get spine and calculate insert position
|
||||
spine = self._get_spine()
|
||||
spine_children = list(spine)
|
||||
target_offset, insert_index = self._resolve_insert_position(
|
||||
position, spine_children
|
||||
)
|
||||
|
||||
# Build extra attrs — include format from first available format
|
||||
extra: dict[str, str] = {}
|
||||
for fmt_id in self.formats:
|
||||
extra['format'] = fmt_id
|
||||
break
|
||||
|
||||
new_clip = self._make_asset_clip(
|
||||
asset_id, asset.get('name', 'Untitled'),
|
||||
target_offset, source_start, clip_duration,
|
||||
**extra,
|
||||
)
|
||||
|
||||
# Insert into spine
|
||||
spine.insert(insert_index, new_clip)
|
||||
|
||||
# Ripple subsequent clips if needed
|
||||
if ripple and insert_index < len(spine_children):
|
||||
self._ripple_from_index(spine, insert_index + 1, clip_duration)
|
||||
|
||||
# Add to clip index
|
||||
clip_id = f"inserted_{len(self.clips)}"
|
||||
self.clips[clip_id] = new_clip
|
||||
|
||||
return new_clip
|
||||
|
||||
# ========================================================================
|
||||
Reference in New Issue
Block a user