@@ -124,7 +124,7 @@ class MontyImpactExposureCategory(StringEnum):
124124 HOUSEHOLDS = "households"
125125
126126
127- class MontyImpactExposureCatgoryLabel (Mapping ):
127+ class MontyImpactExposureCatgoryLabel (Mapping [ MontyImpactExposureCategory , str ] ):
128128 def __init__ (self ) -> None :
129129 self ._data = {
130130 MontyImpactExposureCategory .ALL_PEOPLE : "People (All Demographics)" ,
@@ -173,7 +173,7 @@ def __getitem__(self, key: MontyImpactExposureCategory) -> str:
173173 def __len__ (self ) -> int :
174174 return len (self ._data )
175175
176- def __iter__ (self ) -> Iterator :
176+ def __iter__ (self ) -> Iterator [ MontyImpactExposureCategory ] :
177177 return iter (self ._data )
178178
179179
@@ -208,7 +208,7 @@ class MontyImpactType(StringEnum):
208208 HIGHEST_RISK = "highest_risk"
209209
210210
211- class MontyImpactTypeLabel (Mapping ):
211+ class MontyImpactTypeLabel (Mapping [ MontyImpactType , str ] ):
212212 def __init__ (self ) -> None :
213213 self ._data = {
214214 MontyImpactType .UNSPECIFIED : "Unspecified" ,
@@ -247,7 +247,7 @@ def __getitem__(self, key: MontyImpactType) -> str:
247247 def __len__ (self ) -> int :
248248 return len (self ._data )
249249
250- def __iter__ (self ) -> Iterator :
250+ def __iter__ (self ) -> Iterator [ MontyImpactType ] :
251251 return iter (self ._data )
252252
253253
@@ -266,6 +266,7 @@ def __init__(
266266 severity_unit : str | None = None ,
267267 severity_label : str | None = None ,
268268 estimate_type : MontyEstimateType | None = None ,
269+ ** kwargs : Any ,
269270 ) -> None :
270271 self .properties = {}
271272 self .cluster = cluster
@@ -278,6 +279,10 @@ def __init__(
278279 if estimate_type :
279280 self .estimate_type = estimate_type
280281
282+ # Add any additional properties
283+ for key , value in kwargs .items ():
284+ self .properties [key ] = value
285+
281286 @property
282287 def cluster (self ) -> str :
283288 """The cluster of the hazard."""
@@ -334,7 +339,33 @@ def to_dict(self) -> dict[str, Any]:
334339 def from_dict (d : dict [str , Any ]) -> HazardDetail :
335340 cluster : str = get_required (d .get (HAZDET_CLUSTER_PROP ), "hazard_detail" , HAZDET_CLUSTER_PROP )
336341
337- return HazardDetail (cluster )
342+ # Extract standard properties
343+ severity_value = d .get (HAZDET_SEV_VALUE_PROP )
344+ severity_unit = d .get (HAZDET_SEV_UNIT_PROP )
345+ severity_label = d .get (HAZDET_SEV_LABEL_PROP )
346+ estimate_type = d .get (HAZDET_ESTIMATE_TYPE_PROP )
347+
348+ # Create the HazardDetail with standard properties
349+ hazard_detail = HazardDetail (
350+ cluster = cluster ,
351+ severity_value = severity_value ,
352+ severity_unit = severity_unit ,
353+ severity_label = severity_label ,
354+ estimate_type = estimate_type ,
355+ )
356+
357+ # Add any additional properties
358+ for key , value in d .items ():
359+ if key not in [
360+ HAZDET_CLUSTER_PROP ,
361+ HAZDET_SEV_VALUE_PROP ,
362+ HAZDET_SEV_UNIT_PROP ,
363+ HAZDET_SEV_LABEL_PROP ,
364+ HAZDET_ESTIMATE_TYPE_PROP ,
365+ ]:
366+ hazard_detail .properties [key ] = value
367+
368+ return hazard_detail
338369
339370
340371class ImpactDetail (ABC ):
@@ -351,7 +382,7 @@ def __init__(
351382 type : MontyImpactType ,
352383 value : float ,
353384 unit : str | None = None ,
354- estimate_type : MontyEstimateType = None ,
385+ estimate_type : MontyEstimateType | None = None ,
355386 ) -> None :
356387 self .properties = {}
357388 self .category = category
@@ -424,11 +455,20 @@ def to_dict(self) -> dict[str, Any]:
424455
425456 @staticmethod
426457 def from_dict (d : dict [str , Any ]) -> ImpactDetail :
427- category : str = get_required (d .get (IMPDET_CATEGORY_PROP ), "impact_detail" , IMPDET_CATEGORY_PROP )
428- type : str = get_required (d .get (IMPDET_TYPE_PROP ), "impact_detail" , IMPDET_TYPE_PROP )
458+ category_str : str = get_required (d .get (IMPDET_CATEGORY_PROP ), "impact_detail" , IMPDET_CATEGORY_PROP )
459+ type_str : str = get_required (d .get (IMPDET_TYPE_PROP ), "impact_detail" , IMPDET_TYPE_PROP )
429460 value : float = get_required (d .get (IMPDET_VALUE_PROP ), "impact_detail" , IMPDET_VALUE_PROP )
430461
431- return ImpactDetail (category , type , value )
462+ # Convert strings to enum values
463+ category = MontyImpactExposureCategory (category_str )
464+ impact_type = MontyImpactType (type_str )
465+
466+ # Get optional properties
467+ unit = d .get (IMPDET_UNIT_PROP )
468+ estimate_type_str = d .get (IMPDET_ESTIMATE_TYPE_PROP )
469+ estimate_type = MontyEstimateType (estimate_type_str ) if estimate_type_str else None
470+
471+ return ImpactDetail (category , impact_type , value , unit , estimate_type )
432472
433473
434474class MontyExtension (
@@ -486,8 +526,8 @@ def correlation_id(self, v: str) -> None:
486526 self ._set_property (ITEM_CORR_ID_PROP , v )
487527
488528 def compute_and_set_correlation_id (self , hazard_profiles : HazardProfiles = MontyHazardProfiles ()) -> None :
489- # if the object is an Item , we can generate the correlation id
490- if isinstance (self .item , pystac .Item ):
529+ # if the object is an ItemMontyExtension , we can generate the correlation id
530+ if hasattr ( self , "item" ) and isinstance (self .item , pystac .Item ):
491531 self .correlation_id = self .pairing .generate_correlation_id (self .item , hazard_profiles )
492532 else :
493533 raise ValueError ("Correlation ID can only be computed for Items" )
@@ -520,7 +560,7 @@ def hazard_codes(self, v: list[str] | None) -> None:
520560 @property
521561 def hazard_detail (self ) -> HazardDetail | None :
522562 """The details of the hazard."""
523- result = map_opt (self ._get_property (ITEM_HAZARD_DETAIL_PROP , dict ), HazardDetail )
563+ result = map_opt (HazardDetail . from_dict , self ._get_property (ITEM_HAZARD_DETAIL_PROP , dict ))
524564 return result
525565
526566 @hazard_detail .setter
@@ -530,7 +570,7 @@ def hazard_detail(self, v: HazardDetail | None) -> None:
530570 @property
531571 def impact_detail (self ) -> ImpactDetail | None :
532572 """The details of the impact."""
533- result = map_opt (self ._get_property (ITEM_IMPACT_DETAIL_PROP , dict ), ImpactDetail )
573+ result = map_opt (ImpactDetail . from_dict , self ._get_property (ITEM_IMPACT_DETAIL_PROP , dict ))
534574 return result
535575
536576 @impact_detail .setter
@@ -540,7 +580,7 @@ def impact_detail(self, v: ImpactDetail | None) -> None:
540580 @property
541581 def episode_number (self ) -> int :
542582 """The episode number."""
543- return self .properties .get (ITEM_EPISODE_NUMBER_PROP , 0 )
583+ return self .properties .get (ITEM_EPISODE_NUMBER_PROP , 0 ) or 0
544584
545585 @episode_number .setter
546586 def episode_number (self , v : int ) -> None :
@@ -576,7 +616,8 @@ def ext(cls, obj: T, add_if_missing: bool = False) -> MontyExtension[T]:
576616
577617 @staticmethod
578618 def enable_extension () -> None :
579- pystac .extensions .ext .ItemExt .monty = property (lambda self : MontyExtension .ext (self ))
619+ # Add monty property to ItemExt
620+ setattr (pystac .extensions .ext .ItemExt , "monty" , property (lambda self : MontyExtension .ext (self )))
580621
581622
582623class CollectionMontyExtension (MontyExtension [pystac .Collection ]):
0 commit comments