Skip to content

packable

packable

Base class for packable scenario components.

Classes

Packable

Bases: BaseModel

Abstract base class for managing collections of scenarios.

Packable provides the foundation for organizing, processing, and exporting scenario data in various formats. It defines the common interface and utilities used by all specific packable implementations (inputs, queries, curves, etc.).

Subclasses should implement
  • _build_dataframe_for_scenario: Extract data from single scenario
  • from_dataframe: Import and apply data to scenarios
  • Any specialized import/export logic
Functions
set_scenario_short_names
set_scenario_short_names(scenario_short_names)

Set mapping of scenario IDs to short names for display purposes.

Source code in src/pyetm/models/packables/packable.py
def set_scenario_short_names(self, scenario_short_names: Dict[str, str]) -> None:
    """Set mapping of scenario IDs to short names for display purposes."""
    self._scenario_short_names = scenario_short_names or {}
add
add(*scenarios)

Add one or more scenarios to the packable, maintaining insertion order and uniqueness.

Source code in src/pyetm/models/packables/packable.py
def add(self, *scenarios: Session) -> None:
    """Add one or more scenarios to the packable, maintaining insertion order and uniqueness."""
    if not scenarios:
        return
    for scenario in scenarios:
        if scenario not in self.scenarios:
            self.scenarios.append(scenario)
    self._scenario_id_cache = None
discard
discard(scenario)

Removes a scenario from the pack

Source code in src/pyetm/models/packables/packable.py
def discard(self, scenario: Session) -> None:
    "Removes a scenario from the pack"
    if scenario in self.scenarios:
        self.scenarios.remove(scenario)
    self._scenario_id_cache = None
to_dataframe
to_dataframe(columns='')

Convert the pack into a dataframe

Source code in src/pyetm/models/packables/packable.py
def to_dataframe(self, columns: Any = "") -> pd.DataFrame:
    """Convert the pack into a dataframe"""
    if len(self.scenarios) == 0:
        return pd.DataFrame()
    return self._to_dataframe(columns=columns)
from_dataframe
from_dataframe(df, update_set=None)

Should parse the df and call correct setters on identified scenarios

Source code in src/pyetm/models/packables/packable.py
def from_dataframe(self, df: pd.DataFrame, update_set: Optional[Set[str]] = None) -> None:
    """Should parse the df and call correct setters on identified scenarios"""
    raise NotImplementedError
validate_config classmethod
validate_config(config)

Optional validation hook for packable configurations. Override in subclasses that need validation.

Parameters:

Name Type Description Default
config Any

Configuration value to validate

required

Returns:

Type Description
Any

Tuple of (validated_config, warnings)

List[str]
  • validated_config: The filtered/validated configuration
Tuple[Any, List[str]]
  • warnings: List of warning messages for invalid entries
Source code in src/pyetm/models/packables/packable.py
@classmethod
def validate_config(cls, config: Any) -> Tuple[Any, List[str]]:
    """
    Optional validation hook for packable configurations.
    Override in subclasses that need validation.

    Args:
        config: Configuration value to validate

    Returns:
        Tuple of (validated_config, warnings)
        - validated_config: The filtered/validated configuration
        - warnings: List of warning messages for invalid entries
    """
    return config, []
resolve_scenario
resolve_scenario(label)

Resolve a scenario from various label formats (short name, identifier, or numeric ID).

Source code in src/pyetm/models/packables/packable.py
def resolve_scenario(self, label: Any) -> Optional[Session]:
    """Resolve a scenario from various label formats (short name, identifier, or numeric ID)."""
    if label is None:
        return None

    label_str = str(label).strip()

    # Try short name first
    for scenario in self.scenarios:
        if self._scenario_short_name(scenario) == label_str:
            return scenario

    # Identifier/title
    found_scenario = self._find_by_identifier(label_str)
    if found_scenario is not None:
        return found_scenario

    # Try numeric ID as fallback
    try:
        numeric_id = int(float(label_str))
        for scenario in self.scenarios:
            if scenario.id == numeric_id:
                return scenario
    except (ValueError, TypeError):
        pass

    return None
add_to_workbook
add_to_workbook(workbook, sheet_name=None, **kwargs)

Add this pack's data to an Excel workbook as a sheet.

Source code in src/pyetm/models/packables/packable.py
def add_to_workbook(
    self, workbook: Any, sheet_name: Optional[str] = None, **kwargs: Any
) -> None:
    "Add this pack's data to an Excel workbook as a sheet."
    name = sheet_name if sheet_name else self.sheet_name
    df = self.to_dataframe(**kwargs)
    if df is not None and not df.empty:
        self._add_dataframe_to_workbook(workbook, name, df)
import_from_excel
import_from_excel(excel_file, main_df=None, scenarios_by_column=None, update_set=None)

Import pack data from Excel file. Subclasses should override this to implement specific import logic.

Source code in src/pyetm/models/packables/packable.py
def import_from_excel(
    self,
    excel_file: pd.ExcelFile,
    main_df: Optional[pd.DataFrame] = None,
    scenarios_by_column: Optional[Dict[str, Session]] = None,
    update_set: Optional[Set[str]] = None,
) -> None:
    """Import pack data from Excel file.
    Subclasses should override this to implement specific import logic."""
    df = excel_utils.parse_excel_sheet(excel_file, self.sheet_name, header=None)
    if df is not None and not df.empty:
        self.from_dataframe(df, update_set=update_set)
log_scenario_warnings
log_scenario_warnings(scenario, attribute_name, context)

Log warnings from scenario attributes if available.

Source code in src/pyetm/models/packables/packable.py
def log_scenario_warnings(
    self, scenario: Session, attribute_name: str, context: str
) -> None:
    """Log warnings from scenario attributes if available."""
    try:
        attribute = getattr(scenario, attribute_name, None)
        if attribute is not None and hasattr(attribute, "log_warnings"):
            attribute.log_warnings(
                logger,
                prefix=f"{context} warning for '{scenario.identifier()}'",
            )
    except Exception:
        pass