openepd 4.10.0__tar.gz → 4.11.0__tar.gz
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-4.10.0 → openepd-4.11.0}/PKG-INFO +6 -1
- {openepd-4.10.0 → openepd-4.11.0}/README.md +5 -0
- {openepd-4.10.0 → openepd-4.11.0}/pyproject.toml +1 -1
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/__version__.py +1 -1
- openepd-4.11.0/src/openepd/api/average_dataset/generic_estimate_sync_api.py +200 -0
- openepd-4.11.0/src/openepd/api/average_dataset/industry_epd_sync_api.py +164 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/common.py +11 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/sync_client.py +18 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/declaration.py +3 -2
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/generic_estimate.py +3 -13
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/geography.py +1 -1
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/lcia.py +10 -0
- openepd-4.11.0/src/openepd/model/validation/__init__.py +15 -0
- {openepd-4.10.0 → openepd-4.11.0}/LICENSE +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/__init__.py +0 -0
- {openepd-4.10.0/src/openepd/api/category → openepd-4.11.0/src/openepd/api/average_dataset}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/base_sync_client.py +0 -0
- {openepd-4.10.0/src/openepd/api/dto → openepd-4.11.0/src/openepd/api/category}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/category/dto.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/category/sync_api.py +0 -0
- {openepd-4.10.0/src/openepd/api/epd → openepd-4.11.0/src/openepd/api/dto}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/dto/base.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/dto/common.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/dto/meta.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/dto/mf.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/dto/params.py +0 -0
- {openepd-4.10.0/src/openepd/api/pcr → openepd-4.11.0/src/openepd/api/epd}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/epd/dto.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/epd/sync_api.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/errors.py +0 -0
- {openepd-4.10.0/src/openepd/api/test → openepd-4.11.0/src/openepd/api/pcr}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/pcr/sync_api.py +0 -0
- {openepd-4.10.0/src/openepd/bundle → openepd-4.11.0/src/openepd/api/test}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/api/utils.py +0 -0
- {openepd-4.10.0/src/openepd/compat → openepd-4.11.0/src/openepd/bundle}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/bundle/base.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/bundle/model.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/bundle/reader.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/bundle/writer.py +0 -0
- {openepd-4.10.0/src/openepd/model → openepd-4.11.0/src/openepd/compat}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/compat/compat_functional_validators.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/compat/pydantic.py +0 -0
- {openepd-4.10.0/src/openepd/model/specs/generated → openepd-4.11.0/src/openepd/model}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/base.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/category.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/common.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/epd.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/factory.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/industry_epd.py +2 -2
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/org.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/pcr.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/README.md +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/asphalt.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/base.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/concrete.py +0 -0
- {openepd-4.10.0/src/openepd/model/specs/generated/mixins → openepd-4.11.0/src/openepd/model/specs/generated}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/accessories.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/aggregates.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/aluminium.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/asphalt.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/bulk_materials.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/cast_decks_and_underlayment.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/cladding.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/cmu.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/common.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/concrete.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/conveying_equipment.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/electrical.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/electrical_transmission_and_distribution_equipment.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/electricity.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/enums.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/finishes.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/fire_and_smoke_protection.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/furnishings.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/grouting.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/manufacturing_inputs.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/masonry.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/material_handling.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/mechanical.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/mechanical_insulation.py +0 -0
- {openepd-4.10.0/src/openepd/model/validation → openepd-4.11.0/src/openepd/model/specs/generated/mixins}/__init__.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/mixins/conduit_mixin.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/network_infrastructure.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/openings.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/other_electrical_equipment.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/other_materials.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/plumbing.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/precast_concrete.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/sheathing.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/steel.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/thermal_moisture_protection.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/utility_piping.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/wood.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/wood_joists.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/standard.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/validation/common.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/validation/numbers.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/validation/quantity.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/versioning.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/patch_pydantic.py +0 -0
- {openepd-4.10.0 → openepd-4.11.0}/src/openepd/py.typed +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: openepd
|
3
|
-
Version: 4.
|
3
|
+
Version: 4.11.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
|
@@ -164,6 +164,11 @@ The geography and country enums are generated from several sources, including py
|
|
164
164
|
codes, UN m49 codification, and special regions. To update the enums, first update any of these sources, then use
|
165
165
|
`make codegen`. See 'tools/openepd/codegen' for details.
|
166
166
|
|
167
|
+
## Development
|
168
|
+
|
169
|
+
Windows is not supported for development. You can use WSL2 with Ubuntu 20.04 or higher.
|
170
|
+
Instructions are the same as for regular GNU/Linux installation.
|
171
|
+
|
167
172
|
# Credits
|
168
173
|
|
169
174
|
This library has been written and maintained by [C-Change Labs](https://c-change-labs.com/).
|
@@ -138,6 +138,11 @@ The geography and country enums are generated from several sources, including py
|
|
138
138
|
codes, UN m49 codification, and special regions. To update the enums, first update any of these sources, then use
|
139
139
|
`make codegen`. See 'tools/openepd/codegen' for details.
|
140
140
|
|
141
|
+
## Development
|
142
|
+
|
143
|
+
Windows is not supported for development. You can use WSL2 with Ubuntu 20.04 or higher.
|
144
|
+
Instructions are the same as for regular GNU/Linux installation.
|
145
|
+
|
141
146
|
# Credits
|
142
147
|
|
143
148
|
This library has been written and maintained by [C-Change Labs](https://c-change-labs.com/).
|
@@ -0,0 +1,200 @@
|
|
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 Literal, TypeAlias, overload
|
17
|
+
|
18
|
+
from requests import Response
|
19
|
+
|
20
|
+
from openepd.api.base_sync_client import BaseApiMethodGroup
|
21
|
+
from openepd.api.common import StreamingListResponse, paging_meta_from_v1_api
|
22
|
+
from openepd.api.dto.common import BaseMeta, OpenEpdApiResponse
|
23
|
+
from openepd.api.dto.meta import PagingMetaMixin
|
24
|
+
from openepd.api.utils import encode_path_param
|
25
|
+
from openepd.model.generic_estimate import (
|
26
|
+
GenericEstimate,
|
27
|
+
GenericEstimatePreview,
|
28
|
+
GenericEstimateRef,
|
29
|
+
GenericEstimateWithDeps,
|
30
|
+
)
|
31
|
+
|
32
|
+
|
33
|
+
class GenericEstimateApi(BaseApiMethodGroup):
|
34
|
+
"""API methods for Generic Estimates."""
|
35
|
+
|
36
|
+
@overload
|
37
|
+
def get_by_open_xpd_uuid(self, uuid: str, with_response: Literal[True]) -> tuple[GenericEstimate, Response]: ...
|
38
|
+
|
39
|
+
@overload
|
40
|
+
def get_by_open_xpd_uuid(self, uuid: str, with_response: Literal[False] = False) -> GenericEstimate: ...
|
41
|
+
|
42
|
+
def get_by_open_xpd_uuid(
|
43
|
+
self, uuid: str, with_response: bool = False
|
44
|
+
) -> GenericEstimate | tuple[GenericEstimate, Response]:
|
45
|
+
"""
|
46
|
+
Get Generic Estimate by OpenEPD UUID.
|
47
|
+
|
48
|
+
:param uuid: Open xPD UUID
|
49
|
+
:param with_response: whether to return just object or with response
|
50
|
+
:return: GE or GE with response depending on param with_response
|
51
|
+
:raise ObjectNotFound: if Generic Estimate is not found
|
52
|
+
"""
|
53
|
+
response = self._client.do_request("get", f"/generic_estimates/{uuid}")
|
54
|
+
if with_response:
|
55
|
+
return GenericEstimate.parse_obj(response.json()), response
|
56
|
+
return GenericEstimate.parse_obj(response.json())
|
57
|
+
|
58
|
+
@overload
|
59
|
+
def post_with_refs(
|
60
|
+
self, ge: GenericEstimateWithDeps, with_response: Literal[True]
|
61
|
+
) -> tuple[GenericEstimate, Response]: ...
|
62
|
+
|
63
|
+
@overload
|
64
|
+
def post_with_refs(self, ge: GenericEstimateWithDeps, with_response: Literal[False] = False) -> GenericEstimate: ...
|
65
|
+
|
66
|
+
def post_with_refs(
|
67
|
+
self, ge: GenericEstimateWithDeps, with_response: bool = False
|
68
|
+
) -> GenericEstimate | tuple[GenericEstimate, Response]:
|
69
|
+
"""
|
70
|
+
Post an GenericEstimate with references.
|
71
|
+
|
72
|
+
:param ge: GenericEstimate
|
73
|
+
:param with_response: return the response object togather with the GenericEstimate
|
74
|
+
:return: GenericEstimate alone, or GenericEstimate with HTTP Response object depending on parameter
|
75
|
+
"""
|
76
|
+
response = self._client.do_request(
|
77
|
+
"patch",
|
78
|
+
"/generic_estimates/post_with_refs",
|
79
|
+
json=ge.to_serializable(exclude_unset=True, exclude_defaults=True, by_alias=True),
|
80
|
+
)
|
81
|
+
content = response.json()
|
82
|
+
if with_response:
|
83
|
+
return GenericEstimate.parse_obj(content), response
|
84
|
+
return GenericEstimate.parse_obj(content)
|
85
|
+
|
86
|
+
@overload
|
87
|
+
def create(self, ge: GenericEstimate, with_response: Literal[True]) -> tuple[GenericEstimateRef, Response]: ...
|
88
|
+
|
89
|
+
@overload
|
90
|
+
def create(self, ge: GenericEstimate, with_response: Literal[False] = False) -> GenericEstimateRef: ...
|
91
|
+
|
92
|
+
def create(
|
93
|
+
self, ge: GenericEstimate, with_response: bool = False
|
94
|
+
) -> GenericEstimateRef | tuple[GenericEstimateRef, Response]:
|
95
|
+
"""
|
96
|
+
Create a Generic Estimate.
|
97
|
+
|
98
|
+
:param ge: Generic Estimate
|
99
|
+
:param with_response: return the response object together with the EPD
|
100
|
+
:return: Generic Estimate or Generic Estimate with HTTP Response object depending on parameter
|
101
|
+
"""
|
102
|
+
response = self._client.do_request(
|
103
|
+
"post",
|
104
|
+
"/generic_estimates",
|
105
|
+
json=ge.to_serializable(exclude_unset=True, exclude_defaults=True, by_alias=True),
|
106
|
+
)
|
107
|
+
content = response.json()
|
108
|
+
if with_response:
|
109
|
+
return GenericEstimateRef.parse_obj(content), response
|
110
|
+
return GenericEstimateRef.parse_obj(content)
|
111
|
+
|
112
|
+
@overload
|
113
|
+
def edit(self, ge: GenericEstimate, with_response: Literal[True]) -> tuple[GenericEstimateRef, Response]: ...
|
114
|
+
|
115
|
+
@overload
|
116
|
+
def edit(self, ge: GenericEstimate, with_response: Literal[False] = False) -> GenericEstimateRef: ...
|
117
|
+
|
118
|
+
def edit(
|
119
|
+
self, ge: GenericEstimate, with_response: bool = False
|
120
|
+
) -> GenericEstimateRef | tuple[GenericEstimateRef, Response]:
|
121
|
+
"""
|
122
|
+
Edit a Generic Estimate.
|
123
|
+
|
124
|
+
:param ge: GenericEstimate
|
125
|
+
:param with_response: return the response object together with the GE
|
126
|
+
:return: GE or GE with HTTP Response object depending on parameter
|
127
|
+
"""
|
128
|
+
ge_id = ge.id
|
129
|
+
if not ge_id:
|
130
|
+
raise ValueError("The ID must be set to edit a GenericEstimate.")
|
131
|
+
|
132
|
+
response = self._client.do_request(
|
133
|
+
"put",
|
134
|
+
f"/generic_estimates/{encode_path_param(ge_id)}",
|
135
|
+
json=ge.to_serializable(exclude_unset=True, exclude_defaults=True, by_alias=True),
|
136
|
+
)
|
137
|
+
content = response.json()
|
138
|
+
if with_response:
|
139
|
+
return GenericEstimateRef.parse_obj(content), response
|
140
|
+
return GenericEstimateRef.parse_obj(content)
|
141
|
+
|
142
|
+
@overload
|
143
|
+
def list_raw(
|
144
|
+
self, page_num: int, page_size: int, with_response: Literal[False] = False
|
145
|
+
) -> list[GenericEstimatePreview]: ...
|
146
|
+
|
147
|
+
@overload
|
148
|
+
def list_raw(
|
149
|
+
self, page_num: int, page_size: int, with_response: Literal[True]
|
150
|
+
) -> tuple[list[GenericEstimatePreview], Response]: ...
|
151
|
+
|
152
|
+
def list_raw(
|
153
|
+
self, page_num: int = 1, page_size: int = 10, with_response: bool = False
|
154
|
+
) -> list[GenericEstimatePreview] | tuple[list[GenericEstimatePreview], Response]:
|
155
|
+
"""
|
156
|
+
List generic estimates.
|
157
|
+
|
158
|
+
:param page_num: page number
|
159
|
+
:param page_size: page size
|
160
|
+
:param with_response: whether to return just object or with response
|
161
|
+
|
162
|
+
:return: GE or GE with HTTP Response object depending on parameter
|
163
|
+
"""
|
164
|
+
response = self._client.do_request(
|
165
|
+
"get",
|
166
|
+
"/generic_estimates",
|
167
|
+
params=dict(
|
168
|
+
page_number=page_num,
|
169
|
+
page_size=page_size,
|
170
|
+
),
|
171
|
+
)
|
172
|
+
data = [GenericEstimatePreview.parse_obj(o) for o in response.json()]
|
173
|
+
if with_response:
|
174
|
+
return data, response
|
175
|
+
return data
|
176
|
+
|
177
|
+
def list(self, page_size: int | None = None) -> StreamingListResponse[GenericEstimatePreview]:
|
178
|
+
"""
|
179
|
+
List GenericEstimates.
|
180
|
+
|
181
|
+
:param page_size: page size, None for default
|
182
|
+
:return: streaming list of GEs
|
183
|
+
"""
|
184
|
+
|
185
|
+
def _get_page(p_num: int, p_size: int) -> GenericEstimateListResponse:
|
186
|
+
data_list, response = self.list_raw(page_num=p_num, page_size=p_size, with_response=True)
|
187
|
+
return GenericEstimateListResponse(
|
188
|
+
payload=data_list, meta=GenericEstimateSearchMeta(paging=paging_meta_from_v1_api(response))
|
189
|
+
)
|
190
|
+
|
191
|
+
return StreamingListResponse[GenericEstimatePreview](_get_page, page_size=page_size)
|
192
|
+
|
193
|
+
|
194
|
+
class GenericEstimateSearchMeta(PagingMetaMixin, BaseMeta):
|
195
|
+
"""Metadata for EPD Search endpoint."""
|
196
|
+
|
197
|
+
pass
|
198
|
+
|
199
|
+
|
200
|
+
GenericEstimateListResponse: TypeAlias = OpenEpdApiResponse[list[GenericEstimatePreview], GenericEstimateSearchMeta]
|
@@ -0,0 +1,164 @@
|
|
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 Literal, TypeAlias, overload
|
17
|
+
|
18
|
+
from requests import Response
|
19
|
+
|
20
|
+
from openepd.api.base_sync_client import BaseApiMethodGroup
|
21
|
+
from openepd.api.common import StreamingListResponse, paging_meta_from_v1_api
|
22
|
+
from openepd.api.dto.common import BaseMeta, OpenEpdApiResponse
|
23
|
+
from openepd.api.dto.meta import PagingMetaMixin
|
24
|
+
from openepd.api.utils import encode_path_param
|
25
|
+
from openepd.model.industry_epd import IndustryEpd, IndustryEpdPreview, IndustryEpdRef
|
26
|
+
|
27
|
+
|
28
|
+
class IndustryEpdApi(BaseApiMethodGroup):
|
29
|
+
"""API methods for Industry EPD."""
|
30
|
+
|
31
|
+
@overload
|
32
|
+
def get_by_open_xpd_uuid(self, uuid: str, with_response: Literal[True]) -> tuple[IndustryEpd, Response]: ...
|
33
|
+
|
34
|
+
@overload
|
35
|
+
def get_by_open_xpd_uuid(self, uuid: str, with_response: Literal[False] = False) -> IndustryEpd: ...
|
36
|
+
|
37
|
+
def get_by_open_xpd_uuid(
|
38
|
+
self, uuid: str, with_response: bool = False
|
39
|
+
) -> IndustryEpd | tuple[IndustryEpd, Response]:
|
40
|
+
"""
|
41
|
+
Get Industry EPD by OpenEPD UUID.
|
42
|
+
|
43
|
+
:param uuid: OpenEPD UUID
|
44
|
+
:param with_response: whether to return just object or with response
|
45
|
+
:return: IEPD or IEPD with response depending on param with_response
|
46
|
+
:raise ObjectNotFound: if Industry EPD is not found
|
47
|
+
"""
|
48
|
+
response = self._client.do_request("get", f"/industry_epds/{uuid}")
|
49
|
+
if with_response:
|
50
|
+
return IndustryEpd.parse_obj(response.json()), response
|
51
|
+
return IndustryEpd.parse_obj(response.json())
|
52
|
+
|
53
|
+
@overload
|
54
|
+
def create(self, iepd: IndustryEpd, with_response: Literal[True]) -> tuple[IndustryEpdRef, Response]: ...
|
55
|
+
|
56
|
+
@overload
|
57
|
+
def create(self, iepd: IndustryEpd, with_response: Literal[False] = False) -> IndustryEpdRef: ...
|
58
|
+
|
59
|
+
def create(
|
60
|
+
self, iepd: IndustryEpd, with_response: bool = False
|
61
|
+
) -> IndustryEpdRef | tuple[IndustryEpdRef, Response]:
|
62
|
+
"""
|
63
|
+
Create an Industry EPD.
|
64
|
+
|
65
|
+
:param iepd: Industry EPD
|
66
|
+
:param with_response: return the response object together with the EPD
|
67
|
+
:return: Industry EPD or Industry EPD with HTTP Response object depending on parameter
|
68
|
+
"""
|
69
|
+
response = self._client.do_request(
|
70
|
+
"post",
|
71
|
+
"/industry_epds",
|
72
|
+
json=iepd.to_serializable(exclude_unset=True, exclude_defaults=True, by_alias=True),
|
73
|
+
)
|
74
|
+
content = response.json()
|
75
|
+
if with_response:
|
76
|
+
return IndustryEpdRef.parse_obj(content), response
|
77
|
+
return IndustryEpdRef.parse_obj(content)
|
78
|
+
|
79
|
+
@overload
|
80
|
+
def edit(self, iepd: IndustryEpd, with_response: Literal[True]) -> tuple[IndustryEpdRef, Response]: ...
|
81
|
+
|
82
|
+
@overload
|
83
|
+
def edit(self, iepd: IndustryEpd, with_response: Literal[False] = False) -> IndustryEpdRef: ...
|
84
|
+
|
85
|
+
def edit(self, iepd: IndustryEpd, with_response: bool = False) -> IndustryEpdRef | tuple[IndustryEpdRef, Response]:
|
86
|
+
"""
|
87
|
+
Edit an Industr EPD.
|
88
|
+
|
89
|
+
:param iepd: IndustryEpd
|
90
|
+
:param with_response: return the response object together with the IEPD
|
91
|
+
:return: IEPD or IEPD with HTTP Response object depending on parameter
|
92
|
+
"""
|
93
|
+
iepd_id = iepd.id
|
94
|
+
if not iepd_id:
|
95
|
+
raise ValueError("The ID must be set to edit a IndustryEpd.")
|
96
|
+
|
97
|
+
response = self._client.do_request(
|
98
|
+
"put",
|
99
|
+
f"/industry_epds/{encode_path_param(iepd_id)}",
|
100
|
+
json=iepd.to_serializable(exclude_unset=True, exclude_defaults=True, by_alias=True),
|
101
|
+
)
|
102
|
+
content = response.json()
|
103
|
+
if with_response:
|
104
|
+
return IndustryEpdRef.parse_obj(content), response
|
105
|
+
return IndustryEpdRef.parse_obj(content)
|
106
|
+
|
107
|
+
@overload
|
108
|
+
def list_raw(
|
109
|
+
self, page_num: int, page_size: int, with_response: Literal[False] = False
|
110
|
+
) -> list[IndustryEpdPreview]: ...
|
111
|
+
|
112
|
+
@overload
|
113
|
+
def list_raw(
|
114
|
+
self, page_num: int, page_size: int, with_response: Literal[True]
|
115
|
+
) -> tuple[list[IndustryEpdPreview], Response]: ...
|
116
|
+
|
117
|
+
def list_raw(
|
118
|
+
self, page_num: int = 1, page_size: int = 10, with_response: bool = False
|
119
|
+
) -> list[IndustryEpdPreview] | tuple[list[IndustryEpdPreview], Response]:
|
120
|
+
"""
|
121
|
+
List industry epds.
|
122
|
+
|
123
|
+
:param page_num: page number
|
124
|
+
:param page_size: page size
|
125
|
+
:param with_response: whether to return just object or with response
|
126
|
+
:return: list of IEPDs or list of IEPDs with response depending on param with_response
|
127
|
+
"""
|
128
|
+
response = self._client.do_request(
|
129
|
+
"get",
|
130
|
+
"/industry_epds",
|
131
|
+
params=dict(
|
132
|
+
page_number=page_num,
|
133
|
+
page_size=page_size,
|
134
|
+
),
|
135
|
+
)
|
136
|
+
data = [IndustryEpdPreview.parse_obj(o) for o in response.json()]
|
137
|
+
if with_response:
|
138
|
+
return data, response
|
139
|
+
return data
|
140
|
+
|
141
|
+
def list(self, page_size: int | None = None) -> StreamingListResponse[IndustryEpdPreview]:
|
142
|
+
"""
|
143
|
+
List IndustryEpds.
|
144
|
+
|
145
|
+
:param page_size: page size, None for default
|
146
|
+
:return: streaming list of IEPDs
|
147
|
+
"""
|
148
|
+
|
149
|
+
def _get_page(p_num: int, p_size: int) -> IndustryEpdListResponse:
|
150
|
+
data_list, response = self.list_raw(page_num=p_num, page_size=p_size, with_response=True)
|
151
|
+
return IndustryEpdListResponse(
|
152
|
+
payload=data_list, meta=IndustryEpdSearchMeta(paging=paging_meta_from_v1_api(response))
|
153
|
+
)
|
154
|
+
|
155
|
+
return StreamingListResponse[IndustryEpdPreview](_get_page, page_size=page_size)
|
156
|
+
|
157
|
+
|
158
|
+
class IndustryEpdSearchMeta(PagingMetaMixin, BaseMeta):
|
159
|
+
"""Metadata for EPD Search endpoint."""
|
160
|
+
|
161
|
+
pass
|
162
|
+
|
163
|
+
|
164
|
+
IndustryEpdListResponse: TypeAlias = OpenEpdApiResponse[list[IndustryEpdPreview], IndustryEpdSearchMeta]
|
@@ -20,6 +20,8 @@ import threading
|
|
20
20
|
from time import sleep
|
21
21
|
from typing import Callable, Generic, Iterator, cast
|
22
22
|
|
23
|
+
from requests import Response
|
24
|
+
|
23
25
|
from openepd.api.dto.common import DEFAULT_PAGE_SIZE, MetaCollectionDto, OpenEpdApiResponse
|
24
26
|
from openepd.api.dto.meta import PagingMeta, PagingMetaMixin
|
25
27
|
from openepd.model.base import TOpenEpdObject
|
@@ -233,3 +235,12 @@ def no_trailing_slash(val: str) -> str:
|
|
233
235
|
while val.endswith("/"):
|
234
236
|
val = val[:-1]
|
235
237
|
return val
|
238
|
+
|
239
|
+
|
240
|
+
def paging_meta_from_v1_api(r: Response) -> PagingMeta:
|
241
|
+
"""Return a PagingMeta dto from v1 API format with data in headers."""
|
242
|
+
return PagingMeta(
|
243
|
+
total_count=int(r.headers["X-Total-Count"]),
|
244
|
+
total_pages=int(r.headers["X-Total-Pages"]),
|
245
|
+
page_size=int(r.headers["X-Page-Size"]),
|
246
|
+
)
|
@@ -17,6 +17,8 @@ __all__ = ("OpenEpdApiClientSync",)
|
|
17
17
|
|
18
18
|
from requests.auth import AuthBase
|
19
19
|
|
20
|
+
from openepd.api.average_dataset.generic_estimate_sync_api import GenericEstimateApi
|
21
|
+
from openepd.api.average_dataset.industry_epd_sync_api import IndustryEpdApi
|
20
22
|
from openepd.api.base_sync_client import SyncHttpClient, TokenAuth
|
21
23
|
from openepd.api.category.sync_api import CategoryApi
|
22
24
|
from openepd.api.epd.sync_api import EpdApi
|
@@ -40,6 +42,8 @@ class OpenEpdApiClientSync:
|
|
40
42
|
self.__epd_api: EpdApi | None = None
|
41
43
|
self.__pcr_api: PcrApi | None = None
|
42
44
|
self.__category_api: CategoryApi | None = None
|
45
|
+
self.__generic_estimate_api: GenericEstimateApi | None = None
|
46
|
+
self.__industry_epd_api: IndustryEpdApi | None = None
|
43
47
|
|
44
48
|
@property
|
45
49
|
def epds(self) -> EpdApi:
|
@@ -61,3 +65,17 @@ class OpenEpdApiClientSync:
|
|
61
65
|
if self.__category_api is None:
|
62
66
|
self.__category_api = CategoryApi(self._http_client)
|
63
67
|
return self.__category_api
|
68
|
+
|
69
|
+
@property
|
70
|
+
def industry_epds(self) -> IndustryEpdApi:
|
71
|
+
"""Get the Category API."""
|
72
|
+
if self.__industry_epd_api is None:
|
73
|
+
self.__industry_epd_api = IndustryEpdApi(self._http_client)
|
74
|
+
return self.__industry_epd_api
|
75
|
+
|
76
|
+
@property
|
77
|
+
def generic_estimates(self) -> GenericEstimateApi:
|
78
|
+
"""Get the GE API."""
|
79
|
+
if self.__generic_estimate_api is None:
|
80
|
+
self.__generic_estimate_api = GenericEstimateApi(self._http_client)
|
81
|
+
return self.__generic_estimate_api
|
@@ -57,7 +57,7 @@ class BaseDeclaration(RootDocument, abc.ABC):
|
|
57
57
|
kg_per_declared_unit: Amount | None = pyd.Field(
|
58
58
|
default=None,
|
59
59
|
description="Mass of the product, in kilograms, per declared unit",
|
60
|
-
example=Amount(qty=12.5, unit="kg"),
|
60
|
+
example=Amount(qty=12.5, unit="kg").to_serializable(exclude_unset=True),
|
61
61
|
)
|
62
62
|
compliance: list[Standard] = pyd.Field(
|
63
63
|
description="Standard(s) to which this document is compliant.", default_factory=list
|
@@ -129,7 +129,8 @@ class AverageDatasetMixin(pyd.BaseModel, title="Average Dataset"):
|
|
129
129
|
)
|
130
130
|
|
131
131
|
geography: list[Geography] | None = pyd.Field(
|
132
|
-
"Jurisdiction(s) in which the LCA result is applicable. An empty array, or absent properties,
|
132
|
+
description="Jurisdiction(s) in which the LCA result is applicable. An empty array, or absent properties, "
|
133
|
+
"implies global applicability.",
|
133
134
|
)
|
134
135
|
|
135
136
|
|
@@ -58,6 +58,8 @@ class GenericEstimatePreviewV0(
|
|
58
58
|
Excludes LCIA data.
|
59
59
|
"""
|
60
60
|
|
61
|
+
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
62
|
+
|
61
63
|
doctype: str = pyd.Field(
|
62
64
|
description='Describes the type and schema of the document. Must always be "openGenericEstimate"',
|
63
65
|
default="openGenericEstimate",
|
@@ -79,15 +81,7 @@ GenericEstimatePreview = GenericEstimatePreviewV0
|
|
79
81
|
|
80
82
|
|
81
83
|
class GenericEstimateV0(GenericEstimatePreviewV0, WithLciaMixin, WithAltIdsMixin, title="Generic Estimate (Full)"):
|
82
|
-
"""
|
83
|
-
Full Generic Estimate object.
|
84
|
-
|
85
|
-
This is considered the most complete valid openEPD object for GenericEstimate. In addition to it, several related
|
86
|
-
models are defined, either with fewer fields (to be used in APIs for list requests) or with more relaxed structure
|
87
|
-
to support related entities matching.
|
88
|
-
"""
|
89
|
-
|
90
|
-
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
84
|
+
"""Full Generic Estimate object."""
|
91
85
|
|
92
86
|
|
93
87
|
GenericEstimate = GenericEstimateV0
|
@@ -98,10 +92,6 @@ class GenericEstimateWithDepsV0(GenericEstimateV0, title="Generic Estimate (with
|
|
98
92
|
Expanded version of the GenericEstimate.
|
99
93
|
|
100
94
|
Contains related entities - orgs - with full fields, to support object matching in implementations.
|
101
|
-
|
102
|
-
For now the implementation matches the above GenericEstimate entity, but they will diverge as normal GE would have
|
103
|
-
some required fields in Org (like web_domain), and WithDeps would not.
|
104
|
-
|
105
95
|
"""
|
106
96
|
|
107
97
|
publisher: Org | None = pyd.Field(description="Organization that published the LCA results.")
|
@@ -279,7 +279,7 @@ class Geography(StrEnum):
|
|
279
279
|
* ZM: Zambia
|
280
280
|
* ZW: Zimbabwe
|
281
281
|
|
282
|
-
USA
|
282
|
+
USA and Canada subdivisions, see https://en.wikipedia.org/wiki/ISO_3166-1:
|
283
283
|
|
284
284
|
* CA-AB: Alberta, Canada
|
285
285
|
* CA-BC: British Columbia, Canada
|
@@ -322,6 +322,16 @@ class LCIAMethod(StrEnum):
|
|
322
322
|
class Impacts(pyd.BaseModel):
|
323
323
|
"""List of environmental impacts, compiled per one of the standard Impact Assessment methods."""
|
324
324
|
|
325
|
+
class Config:
|
326
|
+
# pydantic schema generator gets lost in this structure, so we need to re-establish it manually for openapi
|
327
|
+
schema_extra = {
|
328
|
+
"properties": {
|
329
|
+
str(lm): {"description": str(lm), "allOf": [{"$ref": "#/components/schemas/ImpactSet"}]}
|
330
|
+
for lm in LCIAMethod
|
331
|
+
},
|
332
|
+
"additionalProperties": None,
|
333
|
+
}
|
334
|
+
|
325
335
|
__root__: dict[LCIAMethod, ImpactSet]
|
326
336
|
|
327
337
|
def set_unknown_lcia(self, impact_set: ImpactSet):
|
@@ -0,0 +1,15 @@
|
|
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
|
+
#
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{openepd-4.10.0/src/openepd/model/specs/generated → openepd-4.11.0/src/openepd/model}/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -49,6 +49,8 @@ class IndustryEpdPreviewV0(
|
|
49
49
|
Used in lists and other cases where full LCIA data is not required.
|
50
50
|
"""
|
51
51
|
|
52
|
+
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
53
|
+
|
52
54
|
doctype: str = pyd.Field(
|
53
55
|
description='Describes the type and schema of the document. Must always be "openIndustryEpd"',
|
54
56
|
default="openIndustryEpd",
|
@@ -70,8 +72,6 @@ class IndustryEpdV0(IndustryEpdPreviewV0, WithLciaMixin, WithAltIdsMixin, title=
|
|
70
72
|
to support related entities matching.
|
71
73
|
"""
|
72
74
|
|
73
|
-
_FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
|
74
|
-
|
75
75
|
|
76
76
|
IndustryEpd = IndustryEpdV0
|
77
77
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/cast_decks_and_underlayment.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/fire_and_smoke_protection.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/mechanical_insulation.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/network_infrastructure.py
RENAMED
File without changes
|
File without changes
|
{openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/other_electrical_equipment.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{openepd-4.10.0 → openepd-4.11.0}/src/openepd/model/specs/generated/thermal_moisture_protection.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|