openepd 6.13.2__py3-none-any.whl → 7.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. openepd/__init__.py +0 -6
  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/model/base.py +61 -44
  18. openepd/model/category.py +13 -10
  19. openepd/model/common.py +107 -59
  20. openepd/model/declaration.py +93 -64
  21. openepd/model/epd.py +51 -43
  22. openepd/model/generic_estimate.py +28 -13
  23. openepd/model/industry_epd.py +15 -9
  24. openepd/model/lcia.py +161 -136
  25. openepd/model/org.py +70 -37
  26. openepd/model/pcr.py +38 -32
  27. openepd/model/specs/asphalt.py +31 -22
  28. openepd/model/specs/base.py +14 -11
  29. openepd/model/specs/concrete.py +60 -39
  30. openepd/model/specs/range/aggregates.py +9 -9
  31. openepd/model/specs/range/aluminium.py +7 -7
  32. openepd/model/specs/range/asphalt.py +22 -19
  33. openepd/model/specs/range/cladding.py +16 -16
  34. openepd/model/specs/range/cmu.py +10 -9
  35. openepd/model/specs/range/concrete.py +36 -27
  36. openepd/model/specs/range/conveying_equipment.py +16 -15
  37. openepd/model/specs/range/electrical.py +24 -22
  38. openepd/model/specs/range/finishes.py +109 -104
  39. openepd/model/specs/range/fire_and_smoke_protection.py +7 -7
  40. openepd/model/specs/range/furnishings.py +16 -12
  41. openepd/model/specs/range/manufacturing_inputs.py +16 -16
  42. openepd/model/specs/range/masonry.py +16 -16
  43. openepd/model/specs/range/mechanical.py +47 -47
  44. openepd/model/specs/range/mechanical_insulation.py +7 -7
  45. openepd/model/specs/range/network_infrastructure.py +54 -46
  46. openepd/model/specs/range/openings.py +36 -31
  47. openepd/model/specs/range/plumbing.py +15 -13
  48. openepd/model/specs/range/precast_concrete.py +20 -16
  49. openepd/model/specs/range/sheathing.py +18 -18
  50. openepd/model/specs/range/steel.py +27 -25
  51. openepd/model/specs/range/thermal_moisture_protection.py +20 -20
  52. openepd/model/specs/range/utility_piping.py +9 -9
  53. openepd/model/specs/range/wood.py +19 -19
  54. openepd/model/specs/range/wood_joists.py +8 -8
  55. openepd/model/specs/singular/__init__.py +9 -5
  56. openepd/model/specs/singular/aggregates.py +22 -15
  57. openepd/model/specs/singular/aluminium.py +20 -5
  58. openepd/model/specs/singular/asphalt.py +44 -20
  59. openepd/model/specs/singular/cladding.py +38 -23
  60. openepd/model/specs/singular/cmu.py +26 -11
  61. openepd/model/specs/singular/common.py +3 -2
  62. openepd/model/specs/singular/concrete.py +85 -48
  63. openepd/model/specs/singular/conveying_equipment.py +30 -17
  64. openepd/model/specs/singular/deprecated/__init__.py +3 -2
  65. openepd/model/specs/singular/deprecated/concrete.py +68 -33
  66. openepd/model/specs/singular/deprecated/steel.py +28 -15
  67. openepd/model/specs/singular/electrical.py +69 -41
  68. openepd/model/specs/singular/finishes.py +250 -140
  69. openepd/model/specs/singular/fire_and_smoke_protection.py +9 -6
  70. openepd/model/specs/singular/furnishings.py +16 -14
  71. openepd/model/specs/singular/manufacturing_inputs.py +23 -14
  72. openepd/model/specs/singular/masonry.py +66 -21
  73. openepd/model/specs/singular/mechanical.py +48 -47
  74. openepd/model/specs/singular/mechanical_insulation.py +7 -6
  75. openepd/model/specs/singular/mixins/conduit_mixin.py +13 -10
  76. openepd/model/specs/singular/network_infrastructure.py +111 -52
  77. openepd/model/specs/singular/openings.py +127 -95
  78. openepd/model/specs/singular/plumbing.py +15 -12
  79. openepd/model/specs/singular/precast_concrete.py +68 -54
  80. openepd/model/specs/singular/sheathing.py +47 -27
  81. openepd/model/specs/singular/steel.py +69 -45
  82. openepd/model/specs/singular/thermal_moisture_protection.py +36 -20
  83. openepd/model/specs/singular/utility_piping.py +11 -8
  84. openepd/model/specs/singular/wood.py +48 -24
  85. openepd/model/specs/singular/wood_joists.py +19 -6
  86. openepd/model/standard.py +15 -8
  87. openepd/model/validation/common.py +9 -3
  88. openepd/model/validation/numbers.py +0 -13
  89. openepd/model/validation/quantity.py +88 -55
  90. openepd/model/versioning.py +9 -6
  91. {openepd-6.13.2.dist-info → openepd-7.0.1.dist-info}/METADATA +2 -2
  92. openepd-7.0.1.dist-info/RECORD +141 -0
  93. openepd/compat/__init__.py +0 -15
  94. openepd/compat/compat_functional_validators.py +0 -25
  95. openepd/compat/pydantic.py +0 -30
  96. openepd/patch_pydantic.py +0 -108
  97. openepd-6.13.2.dist-info/RECORD +0 -145
  98. {openepd-6.13.2.dist-info → openepd-7.0.1.dist-info}/LICENSE +0 -0
  99. {openepd-6.13.2.dist-info → openepd-7.0.1.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 FireProtectionPipingMaterial, PipingAnsiSchedule, PlumbingPipingMaterial
19
20
  from openepd.model.validation.quantity import LengthMmStr, MassPerLengthStr
@@ -49,12 +50,12 @@ class FireProtectionPipingV1(BaseOpenEpdHierarchicalSpec):
49
50
  _EXT_VERSION = "1.0"
50
51
 
51
52
  # Own fields:
52
- thickness: LengthMmStr | None = pyd.Field(default=None, description="", example="6 mm")
53
- piping_diameter: LengthMmStr | None = pyd.Field(default=None, description="", example="120 mm")
54
- mass_per_unit_length: MassPerLengthStr | None = pyd.Field(default=None, description="", example="1 kg / m")
55
- piping_ansi_schedule: PipingAnsiSchedule | None = pyd.Field(default=None, description="", example="5")
56
- fire_protection_piping_material: FireProtectionPipingMaterial | None = pyd.Field(
57
- default=None, description="", example="PVC"
53
+ thickness: LengthMmStr | None = pydantic.Field(default=None, description="", examples=["6 mm"])
54
+ piping_diameter: LengthMmStr | None = pydantic.Field(default=None, description="", examples=["120 mm"])
55
+ mass_per_unit_length: MassPerLengthStr | None = pydantic.Field(default=None, description="", examples=["1 kg / m"])
56
+ piping_ansi_schedule: PipingAnsiSchedule | None = pydantic.Field(default=None, description="", examples=["5"])
57
+ fire_protection_piping_material: FireProtectionPipingMaterial | None = pydantic.Field(
58
+ default=None, description="", examples=["PVC"]
58
59
  )
59
60
 
60
61
 
@@ -109,11 +110,13 @@ class PipingV1(BaseOpenEpdHierarchicalSpec):
109
110
  _EXT_VERSION = "1.0"
110
111
 
111
112
  # Own fields:
112
- thickness: LengthMmStr | None = pyd.Field(default=None, description="", example="6 mm")
113
- piping_diameter: LengthMmStr | None = pyd.Field(default=None, description="", example="120 mm")
114
- mass_per_unit_length: MassPerLengthStr | None = pyd.Field(default=None, description="", example="1 kg / m")
115
- piping_ansi_schedule: PipingAnsiSchedule | None = pyd.Field(default=None, description="", example="5")
116
- plumbing_piping_material: PlumbingPipingMaterial | None = pyd.Field(default=None, description="", example="PVC")
113
+ thickness: LengthMmStr | None = pydantic.Field(default=None, description="", examples=["6 mm"])
114
+ piping_diameter: LengthMmStr | None = pydantic.Field(default=None, description="", examples=["120 mm"])
115
+ mass_per_unit_length: MassPerLengthStr | None = pydantic.Field(default=None, description="", examples=["1 kg / m"])
116
+ piping_ansi_schedule: PipingAnsiSchedule | None = pydantic.Field(default=None, description="", examples=["5"])
117
+ plumbing_piping_material: PlumbingPipingMaterial | None = pydantic.Field(
118
+ default=None, description="", examples=["PVC"]
119
+ )
117
120
 
118
121
 
119
122
  class PlumbingEquipmentV1(BaseOpenEpdHierarchicalSpec):
@@ -13,53 +13,53 @@
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, BaseOpenEpdSpec
18
- from openepd.model.validation.numbers import RatioFloat
19
19
  from openepd.model.validation.quantity import PressureMPaStr
20
20
 
21
21
 
22
22
  class StructuralPrecastElementType(BaseOpenEpdSpec):
23
23
  """Precast element types for Structural Precast Concrete."""
24
24
 
25
- wall: bool | None = pyd.Field(
25
+ wall: bool | None = pydantic.Field(
26
26
  description="Precast solid wall elements, including thin shell",
27
- example=True,
27
+ examples=[True],
28
28
  default=None,
29
29
  )
30
- solid_slab: bool | None = pyd.Field(
30
+ solid_slab: bool | None = pydantic.Field(
31
31
  description="Precast slabs used for floor or roof applications",
32
- example=True,
32
+ examples=[True],
33
33
  default=None,
34
34
  )
35
- hollowcore: bool | None = pyd.Field(
35
+ hollowcore: bool | None = pydantic.Field(
36
36
  description="Precast slabs with tubular voids, typically used flooring applications",
37
- example=True,
37
+ examples=[True],
38
38
  default=None,
39
39
  )
40
- beam: bool | None = pyd.Field(
40
+ beam: bool | None = pydantic.Field(
41
41
  description="Precast structural beams for carrying or transferring loads; includes girders",
42
- example=True,
42
+ examples=[True],
43
43
  default=None,
44
44
  )
45
- column: bool | None = pyd.Field(
45
+ column: bool | None = pydantic.Field(
46
46
  description="Precast structural columns for carrying or transferring loads",
47
- example=True,
47
+ examples=[True],
48
48
  default=None,
49
49
  )
50
- stairs: bool | None = pyd.Field(
50
+ stairs: bool | None = pydantic.Field(
51
51
  description="Staircases made of precast concrete components",
52
- example=True,
52
+ examples=[True],
53
53
  default=None,
54
54
  )
55
- balcony: bool | None = pyd.Field(
55
+ balcony: bool | None = pydantic.Field(
56
56
  description="Balcony slabs made from precast concrete",
57
- example=True,
57
+ examples=[True],
58
58
  default=None,
59
59
  )
60
- pile: bool | None = pyd.Field(
60
+ pile: bool | None = pydantic.Field(
61
61
  description="Precast concrete structural foundation elements used to support offshore structures such as bridges, oil rigs, and floating airports",
62
- example=True,
62
+ examples=[True],
63
63
  default=None,
64
64
  )
65
65
 
@@ -67,19 +67,19 @@ class StructuralPrecastElementType(BaseOpenEpdSpec):
67
67
  class UtilityPrecastElementType(BaseOpenEpdSpec):
68
68
  """Precast element types for Utility Underground Precast Concrete."""
69
69
 
70
- manhole: bool | None = pyd.Field(
70
+ manhole: bool | None = pydantic.Field(
71
71
  description="Precast barrel-shaped chambers used for wastewater management and access management",
72
- example=True,
72
+ examples=[True],
73
73
  default=None,
74
74
  )
75
- retaining_wall: bool | None = pyd.Field(
75
+ retaining_wall: bool | None = pydantic.Field(
76
76
  description="Precast concrete structures for retaining soil",
77
- example=True,
77
+ examples=[True],
78
78
  default=None,
79
79
  )
80
- box_culvert: bool | None = pyd.Field(
80
+ box_culvert: bool | None = pydantic.Field(
81
81
  description="A precast concrete structure commonly used to channel water, primarily as part of a drainage system",
82
- example=True,
82
+ examples=[True],
83
83
  default=None,
84
84
  )
85
85
 
@@ -87,9 +87,9 @@ class UtilityPrecastElementType(BaseOpenEpdSpec):
87
87
  class ArchitecturalPrecastElementType(BaseOpenEpdSpec):
88
88
  """Precast element types for Architectural Precast Concrete."""
89
89
 
90
- wall: bool | None = pyd.Field(
90
+ wall: bool | None = pydantic.Field(
91
91
  description="Precast solid wall elements, including thin shell",
92
- example=True,
92
+ examples=[True],
93
93
  default=None,
94
94
  )
95
95
 
@@ -97,39 +97,39 @@ class ArchitecturalPrecastElementType(BaseOpenEpdSpec):
97
97
  class CivilPrecastElementType(BaseOpenEpdSpec):
98
98
  """Precast element types for Civil Precast Concrete."""
99
99
 
100
- beam: bool | None = pyd.Field(
100
+ beam: bool | None = pydantic.Field(
101
101
  description="Precast structural beams for carrying or transferring loads; includes girders",
102
- example=True,
102
+ examples=[True],
103
103
  default=None,
104
104
  )
105
- manhole: bool | None = pyd.Field(
105
+ manhole: bool | None = pydantic.Field(
106
106
  description="Precast barrel-shaped chambers used for wastewater management and access management",
107
- example=True,
107
+ examples=[True],
108
108
  default=None,
109
109
  )
110
- retaining_wall: bool | None = pyd.Field(
110
+ retaining_wall: bool | None = pydantic.Field(
111
111
  description="Precast concrete structures for retaining soil",
112
- example=True,
112
+ examples=[True],
113
113
  default=None,
114
114
  )
115
- rail_sleeper: bool | None = pyd.Field(
115
+ rail_sleeper: bool | None = pydantic.Field(
116
116
  description="Rectangular supports for the rails on railroad tracks, which transfer loads to the track ballast and subgrade and keep the rails spaced to the correct gauge. Also called railroad ties",
117
- example=True,
117
+ examples=[True],
118
118
  default=None,
119
119
  )
120
- box_culvert: bool | None = pyd.Field(
120
+ box_culvert: bool | None = pydantic.Field(
121
121
  description="A precast concrete structure commonly used to channel water, primarily as part of a drainage system",
122
- example=True,
122
+ examples=[True],
123
123
  default=None,
124
124
  )
125
- pile: bool | None = pyd.Field(
125
+ pile: bool | None = pydantic.Field(
126
126
  description="Precast concrete structural foundation elements used to support offshore structures such as bridges, oil rigs, and floating airports",
127
- example=True,
127
+ examples=[True],
128
128
  default=None,
129
129
  )
130
- road_barriers: bool | None = pyd.Field(
130
+ road_barriers: bool | None = pydantic.Field(
131
131
  description="Precast Vehicle and Traffic Barriers",
132
- example=True,
132
+ examples=[True],
133
133
  default=None,
134
134
  )
135
135
 
@@ -139,8 +139,9 @@ class ArchitecturalPrecastV1(BaseOpenEpdHierarchicalSpec):
139
139
 
140
140
  _EXT_VERSION = "1.1"
141
141
 
142
- element_type: ArchitecturalPrecastElementType | None = pyd.Field(
143
- default=None, description="Precast element type used for architectural applications."
142
+ element_type: ArchitecturalPrecastElementType | None = pydantic.Field(
143
+ default=None,
144
+ description="Precast element type used for architectural applications.",
144
145
  )
145
146
 
146
147
 
@@ -149,8 +150,9 @@ class StructuralPrecastV1(BaseOpenEpdHierarchicalSpec):
149
150
 
150
151
  _EXT_VERSION = "1.1"
151
152
 
152
- element_type: StructuralPrecastElementType | None = pyd.Field(
153
- default=None, description="Precast element type used for structural applications."
153
+ element_type: StructuralPrecastElementType | None = pydantic.Field(
154
+ default=None,
155
+ description="Precast element type used for structural applications.",
154
156
  )
155
157
 
156
158
 
@@ -159,8 +161,9 @@ class UtilityUndergroundPrecastV1(BaseOpenEpdHierarchicalSpec):
159
161
 
160
162
  _EXT_VERSION = "1.1"
161
163
 
162
- element_type: UtilityPrecastElementType | None = pyd.Field(
163
- default=None, description="Precast element type used for utility underground applications."
164
+ element_type: UtilityPrecastElementType | None = pydantic.Field(
165
+ default=None,
166
+ description="Precast element type used for utility underground applications.",
164
167
  )
165
168
 
166
169
 
@@ -169,8 +172,9 @@ class CivilPrecastV1(BaseOpenEpdHierarchicalSpec):
169
172
 
170
173
  _EXT_VERSION = "1.0"
171
174
 
172
- element_type: CivilPrecastElementType | None = pyd.Field(
173
- default=None, description="Precast element type used as civil engineering components."
175
+ element_type: CivilPrecastElementType | None = pydantic.Field(
176
+ default=None,
177
+ description="Precast element type used as civil engineering components.",
174
178
  )
175
179
 
176
180
 
@@ -180,16 +184,26 @@ class PrecastConcreteV1(BaseOpenEpdHierarchicalSpec):
180
184
  _EXT_VERSION = "1.1"
181
185
 
182
186
  # Own fields:
183
- lightweight: bool | None = pyd.Field(default=None, description="", example=True)
184
- concrete_compressive_strength_28d: PressureMPaStr | None = pyd.Field(default=None, description="", example="1 MPa")
185
- insulated: bool | None = pyd.Field(default=None, description="", example=True)
186
- gfrc: bool | None = pyd.Field(
187
+ lightweight: bool | None = pydantic.Field(
188
+ default=None,
189
+ description="",
190
+ examples=[True],
191
+ )
192
+ concrete_compressive_strength_28d: PressureMPaStr | None = pydantic.Field(
193
+ default=None, description="", examples=["1 MPa"]
194
+ )
195
+ insulated: bool | None = pydantic.Field(
196
+ default=None,
197
+ description="",
198
+ examples=[True],
199
+ )
200
+ gfrc: bool | None = pydantic.Field(
187
201
  default=None,
188
202
  description="Glass Fiber Reinforced Concrete is fiber-reinforced concrete sometimes used in "
189
203
  "architectural panels",
190
- example=True,
204
+ examples=[True],
191
205
  )
192
- steel_mass_percentage: RatioFloat | None = pyd.Field(default=None, description="", example=0.5, ge=0, le=1)
206
+ steel_mass_percentage: float | None = pydantic.Field(default=None, description="", examples=[0.5], ge=0, le=1)
193
207
 
194
208
  # Nested specs:
195
209
  ArchitecturalPrecast: ArchitecturalPrecastV1 | None = None
@@ -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 GypsumFacing, GypsumFireRating, GypsumThickness
19
20
  from openepd.model.validation.quantity import LengthMmStr, RFactorStr, validate_quantity_unit_factory
@@ -30,11 +31,11 @@ class CementitiousSheathingBoardV1(BaseOpenEpdHierarchicalSpec):
30
31
  _EXT_VERSION = "1.0"
31
32
 
32
33
  # Own fields:
33
- cement_board_thickness: LengthMmStr | None = pyd.Field(default=None, description="", example="10 mm")
34
+ cement_board_thickness: LengthMmStr | None = pydantic.Field(default=None, description="", examples=["10 mm"])
34
35
 
35
- _cement_board_thickness_is_quantity_validator = pyd.validator("cement_board_thickness", allow_reuse=True)(
36
- validate_quantity_unit_factory("m")
37
- )
36
+ @pydantic.field_validator("cement_board_thickness", mode="before", check_fields=False)
37
+ def _cement_board_thickness_is_quantity_validator(cls, v):
38
+ return validate_quantity_unit_factory("m")(cls, v)
38
39
 
39
40
 
40
41
  class GypsumSheathingBoardV1(BaseOpenEpdHierarchicalSpec):
@@ -47,32 +48,51 @@ class GypsumSheathingBoardV1(BaseOpenEpdHierarchicalSpec):
47
48
  _EXT_VERSION = "1.1"
48
49
 
49
50
  # Own fields:
50
- fire_rating: GypsumFireRating | None = pyd.Field(default=None, description="", example="-")
51
- thickness: GypsumThickness | None = pyd.Field(default=None, description="", example="9 mm")
52
- facing: GypsumFacing | None = pyd.Field(default=None, description="", example="Paper")
53
-
54
- r_factor: RFactorStr | None = pyd.Field(default=None, description="", example="1 RSI")
55
-
56
- flame_spread_astm_e84: int | None = pyd.Field(default=None, description="", example=3)
57
- smoke_production_astm_e84: int | None = pyd.Field(default=None, description="", example=3)
58
- surface_abrasion_d4977: int | None = pyd.Field(default=None, description="", example=3)
59
- indentation_d5420: int | None = pyd.Field(default=None, description="", example=3)
60
- soft_body_impact_e695: int | None = pyd.Field(default=None, description="", example=3)
61
- hard_body_impact_c1929: int | None = pyd.Field(default=None, description="", example=3)
62
-
63
- mold_resistant: bool | None = pyd.Field(default=None, description="", example=True)
64
- foil_backing: bool | None = pyd.Field(default=None, description="", example=True)
65
- moisture_resistant: bool | None = pyd.Field(default=None, description="", example=True)
66
- abuse_resistant: bool | None = pyd.Field(default=None, description="", example=True)
67
-
68
- _gypsum_thickness_is_quantity_validator = pyd.validator("thickness", allow_reuse=True)(
69
- validate_quantity_unit_factory("m")
51
+ fire_rating: GypsumFireRating | None = pydantic.Field(default=None, description="", examples=["-"])
52
+ thickness: GypsumThickness | None = pydantic.Field(default=None, description="", examples=["9 mm"])
53
+ facing: GypsumFacing | None = pydantic.Field(default=None, description="", examples=["Paper"])
54
+
55
+ r_factor: RFactorStr | None = pydantic.Field(default=None, description="", examples=["1 RSI"])
56
+
57
+ flame_spread_astm_e84: int | None = pydantic.Field(default=None, description="", examples=[3])
58
+ smoke_production_astm_e84: int | None = pydantic.Field(default=None, description="", examples=[3])
59
+ surface_abrasion_d4977: int | None = pydantic.Field(default=None, description="", examples=[3])
60
+ indentation_d5420: int | None = pydantic.Field(default=None, description="", examples=[3])
61
+ soft_body_impact_e695: int | None = pydantic.Field(default=None, description="", examples=[3])
62
+ hard_body_impact_c1929: int | None = pydantic.Field(default=None, description="", examples=[3])
63
+
64
+ mold_resistant: bool | None = pydantic.Field(
65
+ default=None,
66
+ description="",
67
+ examples=[True],
68
+ )
69
+ foil_backing: bool | None = pydantic.Field(
70
+ default=None,
71
+ description="",
72
+ examples=[True],
73
+ )
74
+ moisture_resistant: bool | None = pydantic.Field(
75
+ default=None,
76
+ description="",
77
+ examples=[True],
70
78
  )
71
- _gypsum_r_factor_is_quantity_validator = pyd.validator("r_factor", allow_reuse=True)(
72
- validate_quantity_unit_factory("RSI")
79
+ abuse_resistant: bool | None = pydantic.Field(
80
+ default=None,
81
+ description="",
82
+ examples=[True],
73
83
  )
74
84
 
75
85
 
86
+ @pydantic.field_validator("thickness")
87
+ def _gypsum_thickness_is_quantity_validator(cls, v):
88
+ return validate_quantity_unit_factory("m")(cls, v)
89
+
90
+
91
+ @pydantic.field_validator("r_factor")
92
+ def _gypsum_r_factor_is_quantity_validator(cls, v):
93
+ return validate_quantity_unit_factory("RSI")(cls, v)
94
+
95
+
76
96
  class SheathingV1(BaseOpenEpdHierarchicalSpec):
77
97
  """
78
98
  Sheathing.
@@ -15,12 +15,12 @@
15
15
  #
16
16
  from typing import Annotated
17
17
 
18
- from openepd.compat.pydantic import pyd
18
+ import pydantic
19
+
19
20
  from openepd.model.base import BaseOpenEpdSchema
20
21
  from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec, BaseOpenEpdSpec, CodegenSpec
21
22
  from openepd.model.specs.enums import SteelComposition, SteelRebarGrade
22
23
  from openepd.model.standard import Standard
23
- from openepd.model.validation.numbers import RatioFloat
24
24
  from openepd.model.validation.quantity import (
25
25
  LengthMmStr,
26
26
  PressureMPaStr,
@@ -33,15 +33,19 @@ from openepd.model.validation.quantity import (
33
33
  class SteelMakingRoute(BaseOpenEpdSchema):
34
34
  """Steel making route."""
35
35
 
36
- bof: bool | None = pyd.Field(default=None, description="Basic oxygen furnace")
37
- eaf: bool | None = pyd.Field(default=None, description="Electric arc furnace")
38
- ohf: bool | None = pyd.Field(default=None, description="Open hearth furnace")
36
+ bof: bool | None = pydantic.Field(default=None, description="Basic oxygen furnace")
37
+ eaf: bool | None = pydantic.Field(default=None, description="Electric arc furnace")
38
+ ohf: bool | None = pydantic.Field(default=None, description="Open hearth furnace")
39
39
 
40
40
 
41
41
  class SteelFabricatedMixin(BaseOpenEpdSpec):
42
42
  """Class with fabricated property used in different parts of steel hierarchy."""
43
43
 
44
- fabricated: bool | None = pyd.Field(default=None, description="", example=True)
44
+ fabricated: bool | None = pydantic.Field(
45
+ default=None,
46
+ description="",
47
+ examples=[True],
48
+ )
45
49
 
46
50
 
47
51
  class ColdFormedFramingV1(BaseOpenEpdHierarchicalSpec):
@@ -176,28 +180,29 @@ class StructuralSteelV1(BaseOpenEpdHierarchicalSpec):
176
180
  _EXT_VERSION = "1.0"
177
181
 
178
182
  # Own fields:
179
- modulus_of_elasticity: PressureMPaStr | None = pyd.Field(
183
+ modulus_of_elasticity: PressureMPaStr | None = pydantic.Field(
180
184
  default=None,
181
185
  description="Modulus of Elasticity, https://en.wikipedia.org/wiki/Elastic_modulus ",
182
- example="193 GPa",
186
+ examples=["193 GPa"],
183
187
  )
184
- thermal_expansion: ThermalExpansionStr | None = pyd.Field(
188
+ thermal_expansion: ThermalExpansionStr | None = pydantic.Field(
185
189
  default=None,
186
190
  description="Thermal Expansion, https://en.wikipedia.org/wiki/Thermal_expansion",
187
- example="1.11E-5 / K",
191
+ examples=["1.11E-5 / K"],
188
192
  )
189
- thermal_conductivity: ThermalConductivityStr | None = pyd.Field(
193
+ thermal_conductivity: ThermalConductivityStr | None = pydantic.Field(
190
194
  default=None,
191
195
  description="Thermal Conductivity, https://en.wikipedia.org/wiki/Thermal_conductivity_and_resistivity",
192
- example="1.45E-5 W / m / K)",
196
+ examples=["1.45E-5 W / m / K)"],
193
197
  )
194
198
 
195
- _steel_thermal_expansion_is_quantity_validator = pyd.validator("thermal_expansion", allow_reuse=True)(
196
- validate_quantity_unit_factory("1 / K")
197
- )
198
- _steel_thermal_conductivity_is_quantity_validator = pyd.validator("thermal_conductivity", allow_reuse=True)(
199
- validate_quantity_unit_factory("W / (m * K)")
200
- )
199
+ @pydantic.field_validator("thermal_expansion")
200
+ def _steel_thermal_expansion_is_quantity_validator(cls, value):
201
+ return validate_quantity_unit_factory("1 / K")(cls, value)
202
+
203
+ @pydantic.field_validator("thermal_conductivity")
204
+ def _steel_thermal_conductivity_is_quantity_validator(cls, value):
205
+ return validate_quantity_unit_factory("W / (m * K)")(cls, value)
201
206
 
202
207
  # Nested specs:
203
208
  HollowSections: HollowSectionsV1 | None = None
@@ -229,13 +234,18 @@ class RebarSteelV1(BaseOpenEpdHierarchicalSpec, SteelFabricatedMixin):
229
234
  _EXT_VERSION = "1.0"
230
235
 
231
236
  # Own fields:
232
- grade: SteelRebarGrade | None = pyd.Field(default=None, example="60 ksi")
233
- diameter_min: LengthMmStr | None = pyd.Field(default=None, description="Minimal diameter", example="8 mm")
234
- bending_pin_max: float | None = pyd.Field(default=None, example=2.3)
235
- ts_ys_ratio_max: float | None = pyd.Field(
236
- default=None, description="Max ratio of ultimate tensile to yield tensile strength", example=2.3
237
+ grade: SteelRebarGrade | None = pydantic.Field(default=None, examples=["60 ksi"])
238
+ diameter_min: LengthMmStr | None = pydantic.Field(default=None, description="Minimal diameter", examples=["8 mm"])
239
+ bending_pin_max: float | None = pydantic.Field(default=None, examples=[2.3])
240
+ ts_ys_ratio_max: float | None = pydantic.Field(
241
+ default=None,
242
+ description="Max ratio of ultimate tensile to yield tensile strength",
243
+ examples=[2.3],
244
+ )
245
+ epoxy_coated: bool | None = pydantic.Field(
246
+ default=None,
247
+ examples=[True],
237
248
  )
238
- epoxy_coated: bool | None = pyd.Field(default=None, example=True)
239
249
 
240
250
 
241
251
  class WireMeshSteelV1(BaseOpenEpdHierarchicalSpec, SteelFabricatedMixin):
@@ -256,42 +266,56 @@ class SteelV1(BaseOpenEpdHierarchicalSpec):
256
266
  _EXT_VERSION = "1.1"
257
267
 
258
268
  # Own fields:
259
- yield_tensile_str: PressureMPaStr | None = pyd.Field(
269
+ yield_tensile_str: PressureMPaStr | None = pydantic.Field(
260
270
  default=None,
261
271
  description="Yield Tensile strength (Mpa) per unit area. Yield strength is the point at which a material "
262
272
  "begins to permanently deform or change shape due to applied stress.",
263
- example="100 MPa",
273
+ examples=["100 MPa"],
264
274
  )
265
- bar_elongation: float | None = pyd.Field(
266
- default=None, description="Increase in length at break, in percent. Typically 10%-20%", example=0.2
275
+ bar_elongation: float | None = pydantic.Field(
276
+ default=None,
277
+ description="Increase in length at break, in percent. Typically 10%-20%",
278
+ examples=[0.2],
267
279
  )
268
- recycled_content: RatioFloat | None = pyd.Field(default=None, description="", example=0.5, ge=0, le=1)
269
- # todo look how to pass validation down to range fields
270
- post_consumer_recycled_content: RatioFloat | None = pyd.Field(
280
+ recycled_content: float | None = pydantic.Field(default=None, description="", examples=[0.5], ge=0, le=1)
281
+ post_consumer_recycled_content: float | None = pydantic.Field(
271
282
  default=None,
272
283
  description="Should be a number between zero and the Recycled Content (steel_recycled_content)",
273
- example=0.5,
284
+ examples=[0.5],
274
285
  ge=0,
275
286
  le=1,
276
287
  )
277
- astm_marking: str | None = pyd.Field(
278
- default=None, description="The marking to be expected on the product.", example="S4S60"
288
+ astm_marking: str | None = pydantic.Field(
289
+ default=None,
290
+ description="The marking to be expected on the product.",
291
+ examples=["S4S60"],
279
292
  )
280
- euro_marking: str | None = pyd.Field(
281
- default=None, description="The marking to be expected on the product.", example="S4S60"
293
+ euro_marking: str | None = pydantic.Field(
294
+ default=None,
295
+ description="The marking to be expected on the product.",
296
+ examples=["S4S60"],
282
297
  )
283
- composition: SteelComposition | None = pyd.Field(
284
- default=None, description="Basic chemical composition", example="Carbon"
298
+ composition: SteelComposition | None = pydantic.Field(
299
+ default=None, description="Basic chemical composition", examples=["Carbon"]
300
+ )
301
+ cold_finished: bool | None = pydantic.Field(
302
+ default=None,
303
+ examples=[True],
304
+ )
305
+ galvanized: bool | None = pydantic.Field(
306
+ default=None,
307
+ examples=[True],
308
+ )
309
+ stainless: bool | None = pydantic.Field(
310
+ default=None,
311
+ examples=[True],
285
312
  )
286
- cold_finished: bool | None = pyd.Field(default=None, example=True)
287
- galvanized: bool | None = pyd.Field(default=None, example=True)
288
- stainless: bool | None = pyd.Field(default=None, example=True)
289
- making_route: Annotated[SteelMakingRoute | None, CodegenSpec(override_type=SteelMakingRoute)] = pyd.Field(
313
+ making_route: Annotated[SteelMakingRoute | None, CodegenSpec(override_type=SteelMakingRoute)] = pydantic.Field(
290
314
  default=None
291
315
  )
292
- astm_standards: list[Standard] | None = pyd.Field(default=None, description="List of ASTM standards")
293
- sae_standards: list[Standard] | None = pyd.Field(default=None, description="List of SAE standards")
294
- en_standards: list[Standard] | None = pyd.Field(default=None, description="List of EN standards")
316
+ astm_standards: list[Standard] | None = pydantic.Field(default=None, description="List of ASTM standards")
317
+ sae_standards: list[Standard] | None = pydantic.Field(default=None, description="List of SAE standards")
318
+ en_standards: list[Standard] | None = pydantic.Field(default=None, description="List of EN standards")
295
319
 
296
320
  # Nested specs:
297
321
  MBQSteel: MBQSteelV1 | None = None