107 lines
2.7 KiB
Python
107 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Literal
|
|
|
|
|
|
PortDisplaySide = Literal["left", "right"]
|
|
ComponentCatalogRole = Literal["amesimGasMediumDefinition"]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ComponentCategorySpec:
|
|
"""A presentation-only category declared by one component library."""
|
|
|
|
id: str
|
|
label: str
|
|
order: int = 0
|
|
|
|
def as_catalog_dict(self) -> dict[str, object]:
|
|
return {
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"order": self.order,
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class PortDisplaySpec:
|
|
"""Canvas placement for one port without changing its physical contract."""
|
|
|
|
name: str
|
|
side: PortDisplaySide
|
|
order: int = 0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ParameterGroupDisplaySpec:
|
|
"""Ordered, collapsible presentation group for component parameters."""
|
|
|
|
id: str
|
|
label: str
|
|
parameters: tuple[str, ...]
|
|
order: int = 0
|
|
default_expanded: bool = False
|
|
|
|
def as_catalog_dict(self) -> dict[str, object]:
|
|
return {
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"parameters": list(self.parameters),
|
|
"order": self.order,
|
|
"defaultExpanded": self.default_expanded,
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ComponentDisplaySpec:
|
|
"""Frontend metadata co-located with a component implementation."""
|
|
|
|
label: str
|
|
library_id: str
|
|
category_id: str
|
|
symbol: str
|
|
ports: tuple[PortDisplaySpec, ...]
|
|
order: int = 0
|
|
role: ComponentCatalogRole | None = None
|
|
parameter_groups: tuple[ParameterGroupDisplaySpec, ...] = ()
|
|
|
|
@property
|
|
def port_by_name(self) -> dict[str, PortDisplaySpec]:
|
|
return {port.name: port for port in self.ports}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ComponentLibrarySpec:
|
|
"""Manifest for one explicitly enabled component library."""
|
|
|
|
id: str
|
|
label: str
|
|
version: str
|
|
source_package: str
|
|
categories: tuple[ComponentCategorySpec, ...]
|
|
models: tuple[str, ...]
|
|
temporary: bool = False
|
|
order: int = 0
|
|
|
|
@property
|
|
def category_by_id(self) -> dict[str, ComponentCategorySpec]:
|
|
return {category.id: category for category in self.categories}
|
|
|
|
def as_catalog_dict(self) -> dict[str, object]:
|
|
return {
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"version": self.version,
|
|
"sourcePackage": self.source_package,
|
|
"temporary": self.temporary,
|
|
"order": self.order,
|
|
"categories": [
|
|
category.as_catalog_dict()
|
|
for category in sorted(
|
|
self.categories,
|
|
key=lambda item: (item.order, item.id),
|
|
)
|
|
],
|
|
}
|