openepd 4.4.0__py3-none-any.whl → 4.5.1__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/__init__.py +6 -0
- openepd/__version__.py +1 -1
- openepd/model/base.py +3 -23
- openepd/model/epd.py +101 -97
- openepd/model/factory.py +26 -6
- openepd/model/generic_estimate.py +85 -0
- openepd/model/geography.py +1739 -0
- openepd/patch_pydantic.py +108 -0
- {openepd-4.4.0.dist-info → openepd-4.5.1.dist-info}/METADATA +23 -10
- {openepd-4.4.0.dist-info → openepd-4.5.1.dist-info}/RECORD +12 -11
- openepd/mypy/__init__.py +0 -15
- openepd/mypy/custom_pydantic_plugin.py +0 -91
- {openepd-4.4.0.dist-info → openepd-4.5.1.dist-info}/LICENSE +0 -0
- {openepd-4.4.0.dist-info → openepd-4.5.1.dist-info}/WHEEL +0 -0
openepd/__init__.py
CHANGED
@@ -13,3 +13,9 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
|
+
import os
|
17
|
+
|
18
|
+
from .patch_pydantic import patch_pydantic
|
19
|
+
|
20
|
+
if os.environ.get("OPENEPD_DISABLE_PYDANTIC_PATCH", "false").lower() not in ("true", "1", "yes"):
|
21
|
+
patch_pydantic()
|
openepd/__version__.py
CHANGED
openepd/model/base.py
CHANGED
@@ -36,6 +36,7 @@ class OpenEpdDoctypes(StrEnum):
|
|
36
36
|
"""Enum of supported openEPD document types."""
|
37
37
|
|
38
38
|
Epd = "openEPD"
|
39
|
+
GenericEstimate = "openGenericEstimate"
|
39
40
|
|
40
41
|
|
41
42
|
def modify_pydantic_schema(schema_dict: dict, cls: type) -> dict:
|
@@ -56,28 +57,7 @@ def modify_pydantic_schema(schema_dict: dict, cls: type) -> dict:
|
|
56
57
|
return schema_dict
|
57
58
|
|
58
59
|
|
59
|
-
class
|
60
|
-
"""
|
61
|
-
Extension of the pydantic's ModelMetaclass which restores class attribute lookup for fields.
|
62
|
-
|
63
|
-
In pydantic, while the model fields are defined in the model as class-level attributes, in runtime they disappear
|
64
|
-
due to ModelMetaclass logic. ModelMetaclass takes the defined attributes, removes them from class dict and puts
|
65
|
-
into a special __fields__ attribute to avoid naming conflict.
|
66
|
-
|
67
|
-
We would like to be able to access the attributes via dot notation in the runtimes, since it makes refactoring
|
68
|
-
easier.
|
69
|
-
|
70
|
-
This class exposes the original fields when accessed via class name. For example, one can call `Pcr.name` and get
|
71
|
-
`ModelField`, in addition to calling `pcr.__fields__` on an instance.
|
72
|
-
"""
|
73
|
-
|
74
|
-
def __getattr__(cls, name: str) -> Any:
|
75
|
-
if name in cls.__fields__:
|
76
|
-
return cls.__fields__[name]
|
77
|
-
return getattr(super, name)
|
78
|
-
|
79
|
-
|
80
|
-
class BaseOpenEpdSchema(pyd.BaseModel, metaclass=PydanticClassAttributeExposeModelMetaclass):
|
60
|
+
class BaseOpenEpdSchema(pyd.BaseModel):
|
81
61
|
"""Base class for all OpenEPD models."""
|
82
62
|
|
83
63
|
ext: dict[str, AnySerializable] | None = pyd.Field(alias="ext", default=None)
|
@@ -227,7 +207,7 @@ class BaseDocumentFactory(Generic[TRootDocument]):
|
|
227
207
|
Extend it to create a factory for a specific document type e.g. for industry epd, epd, etc.
|
228
208
|
"""
|
229
209
|
|
230
|
-
DOCTYPE_CONSTRAINT:
|
210
|
+
DOCTYPE_CONSTRAINT: OpenEpdDoctypes
|
231
211
|
VERSION_MAP: dict[Version, type[TRootDocument]] = {}
|
232
212
|
|
233
213
|
@classmethod
|
openepd/model/epd.py
CHANGED
@@ -17,7 +17,7 @@ import datetime
|
|
17
17
|
from typing import Annotated
|
18
18
|
|
19
19
|
from openepd.compat.pydantic import pyd
|
20
|
-
from openepd.model.base import BaseDocumentFactory, RootDocument
|
20
|
+
from openepd.model.base import BaseDocumentFactory, OpenEpdDoctypes, RootDocument
|
21
21
|
from openepd.model.common import Amount, Ingredient, WithAltIdsMixin, WithAttachmentsMixin
|
22
22
|
from openepd.model.lcia import Impacts, OutputFlowSet, ResourceUseSet
|
23
23
|
from openepd.model.org import Org, Plant
|
@@ -27,54 +27,47 @@ from openepd.model.standard import Standard
|
|
27
27
|
from openepd.model.versioning import OpenEpdVersions, Version
|
28
28
|
|
29
29
|
|
30
|
-
class
|
30
|
+
class BaseDeclaration(RootDocument):
|
31
31
|
"""
|
32
32
|
Base class for EPD documents.
|
33
33
|
|
34
34
|
This class should not be used directly. Use Epd or EpdVx instead.
|
35
35
|
"""
|
36
36
|
|
37
|
-
pass
|
38
|
-
|
39
|
-
|
40
|
-
class EpdV0(WithAttachmentsMixin, WithAltIdsMixin, BaseEpd):
|
41
|
-
"""Represent an EPD."""
|
42
|
-
|
43
|
-
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
44
|
-
|
45
|
-
# TODO: Add validator for open-xpd-uuid on this field
|
46
37
|
id: str | None = pyd.Field(
|
47
38
|
description="The unique ID for this EPD. To ensure global uniqueness, should be registered at "
|
48
39
|
"open-xpd-uuid.cqd.io/register or a coordinating registry.",
|
49
40
|
example="1u7zsed8",
|
50
41
|
default=None,
|
51
42
|
)
|
52
|
-
|
53
|
-
|
43
|
+
date_of_issue: datetime.datetime | None = pyd.Field(
|
44
|
+
example=datetime.datetime(day=11, month=9, year=2019, tzinfo=datetime.timezone.utc),
|
45
|
+
description="Date the EPD was issued. This should be the first day on which the EPD is valid.",
|
54
46
|
)
|
55
|
-
|
56
|
-
|
47
|
+
valid_until: datetime.datetime | None = pyd.Field(
|
48
|
+
example=datetime.datetime(day=11, month=9, year=2028, tzinfo=datetime.timezone.utc),
|
49
|
+
description="Last date the EPD is valid on, including any extensions.",
|
57
50
|
)
|
58
|
-
|
59
|
-
|
60
|
-
description="
|
51
|
+
|
52
|
+
declared_unit: Amount | None = pyd.Field(
|
53
|
+
description="SI declared unit for this EPD. If a functional unit is "
|
54
|
+
"utilized, the declared unit shall refer to the amount of "
|
55
|
+
"product associated with the A1-A3 life cycle stage."
|
56
|
+
)
|
57
|
+
kg_per_declared_unit: Amount | None = pyd.Field(
|
58
|
+
default=None,
|
59
|
+
description="Mass of the product, in kilograms, per declared unit",
|
60
|
+
example=Amount(qty=12.5, unit="kg"),
|
61
61
|
)
|
62
|
+
compliance: list[Standard] = pyd.Field(
|
63
|
+
description="Standard(s) to which this declaration is compliant.", default_factory=list
|
64
|
+
)
|
65
|
+
|
62
66
|
# TODO: add product_alt_names? E.g. ILCD has a list of synonymous names
|
63
67
|
product_classes: dict[str, str | list[str]] = pyd.Field(
|
64
68
|
description="List of classifications, including Masterformat and UNSPC", default_factory=dict
|
65
69
|
)
|
66
|
-
|
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
|
-
version: pyd.PositiveInt | None = pyd.Field(
|
73
|
-
description="Version of this document. The document's issuer should increment it anytime even a single "
|
74
|
-
"character changes, as this value is used to determine the most recent version.",
|
75
|
-
example=1,
|
76
|
-
default=None,
|
77
|
-
)
|
70
|
+
|
78
71
|
language: str | None = pyd.Field(
|
79
72
|
min_length=2,
|
80
73
|
max_length=2,
|
@@ -91,6 +84,80 @@ class EpdV0(WithAttachmentsMixin, WithAltIdsMixin, BaseEpd):
|
|
91
84
|
"number of required fields, to allow for multiple systems to coordinate "
|
92
85
|
"incomplete EPDs.",
|
93
86
|
)
|
87
|
+
impacts: Impacts | None = pyd.Field(
|
88
|
+
description="List of environmental impacts, compiled per one of the standard Impact Assessment methods"
|
89
|
+
)
|
90
|
+
resource_uses: ResourceUseSet | None = pyd.Field(
|
91
|
+
description="Set of Resource Use Indicators, over various LCA scopes"
|
92
|
+
)
|
93
|
+
output_flows: OutputFlowSet | None = pyd.Field(
|
94
|
+
description="Set of Waste and Output Flow indicators which describe the waste categories "
|
95
|
+
"and other material output flows derived from the LCI."
|
96
|
+
)
|
97
|
+
|
98
|
+
pcr: Pcr | None = pyd.Field(
|
99
|
+
description="JSON object for product category rules. Should point to the "
|
100
|
+
"most-specific PCR that applies; the PCR entry should point to any "
|
101
|
+
"parent PCR.",
|
102
|
+
default=None,
|
103
|
+
)
|
104
|
+
lca_discussion: str | None = pyd.Field(
|
105
|
+
max_length=20000,
|
106
|
+
description="""A rich text description containing information for experts reviewing the EPD contents.
|
107
|
+
Text descriptions required by ISO 14025, ISO 21930, EN 15804,, relevant PCRs, or program instructions and which do not
|
108
|
+
have specific openEPD fields should be entered here. This field may be large, and may contain multiple sections
|
109
|
+
separated by github flavored markdown formatting.""",
|
110
|
+
example="""# Packaging
|
111
|
+
|
112
|
+
Information on product-specific packaging: type, composition and possible reuse of packaging materials (paper,
|
113
|
+
strapping, pallets, foils, drums, etc.) shall be included in this Section. The EPD shall describe specific packaging
|
114
|
+
scenario assumptions, including disposition pathways for each packaging material by reuse, recycling, or landfill
|
115
|
+
disposal based on packaging type.*
|
116
|
+
|
117
|
+
# Product Installation
|
118
|
+
|
119
|
+
A description of the type of processing, machinery, tools, dust extraction equipment, auxiliary materials, etc.
|
120
|
+
to be used during installation shall be included. Information on industrial and environmental protection may be
|
121
|
+
included in this section. Any waste treatment included within the system boundary of installation waste should be
|
122
|
+
specified.
|
123
|
+
|
124
|
+
# Use Conditions
|
125
|
+
|
126
|
+
Use-stage environmental impacts of flooring products during building operations depend on product cleaning assumptions.
|
127
|
+
Information on cleaning frequency and cleaning products shall be provided based on the manufacturer’s recommendations.
|
128
|
+
In the absence of primary data, cleaning assumptions shall be documented.
|
129
|
+
""",
|
130
|
+
)
|
131
|
+
|
132
|
+
|
133
|
+
class EpdV0(WithAttachmentsMixin, WithAltIdsMixin, BaseDeclaration):
|
134
|
+
"""Represent an EPD."""
|
135
|
+
|
136
|
+
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
137
|
+
|
138
|
+
# TODO: Add validator for open-xpd-uuid on this field
|
139
|
+
product_name: str | None = pyd.Field(
|
140
|
+
max_length=200, description="The name of the product described by this EPD", example="Mix 12345AC", default=None
|
141
|
+
)
|
142
|
+
product_sku: str | None = pyd.Field(
|
143
|
+
max_length=200, description="Unique stock keeping identifier assigned by manufacturer"
|
144
|
+
)
|
145
|
+
product_description: str | None = pyd.Field(
|
146
|
+
max_length=2000,
|
147
|
+
description="1-paragraph description of product. Supports plain text or github flavored markdown.",
|
148
|
+
)
|
149
|
+
product_image_small: pyd.AnyUrl | None = pyd.Field(
|
150
|
+
description="Pointer to image illustrating the product, which is no more than 200x200 pixels", default=None
|
151
|
+
)
|
152
|
+
product_image: pyd.AnyUrl | pyd.FileUrl | None = pyd.Field(
|
153
|
+
description="pointer to image illustrating the product no more than 10MB", default=None
|
154
|
+
)
|
155
|
+
version: pyd.PositiveInt | None = pyd.Field(
|
156
|
+
description="Version of this document. The document's issuer should increment it anytime even a single "
|
157
|
+
"character changes, as this value is used to determine the most recent version.",
|
158
|
+
example=1,
|
159
|
+
default=None,
|
160
|
+
)
|
94
161
|
declaration_url: str | None = pyd.Field(
|
95
162
|
description="Link to data object on original registrar's site",
|
96
163
|
example="https://epd-online.com/EmbeddedEpdList/Download/6029",
|
@@ -131,30 +198,6 @@ class EpdV0(WithAttachmentsMixin, WithAltIdsMixin, BaseEpd):
|
|
131
198
|
third_party_verifier_email: pyd.EmailStr | None = pyd.Field(
|
132
199
|
description="Email address of the third party verifier", example="john.doe@example.com", default=None
|
133
200
|
)
|
134
|
-
date_of_issue: datetime.datetime | None = pyd.Field(
|
135
|
-
example=datetime.datetime(day=11, month=9, year=2019, tzinfo=datetime.timezone.utc),
|
136
|
-
description="Date the EPD was issued. This should be the first day on which the EPD is valid.",
|
137
|
-
)
|
138
|
-
valid_until: datetime.datetime | None = pyd.Field(
|
139
|
-
example=datetime.datetime(day=11, month=9, year=2028, tzinfo=datetime.timezone.utc),
|
140
|
-
description="Last date the EPD is valid on, including any extensions.",
|
141
|
-
)
|
142
|
-
pcr: Pcr | None = pyd.Field(
|
143
|
-
description="JSON object for product category rules. Should point to the "
|
144
|
-
"most-specific PCR that applies; the PCR entry should point to any "
|
145
|
-
"parent PCR.",
|
146
|
-
default=None,
|
147
|
-
)
|
148
|
-
declared_unit: Amount | None = pyd.Field(
|
149
|
-
description="SI declared unit for this EPD. If a functional unit is "
|
150
|
-
"utilized, the declared unit shall refer to the amount of "
|
151
|
-
"product associated with the A1-A3 life cycle stage."
|
152
|
-
)
|
153
|
-
kg_per_declared_unit: Amount | None = pyd.Field(
|
154
|
-
default=None,
|
155
|
-
description="Mass of the product, in kilograms, per declared unit",
|
156
|
-
example=Amount(qty=12.5, unit="kg"),
|
157
|
-
)
|
158
201
|
kg_C_per_declared_unit: Amount | None = pyd.Field(
|
159
202
|
default=None,
|
160
203
|
description="Mass of elemental carbon, per declared unit, contained in the product itself at the manufacturing "
|
@@ -213,19 +256,7 @@ class EpdV0(WithAttachmentsMixin, WithAltIdsMixin, BaseEpd):
|
|
213
256
|
manufacturing_image: pyd.AnyUrl | None = pyd.Field(
|
214
257
|
description="Pointer (url) to an image illustrating the manufacturing process. No more than 10MB.", default=None
|
215
258
|
)
|
216
|
-
|
217
|
-
description="List of environmental impacts, compiled per one of the standard Impact Assessment methods"
|
218
|
-
)
|
219
|
-
resource_uses: ResourceUseSet | None = pyd.Field(
|
220
|
-
description="Set of Resource Use Indicators, over various LCA scopes"
|
221
|
-
)
|
222
|
-
output_flows: OutputFlowSet | None = pyd.Field(
|
223
|
-
description="Set of Waste and Output Flow indicators which describe the waste categories "
|
224
|
-
"and other material output flows derived from the LCI."
|
225
|
-
)
|
226
|
-
compliance: list[Standard] = pyd.Field(
|
227
|
-
description="Standard(s) to which this declaration is compliant.", default_factory=list
|
228
|
-
)
|
259
|
+
|
229
260
|
specs: Specs = pyd.Field(
|
230
261
|
default_factory=Specs,
|
231
262
|
description="Data structure(s) describing performance specs of product. Unique for each material type.",
|
@@ -236,33 +267,6 @@ class EpdV0(WithAttachmentsMixin, WithAltIdsMixin, BaseEpd):
|
|
236
267
|
"Each one should be an EPD or digitized LCI process.",
|
237
268
|
default_factory=list,
|
238
269
|
)
|
239
|
-
lca_discussion: str | None = pyd.Field(
|
240
|
-
max_length=20000,
|
241
|
-
description="""A rich text description containing information for experts reviewing the EPD contents.
|
242
|
-
Text descriptions required by ISO 14025, ISO 21930, EN 15804,, relevant PCRs, or program instructions and which do not
|
243
|
-
have specific openEPD fields should be entered here. This field may be large, and may contain multiple sections
|
244
|
-
separated by github flavored markdown formatting.""",
|
245
|
-
example="""# Packaging
|
246
|
-
|
247
|
-
Information on product-specific packaging: type, composition and possible reuse of packaging materials (paper,
|
248
|
-
strapping, pallets, foils, drums, etc.) shall be included in this Section. The EPD shall describe specific packaging
|
249
|
-
scenario assumptions, including disposition pathways for each packaging material by reuse, recycling, or landfill
|
250
|
-
disposal based on packaging type.*
|
251
|
-
|
252
|
-
# Product Installation
|
253
|
-
|
254
|
-
A description of the type of processing, machinery, tools, dust extraction equipment, auxiliary materials, etc.
|
255
|
-
to be used during installation shall be included. Information on industrial and environmental protection may be
|
256
|
-
included in this section. Any waste treatment included within the system boundary of installation waste should be
|
257
|
-
specified.
|
258
|
-
|
259
|
-
# Use Conditions
|
260
|
-
|
261
|
-
Use-stage environmental impacts of flooring products during building operations depend on product cleaning assumptions.
|
262
|
-
Information on cleaning frequency and cleaning products shall be provided based on the manufacturer’s recommendations.
|
263
|
-
In the absence of primary data, cleaning assumptions shall be documented.
|
264
|
-
""",
|
265
|
-
)
|
266
270
|
|
267
271
|
@classmethod
|
268
272
|
def get_asset_type(cls) -> str | None:
|
@@ -287,8 +291,8 @@ class EpdV0(WithAttachmentsMixin, WithAltIdsMixin, BaseEpd):
|
|
287
291
|
Epd = EpdV0
|
288
292
|
|
289
293
|
|
290
|
-
class EpdFactory(BaseDocumentFactory[
|
294
|
+
class EpdFactory(BaseDocumentFactory[BaseDeclaration]):
|
291
295
|
"""Factory for EPD objects."""
|
292
296
|
|
293
|
-
DOCTYPE_CONSTRAINT =
|
294
|
-
VERSION_MAP: dict[Version, type[
|
297
|
+
DOCTYPE_CONSTRAINT = OpenEpdDoctypes.Epd
|
298
|
+
VERSION_MAP: dict[Version, type[BaseDeclaration]] = {OpenEpdVersions.Version0: EpdV0}
|
openepd/model/factory.py
CHANGED
@@ -15,24 +15,26 @@
|
|
15
15
|
#
|
16
16
|
from openepd.model.base import BaseDocumentFactory, OpenEpdDoctypes, RootDocument
|
17
17
|
from openepd.model.epd import EpdFactory
|
18
|
+
from openepd.model.generic_estimate import GenericEstimateFactory
|
18
19
|
|
19
20
|
|
20
21
|
class DocumentFactory:
|
21
22
|
"""A factory for creating documents regardless of the type."""
|
22
23
|
|
23
|
-
DOCTYPE_TO_FACTORY: dict[
|
24
|
+
DOCTYPE_TO_FACTORY: dict[OpenEpdDoctypes, type[BaseDocumentFactory]] = {
|
24
25
|
OpenEpdDoctypes.Epd: EpdFactory,
|
26
|
+
OpenEpdDoctypes.GenericEstimate: GenericEstimateFactory,
|
25
27
|
}
|
26
28
|
|
27
29
|
@classmethod
|
28
|
-
def
|
30
|
+
def get_factory(cls, doctype: OpenEpdDoctypes | None) -> type[BaseDocumentFactory]:
|
29
31
|
"""
|
30
|
-
|
32
|
+
Get a document factory by given doctype.
|
31
33
|
|
32
|
-
|
33
|
-
:
|
34
|
+
:param doctype: doctype
|
35
|
+
:return document factory
|
36
|
+
:raise ValueError if doctype not supported or not found.
|
34
37
|
"""
|
35
|
-
doctype = data.get("doctype")
|
36
38
|
if doctype is None:
|
37
39
|
raise ValueError("The document type is not specified.")
|
38
40
|
factory = cls.DOCTYPE_TO_FACTORY.get(doctype)
|
@@ -41,4 +43,22 @@ class DocumentFactory:
|
|
41
43
|
f"The document of type `{doctype}` is not supported. Supported documents are: "
|
42
44
|
+ ", ".join(cls.DOCTYPE_TO_FACTORY.keys())
|
43
45
|
)
|
46
|
+
return factory
|
47
|
+
|
48
|
+
@classmethod
|
49
|
+
def from_dict(cls, data: dict) -> RootDocument:
|
50
|
+
"""
|
51
|
+
Create a document from the dictionary.
|
52
|
+
|
53
|
+
Type of the document will be recognized from the `doctype` field.
|
54
|
+
:raise ValueError: if the document type is not specified or not supported.
|
55
|
+
"""
|
56
|
+
doctype = data.get("doctype")
|
57
|
+
if doctype is None or not isinstance(doctype, (str, OpenEpdDoctypes)):
|
58
|
+
raise ValueError(
|
59
|
+
f"The document type is not specified or not supported. "
|
60
|
+
f"Please specify it in `doctype` field. Supported are: {','.join(cls.DOCTYPE_TO_FACTORY)}"
|
61
|
+
)
|
62
|
+
|
63
|
+
factory = cls.get_factory(OpenEpdDoctypes(doctype))
|
44
64
|
return factory.from_dict(data)
|
@@ -0,0 +1,85 @@
|
|
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 enum import StrEnum
|
17
|
+
|
18
|
+
from openepd.compat.pydantic import pyd
|
19
|
+
from openepd.model.base import BaseDocumentFactory, OpenEpdDoctypes
|
20
|
+
from openepd.model.common import WithAltIdsMixin, WithAttachmentsMixin
|
21
|
+
from openepd.model.epd import BaseDeclaration
|
22
|
+
from openepd.model.geography import Geography
|
23
|
+
from openepd.model.org import Org
|
24
|
+
from openepd.model.versioning import OpenEpdVersions, Version
|
25
|
+
|
26
|
+
|
27
|
+
class LicenseTerms(StrEnum):
|
28
|
+
"""Licensing terms."""
|
29
|
+
|
30
|
+
CC_BY = "CC-BY"
|
31
|
+
"""
|
32
|
+
Creative Commons attribution-only license https://creativecommons.org/licenses/by/4.0/.
|
33
|
+
"""
|
34
|
+
ODbL = "ODbL"
|
35
|
+
"""
|
36
|
+
Open Database License per https://opendatacommons.org/licenses/odbl/
|
37
|
+
"""
|
38
|
+
Government = "Government"
|
39
|
+
"""
|
40
|
+
The data is offered at no charge by a government body such as the USDA or Okobaudat.
|
41
|
+
"""
|
42
|
+
Other = "Other"
|
43
|
+
"""
|
44
|
+
Review estimate documentation to determine license terms.
|
45
|
+
"""
|
46
|
+
|
47
|
+
|
48
|
+
class GenericEstimateV0(WithAttachmentsMixin, WithAltIdsMixin, BaseDeclaration):
|
49
|
+
"""Represent a Generic Estimate."""
|
50
|
+
|
51
|
+
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
52
|
+
|
53
|
+
doctype: str = pyd.Field(
|
54
|
+
description='Describes the type and schema of the document. Must always be "openGenericEstimate"',
|
55
|
+
default="openGenericEstimate",
|
56
|
+
)
|
57
|
+
|
58
|
+
name: str | None = pyd.Field(max_length=200, description="", default=None)
|
59
|
+
description: str | None = pyd.Field(
|
60
|
+
max_length=2000,
|
61
|
+
description="1-paragraph description of the Generic Estimate. Supports plain text or github flavored markdown.",
|
62
|
+
)
|
63
|
+
|
64
|
+
publisher: Org | None = pyd.Field(description="Organization that published the LCA results.")
|
65
|
+
reviewer_email: pyd.EmailStr | None = pyd.Field(
|
66
|
+
description="Email address of the third party verifier", example="john.doe@example.com", default=None
|
67
|
+
)
|
68
|
+
reviewer: Org | None = pyd.Field(description="Org that performed a critical review of the LCA.")
|
69
|
+
license_terms: LicenseTerms | None = pyd.Field(description="The license terms for use of the data.")
|
70
|
+
geography: list[Geography] | None = pyd.Field(
|
71
|
+
"Jurisdiction(s) in which the LCA result is applicable. An empty array, or absent properties, implies global applicability."
|
72
|
+
)
|
73
|
+
model_repository: pyd.AnyUrl | None = pyd.Field(
|
74
|
+
default=None, description="A link to the shared git repository containing the LCA model used for this estimate."
|
75
|
+
)
|
76
|
+
|
77
|
+
|
78
|
+
GenericEstimate = GenericEstimateV0
|
79
|
+
|
80
|
+
|
81
|
+
class GenericEstimateFactory(BaseDocumentFactory[GenericEstimate]):
|
82
|
+
"""Factory for EPD objects."""
|
83
|
+
|
84
|
+
DOCTYPE_CONSTRAINT = OpenEpdDoctypes.GenericEstimate
|
85
|
+
VERSION_MAP: dict[Version, type[GenericEstimate]] = {OpenEpdVersions.Version0: GenericEstimateV0}
|