Spaces:
Paused
Paused
File size: 3,284 Bytes
7fb79e4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | from __future__ import annotations
import re
from dataclasses import dataclass
from typing import Iterable
_SPLIT_RE = re.compile(r"[,;\n\r]+")
_VALUE_PREFIXES = (
"dynamic_analog",
"dynamic_string",
"dynamic_level",
"dynamic_dict",
"dynamic_equipment_dict",
)
_INDICATOR_PREFIXES = (
"dynamic_status",
"dynamic_asutp_status_indicator",
)
def split_visual_names(value: object) -> list[str]:
parts = [
part.strip()
for part in _SPLIT_RE.split(str(value or ""))
if part and part.strip()
]
seen: set[str] = set()
ordered: list[str] = []
for part in parts:
key = part.lower()
if key in seen:
continue
seen.add(key)
ordered.append(part)
return ordered
def _normalized_static_names(known_static_names: Iterable[str] | None = None) -> set[str]:
return {
str(name or "").strip().lower()
for name in (known_static_names or ())
if str(name or "").strip()
}
def visual_name_role(name: str, *, known_static_names: Iterable[str] | None = None) -> str:
normalized = str(name or "").strip().lower()
if not normalized:
return "other"
known_statics = _normalized_static_names(known_static_names)
if normalized in known_statics:
return "static"
if any(normalized.startswith(prefix) for prefix in _INDICATOR_PREFIXES):
return "indicator"
if any(normalized.startswith(prefix) for prefix in _VALUE_PREFIXES):
return "value"
if normalized.startswith("dynamic_"):
return "equipment_widget"
return "static"
@dataclass(frozen=True)
class VisualSpec:
ordered: tuple[str, ...]
statics: tuple[str, ...]
value_widgets: tuple[str, ...]
indicator_widgets: tuple[str, ...]
equipment_widgets: tuple[str, ...]
@property
def widgets(self) -> tuple[str, ...]:
return self.value_widgets + self.indicator_widgets + self.equipment_widgets
@property
def is_composite(self) -> bool:
return bool(self.statics) and bool(self.widgets)
@property
def primary_category(self) -> str:
if self.value_widgets:
return "value"
if self.indicator_widgets:
return "indicator"
if self.statics or self.equipment_widgets:
return "equipment"
return "other"
def parse_visual_spec(value: object, *, known_static_names: Iterable[str] | None = None) -> VisualSpec:
ordered = split_visual_names(value)
statics: list[str] = []
value_widgets: list[str] = []
indicator_widgets: list[str] = []
equipment_widgets: list[str] = []
for part in ordered:
role = visual_name_role(part, known_static_names=known_static_names)
if role == "static":
statics.append(part)
elif role == "value":
value_widgets.append(part)
elif role == "indicator":
indicator_widgets.append(part)
elif role == "equipment_widget":
equipment_widgets.append(part)
return VisualSpec(
ordered=tuple(ordered),
statics=tuple(statics),
value_widgets=tuple(value_widgets),
indicator_widgets=tuple(indicator_widgets),
equipment_widgets=tuple(equipment_widgets),
)
|