Skip to content

Commit 96a4428

Browse files
committed
IFRC data validators
1 parent 07f4a0c commit 96a4428

File tree

2 files changed

+134
-1
lines changed

2 files changed

+134
-1
lines changed

pystac_monty/sources/ifrc_events.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from pystac_monty.geocoding import MontyGeoCoder
1515
from pystac_monty.hazard_profiles import MontyHazardProfiles
1616
from pystac_monty.sources.common import MontyDataSource, MontyDataTransformer
17+
from pystac_monty.validators.ifrc import IFRCsourceValidator
1718

1819
STAC_EVENT_ID_PREFIX = "ifrcevent-event-"
1920
STAC_IMPACT_ID_PREFIX = "ifrcevent-impact-"
@@ -23,7 +24,20 @@ class IFRCEventDataSource(MontyDataSource):
2324
def __init__(self, source_url: str, data: str):
2425
super().__init__(source_url, data)
2526
self.source_url = source_url
26-
self.data = json.loads(data)
27+
self.data = self.source_data_validator(json.loads(data))
28+
29+
def source_data_validator(self, data: list[dict]):
30+
# TODO Handle the failed_items
31+
failed_items = []
32+
success_items = []
33+
for item in data:
34+
is_valid = IFRCsourceValidator.validate_event(item)
35+
if is_valid:
36+
success_items.append(item)
37+
else:
38+
failed_items.append(item)
39+
return success_items
40+
2741

2842
def get_data(self) -> dict:
2943
"""Get the event detail data."""

pystac_monty/validators/ifrc.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
from pydantic import BaseModel, field_validator
2+
from typing import List, Optional
3+
from datetime import datetime
4+
5+
import logging
6+
logger = logging.getLogger(__name__)
7+
logging.basicConfig(level=logging.INFO)
8+
logger.setLevel(logging.INFO)
9+
10+
11+
class DisasterType(BaseModel):
12+
id: int
13+
name: str
14+
summary: str
15+
translation_module_original_language: str
16+
17+
class Country(BaseModel):
18+
iso: str
19+
iso3: str
20+
id: int
21+
record_type: int
22+
record_type_display: str
23+
region: int
24+
independent: bool
25+
is_deprecated: bool
26+
fdrs: Optional[str]
27+
average_household_size: Optional[float]
28+
society_name: str
29+
name: str
30+
translation_module_original_language: str
31+
32+
class Appeal(BaseModel):
33+
aid: str
34+
num_beneficiaries: int
35+
amount_requested: float
36+
code: str
37+
amount_funded: float
38+
status: int
39+
status_display: str
40+
start_date: datetime
41+
atype: int
42+
atype_display: str
43+
id: int
44+
translation_module_original_language: str
45+
46+
class Contact(BaseModel):
47+
ctype: str
48+
name: str
49+
title: str
50+
email: str
51+
phone: str
52+
id: int
53+
54+
class FieldReport(BaseModel):
55+
status: int
56+
contacts: List[Contact]
57+
countries: List[Country]
58+
created_at: datetime
59+
updated_at: datetime
60+
report_date: datetime
61+
id: int
62+
is_covid_report: bool
63+
num_assisted: Optional[int]
64+
num_displaced: Optional[int]
65+
gov_num_dead: Optional[int]
66+
gov_num_injured: Optional[int]
67+
other_num_displaced: Optional[int]
68+
affected_pop_centres: Optional[str]
69+
gov_affected_pop_centres: Optional[str]
70+
other_affected_pop_centres: Optional[str]
71+
description: str
72+
summary: str
73+
translation_module_original_language: str
74+
75+
class IFRCsourceValidator(BaseModel):
76+
dtype: DisasterType
77+
countries: List[Country]
78+
num_affected: Optional[int]
79+
ifrc_severity_level: int
80+
ifrc_severity_level_display: str
81+
glide: Optional[str]
82+
disaster_start_date: datetime
83+
created_at: datetime
84+
auto_generated: bool
85+
appeals: List[Appeal]
86+
is_featured: bool
87+
is_featured_region: bool
88+
field_reports: List[FieldReport]
89+
updated_at: datetime
90+
id: int
91+
slug: Optional[str]
92+
parent_event: Optional[str]
93+
tab_one_title: Optional[str]
94+
tab_two_title: Optional[str]
95+
tab_three_title: Optional[str]
96+
emergency_response_contact_email: Optional[str]
97+
active_deployments: int
98+
name: str
99+
summary: str
100+
translation_module_original_language: str
101+
102+
@field_validator("ifrc_severity_level")
103+
def validate_severity_level(cls, value):
104+
if value not in range(0, 4):
105+
raise ValueError("Invalid severity level, must be between 0 and 3")
106+
return value
107+
108+
@classmethod
109+
def validate_event(cls, data: dict) -> bool:
110+
"""Validate the overall data item"""
111+
try:
112+
_ = cls(**data) # This will trigger the validators
113+
except Exception as e:
114+
logger.error(f"Validation failed: {e}")
115+
return False
116+
# If all field validators return True, we consider it valid
117+
return True
118+
119+

0 commit comments

Comments
 (0)