Files
gart/admin/api/project.py
T
João HenriqueandClaude Opus 5 711c397dfe fix: admin/api apontava para admin/code (inexistente) — crash no app
Ao dividir _shared.py em admin/api/*.py ontem, o cálculo
`Path(__file__).resolve().parent.parent / "code"` foi copiado sem ajustar
para o nível de diretório novo. No arquivo original (admin/models_api.py,
direto em admin/) dois `.parent` chegavam na raiz do repo. Em
admin/api/shared.py, um nível mais fundo, dois `.parent` param em admin/ —
e admin/code nunca existiu. sys.path nunca recebia code/, então toda ação
que passa por `server` (analisar voz, aplicar decisões) crashava o app com
ModuleNotFoundError: server_tools.

O bug sobreviveu a duas rodadas de validação da sessão anterior — lint
zero, 1454 testes verdes, comando testado manualmente pela ponte — porque
todos rodam num venv com install editável (__editable__.fcp_mcp_server.pth)
que já deixa fcpxml/server_tools importáveis por conta própria, mascarando
qualquer erro no cálculo manual de sys.path. Só o app real, no fallback sem
uv, expõe o bug.

Correção: o cálculo de sys.path sai de cada módulo de comando (estava
duplicado em nove arquivos) e passa a existir uma única vez em
admin/api/__init__.py, que roda antes de qualquer submódulo — nenhum
precisa mais da própria cópia.

O teste de regressão precisou de duas tentativas pelo mesmo motivo do bug:
a primeira versão também passava com o bug presente, por rodar no mesmo
venv "de sorte". Só ficou confiável isolando um subprocess que remove
site-packages do sys.path antes de importar — confirmado nos dois sentidos,
falha com o bug reintroduzido e passa com a correção
(TestCodeDirResolution).

Detalhe completo, incluindo por que o comando manual não pegou:
Engine/docs/05_EXPERIENCIAS.md #25.

Lint zerado, 1457 testes passando (3 novos), app compilado.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:50:04 -04:00

70 lines
2.0 KiB
Python

"""Projeto: inspecionar o .fcpxml e lembrar a pasta/arquivo em uso.
Extraído de models_api.py — a tabela de comandos segue lá.
"""
from __future__ import annotations
from pathlib import Path
from fcpxml.model_manager import (
load_project_config,
save_project_config,
)
from fcpxml.parser import parse_fcpxml
from . import shared
def cmd_inspect(args: dict) -> int:
"""Validate an FCPXML file and return a summary of its projects/timelines."""
path = str(args.get("path", ""))
if not path:
shared.emit({"ok": False, "error": "Nenhum arquivo informado."})
return 1
if not Path(path).exists():
shared.emit({"ok": False, "error": "Arquivo não encontrado."})
return 1
try:
proj = parse_fcpxml(path)
except Exception as exc:
shared.emit({"ok": False, "error": f"Erro ao ler o projeto: {exc}"})
return 1
timelines = []
for tl in proj.timelines:
timelines.append(
{
"name": tl.name,
"duration_seconds": round(tl.duration.seconds, 3),
"frame_rate": round(tl.frame_rate, 3),
"width": tl.width,
"height": tl.height,
"clips": tl.total_clips,
"cuts": tl.total_cuts,
"connected": len(tl.connected_clips),
"markers": len(tl.markers),
}
)
shared.emit(
{
"ok": True,
"path": path,
"name": proj.name,
"fcpxml_version": proj.fcpxml_version,
"timelines": timelines,
}
)
return 0
def cmd_project_config(args: dict) -> int:
"""Read the last project folder/file the app was working on."""
shared.emit({"ok": True, **load_project_config()})
return 0
def cmd_set_project_config(args: dict) -> int:
"""Persist the last project folder/file. Only the given fields change."""
config = save_project_config(folder=args.get("folder"), file=args.get("file"))
shared.emit({"ok": True, **config})
return 0