openepd 6.13.2__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 (99) 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/model/base.py +60 -43
  18. openepd/model/category.py +13 -10
  19. openepd/model/common.py +100 -55
  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 +132 -113
  25. openepd/model/org.py +54 -33
  26. openepd/model/pcr.py +38 -32
  27. openepd/model/specs/asphalt.py +31 -22
  28. openepd/model/specs/base.py +11 -9
  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 +25 -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 +53 -25
  90. openepd/model/versioning.py +9 -6
  91. openepd/patch_pydantic.py +0 -93
  92. {openepd-6.13.2.dist-info → openepd-7.0.0.dist-info}/METADATA +1 -1
  93. openepd-7.0.0.dist-info/RECORD +142 -0
  94. openepd/compat/__init__.py +0 -15
  95. openepd/compat/compat_functional_validators.py +0 -25
  96. openepd/compat/pydantic.py +0 -30
  97. openepd-6.13.2.dist-info/RECORD +0 -145
  98. {openepd-6.13.2.dist-info → openepd-7.0.0.dist-info}/LICENSE +0 -0
  99. {openepd-6.13.2.dist-info → openepd-7.0.0.dist-info}/WHEEL +0 -0
openepd/model/epd.py CHANGED
@@ -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 BaseDocumentFactory, OpenEpdDoctypes, OpenEpdExtension
19
19
  from openepd.model.common import Ingredient, WithAltIdsMixin, WithAttachmentsMixin
20
20
  from openepd.model.declaration import (
@@ -73,50 +73,50 @@ class Ec3EpdExtension(OpenEpdExtension):
73
73
  """Return the name of the extension."""
74
74
  return "ec3"
75
75
 
76
- uaGWP_a1a2a3_traci21: float | None = pyd.Field(
76
+ uaGWP_a1a2a3_traci21: float | None = pydantic.Field(
77
77
  default=None,
78
78
  description="""The A1A2A3 uncertainty-adjusted GWP, in kgCO2e per declared unit, calculated for the TRACI 2.1
79
79
  LCIA method. This is the value that should be used to compare EPDs against each other, or against an
80
80
  uncertainty-adjusted limit/benchmark, once both have been converted to the same declared unit. This is a
81
81
  materialized value provided for the convenience of integrators, and can be regenerated at any time from the
82
82
  specificity and EC3 category. The value is provided per comparison_unit.""",
83
- example=22.5,
83
+ examples=[22.5],
84
84
  )
85
- uaGWP_a1a2a3_ar5: float | None = pyd.Field(
85
+ uaGWP_a1a2a3_ar5: float | None = pydantic.Field(
86
86
  default=None,
87
87
  description="""The A1A2A3 uncertainty-adjusted GWP, calculated for the IPCC AR5 LCIA method. This is the value
88
88
  that should be used to compare EPDs against each other, or against an uncertainty-adjusted limit/benchmark,
89
89
  once both have been converted to the same declared unit. This is a materialized value, and can be regenerated
90
90
  at any time from the specificity and EC3 category.""",
91
- example=22.5,
91
+ examples=[22.5],
92
92
  )
93
- category: str | None = pyd.Field(
93
+ category: str | None = pydantic.Field(
94
94
  default=None,
95
95
  description="The category of the EPD in EC3 notation. Same as EC3 category from root EPD's product_classes for "
96
96
  "EC3.",
97
97
  )
98
- manufacturer_specific: bool | None = pyd.Field(
98
+ manufacturer_specific: bool | None = pydantic.Field(
99
99
  default=None,
100
100
  description="""An EPD is Manufacturer Specific if it is based on data from a single manufacturer, as opposed
101
101
  to an industry group, sector, or generic process. This field should always be true for openEPD documents
102
102
  (as opposed to openIndustryEPDs).""",
103
103
  )
104
- plant_specific: bool | None = pyd.Field(
104
+ plant_specific: bool | None = pydantic.Field(
105
105
  default=None,
106
106
  description="""An EPD is Product Specific if it is based on data regarding the specific product being
107
107
  delivered, as opposed to a range of products whose GWP per unit may vary by more than 10%.""",
108
108
  )
109
- product_specific: bool | None = pyd.Field(
109
+ product_specific: bool | None = pydantic.Field(
110
110
  default=None,
111
111
  description="""An EPD is Product Specific if it is based on data regarding the specific product being
112
112
  delivered, as opposed to a range of products whose GWP per unit may vary by more than 10%.""",
113
113
  )
114
- batch_specific: bool | None = pyd.Field(
114
+ batch_specific: bool | None = pydantic.Field(
115
115
  default=None,
116
116
  description="""An EPD is Product Specific if it is created with production data for a single production run of
117
117
  no more than 90 days. Typically these must be generated on a just-in-time or on-demand basis.""",
118
118
  )
119
- supply_chain_specificity: float | None = pyd.Field(
119
+ supply_chain_specificity: float | None = pydantic.Field(
120
120
  default=None,
121
121
  description="""An EPD is Supply Chain Specific to the extent that impacts of process inputs are based on
122
122
  product-specific, facility-specific EPDs or third-party verified LCA for those inputs. For example, a concrete
@@ -124,7 +124,7 @@ class Ec3EpdExtension(OpenEpdExtension):
124
124
  have around 85% supply chain specificity.""",
125
125
  )
126
126
 
127
- original_data_format: OriginalDataFormat | None = pyd.Field(default=None)
127
+ original_data_format: OriginalDataFormat | None = pydantic.Field(default=None)
128
128
 
129
129
 
130
130
  class EpdRef(RefBase, title="EPD (Ref)"):
@@ -151,29 +151,35 @@ class EpdPreviewV0(
151
151
 
152
152
  _FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
153
153
 
154
- doctype: str = pyd.Field(
154
+ doctype: str = pydantic.Field(
155
155
  description='Describes the type and schema of the document. Must always always read "openEPD".',
156
156
  default="openEPD",
157
157
  )
158
158
 
159
- product_name: str | None = pyd.Field(
160
- max_length=200, description="The name of the product described by this EPD", example="Mix 12345AC", default=None
159
+ product_name: str | None = pydantic.Field(
160
+ max_length=200,
161
+ description="The name of the product described by this EPD",
162
+ examples=["Mix 12345AC"],
163
+ default=None,
161
164
  )
162
- product_sku: str | None = pyd.Field(
163
- max_length=200, description="Unique stock keeping identifier assigned by manufacturer"
165
+ product_sku: str | None = pydantic.Field(
166
+ max_length=200,
167
+ description="Unique stock keeping identifier assigned by manufacturer",
168
+ default=None,
164
169
  )
165
- product_description: str | None = pyd.Field(
170
+ product_description: str | None = pydantic.Field(
166
171
  max_length=2000,
167
172
  description="1-paragraph description of product. Supports plain text or github flavored markdown.",
173
+ default=None,
168
174
  )
169
- manufacturer: Org | None = pyd.Field(description=MANUFACTURER_DESCRIPTION)
170
- plants: list[Plant] = pyd.Field(
171
- max_items=32,
175
+ manufacturer: Org | None = pydantic.Field(description=MANUFACTURER_DESCRIPTION, default=None)
176
+ plants: list[Plant] = pydantic.Field(
177
+ max_length=32,
172
178
  description=PLANT_DESCRIPTION,
173
179
  default_factory=list,
174
180
  )
175
181
 
176
- annual_production: float | None = pyd.Field(
182
+ annual_production: float | None = pydantic.Field(
177
183
  gt=0,
178
184
  default=None,
179
185
  description="Approximate annual production volume, in declared units, of product covered by this EPD. "
@@ -181,10 +187,10 @@ class EpdPreviewV0(
181
187
  "Providing this data is optional, and it is acceptable to round or obfuscate it downwards "
182
188
  "(but not upwards) by any amount desired to protect confidentiality. For example, if the "
183
189
  "product volume is 123,456 m3, a value of 120,000, 100,000 or even 87,654 would be acceptable.",
184
- example=10000,
190
+ examples=[10000],
185
191
  )
186
- applicable_in: list[Geography] | None = pyd.Field(
187
- max_items=100,
192
+ applicable_in: list[Geography] | None = pydantic.Field(
193
+ max_length=100,
188
194
  default=None,
189
195
  description="Jurisdiction(s) in which EPD is applicable. An empty array, or absent properties, "
190
196
  "implies global applicability. Accepts "
@@ -192,37 +198,39 @@ class EpdPreviewV0(
192
198
  "[M49 region codes](https://unstats.un.org/unsd/methodology/m49/), "
193
199
  'or the alias "EU27" for the 27 members of the Euro bloc, or the alias "NAFTA" '
194
200
  "for the members of North American Free Trade Agreement",
195
- example=["US", "CA", "MX", "EU27", "NAFTA"],
201
+ examples=[["US", "CA", "MX", "EU27", "NAFTA"]],
196
202
  )
197
- product_usage_description: str | None = pyd.Field(
203
+ product_usage_description: str | None = pydantic.Field(
198
204
  default=None,
199
205
  description="Text description of how product is typically used. Can be used to describe accessories "
200
206
  "like fasteners, adhesives, etc. Supports plain text or github flavored markdown.",
201
207
  )
202
- product_usage_image: pyd.AnyUrl | None = pyd.Field(
203
- description="Pointer (url) to image illustrating how the product is used. No more than 10MB.", default=None
208
+ product_usage_image: pydantic.AnyUrl | None = pydantic.Field(
209
+ description="Pointer (url) to image illustrating how the product is used. No more than 10MB.",
210
+ default=None,
204
211
  )
205
- manufacturing_description: str | None = pyd.Field(
212
+ manufacturing_description: str | None = pydantic.Field(
206
213
  default=None,
207
214
  description="Text description of manufacturing process. Supports plain text or github flavored markdown.",
208
215
  )
209
- manufacturing_image: pyd.AnyUrl | None = pyd.Field(
210
- description="Pointer (url) to an image illustrating the manufacturing process. No more than 10MB.", default=None
216
+ manufacturing_image: pydantic.AnyUrl | None = pydantic.Field(
217
+ description="Pointer (url) to an image illustrating the manufacturing process. No more than 10MB.",
218
+ default=None,
211
219
  )
212
220
 
213
- specs: Specs = pyd.Field(
221
+ specs: Specs = pydantic.Field(
214
222
  default_factory=Specs,
215
223
  description="Data structure(s) describing performance specs of product. Unique for each material type.",
216
224
  )
217
- includes: list[Ingredient] = pyd.Field(
218
- max_items=255,
225
+ includes: list[Ingredient] = pydantic.Field(
226
+ max_length=255,
219
227
  description="List of JSON objects pointing to product components. "
220
228
  "Each one should be an EPD or digitized LCI process.",
221
229
  default_factory=list,
222
230
  )
223
- ec3: Ec3EpdExtension | None = pyd.Field(default=None, description="EC3-specific EPD extension.")
231
+ ec3: Ec3EpdExtension | None = pydantic.Field(default=None, description="EC3-specific EPD extension.")
224
232
 
225
- @pyd.validator("doctype")
233
+ @pydantic.field_validator("doctype", mode="before")
226
234
  def validate_doctype(cls, v: str | None) -> str:
227
235
  """
228
236
  Handle possible mixed case options for doctype.
@@ -247,14 +255,14 @@ class EpdV0(WithLciaMixin, EpdPreviewV0, title="EPD (Full)"):
247
255
  """Return the asset type of this class (see BaseOpenEpdSchema.get_asset_type for details)."""
248
256
  return "epd"
249
257
 
250
- @pyd.validator("compliance", always=True, pre=True)
258
+ @pydantic.field_validator("compliance", mode="before")
251
259
  def validate_compliance(cls, v: list | None):
252
260
  """Handle correctly None values for compliance field."""
253
261
  if v is None:
254
262
  return []
255
263
  return v
256
264
 
257
- @pyd.validator("includes", always=True, pre=True)
265
+ @pydantic.field_validator("includes", mode="before")
258
266
  def validate_includes(cls, v: list | None):
259
267
  """Handle correctly None values for includes field."""
260
268
  if v is None:
@@ -274,10 +282,10 @@ class EpdWithDepsV0(EpdV0, title="EPD (with Dependencies)"):
274
282
  some required fields in Org (like web_domain), and WithDeps would not.
275
283
  """
276
284
 
277
- manufacturer: Org | None = pyd.Field(description=MANUFACTURER_DESCRIPTION)
278
- epd_developer: Org | None = pyd.Field(description=DEVELOPER_DESCRIPTION, default=None)
279
- program_operator: Org | None = pyd.Field(description=PROGRAM_OPERATOR_DESCRIPTION)
280
- third_party_verifier: Org | None = pyd.Field(description=THIRD_PARTY_VERIFIER_DESCRIPTION)
285
+ manufacturer: Org | None = pydantic.Field(description=MANUFACTURER_DESCRIPTION)
286
+ epd_developer: Org | None = pydantic.Field(description=DEVELOPER_DESCRIPTION, default=None)
287
+ program_operator: Org | None = pydantic.Field(description=PROGRAM_OPERATOR_DESCRIPTION)
288
+ third_party_verifier: Org | None = pydantic.Field(description=THIRD_PARTY_VERIFIER_DESCRIPTION)
281
289
 
282
290
 
283
291
  EpdWithDeps = EpdWithDepsV0
@@ -16,7 +16,8 @@
16
16
  from enum import StrEnum
17
17
  from typing import Literal
18
18
 
19
- from openepd.compat.pydantic import pyd
19
+ import pydantic
20
+
20
21
  from openepd.model.base import BaseDocumentFactory, OpenEpdDoctypes
21
22
  from openepd.model.common import WithAltIdsMixin, WithAttachmentsMixin
22
23
  from openepd.model.declaration import AverageDatasetMixin, BaseDeclaration, RefBase
@@ -51,7 +52,11 @@ class GenericEstimateRef(RefBase, title="Generic Estimate (Ref)"):
51
52
 
52
53
 
53
54
  class GenericEstimatePreviewV0(
54
- WithAttachmentsMixin, AverageDatasetMixin, GenericEstimateRef, BaseDeclaration, title="Generic Estimate (preview)"
55
+ WithAttachmentsMixin,
56
+ AverageDatasetMixin,
57
+ GenericEstimateRef,
58
+ BaseDeclaration,
59
+ title="Generic Estimate (preview)",
55
60
  ):
56
61
  """
57
62
  Generic Estimate preview, used in API list responses and where there is no need for a full object.
@@ -61,27 +66,37 @@ class GenericEstimatePreviewV0(
61
66
 
62
67
  _FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
63
68
 
64
- doctype: Literal["openGenericEstimate"] = pyd.Field(
69
+ doctype: Literal["openGenericEstimate"] = pydantic.Field(
65
70
  description='Describes the type and schema of the document. Must always be "openGenericEstimate"',
66
71
  default="openGenericEstimate",
67
72
  )
68
73
 
69
- publisher: Org | None = pyd.Field(description="Organization that published the LCA results.")
70
- reviewer: Org | None = pyd.Field(description="Org that performed a critical review of the LCA.")
71
- reviewer_email: pyd.EmailStr | None = pyd.Field(
72
- description="Email address of the third party verifier", example="john.doe@example.com", default=None
74
+ publisher: Org | None = pydantic.Field(description="Organization that published the LCA results.", default=None)
75
+ reviewer: Org | None = pydantic.Field(description="Org that performed a critical review of the LCA.", default=None)
76
+ reviewer_email: pydantic.EmailStr | None = pydantic.Field(
77
+ description="Email address of the third party verifier",
78
+ examples=["john.doe@example.com"],
79
+ default=None,
73
80
  )
74
81
 
75
- license_terms: LicenseTerms | None = pyd.Field(description="The license terms for use of the data.")
76
- model_repository: pyd.AnyUrl | None = pyd.Field(
77
- default=None, description="A link to the shared git repository containing the LCA model used for this estimate."
82
+ license_terms: LicenseTerms | None = pydantic.Field(
83
+ description="The license terms for use of the data.", default=None
84
+ )
85
+ model_repository: pydantic.AnyUrl | None = pydantic.Field(
86
+ default=None,
87
+ description="A link to the shared git repository containing the LCA model used for this estimate.",
78
88
  )
79
89
 
80
90
 
81
91
  GenericEstimatePreview = GenericEstimatePreviewV0
82
92
 
83
93
 
84
- class GenericEstimateV0(GenericEstimatePreviewV0, WithLciaMixin, WithAltIdsMixin, title="Generic Estimate (Full)"):
94
+ class GenericEstimateV0(
95
+ GenericEstimatePreviewV0,
96
+ WithLciaMixin,
97
+ WithAltIdsMixin,
98
+ title="Generic Estimate (Full)",
99
+ ):
85
100
  """Full Generic Estimate object."""
86
101
 
87
102
 
@@ -95,8 +110,8 @@ class GenericEstimateWithDepsV0(GenericEstimateV0, title="Generic Estimate (with
95
110
  Contains related entities - orgs - with full fields, to support object matching in implementations.
96
111
  """
97
112
 
98
- publisher: Org | None = pyd.Field(description="Organization that published the LCA results.")
99
- reviewer: Org | None = pyd.Field(description="Org that performed a critical review of the LCA.")
113
+ publisher: Org | None = pydantic.Field(description="Organization that published the LCA results.")
114
+ reviewer: Org | None = pydantic.Field(description="Org that performed a critical review of the LCA.")
100
115
 
101
116
 
102
117
  GenericEstimateWithDeps = GenericEstimateWithDepsV0
@@ -15,7 +15,8 @@
15
15
  #
16
16
  from typing import Literal
17
17
 
18
- from openepd.compat.pydantic import pyd
18
+ import pydantic
19
+
19
20
  from openepd.model.base import BaseDocumentFactory, BaseOpenEpdSchema, OpenEpdDoctypes
20
21
  from openepd.model.common import WithAltIdsMixin, WithAttachmentsMixin
21
22
  from openepd.model.declaration import (
@@ -34,16 +35,21 @@ from openepd.model.versioning import OpenEpdVersions, Version
34
35
  class SampleSize(BaseOpenEpdSchema):
35
36
  """Sample size."""
36
37
 
37
- products: pyd.NonNegativeInt | None = pyd.Field(
38
+ products: int | None = pydantic.Field(
38
39
  default=None,
39
40
  description="Count of separate products or results that were included in this industry EPD, "
40
41
  "and over which the standard deviation was calculated",
42
+ ge=0,
41
43
  )
42
- plants: pyd.NonNegativeInt | None = pyd.Field(
43
- default=None, description="Count of unique manufacturing plants that submitted data for this Industry EPD"
44
+ plants: int | None = pydantic.Field(
45
+ default=None,
46
+ description="Count of unique manufacturing plants that submitted data for this Industry EPD",
47
+ ge=0,
44
48
  )
45
- manufacturers: pyd.NonNegativeInt | None = pyd.Field(
46
- default=None, description="Count of unique manufacturing companies that submitted data for this Industry EPD"
49
+ manufacturers: int | None = pydantic.Field(
50
+ default=None,
51
+ description="Count of unique manufacturing companies that submitted data for this Industry EPD",
52
+ ge=0,
47
53
  )
48
54
 
49
55
 
@@ -69,15 +75,15 @@ class IndustryEpdPreviewV0(
69
75
 
70
76
  _FORMAT_VERSION = OpenEpdVersions.Version0.as_str()
71
77
 
72
- doctype: Literal["openIndustryEpd"] = pyd.Field(
78
+ doctype: Literal["openIndustryEpd"] = pydantic.Field(
73
79
  description='Describes the type and schema of the document. Must always be "openIndustryEpd"',
74
80
  default="openIndustryEpd",
75
81
  )
76
82
 
77
83
  sample_size: SampleSize | None = None
78
84
 
79
- publishers: list[Org] | None = pyd.Field(description="")
80
- manufacturers: list[Org] | None = pyd.Field(description="Participating manufacturers")
85
+ publishers: list[Org] | None = pydantic.Field(description="", default=None)
86
+ manufacturers: list[Org] | None = pydantic.Field(description="Participating manufacturers", default=None)
81
87
 
82
88
 
83
89
  IndustryEpdPreview = IndustryEpdPreviewV0