diff --git a/examples/fan_spec/schema/RS0003.schema.yaml b/examples/fan_spec/schema/RS0003.schema.yaml index 021fde4..4eb35f3 100644 --- a/examples/fan_spec/schema/RS0003.schema.yaml +++ b/examples/fan_spec/schema/RS0003.schema.yaml @@ -74,7 +74,7 @@ RS0003: metadata: Description: "Metadata data group" Data Type: "{Metadata}" - Constraints: "schema=RS0003" + Constraints: schema_name="RS0003" Required: True description: Description: "Data group describing product and rating information" @@ -156,17 +156,23 @@ Performance: Description: "Type of performance map" Data Type: "" Required: True - Notes: ["Determines which performance map data group is used for `performance_map`", - "If `operation_speed_control_type` is `DISCRETE` performance map data is provided at individual impeller speeds", - "If `operation_speed_control_type` is `CONTINUOUS` performance map data is provided over a range of impeller speeds"] + Notes: + [ + "Determines which performance map data group is used for `performance_map`", + "If `operation_speed_control_type` is `DISCRETE` performance map data is provided at individual impeller speeds", + "If `operation_speed_control_type` is `CONTINUOUS` performance map data is provided over a range of impeller speeds", + ] installation_speed_control_type: Description: "Type of fan impeller speed control" Data Type: "" Required: True - Notes: ["If `operation_speed_control_type` is `DISCRETE` and `installation_speed_control_type` is `FIXED`, impeller speed shall be restricted to a single discrete speed", - "If `operation_speed_control_type` is `DISCRETE` and `installation_speed_control_type` is `VARIABLE`, impeller speed shall be restricted to a set of two or more discrete speeds", - "If `operation_speed_control_type` is `CONTINUOUS` and `installation_speed_control_type` is `FIXED`, impeller speed shall be restricted to a single speed (which may be interpolated from `impeller_speed` values provided in the performance map)", - "If `operation_speed_control_type` is `CONTINUOUS` and `installation_speed_control_type` is `VARIABLE`, impeller speed shall be unrestricted within operational limits"] + Notes: + [ + "If `operation_speed_control_type` is `DISCRETE` and `installation_speed_control_type` is `FIXED`, impeller speed shall be restricted to a single discrete speed", + "If `operation_speed_control_type` is `DISCRETE` and `installation_speed_control_type` is `VARIABLE`, impeller speed shall be restricted to a set of two or more discrete speeds", + "If `operation_speed_control_type` is `CONTINUOUS` and `installation_speed_control_type` is `FIXED`, impeller speed shall be restricted to a single speed (which may be interpolated from `impeller_speed` values provided in the performance map)", + "If `operation_speed_control_type` is `CONTINUOUS` and `installation_speed_control_type` is `VARIABLE`, impeller speed shall be unrestricted within operational limits", + ] motor_representation: Description: "The corresponding Standard 205 motor representation" Notes: "If the fan assembly is packaged with a motor, a motor representation shall be provided" @@ -204,8 +210,11 @@ AssemblyComponent: Data Type: "Numeric" Constraints: ">=0.0" Units: "Pa" - Notes: ["Corresponds to additional pressure difference at `nominal_standard_air_volumetric_flow_rate`", - "If unknown, a value of 75 Pa shall be used"] + Notes: + [ + "Corresponds to additional pressure difference at `nominal_standard_air_volumetric_flow_rate`", + "If unknown, a value of 75 Pa shall be used", + ] Required: True Scalable: True @@ -216,8 +225,8 @@ SystemCurve: Description: "Volumetric air flow rate through an air distribution system at standard air conditions" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[2..]" + - ">=0.0" + - "[2..]" Units: "m3/s" Required: True Scalable: True @@ -225,8 +234,8 @@ SystemCurve: Description: "Static pressure difference of an air distribution system" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[2..]" + - ">=0.0" + - "[2..]" Units: "Pa" Required: True Scalable: True @@ -252,8 +261,8 @@ GridVariablesContinuous: Description: "Volumetric air flow rate through fan assembly at standard air conditions" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "m3/s" Required: True Scalable: True @@ -261,8 +270,8 @@ GridVariablesContinuous: Description: "External static pressure across fan assembly at dry coil conditions" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "Pa" Notes: "Any static pressure deduction (or addition) for wet coil is specified by `wet_pressure_difference` in 'assembly_components' data group" Required: True @@ -275,16 +284,16 @@ LookupVariablesContinuous: Description: "Rotational speed of fan impeller" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "rev/s" Required: True shaft_power: Description: "Mechanical shaft power input to fan assembly" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "W" Notes: "Does not include the mechanical efficiency of any mechanical drive used to modify rotational speed between the motor and impeller" Required: True @@ -316,8 +325,8 @@ GridVariablesDiscrete: Description: "Number indicating discrete speed of fan impeller in rank order (with 1 being the lowest speed)" Data Type: "[Integer]" Constraints: - - ">=0" - - "[1..]" + - ">=0" + - "[1..]" Units: "-" Notes: "Data shall be provided for all allowable discrete speeds or settings" Required: True @@ -325,8 +334,8 @@ GridVariablesDiscrete: Description: "External static pressure across fan assembly at dry coil conditions" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "Pa" Notes: "Any static pressure deduction (or addition) for wet coil is specified by `wet_pressure_difference` in 'assembly_components' data group" Required: True @@ -339,8 +348,8 @@ LookupVariablesDiscrete: Description: "Volumetric air flow rate through fan assembly at standard air conditions" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "m3/s" Required: True Scalable: True @@ -348,8 +357,8 @@ LookupVariablesDiscrete: Description: "Mechanical shaft power input to fan assembly" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "W" Notes: "Does not include the mechanical efficiency of any mechanical drive used to modify rotational speed between the motor and impeller" Required: True @@ -358,8 +367,8 @@ LookupVariablesDiscrete: Description: "Rotational speed of fan impeller" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "rev/s" Required: True operation_state: diff --git a/examples/fan_spec/schema/RS0005.schema.yaml b/examples/fan_spec/schema/RS0005.schema.yaml index dd5ed6f..d74f0e0 100644 --- a/examples/fan_spec/schema/RS0005.schema.yaml +++ b/examples/fan_spec/schema/RS0005.schema.yaml @@ -16,7 +16,7 @@ RS0005: metadata: Description: "Metadata data group" Data Type: "{Metadata}" - Constraints: "schema=RS0005" + Constraints: schema_name="RS0005" Required: True description: Description: "Data group describing product and rating information" @@ -87,8 +87,11 @@ Performance: performance_map: Description: "Data group describing motor performance when operating" Data Type: "{PerformanceMap}" - Notes: ["If no performance map is defined, the motor shall be assumed to transfer all electric power directly to mechanical shaft power", - "***Informative note:*** This field may be omitted for motor-driven equipment where motor efficiencies are incorporated into their performance data"] + Notes: + [ + "If no performance map is defined, the motor shall be assumed to transfer all electric power directly to mechanical shaft power", + "***Informative note:*** This field may be omitted for motor-driven equipment where motor efficiencies are incorporated into their performance data", + ] PerformanceMap: Object Type: "Data Group" @@ -111,8 +114,8 @@ GridVariables: Description: "Delivered rotational shaft power" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "W" Required: True Scalable: True @@ -120,8 +123,8 @@ GridVariables: Description: "Rotational speed of shaft" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "rev/s" Required: True @@ -133,9 +136,9 @@ LookupVariables: Description: "Efficiency of motor" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "<=1.0" - - "[1..]" + - ">=0.0" + - "<=1.0" + - "[1..]" Units: "-" Notes: "Defined as the ratio of mechanical shaft power to electrical input power of the motor" Required: True @@ -143,9 +146,9 @@ LookupVariables: Description: "Power factor of the motor" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "<=1.0" - - "[1..]" + - ">=0.0" + - "<=1.0" + - "[1..]" Units: "-" Required: True operation_state: diff --git a/examples/fan_spec/schema/RS0006.schema.yaml b/examples/fan_spec/schema/RS0006.schema.yaml index b158942..8db37c7 100644 --- a/examples/fan_spec/schema/RS0006.schema.yaml +++ b/examples/fan_spec/schema/RS0006.schema.yaml @@ -18,13 +18,19 @@ CoolingMethod: ACTIVE_AIR_COOLED: Description: "Drive is cooled using forced air convection within the surrounding environment" Display Text: "Active Air Cooled" - Notes: ["Electrical power required for the active cooling system shall be included in the efficiency of the drive", - "All drive efficiency losses are assumed to be added as heat to the surrounding environment"] + Notes: + [ + "Electrical power required for the active cooling system shall be included in the efficiency of the drive", + "All drive efficiency losses are assumed to be added as heat to the surrounding environment", + ] ACTIVE_LIQUID_COOLED: Description: "Drive is cooled using forced liquid convection, transferring heat to the liquid" Display Text: "Active Liquid Cooled" - Notes: ["Any liquid pumping power shall be modeled external to the drive by the application software", - "All drive efficiency losses are assumed to be added as heat to the liquid stream"] + Notes: + [ + "Any liquid pumping power shall be modeled external to the drive by the application software", + "All drive efficiency losses are assumed to be added as heat to the liquid stream", + ] # Data Groups RS0006: @@ -34,7 +40,7 @@ RS0006: metadata: Description: "Metadata data group" Data Type: "{Metadata}" - Constraints: "schema=RS0006" + Constraints: schema_name="RS0006" Required: True description: Description: "Data group describing product and rating information" @@ -54,13 +60,13 @@ Description: ProductInformation: Object Type: "Data Group" Data Elements: - manufacturer: - Description: "Manufacturer name" - Data Type: "String" - model_number: - Description: "Model number" - Data Type: "Pattern" - Notes: "Pattern shall match all model numbers that can be represented by the representation" + manufacturer: + Description: "Manufacturer name" + Data Type: "String" + model_number: + Description: "Model number" + Data Type: "Pattern" + Notes: "Pattern shall match all model numbers that can be represented by the representation" Performance: Object Type: "Data Group" @@ -113,8 +119,8 @@ GridVariables: Description: "Power delivered to the motor" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "W" Required: True Scalable: True @@ -122,8 +128,8 @@ GridVariables: Description: "Frequency delivered to the motor" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "Hz" Required: True @@ -135,12 +141,15 @@ LookupVariables: Description: "Efficiency of drive" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "<=1.0" - - "[1..]" + - ">=0.0" + - "<=1.0" + - "[1..]" Units: "-" - Notes: ["Defined as the ratio of electrical output power (to the motor) to electrical input power (to the drive)", - "Input power shall include any power required to provide active air cooling for the drive"] + Notes: + [ + "Defined as the ratio of electrical output power (to the motor) to electrical input power (to the drive)", + "Input power shall include any power required to provide active air cooling for the drive", + ] Required: True operation_state: Description: "The operation state at the operating conditions" diff --git a/examples/fan_spec/schema/RS0007.schema.yaml b/examples/fan_spec/schema/RS0007.schema.yaml index 0c8a165..dd6b712 100644 --- a/examples/fan_spec/schema/RS0007.schema.yaml +++ b/examples/fan_spec/schema/RS0007.schema.yaml @@ -35,7 +35,7 @@ RS0007: metadata: Description: "Metadata data group" Data Type: "{Metadata}" - Constraints: "schema=RS0007" + Constraints: schema_name="RS0007" Required: True description: Description: "Data group describing product and rating information" @@ -55,16 +55,16 @@ Description: ProductInformation: Object Type: "Data Group" Data Elements: - manufacturer: - Description: "Manufacturer name" - Data Type: "String" - model_number: - Description: "Model number" - Data Type: "Pattern" - Notes: "Pattern shall match all model numbers that can be represented by the representation" - drive_type: - Description: "Type of mechanical drive" - Data Type: "" + manufacturer: + Description: "Manufacturer name" + Data Type: "String" + model_number: + Description: "Model number" + Data Type: "Pattern" + Notes: "Pattern shall match all model numbers that can be represented by the representation" + drive_type: + Description: "Type of mechanical drive" + Data Type: "" Performance: Object Type: "Data Group" @@ -105,8 +105,8 @@ GridVariables: Description: "Output shaft power" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "[1..]" + - ">=0.0" + - "[1..]" Units: "W" Required: True Scalable: True @@ -119,9 +119,9 @@ LookupVariables: Description: "Efficiency of drive" Data Type: "[Numeric]" Constraints: - - ">=0.0" - - "<=1.0" - - "[1..]" + - ">=0.0" + - "<=1.0" + - "[1..]" Units: "-" Notes: "Defined as the ratio of output shaft power to input shaft power" Required: True diff --git a/lattice/schema.py b/lattice/schema.py index bfdd8ff..91b0179 100644 --- a/lattice/schema.py +++ b/lattice/schema.py @@ -130,6 +130,9 @@ def __init__(self, text: str, parent_data_element: DataElement): self.text = text self.parent_data_element = parent_data_element + def resolve(self): + pass + class RangeConstraint(Constraint): pattern = RegularExpressionPattern(f"(>|>=|<=|<)({NumericType.value_pattern})") @@ -168,8 +171,29 @@ def __init__(self, text: str, parent_data_element: DataElement): self.pattern = parent_data_element.parent_data_group.parent_schema.schema_patterns.data_element_value_constraint match = self.pattern.match(self.text) assert match is not None + # parent data element must be a data group + if not isinstance(self.parent_data_element.data_type, DataGroupType): + raise Exception( + f"Data Element Value Constraint must be a Data Group Type, not {type(self.parent_data_element)}" + ) + self.data_element_name = match.group(1) # TODO: Named groups? - self.data_element_value = match.group(5) # TODO: Named groups? + self.data_element_value = match.group(5) + self.data_element: DataElement + + def resolve(self): + assert isinstance(self.parent_data_element.data_type, DataGroupType) + if self.data_element_name not in self.parent_data_element.data_type.data_group.data_elements: + raise Exception( + f"Data Element Value Constraint '{self.data_element_name}' not found in Data Group '{self.parent_data_element.data_type.data_group_name}'" + ) + + self.data_element = self.parent_data_element.data_type.data_group.data_elements[self.data_element_name] + match = self.data_element.data_type.value_pattern.match(self.data_element_value) + if match is None: + raise Exception( + f"Data Element Value Constraint '{self.data_element_value}' does not match the value pattern of '{self.data_element.name}'" + ) class ArrayLengthLimitsConstraint(Constraint): @@ -245,7 +269,10 @@ def __init__(self, name: str, data_element_dictionary: dict, parent_data_group: f"Data Element={self.name}" ) - def get_data_type(self, parent_data_group: DataGroup, attribute_str: str): + def get_data_type(self, parent_data_group: DataGroup, attribute_str: str) -> DataType: + """ + Returns the data type from the attribute string. + """ try: return self.parent_data_group.parent_schema.data_type_factory(attribute_str, self) except RuntimeError: @@ -264,6 +291,8 @@ def set_constraints(self, constraints_input: Union[str, List[str]]) -> None: def resolve(self): self.data_type.resolve() + for constraint in self.constraints: + constraint.resolve() class FundamentalDataType: @@ -302,7 +331,7 @@ def __init__(self, name: str, data_group_dictionary: dict, parent_schema: Schema self.name = name self.dictionary = data_group_dictionary self.parent_schema = parent_schema - self.data_elements = {} + self.data_elements: dict[str, DataElement] = {} self.id_data_element: Union[DataElement, None] = None # data element containing unique id for this data group for data_element in self.dictionary["Data Elements"]: self.data_elements[data_element] = DataElement(