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
@@ -16,7 +16,11 @@
16
16
  from abc import ABC, abstractmethod
17
17
  from typing import TYPE_CHECKING, Any, Callable, ClassVar
18
18
 
19
- from openepd.compat.pydantic import pyd
19
+ import pydantic
20
+ from pydantic import ConfigDict
21
+ import pydantic_core
22
+ from typing_extensions import Self
23
+
20
24
  from openepd.model.base import BaseOpenEpdSchema
21
25
  from openepd.model.common import Amount, OpenEPDUnit, RangeAmount
22
26
 
@@ -113,7 +117,9 @@ def validate_unit_factory(dimensionality: OpenEPDUnit | str) -> "QuantityValidat
113
117
  return validator
114
118
 
115
119
 
116
- def validate_quantity_unit_factory(dimensionality: OpenEPDUnit | str) -> "QuantityValidatorType":
120
+ def validate_quantity_unit_factory(
121
+ dimensionality: OpenEPDUnit | str,
122
+ ) -> "QuantityValidatorType":
117
123
  """Create validator for quantity field to check unit matching."""
118
124
 
119
125
  def validator(cls: type | None, value: str) -> str:
@@ -162,17 +168,32 @@ class QuantityStr(str):
162
168
  unit: ClassVar[str]
163
169
 
164
170
  @classmethod
165
- def __get_validators__(cls):
166
- unit = getattr(cls, "unit", None)
167
- if unit:
168
- yield validate_quantity_unit_factory(cls.unit)
169
- yield validate_quantity_ge_factory(f"0 {cls.unit}")
171
+ def _validate(cls, value: str) -> str:
172
+ value = validate_quantity_unit_factory(cls.unit)(cls, value)
173
+ value = validate_quantity_ge_factory(f"0 {cls.unit}")(cls, value)
174
+ return value
175
+
176
+ @classmethod
177
+ def __get_pydantic_core_schema__(
178
+ cls, source: type[Any], handler: pydantic.GetCoreSchemaHandler
179
+ ) -> pydantic_core.core_schema.CoreSchema:
180
+ return pydantic_core.core_schema.no_info_after_validator_function(
181
+ cls._validate,
182
+ pydantic_core.core_schema.str_schema(),
183
+ serialization=pydantic_core.core_schema.plain_serializer_function_ser_schema(
184
+ lambda x: x,
185
+ info_arg=False,
186
+ return_schema=pydantic_core.core_schema.str_schema(),
187
+ ),
188
+ )
170
189
 
171
190
  @classmethod
172
- def __modify_schema__(cls, field_schema):
173
- field_schema.update(
174
- example=f"1 {cls.unit}",
191
+ def __get_pydantic_json_schema__(cls, core_schema, handler):
192
+ schema = handler(core_schema)
193
+ schema.update(
194
+ examples=[f"1 {cls.unit}"],
175
195
  )
196
+ return schema
176
197
 
177
198
 
178
199
  class PressureMPaStr(QuantityStr):
@@ -205,10 +226,12 @@ class LengthMmStr(QuantityStr):
205
226
  unit = OpenEPDUnit.m
206
227
 
207
228
  @classmethod
208
- def __modify_schema__(cls, field_schema):
209
- field_schema.update(
210
- example="6 mm",
229
+ def __get_pydantic_json_schema__(cls, core_schema, handler):
230
+ schema = handler(core_schema)
231
+ schema.update(
232
+ examples=["6 mm"],
211
233
  )
234
+ return schema
212
235
 
213
236
 
214
237
  class LengthInchStr(QuantityStr):
@@ -217,10 +240,12 @@ class LengthInchStr(QuantityStr):
217
240
  unit = "inch"
218
241
 
219
242
  @classmethod
220
- def __modify_schema__(cls, field_schema):
221
- field_schema.update(
222
- example="2.5 inch",
243
+ def __get_pydantic_json_schema__(cls, core_schema, handler):
244
+ schema = handler(core_schema)
245
+ schema.update(
246
+ examples=["2.5 inch"],
223
247
  )
248
+ return schema
224
249
 
225
250
 
226
251
  class TemperatureCStr(QuantityStr):
@@ -353,35 +378,43 @@ class WithDimensionalityMixin(BaseOpenEpdSchema):
353
378
  """Class for dimensionality-validated amounts."""
354
379
 
355
380
  dimensionality_unit: ClassVar[str | None] = None
381
+ unit: str | None
356
382
 
357
383
  # Unit for dimensionality to validate against, for example "kg"
358
384
 
359
- @pyd.root_validator
360
- def check_dimensionality_matches(cls, values: dict[str, Any]) -> dict[str, Any]:
385
+ @pydantic.model_validator(mode="after")
386
+ def check_dimensionality_matches(self) -> Self:
361
387
  """Check that this amount conforms to the same dimensionality as dimensionality_unit."""
362
- if not cls.dimensionality_unit:
363
- return values
388
+ if not self.dimensionality_unit:
389
+ return self
390
+
391
+ if self.unit is None:
392
+ raise ValueError("`unit` is required for dimensionality-validated amounts")
364
393
 
365
- validate_unit_factory(cls.dimensionality_unit)(BaseOpenEpdSchema, values.get("unit")) # type:ignore [arg-type]
366
- return values
394
+ validate_unit_factory(self.dimensionality_unit)(BaseOpenEpdSchema, self.unit)
395
+ return self
367
396
 
368
397
 
369
398
  class AmountRangeWithDimensionality(RangeAmount, WithDimensionalityMixin):
370
399
  """Mass amount, range."""
371
400
 
372
- class Config:
373
- """Pydantic config."""
374
-
375
- @staticmethod
376
- def schema_extra(schema: dict[str, Any], model: type["AmountRangeWithDimensionality"]) -> None:
377
- """Modify json schema."""
378
- schema["example"] = {"min": 1.2, "max": 3.4, "unit": str(model.dimensionality_unit) or None}
401
+ model_config = ConfigDict(
402
+ json_schema_extra=lambda schema, model: schema.update(
403
+ {
404
+ "example": {
405
+ "min": 1.2,
406
+ "max": 3.4,
407
+ "unit": str(model.dimensionality_unit) or None,
408
+ }
409
+ }
410
+ )
411
+ )
379
412
 
380
413
 
381
414
  class WithMassKgMixin(WithDimensionalityMixin):
382
415
  """Unit validation mixin."""
383
416
 
384
- dimensionality_unit = MassKgStr.unit
417
+ dimensionality_unit: ClassVar[str | None] = MassKgStr.unit
385
418
 
386
419
 
387
420
  class AmountMass(Amount, WithMassKgMixin):
@@ -399,7 +432,7 @@ class AmountRangeMass(AmountRangeWithDimensionality, WithMassKgMixin):
399
432
  class WithGwpMixin(WithDimensionalityMixin):
400
433
  """Unit validation mixin."""
401
434
 
402
- dimensionality_unit = GwpKgCo2eStr.unit
435
+ dimensionality_unit: ClassVar[str | None] = GwpKgCo2eStr.unit
403
436
 
404
437
 
405
438
  class AmountGWP(Amount, WithGwpMixin):
@@ -435,7 +468,7 @@ class AmountLengthM(Amount, WithLengthMMixin):
435
468
  class WithLengthMmMixin(WithDimensionalityMixin):
436
469
  """Unit validation mixin."""
437
470
 
438
- dimensionality_unit = LengthMmStr.unit
471
+ dimensionality_unit: ClassVar[str | None] = LengthMmStr.unit
439
472
 
440
473
 
441
474
  class AmountLengthMm(Amount, WithLengthMMixin):
@@ -453,7 +486,7 @@ class AmountRangeLengthMm(AmountRangeWithDimensionality, WithLengthMmMixin):
453
486
  class WithPressureMpaMixin(WithDimensionalityMixin):
454
487
  """Unit validation mixin."""
455
488
 
456
- dimensionality_unit = PressureMPaStr.unit
489
+ dimensionality_unit: ClassVar[str | None] = PressureMPaStr.unit
457
490
 
458
491
 
459
492
  class AmountPressureMpa(Amount, WithPressureMpaMixin):
@@ -471,7 +504,7 @@ class AmountRangePressureMpa(AmountRangeWithDimensionality, WithPressureMpaMixin
471
504
  class WithAreaM2Mixin(WithDimensionalityMixin):
472
505
  """Unit validation mixin."""
473
506
 
474
- dimensionality_unit = AreaM2Str.unit
507
+ dimensionality_unit: ClassVar[str | None] = AreaM2Str.unit
475
508
 
476
509
 
477
510
  class AmountAreaM2(Amount, WithAreaM2Mixin):
@@ -489,7 +522,7 @@ class AmountRangeAreaM2(AmountRangeWithDimensionality, WithAreaM2Mixin):
489
522
  class WithLengthInchStr(WithDimensionalityMixin):
490
523
  """Unit validation mixin."""
491
524
 
492
- dimensionality_unit = LengthInchStr.unit
525
+ dimensionality_unit: ClassVar[str | None] = LengthInchStr.unit
493
526
 
494
527
 
495
528
  class AmountLengthInch(Amount, WithLengthInchStr):
@@ -507,7 +540,7 @@ class AmountRangeLengthInch(AmountRangeWithDimensionality, WithLengthInchStr):
507
540
  class WithTemperatureCMixin(WithDimensionalityMixin):
508
541
  """Unit validation mixin."""
509
542
 
510
- dimensionality_unit = TemperatureCStr.unit
543
+ dimensionality_unit: ClassVar[str | None] = TemperatureCStr.unit
511
544
 
512
545
 
513
546
  class AmountTemperatureC(Amount, WithTemperatureCMixin):
@@ -525,7 +558,7 @@ class AmountRangeTemperatureC(AmountRangeWithDimensionality, WithTemperatureCMix
525
558
  class WithCapacityPerHourMixin(WithDimensionalityMixin):
526
559
  """Unit validation mixin."""
527
560
 
528
- dimensionality_unit = CapacityPerHourStr.unit
561
+ dimensionality_unit: ClassVar[str | None] = CapacityPerHourStr.unit
529
562
 
530
563
 
531
564
  class AmountCapacityPerHour(Amount, WithCapacityPerHourMixin):
@@ -543,7 +576,7 @@ class AmountRangeCapacityPerHour(AmountRangeWithDimensionality, WithCapacityPerH
543
576
  class WithRValueMixin(WithDimensionalityMixin):
544
577
  """Unit validation mixin."""
545
578
 
546
- dimensionality_unit = RValueStr.unit
579
+ dimensionality_unit: ClassVar[str | None] = RValueStr.unit
547
580
 
548
581
 
549
582
  class AmountRValue(Amount, WithRValueMixin):
@@ -561,7 +594,7 @@ class AmountRangeRValue(AmountRangeWithDimensionality, WithRValueMixin):
561
594
  class WithSpeedMixin(WithDimensionalityMixin):
562
595
  """Unit validation mixin."""
563
596
 
564
- dimensionality_unit = SpeedStr.unit
597
+ dimensionality_unit: ClassVar[str | None] = SpeedStr.unit
565
598
 
566
599
 
567
600
  class AmountSpeed(Amount, WithSpeedMixin):
@@ -579,7 +612,7 @@ class AmountRangeSpeed(AmountRangeWithDimensionality, WithSpeedMixin):
579
612
  class WithColorTemperatureMixin(WithDimensionalityMixin):
580
613
  """Unit validation mixin."""
581
614
 
582
- dimensionality_unit = ColorTemperatureStr.unit
615
+ dimensionality_unit: ClassVar[str | None] = ColorTemperatureStr.unit
583
616
 
584
617
 
585
618
  class AmountColorTemperature(Amount, WithColorTemperatureMixin):
@@ -597,7 +630,7 @@ class AmountRangeColorTemperature(AmountRangeWithDimensionality, WithColorTemper
597
630
  class WithLuminosityMixin(WithDimensionalityMixin):
598
631
  """Unit validation mixin."""
599
632
 
600
- dimensionality_unit = LuminosityStr.unit
633
+ dimensionality_unit: ClassVar[str | None] = LuminosityStr.unit
601
634
 
602
635
 
603
636
  class AmountLuminosity(Amount, WithLuminosityMixin):
@@ -615,7 +648,7 @@ class AmountRangeLuminosity(AmountRangeWithDimensionality, WithLuminosityMixin):
615
648
  class WithPowerMixin(WithDimensionalityMixin):
616
649
  """Unit validation mixin."""
617
650
 
618
- dimensionality_unit = PowerStr.unit
651
+ dimensionality_unit: ClassVar[str | None] = PowerStr.unit
619
652
 
620
653
 
621
654
  class AmountPower(Amount, WithPowerMixin):
@@ -633,7 +666,7 @@ class AmountRangePower(AmountRangeWithDimensionality, WithPowerMixin):
633
666
  class WithElectricalCurrentMixin(WithDimensionalityMixin):
634
667
  """Unit validation mixin."""
635
668
 
636
- dimensionality_unit = ElectricalCurrentStr.unit
669
+ dimensionality_unit: ClassVar[str | None] = ElectricalCurrentStr.unit
637
670
 
638
671
 
639
672
  class AmountElectricalCurrent(Amount, WithElectricalCurrentMixin):
@@ -651,7 +684,7 @@ class AmountRangeElectricalCurrent(AmountRangeWithDimensionality, WithElectrical
651
684
  class WithVolumeMixin(WithDimensionalityMixin):
652
685
  """Unit validation mixin."""
653
686
 
654
- dimensionality_unit = VolumeStr.unit
687
+ dimensionality_unit: ClassVar[str | None] = VolumeStr.unit
655
688
 
656
689
 
657
690
  class AmountVolume(Amount, WithVolumeMixin):
@@ -669,7 +702,7 @@ class AmountRangeVolume(AmountRangeWithDimensionality, WithVolumeMixin):
669
702
  class WithAirflowMixin(WithDimensionalityMixin):
670
703
  """Unit validation mixin."""
671
704
 
672
- dimensionality_unit = AirflowStr.unit
705
+ dimensionality_unit: ClassVar[str | None] = AirflowStr.unit
673
706
 
674
707
 
675
708
  class AmountAirflow(Amount, WithAirflowMixin):
@@ -687,7 +720,7 @@ class AmountRangeAirflow(AmountRangeWithDimensionality, WithAirflowMixin):
687
720
  class WithFlowRateMixin(WithDimensionalityMixin):
688
721
  """Unit validation mixin."""
689
722
 
690
- dimensionality_unit = FlowRateStr.unit
723
+ dimensionality_unit: ClassVar[str | None] = FlowRateStr.unit
691
724
 
692
725
 
693
726
  class AmountFlowRate(Amount, WithFlowRateMixin):
@@ -705,7 +738,7 @@ class AmountRangeFlowRate(AmountRangeWithDimensionality, WithFlowRateMixin):
705
738
  class WithMassPerLengthMixin(WithDimensionalityMixin):
706
739
  """Unit validation mixin."""
707
740
 
708
- dimensionality_unit = MassPerLengthStr.unit
741
+ dimensionality_unit: ClassVar[str | None] = MassPerLengthStr.unit
709
742
 
710
743
 
711
744
  class AmountMassPerLength(Amount, WithFlowRateMixin):
@@ -723,7 +756,7 @@ class AmountRangeMassPerLength(AmountRangeWithDimensionality, WithFlowRateMixin)
723
756
  class WithAreaPerVolumeMixin(WithDimensionalityMixin):
724
757
  """Unit validation mixin."""
725
758
 
726
- dimensionality_unit = AreaPerVolumeStr.unit
759
+ dimensionality_unit: ClassVar[str | None] = AreaPerVolumeStr.unit
727
760
 
728
761
 
729
762
  class AmountAreaPerVolume(Amount, WithFlowRateMixin):
@@ -741,7 +774,7 @@ class AmountRangeAreaPerVolume(AmountRangeWithDimensionality, WithFlowRateMixin)
741
774
  class WithThermalConductivity(WithDimensionalityMixin):
742
775
  """Unit validation mixin."""
743
776
 
744
- dimensionality_unit = ThermalConductivityStr.unit
777
+ dimensionality_unit: ClassVar[str | None] = ThermalConductivityStr.unit
745
778
 
746
779
 
747
780
  class AmountThermalConductivityMixin(Amount, WithThermalConductivity):
@@ -763,7 +796,7 @@ class WithForce(WithDimensionalityMixin):
763
796
  May the Force be with you.
764
797
  """
765
798
 
766
- dimensionality_unit = ForceNStr.unit
799
+ dimensionality_unit: ClassVar[str | None] = ForceNStr.unit
767
800
 
768
801
 
769
802
  class AmountForce(Amount, WithForce):
@@ -781,7 +814,7 @@ class AmountRangeForce(AmountRangeWithDimensionality, WithForce):
781
814
  class WithYarnWeight(WithDimensionalityMixin):
782
815
  """Unit validation mixin."""
783
816
 
784
- dimensionality_unit = YarnWeightStr.unit
817
+ dimensionality_unit: ClassVar[str | None] = YarnWeightStr.unit
785
818
 
786
819
 
787
820
  class AmountYarnWeight(Amount, WithYarnWeight):
@@ -799,7 +832,7 @@ class AmountRangeYarnWeight(AmountRangeWithDimensionality, WithYarnWeight):
799
832
  class WithThermalExpansion(WithDimensionalityMixin):
800
833
  """Unit validation mixin."""
801
834
 
802
- dimensionality_unit = ThermalExpansionStr.unit
835
+ dimensionality_unit: ClassVar[str | None] = ThermalExpansionStr.unit
803
836
 
804
837
 
805
838
  class AmountThermalExpansion(Amount, WithThermalExpansion):
@@ -817,7 +850,7 @@ class AmountRangeThermalExpansion(AmountRangeWithDimensionality, WithThermalExpa
817
850
  class WithUtilization(WithDimensionalityMixin):
818
851
  """Unit validation mixin."""
819
852
 
820
- dimensionality_unit = UtilizationStr.unit
853
+ dimensionality_unit: ClassVar[str | None] = UtilizationStr.unit
821
854
 
822
855
 
823
856
  class AmountUtilization(Amount, WithUtilization):
@@ -835,7 +868,7 @@ class AmountRangeUtilization(AmountRangeWithDimensionality, WithUtilization):
835
868
  class WithUFactor(WithDimensionalityMixin):
836
869
  """Unit validation mixin."""
837
870
 
838
- dimensionality_unit = UFactorStr.unit
871
+ dimensionality_unit: ClassVar[str | None] = UFactorStr.unit
839
872
 
840
873
 
841
874
  class AmountUFactor(Amount, WithUFactor):
@@ -853,7 +886,7 @@ class AmountRangeUFactor(AmountRangeWithDimensionality, WithUFactor):
853
886
  class WithRFactor(WithDimensionalityMixin):
854
887
  """Unit validation mixin."""
855
888
 
856
- dimensionality_unit = RFactorStr.unit
889
+ dimensionality_unit: ClassVar[str | None] = RFactorStr.unit
857
890
 
858
891
 
859
892
  class AmountRFactor(Amount, WithRFactor):
@@ -17,10 +17,10 @@ from abc import ABC
17
17
  from enum import ReprEnum
18
18
  from typing import ClassVar, NamedTuple
19
19
 
20
- from openepd.compat.pydantic import pyd
20
+ import pydantic
21
21
 
22
22
 
23
- class WithExtVersionMixin(ABC, pyd.BaseModel):
23
+ class WithExtVersionMixin(ABC, pydantic.BaseModel):
24
24
  """Mixin for extensions supporting versions: recommended way."""
25
25
 
26
26
  _EXT_VERSION: ClassVar[str]
@@ -30,10 +30,10 @@ class WithExtVersionMixin(ABC, pyd.BaseModel):
30
30
  """Set the default value for the ext_version field from _EXT_VERSION class var."""
31
31
  super().__init_subclass__()
32
32
  if hasattr(cls, "_EXT_VERSION"):
33
- cls.__fields__["ext_version"].default = cls._EXT_VERSION
33
+ cls.model_fields["ext_version"].default = cls._EXT_VERSION
34
34
 
35
35
  # Note: default is set programmatically in __init_subclass__
36
- ext_version: str | None = pyd.Field(description="Extension version", example="3.22", default=None)
36
+ ext_version: str | None = pydantic.Field(description="Extension version", examples=["3.22"], default=None)
37
37
 
38
38
 
39
39
  class Version(NamedTuple):
@@ -43,7 +43,7 @@ class Version(NamedTuple):
43
43
  minor: int
44
44
 
45
45
  @staticmethod
46
- def parse_version(version: str) -> "Version":
46
+ def parse_version(version: str | None) -> "Version":
47
47
  """Parse the version of extension or the format.
48
48
 
49
49
  Version is expected to be major.minor
@@ -51,7 +51,10 @@ class Version(NamedTuple):
51
51
  :param version: The extension version.
52
52
  :return: A tuple of major and minor version numbers.
53
53
  """
54
- splits = version.split(".", 1) if isinstance(version, str) else None
54
+ if isinstance(version, str):
55
+ splits = version.split(".", 1)
56
+ else:
57
+ splits = []
55
58
  if len(splits) != 2:
56
59
  raise ValueError(f"Invalid version: {version}")
57
60
  if not splits[0].isdigit() or not splits[1].isdigit():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openepd
3
- Version: 6.13.2
3
+ Version: 7.0.1
4
4
  Summary: Python library to work with OpenEPD format
5
5
  Home-page: https://github.com/cchangelabs/openepd
6
6
  License: Apache-2.0
@@ -21,7 +21,7 @@ Requires-Dist: email-validator (>=1.3.1)
21
21
  Requires-Dist: idna (>=3.7)
22
22
  Requires-Dist: open-xpd-uuid (>=0.2.1,<0.3.0)
23
23
  Requires-Dist: openlocationcode (>=1.0.1)
24
- Requires-Dist: pydantic (>=1.10,<3.0)
24
+ Requires-Dist: pydantic (>=2.0,<3)
25
25
  Requires-Dist: requests (>=2.0) ; extra == "api-client"
26
26
  Project-URL: Repository, https://github.com/cchangelabs/openepd
27
27
  Description-Content-Type: text/markdown
@@ -0,0 +1,141 @@
1
+ openepd/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
2
+ openepd/__version__.py,sha256=cQ-OwE-r-8WgC7M8aP58dwhTkUGGnep-uii5xipUfHI,638
3
+ openepd/api/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
4
+ openepd/api/average_dataset/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
5
+ openepd/api/average_dataset/generic_estimate_sync_api.py,sha256=SRIs-qmb_wO7ELumeP1DLXJbVUtdBJ4CToecoCIsPAQ,8015
6
+ openepd/api/average_dataset/industry_epd_sync_api.py,sha256=b3oBjt-HIZuuHd6qDTJgHAIBHV73FCIZSc8cLq-htXE,6338
7
+ openepd/api/base_sync_client.py,sha256=lVOn8d_EM6-Vwn99poRt1IEyLmDwatXDOH1D68F0LQ8,21739
8
+ openepd/api/category/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
9
+ openepd/api/category/dto.py,sha256=-nsSNH1zWIluFuF50qmnIcvloX08Jk_KV5mebJqzLe4,850
10
+ openepd/api/category/sync_api.py,sha256=XU68fMQXSsfwfKkZvAlvBS78Z5hNwpXbO_Ffsh7LP0U,1381
11
+ openepd/api/common.py,sha256=bLSER3RQQFR4lyEuxQPKNjTaa3S0K8fFi8x4QRAPM_g,8812
12
+ openepd/api/dto/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
13
+ openepd/api/dto/base.py,sha256=hZbzzBDPEN5-5Hhfcy7FgZj_Ya3g9oS7CgaQYhQiRwU,1041
14
+ openepd/api/dto/common.py,sha256=qwZaquepK1vQrOHVSzP5hMVy8klwrfqmpTSfrJ-YBs0,4489
15
+ openepd/api/dto/meta.py,sha256=0x_rAx4ijO4l0C9C3jSu4sfX7lNctqCAUd51WUkoY3s,2276
16
+ openepd/api/dto/mf.py,sha256=3pobE0iihSBqH0rZgWP95_IlQzSJBqKZrYYufWDobUo,2000
17
+ openepd/api/dto/params.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
18
+ openepd/api/epd/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
19
+ openepd/api/epd/dto.py,sha256=rcRUKUj-N885K6tjQnPGiFVDhc8yd9nUJKnkhIwgOtM,5084
20
+ openepd/api/epd/sync_api.py,sha256=QN62LQH3sHLvCqCVo2MGgN9ZvoTxIsdleEypyW3m-zA,7365
21
+ openepd/api/errors.py,sha256=BgZeNfMNAKVPfhpuiVapCXNBSsXygAOWql-gy7m9j7E,2868
22
+ openepd/api/pcr/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
23
+ openepd/api/pcr/sync_api.py,sha256=bWa6PyU0xT1sZzG4nAHUo83gjo3YcP5QUxVXOMFNQH0,1567
24
+ openepd/api/sync_client.py,sha256=reD_OXsaVOvUvnC-cyp5aq8sKSOH2Z8xmImxV2ClQIM,3105
25
+ openepd/api/test/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
26
+ openepd/api/utils.py,sha256=xOU8ihC0eghsoaCFhC85PU4WYRwNxVEpfK3gzq4e9ik,2092
27
+ openepd/bundle/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
28
+ openepd/bundle/base.py,sha256=Ou2zlAV7VRKp7Lxu8h4k56OLEMwn5F1nrEEF_ies_lE,6869
29
+ openepd/bundle/model.py,sha256=bO6GAN_hMmpnYn9LQAHl6bw9cqwphlZZtMCkQZHzP8c,2627
30
+ openepd/bundle/reader.py,sha256=_kKOCcCtHF-DuezifsArvyUzDMAK2vs4pJB6cNttTeA,6801
31
+ openepd/bundle/writer.py,sha256=ZWQKVRfd0wrys1R4rOabK8KFvwNhUpeBdK9KGS-yt5Q,8283
32
+ openepd/m49/__init__.py,sha256=vkXC6i8OeCl5K88JUIRN_NKfsAIpNIaN-fyPmmd-Lfk,689
33
+ openepd/m49/const.py,sha256=buspTHOOWhkBXWUIS0oqvQ0y1L7y70Y_PXilkiBIKD4,31819
34
+ openepd/m49/utils.py,sha256=Qm8HvxAZlQncsyUYDO0lG0feMFFnT4HQPNSMp78W4zU,7111
35
+ openepd/model/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
36
+ openepd/model/base.py,sha256=zSV_tgZZsd2x0jgmwfrrncGDTr0QINTDkPJDubk-W7Q,10811
37
+ openepd/model/category.py,sha256=iyzzAsiVwW4zJ61oYsm9Sy-sEBA71-aMFXcJP1Y-dPI,1734
38
+ openepd/model/common.py,sha256=TxcLcYDgAgHtS-go8xYzPYnWTHLuE8bUebiVrXMXf5M,14544
39
+ openepd/model/declaration.py,sha256=1NT3NhaYI_5u1K9ErfphOSFMY6r1-97qpBYNxuCmbs0,14687
40
+ openepd/model/epd.py,sha256=KACR_2tbbk0eltaL37MvDxqdJUDWXtiqYGW0_bWl7v4,12730
41
+ openepd/model/factory.py,sha256=doexyqZXJVGd45T1JsbjuyGUjEykW-MerKUq4SQHhRY,2656
42
+ openepd/model/generic_estimate.py,sha256=RGNrGNwaqY42m6nRrwmDZYO_Gy2EhOBZn6g0EAWiDHs,4224
43
+ openepd/model/geography.py,sha256=Jx7NIDdk_sIvwyh-7YxnIjAwIHW2HCQK7UtFGM2xKtw,42095
44
+ openepd/model/industry_epd.py,sha256=Cqn01IUNSZqRkyU05TwtOLXDKlg0YnGzqvKL8A__zbI,4061
45
+ openepd/model/lcia.py,sha256=wilehrZfb5d_kqOuaVVk_TuFRDLr2jagScAXsXArZsI,27186
46
+ openepd/model/org.py,sha256=1ALm91OyJrvyFjkJ1hWQWGKO5fDdYQE8lMWEVZRUPrs,6348
47
+ openepd/model/pcr.py,sha256=W_GjmMwFxZGLnbbU7khoYziSvOxxd6Id4xBdhitq_SE,5655
48
+ openepd/model/specs/README.md,sha256=UGhSiFJ9hOxT1mZl-5ZrhkOrPKf1W_gcu5CI9hzV7LU,2430
49
+ openepd/model/specs/__init__.py,sha256=YcAvn0h_Bhz_Cb4-uEl8DiBI82nXogQsocB-c2zvr_A,3094
50
+ openepd/model/specs/asphalt.py,sha256=6jAZEBkB4hpwcSDvwVUGiNXgg3W3NElgdhS9caVpocI,3545
51
+ openepd/model/specs/base.py,sha256=X_1TiMmTSSoOtZlbRl0jqzo1agX_QivQL4gToGNQeRY,2757
52
+ openepd/model/specs/concrete.py,sha256=gjly5f7QEuaKnYZStMm0CisU0Us1PUa2HmxPyhhmuO0,5573
53
+ openepd/model/specs/enums.py,sha256=_WMe0l8ZKPIGQG53A1rB_Sv_p2izr8Zemg9AEEYOU2g,63638
54
+ openepd/model/specs/range/__init__.py,sha256=ZXgsyzn_c6H2SPCo5hTVZOjRqlCf0HvVVMDQ4RGaPSU,4502
55
+ openepd/model/specs/range/accessories.py,sha256=wnOv1V_uatA6g_9QVfZaSp-rNLbyZ_KS-t3wlHaeEsI,2498
56
+ openepd/model/specs/range/aggregates.py,sha256=wnGI6AxtQaaYgCGvqYUuM94JVOBipCBRvFLTwpflsyA,2555
57
+ openepd/model/specs/range/aluminium.py,sha256=U58Sg6TJi0CfqOtoiNT4M8uwx9H2jlTPxmMWCt-JKHc,2741
58
+ openepd/model/specs/range/asphalt.py,sha256=qd7oGvsIztz2WRMlCfTVqQfRUYBDA-1qzQTiF7tD2O8,3002
59
+ openepd/model/specs/range/bulk_materials.py,sha256=SuKhmJXMa9jl0CrkYr3QVvPX_GDbr7KATzrSS-fJEU4,1051
60
+ openepd/model/specs/range/cast_decks_and_underlayment.py,sha256=37fx7jDRy6xryZTVweW_vu78h0kRs5vQurGS-Ypayog,1132
61
+ openepd/model/specs/range/cladding.py,sha256=-cBYQrABiTbByl-ZioHKBmTL2h-SjukeSJdNTLY7FgQ,7277
62
+ openepd/model/specs/range/cmu.py,sha256=Syfk4gJzWNzBQcKsPKgVcQQutR2syruM1ZJUJ1FdCdU,1879
63
+ openepd/model/specs/range/concrete.py,sha256=BIeM1ozlfjLqohMTfdFPxmk6cIKg19MwYXyVhoHL1i8,7064
64
+ openepd/model/specs/range/conveying_equipment.py,sha256=AvSg6PqK-GcFt-aUCTsaBhjPyEjGfVPu61QiHscQt1M,3216
65
+ openepd/model/specs/range/electrical.py,sha256=jebPfOwDCzUS5ppCXbZBcgQLtMNYl__f5P0hGOfiE10,11945
66
+ openepd/model/specs/range/electrical_transmission_and_distribution_equipment.py,sha256=rbdmHvz9nRMgcWrCGVnN0xXSl5ZezuwArOZ_4xCQIgM,2525
67
+ openepd/model/specs/range/electricity.py,sha256=yn_S25C_tZqseb8hiJ1yiHszu2mQ49FOFWWCqNpOBY0,997
68
+ openepd/model/specs/range/finishes.py,sha256=gJnMvjhivQC0jnKizKcrwn1Y7UJjrK_emixigQhbbfE,21792
69
+ openepd/model/specs/range/fire_and_smoke_protection.py,sha256=KLH5t3d-a2cppF5i-uW4233z1vAPbJIY1zTn89_gV4k,3333
70
+ openepd/model/specs/range/furnishings.py,sha256=SPZDMacVvXHA_zcE4l3fL5hroZWaEeSsql0oSn3BnBo,6576
71
+ openepd/model/specs/range/grouting.py,sha256=BQPxH6BvlXpdhLEZBui9zTuY93K_9syjoa6rdnF8GGY,1095
72
+ openepd/model/specs/range/manufacturing_inputs.py,sha256=iqK4QS-T5vyjMQtl5v63Feb99qSNwKS0kM-1izoJTzA,5615
73
+ openepd/model/specs/range/masonry.py,sha256=egeqDr0K3eTFDHeIzFHrg9_u9d6XIHOSmBPnBERkvxY,2908
74
+ openepd/model/specs/range/material_handling.py,sha256=9jxRHpjMKu71B5omH55UjkNVJvaTLgTMtEidSKPFn5c,1483
75
+ openepd/model/specs/range/mechanical.py,sha256=4_onG6dMjYDvpFe7NmF_gPFwI0N52CAZty4YwDUqx4E,10463
76
+ openepd/model/specs/range/mechanical_insulation.py,sha256=eBvNMuW-zZyphay9aKOphwfAv2Uo3AiBR1UG9sOwBnk,1733
77
+ openepd/model/specs/range/network_infrastructure.py,sha256=WPudKji72n46SXDGCEV9PMWD-zheZd7rvBJv3cZ0L3E,8738
78
+ openepd/model/specs/range/openings.py,sha256=icQFUQLwhoWc5GFrnxUJuQ6pxUzSxTWMdQHyQ342TUM,15587
79
+ openepd/model/specs/range/other_electrical_equipment.py,sha256=H4tZHcHyR2uUYHn-bQfLC6hR4tynVp_7EJbiI-YpK7Y,1001
80
+ openepd/model/specs/range/other_materials.py,sha256=k7Gv6YvWy43B-QFBabBt-TkvkC450Pz2a2pz9t6r4OU,4495
81
+ openepd/model/specs/range/plumbing.py,sha256=GS-q4nMOaE1aoPwHmDXEjlG7xuZOl0veovZraSSQcc4,5382
82
+ openepd/model/specs/range/precast_concrete.py,sha256=9bNluxpGuQ_7HqA5rpvg9FJHeMyrGSIH-c1M9Mzz2qQ,3820
83
+ openepd/model/specs/range/sheathing.py,sha256=FOosFJ8fsyqQnlLTgEqxM4xzDtiYP2jQ7dCf2T4K1O4,3446
84
+ openepd/model/specs/range/steel.py,sha256=T4vk8g9X2PUbkm8pfjAvcZ7Y0iN7ErpNZapp89l0lIg,10547
85
+ openepd/model/specs/range/thermal_moisture_protection.py,sha256=BOZZTNA9mHTaImN4J484LYnYTvv3joBX5OkH6LGBklc,9470
86
+ openepd/model/specs/range/utility_piping.py,sha256=doRcQRfBWvHX7FDDYk-bEU5rVCS_vjZ_5gKslI0xR7Y,2671
87
+ openepd/model/specs/range/wood.py,sha256=0Prq5n3n_-DEFe4-fBKDj9zCu2NdBD7ysCun7DRhT_o,6942
88
+ openepd/model/specs/range/wood_joists.py,sha256=PVGJZPdaI685rUI6TS3MZrAFkeMckFGpCYTNJLBr6IM,1786
89
+ openepd/model/specs/singular/__init__.py,sha256=xN6exBUHRoaM-30YfLPfB4UrLLcQo55MOfK70Dg5KIQ,6945
90
+ openepd/model/specs/singular/accessories.py,sha256=xcuSJrG84oTm_w76_wlv_sItfK36gSyDmUD2TnpZnVE,2013
91
+ openepd/model/specs/singular/aggregates.py,sha256=n_AbZK6TJHJ6boyMz6AyikUkMiNlq8G_NOcqEy_A-Sg,2975
92
+ openepd/model/specs/singular/aluminium.py,sha256=n25EvcrwYNkz4OvZbu4FH008owSkC8B8j7qEHGefTD0,2519
93
+ openepd/model/specs/singular/asphalt.py,sha256=pVOBCaceMKR6eKztVZ-fRk1bgoY0X8QfBr_KCkgvZyM,3488
94
+ openepd/model/specs/singular/bulk_materials.py,sha256=LKTmh432ak51L0GsVf-40389Lwx-sxZm_jSfzWNfagE,875
95
+ openepd/model/specs/singular/cast_decks_and_underlayment.py,sha256=HjIEKekxCAKx51XEvH1tthUP6gNTbntDoi8gSu8LjZk,955
96
+ openepd/model/specs/singular/cladding.py,sha256=KuKNcmkZSKTMVMsNIHQIZ3qkj21_vj_6I7cIladPmo4,6857
97
+ openepd/model/specs/singular/cmu.py,sha256=J5BqQZyoZA6tGVBxg77jaeFOXLNvLwDmA0qAe8wHgJs,2100
98
+ openepd/model/specs/singular/common.py,sha256=1WSoihRTeOkdcOPSmcauzyHNyAVspiacAU5lQX9vahk,1030
99
+ openepd/model/specs/singular/concrete.py,sha256=w7_fvJri1bY1f1sEe6kuxvbjg2iiwDPTh-6Kx5CzHCY,8257
100
+ openepd/model/specs/singular/conveying_equipment.py,sha256=Hcy1zcXKsGIuh303xiRJwDmnEOqyGzhsZoVEz3DpdHY,3203
101
+ openepd/model/specs/singular/deprecated/__init__.py,sha256=OmC79bG2zbDcaPZAjSx5T506h2D7QJXMJOkXSSf8LVo,2617
102
+ openepd/model/specs/singular/deprecated/concrete.py,sha256=xqHxwFUzy0XEa66e1N1Z3aKt6hhnHhbJ76XiRoe0wtQ,5604
103
+ openepd/model/specs/singular/deprecated/steel.py,sha256=xqp6rqA49ARY7uvObvnNh-y9cN0WCy0Qz3sMuuIBXPY,3647
104
+ openepd/model/specs/singular/electrical.py,sha256=lLp8MjAULlnfINi7AayexTGDorSEH_r9OONFcxVHcs4,11598
105
+ openepd/model/specs/singular/electrical_transmission_and_distribution_equipment.py,sha256=oZYyHgnXn9RH3YzltUEDiiQKrin2mvMlTgC3OhxV7DY,1978
106
+ openepd/model/specs/singular/electricity.py,sha256=f1cJ9eklNUf97khCIZiT5-z8V_TbOcvH2me_1UTQVrE,823
107
+ openepd/model/specs/singular/finishes.py,sha256=8BtFK2_olB8OJQFv8rxf7afoLhqlJI1o2tEKopidOGA,24398
108
+ openepd/model/specs/singular/fire_and_smoke_protection.py,sha256=h8Dy4ps_xfa5g8EQEIN8OHxjH6aDvqmZUFRdEzYy7aY,3081
109
+ openepd/model/specs/singular/furnishings.py,sha256=6MZT42b-nlZdQvvZw1_tVg5GFlMQ2gw_r6zBjxMtxHc,5608
110
+ openepd/model/specs/singular/grouting.py,sha256=pg2tX3W7a2TQ3z_eyFYGlBJY3WEwn6JlZyqM3PQIJcU,934
111
+ openepd/model/specs/singular/manufacturing_inputs.py,sha256=OBy7Lzm1TbC8kGxE3YXIXeyrqIPqf2_rXcGEN7MEMBw,5233
112
+ openepd/model/specs/singular/masonry.py,sha256=e9siblrPFFSvIjucYkwZzSlpSSZPZ9rA1bdVIDQz-RM,3627
113
+ openepd/model/specs/singular/material_handling.py,sha256=iEeUx1hNKla669y0zl-QAJn6xA7ceq75aRG8qT0p56Q,1274
114
+ openepd/model/specs/singular/mechanical.py,sha256=q-89Ch0uTlEqFRXM5QPgkmf23L-xyCzVK_mQ33pU4UA,10191
115
+ openepd/model/specs/singular/mechanical_insulation.py,sha256=OjgDkH9ft2mxsfYveuwozCT6x-WrF_XC9V9KbEYKwuQ,1616
116
+ openepd/model/specs/singular/mixins/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
117
+ openepd/model/specs/singular/mixins/conduit_mixin.py,sha256=H5rbXIy3lpiU_Rub3_f7cECtQE2odu1-nIKuRjtO6ts,1959
118
+ openepd/model/specs/singular/network_infrastructure.py,sha256=QGMIFzexHH94phkFw7iYl-fTZ_514dwYgvC-2sHjOZw,9316
119
+ openepd/model/specs/singular/openings.py,sha256=fcYBvSJW64fBArvs0ajcRXRegE07p-YmURICmLA8ilY,19544
120
+ openepd/model/specs/singular/other_electrical_equipment.py,sha256=FX7p4rMuUbTrz1yDwKkS-Z6odohoq-zCw6SU3Kw5ISs,814
121
+ openepd/model/specs/singular/other_materials.py,sha256=_00_fCPn7G_-HVKC1cQcNvBDf4CtXFLOGvYLDJtL5ZA,3498
122
+ openepd/model/specs/singular/plumbing.py,sha256=dP6r7xy2yeP8ICEBN79CfJqyDiuwpTtDnURBfWmFWPs,4639
123
+ openepd/model/specs/singular/precast_concrete.py,sha256=25vn5UxiQbhsNisqBF9_GYASMl3D1iuDWxfnV5HOV4k,7567
124
+ openepd/model/specs/singular/sheathing.py,sha256=J1lHRo0eTcWGhqwLHGnEZq3SHJkVCvSedvg2lGuwDyo,3995
125
+ openepd/model/specs/singular/steel.py,sha256=rrWAyz6w5bgV2lR6H93dLZ_ruwr8N67vATh9nIHS6eU,10809
126
+ openepd/model/specs/singular/thermal_moisture_protection.py,sha256=ZtN1yfED959eMqpdLASge06OZzCseurtPzXrmi8LSjo,8363
127
+ openepd/model/specs/singular/utility_piping.py,sha256=kHflrQpCFGW54daIWwbhb0rvWoPy1Zwa6KGD8eB5ryQ,2522
128
+ openepd/model/specs/singular/wood.py,sha256=ChvILu6Pkend3O-45Fs-FrK0n5yWlu5BFZVYrCv5_TQ,6810
129
+ openepd/model/specs/singular/wood_joists.py,sha256=WhS8_Og8e4cCEd43v00njGNvjLdfCwAabO7XOogC5o4,1829
130
+ openepd/model/standard.py,sha256=5y57ZakJ9nbvz1Hxx8Uo6jISNMGg9kg2kBeBZrjBB5g,1744
131
+ openepd/model/validation/__init__.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
132
+ openepd/model/validation/common.py,sha256=ZlpByfGzCHZuGfj9p0S_uG8NoGy9ezJVZmwAITp7gR8,2450
133
+ openepd/model/validation/enum.py,sha256=ttODVtMEQaBemMFywGUNlXU4bAM25FiBlVDKZbOv2iY,1793
134
+ openepd/model/validation/numbers.py,sha256=9THJcV3LT7JDBOMz1px-QFf_sdJ0LOqJ5dmA9Dvvtd4,620
135
+ openepd/model/validation/quantity.py,sha256=zsyNGygYW4GGeWAtyM9708lFdEuebtSctr3qIfNdEXQ,21720
136
+ openepd/model/versioning.py,sha256=de53OlduidxAkDlSbAu6xrIy2IUuCnwI69vUJPCXX_8,4512
137
+ openepd/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
+ openepd-7.0.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
139
+ openepd-7.0.1.dist-info/METADATA,sha256=nqzPdeu5vJAB7DTCYDXRVx2ebuPlRn4YI9-lcpbzrdg,9035
140
+ openepd-7.0.1.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
141
+ openepd-7.0.1.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- #
2
- # Copyright 2025 by C Change Labs Inc. www.c-change-labs.com
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
@@ -1,25 +0,0 @@
1
- #
2
- # Copyright 2025 by C Change Labs Inc. www.c-change-labs.com
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- from typing import Any
17
-
18
- __all__ = ["AfterValidator"]
19
-
20
-
21
- class AfterValidator:
22
- """Placeholder stub for validator, unused in pydantic 1."""
23
-
24
- def __init__(self, *args: Any, **kwargs: Any) -> None:
25
- pass
@@ -1,30 +0,0 @@
1
- #
2
- # Copyright 2025 by C Change Labs Inc. www.c-change-labs.com
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- try:
17
- from pydantic import functional_validators # type: ignore
18
- from pydantic import v1 as pyd # type: ignore
19
- from pydantic.v1 import generics as pyd_generics # type: ignore
20
-
21
- except ImportError:
22
- import pydantic as pyd # type: ignore[no-redef]
23
- from pydantic import generics as pyd_generics # type: ignore[no-redef]
24
-
25
- from . import compat_functional_validators as functional_validators # type: ignore[no-redef]
26
-
27
-
28
- pydantic = pyd
29
-
30
- __all__ = ["pyd", "pydantic", "pyd_generics", "functional_validators"]