Coverage for backend/django/core/auxiliary/methods/copy_flowsheet/copy_formulas.py: 88%
22 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-06-23 21:51 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-06-23 21:51 +0000
1from typing import List
3from core.auxiliary.formula_limits import validate_formula_length
4from core.auxiliary.models.PropertyValue import PropertyValue
6from .copy_caching import ModelLookupDict
7from ..replace_expression_ids import (
8 extract_id_from_formula_key,
9 get_formula_keys,
10 replace_props,
11)
14def update_formulas(model_lookups: ModelLookupDict, allow_not_found: bool = False) -> None:
15 """
16 Each expression references the property values by their primary key.
17 This is called after the property values have been updated,
18 so that we can update their formulas to reference the new property values.
20 If `allow_not_found` is true, any formula reference that points to a
21 property value outside the copied subset is left unchanged. This is useful
22 for subset copies such as simulation-object duplication, where a formula may
23 intentionally still reference an original property value.
24 """
25 property_values = model_lookups.get(PropertyValue)
26 if property_values is None:
27 return
28 for property_value in property_values:
29 if property_value.formula:
30 formula_keys = get_formula_keys(property_value.formula)
31 # example formula key: prop_500
32 formula_ids = [extract_id_from_formula_key(key) for key in formula_keys]
33 # list of ids
35 if not allow_not_found: 35 ↛ 45line 35 didn't jump to line 45 because the condition on line 35 was always true
36 new_property_values: List[PropertyValue] = [
37 property_values.get_model(pk) for pk in formula_ids
38 ]
39 if None in new_property_values: 39 ↛ 42line 39 didn't jump to line 42 because the condition on line 39 was never true
41 # Gracefully handle the case where a formula key does not match any property value.
42 property_value.formula = "Failed to copy formula, could not find property in flowsheet."
43 continue
44 # otherwise, any none values will be replaced with the original formula key.
45 new_formula_ids = [
46 property_values.get_model(pk).pk # get the new id
47 if property_values.get_model(pk) is not None
48 else pk # retain the original id
49 for pk in formula_ids
50 ]
51 new_formula_props = [f"prop{pk}" for pk in new_formula_ids]
52 property_value.formula = validate_formula_length(
53 replace_props(property_value.formula, new_formula_props)
54 )
56 # We need to use the unsafe manager here, because the normal manager is blocked by access control
57 PropertyValue._unsafe_objects.bulk_update(property_values, ["formula"])