Skip to content

Commit 65e443a

Browse files
authored
Merge pull request #3 from srichs/codex/fix-black-ci-issues
Apply Black formatting fixes to resolve CI failures
2 parents 74afc1b + 06ce56d commit 65e443a

6 files changed

Lines changed: 116 additions & 61 deletions

File tree

docs/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Sphinx configuration for the python-spot documentation."""
2+
23
from __future__ import annotations
34

45
import os
@@ -34,5 +35,5 @@
3435
exclude_patterns: list[str] = ["_build"]
3536

3637
html_static_path = ["_static"]
37-
#html_theme = "alabaster"
38+
# html_theme = "alabaster"
3839
html_theme = "furo"

spot_api/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Public exports for the Spot API package."""
2+
23
from .client import SpotApi, SpotRequestResult, SpotRequestStatus
34
from .enums import (
45
SpotBatteryState,

spot_api/client.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Async client implementation for interacting with the Spot API."""
2+
23
from __future__ import annotations
34

45
import asyncio
@@ -73,7 +74,9 @@ def __bool__(self) -> bool: # pragma: no cover - convenience wrapper
7374
class SpotApi(object):
7475
"""High-level interface for accessing Spot feeds and messages."""
7576

76-
SPOT_API_ENDPOINT: str = "https://api.findmespot.com/spot-main-web/consumer/rest-api/2.0/public/feed/"
77+
SPOT_API_ENDPOINT: str = (
78+
"https://api.findmespot.com/spot-main-web/consumer/rest-api/2.0/public/feed/"
79+
)
7780
# Spot asks to wait at least 2.5 minutes between requests of the same feed
7881
SPOT_API_WAIT_TIME: int = 150
7982
# Spot asks to wait at least 2 seconds between requests for different feeds
@@ -148,9 +151,7 @@ def get_last_response(self, feed_id: Optional[str] = None) -> Optional[dict]:
148151
return None
149152
return self._last_response.get(target_feed_id)
150153

151-
def _normalize_feed_list(
152-
self, feed_list: Iterable[FeedEntry]
153-
) -> list[FeedEntry]:
154+
def _normalize_feed_list(self, feed_list: Iterable[FeedEntry]) -> list[FeedEntry]:
154155
"""Validate and normalize the configured feeds.
155156
156157
Converting the IDs and passwords to strings up front ensures the rest of the
@@ -467,7 +468,10 @@ async def request_all_pages(
467468

468469
if result.status is SpotRequestStatus.THROTTLED:
469470
throttle_count += 1
470-
if max_throttled_retries is not None and throttle_count > max_throttled_retries:
471+
if (
472+
max_throttled_retries is not None
473+
and throttle_count > max_throttled_retries
474+
):
471475
logger.warning(
472476
"Aborting pagination for feed %s after %s throttled responses",
473477
feed.id,
@@ -518,7 +522,9 @@ async def _request(
518522
allowed, wait_seconds = self._can_dispatch_request(feed)
519523
if not allowed:
520524
logger.debug(
521-
"Throttling request for feed %s; %.2f seconds remaining", feed.id, wait_seconds
525+
"Throttling request for feed %s; %.2f seconds remaining",
526+
feed.id,
527+
wait_seconds,
522528
)
523529
return SpotRequestResult(
524530
SpotRequestStatus.THROTTLED,
@@ -582,7 +588,9 @@ async def _perform_http_request(
582588
) -> httpx.Response | SpotRequestResult:
583589
try:
584590
client = self._ensure_client()
585-
response = await client.get(url, params=payload, headers=headers_for_request)
591+
response = await client.get(
592+
url, params=payload, headers=headers_for_request
593+
)
586594
response.raise_for_status()
587595
except httpx.HTTPError as exc:
588596
logger.exception("HTTP error while contacting Spot API")
@@ -770,7 +778,9 @@ def _retry_after_seconds(self, response: Optional[httpx.Response]) -> float:
770778
return default_wait
771779

772780
try:
773-
retry_after = response.headers.get("Retry-After") if response.headers else None
781+
retry_after = (
782+
response.headers.get("Retry-After") if response.headers else None
783+
)
774784
except Exception: # pragma: no cover - defensive
775785
retry_after = None
776786

@@ -839,7 +849,9 @@ def _build_request(
839849

840850
if start_dt and end_dt:
841851
if end_dt < start_dt:
842-
raise ValueError("End datetime must be greater than or equal to start datetime")
852+
raise ValueError(
853+
"End datetime must be greater than or equal to start datetime"
854+
)
843855

844856
payload["startDate"] = self._format_request_datetime(start_dt)
845857
payload["endDate"] = self._format_request_datetime(end_dt)
@@ -906,7 +918,7 @@ def _calculate_throttle_wait(
906918

907919
@staticmethod
908920
def _normalize_headers(
909-
headers: Optional[Mapping[str, str]]
921+
headers: Optional[Mapping[str, str]],
910922
) -> Optional[Dict[str, str]]:
911923
if headers is None:
912924
return None
@@ -919,7 +931,7 @@ def _normalize_headers(
919931

920932
@staticmethod
921933
def _normalize_query_params(
922-
params: Optional[Mapping[str, str]]
934+
params: Optional[Mapping[str, str]],
923935
) -> Optional[Dict[str, str]]:
924936
if params is None:
925937
return None
@@ -1021,7 +1033,9 @@ async def _reset_client_after_sync_run(self) -> None:
10211033
try:
10221034
await client.aclose()
10231035
except Exception: # pragma: no cover - defensive cleanup
1024-
logger.warning("Failed to close AsyncClient after synchronous run", exc_info=True)
1036+
logger.warning(
1037+
"Failed to close AsyncClient after synchronous run", exc_info=True
1038+
)
10251039

10261040
@staticmethod
10271041
def _now() -> datetime.datetime:

spot_api/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Enumeration definitions for the Spot API client."""
2+
23
from __future__ import annotations
34

45
import logging

spot_api/models.py

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Data models and parsing helpers for Spot API responses."""
2+
23
from __future__ import annotations
34

45
import datetime
@@ -107,10 +108,18 @@ def from_json(cls, message: Mapping[str, Any]) -> "SpotMessage":
107108
if not isinstance(message, Mapping):
108109
raise TypeError("message must be a mapping")
109110

110-
required_fields = ["@clientUnixTime", "id", "messengerId", "messengerName", "unixTime"]
111+
required_fields = [
112+
"@clientUnixTime",
113+
"id",
114+
"messengerId",
115+
"messengerName",
116+
"unixTime",
117+
]
111118
missing_fields = [field for field in required_fields if field not in message]
112119
if missing_fields:
113-
logger.warning("Missing expected message fields: %s", ", ".join(missing_fields))
120+
logger.warning(
121+
"Missing expected message fields: %s", ", ".join(missing_fields)
122+
)
114123

115124
message_type = None
116125
if "messageType" in message:
@@ -131,7 +140,9 @@ def from_json(cls, message: Mapping[str, Any]) -> "SpotMessage":
131140

132141
date_time = _parse_datetime(message.get("dateTime"))
133142
raw_battery_state = message.get("batteryState")
134-
battery_state = SpotBatteryState.from_str("" if raw_battery_state is None else str(raw_battery_state))
143+
battery_state = SpotBatteryState.from_str(
144+
"" if raw_battery_state is None else str(raw_battery_state)
145+
)
135146

136147
hidden = _coerce_int(message.get("hidden", 0))
137148
altitude = _coerce_int(message.get("altitude", 0))
@@ -167,9 +178,7 @@ def get_short_datetime(self) -> str:
167178
else:
168179
return datetime.datetime.fromtimestamp(
169180
unix_time_int, tz=datetime.timezone.utc
170-
).strftime(
171-
"%Y-%m-%d %H:%M:%S"
172-
)
181+
).strftime("%Y-%m-%d %H:%M:%S")
173182

174183
return ""
175184

@@ -193,12 +202,12 @@ def _check_longitude(longitude: Optional[float]) -> float:
193202
def __str__(self) -> str:
194203
msg_str = "-------------------------------\n"
195204
msg_str += f"Spot Message ({self.id})\n"
196-
msg_str += (
197-
f"'{self.messenger_name}' {self.messenger_id} ({self.model_id} - {self.message_type})\n"
198-
)
205+
msg_str += f"'{self.messenger_name}' {self.messenger_id} ({self.model_id} - {self.message_type})\n"
199206
msg_str += f"Battery: {self.battery_state}\n"
200207
timestamp = (
201-
self.date_time.isoformat(" ") if self.date_time is not None else self.get_short_datetime()
208+
self.date_time.isoformat(" ")
209+
if self.date_time is not None
210+
else self.get_short_datetime()
202211
)
203212
msg_str += f"{timestamp} ({self.unix_time})\n"
204213
msg_str += self.get_location()
@@ -228,17 +237,22 @@ def from_json(self, response: Mapping[str, Any], *, merge: bool = False) -> None
228237
raise TypeError("response must be a mapping")
229238

230239
if "response" not in response:
231-
logger.warning("No response payload present in Spot feed data: %s", response)
240+
logger.warning(
241+
"No response payload present in Spot feed data: %s", response
242+
)
232243
return
233244

234245
if "feedMessageResponse" not in response["response"]:
235-
logger.warning("No feedMessageResponse present in Spot feed response: %s", response)
246+
logger.warning(
247+
"No feedMessageResponse present in Spot feed response: %s", response
248+
)
236249
return
237250

238251
feed_message_response = response["response"]["feedMessageResponse"]
239252
if not isinstance(feed_message_response, Mapping):
240253
logger.warning(
241-
"feedMessageResponse payload was not a mapping in feed %s response", self.id
254+
"feedMessageResponse payload was not a mapping in feed %s response",
255+
self.id,
242256
)
243257
return
244258
feed_json = feed_message_response.get("feed", {})
@@ -249,9 +263,7 @@ def from_json(self, response: Mapping[str, Any], *, merge: bool = False) -> None
249263
self.description = feed_json.get("description", "")
250264
raw_status = feed_json.get("status")
251265
self.status = (
252-
SpotFeedStatus.from_str(str(raw_status))
253-
if raw_status is not None
254-
else None
266+
SpotFeedStatus.from_str(str(raw_status)) if raw_status is not None else None
255267
)
256268
self.usage = _coerce_int(feed_json.get("usage", 0))
257269
self.days_range = _coerce_int(feed_json.get("daysRange", 0))
@@ -260,9 +272,7 @@ def from_json(self, response: Mapping[str, Any], *, merge: bool = False) -> None
260272
)
261273
raw_type = feed_json.get("type")
262274
self.type = (
263-
SpotFeedType.from_str(str(raw_type))
264-
if raw_type is not None
265-
else None
275+
SpotFeedType.from_str(str(raw_type)) if raw_type is not None else None
266276
)
267277
count = _coerce_int(feed_message_response.get("count", 0))
268278

@@ -291,7 +301,9 @@ def from_json(self, response: Mapping[str, Any], *, merge: bool = False) -> None
291301
iterable: Iterable
292302
if isinstance(message_payload, Mapping):
293303
iterable = message_payload.values()
294-
elif isinstance(message_payload, Sequence) and not isinstance(message_payload, (str, bytes)):
304+
elif isinstance(message_payload, Sequence) and not isinstance(
305+
message_payload, (str, bytes)
306+
):
295307
iterable = message_payload
296308
else:
297309
logger.warning(
@@ -311,7 +323,9 @@ def from_json(self, response: Mapping[str, Any], *, merge: bool = False) -> None
311323
continue
312324
msg_id = message_json.get("messengerId")
313325
if not msg_id:
314-
logger.warning("Encountered message without messengerId in feed %s", self.id)
326+
logger.warning(
327+
"Encountered message without messengerId in feed %s", self.id
328+
)
315329
continue
316330

317331
message = SpotMessage.from_json(message_json)
@@ -335,7 +349,8 @@ def iter_messages(self, *, newest_first: bool = True) -> Iterable[SpotMessage]:
335349
all_messages.extend(device_messages)
336350

337351
all_messages.sort(
338-
key=lambda message: message.date_time or datetime.datetime.min.replace(tzinfo=datetime.timezone.utc),
352+
key=lambda message: message.date_time
353+
or datetime.datetime.min.replace(tzinfo=datetime.timezone.utc),
339354
reverse=newest_first,
340355
)
341356

0 commit comments

Comments
 (0)