Skip to content

Commit 77e5d7e

Browse files
authored
chore: improve resource discovery and reference handling for new sections (#1557)
* chore: improve resource discovery and reference handling for new sections
1 parent 77c40ab commit 77e5d7e

4 files changed

Lines changed: 60 additions & 8 deletions

File tree

src/libecalc/presentation/yaml/mappers/process_simulation_mapper.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,17 @@ def _get_compressor_chart(self, yaml_compressor_model_chart: YamlCompressorModel
180180
resource = self._resources.get(resource_name)
181181
if resource is None:
182182
raise EcalcValidationException(f"Resource '{resource_name}' not found for variable speed chart.")
183+
if "SPEED" not in resource.get_headers():
184+
raise EcalcValidationException(
185+
f"Chart resource '{resource_name}' is missing required 'SPEED' column. "
186+
f"For single-speed charts, use the same speed value for all rows."
187+
)
183188
try:
184189
return UserDefinedChartData.from_resource(
185-
resource, units=yaml_chart.units, is_single_speed=False, control_margin=control_margin_fraction
190+
resource,
191+
units=yaml_chart.units,
192+
is_single_speed=False,
193+
control_margin=control_margin_fraction,
186194
)
187195
except InvalidResourceException as e:
188196
raise InvalidChartResourceException(
@@ -215,13 +223,16 @@ def _resolve_fluid_model_reference(self, ref: str | YamlFluidModel) -> YamlFluid
215223
else:
216224
return ref
217225

218-
def _map_conditions(self, condition: YamlExpressionType | None, conditions: list[YamlExpressionType] | None):
219-
if condition:
226+
def _map_conditions(
227+
self, condition: YamlExpressionType | None, conditions: list[YamlExpressionType] | None
228+
) -> YamlExpressionType | None:
229+
if condition is not None:
220230
assert isinstance(condition, ExpressionType)
221231
return condition
222-
else:
232+
if conditions is not None:
223233
assert isinstance(conditions, list)
224234
return handle_condition_list(conditions)
235+
return None
225236

226237
def _get_regularity(self) -> Regularity:
227238
return Regularity(

src/libecalc/presentation/yaml/yaml_models/pyyaml_yaml_model.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@
4848
_INLET_STREAMS_KEY = "INLET_STREAMS"
4949
_FLUID_MODELS_KEY = "FLUID_MODELS"
5050
_PROCESS_SIMULATIONS_KEY = "PROCESS_SIMULATIONS"
51-
51+
_NEW_SECTIONS_WITH_FILE_REFS: tuple[str, ...] = (
52+
"PROCESS_UNITS",
53+
"PROCESS_SYSTEMS",
54+
)
5255
dt_adapter = TypeAdapter(datetime.datetime)
5356

5457

@@ -310,10 +313,16 @@ def facility_resource_names(self) -> list[str]:
310313
if isinstance(model.get(model_curves), dict)
311314
]
312315
resource_data = facility_input_data + model_curves_data
313-
resource_names = [
316+
resource_names: list[str] = [
314317
data.get(EcalcYamlKeywords.file) for data in resource_data if data.get(EcalcYamlKeywords.file) is not None
315318
]
316-
return resource_names
319+
320+
# Pick up FILE references nested in the new YAML sections (PROCESS_UNITS, PROCESS_SYSTEMS, ...).
321+
for section in _NEW_SECTIONS_WITH_FILE_REFS:
322+
resource_names.extend(_find_file_references(self._internal_datamodel.get(section)))
323+
324+
# Dedup while preserving order — the same CSV may be referenced by multiple charts.
325+
return list(dict.fromkeys(resource_names))
317326

318327
@property
319328
def timeseries_resource_names(self) -> list[str]:
@@ -627,3 +636,23 @@ def common_iterable(obj: list | dict) -> dict | Iterator[int]:
627636
output.extend(find_date_keys_in_yaml(yaml_object[index]))
628637

629638
return output
639+
640+
641+
def _find_file_references(node: dict | list | None) -> list[str]:
642+
"""Recursively collect all string values under a `FILE` key in a parsed YAML datamodel.
643+
644+
Structure-agnostic so we don't have to hard-code each section's nesting
645+
(e.g. CURVES inside COMPRESSOR_MODEL inside COMPRESSOR inside PROCESS_UNITS).
646+
Only string values are returned; anything else under FILE is ignored.
647+
"""
648+
references: list[str] = []
649+
if isinstance(node, dict):
650+
for key, value in node.items():
651+
if key == EcalcYamlKeywords.file and isinstance(value, str):
652+
references.append(value)
653+
else:
654+
references.extend(_find_file_references(value))
655+
elif isinstance(node, list):
656+
for item in node:
657+
references.extend(_find_file_references(item))
658+
return references

src/libecalc/presentation/yaml/yaml_models/yaml_model.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
)
2121
from libecalc.presentation.yaml.yaml_types.facility_model.yaml_facility_model import YamlFacilityModel
2222
from libecalc.presentation.yaml.yaml_types.fuel_type.yaml_fuel_type import YamlFuelType
23-
from libecalc.presentation.yaml.yaml_types.models import YamlConsumerModel
23+
from libecalc.presentation.yaml.yaml_types.models import YamlConsumerModel, YamlFluidModel
2424
from libecalc.presentation.yaml.yaml_types.streams.yaml_inlet_stream import YamlInletStream
2525
from libecalc.presentation.yaml.yaml_types.time_series.yaml_time_series import (
2626
YamlTimeSeriesCollection,
@@ -75,6 +75,11 @@ def models(self) -> Iterable[YamlConsumerModel]:
7575
def fuel_types(self) -> Iterable[YamlFuelType]:
7676
pass
7777

78+
@property
79+
@abc.abstractmethod
80+
def fluid_models(self) -> dict[str, YamlFluidModel]:
81+
pass
82+
7883
@property
7984
@abc.abstractmethod
8085
def inlet_streams(self) -> dict[str, YamlInletStream]:

src/libecalc/presentation/yaml/yaml_reference_service.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ def __init__(
123123
references[process_simulation.name] = process_simulation
124124
reference_yaml_context[process_simulation.name] = process_simulation_path
125125

126+
fluid_models_path = YamlPath(keys=("FLUID_MODELS",))
127+
128+
for fluid_model_key, fluid_model in configuration.fluid_models.items():
129+
fluid_model_path = fluid_models_path.append(fluid_model_key)
130+
references[fluid_model_key] = fluid_model
131+
reference_yaml_context[fluid_model_key] = fluid_model_path
132+
126133
self._references = references
127134
self._references_yaml_context = reference_yaml_context
128135

0 commit comments

Comments
 (0)