Skip to content

Commit a6661ac

Browse files
committed
handle edge cases in conversions
1 parent 96a72f7 commit a6661ac

File tree

3 files changed

+85
-77
lines changed

3 files changed

+85
-77
lines changed

custom_components/cityparking/coordinator.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ async def async_find_city_parking_info(
4242

4343
return cityParkingInfo.model_dump()
4444

45-
def extract_readable_info(cityParkingInfo):
45+
def extract_readable_info(cityParkingInfo: CityParkingModel):
4646
rules = cityParkingInfo.rules.model_dump() if cityParkingInfo.rules else {}
4747
streetComplete = cityParkingInfo.streetComplete.model_dump() if cityParkingInfo.streetComplete else {}
4848
locationResults = cityParkingInfo.location.model_dump().get('results', [{}])[0] if cityParkingInfo.location else {}
@@ -83,6 +83,9 @@ def days_to_string(days):
8383
return 'sat-sun'
8484

8585
# check consecutive
86+
if len(sorted_days) < 2:
87+
return ",".join(names[d] for d in sorted_days)
88+
8689
consecutive = all(
8790
sorted_days[i] == sorted_days[i - 1] + 1
8891
for i in range(1, len(sorted_days))
@@ -153,7 +156,7 @@ async def _async_update_data(self):
153156
so entities can quickly look up their data.
154157
"""
155158
data: CityParkingModel = None
156-
159+
_LOGGER.debug("Coordinator _async_update_data called, origin: %s", self._origin)
157160
resolved_origin = find_coordinates(self.hass, self._origin)
158161
origin_coordinates_json = await self._routeCalculatorClient._ensure_coords(resolved_origin)
159162
origin_coordinates = Coords.model_validate(origin_coordinates_json)
@@ -167,33 +170,38 @@ async def _async_update_data(self):
167170
# _LOGGER.debug(f"nearby_stations: {data}")
168171
except EmptyResponseError as exc:
169172
_LOGGER.error(
170-
"Error occurred while fetching data for charger(s) %s, not found, or coordinates are invalid, %s",
173+
"EmptyResponseError occurred while fetching data for %s (%s): %s",
174+
self._origin,
171175
resolved_origin, exc
172176
)
173177
raise UpdateFailed() from exc
174178
except CancelledError as exc:
175179
_LOGGER.error(
176-
"CancelledError occurred while fetching data for charger(s) %s, %s",
180+
"CancelledError occurred while fetching data for %s (%s): %s",
181+
self._origin,
177182
resolved_origin, exc
178183
)
179184
raise UpdateFailed() from exc
180185
except TimeoutError as exc:
181186
_LOGGER.error(
182-
"TimeoutError occurred while fetching data for charger(s) %s, %s",
187+
"TimeoutError occurred while fetching data for %s (%s): %s",
188+
self._origin,
183189
resolved_origin, exc
184190
)
185191
raise UpdateFailed() from exc
186192
except ClientError as exc:
187193
_LOGGER.error(
188-
"ClientError occurred while fetching data for charger(s) %s: %s",
194+
"ClientError error occurred while fetching data for %s (%s): %s",
195+
self._origin,
189196
resolved_origin,
190197
exc,
191198
exc_info=True,
192199
)
193200
raise UpdateFailed() from exc
194201
except Exception as exc:
195202
_LOGGER.error(
196-
"Unexpected error occurred while fetching data for charger(s) %s: %s",
203+
"Unexpected error occurred while fetching data for %s (%s): %s",
204+
self._origin,
197205
resolved_origin,
198206
exc,
199207
exc_info=True,
@@ -202,9 +210,9 @@ async def _async_update_data(self):
202210

203211
if data is None:
204212
_LOGGER.error(
205-
"API returned None data for charger(s) %s",
206-
resolved_origin,
207-
)
208-
raise UpdateFailed("API returned None data")
213+
"API returned None data for %s (%s)",
214+
self._origin,
215+
resolved_origin)
216+
raise UpdateFailed(f"API returned None data for {self._origin} ({resolved_origin})")
209217

210218
return data

custom_components/cityparking/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
"issue_tracker": "https://github.com/myTselection/CityParking/issues",
1313
"loggers": ["pywaze", "homeassistant.helpers.location"],
1414
"requirements": ["pywaze==1.1.1"],
15-
"version": "0.0.1"
15+
"version": "0.1.1"
1616
}

custom_components/cityparking/seetyApi/models.py

Lines changed: 65 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -21,41 +21,41 @@ class Coords(BaseModel):
2121

2222

2323
class UserModel(BaseModel):
24-
verified: bool
25-
cars: List[str]
26-
mustSendMailOnEachTransaction: bool
27-
proAccountActivated: bool
28-
subscribedToOnboardingCampaign: bool
29-
_id: str
30-
time: datetime
31-
lastSeen: datetime
32-
confidence: int
33-
lang: str
34-
__v: int
24+
verified: Optional[bool] = None
25+
cars: Optional[List[str]] = []
26+
mustSendMailOnEachTransaction: Optional[bool] = None
27+
proAccountActivated: Optional[bool] = None
28+
subscribedToOnboardingCampaign: Optional[bool] = None
29+
_id: Optional[str] = None
30+
time: Optional[datetime] = None
31+
lastSeen: Optional[datetime] = None
32+
confidence: Optional[int] = None
33+
lang: Optional[str] = None
34+
__v: Optional[int] = None
3535

3636
class RemoteConfigsLastUpdateModel(BaseModel):
3737
messages: str
3838

3939
class SeetyUser(BaseModel):
40-
user: UserModel
41-
lastMapUpdate: datetime
42-
remoteConfigsLastUpdate: RemoteConfigsLastUpdateModel
43-
access_token: str
44-
expires_in: int
45-
refresh_token: str
46-
status: str
40+
user: Optional[UserModel] = {}
41+
lastMapUpdate: Optional[datetime] = None
42+
remoteConfigsLastUpdate: Optional[RemoteConfigsLastUpdateModel] = {}
43+
access_token: Optional[str] = None
44+
expires_in: Optional[int] = None
45+
refresh_token: Optional[str] = None
46+
status: Optional[str] = None
4747

4848

4949
class Rules(BaseModel):
50-
days: List[int]
51-
prices: Dict[str, float]
52-
hours: List[str]
53-
type: str
50+
days: Optional[List[int]] = []
51+
prices: Optional[Dict[str, float]] = {}
52+
hours: Optional[List[str]] = []
53+
type: Optional[str] = None
5454
paymentPartner: Optional[str] = None
55-
advantageInApp: bool
56-
displayNotPayable: bool
57-
overrides: Dict[str, Any]
58-
forceDisplayPriceTables: bool
55+
advantageInApp: Optional[bool] = False
56+
displayNotPayable: Optional[bool] = False
57+
overrides: Optional[Dict[str, Any]] = {}
58+
forceDisplayPriceTables: Optional[bool] = False
5959

6060

6161
class Properties(BaseModel):
@@ -69,12 +69,12 @@ class Properties(BaseModel):
6969

7070

7171
class SeetyStreetRules(BaseModel):
72-
rules: Rules
72+
rules: Optional[Rules] = {}
7373
risk: Optional[int] = None
74-
overrides: Dict[str, Any]
75-
properties: Properties
76-
twoSided: bool
77-
status: str
74+
overrides: Optional[Dict[str, Any]] = {}
75+
properties: Optional[Properties] = {}
76+
twoSided: Optional[bool] = False
77+
status: Optional[str] = None
7878

7979

8080
class Location(BaseModel):
@@ -121,18 +121,18 @@ class ZoneColor(BaseModel):
121121
# Special Permits
122122
# -------------------------
123123
class SpecialPermits(BaseModel):
124-
residents: List[str] = []
125-
disabled: List[str] = []
124+
residents: Optional[List[str]] = []
125+
disabled: Optional[List[str]] = []
126126

127127

128128
# -------------------------
129129
# Summary Info
130130
# -------------------------
131131
class ZoneSummary(BaseModel):
132-
days: List[int]
133-
prices: Dict[str, float] = {}
132+
days: Optional[List[int]] = []
133+
prices: Optional[Dict[str, float]] = {}
134134
hours: Optional[List[str]] = None
135-
type: str
135+
type: Optional[str] = None
136136
paymentPartner: Optional[str] = None
137137
advantageInApp: Optional[bool] = False
138138
displayNotPayable: Optional[bool] = False
@@ -144,15 +144,15 @@ class ZoneSummary(BaseModel):
144144
# Zone Definition
145145
# -------------------------
146146
class Zone(BaseModel):
147-
weight: float
148-
summary: ZoneSummary
149-
remarks: List[str] = []
150-
specialPermits: SpecialPermits = SpecialPermits()
151-
maxStay: Union[str, int] = 0
152-
color: ZoneColor
153-
name: str
154-
table: List[ZoneTable] = []
155-
parkingPaymentProviders: List[str] = []
147+
weight: Optional[float] = None
148+
summary: Optional[ZoneSummary] = {}
149+
remarks: Optional[List[str]] = []
150+
specialPermits: Optional[SpecialPermits] = {}
151+
maxStay: Optional[Union[str, int]] = None
152+
color: Optional[ZoneColor] = {}
153+
name: Optional[str] = None
154+
table: Optional[List[ZoneTable]] = []
155+
parkingPaymentProviders: Optional[List[str]] = []
156156
displayNotPayable: Optional[bool] = False
157157

158158
# -------------------------
@@ -167,7 +167,7 @@ class ProviderDescription(BaseModel):
167167

168168

169169
class SessionFee(BaseModel):
170-
comment: Optional[ProviderDescription] = None
170+
comment: Optional[ProviderDescription] = {}
171171
fixed: Optional[float] = None
172172
percentage: Optional[float] = None
173173

@@ -176,10 +176,10 @@ class SessionFee(BaseModel):
176176
# -------------------------
177177
class Fees(BaseModel):
178178
registration: Optional[Dict[str, float]] = {}
179-
session: Optional[SessionFee] = None
180-
sessionSubscription: Optional[SessionFee] = None
181-
notifSms: Optional[SessionFee] = None
182-
notifApp: Optional[SessionFee] = None
179+
session: Optional[SessionFee] = {}
180+
sessionSubscription: Optional[SessionFee] = {}
181+
notifSms: Optional[SessionFee] = {}
182+
notifApp: Optional[SessionFee] = {}
183183

184184

185185

@@ -197,9 +197,9 @@ class Subscription(BaseModel):
197197
# Provider Definition
198198
# -------------------------
199199
class Provider(BaseModel):
200-
descriptionApp: Optional[ProviderDescription] = None
201-
descriptionSMS: Optional[ProviderDescription] = None
202-
fees: Optional[Fees] = None
200+
descriptionApp: Optional[ProviderDescription] = {}
201+
descriptionSMS: Optional[ProviderDescription] = {}
202+
fees: Optional[Fees] = {}
203203
advantageApp: Optional[Dict[str, List[str]]] = {}
204204
disadvantageApp: Optional[Dict[str, List[str]]] = {}
205205
advantageSms: Optional[Dict[str, List[str]]] = {}
@@ -231,21 +231,21 @@ class CityInfo(BaseModel):
231231
# Full Response Model
232232
# -------------------------
233233
class SeetyStreetComplete(BaseModel):
234-
rules: Dict[str, Zone]
234+
rules: Optional[Dict[str, Zone]] = {}
235235
table: Optional[List[ZoneTable]] = []
236-
maxStay: Union[str, int] = 0
236+
maxStay: Optional[Union[str, int]] = None
237237
remarks: Optional[List[str]] = []
238-
specialPermits: Optional[SpecialPermits] = SpecialPermits()
238+
specialPermits: Optional[SpecialPermits] = {}
239239
providers: Optional[List[Provider]] = []
240-
city: CityInfo
241-
cityName: str
242-
status: str
240+
city: Optional[CityInfo] = {}
241+
cityName: Optional[str] = None
242+
status: Optional[str] = None
243243

244244
class CityParkingModel(BaseModel):
245-
user: Optional[SeetyUser] = None
246-
location: Optional[SeetyLocationResponse] = None
247-
rules: Optional[SeetyStreetRules] = None
248-
streetComplete: Optional[SeetyStreetComplete] = None
245+
user: Optional[SeetyUser] = {}
246+
location: Optional[SeetyLocationResponse] = {}
247+
rules: Optional[SeetyStreetRules] = {}
248+
streetComplete: Optional[SeetyStreetComplete] = {}
249249
origin: Optional[str] = None
250-
origin_coordinates: Optional[Coords] = None
251-
extra_data: Optional[Dict[str, Any]] = None
250+
origin_coordinates: Optional[Coords] = {}
251+
extra_data: Optional[Dict[str, Any]] = {}

0 commit comments

Comments
 (0)