openepd 6.4.1__py3-none-any.whl → 6.5.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/__version__.py +1 -1
- openepd/model/lcia.py +11 -3
- openepd/model/specs/concrete.py +0 -91
- openepd/model/specs/singular/__init__.py +43 -1
- openepd/model/specs/singular/deprecated/__init__.py +79 -0
- openepd/model/specs/singular/deprecated/concrete.py +100 -0
- openepd/model/specs/singular/deprecated/steel.py +75 -0
- openepd/model/validation/quantity.py +1 -1
- {openepd-6.4.1.dist-info → openepd-6.5.0.dist-info}/METADATA +1 -1
- {openepd-6.4.1.dist-info → openepd-6.5.0.dist-info}/RECORD +12 -9
- {openepd-6.4.1.dist-info → openepd-6.5.0.dist-info}/LICENSE +0 -0
- {openepd-6.4.1.dist-info → openepd-6.5.0.dist-info}/WHEEL +0 -0
openepd/__version__.py
CHANGED
openepd/model/lcia.py
CHANGED
@@ -206,9 +206,17 @@ class ScopeSet(BaseOpenEpdSchema):
|
|
206
206
|
if isinstance(v, Measurement):
|
207
207
|
all_units.add(v.unit)
|
208
208
|
|
209
|
-
|
210
|
-
|
211
|
-
|
209
|
+
if not cls.allowed_units:
|
210
|
+
# For unknown units - only units should be the same across all measurements (textually)
|
211
|
+
if len(all_units) > 1:
|
212
|
+
raise ValueError("All scopes and measurements should be expressed in the same unit.")
|
213
|
+
else:
|
214
|
+
# might be multiple variations of the same unit (kgCFC-11e, kgCFC11e)
|
215
|
+
if len(all_units) > 1 and ExternalValidationConfig.QUANTITY_VALIDATOR:
|
216
|
+
all_units_list = list(all_units)
|
217
|
+
first = all_units_list[0]
|
218
|
+
for unit in all_units_list[1:]:
|
219
|
+
ExternalValidationConfig.QUANTITY_VALIDATOR.validate_same_dimensionality(first, unit)
|
212
220
|
|
213
221
|
# can correctly validate unit
|
214
222
|
if cls.allowed_units is not None and len(all_units) == 1 and ExternalValidationConfig.QUANTITY_VALIDATOR:
|
openepd/model/specs/concrete.py
CHANGED
@@ -13,7 +13,6 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
|
-
from enum import StrEnum
|
17
16
|
|
18
17
|
from openepd.compat.pydantic import pyd
|
19
18
|
from openepd.model.base import BaseOpenEpdSchema
|
@@ -21,56 +20,6 @@ from openepd.model.specs.base import BaseOpenEpdSpec
|
|
21
20
|
from openepd.model.validation.numbers import RatioFloat
|
22
21
|
|
23
22
|
|
24
|
-
class CmuWeightClassification(StrEnum):
|
25
|
-
"""Concrete Masonry Unit weight classification."""
|
26
|
-
|
27
|
-
Normal = "Normal"
|
28
|
-
"""Normal weight CMU has a density of 125 lbs/cu. ft."""
|
29
|
-
Medium = "Medium"
|
30
|
-
"""Medium weight CMU has a density of 105-125 lbs/cu. ft."""
|
31
|
-
Light = "Light"
|
32
|
-
"""Lightweight CMU has a density less than 105 lbs/cu. ft."""
|
33
|
-
|
34
|
-
|
35
|
-
class CmuOptions(BaseOpenEpdSchema):
|
36
|
-
"""Concrete Masonry Unit options."""
|
37
|
-
|
38
|
-
load_bearing: bool | None = pyd.Field(
|
39
|
-
description="Load-Bearing. CMUs intended to be loadbearing, rather than simply cosmetic",
|
40
|
-
example=True,
|
41
|
-
default=None,
|
42
|
-
)
|
43
|
-
aerated_concrete: bool | None = pyd.Field(
|
44
|
-
description="AAC Aerated Concrete. Aerated Autoclaved Concrete, a foam concrete.", example=True, default=None
|
45
|
-
)
|
46
|
-
insulated: bool | None = pyd.Field(
|
47
|
-
description="Insulated. CMUs with integral insulation", example=True, default=None
|
48
|
-
)
|
49
|
-
sound_absorbing: bool | None = pyd.Field(
|
50
|
-
description="Sound Absorbing. CMUs structured for sound absorbtion", example=True, default=None
|
51
|
-
)
|
52
|
-
white: bool | None = pyd.Field(
|
53
|
-
description="White. CMU using white cement and light-colored aggregate", example=True, default=None
|
54
|
-
)
|
55
|
-
recycled_aggregate: bool | None = pyd.Field(
|
56
|
-
description="Recycled aggregate. CMU using primarily reycled aggregates", example=True, default=None
|
57
|
-
)
|
58
|
-
groundface: bool | None = pyd.Field(
|
59
|
-
description="Ground Face. Ground or Honed facing, typically for improved appearance", example=True, default=None
|
60
|
-
)
|
61
|
-
splitface: bool | None = pyd.Field(
|
62
|
-
description="Splitface. Rough surface texture via splitting; aggregate can be seen", example=True, default=None
|
63
|
-
)
|
64
|
-
smoothface: bool | None = pyd.Field(
|
65
|
-
description="Smooth Face. Standard smooth-faced blocks", example=True, default=None
|
66
|
-
)
|
67
|
-
slumpstone: bool | None = pyd.Field(
|
68
|
-
description="Slumpstone. A slightly rounded, random distortion with the look of rustic adobe.",
|
69
|
-
example=True,
|
70
|
-
default=None,
|
71
|
-
)
|
72
|
-
|
73
|
-
|
74
23
|
class ConcreteTypicalApplication(BaseOpenEpdSpec):
|
75
24
|
"""Typical Application for Concrete."""
|
76
25
|
|
@@ -138,15 +87,6 @@ class ConcreteTypicalApplication(BaseOpenEpdSpec):
|
|
138
87
|
)
|
139
88
|
|
140
89
|
|
141
|
-
class CmuSpec(BaseOpenEpdSpec):
|
142
|
-
"""Standardized Concrete Masonry Unit-specific extension for OpenEPD."""
|
143
|
-
|
144
|
-
strength: str = pyd.Field(description="Compressive strength", example="4000 psi")
|
145
|
-
options: CmuOptions = pyd.Field(
|
146
|
-
description="Options for CMU. List of true/false properties", default_factory=CmuOptions
|
147
|
-
)
|
148
|
-
|
149
|
-
|
150
90
|
class Cementitious(BaseOpenEpdSchema):
|
151
91
|
"""List of cementitious materials, and proportion by mass."""
|
152
92
|
|
@@ -168,34 +108,3 @@ class Cementitious(BaseOpenEpdSchema):
|
|
168
108
|
mk: RatioFloat | None = pyd.Field(default=None, description="Metakaolin", example=0.5, ge=0, le=1)
|
169
109
|
CaCO3: RatioFloat | None = pyd.Field(default=None, description="Limestone", example=0.5, ge=0, le=1)
|
170
110
|
other: RatioFloat | None = pyd.Field(default=None, description="Other SCMs", example=0.5, ge=0, le=1)
|
171
|
-
|
172
|
-
|
173
|
-
class TypicalApplication(BaseOpenEpdSchema):
|
174
|
-
"""Concrete typical application."""
|
175
|
-
|
176
|
-
fnd: bool | None = pyd.Field(description="Foundation", default=None)
|
177
|
-
sog: bool | None = pyd.Field(description="Slab on Grade", default=None)
|
178
|
-
hrz: bool | None = pyd.Field(description="Elevated Horizontal", default=None)
|
179
|
-
vrt_wall: bool | None = pyd.Field(description="Vertical Wall", default=None)
|
180
|
-
vrt_column: bool | None = pyd.Field(description="Vertical Column", default=None)
|
181
|
-
vrt_other: bool | None = pyd.Field(description="Vertical Other", default=None)
|
182
|
-
sht: bool | None = pyd.Field(description="Shotcrete", default=None)
|
183
|
-
cdf: bool | None = pyd.Field(description="Flowable Fill (CDF,default=None)", default=None)
|
184
|
-
sac: bool | None = pyd.Field(description="Sidewalk and Curb", default=None)
|
185
|
-
pav: bool | None = pyd.Field(description="Paving", default=None)
|
186
|
-
oil: bool | None = pyd.Field(description="Oil Patch", default=None)
|
187
|
-
grt: bool | None = pyd.Field(description="Cement Grout", default=None)
|
188
|
-
ota: bool | None = pyd.Field(description="Other", default=None)
|
189
|
-
|
190
|
-
|
191
|
-
class ConcreteV1Options(BaseOpenEpdSchema):
|
192
|
-
"""Concrete options."""
|
193
|
-
|
194
|
-
lightweight: bool | None = pyd.Field(description="Lightweight", default=None)
|
195
|
-
plc: bool | None = pyd.Field(description="Portland Limestone Cement", default=None)
|
196
|
-
scc: bool | None = pyd.Field(description="Self Compacting", default=None)
|
197
|
-
finishable: bool | None = pyd.Field(description="Finishable", default=None)
|
198
|
-
air: bool | None = pyd.Field(description="Air Entrainment", default=None)
|
199
|
-
co2: bool | None = pyd.Field(description="CO2 Curing", default=None)
|
200
|
-
white: bool | None = pyd.Field(description="White Cement", default=None)
|
201
|
-
fiber_reinforced: bool | None = pyd.Field(description="Fiber reinforced", default=None)
|
@@ -13,7 +13,9 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
|
-
from
|
16
|
+
from typing import Any, ClassVar
|
17
|
+
|
18
|
+
from openepd.compat.pydantic import pyd
|
17
19
|
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
18
20
|
from openepd.model.specs.singular.accessories import AccessoriesV1
|
19
21
|
from openepd.model.specs.singular.aggregates import AggregatesV1
|
@@ -25,6 +27,9 @@ from openepd.model.specs.singular.cladding import CladdingV1
|
|
25
27
|
from openepd.model.specs.singular.cmu import CMUV1
|
26
28
|
from openepd.model.specs.singular.concrete import ConcreteV1
|
27
29
|
from openepd.model.specs.singular.conveying_equipment import ConveyingEquipmentV1
|
30
|
+
from openepd.model.specs.singular.deprecated import BaseCompatibilitySpec, get_safely, set_safely
|
31
|
+
from openepd.model.specs.singular.deprecated.concrete import ConcreteOldSpec
|
32
|
+
from openepd.model.specs.singular.deprecated.steel import SteelOldSpec
|
28
33
|
from openepd.model.specs.singular.electrical import ElectricalV1
|
29
34
|
from openepd.model.specs.singular.electrical_transmission_and_distribution_equipment import (
|
30
35
|
ElectricalTransmissionAndDistributionEquipmentV1,
|
@@ -58,6 +63,8 @@ __all__ = ("Specs",)
|
|
58
63
|
class Specs(BaseOpenEpdHierarchicalSpec):
|
59
64
|
"""Material specific specs."""
|
60
65
|
|
66
|
+
COMPATIBILITY_SPECS: ClassVar[list[type[BaseCompatibilitySpec]]] = [ConcreteOldSpec, SteelOldSpec]
|
67
|
+
|
61
68
|
_EXT_VERSION = "1.0"
|
62
69
|
|
63
70
|
# Nested specs:
|
@@ -95,3 +102,38 @@ class Specs(BaseOpenEpdHierarchicalSpec):
|
|
95
102
|
MechanicalInsulation: MechanicalInsulationV1 | None = None
|
96
103
|
OtherElectricalEquipment: OtherElectricalEquipmentV1 | None = None
|
97
104
|
WoodJoists: WoodJoistsV1 | None = None
|
105
|
+
|
106
|
+
# historical backward-compatible specs
|
107
|
+
concrete: ConcreteOldSpec | None = None
|
108
|
+
steel: SteelOldSpec | None = None
|
109
|
+
|
110
|
+
@pyd.root_validator(pre=True)
|
111
|
+
def _ensure_backward_compatibiltiy(cls, values: dict[str, Any]) -> dict[str, Any]:
|
112
|
+
"""
|
113
|
+
Restore the functionality for backward-compatible specs.
|
114
|
+
|
115
|
+
Originally, we used to have 'concrete' and 'steel' specs non-hierarchical and manually maintained. Since we
|
116
|
+
introduced hierarchical specs, there is a need to retain the key mapping to the old structure.
|
117
|
+
|
118
|
+
:return: modified values
|
119
|
+
"""
|
120
|
+
for compat_spec in cls.COMPATIBILITY_SPECS:
|
121
|
+
if (
|
122
|
+
compat_spec.COMPATIBILITY_SPECS_KEY_OLD not in values
|
123
|
+
and compat_spec.COMPATIBILITY_SPECS_KEY_NEW not in values
|
124
|
+
):
|
125
|
+
continue
|
126
|
+
for old_key_spec, new_key_spec in compat_spec.COMPATIBILITY_MAPPING.items():
|
127
|
+
has_new_spec, new_value = get_safely(values, new_key_spec)
|
128
|
+
|
129
|
+
# new value is set, we should not override it but should return it in old spec
|
130
|
+
if has_new_spec:
|
131
|
+
set_safely(values, old_key_spec, new_value)
|
132
|
+
continue
|
133
|
+
|
134
|
+
has_old_spec, old_value = get_safely(values, old_key_spec)
|
135
|
+
# nothing to back
|
136
|
+
if not has_old_spec:
|
137
|
+
continue
|
138
|
+
set_safely(values, new_key_spec, old_value)
|
139
|
+
return values
|
@@ -0,0 +1,79 @@
|
|
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
|
+
from typing import Any, ClassVar
|
17
|
+
|
18
|
+
from openepd.compat.pydantic import pyd
|
19
|
+
from openepd.model.base import BaseOpenEpdSchema
|
20
|
+
|
21
|
+
|
22
|
+
class BaseCompatibilitySpec(BaseOpenEpdSchema):
|
23
|
+
"""
|
24
|
+
Base class for compatibility (legacy) specs.
|
25
|
+
|
26
|
+
See Specs model for implementation.
|
27
|
+
"""
|
28
|
+
|
29
|
+
COMPATIBILITY_SPECS_KEY_OLD: ClassVar[str]
|
30
|
+
COMPATIBILITY_SPECS_KEY_NEW: ClassVar[str]
|
31
|
+
COMPATIBILITY_MAPPING: ClassVar[dict[str, str]]
|
32
|
+
|
33
|
+
|
34
|
+
def get_safely(d: dict, path: str) -> tuple[bool, Any]:
|
35
|
+
"""
|
36
|
+
Get a value from a mixed object via dotted path.
|
37
|
+
|
38
|
+
Mixed object can be a combination of dicts and pydatnic Models on any hierarchy.
|
39
|
+
:param d: source dict/object to search in
|
40
|
+
:param path: dotted path in object like specs.Concrete.strength_28d
|
41
|
+
:return: tuple (WasFound, Value). First element tells if value was found, second - the value itself.
|
42
|
+
"""
|
43
|
+
path_elements = path.split(".")
|
44
|
+
current: Any = d
|
45
|
+
for p in path_elements:
|
46
|
+
match current:
|
47
|
+
case dict():
|
48
|
+
if p not in current:
|
49
|
+
return False, None
|
50
|
+
current = current.get(p)
|
51
|
+
case pyd.BaseModel() as model:
|
52
|
+
if not hasattr(current, p) or p not in model.__fields_set__:
|
53
|
+
return False, None
|
54
|
+
current = getattr(current, p)
|
55
|
+
case _:
|
56
|
+
return False, None
|
57
|
+
|
58
|
+
return True, current
|
59
|
+
|
60
|
+
|
61
|
+
def set_safely(d: dict, path: str, value: Any) -> None:
|
62
|
+
"""
|
63
|
+
Safely set an element in a dict.
|
64
|
+
|
65
|
+
Warning: this is asymmetric compared to get_safely, since it sets value in a dict, not in pydantic model object.
|
66
|
+
|
67
|
+
:param d: source dict/object to set value in
|
68
|
+
:param path: dotted path in object like specs.Concrete.strength_28d
|
69
|
+
:param value: value to set
|
70
|
+
:return: None
|
71
|
+
"""
|
72
|
+
path_elements = path.split(".")
|
73
|
+
current = d
|
74
|
+
for p in path_elements[:-1]:
|
75
|
+
if current.get(p) is None:
|
76
|
+
current[p] = {}
|
77
|
+
current = current[p]
|
78
|
+
|
79
|
+
current[path_elements[-1]] = value
|
@@ -0,0 +1,100 @@
|
|
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
|
+
from typing import ClassVar, Literal
|
17
|
+
|
18
|
+
from openepd.compat.pydantic import pyd
|
19
|
+
from openepd.model.base import BaseOpenEpdSchema
|
20
|
+
from openepd.model.specs.concrete import Cementitious, ConcreteTypicalApplication
|
21
|
+
from openepd.model.specs.enums import AciExposureClass, CsaExposureClass, EnExposureClass
|
22
|
+
from openepd.model.specs.singular import BaseCompatibilitySpec
|
23
|
+
from openepd.model.validation.numbers import RatioFloat
|
24
|
+
from openepd.model.validation.quantity import LengthInchStr, PressureMPaStr
|
25
|
+
|
26
|
+
|
27
|
+
class ConcreteOptions(BaseOpenEpdSchema):
|
28
|
+
"""Legacy Concrete options model."""
|
29
|
+
|
30
|
+
lightweight: bool | None = pyd.Field(
|
31
|
+
default=None, description="Lightweight. True if < 120lb/ft3 or 1900 kg/m3", example=True
|
32
|
+
)
|
33
|
+
scc: bool | None = pyd.Field(default=None, description="Self Compacting", example=True)
|
34
|
+
finishable: bool | None = pyd.Field(default=None, description="Finishable", example=True)
|
35
|
+
air: bool | None = pyd.Field(default=None, description="Air Entrainment", example=True)
|
36
|
+
co2_entrain: bool | None = pyd.Field(
|
37
|
+
default=None, description="CO2 Curing. Uses intentionally entrained CO2.", example=True
|
38
|
+
)
|
39
|
+
white_cement: bool | None = pyd.Field(default=None, description="White Cement", example=True)
|
40
|
+
plc: bool | None = pyd.Field(default=None, description="Portland Limestone Cement", example=True)
|
41
|
+
fiber_reinforced: bool | None = pyd.Field(default=None, description="fiber_reinforced", example=True)
|
42
|
+
|
43
|
+
|
44
|
+
class ConcreteOldSpec(BaseCompatibilitySpec):
|
45
|
+
"""Old version of the Concrete spec, please use Concrete hierarchical version instead."""
|
46
|
+
|
47
|
+
COMPATIBILITY_SPECS_KEY_OLD: ClassVar[str] = "concrete"
|
48
|
+
COMPATIBILITY_SPECS_KEY_NEW: ClassVar[str] = "Concrete"
|
49
|
+
COMPATIBILITY_MAPPING: ClassVar[dict[str, str]] = {
|
50
|
+
"concrete.strength_28d": "Concrete.strength_28d",
|
51
|
+
"concrete.slump": "Concrete.min_slump",
|
52
|
+
"concrete.strength_other": "Concrete.strength_other",
|
53
|
+
"concrete.strength_other_d": "Concrete.strength_other_d",
|
54
|
+
"concrete.w_c_ratio": "Concrete.w_c_ratio",
|
55
|
+
"concrete.aci_exposure_classes": "Concrete.aci_exposure_classes",
|
56
|
+
"concrete.csa_exposure_classes": "Concrete.csa_exposure_classes",
|
57
|
+
"concrete.en_exposure_classes": "Concrete.en_exposure_classes",
|
58
|
+
"concrete.application": "Concrete.typical_application",
|
59
|
+
"concrete.options.lightweight": "Concrete.lightweight",
|
60
|
+
"concrete.options.scc": "Concrete.self_consolidating",
|
61
|
+
"concrete.options.finishable": "Concrete.finishable",
|
62
|
+
"concrete.options.air": "Concrete.air_entrain",
|
63
|
+
"concrete.options.co2_entrain": "Concrete.co2_entrain",
|
64
|
+
"concrete.options.white_cement": "Concrete.white_cement",
|
65
|
+
"concrete.options.plc": "Concrete.plc",
|
66
|
+
"concrete.options.fiber_reinforced": "Concrete.fiber_reinforced",
|
67
|
+
"concrete.cementitious": "Concrete.cementitious",
|
68
|
+
}
|
69
|
+
|
70
|
+
strength_28d: PressureMPaStr | None = pyd.Field(
|
71
|
+
default=None, description="Compressive Strength at 28 days", example="1 MPa"
|
72
|
+
)
|
73
|
+
slump: LengthInchStr | None = pyd.Field(default=None, description="Minimum test slump", example="2 in")
|
74
|
+
strength_other: PressureMPaStr | None = pyd.Field(
|
75
|
+
default=None,
|
76
|
+
description="One additional strength, which can be early (e.g. 3d) or late (e.g. 96d)",
|
77
|
+
example="30 MPa",
|
78
|
+
)
|
79
|
+
strength_other_d: Literal[3, 7, 14, 42, 56, 72, 96, 120] | None = pyd.Field(
|
80
|
+
default=None,
|
81
|
+
description="Days for the strength field above. Required IF strength_other is provided.",
|
82
|
+
example=42,
|
83
|
+
)
|
84
|
+
w_c_ratio: RatioFloat | None = pyd.Field(
|
85
|
+
default=None, description="Ratio of water to cement", example=0.5, ge=0, le=1
|
86
|
+
)
|
87
|
+
aci_exposure_classes: list[AciExposureClass] | None = pyd.Field(
|
88
|
+
default=None, description="List of ACI318-19 exposure classes this product meets", example=["aci.F0"]
|
89
|
+
)
|
90
|
+
csa_exposure_classes: list[CsaExposureClass] | None = pyd.Field(
|
91
|
+
default=None, description="List of CSA A23.1 exposure classes this product meets", example=["csa.C-2"]
|
92
|
+
)
|
93
|
+
en_exposure_classes: list[EnExposureClass] | None = pyd.Field(
|
94
|
+
default=None, description="List of EN206 exposure classes this product meets", example=["en206.X0"]
|
95
|
+
)
|
96
|
+
application: ConcreteTypicalApplication | None = pyd.Field(default=None, description="Typical Application")
|
97
|
+
options: ConcreteOptions | None = pyd.Field(default=None, description="List of true/false properties")
|
98
|
+
cementitious: Cementitious | None = pyd.Field(
|
99
|
+
default=None, description="List of cementitious materials, and proportion by mass"
|
100
|
+
)
|
@@ -0,0 +1,75 @@
|
|
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
|
+
from typing import ClassVar
|
17
|
+
|
18
|
+
from openepd.compat.pydantic import pyd
|
19
|
+
from openepd.model.base import BaseOpenEpdSchema
|
20
|
+
from openepd.model.specs.enums import SteelComposition
|
21
|
+
from openepd.model.specs.singular import BaseCompatibilitySpec
|
22
|
+
from openepd.model.specs.singular.steel import SteelMakingRoute
|
23
|
+
from openepd.model.standard import Standard
|
24
|
+
from openepd.model.validation.quantity import PressureMPaStr
|
25
|
+
|
26
|
+
|
27
|
+
class SteelOldOptions(BaseOpenEpdSchema):
|
28
|
+
"""Legacy Steel options model."""
|
29
|
+
|
30
|
+
cold_finished: bool | None = pyd.Field(default=None, description="Cold Finished", example=True)
|
31
|
+
galvanized: bool | None = pyd.Field(default=None, description="Galvanized", example=True)
|
32
|
+
epoxy: bool | None = pyd.Field(default=None, description="Epoxy Coated", example=True)
|
33
|
+
steel_fabricated: bool | None = pyd.Field(default=None, example=True, description="Fabricated")
|
34
|
+
|
35
|
+
|
36
|
+
class SteelOldSpec(BaseCompatibilitySpec):
|
37
|
+
"""Legacy Steel spec."""
|
38
|
+
|
39
|
+
COMPATIBILITY_SPECS_KEY_OLD: ClassVar[str] = "steel"
|
40
|
+
COMPATIBILITY_SPECS_KEY_NEW: ClassVar[str] = "Steel"
|
41
|
+
COMPATIBILITY_MAPPING: ClassVar[dict[str, str]] = {
|
42
|
+
"steel.steel_composition": "Steel.composition",
|
43
|
+
"steel.Fy": "Steel.yield_tensile_str",
|
44
|
+
"steel.making_route": "Steel.making_route",
|
45
|
+
"steel.ASTM": "Steel.astm_standards",
|
46
|
+
"steel.EN": "Steel.en_standards",
|
47
|
+
"steel.SAE": "Steel.sae_standards",
|
48
|
+
"steel.options.cold_finished": "Steel.cold_finished",
|
49
|
+
"steel.options.galvanized": "Steel.galvanized",
|
50
|
+
"steel.options.epoxy": "Steel.RebarSteel.epoxy_coated", # moved to sub-spec
|
51
|
+
"steel.options.steel_fabricated": "Steel.RebarSteel.fabricated",
|
52
|
+
# last one is tricky as fabricated might be in multiple cases; thus limited support
|
53
|
+
}
|
54
|
+
form_factor: str | None = pyd.Field(default=None, description="Product's form factor, read-only.")
|
55
|
+
steel_composition: SteelComposition | None = pyd.Field(
|
56
|
+
default=None,
|
57
|
+
description="Basic chemical composition. Generally the ASTM or EN grade is a subcategory of one of these.",
|
58
|
+
example="Carbon",
|
59
|
+
)
|
60
|
+
Fy: PressureMPaStr | None = pyd.Field(
|
61
|
+
default=None,
|
62
|
+
description="Minimum Yield Strength",
|
63
|
+
example="2000 psi",
|
64
|
+
)
|
65
|
+
making_route: SteelMakingRoute | None = pyd.Field(
|
66
|
+
default=None, description="List of true/false properties for steelmaking route"
|
67
|
+
)
|
68
|
+
ASTM: list[Standard] | None = pyd.Field(
|
69
|
+
default=None, description="ASTM standard(s) to which this product complies."
|
70
|
+
)
|
71
|
+
SAE: list[Standard] | None = pyd.Field(
|
72
|
+
default=None, description="AISA/SAE standard(s) to which this product complies."
|
73
|
+
)
|
74
|
+
EN: list[Standard] | None = pyd.Field(default=None, description="EN 10027 number(s).")
|
75
|
+
options: SteelOldOptions | None = pyd.Field(default=None, description="List of true/false properties")
|
@@ -33,7 +33,7 @@ class QuantityValidator(ABC):
|
|
33
33
|
"""
|
34
34
|
|
35
35
|
@abstractmethod
|
36
|
-
def validate_same_dimensionality(self, unit: str | None, dimensionality_unit: str) -> None:
|
36
|
+
def validate_same_dimensionality(self, unit: str | None, dimensionality_unit: str | None) -> None:
|
37
37
|
"""
|
38
38
|
Validate that a given unit ('kg') has the same dimesnionality as provided dimensionality_unit ('g').
|
39
39
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
openepd/__init__.py,sha256=Shkfh0Kun0YRhmRDw7LkUj2eQL3X-HnP55u2THOEALw,794
|
2
|
-
openepd/__version__.py,sha256=
|
2
|
+
openepd/__version__.py,sha256=E9JGe31Ne_CaAyZyFDl-umPzCGdXSIR3mkEKcaJjL78,638
|
3
3
|
openepd/api/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,620
|
4
4
|
openepd/api/average_dataset/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,620
|
5
5
|
openepd/api/average_dataset/generic_estimate_sync_api.py,sha256=mxWwDokEGMe87Px8C_aHvIdVKZVHrEAuVtaSA1zJchU,7953
|
@@ -42,14 +42,14 @@ openepd/model/factory.py,sha256=XP7eeQNW5tqwX_4hfuEb3lK6BFQDb4KB0fSN0r8-lCU,2656
|
|
42
42
|
openepd/model/generic_estimate.py,sha256=bbU0cR4izSqjZcfxUHNbdO4pllqqd8OaUFikrEgCFoA,3992
|
43
43
|
openepd/model/geography.py,sha256=G3Oz3QBw5n-RiSCAv-vAGxrOZBhwIT5rASnPlo9dkcs,42095
|
44
44
|
openepd/model/industry_epd.py,sha256=rgXhCUDAgzZ9eGio7ExqE3ymP3zTXnrrwcIDvg5YP1A,3285
|
45
|
-
openepd/model/lcia.py,sha256=
|
45
|
+
openepd/model/lcia.py,sha256=a0OZQzZBtXNx_6O1jMnC1WQrlU3rdFrDN-Y3UchfgGM,25507
|
46
46
|
openepd/model/org.py,sha256=PtG4-EgjKvNSt7446lV60HhDC3YyRx2E-yJ8MMs5raE,5049
|
47
47
|
openepd/model/pcr.py,sha256=QknLtTn6Y14JORWKQ1qBqGgKnZpbKgqNiYF3Axl4U4c,5494
|
48
48
|
openepd/model/specs/README.md,sha256=UGhSiFJ9hOxT1mZl-5ZrhkOrPKf1W_gcu5CI9hzV7LU,2430
|
49
49
|
openepd/model/specs/__init__.py,sha256=IAevXqqYrCWlTH4z4Fy9o77vaOLinX56G05iIJJfm0M,3094
|
50
50
|
openepd/model/specs/asphalt.py,sha256=V-N7NbrxyNnjgNXQbJPj17ZFM3Q-qxTxxjqpx61wEfA,3350
|
51
51
|
openepd/model/specs/base.py,sha256=JgXvfy8K1Jpcai1eCUDZ-ndsLYkL-dcDyH2hQls6Znw,2652
|
52
|
-
openepd/model/specs/concrete.py,sha256=
|
52
|
+
openepd/model/specs/concrete.py,sha256=ndi-z2KYXuhLMChgYq7ZNWDKS_LmkZWTOwY3DgZv19M,5336
|
53
53
|
openepd/model/specs/enums.py,sha256=r7Ik8tgL60McK_5ACQn0qhIUTmxjnCQlGvHtFE6m8xM,63602
|
54
54
|
openepd/model/specs/range/__init__.py,sha256=LmBClxzTNpWzGwS1zvFoAxbKILrMRMz22mJXKYu2u8I,4502
|
55
55
|
openepd/model/specs/range/accessories.py,sha256=T3z-5jLoIVIIGeQi2cc5fMP3a7uGgvoW2E_SVmr3c30,2498
|
@@ -86,7 +86,7 @@ openepd/model/specs/range/thermal_moisture_protection.py,sha256=tNimOVhUBn3U4821
|
|
86
86
|
openepd/model/specs/range/utility_piping.py,sha256=qCyJbOMZQP1nvA71qFos5wWx7xGhb8DFpeGaka8OkjQ,2665
|
87
87
|
openepd/model/specs/range/wood.py,sha256=zRsOsSOkxT84pQVvf9S4m34kFHa7HOppQK1Ggt_toUk,6946
|
88
88
|
openepd/model/specs/range/wood_joists.py,sha256=FevwQ3ebxMStesFehjyBCw4vxTQOYOZnPCdmobo3TGY,1785
|
89
|
-
openepd/model/specs/singular/__init__.py,sha256=
|
89
|
+
openepd/model/specs/singular/__init__.py,sha256=9Wx7xgDo-6KplvHtuTo4dPoTmLOv9FLq1kL1hOtE5gU,6910
|
90
90
|
openepd/model/specs/singular/accessories.py,sha256=hEnrW4Vdr9GopR_A9gF8QyUyKJ9i5sx4khrNYDVLwy8,2013
|
91
91
|
openepd/model/specs/singular/aggregates.py,sha256=EoAdyZc6QPHqGRn8c6VzoXx1wU05FH9UwQ7aOgU_Zkc,2934
|
92
92
|
openepd/model/specs/singular/aluminium.py,sha256=LFkBtSRWajBFRni3V8IPZtRjIo-h8zlvPLaVSVYpzJs,2403
|
@@ -98,6 +98,9 @@ openepd/model/specs/singular/cmu.py,sha256=NaeAcAiN1NkV_kxH1lyexb1Xas2ShSdWWP-7k
|
|
98
98
|
openepd/model/specs/singular/common.py,sha256=iNeJmVYZURVQWewx3zskwnwy7DBuaggCHFWQBThtY2A,1048
|
99
99
|
openepd/model/specs/singular/concrete.py,sha256=PexUR9w_NAkZ_VfgevxeaDqtipbaTY2mVRpPzp8uZnI,7718
|
100
100
|
openepd/model/specs/singular/conveying_equipment.py,sha256=4ftx12OG-9mUvOkoFvx9JKrHQERHrZBDqoCnvmFFQLA,3042
|
101
|
+
openepd/model/specs/singular/deprecated/__init__.py,sha256=ICBpA3saK8JqwSQGMiJIGWb6lPxM1cfb_PkcpYfyExw,2635
|
102
|
+
openepd/model/specs/singular/deprecated/concrete.py,sha256=zh4YysmwKc8TJrYoTIiFt6IUT6c2GT4dd2X0prBIErs,5265
|
103
|
+
openepd/model/specs/singular/deprecated/steel.py,sha256=AKpgfImRdqMB2ShC-WAkZ9IC9WjJ2cAoQrNV33ehteM,3499
|
101
104
|
openepd/model/specs/singular/electrical.py,sha256=IJgSbbcOvUIu70EqtG9qZvUKjtRvFda5eX9-VqRhyH8,11113
|
102
105
|
openepd/model/specs/singular/electrical_transmission_and_distribution_equipment.py,sha256=h6UQixACOHrquhQ2GFqqYWel_zqOXT-vAkI0o_RLf0A,1978
|
103
106
|
openepd/model/specs/singular/electricity.py,sha256=iGtN21K1MRVwoRfO6friVgiXc2b6cVdITbvnXqLmW3k,823
|
@@ -129,11 +132,11 @@ openepd/model/validation/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPo
|
|
129
132
|
openepd/model/validation/common.py,sha256=FLYqK8gYFagx08LCkS0jy3qo4-Zq9VAv5i8ZwF2svkc,2435
|
130
133
|
openepd/model/validation/enum.py,sha256=06Fi2_sdjVhOElavtgvNXvkKU0NQ-bcAFx5_5MiDzdU,1793
|
131
134
|
openepd/model/validation/numbers.py,sha256=J2rVMwJTPr8uC1DrU80xpq2SZGMXvVKx7v74SgOVi0U,851
|
132
|
-
openepd/model/validation/quantity.py,sha256=
|
135
|
+
openepd/model/validation/quantity.py,sha256=1z-G46dlryJEm4W-O0QiEJuFYICz7CPTM6gLhQKstgM,20194
|
133
136
|
openepd/model/versioning.py,sha256=R_zm6rCrgF3vlJQYbpyWhirdS_Oek16cv_mvZmpuE8I,4473
|
134
137
|
openepd/patch_pydantic.py,sha256=xrkzblatmU9HBzukWkp1cPq9ZSuohoz1p0pQqVKSlKs,4122
|
135
138
|
openepd/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
136
|
-
openepd-6.
|
137
|
-
openepd-6.
|
138
|
-
openepd-6.
|
139
|
-
openepd-6.
|
139
|
+
openepd-6.5.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
140
|
+
openepd-6.5.0.dist-info/METADATA,sha256=FADlEGrw8SuXk29hnGRJhtPbIkADL7XbRLYU4O1OaSA,9038
|
141
|
+
openepd-6.5.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
142
|
+
openepd-6.5.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|