Coverage for backend/django/idaes_factory/adapters/property_value_adapter.py: 80%

55 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-05-13 02:47 +0000

1import json 

2from core.auxiliary.enums.uiEnums import DisplayType 

3from common.config_types import * 

4 

5class _PropertyInfoNotSetException(Exception): 

6 def __init__(self, message: str = ""): 

7 if message == "": 

8 message = "PropertyInfo value not set" 

9 super().__init__(message) 

10 

11 

12# Property info operator 

13def check_fixed(ctx, property_info, property_value, is_tear: bool = False) -> bool: 

14 """ 

15 Check that the property is fixed 

16 Raise an error if not, or return False if variables are not required to be fixed 

17 """ 

18 if is_tear and not property_value.is_control_set_point() and not property_value.has_value(): 

19 # recycle guess, allowed to be empty 

20 return False 

21 # Property must be fixed, and have a value 

22 if not property_value.has_value(): 

23 if property_value.is_control_manipulated(): 

24 # this value is a guess variable, and allowed to be empty 

25 return False 

26 indexed_items = [x for x in property_value.indexedItems.all()] 

27 property_values = [x for x in property_info.values.all()] 

28 pv_ii = [[x for x in y.indexedItems.all()] for y in property_values] 

29 # error, property should be fixed and have a value 

30 if ctx.require_variables_fixed: 30 ↛ 31line 30 didn't jump to line 31 because the condition on line 30 was never true

31 raise _PropertyInfoNotSetException(f"Property `{property_info.displayName}` is not set") 

32 else: 

33 # RequireVariablesFixed is a context variable that can be set to False to allow for properties to be unset 

34 # Allow this to pass for testing purposes only. 

35 return False 

36 return True 

37 

38 

39def serialise_property_value(ctx, property_info, property_value, is_indexed: bool = True, is_tear: bool = False): 

40 """ 

41 Serialise a property info object 

42 """ 

43 

44 # TODO: add time step handling: get the value at the given time step 

45 match property_info.type: 

46 case DisplayType.dropdown: 46 ↛ 47line 46 didn't jump to line 47 because the pattern on line 46 never matched

47 raise NotImplementedError("Dropdown properties are not yet supported in idaes_factory") 

48 case DisplayType.checkbox: 48 ↛ 49line 48 didn't jump to line 49 because the pattern on line 48 never matched

49 return bool(json.loads(property_value.value)) # return True or False 

50 case DisplayType.numeric_arg: 50 ↛ 51line 50 didn't jump to line 51 because the pattern on line 50 never matched

51 raise NotImplementedError("Dropdown properties are not yet supported in idaes_factory") 

52 case DisplayType.segmented: 52 ↛ 53line 52 didn't jump to line 53 because the pattern on line 52 never matched

53 raise NotImplementedError("Segmented properties are not yet supported in idaes_factory") 

54 case DisplayType.numeric: 54 ↛ 100line 54 didn't jump to line 100 because the pattern on line 54 always matched

55 if is_tear: 

56 # tear properties are disabled, but we still need to serialise the recycle guesses 

57 if not ( 

58 property_info.is_recycle_var() 

59 or property_value.is_control_set_point() 

60 ): 

61 # skip, not enabled 

62 return None 

63 else: 

64 if not property_value.is_enabled() and not property_value.is_control_manipulated(): 

65 # property is disabled (and not a guess), so don't serialise it 

66 return None 

67 # check that the property is fixed, and raise an error if not 

68 if not check_fixed(ctx, property_info, property_value, is_tear): 

69 # variables are not required to be fixed, so don't serialise this property 

70 return None 

71 

72 value = property_value.value 

73 # We are no longer supporting parsing expressions here, becuase that functionality 

74 # is possible with specification and control blocks. 

75 if getattr(property_value, "dataColumn", None) is not None: 

76 from core.auxiliary.models.DataCell import DataCell 

77 

78 if ctx.solve_index is not None: # if index is given for a value from the csv 

79 value = DataCell.objects.get( 

80 data_column = property_value.dataColumn, 

81 data_row = ctx.solve_index, 

82 ).value 

83 elif ctx.is_dynamic() and is_indexed: # only use MSS for dynamics if the property is indexed, because otherwise it will be a single value. 83 ↛ 96line 83 didn't jump to line 96 because the condition on line 83 was always true

84 # We want to get all the data cells, and use as many data cells as there are timesteps 

85 # (We are using the CSV data as input data) 

86 # Note: assuming DataCell.objects.all() returns the values in the correct order 

87 value = [i.value for i in DataCell.objects.filter(data_column=property_value.dataColumn).all()] 

88 value = value[0:len(ctx.time_steps)] 

89 return value 

90 

91 elif ctx.is_dynamic() and is_indexed: 

92 return [float(value) for _ in ctx.time_steps] 

93 

94 # we used to use the dynamic results as the input but we aren't doing that any more 

95 # so just return the one value, idaes_service will assume it's constant. 

96 if is_indexed: 

97 return [float(value)] 

98 else: 

99 return float(value) 

100 case _: 

101 raise ValueError(f"Property type {property_info.type} is not supported in idaes_factory")