openepd 6.12.0__py3-none-any.whl → 6.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/m49/__init__.py +15 -0
- openepd/m49/const.py +1172 -0
- openepd/m49/geo_converter.py +178 -0
- openepd/model/specs/range/furnishings.py +2 -2
- openepd/model/specs/singular/furnishings.py +2 -2
- {openepd-6.12.0.dist-info → openepd-6.13.0.dist-info}/METADATA +1 -1
- {openepd-6.12.0.dist-info → openepd-6.13.0.dist-info}/RECORD +10 -7
- {openepd-6.12.0.dist-info → openepd-6.13.0.dist-info}/LICENSE +0 -0
- {openepd-6.12.0.dist-info → openepd-6.13.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,178 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2025 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 Collection
|
17
|
+
|
18
|
+
from openepd.m49.const import (
|
19
|
+
COUNTRY_VERBOSE_NAME_TO_M49,
|
20
|
+
ISO3166_ALPHA2_TO_M49,
|
21
|
+
M49_TO_COUNTRY_VERBOSE_NAME,
|
22
|
+
M49_TO_ISO3166_ALPHA2,
|
23
|
+
M49_TO_REGION_VERBOSE_NAME,
|
24
|
+
OPENEPD_SPECIAL_REGIONS,
|
25
|
+
REGION_VERBOSE_NAME_TO_M49,
|
26
|
+
)
|
27
|
+
|
28
|
+
|
29
|
+
def iso_to_m49(regions: Collection[str]) -> set[str]:
|
30
|
+
"""
|
31
|
+
Convert ISO3166 alpha2 country codes to M49 region codes.
|
32
|
+
|
33
|
+
:param regions: List of ISO3166 alpha2 country codes (e.g., ["US", "CA", "MX"])
|
34
|
+
:return: Set of M49 region codes (e.g., {"840", "124", "484"})
|
35
|
+
:raises ValueError: If a country code is not found in M49 region codes.
|
36
|
+
"""
|
37
|
+
|
38
|
+
if not regions:
|
39
|
+
return set()
|
40
|
+
|
41
|
+
result = set()
|
42
|
+
for code in regions:
|
43
|
+
m49_code = ISO3166_ALPHA2_TO_M49.get(code.upper())
|
44
|
+
if m49_code:
|
45
|
+
result.add(m49_code)
|
46
|
+
else:
|
47
|
+
raise ValueError(f"Country code '{code}' not found in M49 region codes.")
|
48
|
+
|
49
|
+
return result
|
50
|
+
|
51
|
+
|
52
|
+
def m49_to_iso(regions: Collection[str]) -> set[str]:
|
53
|
+
"""
|
54
|
+
Convert M49 region codes to ISO3166 alpha2 country codes.
|
55
|
+
|
56
|
+
:param regions: List of M49 region codes (e.g., ["840", "124", "484"])
|
57
|
+
:return: Set of ISO3166 alpha2 country codes (e.g., {"US", "CA", "MX"})
|
58
|
+
:raises ValueError: If a region code is not found in ISO3166.
|
59
|
+
"""
|
60
|
+
|
61
|
+
if not regions:
|
62
|
+
return set()
|
63
|
+
|
64
|
+
result = set()
|
65
|
+
for code in regions:
|
66
|
+
iso_code = M49_TO_ISO3166_ALPHA2.get(code.upper())
|
67
|
+
if iso_code:
|
68
|
+
result.add(iso_code)
|
69
|
+
else:
|
70
|
+
raise ValueError(f"Region code '{code}' not found in ISO3166.")
|
71
|
+
|
72
|
+
return result
|
73
|
+
|
74
|
+
|
75
|
+
def region_and_country_names_to_m49(regions: Collection[str]) -> set[str]:
|
76
|
+
"""
|
77
|
+
Convert user-friendly region and country names to M49 region codes.
|
78
|
+
|
79
|
+
:param regions: List of user-friendly region and country names (e.g., ["Europe",
|
80
|
+
"North America", "Austria", "Germany"])
|
81
|
+
:return: Set of M49 region codes (e.g., {"150", "003", "040", "276"})
|
82
|
+
:raises ValueError: If a region or country name is not found in M49 region codes.
|
83
|
+
"""
|
84
|
+
|
85
|
+
if not regions:
|
86
|
+
return set()
|
87
|
+
|
88
|
+
result = set()
|
89
|
+
for name in regions:
|
90
|
+
m49_code = REGION_VERBOSE_NAME_TO_M49.get(name.title()) or COUNTRY_VERBOSE_NAME_TO_M49.get(name.title())
|
91
|
+
if not m49_code:
|
92
|
+
raise ValueError(f"Region or country name '{name}' not found in M49 region codes.")
|
93
|
+
result.add(m49_code)
|
94
|
+
|
95
|
+
return result
|
96
|
+
|
97
|
+
|
98
|
+
def m49_to_region_and_country_names(regions: Collection[str]) -> set[str]:
|
99
|
+
"""
|
100
|
+
Convert M49 region codes to user-friendly region names and country names.
|
101
|
+
|
102
|
+
:param regions: List of M49 region codes (e.g., ["150", "003", "040", "276"])
|
103
|
+
:return: Set of user-friendly region and country names (e.g., {"Europe", "North America", "Austria", "Germany"})
|
104
|
+
:raises ValueError: If a region code is not found in M49 region codes.
|
105
|
+
"""
|
106
|
+
|
107
|
+
if not regions:
|
108
|
+
return set()
|
109
|
+
|
110
|
+
result = set()
|
111
|
+
for code in regions:
|
112
|
+
if code not in M49_TO_REGION_VERBOSE_NAME and code not in M49_TO_COUNTRY_VERBOSE_NAME:
|
113
|
+
raise ValueError(f"Region code '{code}' not found in M49 region codes.")
|
114
|
+
|
115
|
+
name = M49_TO_REGION_VERBOSE_NAME.get(code) or M49_TO_COUNTRY_VERBOSE_NAME.get(code, code)
|
116
|
+
result.add(name)
|
117
|
+
return result
|
118
|
+
|
119
|
+
|
120
|
+
def openepd_to_m49(regions: Collection[str]) -> set[str]:
|
121
|
+
"""
|
122
|
+
Convert OpenEPD geography definitions to pure M49 region codes.
|
123
|
+
|
124
|
+
:param regions: list of OpenEPD geography definitions including letter codes and aliases
|
125
|
+
like "EU27" or "NAFTA" (e.g., ["EU27", "NAFTA"], ["US", "CA, MX"])
|
126
|
+
:return: Set of M49 region codes (e.g., {"040", "056", "100", "191", "196", "203", "208", "233", "246", "250",
|
127
|
+
"276", "300", "348", "372", "380", "428", "440", "442", "470", "528", "616", "620", "642", "703", "705", "724",
|
128
|
+
"752", "840", "124", "484"}, {"840", "124", "484"})
|
129
|
+
:raises ValueError: If a region or country name is not found in ISO3166 or OpenEPD special regions.
|
130
|
+
"""
|
131
|
+
|
132
|
+
if not regions:
|
133
|
+
return set()
|
134
|
+
|
135
|
+
result = set()
|
136
|
+
for region in regions:
|
137
|
+
if region in OPENEPD_SPECIAL_REGIONS:
|
138
|
+
result.update(OPENEPD_SPECIAL_REGIONS[region].m49_codes)
|
139
|
+
else:
|
140
|
+
m49_code = ISO3166_ALPHA2_TO_M49.get(region.upper())
|
141
|
+
if m49_code:
|
142
|
+
result.add(m49_code)
|
143
|
+
else:
|
144
|
+
raise ValueError(f"Region '{region}' not found in ISO3166 or OpenEPD special regions.")
|
145
|
+
return result
|
146
|
+
|
147
|
+
|
148
|
+
def m49_to_openepd(regions: list[str]) -> set[str]:
|
149
|
+
"""
|
150
|
+
Convert M49 region codes to OpenEPD geography definitions.
|
151
|
+
|
152
|
+
:param regions: List of M49 region codes (e.g., ["040", "056", "100", "191", "196", "203", "208", "233", "246",
|
153
|
+
"250", "276", "300", "348", "372", "380", "428", "440", "442", "470", "528", "616", "620", "642", "703", "705",
|
154
|
+
"724", "752", "840", "124", "484"], ["840", "124", "484"], ["040", "056", "100"])
|
155
|
+
:return: Set of OpenEPD geography definitions including letter codes and aliases
|
156
|
+
like "EU27" or "NAFTA" (e.g., {"EU27", "NAFTA"}, {"NAFTA"}, {"AT", "BE", "BG"})
|
157
|
+
:raises ValueError: If a region code is not found in ISO3166 or OpenEPD special regions.
|
158
|
+
"""
|
159
|
+
|
160
|
+
if not regions:
|
161
|
+
return set()
|
162
|
+
|
163
|
+
result = set()
|
164
|
+
remaining_codes = set(regions)
|
165
|
+
for special_region, special_region_data in OPENEPD_SPECIAL_REGIONS.items():
|
166
|
+
special_region_codes = set(special_region_data.m49_codes)
|
167
|
+
if special_region_codes.issubset(remaining_codes):
|
168
|
+
result.add(special_region)
|
169
|
+
remaining_codes -= special_region_codes
|
170
|
+
|
171
|
+
for code in remaining_codes:
|
172
|
+
iso_code = M49_TO_ISO3166_ALPHA2.get(code)
|
173
|
+
if iso_code:
|
174
|
+
result.add(iso_code)
|
175
|
+
else:
|
176
|
+
raise ValueError(f"Region code '{code}' not found in ISO3166 or OpenEPD special regions.")
|
177
|
+
|
178
|
+
return result
|
@@ -236,12 +236,12 @@ class FurnishingsRangeV1(BaseOpenEpdHierarchicalSpec):
|
|
236
236
|
default=None, title="Functional Storage Volume", description=""
|
237
237
|
)
|
238
238
|
functional_seating_capacity: RangeInt | None = pyd.Field(
|
239
|
-
default=
|
239
|
+
default=None,
|
240
240
|
title="Functional Seating Capacity",
|
241
241
|
description="Intended number of individuals the product seats. This value is used in calculating impact per functional unit.",
|
242
242
|
)
|
243
243
|
installation_waste_factor: RangeRatioFloat | None = pyd.Field(
|
244
|
-
default=
|
244
|
+
default=None,
|
245
245
|
title="Installation Waste Factor",
|
246
246
|
description="Typical increase in impacts to account for installation waste.",
|
247
247
|
)
|
@@ -175,13 +175,13 @@ class FurnishingsV1(BaseOpenEpdHierarchicalSpec):
|
|
175
175
|
example="1 m3",
|
176
176
|
)
|
177
177
|
functional_seating_capacity: pyd.NonNegativeInt | None = pyd.Field(
|
178
|
-
default=
|
178
|
+
default=None,
|
179
179
|
title="Functional Seating Capacity",
|
180
180
|
description="Intended number of individuals the product seats. This value is used in calculating impact per functional unit.",
|
181
181
|
example=1,
|
182
182
|
)
|
183
183
|
installation_waste_factor: RatioFloat | None = pyd.Field(
|
184
|
-
default=
|
184
|
+
default=None,
|
185
185
|
title="Installation Waste Factor",
|
186
186
|
description="Typical increase in impacts to account for installation waste.",
|
187
187
|
example=0.01,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
openepd/__init__.py,sha256=fhxfEyEurLvSfvQci-vb3njzl_lvhcLXiZrecCOaMU8,794
|
2
|
-
openepd/__version__.py,sha256=
|
2
|
+
openepd/__version__.py,sha256=a5hKzjDC_6ktbu65wQ9YE2NrU-x54HWyTkooE0uHe-g,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
5
|
openepd/api/average_dataset/generic_estimate_sync_api.py,sha256=KHCmSKMOJTQct6vhdhAatAENoouStc_yVRza5AFNoIo,7953
|
@@ -32,6 +32,9 @@ openepd/bundle/writer.py,sha256=gHK1D-F-td2C18QFWerg666JUTLaGUkTUSQURJi9o74,8136
|
|
32
32
|
openepd/compat/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
33
33
|
openepd/compat/compat_functional_validators.py,sha256=aWg3a80fqT8zjN0S260N-Ad2WFKAaB8ByN7ArBW3NMA,834
|
34
34
|
openepd/compat/pydantic.py,sha256=dNwPXK1X5xq9sdkd0kcbKQAUIter1GAfcxXOl6hmITQ,1146
|
35
|
+
openepd/m49/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
36
|
+
openepd/m49/const.py,sha256=O31VJ5_sR4GAOvJnFsi3An2YMaMa96H7XBqaQ0kNwnw,31734
|
37
|
+
openepd/m49/geo_converter.py,sha256=mRamQTVwd35kwn5-23N3E8cxqpYG7l9eW787SJYM7nw,6515
|
35
38
|
openepd/model/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
|
36
39
|
openepd/model/base.py,sha256=1GeaEDn-ppy94GaOaZI1y6Yew_0eBBho1COaxfzzLCw,9834
|
37
40
|
openepd/model/category.py,sha256=reeOVRDuZPYU77EMwG0K5VjnK2H9yOGxT0PJXXqrjEk,1639
|
@@ -67,7 +70,7 @@ openepd/model/specs/range/electrical_transmission_and_distribution_equipment.py,
|
|
67
70
|
openepd/model/specs/range/electricity.py,sha256=yn_S25C_tZqseb8hiJ1yiHszu2mQ49FOFWWCqNpOBY0,997
|
68
71
|
openepd/model/specs/range/finishes.py,sha256=oCaPVYJja1KYxwEzTHCl7HtxQ2mokzeyahjyP33zHSg,21291
|
69
72
|
openepd/model/specs/range/fire_and_smoke_protection.py,sha256=u5veICQznf-woYlh49S_IbvPA23CLWEy7Ngvic2FIpw,3337
|
70
|
-
openepd/model/specs/range/furnishings.py,sha256=
|
73
|
+
openepd/model/specs/range/furnishings.py,sha256=7r9albaHmuf0ttqkSQ6elJcSzgFgOHSrwAfhEpJMm5k,6531
|
71
74
|
openepd/model/specs/range/grouting.py,sha256=BQPxH6BvlXpdhLEZBui9zTuY93K_9syjoa6rdnF8GGY,1095
|
72
75
|
openepd/model/specs/range/manufacturing_inputs.py,sha256=xzgkNz7yG8cp715hxS0LtJX9nfJ5RQR8GxlD2bAduwE,5574
|
73
76
|
openepd/model/specs/range/masonry.py,sha256=IyjQMb8Mx3tpJlHIIam0OrMkFsJXKvc0WXRLRBupozY,2867
|
@@ -106,7 +109,7 @@ openepd/model/specs/singular/electrical_transmission_and_distribution_equipment.
|
|
106
109
|
openepd/model/specs/singular/electricity.py,sha256=f1cJ9eklNUf97khCIZiT5-z8V_TbOcvH2me_1UTQVrE,823
|
107
110
|
openepd/model/specs/singular/finishes.py,sha256=bAlNZiUP-HwePaJyC1D4j2fpv0xnMp3V5mhtAs9iaxQ,22571
|
108
111
|
openepd/model/specs/singular/fire_and_smoke_protection.py,sha256=1uyEGdMAsboYORHvSFN1wftRVAps_UJ1Ep3Dk9arT3s,3058
|
109
|
-
openepd/model/specs/singular/furnishings.py,sha256=
|
112
|
+
openepd/model/specs/singular/furnishings.py,sha256=6V6Dc4xph8PcIQhuuLFyFGL4w2Yh_ByEKCNvQfUkxZQ,5603
|
110
113
|
openepd/model/specs/singular/grouting.py,sha256=pg2tX3W7a2TQ3z_eyFYGlBJY3WEwn6JlZyqM3PQIJcU,934
|
111
114
|
openepd/model/specs/singular/manufacturing_inputs.py,sha256=9WSDOVN0mUqvFXqWf82lkpHi-XRQSMcEpe9bweegwhU,5093
|
112
115
|
openepd/model/specs/singular/masonry.py,sha256=f6nph-gscAmVeJ60bG-ebto5kz0fgh0LY27n0VutGFA,3165
|
@@ -136,7 +139,7 @@ openepd/model/validation/quantity.py,sha256=vfSe-3DGQf84bCp_sMIU0ZPAA1wIilodpTjL
|
|
136
139
|
openepd/model/versioning.py,sha256=cm3LaAUODnbbu3W3pC6baJzxKusTQ1kZH-PwwScCj3c,4473
|
137
140
|
openepd/patch_pydantic.py,sha256=LVqDMKn723VYYf_V-RgTLxIb1xiUtYOfPYCQP6-7RoM,4122
|
138
141
|
openepd/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
139
|
-
openepd-6.
|
140
|
-
openepd-6.
|
141
|
-
openepd-6.
|
142
|
-
openepd-6.
|
142
|
+
openepd-6.13.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
143
|
+
openepd-6.13.0.dist-info/METADATA,sha256=ta3TH3-bGEhZt0NaiXcVVkEtbLuKY2YyX8ZwNhMv2Fo,9039
|
144
|
+
openepd-6.13.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
145
|
+
openepd-6.13.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|