Skip to content
This repository has been archived by the owner on Sep 12, 2024. It is now read-only.

[FLAPI-2083] Fix various models type hints when maybe parsing #54

Merged
merged 8 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 68 additions & 29 deletions duffel_api/models/offer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,40 @@ class InvalidPassengerIdentityDocumentType(Exception):

def __init__(self, json):
for key in json:
value = Offer.__maybe_init_value(key, json)

setattr(self, key, value)

@staticmethod
def __maybe_init_value(key, json):
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])

if isinstance(value, dict):
parsers = {
"conditions": OfferConditions,
"owner": Airline,
"payment_requirements": PaymentRequirements,
}

value = parsers[key](value)

if isinstance(value, list):
if key == "allowed_passenger_identity_document_types":
Offer._validate_passenger_identity_document_types(value)
elif key == "conditions":
value = OfferConditions(value)
elif key == "slices":
value = [OfferSlice(v) for v in value]
elif key == "passengers":
value = [Passenger(v) for v in value]
elif key == "payment_requirements":
value = PaymentRequirements(value)
elif key == "available_services":
value = [Service(v) for v in value]
elif key == "owner":
value = Airline(value)
setattr(self, key, value)
return

parsers = {
"slices": OfferSlice,
"passengers": Passenger,
"available_services": Service,
}

value = [parsers[key](v) for v in value]

return value

@staticmethod
def _validate_passenger_identity_document_types(document_types):
Expand All @@ -55,6 +73,8 @@ class OfferConditions:

def __init__(self, json):
for key in json:
value = json[key]

if key == "change_before_departure":
if not json[key] is None:
value = OfferConditionChangeBeforeDeparture(json[key])
Expand Down Expand Up @@ -166,14 +186,23 @@ class InvalidPlaceType(Exception):

def __init__(self, json):
for key in json:
value = maybe_parse_date_entries(key, json[key])
if key in ["destination", "origin"]:
value = Place(value)
elif key in ["destination_type", "origin_type"]:
if value not in OfferSlice.allowed_place_types:
raise OfferSlice.InvalidPlaceType(value)
elif key == "segments":
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])

if key in ["destination", "origin"]:
value = Place(value)
elif key in ["destination_type", "origin_type"]:
if value not in OfferSlice.allowed_place_types:
raise OfferSlice.InvalidPlaceType(value)

setattr(self, key, value)
continue

if key == "segments":
value = [OfferSliceSegment(v) for v in value]

# TODO(nlopes): maybe convert duration to a timedelta or Duration
setattr(self, key, value)

Expand All @@ -185,15 +214,25 @@ class OfferSliceSegment:

def __init__(self, json):
for key in json:
value = maybe_parse_date_entries(key, json[key])
if key == "aircraft" and value:
value = Aircraft(value)
elif key in ["marketing_carrier", "operating_carrier"] and value:
value = Airline(value)
elif key in ["destination", "origin"]:
value = Place(value)
elif key == "passengers":
value = [OfferSliceSegmentPassenger(p) for p in value]
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])
setattr(self, key, value)
continue

if isinstance(value, dict):
if key == "aircraft" and value:
value = Aircraft(value)
elif key in ["marketing_carrier", "operating_carrier"] and value:
value = Airline(value)
elif key in ["destination", "origin"]:
value = Place(value)

if isinstance(value, list):
if key == "passengers":
value = [OfferSliceSegmentPassenger(p) for p in value]

setattr(self, key, value)


Expand Down
22 changes: 15 additions & 7 deletions duffel_api/models/offer_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@ class OfferRequest:

def __init__(self, json):
for key in json:
value = maybe_parse_date_entries(key, json[key])
if key == "offers":
value = [Offer(v) for v in value]
elif key == "passengers":
value = [Passenger(v) for v in value]
elif key == "slices":
value = [Slice(v) for v in value]
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])
setattr(self, key, value)
continue

if isinstance(value, list):
if key == "offers":
value = [Offer(v) for v in value]
elif key == "passengers":
value = [Passenger(v) for v in value]
elif key == "slices":
value = [Slice(v) for v in value]

setattr(self, key, value)


Expand Down
104 changes: 74 additions & 30 deletions duffel_api/models/order.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from ..models import (
Airline,
Place,
Aircraft,
Airline,
OfferConditionChangeBeforeDeparture,
OfferConditionRefundBeforeDeparture,
Place,
)
from ..utils import maybe_parse_date_entries

Expand All @@ -19,25 +19,40 @@ class Order:

def __init__(self, json):
for key in json:
value = json[key]
if value is not None:
value = maybe_parse_date_entries(key, json[key])
if key == "documents":
value = [OrderDocument(v) for v in value]
elif key == "conditions":
value = OrderConditions(value)
elif key == "owner":
value = Airline(value)
elif key == "passengers":
value = [OrderPassenger(v) for v in value]
elif key == "payment_status":
value = OrderPaymentStatus(value)
elif key == "services":
value = [OrderService(v) for v in value]
elif key == "slices":
value = [OrderSlice(v) for v in value]
value = Order.__maybe_init_value(key, json)

setattr(self, key, value)

@staticmethod
def __maybe_init_value(key, json):
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])
elif isinstance(value, dict):
# Metadata is customer-specified data, so we don't try and parse it
if key == "metadata":
return value

parsers = {
"conditions": OrderConditions,
"owner": Airline,
"payment_status": OrderPaymentStatus,
}

value = parsers[key](value)
elif isinstance(value, list):
parsers = {
"documents": OrderDocument,
"passengers": OrderPassenger,
"services": OrderService,
"slices": OrderSlice,
}

value = [parsers[key](v) for v in value]

return value


class OrderConditions:
"""The conditions associated with this order, describing the kinds of modifications you
Expand All @@ -53,8 +68,7 @@ class OrderConditions:

def __init__(self, json):
for key in json:
# Bind the value before we go into the control flow for setting it
value = None
value = json[key]

if key == "change_before_departure":
value = OrderConditionChangeBeforeDeparture(json[key])
Expand All @@ -81,14 +95,23 @@ class InvalidPlaceType(Exception):

def __init__(self, json):
for key in json:
value = maybe_parse_date_entries(key, json[key])
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])
setattr(self, key, value)
continue

if key in ["destination", "origin"]:
value = Place(value)
elif key in ["destination_type", "origin_type"]:
if value not in OrderSlice.allowed_place_types:
raise OrderSlice.InvalidPlaceType(value)
elif key == "segments":
value = [OrderSliceSegment(v) for v in value]

if isinstance(value, list):
if key == "segments":
value = [OrderSliceSegment(v) for v in value]

# TODO(nlopes): maybe convert duration to a timedelta or Duration
setattr(self, key, value)

Expand All @@ -101,7 +124,13 @@ class OrderSliceSegment:

def __init__(self, json):
for key in json:
value = maybe_parse_date_entries(key, json[key])
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])
setattr(self, key, value)
continue

if key == "aircraft" and value:
value = Aircraft(value)
elif key in ["marketing_carrier", "operating_carrier"] and value:
Expand All @@ -110,6 +139,7 @@ def __init__(self, json):
value = Place(value)
elif key == "passengers":
value = [OrderSliceSegmentPassenger(p) for p in value]

setattr(self, key, value)


Expand All @@ -126,9 +156,12 @@ class InvalidCabinClass(Exception):
def __init__(self, json):
for key in json:
value = json[key]
if key == "baggages":
value = [OrderSliceSegmentPassengerBaggage(v) for v in value]
elif key == "seat":

if isinstance(value, list):
if key == "baggages":
value = [OrderSliceSegmentPassengerBaggage(v) for v in value]

if key == "seat":
if value is not None:
value = OrderSliceSegmentPassengerSeat(value)
elif key == "cabin_class":
Expand Down Expand Up @@ -227,8 +260,12 @@ class OrderPaymentStatus:
def __init__(self, json):
for key in json:
value = json[key]
if value is not None:

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])
setattr(self, key, value)
continue

setattr(self, key, value)


Expand All @@ -250,13 +287,20 @@ class InvalidType(Exception):

def __init__(self, json):
for key in json:
value = maybe_parse_date_entries(key, json[key])
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])
setattr(self, key, value)
continue

if key == "gender" and value.lower() not in OrderPassenger.allowed_genders:
raise OrderPassenger.InvalidGender(value)
elif key == "title" and value.lower() not in OrderPassenger.allowed_titles:
raise OrderPassenger.InvalidTitle(value)
elif key == "type" and value.lower() not in OrderPassenger.allowed_types:
raise OrderPassenger.InvalidType(value)

setattr(self, key, value)


Expand Down
19 changes: 14 additions & 5 deletions duffel_api/models/order_change_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,21 @@ class OrderChangeRequest:

def __init__(self, json):
for key in json:
value = maybe_parse_date_entries(key, json[key])
value = json[key]

if isinstance(value, str):
value = maybe_parse_date_entries(key, json[key])
setattr(self, key, value)
continue

if isinstance(value, dict):
if key == "slices":
value = OrderChangeRequestSlice(value)

if isinstance(value, list):
if key == "order_change_offers":
value = [OrderChangeOffer(v) for v in value]

if key == "order_change_offers":
value = [OrderChangeOffer(v) for v in value]
elif key == "slices":
value = OrderChangeRequestSlice(value)
setattr(self, key, value)


Expand Down
12 changes: 7 additions & 5 deletions duffel_api/utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""Assorted auxiliary functions"""
from datetime import datetime, date
from datetime import date, datetime
from typing import Any, Union


def maybe_parse_date_entries(key, value):
"""Parse datetime entries, depending on the value of `key`"""
if value is None:
def maybe_parse_date_entries(key: str, value: Any) -> Union[str, datetime, date]:
jesse-c marked this conversation as resolved.
Show resolved Hide resolved
"""Parse appropriate datetime or date entries, depending on the value of `key`"""
if not isinstance(value, str):
# If it's not a string, don't attempt any parsing
return value

if key in [
"created_at",
"updated_at",
Expand Down Expand Up @@ -44,6 +45,7 @@ def maybe_parse_date_entries(key, value):
else:
return datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%fZ")

# All other strings
return value


Expand Down
Loading