Skip to content

Commit

Permalink
refactor(api.py): replace json import with direct response handling t…
Browse files Browse the repository at this point in the history
…o streamline code

fix(api.py): handle request errors with new OtfRequestError for better error management
feat(api.py): add exception handling for booking requests to improve error reporting
feat(exceptions.py): introduce OtfRequestError for detailed request error handling
  • Loading branch information
NodeJSmith committed Jan 5, 2025
1 parent 68b6495 commit ed4e10b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 11 deletions.
28 changes: 17 additions & 11 deletions src/otf_api/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import atexit
import contextlib
import json
from datetime import date, datetime, timedelta
from logging import getLogger
from typing import Any
Expand Down Expand Up @@ -76,7 +75,8 @@ def _do(

LOGGER.debug(f"Making {method!r} request to {full_url}, params: {params}")

response = self.session.request(method, full_url, headers=headers, params=params, **kwargs)
request = self.session.build_request(method, full_url, headers=headers, params=params, **kwargs)
response = self.session.send(request)

try:
response.raise_for_status()
Expand All @@ -91,7 +91,7 @@ def _do(
if isinstance(response, dict) and "code" in response and response["code"] != "SUCCESS":
LOGGER.error(f"Error making request: {response}")
LOGGER.error(f"Response: {response.text}")
raise Exception(f"Error making request: {response}")
raise exc.OtfRequestError("Error making request", response=response, request=request)

return response.json()

Expand Down Expand Up @@ -267,17 +267,23 @@ def book_class(self, otf_class: str | models.OtfClass) -> models.Booking:

body = {"classUUId": class_uuid, "confirmed": False, "waitlist": False}

resp = self._default_request("PUT", f"/member/members/{self.member_uuid}/bookings", json=body)
try:
resp = self._default_request("PUT", f"/member/members/{self.member_uuid}/bookings", json=body)
except exc.OtfRequestError as e:
resp = e.response

if resp["code"] == "ERROR":
if resp["data"]["errorCode"] == "603":
raise exc.AlreadyBookedError(f"Class {class_uuid} is already booked.")
if resp["data"]["errorCode"] == "602":
raise exc.OutsideSchedulingWindowError(f"Class {class_uuid} is outside the scheduling window.")
if resp["code"] == "ERROR":
if resp["data"]["errorCode"] == "603":
raise exc.AlreadyBookedError(f"Class {class_uuid} is already booked.")
if resp["data"]["errorCode"] == "602":
raise exc.OutsideSchedulingWindowError(f"Class {class_uuid} is outside the scheduling window.")

raise exc.OtfException(f"Error booking class {class_uuid}: {json.dumps(resp)}")
raise
except Exception as e:
raise exc.OtfException(f"Error booking class {class_uuid}: {e}")

# get the booking details - we will only use this to get the booking_uuid
# get the booking details - we will only use this to get the booking_uuid so that we can return a Booking object
# using `get_booking`; this is an attempt to improve on OTF's terrible data model
book_class = models.BookClass(**resp["data"])

booking = self.get_booking(book_class.booking_uuid)
Expand Down
12 changes: 12 additions & 0 deletions src/otf_api/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ class OtfException(Exception):
"""Base class for all exceptions in this package."""


class OtfRequestError(OtfException):
"""Raised when an error occurs while making a request to the OTF API."""

response: dict
request: dict

def __init__(self, message: str, response: dict, request: dict):
super().__init__(message)
self.response = response
self.request = request


class BookingError(OtfException):
"""Base class for booking-related errors, with an optional booking UUID attribute."""

Expand Down

0 comments on commit ed4e10b

Please sign in to comment.