Esempio n. 1
0
 def from_data(cls, floor: element.Element) -> 'Floor':
     try:
         return Floor(
             label=floor.get_text('Label'),
             nominal_insulation=insulation.Insulation(floor.get('Construction/Type/@nominalInsulation', float)),
             effective_insulation=insulation.Insulation(floor.get('Construction/Type/@rValue', float)),
             floor_area=area.Area(floor.get('Measurements/@area', float)),
             floor_length=distance.Distance(floor.get('Measurements/@length', float)),
         )
     except (ElementGetValueError) as exc:
         raise InvalidEmbeddedDataTypeError(Floor) from exc
Esempio n. 2
0
    def from_data(cls, header: element.Element) -> 'BasementHeader':
        try:
            nominal_insulation = header.get('Construction/Type/@nominalInsulation', float)
            effective_insulation = header.get('Construction/Type/@rValue', float)
            height = header.get('Measurements/@height', float)
            width = header.get('Measurements/@perimeter', float)
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(BasementHeader, 'Invalid/Missing attribute value') from exc

        return BasementHeader(
            nominal_insulation=insulation.Insulation(nominal_insulation),
            effective_insulation=insulation.Insulation(effective_insulation),
            height=distance.Distance(height),
            perimeter=distance.Distance(width),
        )
Esempio n. 3
0
    def from_data(cls, node: element.Element) -> 'Heating':
        try:
            label = node.get_text('Label')
            efficiency = node.get('Type1/*/Specifications/@efficiency', float)
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(
                Heating, 'Invalid/missing Heating values') from exc

        heating_type = cls._get_heating_type(node)
        output_size = cls._get_output_size(node)

        if heating_type is HeatingType.BASEBOARD:
            steady_state = 'Steady State'
            energy_source = EnergySource.ELECTRIC
            equipment_type = cls._HEATING_TYPE_TRANSLATIONS[
                HeatingType.BASEBOARD]
        else:
            steady_state = cls._get_steady_state(node)
            energy_source = cls._get_energy_source(node)
            equipment_type = cls._get_equipment_type(node)

        return Heating(
            label=label,
            output_size=output_size,
            efficiency=efficiency,
            steady_state=steady_state,
            heating_type=heating_type,
            energy_source=energy_source,
            equipment_type=equipment_type,
        )
Esempio n. 4
0
def _get_nullable_fields(root: element.Element, path: str) -> typing.Optional[str]:
    data: typing.Optional[str]
    try:
        data = root.get(path, str)
    except ElementGetValueError:
        data = None
    return data
Esempio n. 5
0
    def from_data(cls, wall_code: element.Element) -> 'WallCode':
        structure_type_english = wall_code.findtext(
            'Layers/StructureType/English')
        structure_type_french = wall_code.findtext(
            'Layers/StructureType/French')

        component_type_size_english = wall_code.findtext(
            'Layers/ComponentTypeSize/English')
        component_type_size_french = wall_code.findtext(
            'Layers/ComponentTypeSize/French')

        try:
            return WallCode(identifier=wall_code.get('@id', str),
                            label=wall_code.get_text('Label'),
                            tags={
                                WallCodeTag.STRUCTURE_TYPE:
                                bilingual.Bilingual(
                                    english=structure_type_english,
                                    french=structure_type_french,
                                ) if structure_type_english
                                and structure_type_french else None,
                                WallCodeTag.COMPONENT_TYPE_SIZE:
                                bilingual.Bilingual(
                                    english=component_type_size_english,
                                    french=component_type_size_french,
                                ) if component_type_size_english
                                and component_type_size_french else None,
                            })
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(
                WallCode, 'Unable to get identifier attributes') from exc
Esempio n. 6
0
 def from_data(cls, door: element.Element) -> 'Door':
     try:
         return Door(
             label=door.get_text('Label'),
             door_type=bilingual.Bilingual(
                 english=door.get_text('Construction/Type/English'),
                 french=door.get_text('Construction/Type/French'),
             ),
             door_insulation=insulation.Insulation(
                 door.get('Construction/Type/@value', float)),
             height=distance.Distance(
                 door.get('Measurements/@height', float)),
             width=distance.Distance(door.get('Measurements/@width',
                                              float)),
         )
     except (ElementGetValueError) as exc:
         raise InvalidEmbeddedDataTypeError(Door) from exc
Esempio n. 7
0
    def from_basement(cls, wall: element.Element, wall_perimeter: float) -> typing.List['BasementWall']:
        interior_wall_sections = wall.xpath('Construction/InteriorAddedInsulation/Composite/Section')
        exterior_wall_sections = wall.xpath('Construction/ExteriorAddedInsulation/Composite/Section')
        pony_wall_sections = wall.xpath('Construction/PonyWallType/Composite/Section')

        try:
            wall_height = wall.get('Measurements/@height', float)
            pony_height = wall.get('Measurements/@ponyWallHeight', float)
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(BasementWall, 'Missing/invalid basement wall height') from exc

        walls = []
        sections = (interior_wall_sections, exterior_wall_sections, pony_wall_sections)

        parsers = (
            lambda section, percentage: BasementWall._from_data(
                section,
                wall_perimeter,
                wall_height,
                WallType.INTERIOR,
                percentage
            ),
            lambda section, percentage: BasementWall._from_data(
                section,
                wall_perimeter,
                wall_height,
                WallType.EXTERIOR,
                percentage
            ),
            lambda section, percentage: BasementWall._from_data(
                section,
                wall_perimeter,
                pony_height,
                WallType.PONY,
                percentage
            )
        )

        for parser, wall_sections in zip(parsers, sections):
            percentages = [wall.attrib.get('percentage') for wall in wall_sections]
            accounted_for = sum(float(percentage) for percentage in percentages if percentage is not None)

            walls.extend([parser(wall, 100-accounted_for) for wall in wall_sections])

        return walls
Esempio n. 8
0
    def _get_steady_state(node: element.Element) -> str:
        try:
            steady_state_value = node.get(
                'Type1/*/Specifications/@isSteadyState', str)
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(
                Heating, 'No isSteadyState property value') from exc

        return 'Steady State' if steady_state_value == 'true' else 'AFUE'
Esempio n. 9
0
    def _from_data(cls,
                   floor: element.Element,
                   construction_type: str,
                   floor_type: FloorType) -> 'BasementFloor':

        length: typing.Optional[float] = None
        width: typing.Optional[float] = None

        try:
            rectangular = floor.get('Measurements/@isRectangular', str) == 'true'
            if rectangular:
                length = floor.get('Measurements/@length', float)
                width = floor.get('Measurements/@width', float)
                perimeter = (2 * length) + (2 * width)
                floor_area = length * width
            else:
                floor_area = floor.get('Measurements/@area', float)
                perimeter = floor.get('Measurements/@perimeter', float)

            nominal_insulation_node = floor.xpath(f'Construction/{construction_type}/@nominalInsulation')
            effective_insulation_node = floor.xpath(f'Construction/{construction_type}/@rValue')

            nominal_insulation = float(nominal_insulation_node[0]) if nominal_insulation_node else None

            effective_insulation = float(effective_insulation_node[0]) if effective_insulation_node else None
        except ValueError as exc:
            raise InvalidEmbeddedDataTypeError(BasementFloor, 'Invalid insulation attribute values') from exc
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(BasementFloor, 'Invalid attributes') from exc

        return BasementFloor(
            floor_type=floor_type,
            rectangular=rectangular,
            nominal_insulation=insulation.Insulation(nominal_insulation)
            if nominal_insulation is not None else None,

            effective_insulation=insulation.Insulation(effective_insulation)
            if effective_insulation is not None else None,

            length=distance.Distance(length) if length is not None else None,
            width=distance.Distance(width) if width is not None else None,
            perimeter=distance.Distance(perimeter),
            floor_area=area.Area(floor_area),
        )
Esempio n. 10
0
 def from_data(cls, ceiling: element.Element) -> 'Ceiling':
     try:
         return Ceiling(
             label=ceiling.get_text('Label'),
             ceiling_type=bilingual.Bilingual(
                 english=ceiling.get_text('Construction/Type/English'),
                 french=ceiling.get_text('Construction/Type/French'),
             ),
             nominal_insulation=insulation.Insulation(
                 ceiling.get('Construction/CeilingType/@nominalInsulation',
                             float)),
             effective_insulation=insulation.Insulation(
                 ceiling.get('Construction/CeilingType/@rValue', float)),
             ceiling_area=area.Area(ceiling.get('Measurements/@area',
                                                float)),
             ceiling_length=distance.Distance(
                 ceiling.get('Measurements/@length', float)),
         )
     except (ElementGetValueError) as exc:
         raise InvalidEmbeddedDataTypeError(Ceiling) from exc
Esempio n. 11
0
    def from_data(cls, window: element.Element,
                  window_codes: typing.Dict[str, code.WindowCode]) -> 'Window':

        code_id = window.xpath('Construction/Type/@idref')
        window_code = window_codes[code_id[0]] if code_id else None

        try:
            return Window(
                label=window.get_text('Label'),
                window_code=window_code,
                window_insulation=insulation.Insulation(
                    window.get('Construction/Type/@rValue', float)),
                width=distance.Distance(
                    window.get('Measurements/@width', float) /
                    _MILLIMETRES_TO_METRES),
                height=distance.Distance(
                    window.get('Measurements/@height', float) /
                    _MILLIMETRES_TO_METRES),
            )
        except (ElementGetValueError) as exc:
            raise InvalidEmbeddedDataTypeError(Window) from exc
Esempio n. 12
0
    def from_data(cls, wall: element.Element,
                  wall_codes: typing.Dict[str, code.WallCode]) -> 'Wall':

        code_id = wall.xpath('Construction/Type/@idref')
        wall_code = wall_codes[code_id[0]] if code_id else None

        try:
            return Wall(
                label=wall.get_text('Label'),
                wall_code=wall_code,
                nominal_insulation=insulation.Insulation(
                    wall.get('Construction/Type/@nominalInsulation', float)),
                effective_insulation=insulation.Insulation(
                    wall.get('Construction/Type/@rValue', float)),
                perimeter=distance.Distance(
                    wall.get('Measurements/@perimeter', float)),
                height=distance.Distance(
                    wall.get('Measurements/@height', float)),
            )
        except (ElementGetValueError) as exc:
            raise InvalidEmbeddedDataTypeError(Wall) from exc
Esempio n. 13
0
    def _get_energy_source(cls, node: element.Element) -> EnergySource:
        try:
            code = node.get('Type1/*/Equipment/EnergySource/@code', int)
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(
                Heating, 'No EnergySource heating code') from exc

        energy_source = cls._ENERGY_SOURCE_CODES.get(code)
        if energy_source is None:
            raise InvalidEmbeddedDataTypeError(
                Heating, f'Unknown energy source: {energy_source}')
        return energy_source
Esempio n. 14
0
    def _from_data(cls, water_heating: element.Element) -> 'WaterHeating':
        drain_water_efficiency: typing.Optional[float] = None
        if water_heating.get('@hasDrainWaterHeatRecovery', str) == 'true':
            drain_water_efficiency = water_heating.get(
                'DrainWaterHeatRecovery/@effectivenessAt9.5', float)

        try:
            energy_type = water_heating.get_text('EnergySource/English')
            tank_type = water_heating.get_text('TankType/English')

            water_heater_type = cls._TYPE_MAP[(energy_type.lower(),
                                               tank_type.lower())]
            volume = water_heating.get('TankVolume/@value', float)
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(
                WaterHeating, 'Missing/invalid attribue or text') from exc
        except KeyError as exc:
            raise InvalidEmbeddedDataTypeError(
                WaterHeating,
                'Invlaid energy and tank type combination') from exc

        efficiency_ef_node = water_heating.xpath('EnergyFactor/@value')
        efficiency_percent_node = water_heating.xpath(
            'EnergyFactor/@thermalEfficiency')

        if not efficiency_ef_node and not efficiency_percent_node:
            raise InvalidEmbeddedDataTypeError(WaterHeating,
                                               'No efficiency values')

        return WaterHeating(
            water_heater_type=water_heater_type,
            tank_volume=volume,
            efficiency_ef=float(efficiency_ef_node[0])
            if efficiency_ef_node else None,
            efficiency_percentage=float(efficiency_percent_node[0])
            if efficiency_percent_node else None,
            drain_water_heat_recovery_efficiency_percentage=
            drain_water_efficiency,
        )
Esempio n. 15
0
    def _from_data(cls,
                   wall: element.Element,
                   wall_perimeter: float,
                   wall_height: float,
                   tag: WallType,
                   backup_percentage: float) -> 'BasementWall':

        maybe_percentage = wall.attrib.get('percentage')
        percentage = float(maybe_percentage) if maybe_percentage else backup_percentage

        try:
            nominal_insulation = wall.get('@nominalRsi', float)
            effective_insulation = wall.get('@rsi', float)
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(BasementWall, 'Invalid insulation attributes') from exc

        return BasementWall(
            wall_type=tag,
            nominal_insulation=insulation.Insulation(nominal_insulation),
            effective_insulation=insulation.Insulation(effective_insulation),
            composite_percentage=percentage,
            wall_area=area.Area(wall_perimeter * wall_height * (percentage / 100))
        )
Esempio n. 16
0
    def from_data(cls, basement: element.Element) -> 'Basement':
        foundation_type = cls._derive_foundation_type(basement.tag)
        if foundation_type is FoundationType.UNKNOWN:
            raise InvalidEmbeddedDataTypeError(Basement, f'Invalid foundation type: {basement.tag}')

        if foundation_type is FoundationType.BASEMENT:
            floor_from_data = BasementFloor.from_basement
            wall_from_data = BasementWall.from_basement
            header_from_data = BasementHeader.from_data
        elif foundation_type is FoundationType.CRAWLSPACE:
            floor_from_data = BasementFloor.from_crawlspace
            wall_from_data = BasementWall.from_crawlspace
            header_from_data = BasementHeader.from_data
        else:
            floor_from_data = BasementFloor.from_slab
            wall_from_data = lambda *args: []
            header_from_data = lambda *args: None

        floor_nodes = basement.xpath('Floor')
        header_nodes = basement.xpath('Components/FloorHeader')
        wall_nodes = basement.xpath('Wall')

        floors = floor_from_data(floor_nodes[0] if floor_nodes else None)
        walls = wall_from_data(wall_nodes[0], floors[0].perimeter.metres) if wall_nodes else []
        header = header_from_data(header_nodes[0]) if header_nodes else None

        try:
            configuration_type = basement.get('Configuration/@type', str)
            label = basement.get_text('Label')
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(Basement, 'Missing/invalid foundation attributes') from exc

        if not configuration_type:
            raise InvalidEmbeddedDataTypeError(Basement, 'Empty configuration type')

        return Basement(
            foundation_type=foundation_type,
            label=label,
            configuration_type=configuration_type,
            walls=walls,
            floors=floors,
            header=header,
        )
Esempio n. 17
0
    def from_crawlspace(cls, wall: element.Element, wall_perimeter: float) -> typing.List['BasementWall']:
        wall_sections = wall.xpath('Construction/Type/Composite/Section')

        try:
            wall_height = wall.get('Measurements/@height', float)
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(BasementWall, 'Missing/invalid wall height') from exc

        percentages = [wall.attrib.get('percentage') for wall in wall_sections]
        accounted_for = sum(float(percentage) for percentage in percentages if percentage is not None)

        return [
            BasementWall._from_data(
                wall_section,
                wall_perimeter,
                wall_height,
                WallType.NOT_APPLICABLE,
                100-accounted_for
            )
            for wall_section in wall_sections
        ]
Esempio n. 18
0
def test_get_int(fragment_node: element.Element) -> None:
    result = fragment_node.get('Bar/@id', int)
    assert result == 1
    assert isinstance(result, int)
Esempio n. 19
0
def test_get_float(fragment_node: element.Element) -> None:
    result = fragment_node.get('Bar/@id', float)
    assert result == 1.0
    assert isinstance(result, float)
Esempio n. 20
0
def test_get_str(fragment_node: element.Element) -> None:
    result = fragment_node.get('Bar/@id', str)
    assert result == '1'
    assert isinstance(result, str)
Esempio n. 21
0
def test_get_raises_when_not_found(fragment_node: element.Element) -> None:
    with pytest.raises(ElementGetValueError):
        fragment_node.get('Bar/@foo', int)
Esempio n. 22
0
def test_get_raises_when_cant_cast(fragment_node: element.Element) -> None:
    with pytest.raises(ElementGetValueError):
        fragment_node.get('Bar/text()', int)
Esempio n. 23
0
    def from_data(cls, window_code: element.Element) -> 'WindowCode':

        glazing_type_english = window_code.findtext(
            'Layers/GlazingTypes/English')
        glazing_type_french = window_code.findtext(
            'Layers/GlazingTypes/French')

        coating_tint_english = window_code.findtext(
            'Layers/CoatingsTints/English')
        coating_tint_french = window_code.findtext(
            'Layers/CoatingsTints/French')

        fill_type_english = window_code.findtext('Layers/FillType/English')
        fill_type_french = window_code.findtext('Layers/FillType/French')

        spacer_type_english = window_code.findtext('Layers/SpacerType/English')
        spacer_type_french = window_code.findtext('Layers/SpacerType/French')

        window_code_type_english = window_code.findtext('Layers/Type/English')
        window_code_type_french = window_code.findtext('Layers/Type/French')

        frame_material_english = window_code.findtext(
            'Layers/FrameMaterial/English')
        frame_material_french = window_code.findtext(
            'Layers/FrameMaterial/French')

        try:
            return WindowCode(
                identifier=window_code.get('@id', str),
                label=window_code.get_text('Label'),
                tags={
                    WindowCodeTag.GLAZING_TYPE:
                    bilingual.Bilingual(
                        english=glazing_type_english,
                        french=glazing_type_french,
                    )
                    if glazing_type_english and glazing_type_french else None,
                    WindowCodeTag.COATING_TINTS:
                    bilingual.Bilingual(
                        english=coating_tint_english,
                        french=coating_tint_french,
                    )
                    if coating_tint_english and coating_tint_french else None,
                    WindowCodeTag.FILL_TYPE:
                    bilingual.Bilingual(
                        english=fill_type_english,
                        french=fill_type_french,
                    ) if fill_type_english and fill_type_french else None,
                    WindowCodeTag.SPACER_TYPE:
                    bilingual.Bilingual(
                        english=spacer_type_english,
                        french=spacer_type_french,
                    ) if spacer_type_english and spacer_type_french else None,
                    WindowCodeTag.CODE_TYPE:
                    bilingual.Bilingual(
                        english=window_code_type_english,
                        french=window_code_type_french,
                    ) if window_code_type_english and window_code_type_french
                    else None,
                    WindowCodeTag.FRAME_MATERIAL:
                    bilingual.Bilingual(
                        english=frame_material_english,
                        french=frame_material_french,
                    ) if frame_material_english and frame_material_french else
                    None,
                })
        except ElementGetValueError as exc:
            raise InvalidEmbeddedDataTypeError(
                WindowCode, 'Unable to get identifier attributes') from exc
Esempio n. 24
0
 def from_data(cls, setting: element.Element) -> 'Upgrade':
     return Upgrade(upgrade_type=setting.tag,
                    cost=setting.get('@cost', int),
                    priority=setting.get('@priority', int))