|
11 | 11 | log = getLogger(__name__) |
12 | 12 |
|
13 | 13 |
|
| 14 | +INHERITED_FIELDS = [ |
| 15 | + "database", |
| 16 | + "location", |
| 17 | + "name", |
| 18 | +] |
| 19 | + |
| 20 | + |
14 | 21 | class MFActivity(Activity): |
15 | 22 | """ |
16 | 23 | A class representing an activity of the functional_sqlite backend. |
@@ -192,9 +199,19 @@ def save(self, signal: bool = True, data_already_set: bool = False, force_insert |
192 | 199 |
|
193 | 200 | super().save(signal, data_already_set, force_insert) |
194 | 201 |
|
195 | | - if not created and old.data.get("allocation") != self.get("allocation"): |
| 202 | + if created: |
| 203 | + return |
| 204 | + |
| 205 | + if old.data.get("allocation") != self.get("allocation"): |
196 | 206 | self.allocate() |
197 | 207 |
|
| 208 | + if changed_fields := [field for field in INHERITED_FIELDS if self.get(field) != old.data.get(field)]: |
| 209 | + log.info(f"Updating inherited fields {changed_fields} for products of process {self}") |
| 210 | + for product in self.products(): |
| 211 | + for field in changed_fields: |
| 212 | + product._set_inherited(field, self.get(field)) |
| 213 | + product.save() |
| 214 | + |
198 | 215 | def copy(self, *args, **kwargs): |
199 | 216 | """ |
200 | 217 | Create a copy of the process. |
@@ -245,9 +262,16 @@ def new_product(self, type="product", **kwargs): |
245 | 262 | Returns: |
246 | 263 | Product: A new product. |
247 | 264 | """ |
| 265 | + if kwargs.get("reference product") is None: |
| 266 | + |
| 267 | + kwargs["reference product"] = kwargs.get("product", kwargs.get("name", f"Unnamed {type}")) |
| 268 | + |
248 | 269 | kwargs["type"] = type |
249 | 270 | kwargs["processor"] = self.key |
250 | | - kwargs["database"] = self["database"] |
| 271 | + |
| 272 | + for field in INHERITED_FIELDS: |
| 273 | + kwargs[field] = self.get(field) |
| 274 | + |
251 | 275 | kwargs["properties"] = {p: self.property_template(p) for p in self.available_properties()} |
252 | 276 | return Product(**kwargs) |
253 | 277 |
|
@@ -288,7 +312,7 @@ def property_template(self, name: str, amount=1.0) -> dict: |
288 | 312 | "normalize": normalize.pop() if normalize else True |
289 | 313 | } |
290 | 314 |
|
291 | | - def products(self): |
| 315 | + def products(self) -> list["Product"]: |
292 | 316 | """ |
293 | 317 | Retrieve the products (products or wastes) associated with the process. |
294 | 318 |
|
@@ -367,6 +391,18 @@ class Product(MFActivity): |
367 | 391 | products, including saving, deleting, and validating them, as well as handling |
368 | 392 | processing edges and substitution. |
369 | 393 | """ |
| 394 | + def __setitem__(self, key, value): |
| 395 | + if key in INHERITED_FIELDS: |
| 396 | + raise KeyError(f"Field '{key}' is inherited from the processor and cannot be set directly.") |
| 397 | + if key in ["product", "reference product"]: |
| 398 | + # explicit synonyms |
| 399 | + super().__setitem__("product", value) |
| 400 | + super().__setitem__("reference product", value) |
| 401 | + return |
| 402 | + super().__setitem__(key, value) |
| 403 | + |
| 404 | + def _set_inherited(self, key, value): |
| 405 | + super().__setitem__(key, value) |
370 | 406 |
|
371 | 407 | def save(self, signal: bool = True, data_already_set: bool = False, force_insert: bool = False): |
372 | 408 | """ |
|
0 commit comments