openepd 2.0.0__py3-none-any.whl → 3.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openepd/__init__.py +1 -1
- openepd/__version__.py +2 -2
- openepd/api/__init__.py +19 -0
- openepd/api/base_sync_client.py +550 -0
- openepd/api/category/__init__.py +19 -0
- openepd/api/category/dto.py +25 -0
- openepd/api/category/sync_api.py +44 -0
- openepd/api/common.py +239 -0
- openepd/api/dto/__init__.py +19 -0
- openepd/api/dto/base.py +41 -0
- openepd/api/dto/common.py +115 -0
- openepd/api/dto/meta.py +69 -0
- openepd/api/dto/mf.py +59 -0
- openepd/api/dto/params.py +19 -0
- openepd/api/epd/__init__.py +19 -0
- openepd/api/epd/dto.py +121 -0
- openepd/api/epd/sync_api.py +105 -0
- openepd/api/errors.py +86 -0
- openepd/api/pcr/__init__.py +19 -0
- openepd/api/pcr/dto.py +41 -0
- openepd/api/pcr/sync_api.py +49 -0
- openepd/api/sync_client.py +67 -0
- openepd/api/test/__init__.py +19 -0
- openepd/bundle/__init__.py +1 -1
- openepd/bundle/base.py +1 -1
- openepd/bundle/model.py +5 -6
- openepd/bundle/reader.py +5 -5
- openepd/bundle/writer.py +5 -4
- openepd/compat/__init__.py +19 -0
- openepd/compat/pydantic.py +29 -0
- openepd/model/__init__.py +1 -1
- openepd/model/base.py +114 -15
- openepd/model/category.py +39 -0
- openepd/model/common.py +33 -25
- openepd/model/epd.py +97 -78
- openepd/model/factory.py +48 -0
- openepd/model/lcia.py +24 -13
- openepd/model/org.py +28 -18
- openepd/model/pcr.py +42 -14
- openepd/model/specs/README.md +19 -0
- openepd/model/specs/__init__.py +72 -4
- openepd/model/specs/aluminium.py +67 -0
- openepd/model/specs/asphalt.py +87 -0
- openepd/model/specs/base.py +60 -0
- openepd/model/specs/concrete.py +288 -24
- openepd/model/specs/generated/accessories.py +63 -0
- openepd/model/specs/generated/aggregates.py +71 -0
- openepd/model/specs/generated/aluminium.py +66 -0
- openepd/model/specs/generated/asphalt.py +86 -0
- openepd/model/specs/generated/bulk_materials.py +26 -0
- openepd/model/specs/generated/cast_decks_and_underlayment.py +26 -0
- openepd/model/specs/generated/cladding.py +214 -0
- openepd/model/specs/generated/cmu.py +46 -0
- openepd/model/specs/generated/common.py +27 -0
- openepd/model/specs/generated/concrete.py +151 -0
- openepd/model/specs/generated/conveying_equipment.py +57 -0
- openepd/model/specs/generated/electrical.py +297 -0
- openepd/model/specs/generated/electrical_transmission_and_distribution_equipment.py +63 -0
- openepd/model/specs/generated/electricity.py +26 -0
- openepd/model/specs/generated/enums.py +2420 -0
- openepd/model/specs/generated/finishes.py +519 -0
- openepd/model/specs/generated/fire_and_smoke_protection.py +79 -0
- openepd/model/specs/generated/furnishings.py +95 -0
- openepd/model/specs/generated/grouting.py +26 -0
- openepd/model/specs/generated/manufacturing_inputs.py +131 -0
- openepd/model/specs/generated/masonry.py +77 -0
- openepd/model/specs/generated/material_handling.py +35 -0
- openepd/model/specs/generated/mechanical.py +271 -0
- openepd/model/specs/generated/mechanical_insulation.py +41 -0
- openepd/model/specs/generated/network_infrastructure.py +181 -0
- openepd/model/specs/generated/openings.py +423 -0
- openepd/model/specs/generated/other_electrical_equipment.py +26 -0
- openepd/model/specs/generated/other_materials.py +123 -0
- openepd/model/specs/generated/plumbing.py +153 -0
- openepd/model/specs/generated/precast_concrete.py +68 -0
- openepd/model/specs/generated/sheathing.py +74 -0
- openepd/model/specs/generated/steel.py +224 -0
- openepd/model/specs/generated/thermal_moisture_protection.py +233 -0
- openepd/model/specs/generated/utility_piping.py +65 -0
- openepd/model/specs/generated/wood.py +167 -0
- openepd/model/specs/generated/wood_joists.py +38 -0
- openepd/model/specs/glass.py +360 -0
- openepd/model/specs/steel.py +184 -0
- openepd/model/specs/wood.py +130 -0
- openepd/model/standard.py +2 -3
- openepd/model/validation/__init__.py +19 -0
- openepd/model/validation/common.py +59 -0
- openepd/model/validation/numbers.py +26 -0
- openepd/model/validation/quantity.py +132 -0
- openepd/model/versioning.py +129 -0
- {openepd-2.0.0.dist-info → openepd-3.1.0.dist-info}/METADATA +36 -5
- openepd-3.1.0.dist-info/RECORD +95 -0
- openepd-2.0.0.dist-info/RECORD +0 -22
- {openepd-2.0.0.dist-info → openepd-3.1.0.dist-info}/LICENSE +0 -0
- {openepd-2.0.0.dist-info → openepd-3.1.0.dist-info}/WHEEL +0 -0
openepd/model/pcr.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright
|
2
|
+
# Copyright 2024 by C Change Labs Inc. www.c-change-labs.com
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -18,65 +18,93 @@
|
|
18
18
|
# Find out more at www.BuildingTransparency.org
|
19
19
|
#
|
20
20
|
import datetime
|
21
|
-
from
|
22
|
-
|
23
|
-
import pydantic as pyd
|
21
|
+
from enum import StrEnum
|
22
|
+
from typing import Annotated, Optional
|
24
23
|
|
24
|
+
from openepd.compat.pydantic import pyd
|
25
25
|
from openepd.model.base import BaseOpenEpdSchema
|
26
26
|
from openepd.model.common import WithAltIdsMixin, WithAttachmentsMixin
|
27
27
|
from openepd.model.org import Org
|
28
28
|
|
29
29
|
|
30
|
+
class PcrStatus(StrEnum):
|
31
|
+
"""Status of a PCR."""
|
32
|
+
|
33
|
+
InDevelopment = "InDevelopment"
|
34
|
+
Published = "Published"
|
35
|
+
NonPublic = "NonPublic"
|
36
|
+
Expired = "Expired"
|
37
|
+
Sunset = "Sunset"
|
38
|
+
|
39
|
+
|
30
40
|
class Pcr(WithAttachmentsMixin, WithAltIdsMixin, BaseOpenEpdSchema):
|
31
41
|
"""Represent a PCR (Product Category Rules)."""
|
32
42
|
|
33
43
|
id: str | None = pyd.Field(
|
34
44
|
description="The unique ID for this PCR. To ensure global uniqueness, should be registered "
|
35
45
|
"at open-xpd-uuid.cqd.io/register or a coordinating registry.",
|
46
|
+
example="ec3xpgq2",
|
36
47
|
default=None,
|
37
|
-
json_schema_extra={"example": "ec3xpgq2"},
|
38
48
|
)
|
39
49
|
issuer: Org | None = pyd.Field(description="Organization issuing this PCR", default=None)
|
40
50
|
issuer_doc_id: str | None = pyd.Field(
|
41
51
|
max_length=40,
|
42
52
|
default=None,
|
43
53
|
description="Document ID or code created by issuer",
|
44
|
-
|
54
|
+
example="c-PCR-003",
|
45
55
|
)
|
46
56
|
name: str | None = pyd.Field(
|
47
57
|
max_length=200,
|
48
58
|
default=None,
|
49
59
|
description="Full document name as listed in source document",
|
50
|
-
|
60
|
+
example="c-PCR-003 Concrete and concrete elements (EN 16757)",
|
51
61
|
)
|
52
62
|
short_name: str | None = pyd.Field(
|
53
|
-
max_length=40,
|
54
63
|
default=None,
|
55
64
|
description="A shortened name without boilerplate text.",
|
56
|
-
|
65
|
+
example="Concrete and Concrete Elements",
|
57
66
|
)
|
58
67
|
version: str | None = pyd.Field(
|
59
68
|
description="Document version, as expressed in document.",
|
69
|
+
example="1.0.2",
|
60
70
|
default=None,
|
61
|
-
json_schema_extra=dict(example="1.0.2"),
|
62
71
|
)
|
63
|
-
date_of_issue: datetime.
|
72
|
+
date_of_issue: datetime.datetime | None = pyd.Field(
|
73
|
+
example=datetime.date(day=11, month=2, year=2022),
|
64
74
|
default=None,
|
65
75
|
description="First day on which the document is valid",
|
66
|
-
json_schema_extra=dict(example=datetime.date(day=11, month=2, year=2022)),
|
67
76
|
)
|
68
|
-
valid_until: datetime.
|
77
|
+
valid_until: datetime.datetime | None = pyd.Field(
|
78
|
+
example=datetime.date(day=11, month=2, year=2024),
|
69
79
|
default=None,
|
70
80
|
description="Last day on which the document is valid",
|
71
|
-
json_schema_extra=dict(example=datetime.date(day=11, month=2, year=2024)),
|
72
81
|
)
|
82
|
+
doc: str | None = pyd.Field(default=None, description="URL to original document, preferably directly to a PDF.")
|
73
83
|
parent: Optional["Pcr"] = pyd.Field(
|
74
84
|
description="The parent PCR, base PCR, `Part A` PCR",
|
75
85
|
default=None,
|
76
86
|
)
|
87
|
+
status: PcrStatus | None = pyd.Field(
|
88
|
+
default=None,
|
89
|
+
description="The current release status of this PCR. "
|
90
|
+
"A PCR with valid_until in the past must have status Expired or Sunset; a PCR with valid_until "
|
91
|
+
"more than 5 years in the past must have status Sunset. Compliant systems should automatically "
|
92
|
+
"update these fields within 24 hours.",
|
93
|
+
)
|
77
94
|
product_classes: dict[str, str | list[str]] = pyd.Field(
|
78
95
|
description="List of classifications, including Masterformat and UNSPC", default_factory=dict
|
79
96
|
)
|
97
|
+
applicable_in: list[Annotated[str, pyd.Field(min_length=2, max_length=2)]] | None = pyd.Field(
|
98
|
+
max_items=100,
|
99
|
+
default=None,
|
100
|
+
description="Jurisdiction(s) in which EPD is applicable. An empty array, or absent properties, "
|
101
|
+
"implies global applicability. Accepts "
|
102
|
+
"[2-letter country codes](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2), "
|
103
|
+
"[M49 region codes](https://unstats.un.org/unsd/methodology/m49/), "
|
104
|
+
'or the alias "EU27" for the 27 members of the Euro bloc, or the alias "NAFTA" '
|
105
|
+
"for the members of North American Free Trade Agreement",
|
106
|
+
example=["US", "CA", "MX", "EU27", "NAFTA"],
|
107
|
+
)
|
80
108
|
|
81
109
|
@classmethod
|
82
110
|
def get_asset_type(cls) -> str | None:
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Material Extensions
|
2
|
+
|
3
|
+
This package contains openEPD material extensions. They are used to represent the material properties of the openEPD
|
4
|
+
materials, and are a more dynamic, frequently changing part of the standard.
|
5
|
+
|
6
|
+
## Versioning
|
7
|
+
|
8
|
+
Extensions are versioned separately from the openEPD standard or openEPD API.
|
9
|
+
|
10
|
+
Each material extension is named after the corresponding EC3 product class, and is located in the relevant place
|
11
|
+
in the specs tree. For example, `RebarSteel` is nested under `Steel`.
|
12
|
+
|
13
|
+
Extensions are versioned as Major.Minor, for example "2.4".
|
14
|
+
|
15
|
+
Rules:
|
16
|
+
1. Minor versions for the same major version should be backwards compatible.
|
17
|
+
2. Major versions are not compatible between themselves.
|
18
|
+
3. Pydantic models representing versions are named in a pattern SpecNameV1, where 1 is major version and SpecName is
|
19
|
+
the name of the material extension.
|
openepd/model/specs/__init__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright
|
2
|
+
# Copyright 2024 by C Change Labs Inc. www.c-change-labs.com
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -17,13 +17,81 @@
|
|
17
17
|
# Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
|
18
18
|
# Find out more at www.BuildingTransparency.org
|
19
19
|
#
|
20
|
-
import pydantic as pyd
|
21
20
|
|
22
21
|
from openepd.model.base import BaseOpenEpdSchema
|
23
|
-
from openepd.model.specs.
|
22
|
+
from openepd.model.specs.generated.accessories import AccessoriesV1
|
23
|
+
from openepd.model.specs.generated.aggregates import AggregatesV1
|
24
|
+
from openepd.model.specs.generated.aluminium import AluminiumV1
|
25
|
+
from openepd.model.specs.generated.asphalt import AsphaltV1
|
26
|
+
from openepd.model.specs.generated.bulk_materials import BulkMaterialsV1
|
27
|
+
from openepd.model.specs.generated.cast_decks_and_underlayment import CastDecksAndUnderlaymentV1
|
28
|
+
from openepd.model.specs.generated.cladding import CladdingV1
|
29
|
+
from openepd.model.specs.generated.cmu import CMUV1
|
30
|
+
from openepd.model.specs.generated.concrete import ConcreteV1
|
31
|
+
from openepd.model.specs.generated.conveying_equipment import ConveyingEquipmentV1
|
32
|
+
from openepd.model.specs.generated.electrical import ElectricalV1
|
33
|
+
from openepd.model.specs.generated.electrical_transmission_and_distribution_equipment import (
|
34
|
+
ElectricalTransmissionAndDistributionEquipmentV1,
|
35
|
+
)
|
36
|
+
from openepd.model.specs.generated.electricity import ElectricityV1
|
37
|
+
from openepd.model.specs.generated.finishes import FinishesV1
|
38
|
+
from openepd.model.specs.generated.fire_and_smoke_protection import FireAndSmokeProtectionV1
|
39
|
+
from openepd.model.specs.generated.furnishings import FurnishingsV1
|
40
|
+
from openepd.model.specs.generated.grouting import GroutingV1
|
41
|
+
from openepd.model.specs.generated.manufacturing_inputs import ManufacturingInputsV1
|
42
|
+
from openepd.model.specs.generated.masonry import MasonryV1
|
43
|
+
from openepd.model.specs.generated.material_handling import MaterialHandlingV1
|
44
|
+
from openepd.model.specs.generated.mechanical import MechanicalV1
|
45
|
+
from openepd.model.specs.generated.mechanical_insulation import MechanicalInsulationV1
|
46
|
+
from openepd.model.specs.generated.network_infrastructure import NetworkInfrastructureV1
|
47
|
+
from openepd.model.specs.generated.openings import OpeningsV1
|
48
|
+
from openepd.model.specs.generated.other_electrical_equipment import OtherElectricalEquipmentV1
|
49
|
+
from openepd.model.specs.generated.other_materials import OtherMaterialsV1
|
50
|
+
from openepd.model.specs.generated.plumbing import PlumbingV1
|
51
|
+
from openepd.model.specs.generated.precast_concrete import PrecastConcreteV1
|
52
|
+
from openepd.model.specs.generated.sheathing import SheathingV1
|
53
|
+
from openepd.model.specs.generated.steel import SteelV1
|
54
|
+
from openepd.model.specs.generated.thermal_moisture_protection import ThermalMoistureProtectionV1
|
55
|
+
from openepd.model.specs.generated.utility_piping import UtilityPipingV1
|
56
|
+
from openepd.model.specs.generated.wood import WoodV1
|
57
|
+
from openepd.model.specs.generated.wood_joists import WoodJoistsV1
|
24
58
|
|
25
59
|
|
26
60
|
class Specs(BaseOpenEpdSchema):
|
27
61
|
"""Material specific specs."""
|
28
62
|
|
29
|
-
|
63
|
+
# Nested specs:
|
64
|
+
CMU: CMUV1 | None = None
|
65
|
+
Masonry: MasonryV1 | None = None
|
66
|
+
Steel: SteelV1 | None = None
|
67
|
+
NetworkInfrastructure: NetworkInfrastructureV1 | None = None
|
68
|
+
Finishes: FinishesV1 | None = None
|
69
|
+
ManufacturingInputs: ManufacturingInputsV1 | None = None
|
70
|
+
Accessories: AccessoriesV1 | None = None
|
71
|
+
ElectricalTransmissionAndDistributionEquipment: ElectricalTransmissionAndDistributionEquipmentV1 | None = None
|
72
|
+
Aggregates: AggregatesV1 | None = None
|
73
|
+
ThermalMoistureProtection: ThermalMoistureProtectionV1 | None = None
|
74
|
+
Mechanical: MechanicalV1 | None = None
|
75
|
+
Aluminium: AluminiumV1 | None = None
|
76
|
+
Cladding: CladdingV1 | None = None
|
77
|
+
FireAndSmokeProtection: FireAndSmokeProtectionV1 | None = None
|
78
|
+
PrecastConcrete: PrecastConcreteV1 | None = None
|
79
|
+
Asphalt: AsphaltV1 | None = None
|
80
|
+
OtherMaterials: OtherMaterialsV1 | None = None
|
81
|
+
Plumbing: PlumbingV1 | None = None
|
82
|
+
Electrical: ElectricalV1 | None = None
|
83
|
+
UtilityPiping: UtilityPipingV1 | None = None
|
84
|
+
BulkMaterials: BulkMaterialsV1 | None = None
|
85
|
+
CastDecksAndUnderlayment: CastDecksAndUnderlaymentV1 | None = None
|
86
|
+
Concrete: ConcreteV1 | None = None
|
87
|
+
Sheathing: SheathingV1 | None = None
|
88
|
+
Furnishings: FurnishingsV1 | None = None
|
89
|
+
Wood: WoodV1 | None = None
|
90
|
+
ConveyingEquipment: ConveyingEquipmentV1 | None = None
|
91
|
+
MaterialHandling: MaterialHandlingV1 | None = None
|
92
|
+
Openings: OpeningsV1 | None = None
|
93
|
+
Electricity: ElectricityV1 | None = None
|
94
|
+
Grouting: GroutingV1 | None = None
|
95
|
+
MechanicalInsulation: MechanicalInsulationV1 | None = None
|
96
|
+
OtherElectricalEquipment: OtherElectricalEquipmentV1 | None = None
|
97
|
+
WoodJoists: WoodJoistsV1 | None = None
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2024 by C Change Labs Inc. www.c-change-labs.com
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
# This software was developed with support from the Skanska USA,
|
17
|
+
# Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
|
18
|
+
# Find out more at www.BuildingTransparency.org
|
19
|
+
#
|
20
|
+
from enum import StrEnum
|
21
|
+
|
22
|
+
from openepd.compat.pydantic import pyd
|
23
|
+
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
24
|
+
from openepd.model.validation.numbers import RatioFloat
|
25
|
+
|
26
|
+
|
27
|
+
class AluminiumAlloy(StrEnum):
|
28
|
+
"""Aluminium alloy enum."""
|
29
|
+
|
30
|
+
ALLOY_1xxx = ("1xxx",)
|
31
|
+
ALLOY_2xxx = ("2xxx",)
|
32
|
+
ALLOY_3xxx = ("3xxx",)
|
33
|
+
ALLOY_4xxx = ("4xxx",)
|
34
|
+
ALLOY_5xxx = ("5xxx",)
|
35
|
+
ALLOY_6xxx = ("6xxx",)
|
36
|
+
ALLOY_7xxx = ("7xxx",)
|
37
|
+
ALLOY_8xxx = ("8xxx",)
|
38
|
+
ALLOY_1xx_x = ("1xx.x",)
|
39
|
+
ALLOY_2xx_x = ("2xx.x",)
|
40
|
+
ALLOY_3xx_x = ("3xx.x",)
|
41
|
+
ALLOY_4xx_x = ("4xx.x",)
|
42
|
+
ALLOY_5xx_x = ("5xx.x",)
|
43
|
+
ALLOY_7xx_x = ("7xx.x",)
|
44
|
+
ALLOY_8xx_x = ("8xx.x",)
|
45
|
+
ALLOY_9xx_x = ("9xx.x",)
|
46
|
+
|
47
|
+
|
48
|
+
class AluminiumExtrusionsV1(BaseOpenEpdHierarchicalSpec):
|
49
|
+
"""Aluminium extrusions V1 spec."""
|
50
|
+
|
51
|
+
_EXT_VERSION = "1.0"
|
52
|
+
|
53
|
+
"""Aluminium extrusions V1 spec."""
|
54
|
+
thermally_improved: bool | None = pyd.Field(default=None, description="Thermally improved")
|
55
|
+
|
56
|
+
|
57
|
+
class AluminiumV1(BaseOpenEpdHierarchicalSpec):
|
58
|
+
"""Aluminium V1 spec."""
|
59
|
+
|
60
|
+
_EXT_VERSION = "1.0"
|
61
|
+
recycled_content: RatioFloat | None = pyd.Field(default=None, description="Recycled content")
|
62
|
+
|
63
|
+
alloy: AluminiumAlloy | None = pyd.Field(default=None, description="AluminiumAlloy")
|
64
|
+
anodized: bool | None = None
|
65
|
+
painted: bool | None = None
|
66
|
+
|
67
|
+
AluminiumExtrusions: AluminiumExtrusionsV1 | None = pyd.Field(title="AluminiumExtrusionsV1", default=None)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2024 by C Change Labs Inc. www.c-change-labs.com
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
# This software was developed with support from the Skanska USA,
|
17
|
+
# Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
|
18
|
+
# Find out more at www.BuildingTransparency.org
|
19
|
+
#
|
20
|
+
from enum import StrEnum
|
21
|
+
|
22
|
+
from openepd.compat.pydantic import pyd
|
23
|
+
from openepd.model.common import OpenEPDUnit
|
24
|
+
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
25
|
+
from openepd.model.validation.numbers import RatioFloat
|
26
|
+
from openepd.model.validation.quantity import LengthMmStr, TemperatureCStr, validate_unit_factory
|
27
|
+
|
28
|
+
|
29
|
+
class AsphaltMixType(StrEnum):
|
30
|
+
"""Asphalt mix type enum."""
|
31
|
+
|
32
|
+
HMA = "HMA"
|
33
|
+
WMA = "WMA"
|
34
|
+
|
35
|
+
|
36
|
+
class AsphaltGradation(StrEnum):
|
37
|
+
"""Asphalt gradation enum."""
|
38
|
+
|
39
|
+
Dense_graded = "Dense-graded"
|
40
|
+
Open_graded = "Open-graded"
|
41
|
+
Gap_graded = "Gap-graded"
|
42
|
+
|
43
|
+
|
44
|
+
class AsphaltV1(BaseOpenEpdHierarchicalSpec):
|
45
|
+
"""Asphalt spec."""
|
46
|
+
|
47
|
+
_EXT_VERSION = "1.0"
|
48
|
+
|
49
|
+
asphalt_aggregate_size_max: LengthMmStr | None = pyd.Field(
|
50
|
+
default=None, example="5mm", description="Max aggregate size"
|
51
|
+
)
|
52
|
+
|
53
|
+
asphalt_rap: RatioFloat | None = pyd.Field(
|
54
|
+
default=None, description="Percent of mixture that has been replaced by recycled " "asphalt pavement (RAP)."
|
55
|
+
)
|
56
|
+
asphalt_ras: RatioFloat | None = pyd.Field(
|
57
|
+
default=None, description="Percent of mixture that has been replaced by recycled " "asphalt shingles (RAS)."
|
58
|
+
)
|
59
|
+
asphalt_ground_tire_rubber: RatioFloat | None = pyd.Field(
|
60
|
+
default=None, description="Percent of mixture that has been replaced " "by ground tire rubber (GTR)."
|
61
|
+
)
|
62
|
+
|
63
|
+
asphalt_max_temperature: TemperatureCStr | None = pyd.Field(
|
64
|
+
default=None,
|
65
|
+
description="The upper threshold temperature to which an asphalt "
|
66
|
+
"binder can be heated preventing the asphalt mixture "
|
67
|
+
"from rutting",
|
68
|
+
)
|
69
|
+
asphalt_min_temperature: TemperatureCStr | None = pyd.Field(
|
70
|
+
default=None,
|
71
|
+
description="The lower threshold temperature for an asphalt "
|
72
|
+
"binder to prevent thermal cracking of the asphalt"
|
73
|
+
" mixture.",
|
74
|
+
)
|
75
|
+
|
76
|
+
asphalt_mix_type: AsphaltMixType | None = pyd.Field(default=None, description="Asphalt mix type")
|
77
|
+
asphalt_gradation: AsphaltGradation | None = pyd.Field(default=None, description="Asphalt gradation")
|
78
|
+
|
79
|
+
asphalt_sbr: bool | None = pyd.Field(default=None, description="Styrene-butadiene rubber (SBR)")
|
80
|
+
asphalt_sbs: bool | None = pyd.Field(default=None, description="Styrene-butadiene-styrene (SBS)")
|
81
|
+
asphalt_ppa: bool | None = pyd.Field(default=None, description="Polyphosphoric acid (PPA)")
|
82
|
+
asphalt_gtr: bool | None = pyd.Field(default=None, description="Ground tire rubber (GTR)")
|
83
|
+
asphalt_pmb: bool | None = pyd.Field(default=None, description="Polymer modified bitumen (PMB)")
|
84
|
+
|
85
|
+
_aggregate_size_max_validator = pyd.validator("asphalt_aggregate_size_max", allow_reuse=True)(
|
86
|
+
validate_unit_factory(OpenEPDUnit.m)
|
87
|
+
)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2024 by C Change Labs Inc. www.c-change-labs.com
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
# This software was developed with support from the Skanska USA,
|
17
|
+
# Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
|
18
|
+
# Find out more at www.BuildingTransparency.org
|
19
|
+
#
|
20
|
+
from typing import Any
|
21
|
+
|
22
|
+
from openepd.compat.pydantic import pyd
|
23
|
+
from openepd.model.base import BaseOpenEpdSchema, Version
|
24
|
+
from openepd.model.validation.common import validate_version_compatibility, validate_version_format
|
25
|
+
from openepd.model.validation.quantity import QuantityValidator
|
26
|
+
from openepd.model.versioning import WithExtVersionMixin
|
27
|
+
|
28
|
+
|
29
|
+
class BaseOpenEpdSpec(BaseOpenEpdSchema):
|
30
|
+
"""Base class for all OpenEPD specs."""
|
31
|
+
|
32
|
+
class Config:
|
33
|
+
use_enum_values = False # we need to store enums as strings and not values
|
34
|
+
|
35
|
+
|
36
|
+
class BaseOpenEpdHierarchicalSpec(BaseOpenEpdSpec, WithExtVersionMixin):
|
37
|
+
"""Base class for new specs (hierarchical, versioned)."""
|
38
|
+
|
39
|
+
# external validator for quantities (e.g. length, mass, etc.) which should be setup by the user of the library.
|
40
|
+
_QUANTITY_VALIDATOR: QuantityValidator | None = None
|
41
|
+
|
42
|
+
def __init__(self, **data: Any) -> None:
|
43
|
+
# ensure that all the concrete spec objects fail on creations if they dont have _EXT_VERSION declared to
|
44
|
+
# something meaningful
|
45
|
+
if not hasattr(self, "_EXT_VERSION") or self._EXT_VERSION is None:
|
46
|
+
raise ValueError(f"Class {self.__class__} must declare an extension version")
|
47
|
+
Version.parse_version(self._EXT_VERSION) # validate format correctness
|
48
|
+
super().__init__(**{"ext_version": self._EXT_VERSION, **data})
|
49
|
+
|
50
|
+
_version_format_validator = pyd.validator("ext_version", allow_reuse=True, check_fields=False)(
|
51
|
+
validate_version_format
|
52
|
+
)
|
53
|
+
_version_major_match_validator = pyd.validator("ext_version", allow_reuse=True, check_fields=False)(
|
54
|
+
validate_version_compatibility("_EXT_VERSION")
|
55
|
+
)
|
56
|
+
|
57
|
+
|
58
|
+
def setup_external_validators(quantity_validator: QuantityValidator):
|
59
|
+
"""Set the implementation unit validator for specs."""
|
60
|
+
BaseOpenEpdHierarchicalSpec._QUANTITY_VALIDATOR = quantity_validator
|