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>
58 lines
1.6 KiB
Python
58 lines
1.6 KiB
Python
"""Selecionar clipes por palavra-chave.
|
|
|
|
Extraído de writer.py — ver fcpxml/writer/__init__.py para o conjunto.
|
|
"""
|
|
|
|
from typing import List
|
|
|
|
|
|
class SelectionMixin:
|
|
"""Selecionar clipes por palavra-chave."""
|
|
|
|
# SELECTION OPERATIONS
|
|
# ========================================================================
|
|
|
|
def select_by_keyword(
|
|
self,
|
|
keywords: List[str],
|
|
match_mode: str = 'any',
|
|
favorites_only: bool = False,
|
|
exclude_rejected: bool = True
|
|
) -> List[str]:
|
|
"""
|
|
Find clips matching keywords.
|
|
|
|
Args:
|
|
keywords: Keywords to match
|
|
match_mode: 'any' (OR), 'all' (AND), 'none' (exclude)
|
|
favorites_only: Only return favorited clips
|
|
exclude_rejected: Exclude rejected clips
|
|
|
|
Returns:
|
|
List of matching clip IDs
|
|
"""
|
|
matches = []
|
|
|
|
for clip_id, clip in self.clips.items():
|
|
clip_keywords = set()
|
|
for kw_elem in clip.findall('keyword'):
|
|
clip_keywords.add(kw_elem.get('value', ''))
|
|
|
|
# Check keyword match
|
|
keyword_set = set(keywords)
|
|
if match_mode == 'any':
|
|
match = bool(clip_keywords & keyword_set)
|
|
elif match_mode == 'all':
|
|
match = keyword_set <= clip_keywords
|
|
elif match_mode == 'none':
|
|
match = not bool(clip_keywords & keyword_set)
|
|
else:
|
|
match = True
|
|
|
|
if match:
|
|
matches.append(clip_id)
|
|
|
|
return matches
|
|
|
|
# ========================================================================
|