Coverage for backend/django/core/auxiliary/models/PropertySet.py: 93%

63 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-06-23 21:51 +0000

1from typing import TYPE_CHECKING, Tuple 

2from django.db import models 

3 

4from flowsheetInternals.unitops.config import PropertySetType 

5from core.auxiliary.enums.uiEnums import CompoundMode 

6 

7from .PropertyInfo import PropertyInfo 

8from .PropertyValue import PropertyValue 

9from .ControlValue import ControlValue 

10from flowsheetInternals.unitops.config import * 

11from core.managers import AccessControlManager 

12if TYPE_CHECKING: 

13 from flowsheetInternals.unitops.models.SimulationObject import SimulationObject 

14class PropertySet(models.Model): 

15 """ 

16 Base class for property sets 

17 This class implements no special methods for updating properties 

18 """ 

19 flowsheet = models.ForeignKey("Flowsheet", on_delete=models.CASCADE, related_name="propertySets") 

20 compoundMode = models.CharField(choices=CompoundMode.choices, default="") 

21 simulationObject: models.OneToOneField["SimulationObject"] = models.OneToOneField("flowsheetInternals_unitops.SimulationObject", on_delete=models.CASCADE, related_name="properties", null=True) 

22 

23 

24 created_at = models.DateTimeField(auto_now_add=True) 

25 

26 objects = AccessControlManager() 

27 

28 class Meta: 

29 ordering = ['created_at'] 

30 

31 @property 

32 def containedProperties(self) -> models.QuerySet[PropertyInfo]: 

33 return self.ContainedProperties.all() 

34 

35 @property 

36 def schema(self) -> PropertySetType: 

37 return get_object_schema(self.simulationObject).properties 

38 

39 @property 

40 def disable_all(self) -> bool: 

41 simulationObject = self.simulationObject 

42 if not simulationObject.is_stream(): 

43 return False 

44 if simulationObject.has_recycle_connection: 

45 return False # don't disable properties if connected to a recycle block 

46 ports = simulationObject.connectedPorts 

47 if ports.count() == 0: 47 ↛ 48line 47 didn't jump to line 48 because the condition on line 47 was never true

48 return False # floating stream 

49 elif ports.count() == 1: 

50 if ports.get().direction == "inlet": 

51 return False # inlet stream 

52 return True 

53 

54 @property 

55 def has_simulation_object(self) -> bool: 

56 # eg. pinch analysis property set has no simulation object 

57 return bool(self.simulationObject) 

58 

59 

60 def get_property(self, key: str, index: int = 0) -> PropertyInfo: 

61 """ 

62 Utility method for getting a property within this set by key. 

63 """ 

64 try: 

65 prop: PropertyInfo = self.ContainedProperties.get(key=key, index=index) 

66 return prop 

67 except PropertyInfo.DoesNotExist: 

68 raise ValueError(f"Property with key `{key}` not found in PropertySet, options: {[prop.key for prop in self.containedProperties]}") 

69 

70 

71 def update_property(self, key: str, value: float | None = None, unit: str | None = None, index: int = 0) -> None: 

72 """ 

73 Utility method for updating the value and/or unit of a property, referenced by the key. 

74 """ 

75 prop = self.get_property(key, index) 

76 if value is not None: 

77 prop.set_value(value) 

78 if unit is not None: 

79 prop.unit = unit 

80 prop.save() 

81 

82 

83 def add_control(self, prop1: str | PropertyInfo, prop2: str | PropertyInfo) -> ControlValue: 

84 """ 

85 Add a control relationship between two properties. 

86 """ 

87 if isinstance(prop1, str): 87 ↛ 89line 87 didn't jump to line 89 because the condition on line 87 was always true

88 prop1 = self.get_property(prop1) 

89 if isinstance(prop2, str): 

90 prop2 = self.get_property(prop2) 

91 return prop1.add_control(prop2) 

92 

93 def get_unspecified_properties(self) -> list[str]: 

94 # For some reason, Pinch analysis is using property sets. They don't have simulation objects attached, 

95 # so getting unspecified properties is not possible. 

96 # Thus we have to return an empty list. 

97 if not self.simulationObject: 

98 return [] 

99 return self.simulationObject.get_unspecified_properties()