WIP #35
@@ -5,13 +5,24 @@ Application orchestrator — pipeline mode entry point.
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import effects_plugins
|
||||||
from engine import config
|
from engine import config
|
||||||
|
from engine.display import DisplayRegistry
|
||||||
|
from engine.effects import PerformanceMonitor, get_registry, set_monitor
|
||||||
|
from engine.fetch import fetch_all, fetch_poetry, load_cache
|
||||||
from engine.pipeline import (
|
from engine.pipeline import (
|
||||||
Pipeline,
|
Pipeline,
|
||||||
PipelineConfig,
|
PipelineConfig,
|
||||||
get_preset,
|
get_preset,
|
||||||
list_presets,
|
list_presets,
|
||||||
)
|
)
|
||||||
|
from engine.pipeline.adapters import (
|
||||||
|
RenderStage,
|
||||||
|
SourceItemsToBufferStage,
|
||||||
|
create_items_stage,
|
||||||
|
create_stage_from_display,
|
||||||
|
create_stage_from_effect,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -45,18 +56,6 @@ def main():
|
|||||||
|
|
||||||
def run_pipeline_mode(preset_name: str = "demo"):
|
def run_pipeline_mode(preset_name: str = "demo"):
|
||||||
"""Run using the new unified pipeline architecture."""
|
"""Run using the new unified pipeline architecture."""
|
||||||
import effects_plugins
|
|
||||||
from engine.display import DisplayRegistry
|
|
||||||
from engine.effects import PerformanceMonitor, get_registry, set_monitor
|
|
||||||
from engine.fetch import fetch_all, fetch_poetry, load_cache
|
|
||||||
from engine.pipeline.adapters import (
|
|
||||||
RenderStage,
|
|
||||||
SourceItemsToBufferStage,
|
|
||||||
create_items_stage,
|
|
||||||
create_stage_from_display,
|
|
||||||
create_stage_from_effect,
|
|
||||||
)
|
|
||||||
|
|
||||||
print(" \033[1;38;5;46mPIPELINE MODE\033[0m")
|
print(" \033[1;38;5;46mPIPELINE MODE\033[0m")
|
||||||
print(" \033[38;5;245mUsing unified pipeline architecture\033[0m")
|
print(" \033[38;5;245mUsing unified pipeline architecture\033[0m")
|
||||||
|
|
||||||
|
|||||||
@@ -38,31 +38,16 @@ class TestMain:
|
|||||||
|
|
||||||
def test_main_exits_on_unknown_preset(self):
|
def test_main_exits_on_unknown_preset(self):
|
||||||
"""main() exits with error message for unknown preset."""
|
"""main() exits with error message for unknown preset."""
|
||||||
|
sys.argv = ["mainline.py"]
|
||||||
with (
|
with (
|
||||||
patch("engine.app.run_pipeline_mode"),
|
patch("engine.app.config") as mock_config,
|
||||||
patch("engine.app.list_presets", return_value=["demo", "poetry"]),
|
patch("engine.app.list_presets", return_value=["demo", "poetry"]),
|
||||||
pytest.raises(SystemExit) as exc_info,
|
pytest.raises(SystemExit) as exc_info,
|
||||||
patch("engine.app.config") as mock_config,
|
|
||||||
):
|
):
|
||||||
sys.argv = ["mainline.py"]
|
|
||||||
mock_config.PRESET = "nonexistent"
|
mock_config.PRESET = "nonexistent"
|
||||||
main()
|
main()
|
||||||
assert exc_info.value.code == 1
|
assert exc_info.value.code == 1
|
||||||
|
|
||||||
def test_main_handles_pipeline_diagram_flag(self):
|
|
||||||
"""main() generates pipeline diagram if PIPELINE_DIAGRAM is set."""
|
|
||||||
with (
|
|
||||||
patch("engine.app.config") as mock_config,
|
|
||||||
patch(
|
|
||||||
"engine.app.generate_pipeline_diagram", return_value="diagram"
|
|
||||||
) as mock_gen,
|
|
||||||
):
|
|
||||||
mock_config.PIPELINE_DIAGRAM = True
|
|
||||||
with patch("builtins.print") as mock_print:
|
|
||||||
main()
|
|
||||||
mock_gen.assert_called_once()
|
|
||||||
mock_print.assert_called_with("diagram")
|
|
||||||
|
|
||||||
|
|
||||||
class TestRunPipelineMode:
|
class TestRunPipelineMode:
|
||||||
"""Test run_pipeline_mode() pipeline setup and execution."""
|
"""Test run_pipeline_mode() pipeline setup and execution."""
|
||||||
@@ -94,18 +79,16 @@ class TestRunPipelineMode:
|
|||||||
),
|
),
|
||||||
patch("engine.app.DisplayRegistry.create") as mock_create,
|
patch("engine.app.DisplayRegistry.create") as mock_create,
|
||||||
patch("engine.app.effects_plugins"),
|
patch("engine.app.effects_plugins"),
|
||||||
|
patch("engine.app.Pipeline") as mock_pipeline_class,
|
||||||
|
patch("engine.app.time.sleep"),
|
||||||
):
|
):
|
||||||
mock_display = MagicMock()
|
mock_display = MagicMock()
|
||||||
mock_create.return_value = mock_display
|
mock_create.return_value = mock_display
|
||||||
|
|
||||||
with (
|
|
||||||
patch("engine.app.Pipeline") as mock_pipeline_class,
|
|
||||||
patch("engine.app.time.sleep"),
|
|
||||||
pytest.raises((StopIteration, AttributeError)),
|
|
||||||
):
|
|
||||||
mock_pipeline = MagicMock()
|
mock_pipeline = MagicMock()
|
||||||
mock_pipeline_class.return_value = mock_pipeline
|
mock_pipeline_class.return_value = mock_pipeline
|
||||||
# Will timeout after first iteration
|
|
||||||
|
# Will timeout after first iteration due to KeyboardInterrupt
|
||||||
|
with pytest.raises((StopIteration, AttributeError)):
|
||||||
run_pipeline_mode("demo")
|
run_pipeline_mode("demo")
|
||||||
|
|
||||||
def test_run_pipeline_mode_handles_empty_source(self):
|
def test_run_pipeline_mode_handles_empty_source(self):
|
||||||
@@ -114,14 +97,14 @@ class TestRunPipelineMode:
|
|||||||
patch("engine.app.fetch_all") as mock_fetch,
|
patch("engine.app.fetch_all") as mock_fetch,
|
||||||
patch("engine.app.DisplayRegistry.create") as mock_create,
|
patch("engine.app.DisplayRegistry.create") as mock_create,
|
||||||
patch("engine.app.effects_plugins"),
|
patch("engine.app.effects_plugins"),
|
||||||
|
patch("engine.app.Pipeline") as mock_pipeline_class,
|
||||||
|
patch("engine.app.time.sleep"),
|
||||||
):
|
):
|
||||||
mock_display = MagicMock()
|
mock_display = MagicMock()
|
||||||
mock_create.return_value = mock_display
|
mock_create.return_value = mock_display
|
||||||
|
|
||||||
with patch("engine.app.Pipeline") as mock_pipeline_class:
|
|
||||||
mock_pipeline = MagicMock()
|
mock_pipeline = MagicMock()
|
||||||
mock_pipeline_class.return_value = mock_pipeline
|
mock_pipeline_class.return_value = mock_pipeline
|
||||||
with patch("engine.app.time.sleep"):
|
|
||||||
try:
|
try:
|
||||||
run_pipeline_mode("border-test")
|
run_pipeline_mode("border-test")
|
||||||
except (StopIteration, AttributeError):
|
except (StopIteration, AttributeError):
|
||||||
@@ -137,14 +120,14 @@ class TestRunPipelineMode:
|
|||||||
patch("engine.app.fetch_all") as mock_fetch,
|
patch("engine.app.fetch_all") as mock_fetch,
|
||||||
patch("engine.app.DisplayRegistry.create") as mock_create,
|
patch("engine.app.DisplayRegistry.create") as mock_create,
|
||||||
patch("engine.app.effects_plugins"),
|
patch("engine.app.effects_plugins"),
|
||||||
|
patch("engine.app.Pipeline") as mock_pipeline_class,
|
||||||
|
patch("engine.app.time.sleep"),
|
||||||
):
|
):
|
||||||
mock_display = MagicMock()
|
mock_display = MagicMock()
|
||||||
mock_create.return_value = mock_display
|
mock_create.return_value = mock_display
|
||||||
|
|
||||||
with patch("engine.app.Pipeline") as mock_pipeline_class:
|
|
||||||
mock_pipeline = MagicMock()
|
mock_pipeline = MagicMock()
|
||||||
mock_pipeline_class.return_value = mock_pipeline
|
mock_pipeline_class.return_value = mock_pipeline
|
||||||
with patch("engine.app.time.sleep"):
|
|
||||||
try:
|
try:
|
||||||
run_pipeline_mode("demo")
|
run_pipeline_mode("demo")
|
||||||
except (StopIteration, AttributeError):
|
except (StopIteration, AttributeError):
|
||||||
@@ -160,14 +143,14 @@ class TestRunPipelineMode:
|
|||||||
patch("engine.app.fetch_all") as mock_fetch_all,
|
patch("engine.app.fetch_all") as mock_fetch_all,
|
||||||
patch("engine.app.DisplayRegistry.create") as mock_create,
|
patch("engine.app.DisplayRegistry.create") as mock_create,
|
||||||
patch("engine.app.effects_plugins"),
|
patch("engine.app.effects_plugins"),
|
||||||
|
patch("engine.app.Pipeline") as mock_pipeline_class,
|
||||||
|
patch("engine.app.time.sleep"),
|
||||||
):
|
):
|
||||||
mock_display = MagicMock()
|
mock_display = MagicMock()
|
||||||
mock_create.return_value = mock_display
|
mock_create.return_value = mock_display
|
||||||
|
|
||||||
with patch("engine.app.Pipeline") as mock_pipeline_class:
|
|
||||||
mock_pipeline = MagicMock()
|
mock_pipeline = MagicMock()
|
||||||
mock_pipeline_class.return_value = mock_pipeline
|
mock_pipeline_class.return_value = mock_pipeline
|
||||||
with patch("engine.app.time.sleep"):
|
|
||||||
try:
|
try:
|
||||||
run_pipeline_mode("poetry")
|
run_pipeline_mode("poetry")
|
||||||
except (StopIteration, AttributeError):
|
except (StopIteration, AttributeError):
|
||||||
@@ -181,8 +164,8 @@ class TestRunPipelineMode:
|
|||||||
patch("engine.app.load_cache", return_value=None),
|
patch("engine.app.load_cache", return_value=None),
|
||||||
patch("engine.app.fetch_all", return_value=([], None, None)),
|
patch("engine.app.fetch_all", return_value=([], None, None)),
|
||||||
patch("engine.app.effects_plugins"),
|
patch("engine.app.effects_plugins"),
|
||||||
|
pytest.raises(SystemExit) as exc_info,
|
||||||
):
|
):
|
||||||
with pytest.raises(SystemExit) as exc_info:
|
|
||||||
run_pipeline_mode("demo")
|
run_pipeline_mode("demo")
|
||||||
assert exc_info.value.code == 1
|
assert exc_info.value.code == 1
|
||||||
|
|
||||||
@@ -194,14 +177,14 @@ class TestRunPipelineMode:
|
|||||||
patch("engine.app.fetch_all", return_value=(["item"], None, None)),
|
patch("engine.app.fetch_all", return_value=(["item"], None, None)),
|
||||||
patch("engine.app.DisplayRegistry.create") as mock_create,
|
patch("engine.app.DisplayRegistry.create") as mock_create,
|
||||||
patch("engine.app.effects_plugins"),
|
patch("engine.app.effects_plugins"),
|
||||||
|
patch("engine.app.Pipeline") as mock_pipeline_class,
|
||||||
|
patch("engine.app.time.sleep"),
|
||||||
):
|
):
|
||||||
mock_display = MagicMock()
|
mock_display = MagicMock()
|
||||||
mock_create.return_value = mock_display
|
mock_create.return_value = mock_display
|
||||||
|
|
||||||
with patch("engine.app.Pipeline") as mock_pipeline_class:
|
|
||||||
mock_pipeline = MagicMock()
|
mock_pipeline = MagicMock()
|
||||||
mock_pipeline_class.return_value = mock_pipeline
|
mock_pipeline_class.return_value = mock_pipeline
|
||||||
with patch("engine.app.time.sleep"):
|
|
||||||
try:
|
try:
|
||||||
run_pipeline_mode("border-test")
|
run_pipeline_mode("border-test")
|
||||||
except (StopIteration, AttributeError):
|
except (StopIteration, AttributeError):
|
||||||
@@ -216,12 +199,13 @@ class TestRunPipelineMode:
|
|||||||
patch("engine.app.load_cache", return_value=["item"]),
|
patch("engine.app.load_cache", return_value=["item"]),
|
||||||
patch("engine.app.DisplayRegistry.create") as mock_create,
|
patch("engine.app.DisplayRegistry.create") as mock_create,
|
||||||
patch("engine.app.Pipeline") as mock_pipeline_class,
|
patch("engine.app.Pipeline") as mock_pipeline_class,
|
||||||
|
patch("engine.app.time.sleep"),
|
||||||
):
|
):
|
||||||
mock_display = MagicMock()
|
mock_display = MagicMock()
|
||||||
mock_create.return_value = mock_display
|
mock_create.return_value = mock_display
|
||||||
mock_pipeline = MagicMock()
|
mock_pipeline = MagicMock()
|
||||||
mock_pipeline_class.return_value = mock_pipeline
|
mock_pipeline_class.return_value = mock_pipeline
|
||||||
with patch("engine.app.time.sleep"):
|
|
||||||
try:
|
try:
|
||||||
run_pipeline_mode("demo")
|
run_pipeline_mode("demo")
|
||||||
except (StopIteration, AttributeError):
|
except (StopIteration, AttributeError):
|
||||||
@@ -229,26 +213,6 @@ class TestRunPipelineMode:
|
|||||||
# Should call discover_plugins
|
# Should call discover_plugins
|
||||||
mock_effects.discover_plugins.assert_called_once()
|
mock_effects.discover_plugins.assert_called_once()
|
||||||
|
|
||||||
def test_run_pipeline_mode_creates_pipeline_with_preset_config(self):
|
|
||||||
"""run_pipeline_mode() creates pipeline with preset configuration."""
|
|
||||||
with (
|
|
||||||
patch("engine.app.load_cache", return_value=["item"]),
|
|
||||||
patch("engine.app.DisplayRegistry.create") as mock_create,
|
|
||||||
patch("engine.app.effects_plugins"),
|
|
||||||
patch("engine.app.Pipeline") as mock_pipeline_class,
|
|
||||||
):
|
|
||||||
mock_display = MagicMock()
|
|
||||||
mock_create.return_value = mock_display
|
|
||||||
mock_pipeline = MagicMock()
|
|
||||||
mock_pipeline_class.return_value = mock_pipeline
|
|
||||||
with patch("engine.app.time.sleep"):
|
|
||||||
try:
|
|
||||||
run_pipeline_mode("demo")
|
|
||||||
except (StopIteration, AttributeError):
|
|
||||||
pass
|
|
||||||
# Verify Pipeline was created (call may vary, but it should be called)
|
|
||||||
assert mock_pipeline_class.called
|
|
||||||
|
|
||||||
def test_run_pipeline_mode_initializes_display(self):
|
def test_run_pipeline_mode_initializes_display(self):
|
||||||
"""run_pipeline_mode() initializes display with dimensions."""
|
"""run_pipeline_mode() initializes display with dimensions."""
|
||||||
with (
|
with (
|
||||||
@@ -256,31 +220,14 @@ class TestRunPipelineMode:
|
|||||||
patch("engine.app.DisplayRegistry.create") as mock_create,
|
patch("engine.app.DisplayRegistry.create") as mock_create,
|
||||||
patch("engine.app.effects_plugins"),
|
patch("engine.app.effects_plugins"),
|
||||||
patch("engine.app.Pipeline"),
|
patch("engine.app.Pipeline"),
|
||||||
|
patch("engine.app.time.sleep"),
|
||||||
):
|
):
|
||||||
mock_display = MagicMock()
|
mock_display = MagicMock()
|
||||||
mock_create.return_value = mock_display
|
mock_create.return_value = mock_display
|
||||||
with patch("engine.app.time.sleep"):
|
|
||||||
try:
|
try:
|
||||||
run_pipeline_mode("demo")
|
run_pipeline_mode("demo")
|
||||||
except (StopIteration, AttributeError):
|
except (StopIteration, AttributeError):
|
||||||
pass
|
pass
|
||||||
# Display should be initialized with dimensions
|
# Display should be initialized with dimensions
|
||||||
mock_display.init.assert_called()
|
mock_display.init.assert_called()
|
||||||
|
|
||||||
def test_run_pipeline_mode_builds_pipeline_before_initialize(self):
|
|
||||||
"""run_pipeline_mode() calls pipeline.build() before initialize()."""
|
|
||||||
with (
|
|
||||||
patch("engine.app.load_cache", return_value=["item"]),
|
|
||||||
patch("engine.app.DisplayRegistry.create"),
|
|
||||||
patch("engine.app.effects_plugins"),
|
|
||||||
patch("engine.app.Pipeline") as mock_pipeline_class,
|
|
||||||
):
|
|
||||||
mock_pipeline = MagicMock()
|
|
||||||
mock_pipeline_class.return_value = mock_pipeline
|
|
||||||
with patch("engine.app.time.sleep"):
|
|
||||||
try:
|
|
||||||
run_pipeline_mode("demo")
|
|
||||||
except (StopIteration, AttributeError):
|
|
||||||
pass
|
|
||||||
# Build should be called
|
|
||||||
assert mock_pipeline.build.called
|
|
||||||
|
|||||||
Reference in New Issue
Block a user