Spaces:
Sleeping
Sleeping
feat(modes): Mode dataclass + empty MODE_REGISTRY skeleton
Browse files- modes.py +43 -0
- tests/test_modes.py +16 -0
modes.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""MODE_REGISTRY — one Mode entry per generation mode.
|
| 2 |
+
|
| 3 |
+
Each Mode declares:
|
| 4 |
+
- name: short id ("t2v", "i2v", ...)
|
| 5 |
+
- label: display name
|
| 6 |
+
- icon: single-character or emoji icon for the sidebar
|
| 7 |
+
- stage_map: list of (label, expected_share_pct) for the status banner
|
| 8 |
+
- parameterize_fn: (Gradio inputs dict) -> list[(node_id, widget_index, value)]
|
| 9 |
+
|
| 10 |
+
The parameterize_fn is the only mode-specific logic. Everything else (workflow
|
| 11 |
+
loading, validation, dispatch) is mode-agnostic and lives in workflow.py /
|
| 12 |
+
backend.py.
|
| 13 |
+
|
| 14 |
+
Tasks 11 (T2V + I2V) and 12 (A2V + Lipsync + Keyframe + Style) populate
|
| 15 |
+
MODE_REGISTRY. This task only sets up the dataclass and the empty container.
|
| 16 |
+
"""
|
| 17 |
+
from __future__ import annotations
|
| 18 |
+
|
| 19 |
+
from collections.abc import Callable
|
| 20 |
+
from dataclasses import dataclass, field
|
| 21 |
+
from typing import Any
|
| 22 |
+
|
| 23 |
+
Patch = tuple[int, int, Any]
|
| 24 |
+
ParameterizeFn = Callable[[dict[str, Any]], list[Patch]]
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
@dataclass(frozen=True)
|
| 28 |
+
class Stage:
|
| 29 |
+
label: str
|
| 30 |
+
share_pct: int # rough share of total time, sums to ~100 across stages
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
@dataclass(frozen=True)
|
| 34 |
+
class Mode:
|
| 35 |
+
name: str
|
| 36 |
+
label: str
|
| 37 |
+
icon: str
|
| 38 |
+
parameterize_fn: ParameterizeFn
|
| 39 |
+
stage_map: list[Stage] = field(default_factory=list)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
# Filled in by tasks 11–12.
|
| 43 |
+
MODE_REGISTRY: dict[str, Mode] = {}
|
tests/test_modes.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Unit tests for modes.py — MODE_REGISTRY and parameterize_fn correctness."""
|
| 2 |
+
import pytest
|
| 3 |
+
|
| 4 |
+
import modes
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def test_mode_dataclass_has_expected_fields():
|
| 8 |
+
"""Mode dataclass exposes the expected attribute set."""
|
| 9 |
+
fields = {"name", "label", "icon", "parameterize_fn", "stage_map"}
|
| 10 |
+
actual = set(modes.Mode.__dataclass_fields__.keys())
|
| 11 |
+
assert fields == actual
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def test_mode_registry_is_a_dict():
|
| 15 |
+
"""MODE_REGISTRY exists and is a dict (entries added in Tasks 11–12)."""
|
| 16 |
+
assert isinstance(modes.MODE_REGISTRY, dict)
|