2019-06-12 13:40:57 +01:00
|
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
|
|
from collections.abc import Sequence
|
|
|
|
|
|
|
2019-04-04 11:18:22 +01:00
|
|
|
|
from flask import abort
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class JSONModel():
|
|
|
|
|
|
|
|
|
|
|
|
ALLOWED_PROPERTIES = set()
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, _dict):
|
|
|
|
|
|
# in the case of a bad request _dict may be `None`
|
|
|
|
|
|
self._dict = _dict or {}
|
|
|
|
|
|
|
|
|
|
|
|
def __bool__(self):
|
|
|
|
|
|
return self._dict != {}
|
|
|
|
|
|
|
2019-06-12 12:09:26 +01:00
|
|
|
|
def __hash__(self):
|
|
|
|
|
|
return hash(self.id)
|
|
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
|
|
return self.id == other.id
|
|
|
|
|
|
|
2019-07-09 11:47:40 +01:00
|
|
|
|
def __getattribute__(self, attr):
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
return super().__getattribute__(attr)
|
|
|
|
|
|
except AttributeError as e:
|
|
|
|
|
|
# Re-raise any `AttributeError`s that are not directly on
|
|
|
|
|
|
# this object because they indicate an underlying exception
|
|
|
|
|
|
# that we don’t want to swallow
|
|
|
|
|
|
if str(e) != "'{}' object has no attribute '{}'".format(
|
|
|
|
|
|
self.__class__.__name__, attr
|
|
|
|
|
|
):
|
|
|
|
|
|
raise e
|
|
|
|
|
|
|
|
|
|
|
|
if attr in super().__getattribute__('ALLOWED_PROPERTIES'):
|
|
|
|
|
|
return super().__getattribute__('_dict')[attr]
|
|
|
|
|
|
|
|
|
|
|
|
raise AttributeError((
|
|
|
|
|
|
"'{}' object has no attribute '{}' and '{}' is not a field "
|
|
|
|
|
|
"in the underlying JSON"
|
|
|
|
|
|
).format(
|
|
|
|
|
|
self.__class__.__name__, attr, attr
|
2019-04-04 11:18:22 +01:00
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
def _get_by_id(self, things, id):
|
|
|
|
|
|
try:
|
|
|
|
|
|
return next(thing for thing in things if thing['id'] == str(id))
|
|
|
|
|
|
except StopIteration:
|
|
|
|
|
|
abort(404)
|
2019-05-23 15:27:35 +01:00
|
|
|
|
|
|
|
|
|
|
|
2019-06-12 13:40:57 +01:00
|
|
|
|
class ModelList(ABC, Sequence):
|
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
|
@abstractmethod
|
2020-01-16 15:57:51 +00:00
|
|
|
|
def client_method(self):
|
2019-06-12 13:40:57 +01:00
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
|
@abstractmethod
|
2019-11-01 10:43:01 +00:00
|
|
|
|
def model(self):
|
2019-06-12 13:40:57 +01:00
|
|
|
|
pass
|
|
|
|
|
|
|
2019-10-18 16:09:39 +01:00
|
|
|
|
def __init__(self, *args):
|
2020-01-16 15:57:51 +00:00
|
|
|
|
self.items = self.client_method(*args)
|
2019-06-12 13:40:57 +01:00
|
|
|
|
|
|
|
|
|
|
def __getitem__(self, index):
|
|
|
|
|
|
return self.model(self.items[index])
|
|
|
|
|
|
|
|
|
|
|
|
def __len__(self):
|
|
|
|
|
|
return len(self.items)
|
|
|
|
|
|
|
|
|
|
|
|
def __add__(self, other):
|
|
|
|
|
|
return list(self) + list(other)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-05-23 15:27:35 +01:00
|
|
|
|
class InviteTokenError(Exception):
|
|
|
|
|
|
pass
|