openepd 5.0.0__tar.gz → 5.1.1__tar.gz
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-5.0.0 → openepd-5.1.1}/PKG-INFO +6 -1
- {openepd-5.0.0 → openepd-5.1.1}/README.md +5 -0
- {openepd-5.0.0 → openepd-5.1.1}/pyproject.toml +3 -2
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/__version__.py +1 -1
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/common.py +39 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/declaration.py +7 -2
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/geography.py +1 -1
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/lcia.py +6 -3
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/org.py +0 -1
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/pcr.py +2 -2
- openepd-5.1.1/src/openepd/model/specs/README.md +45 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/asphalt.py +2 -2
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/base.py +13 -0
- openepd-5.1.1/src/openepd/model/specs/generated/__init__.py +95 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/cladding.py +4 -4
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/concrete.py +8 -7
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/electrical.py +2 -2
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/finishes.py +10 -6
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/masonry.py +6 -2
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/network_infrastructure.py +7 -2
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/openings.py +10 -6
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/sheathing.py +8 -4
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/steel.py +10 -5
- openepd-5.1.1/src/openepd/model/specs/range/__init__.py +101 -0
- openepd-5.1.1/src/openepd/model/specs/range/accessories.py +97 -0
- openepd-5.1.1/src/openepd/model/specs/range/aggregates.py +57 -0
- openepd-5.1.1/src/openepd/model/specs/range/aluminium.py +92 -0
- openepd-5.1.1/src/openepd/model/specs/range/asphalt.py +61 -0
- openepd-5.1.1/src/openepd/model/specs/range/bulk_materials.py +31 -0
- openepd-5.1.1/src/openepd/model/specs/range/cast_decks_and_underlayment.py +34 -0
- openepd-5.1.1/src/openepd/model/specs/range/cladding.py +275 -0
- openepd-5.1.1/src/openepd/model/specs/range/cmu.py +44 -0
- openepd-5.1.1/src/openepd/model/specs/range/concrete.py +179 -0
- openepd-5.1.1/src/openepd/model/specs/range/conveying_equipment.py +86 -0
- openepd-5.1.1/src/openepd/model/specs/range/electrical.py +422 -0
- openepd-5.1.1/src/openepd/model/specs/range/electrical_transmission_and_distribution_equipment.py +96 -0
- openepd-5.1.1/src/openepd/model/specs/range/electricity.py +31 -0
- openepd-5.1.1/src/openepd/model/specs/range/finishes.py +585 -0
- openepd-5.1.1/src/openepd/model/specs/range/fire_and_smoke_protection.py +108 -0
- openepd-5.1.1/src/openepd/model/specs/range/furnishings.py +137 -0
- openepd-5.1.1/src/openepd/model/specs/range/grouting.py +34 -0
- openepd-5.1.1/src/openepd/model/specs/range/manufacturing_inputs.py +190 -0
- openepd-5.1.1/src/openepd/model/specs/range/masonry.py +87 -0
- openepd-5.1.1/src/openepd/model/specs/range/material_handling.py +50 -0
- openepd-5.1.1/src/openepd/model/specs/range/mechanical.py +307 -0
- openepd-5.1.1/src/openepd/model/specs/range/mechanical_insulation.py +42 -0
- openepd-5.1.1/src/openepd/model/specs/range/network_infrastructure.py +208 -0
- openepd-5.1.1/src/openepd/model/specs/range/openings.py +512 -0
- openepd-5.1.1/src/openepd/model/specs/range/other_electrical_equipment.py +31 -0
- openepd-5.1.1/src/openepd/model/specs/range/other_materials.py +194 -0
- openepd-5.1.1/src/openepd/model/specs/range/plumbing.py +200 -0
- openepd-5.1.1/src/openepd/model/specs/range/precast_concrete.py +115 -0
- openepd-5.1.1/src/openepd/model/specs/range/sheathing.py +86 -0
- openepd-5.1.1/src/openepd/model/specs/range/steel.py +332 -0
- openepd-5.1.1/src/openepd/model/specs/range/thermal_moisture_protection.py +336 -0
- openepd-5.1.1/src/openepd/model/specs/range/utility_piping.py +75 -0
- openepd-5.1.1/src/openepd/model/specs/range/wood.py +228 -0
- openepd-5.1.1/src/openepd/model/specs/range/wood_joists.py +44 -0
- openepd-5.1.1/src/openepd/model/validation/numbers.py +28 -0
- openepd-5.1.1/src/openepd/model/validation/quantity.py +726 -0
- openepd-5.0.0/src/openepd/model/specs/README.md +0 -19
- openepd-5.0.0/src/openepd/model/validation/__init__.py +0 -15
- openepd-5.0.0/src/openepd/model/validation/numbers.py +0 -22
- openepd-5.0.0/src/openepd/model/validation/quantity.py +0 -338
- {openepd-5.0.0 → openepd-5.1.1}/LICENSE +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/average_dataset/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/average_dataset/generic_estimate_sync_api.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/average_dataset/industry_epd_sync_api.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/base_sync_client.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/category/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/category/dto.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/category/sync_api.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/common.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/dto/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/dto/base.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/dto/common.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/dto/meta.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/dto/mf.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/dto/params.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/epd/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/epd/dto.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/epd/sync_api.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/errors.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/pcr/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/pcr/sync_api.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/sync_client.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/test/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/api/utils.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/bundle/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/bundle/base.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/bundle/model.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/bundle/reader.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/bundle/writer.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/compat/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/compat/compat_functional_validators.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/compat/pydantic.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/base.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/category.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/epd.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/factory.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/generic_estimate.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/industry_epd.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/concrete.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/accessories.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/aggregates.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/aluminium.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/asphalt.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/bulk_materials.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/cast_decks_and_underlayment.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/cmu.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/common.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/conveying_equipment.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/electrical_transmission_and_distribution_equipment.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/electricity.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/enums.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/fire_and_smoke_protection.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/furnishings.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/grouting.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/manufacturing_inputs.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/material_handling.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/mechanical.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/mechanical_insulation.py +0 -0
- {openepd-5.0.0/src/openepd/model/specs/generated → openepd-5.1.1/src/openepd/model/specs/generated/mixins}/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/mixins/conduit_mixin.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/other_electrical_equipment.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/other_materials.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/plumbing.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/precast_concrete.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/thermal_moisture_protection.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/utility_piping.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/wood.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/specs/generated/wood_joists.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/standard.py +0 -0
- {openepd-5.0.0/src/openepd/model/specs/generated/mixins → openepd-5.1.1/src/openepd/model/validation}/__init__.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/validation/common.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/model/versioning.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/patch_pydantic.py +0 -0
- {openepd-5.0.0 → openepd-5.1.1}/src/openepd/py.typed +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: openepd
|
3
|
-
Version: 5.
|
3
|
+
Version: 5.1.1
|
4
4
|
Summary: Python library to work with OpenEPD format
|
5
5
|
Home-page: https://github.com/cchangelabs/openepd
|
6
6
|
License: Apache-2.0
|
@@ -170,6 +170,11 @@ codes, UN m49 codification, and special regions. To update the enums, first upda
|
|
170
170
|
Windows is not supported for development. You can use WSL2 with Ubuntu 20.04 or higher.
|
171
171
|
Instructions are the same as for regular GNU/Linux installation.
|
172
172
|
|
173
|
+
### Commit messages
|
174
|
+
|
175
|
+
Commit messages should follow [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/#specification)
|
176
|
+
specification as we use automatic version with [commitizen](https://commitizen-tools.github.io/commitizen/).
|
177
|
+
|
173
178
|
# Credits
|
174
179
|
|
175
180
|
This library has been written and maintained by [C-Change Labs](https://c-change-labs.com/).
|
@@ -143,6 +143,11 @@ codes, UN m49 codification, and special regions. To update the enums, first upda
|
|
143
143
|
Windows is not supported for development. You can use WSL2 with Ubuntu 20.04 or higher.
|
144
144
|
Instructions are the same as for regular GNU/Linux installation.
|
145
145
|
|
146
|
+
### Commit messages
|
147
|
+
|
148
|
+
Commit messages should follow [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/#specification)
|
149
|
+
specification as we use automatic version with [commitizen](https://commitizen-tools.github.io/commitizen/).
|
150
|
+
|
146
151
|
# Credits
|
147
152
|
|
148
153
|
This library has been written and maintained by [C-Change Labs](https://c-change-labs.com/).
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "openepd"
|
3
|
-
version = "5.
|
3
|
+
version = "5.1.1"
|
4
4
|
license = "Apache-2.0"
|
5
5
|
description = "Python library to work with OpenEPD format"
|
6
6
|
authors = ["C-Change Labs <support@c-change-labs.com>"]
|
@@ -38,6 +38,7 @@ pytest-subtests = "~=0.4"
|
|
38
38
|
pytest-cov = "~=4.0"
|
39
39
|
teamcity-messages = ">=1.31"
|
40
40
|
wheel = "~=0.40.0"
|
41
|
+
click = "~=8.1.7"
|
41
42
|
|
42
43
|
# Dev tools
|
43
44
|
black = "~=24.3"
|
@@ -58,7 +59,7 @@ types-requests = ">=2.0"
|
|
58
59
|
# Code generation
|
59
60
|
# For list of countries
|
60
61
|
pycountry = ">=24.6.1"
|
61
|
-
jinja2 = ">=
|
62
|
+
jinja2 = ">=3.1.4"
|
62
63
|
|
63
64
|
|
64
65
|
[tool.poetry.extras]
|
@@ -150,3 +150,42 @@ class OpenEPDUnit(StrEnum):
|
|
150
150
|
degree_c = "°C"
|
151
151
|
kg_co2 = "kgCO2e"
|
152
152
|
hour = "hour"
|
153
|
+
|
154
|
+
|
155
|
+
class RangeBase(BaseOpenEpdSchema):
|
156
|
+
"""Base class for range types having min and max and order between them."""
|
157
|
+
|
158
|
+
@pyd.root_validator
|
159
|
+
def _validate_range_bounds(cls, values: dict[str, Any]) -> dict[str, Any]:
|
160
|
+
min_boundary = values.get("min")
|
161
|
+
max_boundary = values.get("max")
|
162
|
+
if min_boundary is not None and max_boundary is not None and min_boundary > max_boundary:
|
163
|
+
raise ValueError("Max should be greater than min")
|
164
|
+
return values
|
165
|
+
|
166
|
+
|
167
|
+
class RangeFloat(RangeBase):
|
168
|
+
"""Structure representing a range of floats."""
|
169
|
+
|
170
|
+
min: float | None = pyd.Field(default=None, example=3.1)
|
171
|
+
max: float | None = pyd.Field(default=None, example=5.8)
|
172
|
+
|
173
|
+
|
174
|
+
class RangeInt(RangeBase):
|
175
|
+
"""Structure representing a range of ints1."""
|
176
|
+
|
177
|
+
min: int | None = pyd.Field(default=None, example=2)
|
178
|
+
max: int | None = pyd.Field(default=None, example=3)
|
179
|
+
|
180
|
+
|
181
|
+
class RangeRatioFloat(RangeFloat):
|
182
|
+
"""Range of ratios (0-1 to 0-10)."""
|
183
|
+
|
184
|
+
min: float | None = pyd.Field(default=None, example=0.2, ge=0, le=1)
|
185
|
+
max: float | None = pyd.Field(default=None, example=0.65, ge=0, le=1)
|
186
|
+
|
187
|
+
|
188
|
+
class RangeAmount(RangeFloat):
|
189
|
+
"""Structure representing a range of quantities."""
|
190
|
+
|
191
|
+
unit: str | None = pyd.Field(default=None, description="Unit of the range.")
|
@@ -22,6 +22,7 @@ from openepd.model.common import Amount
|
|
22
22
|
from openepd.model.geography import Geography
|
23
23
|
from openepd.model.org import Org
|
24
24
|
from openepd.model.pcr import Pcr
|
25
|
+
from openepd.model.specs.range import SpecsRange
|
25
26
|
from openepd.model.standard import Standard
|
26
27
|
from openepd.model.validation.common import ReferenceStr
|
27
28
|
from openepd.model.validation.quantity import AmountGWP, AmountMass
|
@@ -141,14 +142,14 @@ class BaseDeclaration(RootDocument, abc.ABC):
|
|
141
142
|
description="Mass of elemental carbon, per declared unit, contained in the product itself at the manufacturing "
|
142
143
|
"facility gate. Used (among other things) to check a carbon balance or calculate incineration "
|
143
144
|
"emissions. The source of carbon (e.g. biogenic) is not relevant in this field.",
|
144
|
-
example=Amount(qty=8.76, unit="kgCO2e"),
|
145
|
+
example=Amount(qty=8.76, unit="kgCO2e").to_serializable(exclude_unset=True),
|
145
146
|
)
|
146
147
|
kg_C_biogenic_per_declared_unit: AmountGWP | None = pyd.Field(
|
147
148
|
default=None,
|
148
149
|
description="Mass of elemental carbon from biogenic sources, per declared unit, contained in the product "
|
149
150
|
"itself at the manufacturing facility gate. It may be presumed that any biogenic carbon content "
|
150
151
|
"has been accounted for as -44/12 kgCO2e per kg C in stages A1-A3, per EN15804 and ISO 21930.",
|
151
|
-
example=Amount(qty=8.76, unit="kgCO2e"),
|
152
|
+
example=Amount(qty=8.76, unit="kgCO2e").to_serializable(exclude_unset=True),
|
152
153
|
)
|
153
154
|
product_service_life_years: float | None = pyd.Field(
|
154
155
|
gt=0.0009,
|
@@ -173,6 +174,10 @@ class AverageDatasetMixin(pyd.BaseModel, title="Average Dataset"):
|
|
173
174
|
"implies global applicability.",
|
174
175
|
)
|
175
176
|
|
177
|
+
specs: SpecsRange | None = pyd.Field(
|
178
|
+
default=None, description="Average dataset material performance specifications."
|
179
|
+
)
|
180
|
+
|
176
181
|
|
177
182
|
class WithProgramOperatorMixin(pyd.BaseModel):
|
178
183
|
"""Object which has a connection to ProgramOperator."""
|
@@ -279,7 +279,7 @@ class Geography(StrEnum):
|
|
279
279
|
* ZM: Zambia
|
280
280
|
* ZW: Zimbabwe
|
281
281
|
|
282
|
-
USA and Canada
|
282
|
+
USA states and Canada provinces, see https://en.wikipedia.org/wiki/ISO_3166-1:
|
283
283
|
|
284
284
|
* CA-AB: Alberta, Canada
|
285
285
|
* CA-BC: British Columbia, Canada
|
@@ -681,12 +681,15 @@ class WithLciaMixin(BaseOpenEpdSchema):
|
|
681
681
|
"""Mixin for LCIA data."""
|
682
682
|
|
683
683
|
impacts: Impacts | None = pyd.Field(
|
684
|
-
description="List of environmental impacts, compiled per one of the standard Impact Assessment methods"
|
684
|
+
description="List of environmental impacts, compiled per one of the standard Impact Assessment methods",
|
685
|
+
example={"TRACI 2.1": {"gwp": {"A1A2A3": {"mean": 22.4, "unit": "kgCO2e"}}}},
|
685
686
|
)
|
686
687
|
resource_uses: ResourceUseSet | None = pyd.Field(
|
687
|
-
description="Set of Resource Use Indicators, over various LCA scopes"
|
688
|
+
description="Set of Resource Use Indicators, over various LCA scopes",
|
689
|
+
example={"RPRe": {"A1A2A3": {"mean": 12, "unit": "MJ", "rsd": 0.12}}},
|
688
690
|
)
|
689
691
|
output_flows: OutputFlowSet | None = pyd.Field(
|
690
692
|
description="Set of Waste and Output Flow indicators which describe the waste categories "
|
691
|
-
"and other material output flows derived from the LCI."
|
693
|
+
"and other material output flows derived from the LCI.",
|
694
|
+
example={"hwd": {"A1A2A3": {"mean": 2300, "unit": "kg", "rsd": 0.22}}},
|
692
695
|
)
|
@@ -69,7 +69,6 @@ class Plant(WithAttachmentsMixin, WithAltIdsMixin, BaseOpenEpdSchema):
|
|
69
69
|
description="Plus code (aka Open Location Code) of plant's location and "
|
70
70
|
"owner's web domain joined with `.`(dot).",
|
71
71
|
example="865P2W3V+3W.interface.com",
|
72
|
-
alias="pluscode",
|
73
72
|
default=None,
|
74
73
|
)
|
75
74
|
owner: Org | None = pyd.Field(description="Organization that owns the plant", default=None)
|
@@ -91,12 +91,12 @@ class Pcr(WithAttachmentsMixin, WithAltIdsMixin, BaseOpenEpdSchema):
|
|
91
91
|
default=None,
|
92
92
|
)
|
93
93
|
date_of_issue: datetime.datetime | None = pyd.Field(
|
94
|
-
example=datetime.
|
94
|
+
example=datetime.datetime(day=11, month=9, year=2019, tzinfo=datetime.timezone.utc),
|
95
95
|
default=None,
|
96
96
|
description="First day on which the document is valid",
|
97
97
|
)
|
98
98
|
valid_until: datetime.datetime | None = pyd.Field(
|
99
|
-
example=datetime.
|
99
|
+
example=datetime.datetime(day=11, month=9, year=2019, tzinfo=datetime.timezone.utc),
|
100
100
|
default=None,
|
101
101
|
description="Last day on which the document is valid",
|
102
102
|
)
|
@@ -0,0 +1,45 @@
|
|
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
|
+
|
17
|
+
1. Minor versions for the same major version should be backwards compatible.
|
18
|
+
2. Major versions are not compatible between themselves.
|
19
|
+
3. Pydantic models representing versions are named in a pattern SpecNameV1, where 1 is major version and SpecName is
|
20
|
+
the name of the material extension.
|
21
|
+
|
22
|
+
## Range specs
|
23
|
+
|
24
|
+
Normal EPDs get singular specs (e.g. `SteelV1`). Single specs can express performance parameters of one concrete
|
25
|
+
material/EPD. However, the IndustryEDPs and Generic Estimates often cover a specific segment of the market, and
|
26
|
+
include a range of products under the hood, thus demanding for ranges. For example, a single EPD has one `strength_28d`
|
27
|
+
of `4000 psi`, but an industry EPD can be applicable to certain concretes in the range of `4000 psi` to `5000 psi`.
|
28
|
+
|
29
|
+
Range specs are used to express that. Range specs are located in `specs.range` package, and are auto-generated from the
|
30
|
+
single specs, please see `make codegen` command and `tools/openepd/codegen/generate_range_spec_models.py`
|
31
|
+
|
32
|
+
Range specs are created by following general rules:
|
33
|
+
|
34
|
+
1. A QuantityStr (such as `QuantityMassKg`) becomes an `AmountRange` of certain type - `AmountRangeMass`
|
35
|
+
2. Float -> RangeFloat, Ratio -> RatioRange, int -> IntRange
|
36
|
+
3. Enums become lists of enums, for example: `cable_trays_material: enums.CableTrayMaterial` in normal spec becomes a
|
37
|
+
`cable_trays_material: list[enums.CabeTrayMaterial]` in the range spec.
|
38
|
+
4. Complex objects, strings remain unchanged.
|
39
|
+
|
40
|
+
This is, however, not always desired. For example, `recarbonation: float` and `recarbonation_z: float` property of CMU
|
41
|
+
should not be converted to ranges as these do not make sense.
|
42
|
+
|
43
|
+
The default rule-base behaviour can be overridden with the
|
44
|
+
`CodeGenSpec` class annotation like this: `recarbonation: Annotated[float, CodeGenSpec(override_type=float)]` in single
|
45
|
+
spec to make RangeSpec have normal `float` type.
|
@@ -19,7 +19,7 @@ from openepd.compat.pydantic import pyd
|
|
19
19
|
from openepd.model.common import OpenEPDUnit
|
20
20
|
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
21
21
|
from openepd.model.validation.numbers import RatioFloat
|
22
|
-
from openepd.model.validation.quantity import LengthMmStr, TemperatureCStr,
|
22
|
+
from openepd.model.validation.quantity import LengthMmStr, TemperatureCStr, validate_quantity_unit_factory
|
23
23
|
|
24
24
|
|
25
25
|
class AsphaltMixType(StrEnum):
|
@@ -79,5 +79,5 @@ class AsphaltV1(BaseOpenEpdHierarchicalSpec):
|
|
79
79
|
asphalt_pmb: bool | None = pyd.Field(default=None, description="Polymer modified bitumen (PMB)")
|
80
80
|
|
81
81
|
_aggregate_size_max_validator = pyd.validator("asphalt_aggregate_size_max", allow_reuse=True)(
|
82
|
-
|
82
|
+
validate_quantity_unit_factory(OpenEPDUnit.m)
|
83
83
|
)
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
|
+
import dataclasses
|
16
17
|
from typing import Any
|
17
18
|
|
18
19
|
from openepd.compat.pydantic import pyd
|
@@ -51,3 +52,15 @@ class BaseOpenEpdHierarchicalSpec(BaseOpenEpdSpec, WithExtVersionMixin):
|
|
51
52
|
def setup_external_validators(quantity_validator: QuantityValidator):
|
52
53
|
"""Set the implementation unit validator for specs."""
|
53
54
|
ExternalValidationConfig.QUANTITY_VALIDATOR = quantity_validator
|
55
|
+
|
56
|
+
|
57
|
+
@dataclasses.dataclass(kw_only=True)
|
58
|
+
class CodegenSpec:
|
59
|
+
"""
|
60
|
+
Specification for codegen when generating RangeSpecs from normal specs.
|
61
|
+
|
62
|
+
See openepd.mode.specs.README.md for details.
|
63
|
+
"""
|
64
|
+
|
65
|
+
exclude_from_codegen: bool = False
|
66
|
+
override_type: type
|
@@ -0,0 +1,95 @@
|
|
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
|
+
|
17
|
+
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
18
|
+
from openepd.model.specs.generated.accessories import AccessoriesV1
|
19
|
+
from openepd.model.specs.generated.aggregates import AggregatesV1
|
20
|
+
from openepd.model.specs.generated.aluminium import AluminiumV1
|
21
|
+
from openepd.model.specs.generated.asphalt import AsphaltV1
|
22
|
+
from openepd.model.specs.generated.bulk_materials import BulkMaterialsV1
|
23
|
+
from openepd.model.specs.generated.cast_decks_and_underlayment import CastDecksAndUnderlaymentV1
|
24
|
+
from openepd.model.specs.generated.cladding import CladdingV1
|
25
|
+
from openepd.model.specs.generated.cmu import CMUV1
|
26
|
+
from openepd.model.specs.generated.concrete import ConcreteV1
|
27
|
+
from openepd.model.specs.generated.conveying_equipment import ConveyingEquipmentV1
|
28
|
+
from openepd.model.specs.generated.electrical import ElectricalV1
|
29
|
+
from openepd.model.specs.generated.electrical_transmission_and_distribution_equipment import (
|
30
|
+
ElectricalTransmissionAndDistributionEquipmentV1,
|
31
|
+
)
|
32
|
+
from openepd.model.specs.generated.electricity import ElectricityV1
|
33
|
+
from openepd.model.specs.generated.finishes import FinishesV1
|
34
|
+
from openepd.model.specs.generated.fire_and_smoke_protection import FireAndSmokeProtectionV1
|
35
|
+
from openepd.model.specs.generated.furnishings import FurnishingsV1
|
36
|
+
from openepd.model.specs.generated.grouting import GroutingV1
|
37
|
+
from openepd.model.specs.generated.manufacturing_inputs import ManufacturingInputsV1
|
38
|
+
from openepd.model.specs.generated.masonry import MasonryV1
|
39
|
+
from openepd.model.specs.generated.material_handling import MaterialHandlingV1
|
40
|
+
from openepd.model.specs.generated.mechanical import MechanicalV1
|
41
|
+
from openepd.model.specs.generated.mechanical_insulation import MechanicalInsulationV1
|
42
|
+
from openepd.model.specs.generated.network_infrastructure import NetworkInfrastructureV1
|
43
|
+
from openepd.model.specs.generated.openings import OpeningsV1
|
44
|
+
from openepd.model.specs.generated.other_electrical_equipment import OtherElectricalEquipmentV1
|
45
|
+
from openepd.model.specs.generated.other_materials import OtherMaterialsV1
|
46
|
+
from openepd.model.specs.generated.plumbing import PlumbingV1
|
47
|
+
from openepd.model.specs.generated.precast_concrete import PrecastConcreteV1
|
48
|
+
from openepd.model.specs.generated.sheathing import SheathingV1
|
49
|
+
from openepd.model.specs.generated.steel import SteelV1
|
50
|
+
from openepd.model.specs.generated.thermal_moisture_protection import ThermalMoistureProtectionV1
|
51
|
+
from openepd.model.specs.generated.utility_piping import UtilityPipingV1
|
52
|
+
from openepd.model.specs.generated.wood import WoodV1
|
53
|
+
from openepd.model.specs.generated.wood_joists import WoodJoistsV1
|
54
|
+
|
55
|
+
|
56
|
+
class Specs(BaseOpenEpdHierarchicalSpec):
|
57
|
+
"""Material specific specs."""
|
58
|
+
|
59
|
+
_EXT_VERSION = "1.0"
|
60
|
+
|
61
|
+
# Nested specs:
|
62
|
+
CMU: CMUV1 | None = None
|
63
|
+
Masonry: MasonryV1 | None = None
|
64
|
+
Steel: SteelV1 | None = None
|
65
|
+
NetworkInfrastructure: NetworkInfrastructureV1 | None = None
|
66
|
+
Finishes: FinishesV1 | None = None
|
67
|
+
ManufacturingInputs: ManufacturingInputsV1 | None = None
|
68
|
+
Accessories: AccessoriesV1 | None = None
|
69
|
+
ElectricalTransmissionAndDistributionEquipment: ElectricalTransmissionAndDistributionEquipmentV1 | None = None
|
70
|
+
Aggregates: AggregatesV1 | None = None
|
71
|
+
ThermalMoistureProtection: ThermalMoistureProtectionV1 | None = None
|
72
|
+
Mechanical: MechanicalV1 | None = None
|
73
|
+
Aluminium: AluminiumV1 | None = None
|
74
|
+
Cladding: CladdingV1 | None = None
|
75
|
+
FireAndSmokeProtection: FireAndSmokeProtectionV1 | None = None
|
76
|
+
PrecastConcrete: PrecastConcreteV1 | None = None
|
77
|
+
Asphalt: AsphaltV1 | None = None
|
78
|
+
OtherMaterials: OtherMaterialsV1 | None = None
|
79
|
+
Plumbing: PlumbingV1 | None = None
|
80
|
+
Electrical: ElectricalV1 | None = None
|
81
|
+
UtilityPiping: UtilityPipingV1 | None = None
|
82
|
+
BulkMaterials: BulkMaterialsV1 | None = None
|
83
|
+
CastDecksAndUnderlayment: CastDecksAndUnderlaymentV1 | None = None
|
84
|
+
Concrete: ConcreteV1 | None = None
|
85
|
+
Sheathing: SheathingV1 | None = None
|
86
|
+
Furnishings: FurnishingsV1 | None = None
|
87
|
+
Wood: WoodV1 | None = None
|
88
|
+
ConveyingEquipment: ConveyingEquipmentV1 | None = None
|
89
|
+
MaterialHandling: MaterialHandlingV1 | None = None
|
90
|
+
Openings: OpeningsV1 | None = None
|
91
|
+
Electricity: ElectricityV1 | None = None
|
92
|
+
Grouting: GroutingV1 | None = None
|
93
|
+
MechanicalInsulation: MechanicalInsulationV1 | None = None
|
94
|
+
OtherElectricalEquipment: OtherElectricalEquipmentV1 | None = None
|
95
|
+
WoodJoists: WoodJoistsV1 | None = None
|
@@ -16,7 +16,7 @@
|
|
16
16
|
from openepd.compat.pydantic import pyd
|
17
17
|
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
18
18
|
from openepd.model.specs.generated.enums import CladdingFacingMaterial, CladdingInsulatingMaterial, SidingFormFactor
|
19
|
-
from openepd.model.validation.quantity import LengthMmStr, LengthMStr, RValueStr,
|
19
|
+
from openepd.model.validation.quantity import LengthMmStr, LengthMStr, RValueStr, validate_quantity_unit_factory
|
20
20
|
|
21
21
|
|
22
22
|
class AluminiumSidingV1(BaseOpenEpdHierarchicalSpec):
|
@@ -75,7 +75,7 @@ class InsulatedVinylSidingV1(BaseOpenEpdHierarchicalSpec):
|
|
75
75
|
thickness: LengthMmStr | None = pyd.Field(default=None, description="", example="1 mm")
|
76
76
|
|
77
77
|
_vinyl_siding_thickness_is_quantity_validator = pyd.validator("thickness", allow_reuse=True)(
|
78
|
-
|
78
|
+
validate_quantity_unit_factory("m")
|
79
79
|
)
|
80
80
|
|
81
81
|
|
@@ -109,7 +109,7 @@ class VinylSidingV1(BaseOpenEpdHierarchicalSpec):
|
|
109
109
|
thickness: LengthMmStr | None = pyd.Field(default=None, description="", example="5 mm")
|
110
110
|
|
111
111
|
_vinyl_siding_thickness_is_quantity_validator = pyd.validator("thickness", allow_reuse=True)(
|
112
|
-
|
112
|
+
validate_quantity_unit_factory("m")
|
113
113
|
)
|
114
114
|
|
115
115
|
|
@@ -191,7 +191,7 @@ class CladdingV1(BaseOpenEpdHierarchicalSpec):
|
|
191
191
|
thickness: LengthMStr | None = pyd.Field(default=None, description="", example="10 mm")
|
192
192
|
facing_material: CladdingFacingMaterial | None = pyd.Field(default=None, description="", example="Steel")
|
193
193
|
|
194
|
-
_thickness_is_quantity_validator = pyd.validator("thickness", allow_reuse=True)(
|
194
|
+
_thickness_is_quantity_validator = pyd.validator("thickness", allow_reuse=True)(validate_quantity_unit_factory("m"))
|
195
195
|
|
196
196
|
# Nested specs:
|
197
197
|
Siding: SidingV1 | None = None
|
@@ -13,10 +13,10 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
|
-
from typing import Literal
|
16
|
+
from typing import Annotated, Literal
|
17
17
|
|
18
18
|
from openepd.compat.pydantic import pyd
|
19
|
-
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
19
|
+
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec, CodegenSpec
|
20
20
|
from openepd.model.specs.concrete import Cementitious, ConcreteTypicalApplication
|
21
21
|
from openepd.model.specs.generated.enums import AciExposureClass, CsaExposureClass, EnExposureClass
|
22
22
|
from openepd.model.validation.numbers import RatioFloat
|
@@ -25,7 +25,7 @@ from openepd.model.validation.quantity import (
|
|
25
25
|
LengthMmStr,
|
26
26
|
MassKgStr,
|
27
27
|
PressureMPaStr,
|
28
|
-
|
28
|
+
validate_quantity_unit_factory,
|
29
29
|
)
|
30
30
|
|
31
31
|
|
@@ -53,7 +53,7 @@ class ConcretePavingV1(BaseOpenEpdHierarchicalSpec):
|
|
53
53
|
)
|
54
54
|
|
55
55
|
_concrete_flexion_strength_is_quantity_validator = pyd.validator("flexion_strength", allow_reuse=True)(
|
56
|
-
|
56
|
+
validate_quantity_unit_factory("MPa")
|
57
57
|
)
|
58
58
|
|
59
59
|
|
@@ -119,9 +119,10 @@ class ConcreteV1(BaseOpenEpdHierarchicalSpec):
|
|
119
119
|
description="A strength spec which is to be reached later other 28 days (e.g. 42d)",
|
120
120
|
example="30 MPa",
|
121
121
|
)
|
122
|
-
strength_other_d:
|
123
|
-
|
124
|
-
|
122
|
+
strength_other_d: Annotated[
|
123
|
+
Literal[3, 7, 14, 42, 56, 72, 96, 120] | None,
|
124
|
+
CodegenSpec(override_type=Literal[3, 7, 14, 42, 56, 72, 96, 120]),
|
125
|
+
] = pyd.Field(default=None, description="Test Day for strength_other", example=42)
|
125
126
|
|
126
127
|
slump: LengthInchStr | None = pyd.Field(default=None, description="", example="2 in")
|
127
128
|
min_slump: LengthInchStr | None = pyd.Field(default=None, description="Minimum test slump", example="2 in")
|
@@ -26,7 +26,7 @@ from openepd.model.validation.quantity import (
|
|
26
26
|
PowerStr,
|
27
27
|
validate_quantity_ge_factory,
|
28
28
|
validate_quantity_le_factory,
|
29
|
-
|
29
|
+
validate_quantity_unit_factory,
|
30
30
|
)
|
31
31
|
|
32
32
|
|
@@ -268,7 +268,7 @@ class LightingV1(BaseOpenEpdHierarchicalSpec):
|
|
268
268
|
validate_quantity_le_factory("1E+04 K")
|
269
269
|
)
|
270
270
|
_typical_utilization_unit_validator = pyd.validator("typical_utilization", allow_reuse=True)(
|
271
|
-
|
271
|
+
validate_quantity_unit_factory("h / yr")
|
272
272
|
)
|
273
273
|
_typical_utilization_quantity_ge_validator = pyd.validator("typical_utilization", allow_reuse=True)(
|
274
274
|
validate_quantity_ge_factory("25 h / yr")
|
@@ -52,7 +52,7 @@ from openepd.model.validation.quantity import (
|
|
52
52
|
PressureMPaStr,
|
53
53
|
validate_quantity_ge_factory,
|
54
54
|
validate_quantity_le_factory,
|
55
|
-
|
55
|
+
validate_quantity_unit_factory,
|
56
56
|
)
|
57
57
|
|
58
58
|
|
@@ -85,10 +85,10 @@ class AccessFlooringV1(BaseOpenEpdHierarchicalSpec):
|
|
85
85
|
|
86
86
|
_access_flooring_rolling_load_10_pass_is_quantity_validator = pyd.validator(
|
87
87
|
"rolling_load_10_pass", allow_reuse=True
|
88
|
-
)(
|
88
|
+
)(validate_quantity_unit_factory("N"))
|
89
89
|
_access_flooring_rolling_load_10000_pass_is_quantity_validator = pyd.validator(
|
90
90
|
"rolling_load_10000_pass", allow_reuse=True
|
91
|
-
)(
|
91
|
+
)(validate_quantity_unit_factory("N"))
|
92
92
|
|
93
93
|
|
94
94
|
class CarpetV1(BaseOpenEpdHierarchicalSpec):
|
@@ -114,7 +114,9 @@ class CarpetV1(BaseOpenEpdHierarchicalSpec):
|
|
114
114
|
gwp_factor_base: GwpKgCo2eStr | None = pyd.Field(default=None, description="", example="1 kgCO2e")
|
115
115
|
gwp_factor_yarn: GwpKgCo2eStr | None = pyd.Field(default=None, description="", example="1 kgCO2e")
|
116
116
|
|
117
|
-
_yarn_weight_is_quantity_validator = pyd.validator("yarn_weight", allow_reuse=True)(
|
117
|
+
_yarn_weight_is_quantity_validator = pyd.validator("yarn_weight", allow_reuse=True)(
|
118
|
+
validate_quantity_unit_factory("g / m2")
|
119
|
+
)
|
118
120
|
_yarn_weight_ge_validator = pyd.validator("yarn_weight", allow_reuse=True)(validate_quantity_ge_factory("0 g / m2"))
|
119
121
|
|
120
122
|
|
@@ -348,7 +350,7 @@ class CementBoardV1(BaseOpenEpdHierarchicalSpec):
|
|
348
350
|
)
|
349
351
|
|
350
352
|
_cement_board_thickness_is_quantity_validator = pyd.validator("thickness", allow_reuse=True)(
|
351
|
-
|
353
|
+
validate_quantity_unit_factory("m")
|
352
354
|
)
|
353
355
|
|
354
356
|
|
@@ -456,7 +458,9 @@ class GypsumV1(BaseOpenEpdHierarchicalSpec):
|
|
456
458
|
moisture_resistant: bool | None = pyd.Field(default=None, description="", example=True)
|
457
459
|
abuse_resistant: bool | None = pyd.Field(default=None, description="", example=True)
|
458
460
|
|
459
|
-
_gypsum_r_factor_is_quantity_validator = pyd.validator("r_factor", allow_reuse=True)(
|
461
|
+
_gypsum_r_factor_is_quantity_validator = pyd.validator("r_factor", allow_reuse=True)(
|
462
|
+
validate_quantity_unit_factory("RSI")
|
463
|
+
)
|
460
464
|
|
461
465
|
# Nested specs:
|
462
466
|
GypsumSupports: GypsumSupportsV1 | None = None
|
@@ -15,7 +15,11 @@
|
|
15
15
|
#
|
16
16
|
from openepd.compat.pydantic import pyd
|
17
17
|
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
18
|
-
from openepd.model.validation.quantity import
|
18
|
+
from openepd.model.validation.quantity import (
|
19
|
+
PressureMPaStr,
|
20
|
+
validate_quantity_ge_factory,
|
21
|
+
validate_quantity_unit_factory,
|
22
|
+
)
|
19
23
|
|
20
24
|
|
21
25
|
class GMUV1(BaseOpenEpdHierarchicalSpec):
|
@@ -35,7 +39,7 @@ class AutoclavedAeratedConcreteV1(BaseOpenEpdHierarchicalSpec):
|
|
35
39
|
white: bool | None = pyd.Field(default=None, description="", example=True)
|
36
40
|
|
37
41
|
_aac_thermal_conductivity_is_quantity_validator = pyd.validator("thermal_conductivity", allow_reuse=True)(
|
38
|
-
|
42
|
+
validate_quantity_unit_factory("W / (m * K)")
|
39
43
|
)
|
40
44
|
|
41
45
|
_aac_thermal_conductivity_min_validator = pyd.validator("thermal_conductivity", allow_reuse=True)(
|
@@ -28,7 +28,12 @@ from openepd.model.specs.generated.enums import (
|
|
28
28
|
RackType,
|
29
29
|
)
|
30
30
|
from openepd.model.specs.generated.mixins.conduit_mixin import ConduitMixin
|
31
|
-
from openepd.model.validation.quantity import
|
31
|
+
from openepd.model.validation.quantity import (
|
32
|
+
ElectricalCurrentStr,
|
33
|
+
LengthMmStr,
|
34
|
+
MassKgStr,
|
35
|
+
validate_quantity_unit_factory,
|
36
|
+
)
|
32
37
|
|
33
38
|
|
34
39
|
class PDUV1(BaseOpenEpdHierarchicalSpec):
|
@@ -43,7 +48,7 @@ class PDUV1(BaseOpenEpdHierarchicalSpec):
|
|
43
48
|
pdu_technology: PduTechnology | None = pyd.Field(default=None, description="", example="Basic")
|
44
49
|
pdu_outlets: int | None = pyd.Field(default=None, description="", example=3, le=200)
|
45
50
|
|
46
|
-
_amperage_is_quantity_validator = pyd.validator("amperage", allow_reuse=True)(
|
51
|
+
_amperage_is_quantity_validator = pyd.validator("amperage", allow_reuse=True)(validate_quantity_unit_factory("A"))
|
47
52
|
|
48
53
|
|
49
54
|
class CabinetsRacksAndEnclosuresV1(BaseOpenEpdHierarchicalSpec):
|
@@ -26,7 +26,7 @@ from openepd.model.specs.generated.enums import (
|
|
26
26
|
ThermalSeparation,
|
27
27
|
)
|
28
28
|
from openepd.model.validation.numbers import RatioFloat
|
29
|
-
from openepd.model.validation.quantity import LengthMmStr, PressureMPaStr, SpeedStr,
|
29
|
+
from openepd.model.validation.quantity import LengthMmStr, PressureMPaStr, SpeedStr, validate_quantity_unit_factory
|
30
30
|
|
31
31
|
|
32
32
|
class GlazingIntendedApplication(BaseOpenEpdSchema):
|
@@ -197,7 +197,7 @@ class FlatGlassPanesV1(BaseOpenEpdHierarchicalSpec):
|
|
197
197
|
thickness: FlatGlassPanesThickness | None = pyd.Field(default=None, example="12 mm")
|
198
198
|
|
199
199
|
_flat_glass_panes_thickness_is_quantity_validator = pyd.validator("thickness", allow_reuse=True)(
|
200
|
-
|
200
|
+
validate_quantity_unit_factory("m")
|
201
201
|
)
|
202
202
|
|
203
203
|
|
@@ -380,10 +380,10 @@ class NAFSFenestrationV1(BaseOpenEpdHierarchicalSpec, GlazingOptionsMixin):
|
|
380
380
|
)
|
381
381
|
|
382
382
|
_assembly_u_factor_is_quantity_validator = pyd.validator("assembly_u_factor", allow_reuse=True)(
|
383
|
-
|
383
|
+
validate_quantity_unit_factory("USI")
|
384
384
|
)
|
385
385
|
_nafs_performance_grade_is_quantity_validator = pyd.validator("performance_grade", allow_reuse=True)(
|
386
|
-
|
386
|
+
validate_quantity_unit_factory("psf")
|
387
387
|
)
|
388
388
|
|
389
389
|
# Nested specs:
|
@@ -424,8 +424,12 @@ class InsulatingGlazingUnitsV1(BaseOpenEpdHierarchicalSpec, GlazingOptionsMixin)
|
|
424
424
|
default=None, description="Spacer material for Integrated Glass Unit.", example="Aluminium"
|
425
425
|
)
|
426
426
|
|
427
|
-
_dp_rating_is_quantity_validator = pyd.validator("dp_rating", allow_reuse=True)(
|
428
|
-
|
427
|
+
_dp_rating_is_quantity_validator = pyd.validator("dp_rating", allow_reuse=True)(
|
428
|
+
validate_quantity_unit_factory("MPa")
|
429
|
+
)
|
430
|
+
_cog_u_factor_is_quantity_validator = pyd.validator("cog_u_factor", allow_reuse=True)(
|
431
|
+
validate_quantity_unit_factory("USI")
|
432
|
+
)
|
429
433
|
|
430
434
|
|
431
435
|
class CurtainWallsV1(BaseOpenEpdHierarchicalSpec):
|