Skip to content

Commit 897da74

Browse files
committed
Update all models to use Warnings
1 parent bfe2ca8 commit 897da74

15 files changed

+447
-317
lines changed

src/pyetm/models/base.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,9 @@ def add_warning(
9292
def warnings(self) -> Union[WarningCollector, Dict[str, List[str]]]:
9393
"""
9494
Return warnings.
95-
96-
For backward compatibility, this can return either the new WarningCollector
97-
or the legacy dict format. The implementation can be switched based on needs.
9895
"""
99-
# Return the new collector (recommended)
10096
return self._warning_collector
10197

102-
# OR return legacy format for backward compatibility:
103-
# return self._warning_collector.to_legacy_dict()
104-
10598
def show_warnings(self) -> None:
10699
"""Print all warnings to the console."""
107100
self._warning_collector.show_warnings()

src/pyetm/models/custom_curves.py

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Optional
55
from pyetm.clients import BaseClient
66
from pyetm.models.base import Base
7+
from pyetm.models.warnings import WarningCollector
78
from pyetm.services.scenario_runners.fetch_custom_curves import (
89
DownloadCustomCurveRunner,
910
)
@@ -59,10 +60,7 @@ def retrieve(self, client, scenario) -> Optional[pd.DataFrame]:
5960
return curve.rename(self.key)
6061
except Exception as e:
6162
# File processing error - add warning and return None
62-
self.add_warning(
63-
self.key,
64-
f"Failed to process curve data: {e}"
65-
)
63+
self.add_warning(self.key, f"Failed to process curve data: {e}")
6664
return None
6765
else:
6866
# API call failed - add warning for each error
@@ -119,8 +117,8 @@ def from_json(cls, data: dict) -> CustomCurve:
119117
"key": data.get("key", "unknown"),
120118
"type": data.get("type", "unknown"),
121119
}
122-
curve = cls.model_validate(basic_data)
123-
curve.add_warning(basic_data["key"], f"Failed to create curve from data: {e}")
120+
curve = cls.model_construct(**basic_data)
121+
curve.add_warning("base", f"Failed to create curve from data: {e}")
124122
return curve
125123

126124

@@ -147,19 +145,17 @@ def get_contents(
147145
curve = self._find(curve_name)
148146

149147
if not curve:
150-
self.add_warning('curves', f"Curve {curve_name} not found in collection")
148+
self.add_warning("curves", f"Curve {curve_name} not found in collection")
151149
return None
152150

153151
if not curve.available():
154152
# Try to retrieve it
155153
result = curve.retrieve(BaseClient(), scenario)
156-
# Merge any warnings from the curve retrieval
157-
self._merge_submodel_warnings(curve)
154+
self._merge_submodel_warnings(curve, key_attr="key")
158155
return result
159156
else:
160157
contents = curve.contents()
161-
# Merge any warnings from reading contents
162-
self._merge_submodel_warnings(curve)
158+
self._merge_submodel_warnings(curve, key_attr="key")
163159
return contents
164160

165161
def _find(self, curve_name: str) -> Optional[CustomCurve]:
@@ -171,24 +167,23 @@ def from_json(cls, data: list[dict]) -> CustomCurves:
171167
Initialize CustomCurves collection from JSON data
172168
"""
173169
curves = []
174-
collection_warnings = {}
175170

176171
for curve_data in data:
177172
try:
178-
key = curve_data['key']
179173
curve = CustomCurve.from_json(curve_data)
180174
curves.append(curve)
181175
except Exception as e:
182-
# Log the problematic curve but continue processing
183-
collection_warnings[f"CustomCurve(key={key})"] = f"Skipped invalid curve data: {e}"
176+
# Create a basic curve and continue processing
177+
key = curve_data.get("key", "unknown")
178+
basic_curve = CustomCurve.model_construct(key=key, type="unknown")
179+
basic_curve.add_warning(key, f"Skipped invalid curve data: {e}")
180+
curves.append(basic_curve)
184181

185182
collection = cls.model_validate({"curves": curves})
186183

187-
# Add any collection-level warnings
188-
for loc, msg in collection_warnings.items():
189-
collection.add_warning(loc, msg)
190-
191-
# Merge warnings from individual curves
192-
collection._merge_submodel_warnings(*curves, key_attr='key')
184+
# Merge warnings from individual curves using new system
185+
collection._merge_submodel_warnings(*curves, key_attr="key")
193186

194187
return collection
188+
189+
# TODO: _to_dataframe

src/pyetm/models/gqueries.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
class Gqueries(Base):
1212
"""
13-
We cannot validat yet - as we'd need a servcie connected to the main
13+
We cannot validate yet - as we'd need a service connected to the main
1414
gquery endpoint
1515
"""
1616

@@ -48,7 +48,7 @@ def execute(self, client, scenario):
4848
if result.success:
4949
self.update(result.data)
5050
else:
51-
self.add_warning('results', f"Error retrieving queries: {result.errors}")
51+
self.add_warning("results", f"Error retrieving queries: {result.errors}")
5252

5353
def to_dataframe(self, columns="future"):
5454
if not self.is_ready():
@@ -58,6 +58,13 @@ def to_dataframe(self, columns="future"):
5858
df.index.name = "gquery"
5959
return df.set_index("unit", append=True)
6060

61+
def _to_dataframe(self, **kwargs) -> pd.DataFrame:
62+
"""
63+
Implementation required by Base class.
64+
Uses to_dataframe with default parameters.
65+
"""
66+
return self.to_dataframe()
67+
6168
@classmethod
6269
def from_list(cls, query_list: list[str]):
6370
return cls(query_dict={q: None for q in query_list})

src/pyetm/models/inputs.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ def from_json(cls, data: tuple[str, dict]) -> "Input":
4545
except Exception as e:
4646
# Create a basic Input with warning attached
4747
basic_input = cls.model_construct(**payload) # Bypass validation
48-
basic_input._warning_collector = WarningCollector()
4948
basic_input.add_warning(key, f"Failed to create specialized input: {e}")
5049
return basic_input
5150

@@ -114,7 +113,7 @@ def check_permitted(self) -> EnumInput:
114113
"ValueError",
115114
type="inclusion",
116115
loc="user",
117-
msg=f"Value error, {self.user} should be in {self.permitted_values}",
116+
msg=f"Value error, {self.value} should be in {self.permitted_values}",
118117
)
119118

120119

@@ -180,10 +179,7 @@ def is_valid_update(self, key_vals: dict) -> dict[str, WarningCollector]:
180179
# Check for non-existent keys
181180
non_existent_keys = set(key_vals.keys()) - set(self.keys())
182181
for key in non_existent_keys:
183-
# Create a warning collector for non-existent keys
184-
warning_collector = WarningCollector()
185-
warning_collector.add(key, "Key does not exist")
186-
warnings[key] = warning_collector
182+
warnings[key] = WarningCollector.with_warning(key, "Key does not exist")
187183

188184
return warnings
189185

src/pyetm/models/output_curves.py

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import yaml
88
from pyetm.clients import BaseClient
99
from pyetm.models.base import Base
10+
from pyetm.models.warnings import WarningCollector
1011
from pyetm.config.settings import get_settings
1112
from pyetm.services.scenario_runners.fetch_output_curves import (
1213
DownloadOutputCurveRunner,
@@ -59,27 +60,32 @@ def retrieve(self, client, scenario) -> Optional[pd.DataFrame]:
5960

6061
except Exception as e:
6162
self.add_warning(
62-
'data',
63-
f"Failed to process curve data for {self.key}: {e}"
63+
"data", f"Failed to process curve data for {self.key}: {e}"
6464
)
6565
return None
6666

6767
except Exception as e:
6868
# Unexpected error - add warning
69-
self.add_warning('base', f"Unexpected error retrieving curve {self.key}: {e}")
69+
self.add_warning(
70+
"base", f"Unexpected error retrieving curve {self.key}: {e}"
71+
)
7072
return None
7173

7274
def contents(self) -> Optional[pd.DataFrame]:
7375
"""Open file from path and return contents"""
7476
if not self.available():
75-
self.add_warning('file_path', f"Curve {self.key} not available - no file path set")
77+
self.add_warning(
78+
"file_path", f"Curve {self.key} not available - no file path set"
79+
)
7680
return None
7781

7882
try:
7983
df = pd.read_csv(self.file_path, index_col=0)
8084
return df.dropna(how="all")
8185
except Exception as e:
82-
self.add_warning('file_path', f"Failed to read curve file for {self.key}: {e}")
86+
self.add_warning(
87+
"file_path", f"Failed to read curve file for {self.key}: {e}"
88+
)
8389
return None
8490

8591
def remove(self) -> bool:
@@ -92,7 +98,9 @@ def remove(self) -> bool:
9298
self.file_path = None
9399
return True
94100
except Exception as e:
95-
self.add_warning('file_path', f"Failed to remove curve file for {self.key}: {e}")
101+
self.add_warning(
102+
"file_path", f"Failed to remove curve file for {self.key}: {e}"
103+
)
96104
return False
97105

98106
@classmethod
@@ -109,8 +117,8 @@ def from_json(cls, data: dict) -> OutputCurve:
109117
"key": data.get("key", "unknown"),
110118
"type": data.get("type", "unknown"),
111119
}
112-
curve = cls.model_validate(basic_data)
113-
curve.add_warning('base', f"Failed to create curve from data: {e}")
120+
curve = cls.model_construct(**basic_data)
121+
curve.add_warning("base", f"Failed to create curve from data: {e}")
114122
return curve
115123

116124

@@ -135,19 +143,19 @@ def get_contents(self, scenario, curve_name: str) -> Optional[pd.DataFrame]:
135143
curve = self._find(curve_name)
136144

137145
if not curve:
138-
self.add_warning('curves', f"Curve {curve_name} not found in collection")
146+
self.add_warning("curves", f"Curve {curve_name} not found in collection")
139147
return None
140148

141149
if not curve.available():
142150
# Try to retrieve it
143151
result = curve.retrieve(BaseClient(), scenario)
144-
# Merge any warnings from the curve retrieval
145-
self._merge_submodel_warnings(curve)
152+
# Merge any warnings from the curve retrieval using new system
153+
self._merge_submodel_warnings(curve, key_attr="key")
146154
return result
147155
else:
148156
contents = curve.contents()
149-
# Merge any warnings from reading contents
150-
self._merge_submodel_warnings(curve)
157+
# Merge any warnings from reading contents using new system
158+
self._merge_submodel_warnings(curve, key_attr="key")
151159
return contents
152160

153161
@staticmethod
@@ -203,8 +211,8 @@ def get_curves_by_carrier_type(
203211
if carrier_type not in carrier_mapping:
204212
valid_types = ", ".join(carrier_mapping.keys())
205213
self.add_warning(
206-
'carrier_type',
207-
f"Invalid carrier type '{carrier_type}'. Valid types: {valid_types}"
214+
"carrier_type",
215+
f"Invalid carrier type '{carrier_type}'. Valid types: {valid_types}",
208216
)
209217
return {}
210218

@@ -225,25 +233,22 @@ def from_json(cls, data: list[dict]) -> OutputCurves:
225233
Initialize OutputCurves collection from JSON data
226234
"""
227235
curves = []
228-
collection_warnings = {}
229236

230237
for curve_data in data:
231238
try:
232-
key = curve_data['key']
233239
curve = OutputCurve.from_json(curve_data)
234240
curves.append(curve)
235241
except Exception as e:
236-
# Log the problematic curve but continue processing
237-
collection_warnings[f"OutputCurve(key={key})"] = f"Skipped invalid curve data: {e}"
242+
# Create a basic curve and continue processing
243+
key = curve_data.get("key", "unknown")
244+
basic_curve = OutputCurve.model_construct(key=key, type="unknown")
245+
basic_curve.add_warning(key, f"Skipped invalid curve data: {e}")
246+
curves.append(basic_curve)
238247

239248
collection = cls.model_validate({"curves": curves})
240249

241-
# Add any collection-level warnings
242-
for loc, msg in collection_warnings.items():
243-
collection.add_warning(loc, msg)
244-
245-
# Merge warnings from individual curves
246-
collection._merge_submodel_warnings(*curves, key_attr='key')
250+
# Merge warnings from individual curves using new system
251+
collection._merge_submodel_warnings(*curves, key_attr="key")
247252

248253
return collection
249254

@@ -255,7 +260,7 @@ def from_service_result(
255260
if not service_result.success or not service_result.data:
256261
empty_curves = cls(curves=[])
257262
for error in service_result.errors:
258-
empty_curves.add_warning('base', f"Service error: {error}")
263+
empty_curves.add_warning("base", f"Service error: {error}")
259264
return empty_curves
260265

261266
curves_list = []
@@ -281,17 +286,18 @@ def from_service_result(
281286
curves_list.append(curve)
282287

283288
except Exception as e:
284-
curves_list.append(
285-
OutputCurve.model_validate({"key": curve_name, "type": "unknown"})
289+
basic_curve = OutputCurve.model_construct(
290+
key=curve_name, type="unknown"
286291
)
287-
curves_list[-1].add_warning('base', f"Failed to process curve data: {e}")
292+
basic_curve.add_warning("base", f"Failed to process curve data: {e}")
293+
curves_list.append(basic_curve)
288294

289295
curves_collection = cls(curves=curves_list)
290296

291297
for error in service_result.errors:
292-
curves_collection.add_warning('base', f"Download warning: {error}")
298+
curves_collection.add_warning("base", f"Download warning: {error}")
293299

294-
curves_collection._merge_submodel_warnings(curves_list, key_attr='key')
300+
curves_collection._merge_submodel_warnings(*curves_list, key_attr="key")
295301

296302
return curves_collection
297303

0 commit comments

Comments
 (0)