dfdkflj
This commit is contained in:
241
pipeline.py
241
pipeline.py
@@ -25,21 +25,18 @@ from models import PipelineStageContext
|
||||
from helper.logger import log
|
||||
|
||||
|
||||
def _is_selectable_table(table: Any) -> bool:
|
||||
"""Return True when a table can be used for @ selection."""
|
||||
return bool(table) and not getattr(table, "no_choice", False)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# PIPELINE GLOBALS (maintained for backward compatibility)
|
||||
# PIPELINE STATE
|
||||
# ============================================================================
|
||||
|
||||
# Current pipeline context (thread-local in real world, global here for simplicity)
|
||||
# Current pipeline context
|
||||
_CURRENT_CONTEXT: Optional[PipelineStageContext] = None
|
||||
|
||||
# Active execution state
|
||||
_PIPE_EMITS: List[Any] = []
|
||||
_PIPE_ACTIVE: bool = False
|
||||
_PIPE_IS_LAST: bool = False
|
||||
|
||||
# Ephemeral handoff for direct pipelines (e.g., URL --screen-shot | ...)
|
||||
_LAST_PIPELINE_CAPTURE: Optional[Any] = None
|
||||
|
||||
# Remember last search query to support refreshing results after pipeline actions
|
||||
_LAST_SEARCH_QUERY: Optional[str] = None
|
||||
|
||||
@@ -52,25 +49,23 @@ _PIPELINE_LAST_ITEMS: List[Any] = []
|
||||
# Store the last result table for @ selection syntax (e.g., @2, @2-5, @{1,3,5})
|
||||
_LAST_RESULT_TABLE: Optional[Any] = None
|
||||
_LAST_RESULT_ITEMS: List[Any] = []
|
||||
# Subject for the current result table (e.g., the file whose tags/URLs are displayed)
|
||||
# Subject for the current result table (e.g., the file whose tags/url are displayed)
|
||||
_LAST_RESULT_SUBJECT: Optional[Any] = None
|
||||
|
||||
# History of result tables for @.. navigation (LIFO stack, max 20 tables)
|
||||
_RESULT_TABLE_HISTORY: List[tuple[Optional[Any], List[Any], Optional[Any]]] = []
|
||||
_MAX_RESULT_TABLE_HISTORY = 20
|
||||
|
||||
# Forward history for @,, navigation (LIFO stack for popped tables)
|
||||
_RESULT_TABLE_FORWARD: List[tuple[Optional[Any], List[Any], Optional[Any]]] = []
|
||||
|
||||
# Current stage table for @N expansion (separate from history)
|
||||
# Used to track the ResultTable with source_command + row_selection_args from current pipeline stage
|
||||
# This is set by cmdlets that display tabular results (e.g., download-data showing formats)
|
||||
# and used by CLI to expand @N into full commands like "download-data URL -item 2"
|
||||
_CURRENT_STAGE_TABLE: Optional[Any] = None
|
||||
|
||||
# Items displayed by non-selectable commands (get-tag, delete-tag, etc.)
|
||||
# These are available for @N selection but NOT saved to history
|
||||
_DISPLAY_ITEMS: List[Any] = []
|
||||
|
||||
# Table for display-only commands (overlay)
|
||||
# Used when a command wants to show a specific table formatting but not affect history
|
||||
_DISPLAY_TABLE: Optional[Any] = None
|
||||
# Subject for overlay/display-only tables (takes precedence over _LAST_RESULT_SUBJECT)
|
||||
_DISPLAY_SUBJECT: Optional[Any] = None
|
||||
@@ -98,7 +93,7 @@ _UI_LIBRARY_REFRESH_CALLBACK: Optional[Any] = None
|
||||
# ============================================================================
|
||||
|
||||
def set_stage_context(context: Optional[PipelineStageContext]) -> None:
|
||||
"""Internal: Set the current pipeline stage context."""
|
||||
"""Set the current pipeline stage context."""
|
||||
global _CURRENT_CONTEXT
|
||||
_CURRENT_CONTEXT = context
|
||||
|
||||
@@ -126,26 +121,21 @@ def emit(obj: Any) -> None:
|
||||
return 0
|
||||
```
|
||||
"""
|
||||
# Try new context-based approach first
|
||||
if _CURRENT_CONTEXT is not None:
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.debug(f"[EMIT] Context-based: appending to _CURRENT_CONTEXT.emits. obj={obj}")
|
||||
_CURRENT_CONTEXT.emit(obj)
|
||||
return
|
||||
|
||||
|
||||
def emit_list(objects: List[Any]) -> None:
|
||||
"""Emit a list of objects to the next pipeline stage.
|
||||
|
||||
# Fallback to legacy global approach (for backward compatibility)
|
||||
try:
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.debug(f"[EMIT] Legacy: appending to _PIPE_EMITS. obj type={type(obj).__name__}, _PIPE_EMITS len before={len(_PIPE_EMITS)}")
|
||||
_PIPE_EMITS.append(obj)
|
||||
logger.debug(f"[EMIT] Legacy: _PIPE_EMITS len after={len(_PIPE_EMITS)}")
|
||||
except Exception as e:
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.error(f"[EMIT] Error appending to _PIPE_EMITS: {e}", exc_info=True)
|
||||
pass
|
||||
This allows cmdlets to emit multiple results that are tracked as a list,
|
||||
enabling downstream cmdlets to process all of them or filter by metadata.
|
||||
|
||||
Args:
|
||||
objects: List of objects to emit
|
||||
"""
|
||||
if _CURRENT_CONTEXT is not None:
|
||||
_CURRENT_CONTEXT.emit(objects)
|
||||
|
||||
|
||||
def print_if_visible(*args: Any, file=None, **kwargs: Any) -> None:
|
||||
@@ -171,7 +161,7 @@ def print_if_visible(*args: Any, file=None, **kwargs: Any) -> None:
|
||||
"""
|
||||
try:
|
||||
# Print if: not in a pipeline OR this is the last stage
|
||||
should_print = (not _PIPE_ACTIVE) or _PIPE_IS_LAST
|
||||
should_print = (_CURRENT_CONTEXT is None) or (_CURRENT_CONTEXT and _CURRENT_CONTEXT.is_last_stage)
|
||||
|
||||
# Always print to stderr regardless
|
||||
if file is not None:
|
||||
@@ -304,17 +294,17 @@ def clear_pending_pipeline_tail() -> None:
|
||||
_PENDING_PIPELINE_SOURCE = None
|
||||
|
||||
|
||||
|
||||
|
||||
def reset() -> None:
|
||||
"""Reset all pipeline state. Called between pipeline executions."""
|
||||
global _PIPE_EMITS, _PIPE_ACTIVE, _PIPE_IS_LAST, _PIPELINE_VALUES
|
||||
global _LAST_PIPELINE_CAPTURE, _PIPELINE_REFRESHED, _PIPELINE_LAST_ITEMS
|
||||
global _PIPELINE_COMMAND_TEXT, _LAST_RESULT_SUBJECT, _DISPLAY_SUBJECT
|
||||
global _PENDING_PIPELINE_TAIL, _PENDING_PIPELINE_SOURCE
|
||||
global _PIPELINE_VALUES, _LAST_SEARCH_QUERY, _PIPELINE_REFRESHED
|
||||
global _PIPELINE_LAST_ITEMS, _PIPELINE_COMMAND_TEXT, _LAST_RESULT_SUBJECT
|
||||
global _DISPLAY_SUBJECT, _PENDING_PIPELINE_TAIL, _PENDING_PIPELINE_SOURCE
|
||||
global _CURRENT_CONTEXT
|
||||
|
||||
_PIPE_EMITS = []
|
||||
_PIPE_ACTIVE = False
|
||||
_PIPE_IS_LAST = False
|
||||
_LAST_PIPELINE_CAPTURE = None
|
||||
_CURRENT_CONTEXT = None
|
||||
_LAST_SEARCH_QUERY = None
|
||||
_PIPELINE_REFRESHED = False
|
||||
_PIPELINE_LAST_ITEMS = []
|
||||
_PIPELINE_VALUES = {}
|
||||
@@ -327,13 +317,15 @@ def reset() -> None:
|
||||
|
||||
def get_emitted_items() -> List[Any]:
|
||||
"""Get a copy of all items emitted by the current pipeline stage."""
|
||||
return list(_PIPE_EMITS)
|
||||
if _CURRENT_CONTEXT is not None:
|
||||
return list(_CURRENT_CONTEXT.emits)
|
||||
return []
|
||||
|
||||
|
||||
def clear_emits() -> None:
|
||||
"""Clear the emitted items list (called between stages)."""
|
||||
global _PIPE_EMITS
|
||||
_PIPE_EMITS = []
|
||||
if _CURRENT_CONTEXT is not None:
|
||||
_CURRENT_CONTEXT.emits.clear()
|
||||
|
||||
|
||||
def set_last_selection(indices: Sequence[int]) -> None:
|
||||
@@ -375,20 +367,8 @@ def clear_current_command_text() -> None:
|
||||
_PIPELINE_COMMAND_TEXT = ""
|
||||
|
||||
|
||||
def set_active(active: bool) -> None:
|
||||
"""Internal: Set whether we're in a pipeline context."""
|
||||
global _PIPE_ACTIVE
|
||||
_PIPE_ACTIVE = active
|
||||
|
||||
|
||||
def set_last_stage(is_last: bool) -> None:
|
||||
"""Internal: Set whether this is the last stage of the pipeline."""
|
||||
global _PIPE_IS_LAST
|
||||
_PIPE_IS_LAST = is_last
|
||||
|
||||
|
||||
def set_search_query(query: Optional[str]) -> None:
|
||||
"""Internal: Set the last search query for refresh purposes."""
|
||||
"""Set the last search query for refresh purposes."""
|
||||
global _LAST_SEARCH_QUERY
|
||||
_LAST_SEARCH_QUERY = query
|
||||
|
||||
@@ -399,7 +379,7 @@ def get_search_query() -> Optional[str]:
|
||||
|
||||
|
||||
def set_pipeline_refreshed(refreshed: bool) -> None:
|
||||
"""Internal: Track whether the pipeline already refreshed results."""
|
||||
"""Track whether the pipeline already refreshed results."""
|
||||
global _PIPELINE_REFRESHED
|
||||
_PIPELINE_REFRESHED = refreshed
|
||||
|
||||
@@ -410,7 +390,7 @@ def was_pipeline_refreshed() -> bool:
|
||||
|
||||
|
||||
def set_last_items(items: list) -> None:
|
||||
"""Internal: Cache the last pipeline outputs."""
|
||||
"""Cache the last pipeline outputs."""
|
||||
global _PIPELINE_LAST_ITEMS
|
||||
_PIPELINE_LAST_ITEMS = list(items) if items else []
|
||||
|
||||
@@ -420,17 +400,6 @@ def get_last_items() -> List[Any]:
|
||||
return list(_PIPELINE_LAST_ITEMS)
|
||||
|
||||
|
||||
def set_last_capture(obj: Any) -> None:
|
||||
"""Internal: Store ephemeral handoff for direct pipelines."""
|
||||
global _LAST_PIPELINE_CAPTURE
|
||||
_LAST_PIPELINE_CAPTURE = obj
|
||||
|
||||
|
||||
def get_last_capture() -> Optional[Any]:
|
||||
"""Get ephemeral pipeline handoff (e.g., URL --screen-shot | ...)."""
|
||||
return _LAST_PIPELINE_CAPTURE
|
||||
|
||||
|
||||
def set_ui_library_refresh_callback(callback: Any) -> None:
|
||||
"""Set a callback to be called when library content is updated.
|
||||
|
||||
@@ -501,6 +470,22 @@ def set_last_result_table(result_table: Optional[Any], items: Optional[List[Any]
|
||||
_LAST_RESULT_TABLE = result_table
|
||||
_LAST_RESULT_ITEMS = items or []
|
||||
_LAST_RESULT_SUBJECT = subject
|
||||
|
||||
# Sort table by Title/Name column alphabetically if available
|
||||
if result_table is not None and hasattr(result_table, 'sort_by_title') and not getattr(result_table, 'preserve_order', False):
|
||||
try:
|
||||
result_table.sort_by_title()
|
||||
# Re-order items list to match the sorted table
|
||||
if _LAST_RESULT_ITEMS and hasattr(result_table, 'rows'):
|
||||
sorted_items = []
|
||||
for row in result_table.rows:
|
||||
src_idx = getattr(row, 'source_index', None)
|
||||
if isinstance(src_idx, int) and 0 <= src_idx < len(_LAST_RESULT_ITEMS):
|
||||
sorted_items.append(_LAST_RESULT_ITEMS[src_idx])
|
||||
if len(sorted_items) == len(result_table.rows):
|
||||
_LAST_RESULT_ITEMS = sorted_items
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def set_last_result_table_overlay(result_table: Optional[Any], items: Optional[List[Any]] = None, subject: Optional[Any] = None) -> None:
|
||||
@@ -518,6 +503,22 @@ def set_last_result_table_overlay(result_table: Optional[Any], items: Optional[L
|
||||
_DISPLAY_TABLE = result_table
|
||||
_DISPLAY_ITEMS = items or []
|
||||
_DISPLAY_SUBJECT = subject
|
||||
|
||||
# Sort table by Title/Name column alphabetically if available
|
||||
if result_table is not None and hasattr(result_table, 'sort_by_title') and not getattr(result_table, 'preserve_order', False):
|
||||
try:
|
||||
result_table.sort_by_title()
|
||||
# Re-order items list to match the sorted table
|
||||
if _DISPLAY_ITEMS and hasattr(result_table, 'rows'):
|
||||
sorted_items = []
|
||||
for row in result_table.rows:
|
||||
src_idx = getattr(row, 'source_index', None)
|
||||
if isinstance(src_idx, int) and 0 <= src_idx < len(_DISPLAY_ITEMS):
|
||||
sorted_items.append(_DISPLAY_ITEMS[src_idx])
|
||||
if len(sorted_items) == len(result_table.rows):
|
||||
_DISPLAY_ITEMS = sorted_items
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def set_last_result_table_preserve_history(result_table: Optional[Any], items: Optional[List[Any]] = None, subject: Optional[Any] = None) -> None:
|
||||
@@ -567,7 +568,7 @@ def restore_previous_result_table() -> bool:
|
||||
True if a previous table was restored, False if history is empty
|
||||
"""
|
||||
global _LAST_RESULT_TABLE, _LAST_RESULT_ITEMS, _LAST_RESULT_SUBJECT
|
||||
global _RESULT_TABLE_HISTORY, _DISPLAY_ITEMS, _DISPLAY_TABLE, _DISPLAY_SUBJECT
|
||||
global _RESULT_TABLE_HISTORY, _RESULT_TABLE_FORWARD, _DISPLAY_ITEMS, _DISPLAY_TABLE, _DISPLAY_SUBJECT
|
||||
|
||||
# If we have an active overlay (display items/table), clear it to "go back" to the underlying table
|
||||
if _DISPLAY_ITEMS or _DISPLAY_TABLE or _DISPLAY_SUBJECT is not None:
|
||||
@@ -579,6 +580,9 @@ def restore_previous_result_table() -> bool:
|
||||
if not _RESULT_TABLE_HISTORY:
|
||||
return False
|
||||
|
||||
# Save current state to forward stack before popping
|
||||
_RESULT_TABLE_FORWARD.append((_LAST_RESULT_TABLE, _LAST_RESULT_ITEMS, _LAST_RESULT_SUBJECT))
|
||||
|
||||
# Pop from history and restore
|
||||
prev = _RESULT_TABLE_HISTORY.pop()
|
||||
if isinstance(prev, tuple) and len(prev) >= 3:
|
||||
@@ -595,6 +599,44 @@ def restore_previous_result_table() -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def restore_next_result_table() -> bool:
|
||||
"""Restore the next result table from forward history (for @,, navigation).
|
||||
|
||||
Returns:
|
||||
True if a next table was restored, False if forward history is empty
|
||||
"""
|
||||
global _LAST_RESULT_TABLE, _LAST_RESULT_ITEMS, _LAST_RESULT_SUBJECT
|
||||
global _RESULT_TABLE_HISTORY, _RESULT_TABLE_FORWARD, _DISPLAY_ITEMS, _DISPLAY_TABLE, _DISPLAY_SUBJECT
|
||||
|
||||
# If we have an active overlay (display items/table), clear it to "go forward" to the underlying table
|
||||
if _DISPLAY_ITEMS or _DISPLAY_TABLE or _DISPLAY_SUBJECT is not None:
|
||||
_DISPLAY_ITEMS = []
|
||||
_DISPLAY_TABLE = None
|
||||
_DISPLAY_SUBJECT = None
|
||||
return True
|
||||
|
||||
if not _RESULT_TABLE_FORWARD:
|
||||
return False
|
||||
|
||||
# Save current state to history stack before popping forward
|
||||
_RESULT_TABLE_HISTORY.append((_LAST_RESULT_TABLE, _LAST_RESULT_ITEMS, _LAST_RESULT_SUBJECT))
|
||||
|
||||
# Pop from forward stack and restore
|
||||
next_state = _RESULT_TABLE_FORWARD.pop()
|
||||
if isinstance(next_state, tuple) and len(next_state) >= 3:
|
||||
_LAST_RESULT_TABLE, _LAST_RESULT_ITEMS, _LAST_RESULT_SUBJECT = next_state[0], next_state[1], next_state[2]
|
||||
elif isinstance(next_state, tuple) and len(next_state) == 2:
|
||||
_LAST_RESULT_TABLE, _LAST_RESULT_ITEMS = next_state
|
||||
_LAST_RESULT_SUBJECT = None
|
||||
else:
|
||||
_LAST_RESULT_TABLE, _LAST_RESULT_ITEMS, _LAST_RESULT_SUBJECT = None, [], None
|
||||
# Clear display items so get_last_result_items() falls back to restored items
|
||||
_DISPLAY_ITEMS = []
|
||||
_DISPLAY_TABLE = None
|
||||
_DISPLAY_SUBJECT = None
|
||||
return True
|
||||
|
||||
|
||||
def get_display_table() -> Optional[Any]:
|
||||
"""Get the current display overlay table.
|
||||
|
||||
@@ -637,9 +679,15 @@ def get_last_result_items() -> List[Any]:
|
||||
# Prioritize items from display commands (get-tag, delete-tag, etc.)
|
||||
# These are available for immediate @N selection
|
||||
if _DISPLAY_ITEMS:
|
||||
if _DISPLAY_TABLE is not None and not _is_selectable_table(_DISPLAY_TABLE):
|
||||
return []
|
||||
return _DISPLAY_ITEMS
|
||||
# Fall back to items from last search/selectable command
|
||||
return _LAST_RESULT_ITEMS
|
||||
if _LAST_RESULT_TABLE is None:
|
||||
return _LAST_RESULT_ITEMS
|
||||
if _is_selectable_table(_LAST_RESULT_TABLE):
|
||||
return _LAST_RESULT_ITEMS
|
||||
return []
|
||||
|
||||
|
||||
def get_last_result_table_source_command() -> Optional[str]:
|
||||
@@ -648,7 +696,7 @@ def get_last_result_table_source_command() -> Optional[str]:
|
||||
Returns:
|
||||
Command name (e.g., 'download-data') or None if not set
|
||||
"""
|
||||
if _LAST_RESULT_TABLE and hasattr(_LAST_RESULT_TABLE, 'source_command'):
|
||||
if _is_selectable_table(_LAST_RESULT_TABLE) and hasattr(_LAST_RESULT_TABLE, 'source_command'):
|
||||
return _LAST_RESULT_TABLE.source_command
|
||||
return None
|
||||
|
||||
@@ -659,7 +707,7 @@ def get_last_result_table_source_args() -> List[str]:
|
||||
Returns:
|
||||
List of arguments (e.g., ['https://example.com']) or empty list
|
||||
"""
|
||||
if _LAST_RESULT_TABLE and hasattr(_LAST_RESULT_TABLE, 'source_args'):
|
||||
if _is_selectable_table(_LAST_RESULT_TABLE) and hasattr(_LAST_RESULT_TABLE, 'source_args'):
|
||||
return _LAST_RESULT_TABLE.source_args or []
|
||||
return []
|
||||
|
||||
@@ -673,7 +721,7 @@ def get_last_result_table_row_selection_args(row_index: int) -> Optional[List[st
|
||||
Returns:
|
||||
Selection arguments (e.g., ['-item', '3']) or None
|
||||
"""
|
||||
if _LAST_RESULT_TABLE and hasattr(_LAST_RESULT_TABLE, 'rows'):
|
||||
if _is_selectable_table(_LAST_RESULT_TABLE) and hasattr(_LAST_RESULT_TABLE, 'rows'):
|
||||
if 0 <= row_index < len(_LAST_RESULT_TABLE.rows):
|
||||
row = _LAST_RESULT_TABLE.rows[row_index]
|
||||
if hasattr(row, 'selection_args'):
|
||||
@@ -696,13 +744,18 @@ def set_current_stage_table(result_table: Optional[Any]) -> None:
|
||||
_CURRENT_STAGE_TABLE = result_table
|
||||
|
||||
|
||||
def get_current_stage_table() -> Optional[Any]:
|
||||
"""Get the current pipeline stage table (if any)."""
|
||||
return _CURRENT_STAGE_TABLE
|
||||
|
||||
|
||||
def get_current_stage_table_source_command() -> Optional[str]:
|
||||
"""Get the source command from the current pipeline stage table.
|
||||
|
||||
Returns:
|
||||
Command name (e.g., 'download-data') or None
|
||||
"""
|
||||
if _CURRENT_STAGE_TABLE and hasattr(_CURRENT_STAGE_TABLE, 'source_command'):
|
||||
if _is_selectable_table(_CURRENT_STAGE_TABLE) and hasattr(_CURRENT_STAGE_TABLE, 'source_command'):
|
||||
return _CURRENT_STAGE_TABLE.source_command
|
||||
return None
|
||||
|
||||
@@ -713,7 +766,7 @@ def get_current_stage_table_source_args() -> List[str]:
|
||||
Returns:
|
||||
List of arguments or empty list
|
||||
"""
|
||||
if _CURRENT_STAGE_TABLE and hasattr(_CURRENT_STAGE_TABLE, 'source_args'):
|
||||
if _is_selectable_table(_CURRENT_STAGE_TABLE) and hasattr(_CURRENT_STAGE_TABLE, 'source_args'):
|
||||
return _CURRENT_STAGE_TABLE.source_args or []
|
||||
return []
|
||||
|
||||
@@ -727,7 +780,7 @@ def get_current_stage_table_row_selection_args(row_index: int) -> Optional[List[
|
||||
Returns:
|
||||
Selection arguments or None
|
||||
"""
|
||||
if _CURRENT_STAGE_TABLE and hasattr(_CURRENT_STAGE_TABLE, 'rows'):
|
||||
if _is_selectable_table(_CURRENT_STAGE_TABLE) and hasattr(_CURRENT_STAGE_TABLE, 'rows'):
|
||||
if 0 <= row_index < len(_CURRENT_STAGE_TABLE.rows):
|
||||
row = _CURRENT_STAGE_TABLE.rows[row_index]
|
||||
if hasattr(row, 'selection_args'):
|
||||
@@ -735,23 +788,21 @@ def get_current_stage_table_row_selection_args(row_index: int) -> Optional[List[
|
||||
return None
|
||||
|
||||
|
||||
def get_current_stage_table_row_source_index(row_index: int) -> Optional[int]:
|
||||
"""Get the original source index for a row in the current stage table.
|
||||
|
||||
Useful when the table has been sorted for display but selections should map
|
||||
back to the original item order (e.g., playlist or provider order).
|
||||
"""
|
||||
if _is_selectable_table(_CURRENT_STAGE_TABLE) and hasattr(_CURRENT_STAGE_TABLE, 'rows'):
|
||||
if 0 <= row_index < len(_CURRENT_STAGE_TABLE.rows):
|
||||
row = _CURRENT_STAGE_TABLE.rows[row_index]
|
||||
return getattr(row, 'source_index', None)
|
||||
return None
|
||||
|
||||
|
||||
def clear_last_result() -> None:
|
||||
"""Clear the stored last result table and items."""
|
||||
global _LAST_RESULT_TABLE, _LAST_RESULT_ITEMS
|
||||
_LAST_RESULT_TABLE = None
|
||||
_LAST_RESULT_ITEMS = []
|
||||
|
||||
|
||||
def emit_list(objects: List[Any]) -> None:
|
||||
"""Emit a list of PipeObjects to the next pipeline stage.
|
||||
|
||||
This allows cmdlets to emit multiple results that are tracked as a list,
|
||||
enabling downstream cmdlets to process all of them or filter by metadata.
|
||||
|
||||
Args:
|
||||
objects: List of PipeObject instances or dicts to emit
|
||||
"""
|
||||
if _CURRENT_CONTEXT is not None:
|
||||
_CURRENT_CONTEXT.emit(objects)
|
||||
else:
|
||||
_PIPE_EMITS.append(objects)
|
||||
|
||||
Reference in New Issue
Block a user