openepd 4.11.3__py3-none-any.whl → 4.13.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/base_sync_client.py +2 -1
- openepd/api/errors.py +14 -1
- openepd/model/base.py +31 -1
- openepd/model/declaration.py +38 -5
- openepd/model/epd.py +18 -33
- openepd/model/generic_estimate.py +2 -1
- openepd/model/industry_epd.py +3 -1
- openepd/model/lcia.py +1 -1
- openepd/model/pcr.py +3 -3
- openepd/model/validation/quantity.py +29 -2
- {openepd-4.11.3.dist-info → openepd-4.13.0.dist-info}/METADATA +1 -1
- {openepd-4.11.3.dist-info → openepd-4.13.0.dist-info}/RECORD +15 -15
- {openepd-4.11.3.dist-info → openepd-4.13.0.dist-info}/LICENSE +0 -0
- {openepd-4.11.3.dist-info → openepd-4.13.0.dist-info}/WHEEL +0 -0
openepd/__version__.py
CHANGED
openepd/api/base_sync_client.py
CHANGED
@@ -151,6 +151,7 @@ class SyncHttpClient:
|
|
151
151
|
|
152
152
|
HTTP_DATE_TIME_FORMAT = "%a, %d %b %Y %H:%M:%S %Z"
|
153
153
|
DEFAULT_RETRY_INTERVAL_SEC = 10
|
154
|
+
DEFAULT_TIMEOUT_SEC = (15, 2 * 60)
|
154
155
|
|
155
156
|
def __init__(
|
156
157
|
self,
|
@@ -183,7 +184,7 @@ class SyncHttpClient:
|
|
183
184
|
else throttle_retry_timeout.total_seconds()
|
184
185
|
)
|
185
186
|
self.user_agent = user_agent
|
186
|
-
self.timeout = timeout_sec
|
187
|
+
self.timeout = timeout_sec or self.DEFAULT_TIMEOUT_SEC
|
187
188
|
self._session: Session | None = None
|
188
189
|
self._auth: AuthBase | None = auth
|
189
190
|
self._retry_count: int = retry_count
|
openepd/api/errors.py
CHANGED
@@ -55,9 +55,22 @@ class ValidationError(ApiError):
|
|
55
55
|
super().__init__(http_status, error_summary, response, error_code)
|
56
56
|
self.validation_errors: dict[str, list[str]] = validation_errors or {}
|
57
57
|
|
58
|
+
@staticmethod
|
59
|
+
def __flatten(nested_errors: dict[str, Any], parent_key: str = "") -> dict[str, list[str]]:
|
60
|
+
result: dict[str, list[str]] = {}
|
61
|
+
for key, value in nested_errors.items():
|
62
|
+
full_key = f"{parent_key}.{key}" if parent_key else key
|
63
|
+
if isinstance(value, dict):
|
64
|
+
nested_result = ValidationError.__flatten(value, full_key)
|
65
|
+
for nested_key, nested_errors in nested_result.items(): # type: ignore[assignment]
|
66
|
+
result.setdefault(nested_key, []).extend(nested_errors)
|
67
|
+
else:
|
68
|
+
result.setdefault(full_key, []).extend(value)
|
69
|
+
return result
|
70
|
+
|
58
71
|
def __str__(self) -> str:
|
59
72
|
result: list[str] = ["Validation errors:"]
|
60
|
-
for code, errors in self.validation_errors.items():
|
73
|
+
for code, errors in self.__flatten(self.validation_errors).items(): # type: ignore[arg-type]
|
61
74
|
result.append(f"{code}:")
|
62
75
|
for e in errors:
|
63
76
|
result.append(f" {e}")
|
openepd/model/base.py
CHANGED
@@ -18,6 +18,8 @@ from enum import StrEnum
|
|
18
18
|
import json
|
19
19
|
from typing import Any, Callable, ClassVar, Generic, Optional, Type, TypeAlias, TypeVar
|
20
20
|
|
21
|
+
from cqd import open_xpd_uuid # type:ignore[import-untyped]
|
22
|
+
|
21
23
|
from openepd.compat.pydantic import pyd, pyd_generics
|
22
24
|
from openepd.model.validation.common import validate_version_compatibility, validate_version_format
|
23
25
|
from openepd.model.versioning import OpenEpdVersions, Version
|
@@ -183,7 +185,7 @@ class RootDocument(abc.ABC, BaseOpenEpdSchema):
|
|
183
185
|
|
184
186
|
doctype: str = pyd.Field(
|
185
187
|
description='Describes the type and schema of the document. Must always always read "openEPD".',
|
186
|
-
default="
|
188
|
+
default="openEPD",
|
187
189
|
)
|
188
190
|
openepd_version: str = pyd.Field(
|
189
191
|
description="Version of the document format, related to /doctype",
|
@@ -233,3 +235,31 @@ class BaseDocumentFactory(Generic[TRootDocument]):
|
|
233
235
|
)
|
234
236
|
supported_versions = ", ".join(f"{v.major}.x" for v in cls.VERSION_MAP.keys())
|
235
237
|
raise ValueError(f"Version {version} is not supported. Supported versions are: {supported_versions}")
|
238
|
+
|
239
|
+
|
240
|
+
class OpenXpdUUID(str):
|
241
|
+
"""
|
242
|
+
An open xpd UUID format for IDs of openEPD documents.
|
243
|
+
|
244
|
+
See https://github.com/cchangelabs/open-xpd-uuid-lib for details.
|
245
|
+
"""
|
246
|
+
|
247
|
+
def _validate_id(cls, v: str | None) -> str | None:
|
248
|
+
if v is None:
|
249
|
+
return v
|
250
|
+
|
251
|
+
try:
|
252
|
+
open_xpd_uuid.validate(open_xpd_uuid.sanitize(str(v)))
|
253
|
+
return v
|
254
|
+
except open_xpd_uuid.GuidValidationError as e:
|
255
|
+
raise ValueError("Invalid format") from e
|
256
|
+
|
257
|
+
@classmethod
|
258
|
+
def __get_validators__(cls):
|
259
|
+
yield cls._validate_id
|
260
|
+
|
261
|
+
@classmethod
|
262
|
+
def __modify_schema__(cls, field_schema):
|
263
|
+
field_schema.update(
|
264
|
+
example="XC300001",
|
265
|
+
)
|
openepd/model/declaration.py
CHANGED
@@ -17,13 +17,14 @@ import abc
|
|
17
17
|
import datetime
|
18
18
|
|
19
19
|
from openepd.compat.pydantic import pyd
|
20
|
-
from openepd.model.base import BaseOpenEpdSchema, RootDocument
|
20
|
+
from openepd.model.base import BaseOpenEpdSchema, OpenXpdUUID, RootDocument
|
21
21
|
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
25
|
from openepd.model.standard import Standard
|
26
26
|
from openepd.model.validation.common import ReferenceStr
|
27
|
+
from openepd.model.validation.quantity import AmountMass
|
27
28
|
|
28
29
|
DEVELOPER_DESCRIPTION = "The organization responsible for the underlying LCA (and subsequent summarization as EPD)."
|
29
30
|
PROGRAM_OPERATOR_DESCRIPTION = "JSON object for program operator Org"
|
@@ -33,8 +34,7 @@ THIRD_PARTY_VERIFIER_DESCRIPTION = "JSON object for Org that performed a critica
|
|
33
34
|
class BaseDeclaration(RootDocument, abc.ABC):
|
34
35
|
"""Base class for declaration-related documents (EPDs, Industry-wide EPDs, Generic Estimates)."""
|
35
36
|
|
36
|
-
|
37
|
-
id: str | None = pyd.Field(
|
37
|
+
id: OpenXpdUUID | None = pyd.Field(
|
38
38
|
description="The unique ID for this document. To ensure global uniqueness, should be registered at "
|
39
39
|
"open-xpd-uuid.cqd.io/register or a coordinating registry.",
|
40
40
|
example="1u7zsed8",
|
@@ -61,7 +61,7 @@ class BaseDeclaration(RootDocument, abc.ABC):
|
|
61
61
|
"utilized, the declared unit shall refer to the amount of "
|
62
62
|
"product associated with the A1-A3 life cycle stage."
|
63
63
|
)
|
64
|
-
kg_per_declared_unit:
|
64
|
+
kg_per_declared_unit: AmountMass | None = pyd.Field(
|
65
65
|
default=None,
|
66
66
|
description="Mass of the product, in kilograms, per declared unit",
|
67
67
|
example=Amount(qty=12.5, unit="kg").to_serializable(exclude_unset=True),
|
@@ -126,6 +126,39 @@ class BaseDeclaration(RootDocument, abc.ABC):
|
|
126
126
|
""",
|
127
127
|
)
|
128
128
|
|
129
|
+
product_image_small: pyd.AnyUrl | None = pyd.Field(
|
130
|
+
description="Pointer to image illustrating the product, which is no more than 200x200 pixels", default=None
|
131
|
+
)
|
132
|
+
product_image: pyd.AnyUrl | pyd.FileUrl | None = pyd.Field(
|
133
|
+
description="pointer to image illustrating the product no more than 10MB", default=None
|
134
|
+
)
|
135
|
+
declaration_url: str | None = pyd.Field(
|
136
|
+
description="Link to data object on original registrar's site",
|
137
|
+
example="https://epd-online.com/EmbeddedEpdList/Download/6029",
|
138
|
+
)
|
139
|
+
kg_C_per_declared_unit: AmountMass | None = pyd.Field(
|
140
|
+
default=None,
|
141
|
+
description="Mass of elemental carbon, per declared unit, contained in the product itself at the manufacturing "
|
142
|
+
"facility gate. Used (among other things) to check a carbon balance or calculate incineration "
|
143
|
+
"emissions. The source of carbon (e.g. biogenic) is not relevant in this field.",
|
144
|
+
example=Amount(qty=8.76, unit="kg"),
|
145
|
+
)
|
146
|
+
kg_C_biogenic_per_declared_unit: AmountMass | None = pyd.Field(
|
147
|
+
default=None,
|
148
|
+
description="Mass of elemental carbon from biogenic sources, per declared unit, contained in the product "
|
149
|
+
"itself at the manufacturing facility gate. It may be presumed that any biogenic carbon content "
|
150
|
+
"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="kg"),
|
152
|
+
)
|
153
|
+
product_service_life_years: float | None = pyd.Field(
|
154
|
+
gt=0.0009,
|
155
|
+
lt=101,
|
156
|
+
description="Reference service life of the product, in years. Serves as a maximum for replacement interval, "
|
157
|
+
"which may also be constrained by usage or the service life of what the product goes into "
|
158
|
+
"(e.g. a building).",
|
159
|
+
example=50.0,
|
160
|
+
)
|
161
|
+
|
129
162
|
|
130
163
|
class AverageDatasetMixin(pyd.BaseModel, title="Average Dataset"):
|
131
164
|
"""Fields common for average dataset (Industry-wide EPDs, Generic Estimates)."""
|
@@ -184,7 +217,7 @@ class WithEpdDeveloperMixin(pyd.BaseModel):
|
|
184
217
|
class RefBase(BaseOpenEpdSchema, title="Ref Object"):
|
185
218
|
"""Base class for reference-style objects."""
|
186
219
|
|
187
|
-
id:
|
220
|
+
id: OpenXpdUUID | None = pyd.Field(
|
188
221
|
description="The unique ID for this object. To ensure global uniqueness, should be registered at "
|
189
222
|
"open-xpd-uuid.cqd.io/register or a coordinating registry.",
|
190
223
|
example="1u7zsed8",
|
openepd/model/epd.py
CHANGED
@@ -17,7 +17,7 @@ from typing import Annotated
|
|
17
17
|
|
18
18
|
from openepd.compat.pydantic import pyd
|
19
19
|
from openepd.model.base import BaseDocumentFactory, OpenEpdDoctypes
|
20
|
-
from openepd.model.common import
|
20
|
+
from openepd.model.common import Ingredient, WithAltIdsMixin, WithAttachmentsMixin
|
21
21
|
from openepd.model.declaration import (
|
22
22
|
DEVELOPER_DESCRIPTION,
|
23
23
|
PROGRAM_OPERATOR_DESCRIPTION,
|
@@ -53,6 +53,11 @@ class EpdPreviewV0(
|
|
53
53
|
|
54
54
|
"""
|
55
55
|
|
56
|
+
doctype: str = pyd.Field(
|
57
|
+
description='Describes the type and schema of the document. Must always always read "openEPD".',
|
58
|
+
default="openEPD",
|
59
|
+
)
|
60
|
+
|
56
61
|
product_name: str | None = pyd.Field(
|
57
62
|
max_length=200, description="The name of the product described by this EPD", example="Mix 12345AC", default=None
|
58
63
|
)
|
@@ -63,44 +68,13 @@ class EpdPreviewV0(
|
|
63
68
|
max_length=2000,
|
64
69
|
description="1-paragraph description of product. Supports plain text or github flavored markdown.",
|
65
70
|
)
|
66
|
-
product_image_small: pyd.AnyUrl | None = pyd.Field(
|
67
|
-
description="Pointer to image illustrating the product, which is no more than 200x200 pixels", default=None
|
68
|
-
)
|
69
|
-
product_image: pyd.AnyUrl | pyd.FileUrl | None = pyd.Field(
|
70
|
-
description="pointer to image illustrating the product no more than 10MB", default=None
|
71
|
-
)
|
72
|
-
declaration_url: str | None = pyd.Field(
|
73
|
-
description="Link to data object on original registrar's site",
|
74
|
-
example="https://epd-online.com/EmbeddedEpdList/Download/6029",
|
75
|
-
)
|
76
71
|
manufacturer: Org | None = pyd.Field(description=MANUFACTURER_DESCRIPTION)
|
77
72
|
plants: list[Plant] = pyd.Field(
|
78
73
|
max_items=32,
|
79
74
|
description="List of object(s) for one or more plant(s) that this declaration applies to.",
|
80
75
|
default_factory=list,
|
81
76
|
)
|
82
|
-
|
83
|
-
default=None,
|
84
|
-
description="Mass of elemental carbon, per declared unit, contained in the product itself at the manufacturing "
|
85
|
-
"facility gate. Used (among other things) to check a carbon balance or calculate incineration "
|
86
|
-
"emissions. The source of carbon (e.g. biogenic) is not relevant in this field.",
|
87
|
-
example=Amount(qty=8.76, unit="kg"),
|
88
|
-
)
|
89
|
-
kg_C_biogenic_per_declared_unit: Amount | None = pyd.Field(
|
90
|
-
default=None,
|
91
|
-
description="Mass of elemental carbon from biogenic sources, per declared unit, contained in the product "
|
92
|
-
"itself at the manufacturing facility gate. It may be presumed that any biogenic carbon content "
|
93
|
-
"has been accounted for as -44/12 kgCO2e per kg C in stages A1-A3, per EN15804 and ISO 21930.",
|
94
|
-
example=Amount(qty=8.76, unit="kg"),
|
95
|
-
)
|
96
|
-
product_service_life_years: float | None = pyd.Field(
|
97
|
-
gt=0.0009,
|
98
|
-
lt=101,
|
99
|
-
description="Reference service life of the product, in years. Serves as a maximum for replacement interval, "
|
100
|
-
"which may also be constrained by usage or the service life of what the product goes into "
|
101
|
-
"(e.g. a building).",
|
102
|
-
example=50.0,
|
103
|
-
)
|
77
|
+
|
104
78
|
annual_production: float | None = pyd.Field(
|
105
79
|
gt=0,
|
106
80
|
default=None,
|
@@ -149,6 +123,17 @@ class EpdPreviewV0(
|
|
149
123
|
default_factory=list,
|
150
124
|
)
|
151
125
|
|
126
|
+
@pyd.validator("doctype")
|
127
|
+
def validate_doctype(cls, v: str | None) -> str:
|
128
|
+
"""
|
129
|
+
Handle possible mixed case options for doctype.
|
130
|
+
|
131
|
+
Required for backward compatibility as some code might have already used 'doctype: OpenEPD' instead of 'openEPD'
|
132
|
+
"""
|
133
|
+
if not v or v.lower() == "openepd":
|
134
|
+
return "openEPD"
|
135
|
+
raise ValueError("Invalid doctype")
|
136
|
+
|
152
137
|
|
153
138
|
EpdPreview = EpdPreviewV0
|
154
139
|
|
@@ -14,6 +14,7 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
from enum import StrEnum
|
17
|
+
from typing import Literal
|
17
18
|
|
18
19
|
from openepd.compat.pydantic import pyd
|
19
20
|
from openepd.model.base import BaseDocumentFactory, OpenEpdDoctypes
|
@@ -60,7 +61,7 @@ class GenericEstimatePreviewV0(
|
|
60
61
|
|
61
62
|
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
62
63
|
|
63
|
-
doctype:
|
64
|
+
doctype: Literal["openGenericEstimate"] = pyd.Field(
|
64
65
|
description='Describes the type and schema of the document. Must always be "openGenericEstimate"',
|
65
66
|
default="openGenericEstimate",
|
66
67
|
)
|
openepd/model/industry_epd.py
CHANGED
@@ -13,6 +13,8 @@
|
|
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
|
17
|
+
|
16
18
|
from openepd.compat.pydantic import pyd
|
17
19
|
from openepd.model.base import BaseDocumentFactory, OpenEpdDoctypes
|
18
20
|
from openepd.model.common import WithAltIdsMixin, WithAttachmentsMixin
|
@@ -51,7 +53,7 @@ class IndustryEpdPreviewV0(
|
|
51
53
|
|
52
54
|
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
53
55
|
|
54
|
-
doctype:
|
56
|
+
doctype: Literal["openIndustryEpd"] = pyd.Field(
|
55
57
|
description='Describes the type and schema of the document. Must always be "openIndustryEpd"',
|
56
58
|
default="openIndustryEpd",
|
57
59
|
)
|
openepd/model/lcia.py
CHANGED
@@ -204,7 +204,7 @@ class ScopesetByNameBase(BaseOpenEpdSchema):
|
|
204
204
|
|
205
205
|
:return: set of names, for example ['gwp', 'odp]
|
206
206
|
"""
|
207
|
-
return [self.__fields__[f].alias or f for f in self.__fields_set__]
|
207
|
+
return [self.__fields__[f].alias or f for f in self.__fields_set__ if f not in ("ext",)]
|
208
208
|
|
209
209
|
def get_scopeset_by_name(self, name: str) -> ScopeSet | None:
|
210
210
|
"""
|
openepd/model/pcr.py
CHANGED
@@ -18,7 +18,7 @@ from enum import StrEnum
|
|
18
18
|
from typing import Annotated, Optional
|
19
19
|
|
20
20
|
from openepd.compat.pydantic import pyd
|
21
|
-
from openepd.model.base import BaseOpenEpdSchema
|
21
|
+
from openepd.model.base import BaseOpenEpdSchema, OpenXpdUUID
|
22
22
|
from openepd.model.common import Amount, WithAltIdsMixin, WithAttachmentsMixin
|
23
23
|
from openepd.model.org import Org
|
24
24
|
|
@@ -36,7 +36,7 @@ class PcrStatus(StrEnum):
|
|
36
36
|
class PcrRef(BaseOpenEpdSchema):
|
37
37
|
"""Reference to a PCR."""
|
38
38
|
|
39
|
-
id:
|
39
|
+
id: OpenXpdUUID | None = pyd.Field(
|
40
40
|
description="The unique ID for this PCR. To ensure global uniqueness, should be registered "
|
41
41
|
"at open-xpd-uuid.cqd.io/register or a coordinating registry.",
|
42
42
|
example="ec3xpgq2",
|
@@ -56,7 +56,7 @@ class PcrRef(BaseOpenEpdSchema):
|
|
56
56
|
class Pcr(WithAttachmentsMixin, WithAltIdsMixin, BaseOpenEpdSchema):
|
57
57
|
"""Represent a PCR (Product Category Rules)."""
|
58
58
|
|
59
|
-
id:
|
59
|
+
id: OpenXpdUUID | None = pyd.Field(
|
60
60
|
description="The unique ID for this PCR. To ensure global uniqueness, should be registered "
|
61
61
|
"at open-xpd-uuid.cqd.io/register or a coordinating registry.",
|
62
62
|
example="ec3xpgq2",
|
@@ -14,9 +14,10 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
from abc import ABC, abstractmethod
|
17
|
-
from typing import TYPE_CHECKING, Callable, ClassVar
|
17
|
+
from typing import TYPE_CHECKING, Any, Callable, ClassVar
|
18
18
|
|
19
|
-
from openepd.
|
19
|
+
from openepd.compat.pydantic import pyd
|
20
|
+
from openepd.model.common import Amount, OpenEPDUnit
|
20
21
|
|
21
22
|
if TYPE_CHECKING:
|
22
23
|
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
@@ -127,6 +128,32 @@ def validate_quantity_for_new_validator(max_value: str) -> Callable:
|
|
127
128
|
# todo these types should be replaced by Annotated[str, AfterValidator...] as we move completely to pydantic 2
|
128
129
|
|
129
130
|
|
131
|
+
class AmountWithDimensionality(Amount, ABC):
|
132
|
+
"""Class for dimensionality-validated amounts."""
|
133
|
+
|
134
|
+
dimensionality_unit: ClassVar[str | None] = None
|
135
|
+
|
136
|
+
# Unit for dimensionality to validate against, for example "kg"
|
137
|
+
|
138
|
+
@pyd.root_validator
|
139
|
+
def check_dimensionality_matches(cls, values: dict[str, Any]) -> dict[str, Any]:
|
140
|
+
"""Check that this amount conforms to the same dimensionality as dimensionality_unit."""
|
141
|
+
if not cls.dimensionality_unit:
|
142
|
+
return values
|
143
|
+
|
144
|
+
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
145
|
+
|
146
|
+
str_repr = f"{values['qty']} {values['unit']}"
|
147
|
+
validate_unit_factory(cls.dimensionality_unit)(BaseOpenEpdHierarchicalSpec, str_repr)
|
148
|
+
return values
|
149
|
+
|
150
|
+
|
151
|
+
class AmountMass(AmountWithDimensionality):
|
152
|
+
"""Amount of mass, measured in kg, t, etc."""
|
153
|
+
|
154
|
+
dimensionality_unit = OpenEPDUnit.kg
|
155
|
+
|
156
|
+
|
130
157
|
class QuantityStr(str):
|
131
158
|
"""
|
132
159
|
Quantity string type.
|
@@ -1,10 +1,10 @@
|
|
1
1
|
openepd/__init__.py,sha256=Shkfh0Kun0YRhmRDw7LkUj2eQL3X-HnP55u2THOEALw,794
|
2
|
-
openepd/__version__.py,sha256=
|
2
|
+
openepd/__version__.py,sha256=ct2ojZmiO087rEAYSPIKIFv4c6Tf57TQ7E0AKUt3Iyw,639
|
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=DM7i8gugUIEAutEsakEUxFjwgtKmcytkjvNAvfhVYUs,7690
|
6
6
|
openepd/api/average_dataset/industry_epd_sync_api.py,sha256=xoicuZdclf4BTBa2ndG1K2Aog-iZd7_jOqdDPZSCLq4,6286
|
7
|
-
openepd/api/base_sync_client.py,sha256=
|
7
|
+
openepd/api/base_sync_client.py,sha256=IX-q6JdWLMqYHC-hKLXUFRPs-DZZ9Co0NRZ5pSAipAs,20992
|
8
8
|
openepd/api/category/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,620
|
9
9
|
openepd/api/category/dto.py,sha256=tDojagSwT7CTtcYq31Qe_c0P3xKKUWXKdzT5iN6odtk,850
|
10
10
|
openepd/api/category/sync_api.py,sha256=VHHOVbblZGyc4AtbsgQza00trSLuaCO6KfQw6r8vzgg,1371
|
@@ -18,7 +18,7 @@ openepd/api/dto/params.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,620
|
|
18
18
|
openepd/api/epd/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,620
|
19
19
|
openepd/api/epd/dto.py,sha256=NZ76vfUkCEkwDibQd2QCEQP5DZms_NFc9tjoP-mcw3o,4874
|
20
20
|
openepd/api/epd/sync_api.py,sha256=5wuPiM_zVciVtTvsGaaRdf7T6q2CUp7QMZCW0DAjQng,7072
|
21
|
-
openepd/api/errors.py,sha256=
|
21
|
+
openepd/api/errors.py,sha256=Iipd0QW2tbhUu_UjUbmiFWgmrPVgOFHc3uxZN-SX-g4,2868
|
22
22
|
openepd/api/pcr/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,620
|
23
23
|
openepd/api/pcr/sync_api.py,sha256=Riu77h8uLJngKpITOiXYmO7mzjAHpYskUJ6ynyfNG78,1557
|
24
24
|
openepd/api/sync_client.py,sha256=IurnhZrkBQoQIbbfon6TPuhjGpAV_CSTJNeXjIiN0QI,3105
|
@@ -33,18 +33,18 @@ openepd/compat/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,62
|
|
33
33
|
openepd/compat/compat_functional_validators.py,sha256=yz6DfWeg7knBHEN_enpCGGTLRknEsecXfpzD1FDlywY,834
|
34
34
|
openepd/compat/pydantic.py,sha256=DOjSixsylLqMtFAIARu50sGcT4VPXN_c473q_2JwZQ0,1146
|
35
35
|
openepd/model/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,620
|
36
|
-
openepd/model/base.py,sha256=
|
36
|
+
openepd/model/base.py,sha256=OEYNFUTL4BivBNAt_LGowTlDuUjvKMHgf5U5ZBncZwQ,9805
|
37
37
|
openepd/model/category.py,sha256=IQXNGQFQmFZ_H9PRONloX_UOSf1sTMDq1rM1yz8JR0Y,1639
|
38
38
|
openepd/model/common.py,sha256=hXnz2QiQDx3Z7F4BMHlHQ2iddq3OonKrveltl-nOiEI,5468
|
39
|
-
openepd/model/declaration.py,sha256=
|
40
|
-
openepd/model/epd.py,sha256=
|
39
|
+
openepd/model/declaration.py,sha256=9KnmYr3ZLpkbBFVkesaEdDtGpG-SrVFuIOO2ekRyTgk,10796
|
40
|
+
openepd/model/epd.py,sha256=GU7OW6hp9GeLB9PUGqacDYMAJVWmAAHzGp3dZs2aGqo,7479
|
41
41
|
openepd/model/factory.py,sha256=XP7eeQNW5tqwX_4hfuEb3lK6BFQDb4KB0fSN0r8-lCU,2656
|
42
|
-
openepd/model/generic_estimate.py,sha256=
|
42
|
+
openepd/model/generic_estimate.py,sha256=bbU0cR4izSqjZcfxUHNbdO4pllqqd8OaUFikrEgCFoA,3992
|
43
43
|
openepd/model/geography.py,sha256=eCt15zXKDtiteNwXQ675cFwBXQqSpiGpIqwDo4nkOek,42091
|
44
|
-
openepd/model/industry_epd.py,sha256=
|
45
|
-
openepd/model/lcia.py,sha256=
|
44
|
+
openepd/model/industry_epd.py,sha256=rgXhCUDAgzZ9eGio7ExqE3ymP3zTXnrrwcIDvg5YP1A,3285
|
45
|
+
openepd/model/lcia.py,sha256=pVh4LbZgzDuLuM3epdCNLlAp5B0BnUrwggaaDiuPccM,18848
|
46
46
|
openepd/model/org.py,sha256=FHcYh2WOOQrCMyzm0Ow-iP79jMTBPcneidjH6NXIklA,3760
|
47
|
-
openepd/model/pcr.py,sha256=
|
47
|
+
openepd/model/pcr.py,sha256=1abCO00f_zaZrGiBN4fzauQ-5zPhNc31RXFUJzLVIJ0,5426
|
48
48
|
openepd/model/specs/README.md,sha256=W5LSMpZuW5x36cKS4HRfeFsClsRf8J9yHMMICghdc0s,862
|
49
49
|
openepd/model/specs/__init__.py,sha256=CfuCZKFE6xysags8XY9VlW-o_zHEyCu9fGekoj-RJOg,4959
|
50
50
|
openepd/model/specs/asphalt.py,sha256=kyv-WvqujYD5xqi-lS2nSculXLQAuuBbJU_YRCb-5ug,3332
|
@@ -93,11 +93,11 @@ openepd/model/standard.py,sha256=QhGpWN3U27fDcS0Yy1Dk8ElJfD0etet6i_PzoTD6B48,131
|
|
93
93
|
openepd/model/validation/__init__.py,sha256=UGmZGEyMnASrYwEBPHuXmVzHiuCUskUsJEPoHTIo-lg,620
|
94
94
|
openepd/model/validation/common.py,sha256=FLYqK8gYFagx08LCkS0jy3qo4-Zq9VAv5i8ZwF2svkc,2435
|
95
95
|
openepd/model/validation/numbers.py,sha256=tgirqrDGgrSo6APGlW1ozNuVV8mJz_4HCAXS2OUENq0,888
|
96
|
-
openepd/model/validation/quantity.py,sha256=
|
96
|
+
openepd/model/validation/quantity.py,sha256=h4AXXMijFtJRFUb5bi_iRzK2v7v1CtggLi7CyK5bA4s,8349
|
97
97
|
openepd/model/versioning.py,sha256=R_zm6rCrgF3vlJQYbpyWhirdS_Oek16cv_mvZmpuE8I,4473
|
98
98
|
openepd/patch_pydantic.py,sha256=xrkzblatmU9HBzukWkp1cPq9ZSuohoz1p0pQqVKSlKs,4122
|
99
99
|
openepd/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
100
|
-
openepd-4.
|
101
|
-
openepd-4.
|
102
|
-
openepd-4.
|
103
|
-
openepd-4.
|
100
|
+
openepd-4.13.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
101
|
+
openepd-4.13.0.dist-info/METADATA,sha256=eO3P8R_93hVQpLWCZOuDVScaXDdq8wsYkahzx5N7ifo,8705
|
102
|
+
openepd-4.13.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
103
|
+
openepd-4.13.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|