WIP #35

Open
david wants to merge 135 commits from klubhaus/sideline:feature/capability-based-deps into main
4 changed files with 71 additions and 29 deletions
Showing only changes of commit 637cbc5515 - Show all commits

View File

@@ -51,6 +51,7 @@ def run_pipeline_mode(preset_name: str = "demo"):
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,
@@ -85,19 +86,29 @@ def run_pipeline_mode(preset_name: str = "demo"):
)
print(" \033[38;5;245mFetching content...\033[0m")
cached = load_cache()
if cached:
items = cached
elif preset.source == "poetry":
items, _, _ = fetch_poetry()
# Handle special sources that don't need traditional fetching
introspection_source = None
if preset.source == "pipeline-inspect":
items = []
print(" \033[38;5;245mUsing pipeline introspection source\033[0m")
elif preset.source == "empty":
items = []
print(" \033[38;5;245mUsing empty source (no content)\033[0m")
else:
items, _, _ = fetch_all()
cached = load_cache()
if cached:
items = cached
elif preset.source == "poetry":
items, _, _ = fetch_poetry()
else:
items, _, _ = fetch_all()
if not items:
print(" \033[38;5;196mNo content available\033[0m")
sys.exit(1)
if not items:
print(" \033[38;5;196mNo content available\033[0m")
sys.exit(1)
print(f" \033[38;5;82mLoaded {len(items)} items\033[0m")
print(f" \033[38;5;82mLoaded {len(items)} items\033[0m")
display = DisplayRegistry.create(preset.display)
if not display:
@@ -108,18 +119,45 @@ def run_pipeline_mode(preset_name: str = "demo"):
effect_registry = get_registry()
pipeline.add_stage("source", create_items_stage(items, preset.source))
pipeline.add_stage(
"render",
RenderStage(
items,
width=80,
height=24,
camera_speed=params.camera_speed,
camera_mode=preset.camera,
firehose_enabled=params.firehose_enabled,
),
)
# Create source stage based on preset source type
if preset.source == "pipeline-inspect":
from engine.data_sources.pipeline_introspection import (
PipelineIntrospectionSource,
)
from engine.pipeline.adapters import DataSourceStage
introspection_source = PipelineIntrospectionSource(
pipeline=None, # Will be set after pipeline.build()
viewport_width=80,
viewport_height=24,
)
pipeline.add_stage(
"source", DataSourceStage(introspection_source, name="pipeline-inspect")
)
elif preset.source == "empty":
from engine.data_sources.sources import EmptyDataSource
from engine.pipeline.adapters import DataSourceStage
empty_source = EmptyDataSource(width=80, height=24)
pipeline.add_stage("source", DataSourceStage(empty_source, name="empty"))
else:
pipeline.add_stage("source", create_items_stage(items, preset.source))
# Add appropriate render stage
if preset.source in ("pipeline-inspect", "empty"):
pipeline.add_stage("render", SourceItemsToBufferStage(name="items-to-buffer"))
else:
pipeline.add_stage(
"render",
RenderStage(
items,
width=80,
height=24,
camera_speed=params.camera_speed,
camera_mode=preset.camera,
firehose_enabled=params.firehose_enabled,
),
)
for effect_name in preset.effects:
effect = effect_registry.get(effect_name)
@@ -132,6 +170,10 @@ def run_pipeline_mode(preset_name: str = "demo"):
pipeline.build()
# For pipeline-inspect, set the pipeline after build to avoid circular dependency
if introspection_source is not None:
introspection_source.set_pipeline(pipeline)
if not pipeline.initialize():
print(" \033[38;5;196mFailed to initialize pipeline\033[0m")
sys.exit(1)
@@ -162,7 +204,7 @@ def run_pipeline_mode(preset_name: str = "demo"):
result = pipeline.execute(items)
if result.success:
display.show(result.data)
display.show(result.data, border=params.border)
if hasattr(display, "is_quit_requested") and display.is_quit_requested():
if hasattr(display, "clear_quit_request"):

View File

@@ -30,9 +30,9 @@ class MultiDisplay:
for d in self.displays:
d.init(width, height, reuse=reuse)
def show(self, buffer: list[str]) -> None:
def show(self, buffer: list[str], border: bool = False) -> None:
for d in self.displays:
d.show(buffer)
d.show(buffer, border=border)
def clear(self) -> None:
for d in self.displays:

View File

@@ -24,7 +24,7 @@ class Display(Protocol):
"""Initialize display with dimensions."""
...
def show(self, buffer: list[str]) -> None:
def show(self, buffer: list[str], border: bool = False) -> None:
"""Show buffer on display."""
...

View File

@@ -165,10 +165,10 @@ class TestMultiDisplay:
multi = MultiDisplay([mock_display1, mock_display2])
buffer = ["line1", "line2"]
multi.show(buffer)
multi.show(buffer, border=False)
mock_display1.show.assert_called_once_with(buffer)
mock_display2.show.assert_called_once_with(buffer)
mock_display1.show.assert_called_once_with(buffer, border=False)
mock_display2.show.assert_called_once_with(buffer, border=False)
def test_clear_forwards_to_all_displays(self):
"""clear forwards to all displays."""