openepd 6.14.0__py3-none-any.whl → 6.15.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/api/average_dataset/generic_estimate_sync_api.py +2 -1
- openepd/api/average_dataset/industry_epd_sync_api.py +2 -1
- openepd/api/base_sync_client.py +10 -8
- openepd/api/common.py +17 -11
- openepd/api/dto/common.py +1 -1
- openepd/api/epd/sync_api.py +2 -1
- openepd/bundle/base.py +5 -4
- openepd/bundle/reader.py +13 -7
- openepd/bundle/writer.py +11 -6
- openepd/compat/pydantic.py +1 -1
- openepd/m49/__init__.py +2 -0
- openepd/m49/const.py +1 -1
- openepd/m49/utils.py +16 -10
- openepd/model/base.py +19 -15
- openepd/model/common.py +22 -19
- openepd/model/declaration.py +2 -2
- openepd/model/epd.py +2 -1
- openepd/model/factory.py +5 -3
- openepd/model/lcia.py +7 -6
- openepd/model/org.py +6 -3
- openepd/model/pcr.py +2 -2
- openepd/model/specs/__init__.py +36 -0
- openepd/model/specs/asphalt.py +3 -3
- openepd/model/specs/base.py +2 -1
- openepd/model/specs/enums.py +695 -695
- openepd/model/specs/range/accessories.py +1 -1
- openepd/model/specs/range/aluminium.py +1 -1
- openepd/model/specs/range/cladding.py +10 -10
- openepd/model/specs/range/cmu.py +0 -3
- openepd/model/specs/range/concrete.py +1 -1
- openepd/model/specs/range/conveying_equipment.py +2 -2
- openepd/model/specs/range/electrical.py +18 -18
- openepd/model/specs/range/electrical_transmission_and_distribution_equipment.py +1 -1
- openepd/model/specs/range/finishes.py +16 -16
- openepd/model/specs/range/fire_and_smoke_protection.py +3 -3
- openepd/model/specs/range/furnishings.py +7 -7
- openepd/model/specs/range/manufacturing_inputs.py +4 -4
- openepd/model/specs/range/masonry.py +1 -1
- openepd/model/specs/range/mechanical.py +6 -6
- openepd/model/specs/range/network_infrastructure.py +3 -3
- openepd/model/specs/range/openings.py +17 -17
- openepd/model/specs/range/other_materials.py +4 -4
- openepd/model/specs/range/plumbing.py +5 -5
- openepd/model/specs/range/precast_concrete.py +2 -2
- openepd/model/specs/range/steel.py +16 -11
- openepd/model/specs/range/thermal_moisture_protection.py +12 -12
- openepd/model/specs/range/wood.py +4 -7
- openepd/model/specs/singular/__init__.py +109 -1
- openepd/model/specs/singular/aluminium.py +2 -1
- openepd/model/specs/singular/steel.py +10 -2
- openepd/model/validation/common.py +10 -6
- openepd/model/validation/enum.py +4 -2
- openepd/model/validation/quantity.py +8 -1
- openepd/model/versioning.py +8 -6
- openepd/patch_pydantic.py +2 -1
- {openepd-6.14.0.dist-info → openepd-6.15.0.dist-info}/METADATA +1 -3
- {openepd-6.14.0.dist-info → openepd-6.15.0.dist-info}/RECORD +60 -60
- {openepd-6.14.0.dist-info → openepd-6.15.0.dist-info}/WHEEL +1 -1
- {openepd-6.14.0.dist-info → openepd-6.15.0.dist-info}/LICENSE +0 -0
@@ -13,7 +13,11 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
|
-
from
|
16
|
+
from collections.abc import Sequence
|
17
|
+
import types
|
18
|
+
from typing import Any, ClassVar, TypeVar
|
19
|
+
|
20
|
+
from pydantic.v1.fields import FieldInfo
|
17
21
|
|
18
22
|
from openepd.compat.pydantic import pyd
|
19
23
|
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
@@ -59,6 +63,8 @@ from openepd.model.specs.singular.wood_joists import WoodJoistsV1
|
|
59
63
|
|
60
64
|
__all__ = ("Specs",)
|
61
65
|
|
66
|
+
TValue = TypeVar("TValue")
|
67
|
+
|
62
68
|
|
63
69
|
class Specs(BaseOpenEpdHierarchicalSpec):
|
64
70
|
"""Material specific specs."""
|
@@ -137,3 +143,105 @@ class Specs(BaseOpenEpdHierarchicalSpec):
|
|
137
143
|
continue
|
138
144
|
set_safely(values, new_key_spec, old_value)
|
139
145
|
return values
|
146
|
+
|
147
|
+
def get_by_spec_path(
|
148
|
+
self,
|
149
|
+
path: str | Sequence[str],
|
150
|
+
*,
|
151
|
+
delimiter: str = ".",
|
152
|
+
asserted_type: type[TValue] | None = None,
|
153
|
+
ensure_path: bool = True,
|
154
|
+
) -> TValue | None:
|
155
|
+
"""
|
156
|
+
Access specific property of the spec by a path, which can be string-separated or sequence of keys.
|
157
|
+
|
158
|
+
:param path: The path to access, either as a string with delimiters (e.g. "Concrete.strength_28d")
|
159
|
+
or sequence of keys (e.g. ["Concrete", "strength_28d"])
|
160
|
+
:param delimiter: String separator used when path is provided as a string (default ".")
|
161
|
+
:param asserted_type: Type to validate the returned value against (optional)
|
162
|
+
:param ensure_path: If True, validates that path exists in the spec schema before accessing (default True)
|
163
|
+
:return: Value at the specified path if found, None if path resolves to None
|
164
|
+
:raises KeyError: If ensure_path=True and path does not exist in schema
|
165
|
+
:raises TypeError: If asserted_type is provided and value type doesn't match
|
166
|
+
:raises ValueError: If path is not string or sequence
|
167
|
+
|
168
|
+
Example usage:
|
169
|
+
>>> specs.get_by_spec_path("Concrete.strength_28d")
|
170
|
+
>>> specs.get_by_spec_path(["Concrete", "strength_28d"])
|
171
|
+
>>> specs.get_by_spec_path("Concrete.strength_28d", asserted_type=str)
|
172
|
+
"""
|
173
|
+
keys = self._path_to_keys(path, delimiter)
|
174
|
+
|
175
|
+
if ensure_path:
|
176
|
+
self._ensure_path(keys)
|
177
|
+
|
178
|
+
result: Any = self
|
179
|
+
for key in self._path_to_keys(path, delimiter):
|
180
|
+
result = getattr(result, key, None)
|
181
|
+
if result is None:
|
182
|
+
return None
|
183
|
+
|
184
|
+
if not asserted_type:
|
185
|
+
return result
|
186
|
+
|
187
|
+
if isinstance(result, asserted_type):
|
188
|
+
return result
|
189
|
+
|
190
|
+
msg = f"Expected {asserted_type} but got {type(result)}"
|
191
|
+
raise TypeError(msg)
|
192
|
+
|
193
|
+
def _ensure_path(self, keys: Sequence[str]) -> None:
|
194
|
+
"""
|
195
|
+
Validate if a sequence of keys exists in the spec schema structure.
|
196
|
+
|
197
|
+
:param keys: Sequence of string keys representing path in spec schema
|
198
|
+
:raises KeyError: If path specified by keys does not exist in schema
|
199
|
+
|
200
|
+
This internal method walks through the schema structure following the provided keys
|
201
|
+
sequence, checking if each key exists at the corresponding level. For UnionType fields,
|
202
|
+
it extracts the non-None type and continues validation if it's a BaseModel.
|
203
|
+
"""
|
204
|
+
klass = self.__class__
|
205
|
+
|
206
|
+
fields: dict[str, FieldInfo] = klass.__fields__ # type: ignore[assignment]
|
207
|
+
|
208
|
+
field: FieldInfo | None
|
209
|
+
for i, key in enumerate(keys, start=1):
|
210
|
+
field = fields.get(key)
|
211
|
+
if field is None:
|
212
|
+
msg = f"Path {'.'.join(keys)} does not exist in {klass.__name__} spec"
|
213
|
+
raise KeyError(msg)
|
214
|
+
|
215
|
+
assert hasattr(field, "annotation"), "Annotation field is required"
|
216
|
+
if isinstance(field.annotation, types.UnionType):
|
217
|
+
target_type = next(item for item in field.annotation.__args__ if item is not None)
|
218
|
+
else:
|
219
|
+
target_type = field.annotation
|
220
|
+
|
221
|
+
if issubclass(target_type, pyd.BaseModel):
|
222
|
+
fields = target_type.__fields__
|
223
|
+
elif i == len(keys):
|
224
|
+
return None
|
225
|
+
else:
|
226
|
+
msg = f"Path {'.'.join(keys)} does not exist in {klass.__name__} spec"
|
227
|
+
raise KeyError(msg)
|
228
|
+
|
229
|
+
return None
|
230
|
+
|
231
|
+
def _path_to_keys(self, path: str | Sequence[str], delimiter: str) -> Sequence[str]:
|
232
|
+
"""
|
233
|
+
Convert path parameter to sequence of keys.
|
234
|
+
|
235
|
+
:param path: Path to convert, either string to split by delimiter or sequence of keys
|
236
|
+
:param delimiter: String separator used to split path if string is provided
|
237
|
+
:return: Sequence of string keys
|
238
|
+
:raises ValueError: If a path is not string or sequence
|
239
|
+
"""
|
240
|
+
match path:
|
241
|
+
case str():
|
242
|
+
return path.split(delimiter)
|
243
|
+
case Sequence():
|
244
|
+
return path
|
245
|
+
case _:
|
246
|
+
msg = f"Unsupported path type: {type(path)}"
|
247
|
+
raise ValueError(msg)
|
@@ -25,7 +25,8 @@ class AluminiumBilletsV1(BaseOpenEpdHierarchicalSpec):
|
|
25
25
|
|
26
26
|
|
27
27
|
class AluminiumExtrusionsV1(BaseOpenEpdHierarchicalSpec):
|
28
|
-
"""
|
28
|
+
"""
|
29
|
+
Extruded aluminum products used in construction.
|
29
30
|
|
30
31
|
Includes range of finish options including mill finish, painted, and anodized.
|
31
32
|
"""
|
@@ -85,7 +85,8 @@ class HotRolledSectionsV1(BaseOpenEpdHierarchicalSpec, SteelFabricatedMixin):
|
|
85
85
|
|
86
86
|
|
87
87
|
class PlateSteelV1(BaseOpenEpdHierarchicalSpec, SteelFabricatedMixin):
|
88
|
-
"""
|
88
|
+
"""
|
89
|
+
Plate Steels.
|
89
90
|
|
90
91
|
Flat hot-rolled steel, typically thicker than 'sheet', made by compressing multiple steel
|
91
92
|
layers together into one.
|
@@ -250,10 +251,16 @@ class OtherSteelV1(BaseOpenEpdHierarchicalSpec):
|
|
250
251
|
_EXT_VERSION = "1.0"
|
251
252
|
|
252
253
|
|
254
|
+
class CrudeSteelV1(BaseOpenEpdHierarchicalSpec):
|
255
|
+
"""Steel ingots, billets, blooms, and slabs for use in manufacturing steel products."""
|
256
|
+
|
257
|
+
_EXT_VERSION = "1.0"
|
258
|
+
|
259
|
+
|
253
260
|
class SteelV1(BaseOpenEpdHierarchicalSpec):
|
254
261
|
"""Broad category for construction materials made from steel and its alloys."""
|
255
262
|
|
256
|
-
_EXT_VERSION = "1.
|
263
|
+
_EXT_VERSION = "1.2"
|
257
264
|
|
258
265
|
# Own fields:
|
259
266
|
yield_tensile_str: PressureMPaStr | None = pyd.Field(
|
@@ -303,3 +310,4 @@ class SteelV1(BaseOpenEpdHierarchicalSpec):
|
|
303
310
|
RebarSteel: RebarSteelV1 | None = None
|
304
311
|
WireMeshSteel: WireMeshSteelV1 | None = None
|
305
312
|
OtherSteel: OtherSteelV1 | None = None
|
313
|
+
CrudeSteel: CrudeSteelV1 | None = None
|
@@ -13,7 +13,8 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
|
-
from
|
16
|
+
from collections.abc import Callable
|
17
|
+
from typing import Annotated, Any, TypeAlias
|
17
18
|
|
18
19
|
from openepd.compat.pydantic import pyd
|
19
20
|
from openepd.model.versioning import Version
|
@@ -24,7 +25,8 @@ def together_validator(field1: str, field2: Any, values: dict[str, Any]) -> Any:
|
|
24
25
|
value1 = values.get(field1)
|
25
26
|
value2 = values.get(field2)
|
26
27
|
if value1 is not None and value2 is None or value1 is None and value2 is not None:
|
27
|
-
|
28
|
+
msg = f"Both or neither {field1} and {field2} days must be provided together"
|
29
|
+
raise ValueError(msg)
|
28
30
|
|
29
31
|
|
30
32
|
def validate_version_format(v: str) -> str:
|
@@ -33,17 +35,19 @@ def validate_version_format(v: str) -> str:
|
|
33
35
|
return v
|
34
36
|
|
35
37
|
|
36
|
-
def validate_version_compatibility(class_version_attribute_name: str) -> Callable[[
|
38
|
+
def validate_version_compatibility(class_version_attribute_name: str) -> Callable[[type, str], str]:
|
37
39
|
"""Ensure that the object which is passed for parsing and validation is compatible with the class."""
|
38
40
|
|
39
41
|
# we need closure to pass property name, since actual class will only be available in runtime
|
40
|
-
def internal_validate_version_compatibility(cls:
|
42
|
+
def internal_validate_version_compatibility(cls: type, v: str) -> str:
|
41
43
|
if not hasattr(cls, class_version_attribute_name):
|
42
|
-
|
44
|
+
msg = f"Class {cls} must declare a class var extension var named {class_version_attribute_name}"
|
45
|
+
raise ValueError(msg)
|
43
46
|
|
44
47
|
class_version = getattr(cls, class_version_attribute_name)
|
45
48
|
if Version.parse_version(v).major != Version.parse_version(class_version).major:
|
46
|
-
|
49
|
+
msg = f"Extension version {v} does not match class version {class_version}"
|
50
|
+
raise ValueError(msg)
|
47
51
|
return v
|
48
52
|
|
49
53
|
return internal_validate_version_compatibility
|
openepd/model/validation/enum.py
CHANGED
@@ -13,7 +13,8 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
|
-
from
|
16
|
+
from collections.abc import Callable
|
17
|
+
from typing import Any
|
17
18
|
|
18
19
|
from openepd.model.common import EnumGroupingAware
|
19
20
|
|
@@ -35,7 +36,8 @@ def exclusive_groups_validator_factory(enum_type: type[EnumGroupingAware]) -> Ca
|
|
35
36
|
for grouping in enum_type.get_groupings():
|
36
37
|
matching_from_group = [v for v in (value or []) if v in grouping]
|
37
38
|
if len(matching_from_group) > 1:
|
38
|
-
|
39
|
+
msg = f"Values {', '.join(matching_from_group)} are not allowed together."
|
40
|
+
raise ValueError(msg)
|
39
41
|
|
40
42
|
return value
|
41
43
|
|
@@ -14,7 +14,8 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
from abc import ABC, abstractmethod
|
17
|
-
from
|
17
|
+
from collections.abc import Callable
|
18
|
+
from typing import TYPE_CHECKING, Any, ClassVar
|
18
19
|
|
19
20
|
from openepd.compat.pydantic import pyd
|
20
21
|
from openepd.model.base import BaseOpenEpdSchema
|
@@ -55,8 +56,10 @@ class QuantityValidator(ABC):
|
|
55
56
|
dimensionality: The dimensionality to validate against, like "kg"
|
56
57
|
Returns:
|
57
58
|
None if the value is valid, raises an error otherwise.
|
59
|
+
|
58
60
|
Raises:
|
59
61
|
ValueError: If the value is not valid.
|
62
|
+
|
60
63
|
"""
|
61
64
|
pass
|
62
65
|
|
@@ -70,8 +73,10 @@ class QuantityValidator(ABC):
|
|
70
73
|
min_value: The value to compare with, like "102.4 kg"
|
71
74
|
Returns:
|
72
75
|
None if the value is valid, raises an error otherwise.
|
76
|
+
|
73
77
|
Raises:
|
74
78
|
ValueError: If the value is not valid.
|
79
|
+
|
75
80
|
"""
|
76
81
|
pass
|
77
82
|
|
@@ -85,8 +90,10 @@ class QuantityValidator(ABC):
|
|
85
90
|
max_value: The value to compare with, like "0.4 kg"
|
86
91
|
Returns:
|
87
92
|
None if the value is valid, raises an error otherwise.
|
93
|
+
|
88
94
|
Raises:
|
89
95
|
ValueError: If the value is not valid.
|
96
|
+
|
90
97
|
"""
|
91
98
|
pass
|
92
99
|
|
openepd/model/versioning.py
CHANGED
@@ -44,7 +44,8 @@ class Version(NamedTuple):
|
|
44
44
|
|
45
45
|
@staticmethod
|
46
46
|
def parse_version(version: str) -> "Version":
|
47
|
-
"""
|
47
|
+
"""
|
48
|
+
Parse the version of extension or the format.
|
48
49
|
|
49
50
|
Version is expected to be major.minor
|
50
51
|
|
@@ -53,9 +54,11 @@ class Version(NamedTuple):
|
|
53
54
|
"""
|
54
55
|
splits = version.split(".", 1) if isinstance(version, str) else None
|
55
56
|
if len(splits) != 2:
|
56
|
-
|
57
|
+
msg = f"Invalid version: {version}"
|
58
|
+
raise ValueError(msg)
|
57
59
|
if not splits[0].isdigit() or not splits[1].isdigit():
|
58
|
-
|
60
|
+
msg = f"Invalid version: {version}"
|
61
|
+
raise ValueError(msg)
|
59
62
|
return Version(major=int(splits[0]), minor=int(splits[1]))
|
60
63
|
|
61
64
|
def __str__(self) -> str:
|
@@ -112,9 +115,8 @@ class OpenEpdVersions(Version, ReprEnum):
|
|
112
115
|
for x in cls:
|
113
116
|
if x.value.major == branch:
|
114
117
|
return x.value
|
115
|
-
|
116
|
-
|
117
|
-
)
|
118
|
+
msg = f"No version {branch}.x is not supported. Supported versions are: {', '.join(str(x.value) for x in cls)}"
|
119
|
+
raise ValueError(msg)
|
118
120
|
|
119
121
|
@classmethod
|
120
122
|
def get_current(cls) -> Version:
|
openepd/patch_pydantic.py
CHANGED
@@ -86,10 +86,11 @@ def patch_pydantic_metaclass_validator():
|
|
86
86
|
if isinstance(attr, model_field_classes_tuple):
|
87
87
|
continue
|
88
88
|
|
89
|
-
|
89
|
+
msg = (
|
90
90
|
f'Field name "{field_name}" shadows a BaseModel attribute; '
|
91
91
|
f"use a different field name with \"alias='{field_name}'\"."
|
92
92
|
)
|
93
|
+
raise NameError(msg)
|
93
94
|
|
94
95
|
pyd.main.validate_field_name = pydantic_utils__validate_field_name
|
95
96
|
pydantic_utils.validate_field_name = pydantic_utils__validate_field_name
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: openepd
|
3
|
-
Version: 6.
|
3
|
+
Version: 6.15.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
|
@@ -15,8 +15,6 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
18
|
-
Classifier: Programming Language :: Python :: 3.12
|
19
|
-
Classifier: Programming Language :: Python :: 3.13
|
20
18
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
21
19
|
Provides-Extra: api-client
|
22
20
|
Requires-Dist: email-validator (>=1.3.1)
|
@@ -1,23 +1,23 @@
|
|
1
1
|
openepd/__init__.py,sha256=fhxfEyEurLvSfvQci-vb3njzl_lvhcLXiZrecCOaMU8,794
|
2
|
-
openepd/__version__.py,sha256=
|
2
|
+
openepd/__version__.py,sha256=iyY3VSoCvm9hVasih1ViXL90QibEUft4FAGomBc7DNg,639
|
3
3
|
openepd/api/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
4
4
|
openepd/api/average_dataset/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
5
|
-
openepd/api/average_dataset/generic_estimate_sync_api.py,sha256=
|
6
|
-
openepd/api/average_dataset/industry_epd_sync_api.py,sha256=
|
7
|
-
openepd/api/base_sync_client.py,sha256=
|
5
|
+
openepd/api/average_dataset/generic_estimate_sync_api.py,sha256=_eZt_jGVL1a3p9cr-EF39Ve9Vl5sB8zwzTc_slnRL50,7975
|
6
|
+
openepd/api/average_dataset/industry_epd_sync_api.py,sha256=8SJaWfc9yJwtWbODM4oNXLBWiVg6_JUB_IalK1Rqli4,6308
|
7
|
+
openepd/api/base_sync_client.py,sha256=ChXvtOeKAIPe2grr05fb0AosFlOt431_VSm-8zra450,21050
|
8
8
|
openepd/api/category/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
9
9
|
openepd/api/category/dto.py,sha256=-nsSNH1zWIluFuF50qmnIcvloX08Jk_KV5mebJqzLe4,850
|
10
10
|
openepd/api/category/sync_api.py,sha256=XlT5a_IkfaVARrZY0hjDUzDVP2ThkR2j_MRNqz6zkTE,1371
|
11
|
-
openepd/api/common.py,sha256=
|
11
|
+
openepd/api/common.py,sha256=KfV-HX93QtQp1vnmfAp-pdpDBvpfzahbXavCXbLt6L0,8943
|
12
12
|
openepd/api/dto/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
13
13
|
openepd/api/dto/base.py,sha256=w-Ci0MN2vTIQ0Vl0YKLUXVG_fC0OxiwojT9SX3lWktg,1033
|
14
|
-
openepd/api/dto/common.py,sha256=
|
14
|
+
openepd/api/dto/common.py,sha256=0XGGawcj7KP-P864yqvNusEaMFj6ImfsfbcmebwYqxY,4502
|
15
15
|
openepd/api/dto/meta.py,sha256=IrGJtfl6-mBXLSWZjcyr08WvvOh9VL0LJnx5ubhJqco,2160
|
16
16
|
openepd/api/dto/mf.py,sha256=59YvIrH5teHlpxINihxryFyCjs7jBZZuqYIO1K-daA8,1994
|
17
17
|
openepd/api/dto/params.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
18
18
|
openepd/api/epd/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
19
19
|
openepd/api/epd/dto.py,sha256=MqhHjaNdtOc-KT2zNI88EB9-1d2a6CS2zzSus8HefBo,4874
|
20
|
-
openepd/api/epd/sync_api.py,sha256=
|
20
|
+
openepd/api/epd/sync_api.py,sha256=kBsx43q0cBm51hl3HVvzMIDrMMRi8NMyudPmHYd0qqU,7342
|
21
21
|
openepd/api/errors.py,sha256=BgZeNfMNAKVPfhpuiVapCXNBSsXygAOWql-gy7m9j7E,2868
|
22
22
|
openepd/api/pcr/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
23
23
|
openepd/api/pcr/sync_api.py,sha256=MyBOlBqdJt35-fXk-Vr-RpiKUbN_XlilUwwFGvVROdQ,1557
|
@@ -25,74 +25,74 @@ openepd/api/sync_client.py,sha256=reD_OXsaVOvUvnC-cyp5aq8sKSOH2Z8xmImxV2ClQIM,31
|
|
25
25
|
openepd/api/test/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
26
26
|
openepd/api/utils.py,sha256=xOU8ihC0eghsoaCFhC85PU4WYRwNxVEpfK3gzq4e9ik,2092
|
27
27
|
openepd/bundle/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
28
|
-
openepd/bundle/base.py,sha256=
|
28
|
+
openepd/bundle/base.py,sha256=ovURf721k9XWe0C8-tmik_bEOrHdOtF1jbN03T5G7M4,6918
|
29
29
|
openepd/bundle/model.py,sha256=_fQWW1KsxKquFFB6JtU3dyc82re1vqmwMpxe6zUEfSE,2605
|
30
|
-
openepd/bundle/reader.py,sha256=
|
31
|
-
openepd/bundle/writer.py,sha256=
|
30
|
+
openepd/bundle/reader.py,sha256=YvTXglxp8HLxkaOUdbvOuyA9qeN3vt_PjlAroOSzNO0,6822
|
31
|
+
openepd/bundle/writer.py,sha256=qfQWlGnbQxzim8mMbDKRyBpdEXDe60nyNbgjAbG0eq8,8245
|
32
32
|
openepd/compat/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
33
33
|
openepd/compat/compat_functional_validators.py,sha256=aWg3a80fqT8zjN0S260N-Ad2WFKAaB8ByN7ArBW3NMA,834
|
34
|
-
openepd/compat/pydantic.py,sha256=
|
35
|
-
openepd/m49/__init__.py,sha256=
|
36
|
-
openepd/m49/const.py,sha256=
|
37
|
-
openepd/m49/utils.py,sha256=
|
34
|
+
openepd/compat/pydantic.py,sha256=HZJmAiYO7s-LLcFHuj3iXS4MGOITExZYn2rPmteoqNI,1146
|
35
|
+
openepd/m49/__init__.py,sha256=AApOMp9PJPMXZbPB4piedqKtgHE01mlj_MyF3kf519U,718
|
36
|
+
openepd/m49/const.py,sha256=bkYu6J7dQNVb2-nNkjy97uMpt64vICX5o-PHr0lk_90,31833
|
37
|
+
openepd/m49/utils.py,sha256=vQl0wMXtYS2b7NeLIWilDNUopq3MATmLnhEFcMYTeZA,7256
|
38
38
|
openepd/model/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
39
|
-
openepd/model/base.py,sha256=
|
39
|
+
openepd/model/base.py,sha256=6rP6r-7NwKC6JLFB24v2w4Z-_f_w6ZSNLte5zyj5o70,9928
|
40
40
|
openepd/model/category.py,sha256=reeOVRDuZPYU77EMwG0K5VjnK2H9yOGxT0PJXXqrjEk,1639
|
41
|
-
openepd/model/common.py,sha256=
|
42
|
-
openepd/model/declaration.py,sha256=
|
43
|
-
openepd/model/epd.py,sha256=
|
44
|
-
openepd/model/factory.py,sha256=
|
41
|
+
openepd/model/common.py,sha256=jblgVf_ASMelxe_-mk6fnOIyM4n0TY4PJ8MeLX8O92c,13134
|
42
|
+
openepd/model/declaration.py,sha256=72oR19n0CfJx4DhMXGYrLYY_sUB4awZzpr4Tr3Jcnks,13814
|
43
|
+
openepd/model/epd.py,sha256=_1P9-etXfLAVmg44pglnBUvoEyQ50odNBsUrv_OeS9M,12308
|
44
|
+
openepd/model/factory.py,sha256=UWSGpfCr3GiMTP4rzBkwqxzbXB6GKZ_5Okb1Dqa_4aA,2701
|
45
45
|
openepd/model/generic_estimate.py,sha256=zLGTyf4Uzmp2C0m-J1ePWItSz2RGdZ0OiGPWC5nhKHk,3992
|
46
46
|
openepd/model/geography.py,sha256=Jx7NIDdk_sIvwyh-7YxnIjAwIHW2HCQK7UtFGM2xKtw,42095
|
47
47
|
openepd/model/industry_epd.py,sha256=QZr7OhgGkzqZ8H5p6dCIVk9zSHEYtK3y9Nk-DvkFMyk,4011
|
48
|
-
openepd/model/lcia.py,sha256=
|
49
|
-
openepd/model/org.py,sha256=
|
50
|
-
openepd/model/pcr.py,sha256=
|
48
|
+
openepd/model/lcia.py,sha256=jgxTVoY2gCgfPCLrV5xRYGHbxntellGTfgLUGU9J22Y,26152
|
49
|
+
openepd/model/org.py,sha256=nm3B4HdJDASyr4SIosE64BK45tR4bv9CsFBls0umoG8,5408
|
50
|
+
openepd/model/pcr.py,sha256=7nf6ATofdrlPt81vdU6p0E8n_ftFEuCEIKxtYlFwclw,5476
|
51
51
|
openepd/model/specs/README.md,sha256=UGhSiFJ9hOxT1mZl-5ZrhkOrPKf1W_gcu5CI9hzV7LU,2430
|
52
|
-
openepd/model/specs/__init__.py,sha256=
|
53
|
-
openepd/model/specs/asphalt.py,sha256=
|
54
|
-
openepd/model/specs/base.py,sha256=
|
52
|
+
openepd/model/specs/__init__.py,sha256=toVWd8_jxmAf7gRwpoXQpLfZW6Cl-NwveoduMXhECms,3903
|
53
|
+
openepd/model/specs/asphalt.py,sha256=eHhcITbBrNYR5N6x4Q2BxpsR64BR9OkjJ4bvPRYOqMg,3411
|
54
|
+
openepd/model/specs/base.py,sha256=10IDyRFKQgFnyIPSqpeayP8Og1BDgs1EepXX5dyCMM4,2674
|
55
55
|
openepd/model/specs/concrete.py,sha256=D9jbhZDtTXNBoAgljQBPxsmGsMvLSIAP5H53ZYiXcGI,5336
|
56
|
-
openepd/model/specs/enums.py,sha256=
|
56
|
+
openepd/model/specs/enums.py,sha256=H6PPr_wRnGFXIjFqMoVAgVNxqtUedkq9dKN9KVs_G_o,62893
|
57
57
|
openepd/model/specs/range/__init__.py,sha256=ZXgsyzn_c6H2SPCo5hTVZOjRqlCf0HvVVMDQ4RGaPSU,4502
|
58
|
-
openepd/model/specs/range/accessories.py,sha256=
|
58
|
+
openepd/model/specs/range/accessories.py,sha256=hZYz8mvAqrfLFiOIZ9qQZ59zmEiu0xE61Ko9cQ7NSKU,2498
|
59
59
|
openepd/model/specs/range/aggregates.py,sha256=udVbsYc1Lyrd6a4YZBGNDQ3sBi-L3WLub_e1ecq7U-Q,2549
|
60
|
-
openepd/model/specs/range/aluminium.py,sha256=
|
60
|
+
openepd/model/specs/range/aluminium.py,sha256=Z3laZKXoPtfmOLLr4c4uf7Z-8TNmfz51X-_yd7GQIj8,2745
|
61
61
|
openepd/model/specs/range/asphalt.py,sha256=DN3--5g0WL2AQ8Vc23M899rPqxCaFgEhaYqV8vWRbZY,2934
|
62
62
|
openepd/model/specs/range/bulk_materials.py,sha256=SuKhmJXMa9jl0CrkYr3QVvPX_GDbr7KATzrSS-fJEU4,1051
|
63
63
|
openepd/model/specs/range/cast_decks_and_underlayment.py,sha256=37fx7jDRy6xryZTVweW_vu78h0kRs5vQurGS-Ypayog,1132
|
64
|
-
openepd/model/specs/range/cladding.py,sha256=
|
65
|
-
openepd/model/specs/range/cmu.py,sha256=
|
66
|
-
openepd/model/specs/range/concrete.py,sha256=
|
67
|
-
openepd/model/specs/range/conveying_equipment.py,sha256=
|
68
|
-
openepd/model/specs/range/electrical.py,sha256=
|
69
|
-
openepd/model/specs/range/electrical_transmission_and_distribution_equipment.py,sha256=
|
64
|
+
openepd/model/specs/range/cladding.py,sha256=r7M2lc77NR2GXBkgkqRzskQ6TdZeMd7pEEm8ecHb8rc,7236
|
65
|
+
openepd/model/specs/range/cmu.py,sha256=Sv4yw6121LSgYhW4J82xKsIi1KucaeDVF7xmpZtoCt8,1833
|
66
|
+
openepd/model/specs/range/concrete.py,sha256=m2JP-W4Pnoo6q3hUbkIJF4_hTwI_-7FNLGZzdp-PX1w,6907
|
67
|
+
openepd/model/specs/range/conveying_equipment.py,sha256=_rqJ9Y3kkP8E6-vkZb6Pih3JnR1nUESJoOLf-LT--sc,3176
|
68
|
+
openepd/model/specs/range/electrical.py,sha256=EI8pv9SN4lJbFNz1wlyMNAjkA0dsi84pc2J9YvtiwzY,11860
|
69
|
+
openepd/model/specs/range/electrical_transmission_and_distribution_equipment.py,sha256=xDdyLj6oJRmdybq7W91MtgE80FDpaG6ii5hE921aRGQ,2525
|
70
70
|
openepd/model/specs/range/electricity.py,sha256=yn_S25C_tZqseb8hiJ1yiHszu2mQ49FOFWWCqNpOBY0,997
|
71
|
-
openepd/model/specs/range/finishes.py,sha256=
|
72
|
-
openepd/model/specs/range/fire_and_smoke_protection.py,sha256=
|
73
|
-
openepd/model/specs/range/furnishings.py,sha256=
|
71
|
+
openepd/model/specs/range/finishes.py,sha256=Yu0Jz8L7Eqy79n79uyoqYwpKa1UeX4m2A5CFJxn49AQ,21291
|
72
|
+
openepd/model/specs/range/fire_and_smoke_protection.py,sha256=GUap2Xrn-rFF8CMDyRcOpmQpO8JgZ7PSUXGr_SKUzws,3337
|
73
|
+
openepd/model/specs/range/furnishings.py,sha256=_HdPg1_LepLgdo5tV59oRer1PRYniIM0kLEKbnlyoLM,6703
|
74
74
|
openepd/model/specs/range/grouting.py,sha256=BQPxH6BvlXpdhLEZBui9zTuY93K_9syjoa6rdnF8GGY,1095
|
75
|
-
openepd/model/specs/range/manufacturing_inputs.py,sha256=
|
76
|
-
openepd/model/specs/range/masonry.py,sha256=
|
75
|
+
openepd/model/specs/range/manufacturing_inputs.py,sha256=RFqWTQij2Zc5-Y4jzOBQKC0ENV3ncg5O9yHoqdo9rUQ,5574
|
76
|
+
openepd/model/specs/range/masonry.py,sha256=P9USz744YQLBEk_XdG4v9a4ImXtMymnPC30qtbd2F6I,2867
|
77
77
|
openepd/model/specs/range/material_handling.py,sha256=9jxRHpjMKu71B5omH55UjkNVJvaTLgTMtEidSKPFn5c,1483
|
78
|
-
openepd/model/specs/range/mechanical.py,sha256=
|
78
|
+
openepd/model/specs/range/mechanical.py,sha256=kyAJj9KJ17usuKDOt7v2gAJpzSEeYO9nnTOB_pht-fc,10267
|
79
79
|
openepd/model/specs/range/mechanical_insulation.py,sha256=S2-NkFVkjLmn_dk3gsG8C2YcV0SFXbOCgY6LKberqh8,1737
|
80
|
-
openepd/model/specs/range/network_infrastructure.py,sha256=
|
81
|
-
openepd/model/specs/range/openings.py,sha256=
|
80
|
+
openepd/model/specs/range/network_infrastructure.py,sha256=aqXEIGqFy0gNCM_ftd3J6aT3FZf9JlT0SBOImhdkTg0,8498
|
81
|
+
openepd/model/specs/range/openings.py,sha256=4n5PEMJJFL75wMmYUcJNxdWtDMpWYZLKK4d-730KASA,15451
|
82
82
|
openepd/model/specs/range/other_electrical_equipment.py,sha256=H4tZHcHyR2uUYHn-bQfLC6hR4tynVp_7EJbiI-YpK7Y,1001
|
83
|
-
openepd/model/specs/range/other_materials.py,sha256=
|
84
|
-
openepd/model/specs/range/plumbing.py,sha256=
|
85
|
-
openepd/model/specs/range/precast_concrete.py,sha256=
|
83
|
+
openepd/model/specs/range/other_materials.py,sha256=RHusAyExYl9n1BDiOFDq2_znEn3MXGxEkunb3BjiC2U,4495
|
84
|
+
openepd/model/specs/range/plumbing.py,sha256=jQKrKYGDR33uh3ffo6uVyt3xuSmexkkelfNh_-omNCg,5342
|
85
|
+
openepd/model/specs/range/precast_concrete.py,sha256=nn1U1XwKqqzY1cOPP3KqHZMJq4Ut9RAox4SMVYBa5B8,3763
|
86
86
|
openepd/model/specs/range/sheathing.py,sha256=tATL6dzKTdN0rUKZRzZd779dLhKdEavL5Bjybnt2MjU,3395
|
87
|
-
openepd/model/specs/range/steel.py,sha256=
|
88
|
-
openepd/model/specs/range/thermal_moisture_protection.py,sha256=
|
87
|
+
openepd/model/specs/range/steel.py,sha256=LY54qqxL1XgkWGZ2MYH8WdsARU3lLf3R_-3pNZUyhbY,10476
|
88
|
+
openepd/model/specs/range/thermal_moisture_protection.py,sha256=aUpStISG2snc8aZ7iLCTIejurcCoMHNgRNYwp5PwgOc,9409
|
89
89
|
openepd/model/specs/range/utility_piping.py,sha256=mQTrKbMTES_0Yta9DBnKehsmA2BAN_zYF_uPZCTKLPo,2665
|
90
|
-
openepd/model/specs/range/wood.py,sha256=
|
90
|
+
openepd/model/specs/range/wood.py,sha256=ZMStFsFOw5d6tCL2P7kksBnlYhwfvWJBZqoAdqSIUDg,6917
|
91
91
|
openepd/model/specs/range/wood_joists.py,sha256=NCBHL0gdKwdKlGCP6up_Royl9BtWUUeuFfS1r2vIZ30,1785
|
92
|
-
openepd/model/specs/singular/__init__.py,sha256=
|
92
|
+
openepd/model/specs/singular/__init__.py,sha256=AUVpQi2F8oq9xoMdz5zI0FFXHQYjknPvg_1ydxwVp3A,11278
|
93
93
|
openepd/model/specs/singular/accessories.py,sha256=xcuSJrG84oTm_w76_wlv_sItfK36gSyDmUD2TnpZnVE,2013
|
94
94
|
openepd/model/specs/singular/aggregates.py,sha256=oSfArxvLUj63w_U0tZViRyiOpMRRjE72ncy2BimKxco,2934
|
95
|
-
openepd/model/specs/singular/aluminium.py,sha256=
|
95
|
+
openepd/model/specs/singular/aluminium.py,sha256=7Z3WmuW22o92cPHfR6X_OBSoer0V5llwiNdQmWgKTx8,2408
|
96
96
|
openepd/model/specs/singular/asphalt.py,sha256=JDviENdY_2tcj5SrzgJnYJHuxTIOhLCWcXhmoSiELKk,3295
|
97
97
|
openepd/model/specs/singular/bulk_materials.py,sha256=LKTmh432ak51L0GsVf-40389Lwx-sxZm_jSfzWNfagE,875
|
98
98
|
openepd/model/specs/singular/cast_decks_and_underlayment.py,sha256=HjIEKekxCAKx51XEvH1tthUP6gNTbntDoi8gSu8LjZk,955
|
@@ -125,21 +125,21 @@ openepd/model/specs/singular/other_materials.py,sha256=_00_fCPn7G_-HVKC1cQcNvBDf
|
|
125
125
|
openepd/model/specs/singular/plumbing.py,sha256=fHmKyy1aQxu8NZ3RTwxuA0CCERMgwVUdMA74kMDVc8o,4568
|
126
126
|
openepd/model/specs/singular/precast_concrete.py,sha256=W2tKf0vOnAdfeGc1n7Pk8yx9jy44afdFB0cbwHjw1HI,7327
|
127
127
|
openepd/model/specs/singular/sheathing.py,sha256=dfBSGElsJ-suj3WH7CZx5k3_v5E5IHVDOscwRI5yghE,3709
|
128
|
-
openepd/model/specs/singular/steel.py,sha256=
|
128
|
+
openepd/model/specs/singular/steel.py,sha256=Kfnb1Tnk8eGAbFALDWffOzo1tZQdSk6MgnPldLAoe2o,10746
|
129
129
|
openepd/model/specs/singular/thermal_moisture_protection.py,sha256=7fikgfPyopWruPzhWdyU-YWvlo5facOjXbviyl_qOEw,8195
|
130
130
|
openepd/model/specs/singular/utility_piping.py,sha256=KunlvMGqH_Z62TecGnT_4HhsTase01aJJIGIsyY5mGY,2483
|
131
131
|
openepd/model/specs/singular/wood.py,sha256=6bGl5TgJgAZxosh_46YcZDm57DOyFyLZ9g2W-oDlhl8,6591
|
132
132
|
openepd/model/specs/singular/wood_joists.py,sha256=WL_l48aTuazQkWwdz5EQcGrbK5biWhqHqhWdHXITPIo,1719
|
133
133
|
openepd/model/standard.py,sha256=LFqZKK8nYJHKvcW0BaLoFm0-TVYpQr2l9l70vHLRiNk,1688
|
134
134
|
openepd/model/validation/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
135
|
-
openepd/model/validation/common.py,sha256=
|
136
|
-
openepd/model/validation/enum.py,sha256=
|
135
|
+
openepd/model/validation/common.py,sha256=nzZoboF8Hab8WpQA4HGkqe7hds-SLJylh_QhasrEtZs,2518
|
136
|
+
openepd/model/validation/enum.py,sha256=0nRnjwmObw8ERQYWRWbovZjm90CMHi1Sc-UeNxCFnsc,1846
|
137
137
|
openepd/model/validation/numbers.py,sha256=r15pLe8oWY1tshazQvis_suVXpC6PUcPzKTvj3QTL9Q,851
|
138
|
-
openepd/model/validation/quantity.py,sha256=
|
139
|
-
openepd/model/versioning.py,sha256=
|
140
|
-
openepd/patch_pydantic.py,sha256=
|
138
|
+
openepd/model/validation/quantity.py,sha256=ve0sPN9hG4Zca-fb4xJT9RqFBJ6rpPHSquBzLm7ldyQ,20227
|
139
|
+
openepd/model/versioning.py,sha256=wBZdOVL3ND9FMIRU9PS3vx9M_7MBiO70xYPQvPez6po,4522
|
140
|
+
openepd/patch_pydantic.py,sha256=bO7U5HqthFol0vfycb0a42UAGL3KOQ8-9MW4yCWOFP0,4150
|
141
141
|
openepd/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
142
|
-
openepd-6.
|
143
|
-
openepd-6.
|
144
|
-
openepd-6.
|
145
|
-
openepd-6.
|
142
|
+
openepd-6.15.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
143
|
+
openepd-6.15.0.dist-info/METADATA,sha256=6kAg4ctCE4Zawd9nxaVsVRqKiHBWicl1NFgzKeSKNYo,9039
|
144
|
+
openepd-6.15.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
145
|
+
openepd-6.15.0.dist-info/RECORD,,
|
File without changes
|