openepd 6.4.2__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 CHANGED
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- VERSION = "6.4.2"
16
+ VERSION = "6.5.0"
@@ -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 openepd.model.base import BaseOpenEpdSchema
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")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openepd
3
- Version: 6.4.2
3
+ Version: 6.5.0
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
@@ -1,5 +1,5 @@
1
1
  openepd/__init__.py,sha256=Shkfh0Kun0YRhmRDw7LkUj2eQL3X-HnP55u2THOEALw,794
2
- openepd/__version__.py,sha256=LyifoozbkojKiw7ry9hn1dHTlFfXjPvebpjBZDdw6uU,638
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
@@ -49,7 +49,7 @@ openepd/model/specs/README.md,sha256=UGhSiFJ9hOxT1mZl-5ZrhkOrPKf1W_gcu5CI9hzV7LU
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=spMvijIv79c87PXT_YV7coG851AkJ1ILl9EHCxN2-6E,9593
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=T99PWY-76bYBg-Fi10R0PhjzpiG9BWv62lmjddZI7-Y,5047
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
@@ -133,7 +136,7 @@ openepd/model/validation/quantity.py,sha256=1z-G46dlryJEm4W-O0QiEJuFYICz7CPTM6gL
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.4.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
137
- openepd-6.4.2.dist-info/METADATA,sha256=5kTEsZy4PiO9EBGPxbl5Lu7pqAwDaJOjqkpRkVKUbas,9038
138
- openepd-6.4.2.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
139
- openepd-6.4.2.dist-info/RECORD,,
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,,