openepd 6.13.1__py3-none-any.whl → 7.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.
Files changed (102) hide show
  1. openepd/__init__.py +4 -4
  2. openepd/__version__.py +1 -1
  3. openepd/api/average_dataset/generic_estimate_sync_api.py +11 -10
  4. openepd/api/average_dataset/industry_epd_sync_api.py +9 -8
  5. openepd/api/base_sync_client.py +53 -9
  6. openepd/api/category/sync_api.py +1 -1
  7. openepd/api/dto/base.py +4 -4
  8. openepd/api/dto/common.py +24 -16
  9. openepd/api/dto/meta.py +15 -11
  10. openepd/api/dto/mf.py +9 -8
  11. openepd/api/epd/dto.py +43 -33
  12. openepd/api/epd/sync_api.py +9 -9
  13. openepd/api/pcr/sync_api.py +2 -2
  14. openepd/bundle/model.py +11 -10
  15. openepd/bundle/reader.py +12 -5
  16. openepd/bundle/writer.py +17 -6
  17. openepd/m49/__init__.py +2 -0
  18. openepd/m49/const.py +5 -2
  19. openepd/m49/{geo_converter.py → utils.py} +24 -2
  20. openepd/model/base.py +60 -43
  21. openepd/model/category.py +13 -10
  22. openepd/model/common.py +100 -55
  23. openepd/model/declaration.py +93 -64
  24. openepd/model/epd.py +51 -43
  25. openepd/model/generic_estimate.py +28 -13
  26. openepd/model/industry_epd.py +15 -9
  27. openepd/model/lcia.py +132 -113
  28. openepd/model/org.py +54 -33
  29. openepd/model/pcr.py +38 -32
  30. openepd/model/specs/asphalt.py +31 -22
  31. openepd/model/specs/base.py +11 -9
  32. openepd/model/specs/concrete.py +60 -39
  33. openepd/model/specs/range/aggregates.py +9 -9
  34. openepd/model/specs/range/aluminium.py +7 -7
  35. openepd/model/specs/range/asphalt.py +22 -19
  36. openepd/model/specs/range/cladding.py +16 -16
  37. openepd/model/specs/range/cmu.py +10 -9
  38. openepd/model/specs/range/concrete.py +36 -27
  39. openepd/model/specs/range/conveying_equipment.py +16 -15
  40. openepd/model/specs/range/electrical.py +24 -22
  41. openepd/model/specs/range/finishes.py +109 -104
  42. openepd/model/specs/range/fire_and_smoke_protection.py +7 -7
  43. openepd/model/specs/range/furnishings.py +16 -12
  44. openepd/model/specs/range/manufacturing_inputs.py +16 -16
  45. openepd/model/specs/range/masonry.py +16 -16
  46. openepd/model/specs/range/mechanical.py +47 -47
  47. openepd/model/specs/range/mechanical_insulation.py +7 -7
  48. openepd/model/specs/range/network_infrastructure.py +54 -46
  49. openepd/model/specs/range/openings.py +36 -31
  50. openepd/model/specs/range/plumbing.py +15 -13
  51. openepd/model/specs/range/precast_concrete.py +20 -16
  52. openepd/model/specs/range/sheathing.py +18 -18
  53. openepd/model/specs/range/steel.py +25 -25
  54. openepd/model/specs/range/thermal_moisture_protection.py +20 -20
  55. openepd/model/specs/range/utility_piping.py +9 -9
  56. openepd/model/specs/range/wood.py +19 -19
  57. openepd/model/specs/range/wood_joists.py +8 -8
  58. openepd/model/specs/singular/__init__.py +9 -5
  59. openepd/model/specs/singular/aggregates.py +22 -15
  60. openepd/model/specs/singular/aluminium.py +20 -5
  61. openepd/model/specs/singular/asphalt.py +44 -20
  62. openepd/model/specs/singular/cladding.py +38 -23
  63. openepd/model/specs/singular/cmu.py +26 -11
  64. openepd/model/specs/singular/common.py +3 -2
  65. openepd/model/specs/singular/concrete.py +85 -48
  66. openepd/model/specs/singular/conveying_equipment.py +30 -17
  67. openepd/model/specs/singular/deprecated/__init__.py +3 -2
  68. openepd/model/specs/singular/deprecated/concrete.py +68 -33
  69. openepd/model/specs/singular/deprecated/steel.py +28 -15
  70. openepd/model/specs/singular/electrical.py +69 -41
  71. openepd/model/specs/singular/finishes.py +250 -140
  72. openepd/model/specs/singular/fire_and_smoke_protection.py +9 -6
  73. openepd/model/specs/singular/furnishings.py +16 -14
  74. openepd/model/specs/singular/manufacturing_inputs.py +23 -14
  75. openepd/model/specs/singular/masonry.py +66 -21
  76. openepd/model/specs/singular/mechanical.py +48 -47
  77. openepd/model/specs/singular/mechanical_insulation.py +7 -6
  78. openepd/model/specs/singular/mixins/conduit_mixin.py +13 -10
  79. openepd/model/specs/singular/network_infrastructure.py +111 -52
  80. openepd/model/specs/singular/openings.py +127 -95
  81. openepd/model/specs/singular/plumbing.py +15 -12
  82. openepd/model/specs/singular/precast_concrete.py +68 -54
  83. openepd/model/specs/singular/sheathing.py +47 -27
  84. openepd/model/specs/singular/steel.py +69 -45
  85. openepd/model/specs/singular/thermal_moisture_protection.py +36 -20
  86. openepd/model/specs/singular/utility_piping.py +11 -8
  87. openepd/model/specs/singular/wood.py +48 -24
  88. openepd/model/specs/singular/wood_joists.py +19 -6
  89. openepd/model/standard.py +15 -8
  90. openepd/model/validation/common.py +9 -3
  91. openepd/model/validation/numbers.py +0 -13
  92. openepd/model/validation/quantity.py +53 -25
  93. openepd/model/versioning.py +9 -6
  94. openepd/patch_pydantic.py +0 -93
  95. {openepd-6.13.1.dist-info → openepd-7.0.0.dist-info}/METADATA +1 -1
  96. openepd-7.0.0.dist-info/RECORD +142 -0
  97. openepd/compat/__init__.py +0 -15
  98. openepd/compat/compat_functional_validators.py +0 -25
  99. openepd/compat/pydantic.py +0 -30
  100. openepd-6.13.1.dist-info/RECORD +0 -145
  101. {openepd-6.13.1.dist-info → openepd-7.0.0.dist-info}/LICENSE +0 -0
  102. {openepd-6.13.1.dist-info → openepd-7.0.0.dist-info}/WHEEL +0 -0
@@ -13,7 +13,8 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- from openepd.compat.pydantic import pyd
16
+ import pydantic
17
+
17
18
  from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
18
19
  from openepd.model.specs.enums import (
19
20
  CableTraysMaterial,
@@ -42,13 +43,23 @@ class PDUV1(BaseOpenEpdHierarchicalSpec):
42
43
  _EXT_VERSION = "1.0"
43
44
 
44
45
  # Own fields:
45
- amperage: ElectricalCurrentStr | None = pyd.Field(default=None, description="", example="1 A")
46
- outlet_level_metering: bool | None = pyd.Field(default=None, description="", example=True)
47
- outlet_level_switching: bool | None = pyd.Field(default=None, description="", example=True)
48
- pdu_technology: PduTechnology | None = pyd.Field(default=None, description="", example="Basic")
49
- pdu_outlets: int | None = pyd.Field(default=None, description="", example=3, le=200)
46
+ amperage: ElectricalCurrentStr | None = pydantic.Field(default=None, description="", examples=["1 A"])
47
+ outlet_level_metering: bool | None = pydantic.Field(
48
+ default=None,
49
+ description="",
50
+ examples=[True],
51
+ )
52
+ outlet_level_switching: bool | None = pydantic.Field(
53
+ default=None,
54
+ description="",
55
+ examples=[True],
56
+ )
57
+ pdu_technology: PduTechnology | None = pydantic.Field(default=None, description="", examples=["Basic"])
58
+ pdu_outlets: int | None = pydantic.Field(default=None, description="", examples=[3], le=200)
50
59
 
51
- _amperage_is_quantity_validator = pyd.validator("amperage", allow_reuse=True)(validate_quantity_unit_factory("A"))
60
+ @pydantic.field_validator("amperage", mode="before", check_fields=False)
61
+ def _validate_amperage(cls, value):
62
+ return validate_quantity_unit_factory("A")(cls, value)
52
63
 
53
64
 
54
65
  class CabinetsRacksAndEnclosuresV1(BaseOpenEpdHierarchicalSpec):
@@ -57,9 +68,9 @@ class CabinetsRacksAndEnclosuresV1(BaseOpenEpdHierarchicalSpec):
57
68
  _EXT_VERSION = "1.0"
58
69
 
59
70
  # Own fields:
60
- static_load: MassKgStr | None = pyd.Field(default=None, description="", example="1 kg")
61
- total_racking_units: int | None = pyd.Field(default=None, description="", example=3)
62
- rack_type: RackType | None = pyd.Field(default=None, description="", example="Cabinet")
71
+ static_load: MassKgStr | None = pydantic.Field(default=None, description="", examples=["1 kg"])
72
+ total_racking_units: int | None = pydantic.Field(default=None, description="", examples=[3])
73
+ rack_type: RackType | None = pydantic.Field(default=None, description="", examples=["Cabinet"])
63
74
 
64
75
 
65
76
  class DataCablingV1(BaseOpenEpdHierarchicalSpec):
@@ -68,30 +79,52 @@ class DataCablingV1(BaseOpenEpdHierarchicalSpec):
68
79
  _EXT_VERSION = "1.0"
69
80
 
70
81
  # Own fields:
71
- outdoor: bool | None = pyd.Field(default=None, description="", example=True)
72
- cabling_category: CablingCategory | None = pyd.Field(default=None, description="", example="Cat7")
73
- fire_rating: CablingFireRating | None = pyd.Field(default=None, description="", example="CMP")
74
- jacket_material: CablingJacketMaterial | None = pyd.Field(default=None, description="", example="PVC")
75
- shielded: bool | None = pyd.Field(
76
- default=None, description="Foil or similar electromagnetic shielding", example=True
77
- )
78
- armored: bool | None = pyd.Field(default=None, description="Steel or similar physical armor jacket", example=True)
79
- rohs: bool | None = pyd.Field(default=None, description="Certified ROHS Compliant", example=True)
80
- reach: bool | None = pyd.Field(default=None, description="Certified REACH compliant", example=True)
81
- zwtl: bool | None = pyd.Field(default=None, description="Certified ZWTL compliant", example=True)
82
- connectorized: bool | None = pyd.Field(
82
+ outdoor: bool | None = pydantic.Field(
83
+ default=None,
84
+ description="",
85
+ examples=[True],
86
+ )
87
+ cabling_category: CablingCategory | None = pydantic.Field(default=None, description="", examples=["Cat7"])
88
+ fire_rating: CablingFireRating | None = pydantic.Field(default=None, description="", examples=["CMP"])
89
+ jacket_material: CablingJacketMaterial | None = pydantic.Field(default=None, description="", examples=["PVC"])
90
+ shielded: bool | None = pydantic.Field(
91
+ default=None,
92
+ description="Foil or similar electromagnetic shielding",
93
+ examples=[True],
94
+ )
95
+ armored: bool | None = pydantic.Field(
96
+ default=None,
97
+ description="Steel or similar physical armor jacket",
98
+ examples=[True],
99
+ )
100
+ rohs: bool | None = pydantic.Field(
101
+ default=None,
102
+ description="Certified ROHS Compliant",
103
+ examples=[True],
104
+ )
105
+ reach: bool | None = pydantic.Field(
106
+ default=None,
107
+ description="Certified REACH compliant",
108
+ examples=[True],
109
+ )
110
+ zwtl: bool | None = pydantic.Field(
111
+ default=None,
112
+ description="Certified ZWTL compliant",
113
+ examples=[True],
114
+ )
115
+ connectorized: bool | None = pydantic.Field(
83
116
  default=None,
84
117
  description="This cable is shipped as a specific length with integrated connectors. Impacts include the "
85
118
  "connectors for the specific cable length. Connectors add impact similar to 0.1-0.5 additional "
86
119
  "meters of cable",
87
- example=True,
120
+ examples=[True],
88
121
  )
89
- thin_ethernet: bool | None = pyd.Field(
122
+ thin_ethernet: bool | None = pydantic.Field(
90
123
  default=None,
91
124
  description="At least part of this cable has a reduced outer diameter and thinner wires. Thin ethernet cables "
92
125
  "have handling advantages and tend to have a reduced impact, but also reduced channel length. "
93
126
  "See TIA 568.2-D Annex G.",
94
- example=True,
127
+ examples=[True],
95
128
  )
96
129
 
97
130
 
@@ -105,29 +138,45 @@ class FloorBoxesAndAccessoriesV1(BaseOpenEpdHierarchicalSpec):
105
138
  _EXT_VERSION = "1.0"
106
139
 
107
140
  # Own fields:
108
- painted: bool | None = pyd.Field(default=None, description="", example=True)
109
- fire_classified: bool | None = pyd.Field(
110
- default=None, description="Includes hardware to maintain fire rating of the floor", example=True
141
+ painted: bool | None = pydantic.Field(
142
+ default=None,
143
+ description="",
144
+ examples=[True],
145
+ )
146
+ fire_classified: bool | None = pydantic.Field(
147
+ default=None,
148
+ description="Includes hardware to maintain fire rating of the floor",
149
+ examples=[True],
150
+ )
151
+ outdoor: bool | None = pydantic.Field(
152
+ default=None,
153
+ description="Floor boxes installed in the ground",
154
+ examples=[True],
111
155
  )
112
- outdoor: bool | None = pyd.Field(default=None, description="Floor boxes installed in the ground", example=True)
113
- raised: bool | None = pyd.Field(default=None, description="Used in raised or computer style flooring", example=True)
114
- poke_through: bool | None = pyd.Field(
156
+ raised: bool | None = pydantic.Field(
157
+ default=None,
158
+ description="Used in raised or computer style flooring",
159
+ examples=[True],
160
+ )
161
+ poke_through: bool | None = pydantic.Field(
115
162
  default=None,
116
163
  description="Used primarily in retrofit or renovation and will maintain fire rating of the floor",
117
- example=True,
164
+ examples=[True],
118
165
  )
119
- cover: bool | None = pyd.Field(
120
- default=None, description="Floor box cover or lid for use with a separate floor box", example=True
166
+ cover: bool | None = pydantic.Field(
167
+ default=None,
168
+ description="Floor box cover or lid for use with a separate floor box",
169
+ examples=[True],
121
170
  )
122
- outlets: int | None = pyd.Field(
171
+ outlets: int | None = pydantic.Field(
123
172
  default=None,
124
173
  description="Number of outlet ports from floor box, including power, data, video, and other connections",
125
- example=3,
174
+ examples=[3],
126
175
  le=16,
127
176
  )
128
- material: FloorBoxMaterial | None = pyd.Field(default=None, description="", example="Metallic Box")
129
- cover_material: FloorBoxCoverMaterial | None = pyd.Field(default=None, description="", example="Brass")
130
- floor_material: FloorBoxFloorMaterial | None = pyd.Field(default=None, description="", example="Concrete")
177
+ material: FloorBoxMaterial | None = pydantic.Field(default=None, description="", examples=["Metallic Box"])
178
+ cover_material: FloorBoxCoverMaterial | None = pydantic.Field(default=None, description="", examples=["Brass"])
179
+ floor_material: FloorBoxFloorMaterial | None = pydantic.Field(default=None, description="", examples=["Concrete"])
131
180
 
132
181
 
133
182
  class NetworkingCableTraysV1(BaseOpenEpdHierarchicalSpec):
@@ -141,14 +190,18 @@ class NetworkingCableTraysV1(BaseOpenEpdHierarchicalSpec):
141
190
  _EXT_VERSION = "1.0"
142
191
 
143
192
  # Own fields:
144
- height: LengthMmStr | None = pyd.Field(default=None, description="", example="100 mm")
145
- width: LengthMmStr | None = pyd.Field(default=None, description="", example="100 mm")
146
- depth: LengthMmStr | None = pyd.Field(default=None, description="Depth of enclosure system", example="1 m")
147
- static_load: MassKgStr | None = pyd.Field(default=None, description="Mass that the unit can hold", example="1 kg")
148
- ventilated: bool | None = pyd.Field(
149
- default=None, description="At least 40% of the tray base is open to air flow", example=True
193
+ height: LengthMmStr | None = pydantic.Field(default=None, description="", examples=["100 mm"])
194
+ width: LengthMmStr | None = pydantic.Field(default=None, description="", examples=["100 mm"])
195
+ depth: LengthMmStr | None = pydantic.Field(default=None, description="Depth of enclosure system", examples=["1 m"])
196
+ static_load: MassKgStr | None = pydantic.Field(
197
+ default=None, description="Mass that the unit can hold", examples=["1 kg"]
198
+ )
199
+ ventilated: bool | None = pydantic.Field(
200
+ default=None,
201
+ description="At least 40% of the tray base is open to air flow",
202
+ examples=[True],
150
203
  )
151
- material: CableTraysMaterial | None = pyd.Field(default=None, description="", example="Stainless Steel")
204
+ material: CableTraysMaterial | None = pydantic.Field(default=None, description="", examples=["Stainless Steel"])
152
205
 
153
206
 
154
207
  class NetworkingRacewaysV1(BaseOpenEpdHierarchicalSpec):
@@ -161,15 +214,21 @@ class NetworkingRacewaysV1(BaseOpenEpdHierarchicalSpec):
161
214
  _EXT_VERSION = "1.0"
162
215
 
163
216
  # Own fields:
164
- width: LengthMmStr | None = pyd.Field(default=None, description="", example="100 mm")
165
- depth: LengthMmStr | None = pyd.Field(default=None, description="Depth of enclosure system", example="100 mm")
166
- painted: bool | None = pyd.Field(default=None, description="", example=True)
167
- divided: bool | None = pyd.Field(
217
+ width: LengthMmStr | None = pydantic.Field(default=None, description="", examples=["100 mm"])
218
+ depth: LengthMmStr | None = pydantic.Field(
219
+ default=None, description="Depth of enclosure system", examples=["100 mm"]
220
+ )
221
+ painted: bool | None = pydantic.Field(
222
+ default=None,
223
+ description="",
224
+ examples=[True],
225
+ )
226
+ divided: bool | None = pydantic.Field(
168
227
  default=None,
169
228
  description="Dual service raceway for high and low voltage data and power applications",
170
- example=True,
229
+ examples=[True],
171
230
  )
172
- raceways_material: RacewaysMaterial | None = pyd.Field(default=None, description="", example="Aluminum")
231
+ raceways_material: RacewaysMaterial | None = pydantic.Field(default=None, description="", examples=["Aluminum"])
173
232
 
174
233
 
175
234
  class CommunicationsConduitV1(BaseOpenEpdHierarchicalSpec, ConduitMixin):
@@ -13,8 +13,8 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
+ import pydantic
16
17
 
17
- from openepd.compat.pydantic import pyd
18
18
  from openepd.model.base import BaseOpenEpdSchema
19
19
  from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec
20
20
  from openepd.model.specs.enums import (
@@ -25,7 +25,6 @@ from openepd.model.specs.enums import (
25
25
  Spacer,
26
26
  ThermalSeparation,
27
27
  )
28
- from openepd.model.validation.numbers import RatioFloat
29
28
  from openepd.model.validation.quantity import (
30
29
  LengthMmStr,
31
30
  PressureMPaStr,
@@ -38,90 +37,108 @@ from openepd.model.validation.quantity import (
38
37
  class GlazingIntendedApplication(BaseOpenEpdSchema):
39
38
  """Glass intended application mixin."""
40
39
 
41
- curtain_wall: bool | None = pyd.Field(default=None, description="Intended for curtain walls. Relevant for IGUs.")
42
- r_windows: bool | None = pyd.Field(
40
+ curtain_wall: bool | None = pydantic.Field(
41
+ default=None, description="Intended for curtain walls. Relevant for IGUs."
42
+ )
43
+ r_windows: bool | None = pydantic.Field(
43
44
  default=None,
44
45
  description="Intended for residential (NAFS 'R') and similar windows, doors, or skylights. Relevant for IGUs.",
45
46
  )
46
- lc_windows: bool | None = pyd.Field(
47
- default=None, description="Intended for light commercial (NAFS 'LC') and similar windows. Relevant for IGUs."
47
+ lc_windows: bool | None = pydantic.Field(
48
+ default=None,
49
+ description="Intended for light commercial (NAFS 'LC') and similar windows. Relevant for IGUs.",
48
50
  )
49
- cw_windows: bool | None = pyd.Field(
50
- default=None, description="Intended for commercial (NAFS 'CW') and similar windows. Relevant for IGUs."
51
+ cw_windows: bool | None = pydantic.Field(
52
+ default=None,
53
+ description="Intended for commercial (NAFS 'CW') and similar windows. Relevant for IGUs.",
51
54
  )
52
- aw_windows: bool | None = pyd.Field(
53
- default=None, description="Intended for architectural (NAFS 'AW') and similar windows. Relevant for IGUs."
55
+ aw_windows: bool | None = pydantic.Field(
56
+ default=None,
57
+ description="Intended for architectural (NAFS 'AW') and similar windows. Relevant for IGUs.",
54
58
  )
55
- storefronts: bool | None = pyd.Field(
56
- default=None, description="Intended for Storefronts and similar applications. Relevant for IGUs."
59
+ storefronts: bool | None = pydantic.Field(
60
+ default=None,
61
+ description="Intended for Storefronts and similar applications. Relevant for IGUs.",
57
62
  )
58
- glazed_doors: bool | None = pyd.Field(
59
- default=None, description="Intended for Glazed Doors and similar applications. Relevant for IGUs."
63
+ glazed_doors: bool | None = pydantic.Field(
64
+ default=None,
65
+ description="Intended for Glazed Doors and similar applications. Relevant for IGUs.",
60
66
  )
61
- unit_skylights: bool | None = pyd.Field(
62
- default=None, description="Intended for Unit Skylights and similar applications. Relevant for IGUs."
67
+ unit_skylights: bool | None = pydantic.Field(
68
+ default=None,
69
+ description="Intended for Unit Skylights and similar applications. Relevant for IGUs.",
63
70
  )
64
- sloped_skylights: bool | None = pyd.Field(
71
+ sloped_skylights: bool | None = pydantic.Field(
65
72
  default=None,
66
73
  description="Intended for sloped glazing, and architectural skylights, and similar. Relevant for IGUs.",
67
74
  )
68
- other: bool | None = pyd.Field(
69
- default=None, description="Intended for other application not listed. Relevant for IGUs."
75
+ other: bool | None = pydantic.Field(
76
+ default=None,
77
+ description="Intended for other application not listed. Relevant for IGUs.",
70
78
  )
71
79
 
72
80
 
73
81
  class GlazingOptionsMixin(BaseOpenEpdSchema):
74
82
  """Common glazing options."""
75
83
 
76
- low_emissivity: bool | None = pyd.Field(default=None, description="Low Emissivity coatings", example=True)
77
- electrochromic: bool | None = pyd.Field(
84
+ low_emissivity: bool | None = pydantic.Field(
85
+ default=None,
86
+ description="Low Emissivity coatings",
87
+ examples=[True],
88
+ )
89
+ electrochromic: bool | None = pydantic.Field(
78
90
  default=None,
79
91
  description="Glazing with an electrically controllable solar heat gain and/or other properties.",
80
- example=True,
92
+ examples=[True],
81
93
  )
82
- acid_etched: bool | None = pyd.Field(
83
- default=None, description="Flat glass that has undergone a chemical etching process.", example=True
94
+ acid_etched: bool | None = pydantic.Field(
95
+ default=None,
96
+ description="Flat glass that has undergone a chemical etching process.",
97
+ examples=[True],
84
98
  )
85
- tempered: bool | None = pyd.Field(
99
+ tempered: bool | None = pydantic.Field(
86
100
  default=None,
87
101
  description="Consists of a single pane that has been heat-treated to give the glass increased impact "
88
102
  "resistance. Standard typically used in North America.",
89
- example=True,
103
+ examples=[True],
90
104
  )
91
- toughened: bool | None = pyd.Field(
105
+ toughened: bool | None = pydantic.Field(
92
106
  default=None,
93
107
  description="Consists of a single pane that has been specially heat-treated to give the glass increased impact "
94
108
  "resistance. Standard typically used in Europe.",
95
- example=True,
109
+ examples=[True],
96
110
  )
97
- laminated: bool | None = pyd.Field(
111
+ laminated: bool | None = pydantic.Field(
98
112
  default=None,
99
113
  description="Consists of at least two glass panes lying one on top of the other, with one or several layers of "
100
114
  "a tear-resistant, viscoelastic film positioned between the panes, which consist of polyvinyl "
101
115
  "butyral (PVB)",
102
- example=True,
116
+ examples=[True],
103
117
  )
104
- fire_resistant: bool | None = pyd.Field(default=None, example=True)
105
- fire_protection: bool | None = pyd.Field(
118
+ fire_resistant: bool | None = pydantic.Field(
119
+ default=None,
120
+ examples=[True],
121
+ )
122
+ fire_protection: bool | None = pydantic.Field(
106
123
  default=None,
107
124
  description="Specifically tested for its ability to block flames and smoke, but not radiant heat. Ranges from"
108
125
  " specialty tempered products rated for ~20 minutes to glass ceramics rated up to 3 hours.",
109
- example=True,
126
+ examples=[True],
110
127
  )
111
- pyrolytic_coated: bool | None = pyd.Field(
128
+ pyrolytic_coated: bool | None = pydantic.Field(
112
129
  default=None,
113
130
  description="At least one coating is applied in a pyrolytic process, typically during float glass production.",
114
- example=True,
131
+ examples=[True],
115
132
  )
116
- sputter_coat: bool | None = pyd.Field(
133
+ sputter_coat: bool | None = pydantic.Field(
117
134
  default=None,
118
135
  description="At least one coating is applied using sputter (vacuum deposition) coating.",
119
- example=True,
136
+ examples=[True],
120
137
  )
121
- solar_heat_gain: RatioFloat | None = pyd.Field(
138
+ solar_heat_gain: float | None = pydantic.Field(
122
139
  default=None,
123
140
  description="Solar heat gain, measured at a certain level of Differential Pressure. Range is 0 to 1.",
124
- example=0.5,
141
+ examples=[0.5],
125
142
  ge=0,
126
143
  le=1,
127
144
  )
@@ -181,8 +198,8 @@ class FenestrationFramingV1(BaseOpenEpdHierarchicalSpec):
181
198
  _EXT_VERSION = "1.0"
182
199
 
183
200
  # Own fields:
184
- thermal_separation: ThermalSeparation | None = pyd.Field(default=None, example="Aluminium")
185
- material: FrameMaterial | None = pyd.Field(default=None, example="Vinyl")
201
+ thermal_separation: ThermalSeparation | None = pydantic.Field(default=None, examples=["Aluminium"])
202
+ material: FrameMaterial | None = pydantic.Field(default=None, examples=["Vinyl"])
186
203
 
187
204
 
188
205
  class FenestrationHardwareV1(BaseOpenEpdHierarchicalSpec):
@@ -191,7 +208,7 @@ class FenestrationHardwareV1(BaseOpenEpdHierarchicalSpec):
191
208
  _EXT_VERSION = "1.0"
192
209
 
193
210
  # Own fields:
194
- function: HardwareFunction | None = pyd.Field(default=None, description="", example="Lock")
211
+ function: HardwareFunction | None = pydantic.Field(default=None, description="", examples=["Lock"])
195
212
 
196
213
 
197
214
  class FlatGlassPanesV1(BaseOpenEpdHierarchicalSpec):
@@ -200,11 +217,11 @@ class FlatGlassPanesV1(BaseOpenEpdHierarchicalSpec):
200
217
  _EXT_VERSION = "1.0"
201
218
 
202
219
  # Own fields:
203
- thickness: FlatGlassPanesThickness | None = pyd.Field(default=None, example="12 mm")
220
+ thickness: FlatGlassPanesThickness | None = pydantic.Field(default=None, examples=["12 mm"])
204
221
 
205
- _flat_glass_panes_thickness_is_quantity_validator = pyd.validator("thickness", allow_reuse=True)(
206
- validate_quantity_unit_factory("m")
207
- )
222
+ @pydantic.field_validator("thickness")
223
+ def _flat_glass_panes_thickness_is_quantity_validator(cls, v):
224
+ return validate_quantity_unit_factory("m")(cls, v)
208
225
 
209
226
 
210
227
  class ProcessedNonInsulatingGlassPanesV1(BaseOpenEpdHierarchicalSpec, GlazingOptionsMixin):
@@ -295,7 +312,7 @@ class FenestrationPartsV1(BaseOpenEpdHierarchicalSpec):
295
312
  _EXT_VERSION = "1.0"
296
313
 
297
314
  # Own fields:
298
- intended_application: GlazingIntendedApplication | None = pyd.Field(
315
+ intended_application: GlazingIntendedApplication | None = pydantic.Field(
299
316
  default=None, description="Intended application."
300
317
  )
301
318
 
@@ -318,27 +335,29 @@ class GlassPanesV1(BaseOpenEpdHierarchicalSpec):
318
335
  class NAFSPerformanceClass(BaseOpenEpdSchema):
319
336
  """NAFS Performance class."""
320
337
 
321
- r: bool | None = pyd.Field(
322
- default=None, description="Residential; commonly used in one- and two-family dwellings.", example=True
338
+ r: bool | None = pydantic.Field(
339
+ default=None,
340
+ description="Residential; commonly used in one- and two-family dwellings.",
341
+ examples=[True],
323
342
  )
324
- lc: bool | None = pyd.Field(
343
+ lc: bool | None = pydantic.Field(
325
344
  default=None,
326
345
  description="Light Commercial: commonly used in low-rise and mid-rise multi-family dwellings and other "
327
346
  "buildings where larger sizes and higher loading requirements are expected.",
328
- example=True,
347
+ examples=[True],
329
348
  )
330
- cw: bool | None = pyd.Field(
349
+ cw: bool | None = pydantic.Field(
331
350
  default=None,
332
351
  description="Commercial Window: commonly used in low-rise and mid-rise buildings where larger sizes, higher "
333
352
  "loading requirements, limits on deflection, and heavy use are expected.",
334
- example=True,
353
+ examples=[True],
335
354
  )
336
- aw: bool | None = pyd.Field(
355
+ aw: bool | None = pydantic.Field(
337
356
  default=None,
338
357
  description="Architectural Window: commonly used in high-rise and mid-rise buildings to meet increased "
339
358
  "loading requirements and limits on deflection, and in buildings where frequent and extreme use "
340
359
  "of the fenestration products is expected.",
341
- example=True,
360
+ examples=[True],
342
361
  )
343
362
 
344
363
 
@@ -348,49 +367,52 @@ class NAFSFenestrationV1(BaseOpenEpdHierarchicalSpec, GlazingOptionsMixin):
348
367
  _EXT_VERSION = "1.0"
349
368
 
350
369
  # Own fields:
351
- hurricane_resistant: bool | None = pyd.Field(
352
- default=None, description="The product has been designed to resist windborne debris.", example=True
370
+ hurricane_resistant: bool | None = pydantic.Field(
371
+ default=None,
372
+ description="The product has been designed to resist windborne debris.",
373
+ examples=[True],
353
374
  )
354
375
 
355
- assembly_u_factor: UFactorStr | None = pyd.Field(
376
+ assembly_u_factor: UFactorStr | None = pydantic.Field(
356
377
  default=None,
357
378
  description="Weighted average conductance of heat across assembly (including frame).",
358
- example="1 USI",
379
+ examples=["1 USI"],
359
380
  )
360
- air_infiltration: SpeedStr | None = pyd.Field(
381
+ air_infiltration: SpeedStr | None = pydantic.Field(
361
382
  default=None,
362
383
  description="Air infiltration, measured at a certain level of Differential Pressure.",
363
- example="1 m3 / m2 / s",
384
+ examples=["1 m3 / m2 / s"],
364
385
  )
365
386
 
366
- thermal_separation: ThermalSeparation | None = pyd.Field(default=None, example="Aluminium")
367
- dp_rating: PressureMPaStr | None = pyd.Field(default=None, description="", example="1 MPa")
368
- glass_panes: int | None = pyd.Field(
387
+ thermal_separation: ThermalSeparation | None = pydantic.Field(default=None, examples=["Aluminium"])
388
+ dp_rating: PressureMPaStr | None = pydantic.Field(default=None, description="", examples=["1 MPa"])
389
+ glass_panes: int | None = pydantic.Field(
369
390
  default=None,
370
391
  description="Number of panes, each separated by a cavity. A 3 pane unit has 2 cavities. example: 3",
371
- example=3,
392
+ examples=[3],
372
393
  )
373
394
 
374
- performance_class: NAFSPerformanceClass | None = pyd.Field(
395
+ performance_class: NAFSPerformanceClass | None = pydantic.Field(
375
396
  default=None, description="Performance class according to NAFS."
376
397
  )
377
398
 
378
- performance_grade: NAFSPerformanceGrade | None = pyd.Field(
399
+ performance_grade: NAFSPerformanceGrade | None = pydantic.Field(
379
400
  default=None,
380
401
  description="NAFS Performance Grade. The NAFS Performance Grade is a number that represents the performance "
381
402
  "of the glazing product. The higher the number, the better the performance. The NAFS Performance "
382
403
  "Grade is calculated using the NAFS Performance Class, the NAFS Performance Index, and the NAFS "
383
404
  "Performance Factor. While it is expressed as pressure, there are specific values which are "
384
405
  "allowed. The values are listed in the enum.",
385
- example="95 psf",
406
+ examples=["95 psf"],
386
407
  )
387
408
 
388
- _assembly_u_factor_is_quantity_validator = pyd.validator("assembly_u_factor", allow_reuse=True)(
389
- validate_quantity_unit_factory("USI")
390
- )
391
- _nafs_performance_grade_is_quantity_validator = pyd.validator("performance_grade", allow_reuse=True)(
392
- validate_quantity_unit_factory("psf")
393
- )
409
+ @pydantic.field_validator("assembly_u_factor")
410
+ def _assembly_u_factor_is_quantity_validator(cls, v):
411
+ return validate_quantity_unit_factory("USI")(cls, v)
412
+
413
+ @pydantic.field_validator("performance_grade")
414
+ def _nafs_performance_grade_is_quantity_validator(cls, v):
415
+ return validate_quantity_unit_factory("psf")(cls, v)
394
416
 
395
417
  # Nested specs:
396
418
  GlazedDoors: GlazedDoorsV1 | None = None
@@ -404,38 +426,48 @@ class InsulatingGlazingUnitsV1(BaseOpenEpdHierarchicalSpec, GlazingOptionsMixin)
404
426
  _EXT_VERSION = "1.0"
405
427
 
406
428
  # Own fields:
407
- intended_application: GlazingIntendedApplication | None = pyd.Field(
429
+ intended_application: GlazingIntendedApplication | None = pydantic.Field(
408
430
  default=None, description="Intended application for IGUs."
409
431
  )
410
432
 
411
- hurricane_resistant: bool | None = pyd.Field(default=None, example=True)
433
+ hurricane_resistant: bool | None = pydantic.Field(
434
+ default=None,
435
+ examples=[True],
436
+ )
412
437
 
413
- dp_rating: PressureMPaStr | None = pyd.Field(
414
- default=None, description="Maximum Differential Pressure, a measure of wind tolerance.", example="1 MPa"
438
+ dp_rating: PressureMPaStr | None = pydantic.Field(
439
+ default=None,
440
+ description="Maximum Differential Pressure, a measure of wind tolerance.",
441
+ examples=["1 MPa"],
415
442
  )
416
- air_infiltration: SpeedStr | None = pyd.Field(
443
+ air_infiltration: SpeedStr | None = pydantic.Field(
417
444
  default=None,
418
445
  description="Air infiltration, measured at a certain level of Differential Pressure.",
419
- example="1 m3 / m2 / s",
446
+ examples=["1 m3 / m2 / s"],
420
447
  )
421
- glass_panes: int | None = pyd.Field(
448
+ glass_panes: int | None = pydantic.Field(
422
449
  default=None,
423
450
  description="Number of panes, each separated by a cavity. A 3 pane unit has 2 cavities. example: 3",
424
- example=3,
451
+ examples=[3],
425
452
  )
426
- cog_u_factor: UFactorStr | None = pyd.Field(
427
- default=None, description="Conductance of heat at center of glass.", example="1 USI"
453
+ cog_u_factor: UFactorStr | None = pydantic.Field(
454
+ default=None,
455
+ description="Conductance of heat at center of glass.",
456
+ examples=["1 USI"],
428
457
  )
429
- spacer: Spacer | None = pyd.Field(
430
- default=None, description="Spacer material for Integrated Glass Unit.", example="Aluminium"
458
+ spacer: Spacer | None = pydantic.Field(
459
+ default=None,
460
+ description="Spacer material for Integrated Glass Unit.",
461
+ examples=["Aluminium"],
431
462
  )
432
463
 
433
- _dp_rating_is_quantity_validator = pyd.validator("dp_rating", allow_reuse=True)(
434
- validate_quantity_unit_factory("MPa")
435
- )
436
- _cog_u_factor_is_quantity_validator = pyd.validator("cog_u_factor", allow_reuse=True)(
437
- validate_quantity_unit_factory("USI")
438
- )
464
+ @pydantic.field_validator("dp_rating")
465
+ def _dp_rating_is_quantity_validator(cls, v):
466
+ return validate_quantity_unit_factory("MPa")(cls, v)
467
+
468
+ @pydantic.field_validator("cog_u_factor")
469
+ def _cog_u_factor_is_quantity_validator(cls, v):
470
+ return validate_quantity_unit_factory("USI")(cls, v)
439
471
 
440
472
 
441
473
  class CurtainWallsV1(BaseOpenEpdHierarchicalSpec):
@@ -458,8 +490,8 @@ class DoorsAndFramesV1(BaseOpenEpdHierarchicalSpec):
458
490
  _EXT_VERSION = "1.0"
459
491
 
460
492
  # Own fields:
461
- height: LengthMmStr | None = pyd.Field(default=None, example="1200 mm")
462
- width: LengthMmStr | None = pyd.Field(default=None, example="600 mm")
493
+ height: LengthMmStr | None = pydantic.Field(default=None, examples=["1200 mm"])
494
+ width: LengthMmStr | None = pydantic.Field(default=None, examples=["600 mm"])
463
495
 
464
496
  # Nested specs:
465
497
  IntegratedDoorsOpeningAssemblies: IntegratedDoorsOpeningAssembliesV1 | None = None
@@ -535,7 +567,7 @@ class OpeningsV1(BaseOpenEpdHierarchicalSpec):
535
567
  _EXT_VERSION = "1.0"
536
568
 
537
569
  # Own fields:
538
- thickness: LengthMmStr | None = pyd.Field(default=None, example="80 mm")
570
+ thickness: LengthMmStr | None = pydantic.Field(default=None, examples=["80 mm"])
539
571
 
540
572
  # Nested specs:
541
573
  CurtainWalls: CurtainWallsV1 | None = None