openepd 2.0.0__py3-none-any.whl → 3.0.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/__init__.py +1 -1
- openepd/__version__.py +2 -2
- openepd/api/__init__.py +19 -0
- openepd/api/base_sync_client.py +550 -0
- openepd/api/category/__init__.py +19 -0
- openepd/api/category/dto.py +25 -0
- openepd/api/category/sync_api.py +44 -0
- openepd/api/common.py +239 -0
- openepd/api/dto/__init__.py +19 -0
- openepd/api/dto/base.py +41 -0
- openepd/api/dto/common.py +115 -0
- openepd/api/dto/meta.py +69 -0
- openepd/api/dto/mf.py +59 -0
- openepd/api/dto/params.py +19 -0
- openepd/api/epd/__init__.py +19 -0
- openepd/api/epd/dto.py +121 -0
- openepd/api/epd/sync_api.py +105 -0
- openepd/api/errors.py +86 -0
- openepd/api/pcr/__init__.py +19 -0
- openepd/api/pcr/dto.py +41 -0
- openepd/api/pcr/sync_api.py +49 -0
- openepd/api/sync_client.py +67 -0
- openepd/api/test/__init__.py +19 -0
- openepd/bundle/__init__.py +1 -1
- openepd/bundle/base.py +1 -1
- openepd/bundle/model.py +5 -6
- openepd/bundle/reader.py +5 -5
- openepd/bundle/writer.py +5 -4
- openepd/compat/__init__.py +19 -0
- openepd/compat/pydantic.py +29 -0
- openepd/model/__init__.py +1 -1
- openepd/model/base.py +114 -15
- openepd/model/category.py +39 -0
- openepd/model/common.py +33 -25
- openepd/model/epd.py +97 -78
- openepd/model/factory.py +48 -0
- openepd/model/lcia.py +24 -13
- openepd/model/org.py +28 -18
- openepd/model/pcr.py +42 -14
- openepd/model/specs/README.md +19 -0
- openepd/model/specs/__init__.py +20 -4
- openepd/model/specs/aluminium.py +67 -0
- openepd/model/specs/asphalt.py +87 -0
- openepd/model/specs/base.py +60 -0
- openepd/model/specs/concrete.py +453 -23
- openepd/model/specs/glass.py +404 -0
- openepd/model/specs/steel.py +193 -0
- openepd/model/specs/wood.py +130 -0
- openepd/model/standard.py +2 -3
- openepd/model/validation/__init__.py +19 -0
- openepd/model/validation/common.py +59 -0
- openepd/model/validation/numbers.py +26 -0
- openepd/model/validation/quantity.py +131 -0
- openepd/model/versioning.py +129 -0
- {openepd-2.0.0.dist-info → openepd-3.0.0.dist-info}/METADATA +36 -5
- openepd-3.0.0.dist-info/RECORD +59 -0
- openepd-2.0.0.dist-info/RECORD +0 -22
- {openepd-2.0.0.dist-info → openepd-3.0.0.dist-info}/LICENSE +0 -0
- {openepd-2.0.0.dist-info → openepd-3.0.0.dist-info}/WHEEL +0 -0
openepd/model/pcr.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright
|
2
|
+
# Copyright 2024 by C Change Labs Inc. www.c-change-labs.com
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -18,65 +18,93 @@
|
|
18
18
|
# Find out more at www.BuildingTransparency.org
|
19
19
|
#
|
20
20
|
import datetime
|
21
|
-
from
|
22
|
-
|
23
|
-
import pydantic as pyd
|
21
|
+
from enum import StrEnum
|
22
|
+
from typing import Annotated, Optional
|
24
23
|
|
24
|
+
from openepd.compat.pydantic import pyd
|
25
25
|
from openepd.model.base import BaseOpenEpdSchema
|
26
26
|
from openepd.model.common import WithAltIdsMixin, WithAttachmentsMixin
|
27
27
|
from openepd.model.org import Org
|
28
28
|
|
29
29
|
|
30
|
+
class PcrStatus(StrEnum):
|
31
|
+
"""Status of a PCR."""
|
32
|
+
|
33
|
+
InDevelopment = "InDevelopment"
|
34
|
+
Published = "Published"
|
35
|
+
NonPublic = "NonPublic"
|
36
|
+
Expired = "Expired"
|
37
|
+
Sunset = "Sunset"
|
38
|
+
|
39
|
+
|
30
40
|
class Pcr(WithAttachmentsMixin, WithAltIdsMixin, BaseOpenEpdSchema):
|
31
41
|
"""Represent a PCR (Product Category Rules)."""
|
32
42
|
|
33
43
|
id: str | None = pyd.Field(
|
34
44
|
description="The unique ID for this PCR. To ensure global uniqueness, should be registered "
|
35
45
|
"at open-xpd-uuid.cqd.io/register or a coordinating registry.",
|
46
|
+
example="ec3xpgq2",
|
36
47
|
default=None,
|
37
|
-
json_schema_extra={"example": "ec3xpgq2"},
|
38
48
|
)
|
39
49
|
issuer: Org | None = pyd.Field(description="Organization issuing this PCR", default=None)
|
40
50
|
issuer_doc_id: str | None = pyd.Field(
|
41
51
|
max_length=40,
|
42
52
|
default=None,
|
43
53
|
description="Document ID or code created by issuer",
|
44
|
-
|
54
|
+
example="c-PCR-003",
|
45
55
|
)
|
46
56
|
name: str | None = pyd.Field(
|
47
57
|
max_length=200,
|
48
58
|
default=None,
|
49
59
|
description="Full document name as listed in source document",
|
50
|
-
|
60
|
+
example="c-PCR-003 Concrete and concrete elements (EN 16757)",
|
51
61
|
)
|
52
62
|
short_name: str | None = pyd.Field(
|
53
|
-
max_length=40,
|
54
63
|
default=None,
|
55
64
|
description="A shortened name without boilerplate text.",
|
56
|
-
|
65
|
+
example="Concrete and Concrete Elements",
|
57
66
|
)
|
58
67
|
version: str | None = pyd.Field(
|
59
68
|
description="Document version, as expressed in document.",
|
69
|
+
example="1.0.2",
|
60
70
|
default=None,
|
61
|
-
json_schema_extra=dict(example="1.0.2"),
|
62
71
|
)
|
63
|
-
date_of_issue: datetime.
|
72
|
+
date_of_issue: datetime.datetime | None = pyd.Field(
|
73
|
+
example=datetime.date(day=11, month=2, year=2022),
|
64
74
|
default=None,
|
65
75
|
description="First day on which the document is valid",
|
66
|
-
json_schema_extra=dict(example=datetime.date(day=11, month=2, year=2022)),
|
67
76
|
)
|
68
|
-
valid_until: datetime.
|
77
|
+
valid_until: datetime.datetime | None = pyd.Field(
|
78
|
+
example=datetime.date(day=11, month=2, year=2024),
|
69
79
|
default=None,
|
70
80
|
description="Last day on which the document is valid",
|
71
|
-
json_schema_extra=dict(example=datetime.date(day=11, month=2, year=2024)),
|
72
81
|
)
|
82
|
+
doc: str | None = pyd.Field(default=None, description="URL to original document, preferably directly to a PDF.")
|
73
83
|
parent: Optional["Pcr"] = pyd.Field(
|
74
84
|
description="The parent PCR, base PCR, `Part A` PCR",
|
75
85
|
default=None,
|
76
86
|
)
|
87
|
+
status: PcrStatus | None = pyd.Field(
|
88
|
+
default=None,
|
89
|
+
description="The current release status of this PCR. "
|
90
|
+
"A PCR with valid_until in the past must have status Expired or Sunset; a PCR with valid_until "
|
91
|
+
"more than 5 years in the past must have status Sunset. Compliant systems should automatically "
|
92
|
+
"update these fields within 24 hours.",
|
93
|
+
)
|
77
94
|
product_classes: dict[str, str | list[str]] = pyd.Field(
|
78
95
|
description="List of classifications, including Masterformat and UNSPC", default_factory=dict
|
79
96
|
)
|
97
|
+
applicable_in: list[Annotated[str, pyd.Field(min_length=2, max_length=2)]] | None = pyd.Field(
|
98
|
+
max_items=100,
|
99
|
+
default=None,
|
100
|
+
description="Jurisdiction(s) in which EPD is applicable. An empty array, or absent properties, "
|
101
|
+
"implies global applicability. Accepts "
|
102
|
+
"[2-letter country codes](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2), "
|
103
|
+
"[M49 region codes](https://unstats.un.org/unsd/methodology/m49/), "
|
104
|
+
'or the alias "EU27" for the 27 members of the Euro bloc, or the alias "NAFTA" '
|
105
|
+
"for the members of North American Free Trade Agreement",
|
106
|
+
example=["US", "CA", "MX", "EU27", "NAFTA"],
|
107
|
+
)
|
80
108
|
|
81
109
|
@classmethod
|
82
110
|
def get_asset_type(cls) -> str | None:
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Material Extensions
|
2
|
+
|
3
|
+
This package contains openEPD material extensions. They are used to represent the material properties of the openEPD
|
4
|
+
materials, and are a more dynamic, frequently changing part of the standard.
|
5
|
+
|
6
|
+
## Versioning
|
7
|
+
|
8
|
+
Extensions are versioned separately from the openEPD standard or openEPD API.
|
9
|
+
|
10
|
+
Each material extension is named after the corresponding EC3 product class, and is located in the relevant place
|
11
|
+
in the specs tree. For example, `RebarSteel` is nested under `Steel`.
|
12
|
+
|
13
|
+
Extensions are versioned as Major.Minor, for example "2.4".
|
14
|
+
|
15
|
+
Rules:
|
16
|
+
1. Minor versions for the same major version should be backwards compatible.
|
17
|
+
2. Major versions are not compatible between themselves.
|
18
|
+
3. Pydantic models representing versions are named in a pattern SpecNameV1, where 1 is major version and SpecName is
|
19
|
+
the name of the material extension.
|
openepd/model/specs/__init__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright
|
2
|
+
# Copyright 2024 by C Change Labs Inc. www.c-change-labs.com
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -17,13 +17,29 @@
|
|
17
17
|
# Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
|
18
18
|
# Find out more at www.BuildingTransparency.org
|
19
19
|
#
|
20
|
-
import pydantic as pyd
|
21
20
|
|
21
|
+
from openepd.compat.pydantic import pyd
|
22
22
|
from openepd.model.base import BaseOpenEpdSchema
|
23
|
-
from openepd.model.specs
|
23
|
+
from openepd.model.specs import concrete, steel
|
24
|
+
from openepd.model.specs.aluminium import AluminiumV1
|
25
|
+
from openepd.model.specs.asphalt import AsphaltV1
|
26
|
+
from openepd.model.specs.glass import GlazingV1
|
27
|
+
from openepd.model.specs.wood import TimberV1
|
24
28
|
|
25
29
|
|
26
30
|
class Specs(BaseOpenEpdSchema):
|
27
31
|
"""Material specific specs."""
|
28
32
|
|
29
|
-
cmu: CmuSpec | None = pyd.Field(default=None, description="Concrete Masonry Unit-specific (CMU) specs")
|
33
|
+
cmu: concrete.CmuSpec | None = pyd.Field(default=None, description="Concrete Masonry Unit-specific (CMU) specs")
|
34
|
+
CMU: concrete.CmuSpec | None = pyd.Field(default=None, description="Concrete Masonry Unit-specific (CMU) specs")
|
35
|
+
Concrete: concrete.ConcreteV1 | None = pyd.Field(
|
36
|
+
default=None, title="ConcreteV1", description="Concrete-specific specs"
|
37
|
+
)
|
38
|
+
PrecastConcrete: concrete.PrecastConcreteV1 | None = pyd.Field(
|
39
|
+
default=None, title="PrecastConcreteV1", description="Precast Concrete-specific specs"
|
40
|
+
)
|
41
|
+
Steel: steel.SteelV1 | None = pyd.Field(default=None, title="SteelV1", description="Steel-specific specs")
|
42
|
+
Asphalt: AsphaltV1 | None = pyd.Field(default=None, title="AsphaltV1")
|
43
|
+
Aluminium: AluminiumV1 | None = pyd.Field(default=None, title="AluminiumV1", description="Aluminium-specific specs")
|
44
|
+
Timber: TimberV1 | None = pyd.Field(default=None, title="TimberV1", description="Timber-specific specs")
|
45
|
+
Glazing: GlazingV1 | None = pyd.Field(default=None, title="GlazingV1", description="Glazing-specific specs")
|
@@ -0,0 +1,67 @@
|
|
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
|
+
# This software was developed with support from the Skanska USA,
|
17
|
+
# Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
|
18
|
+
# Find out more at www.BuildingTransparency.org
|
19
|
+
#
|
20
|
+
from enum import StrEnum
|
21
|
+
|
22
|
+
from openepd.compat.pydantic import pyd
|
23
|
+
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
24
|
+
from openepd.model.validation.numbers import RatioFloat
|
25
|
+
|
26
|
+
|
27
|
+
class AluminiumAlloy(StrEnum):
|
28
|
+
"""Aluminium alloy enum."""
|
29
|
+
|
30
|
+
ALLOY_1xxx = ("1xxx",)
|
31
|
+
ALLOY_2xxx = ("2xxx",)
|
32
|
+
ALLOY_3xxx = ("3xxx",)
|
33
|
+
ALLOY_4xxx = ("4xxx",)
|
34
|
+
ALLOY_5xxx = ("5xxx",)
|
35
|
+
ALLOY_6xxx = ("6xxx",)
|
36
|
+
ALLOY_7xxx = ("7xxx",)
|
37
|
+
ALLOY_8xxx = ("8xxx",)
|
38
|
+
ALLOY_1xx_x = ("1xx.x",)
|
39
|
+
ALLOY_2xx_x = ("2xx.x",)
|
40
|
+
ALLOY_3xx_x = ("3xx.x",)
|
41
|
+
ALLOY_4xx_x = ("4xx.x",)
|
42
|
+
ALLOY_5xx_x = ("5xx.x",)
|
43
|
+
ALLOY_7xx_x = ("7xx.x",)
|
44
|
+
ALLOY_8xx_x = ("8xx.x",)
|
45
|
+
ALLOY_9xx_x = ("9xx.x",)
|
46
|
+
|
47
|
+
|
48
|
+
class AluminiumExtrusionsV1(BaseOpenEpdHierarchicalSpec):
|
49
|
+
"""Aluminium extrusions V1 spec."""
|
50
|
+
|
51
|
+
_EXT_VERSION = "1.0"
|
52
|
+
|
53
|
+
"""Aluminium extrusions V1 spec."""
|
54
|
+
thermally_improved: bool | None = pyd.Field(default=None, description="Thermally improved")
|
55
|
+
|
56
|
+
|
57
|
+
class AluminiumV1(BaseOpenEpdHierarchicalSpec):
|
58
|
+
"""Aluminium V1 spec."""
|
59
|
+
|
60
|
+
_EXT_VERSION = "1.0"
|
61
|
+
recycled_content: RatioFloat | None = pyd.Field(default=None, description="Recycled content")
|
62
|
+
|
63
|
+
alloy: AluminiumAlloy | None = pyd.Field(default=None, description="Alloy")
|
64
|
+
anodized: bool | None = None
|
65
|
+
painted: bool | None = None
|
66
|
+
|
67
|
+
AluminiumExtrusions: AluminiumExtrusionsV1 | None = pyd.Field(title="AluminiumExtrusionsV1", default=None)
|
@@ -0,0 +1,87 @@
|
|
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
|
+
# This software was developed with support from the Skanska USA,
|
17
|
+
# Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
|
18
|
+
# Find out more at www.BuildingTransparency.org
|
19
|
+
#
|
20
|
+
from enum import StrEnum
|
21
|
+
|
22
|
+
from openepd.compat.pydantic import pyd
|
23
|
+
from openepd.model.common import OpenEPDUnit
|
24
|
+
from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
|
25
|
+
from openepd.model.validation.numbers import RatioFloat
|
26
|
+
from openepd.model.validation.quantity import LengthMmStr, TemperatureCStr, validate_unit_factory
|
27
|
+
|
28
|
+
|
29
|
+
class AsphaltMixType(StrEnum):
|
30
|
+
"""Asphalt mix type enum."""
|
31
|
+
|
32
|
+
HMA = "HMA"
|
33
|
+
WMA = "WMA"
|
34
|
+
|
35
|
+
|
36
|
+
class AsphaltGradation(StrEnum):
|
37
|
+
"""Asphalt gradation enum."""
|
38
|
+
|
39
|
+
Dense_graded = "Dense-graded"
|
40
|
+
Open_graded = "Open-graded"
|
41
|
+
Gap_graded = "Gap-graded"
|
42
|
+
|
43
|
+
|
44
|
+
class AsphaltV1(BaseOpenEpdHierarchicalSpec):
|
45
|
+
"""Asphalt spec."""
|
46
|
+
|
47
|
+
_EXT_VERSION = "1.0"
|
48
|
+
|
49
|
+
asphalt_aggregate_size_max: LengthMmStr | None = pyd.Field(
|
50
|
+
default=None, example="5mm", description="Max aggregate size"
|
51
|
+
)
|
52
|
+
|
53
|
+
asphalt_rap: RatioFloat | None = pyd.Field(
|
54
|
+
default=None, description="Percent of mixture that has been replaced by recycled " "asphalt pavement (RAP)."
|
55
|
+
)
|
56
|
+
asphalt_ras: RatioFloat | None = pyd.Field(
|
57
|
+
default=None, description="Percent of mixture that has been replaced by recycled " "asphalt shingles (RAS)."
|
58
|
+
)
|
59
|
+
asphalt_ground_tire_rubber: RatioFloat | None = pyd.Field(
|
60
|
+
default=None, description="Percent of mixture that has been replaced " "by ground tire rubber (GTR)."
|
61
|
+
)
|
62
|
+
|
63
|
+
asphalt_max_temperature: TemperatureCStr | None = pyd.Field(
|
64
|
+
default=None,
|
65
|
+
description="The upper threshold temperature to which an asphalt "
|
66
|
+
"binder can be heated preventing the asphalt mixture "
|
67
|
+
"from rutting",
|
68
|
+
)
|
69
|
+
asphalt_min_temperature: TemperatureCStr | None = pyd.Field(
|
70
|
+
default=None,
|
71
|
+
description="The lower threshold temperature for an asphalt "
|
72
|
+
"binder to prevent thermal cracking of the asphalt"
|
73
|
+
" mixture.",
|
74
|
+
)
|
75
|
+
|
76
|
+
asphalt_mix_type: AsphaltMixType | None = pyd.Field(default=None, description="Asphalt mix type")
|
77
|
+
asphalt_gradation: AsphaltGradation | None = pyd.Field(default=None, description="Asphalt gradation")
|
78
|
+
|
79
|
+
asphalt_sbr: bool | None = pyd.Field(default=None, description="Styrene-butadiene rubber (SBR)")
|
80
|
+
asphalt_sbs: bool | None = pyd.Field(default=None, description="Styrene-butadiene-styrene (SBS)")
|
81
|
+
asphalt_ppa: bool | None = pyd.Field(default=None, description="Polyphosphoric acid (PPA)")
|
82
|
+
asphalt_gtr: bool | None = pyd.Field(default=None, description="Ground tire rubber (GTR)")
|
83
|
+
asphalt_pmb: bool | None = pyd.Field(default=None, description="Polymer modified bitumen (PMB)")
|
84
|
+
|
85
|
+
_aggregate_size_max_validator = pyd.validator("asphalt_aggregate_size_max", allow_reuse=True)(
|
86
|
+
validate_unit_factory(OpenEPDUnit.m)
|
87
|
+
)
|
@@ -0,0 +1,60 @@
|
|
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
|
+
# This software was developed with support from the Skanska USA,
|
17
|
+
# Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
|
18
|
+
# Find out more at www.BuildingTransparency.org
|
19
|
+
#
|
20
|
+
from typing import Any
|
21
|
+
|
22
|
+
from openepd.compat.pydantic import pyd
|
23
|
+
from openepd.model.base import BaseOpenEpdSchema, Version
|
24
|
+
from openepd.model.validation.common import validate_version_compatibility, validate_version_format
|
25
|
+
from openepd.model.validation.quantity import QuantityValidator
|
26
|
+
from openepd.model.versioning import WithExtVersionMixin
|
27
|
+
|
28
|
+
|
29
|
+
class BaseOpenEpdSpec(BaseOpenEpdSchema):
|
30
|
+
"""Base class for all OpenEPD specs."""
|
31
|
+
|
32
|
+
class Config:
|
33
|
+
use_enum_values = False # we need to store enums as strings and not values
|
34
|
+
|
35
|
+
|
36
|
+
class BaseOpenEpdHierarchicalSpec(BaseOpenEpdSpec, WithExtVersionMixin):
|
37
|
+
"""Base class for new specs (hierarchical, versioned)."""
|
38
|
+
|
39
|
+
# external validator for quantities (e.g. length, mass, etc.) which should be setup by the user of the library.
|
40
|
+
_QUANTITY_VALIDATOR: QuantityValidator | None = None
|
41
|
+
|
42
|
+
def __init__(self, **data: Any) -> None:
|
43
|
+
# ensure that all the concrete spec objects fail on creations if they dont have _EXT_VERSION declared to
|
44
|
+
# something meaningful
|
45
|
+
if not hasattr(self, "_EXT_VERSION") or self._EXT_VERSION is None:
|
46
|
+
raise ValueError(f"Class {self.__class__} must declare an extension version")
|
47
|
+
Version.parse_version(self._EXT_VERSION) # validate format correctness
|
48
|
+
super().__init__(**{"ext_version": self._EXT_VERSION, **data})
|
49
|
+
|
50
|
+
_version_format_validator = pyd.validator("ext_version", allow_reuse=True, check_fields=False)(
|
51
|
+
validate_version_format
|
52
|
+
)
|
53
|
+
_version_major_match_validator = pyd.validator("ext_version", allow_reuse=True, check_fields=False)(
|
54
|
+
validate_version_compatibility("_EXT_VERSION")
|
55
|
+
)
|
56
|
+
|
57
|
+
|
58
|
+
def setup_external_validators(quantity_validator: QuantityValidator):
|
59
|
+
"""Set the implementation unit validator for specs."""
|
60
|
+
BaseOpenEpdHierarchicalSpec._QUANTITY_VALIDATOR = quantity_validator
|