|
import json |
|
import logging |
|
from functools import wraps |
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
class PandaError(Exception): |
|
pass |
|
|
|
def error_check(func): |
|
@wraps(func) |
|
def check(*args, **kwargs): |
|
try: |
|
res = func(*args, **kwargs) |
|
if "error" in res: |
|
logger.error(res["message"]) |
|
raise PandaError(res["message"]) |
|
except Exception as e: |
|
logger.error(e) |
|
raise |
|
return res |
|
return check |
|
|
|
class Retriever(object): |
|
def __init__(self, panda, model_type, path = None): |
|
self.panda = panda |
|
self.model_type = model_type |
|
if path: |
|
self.path = path |
|
else: |
|
self.path = model_type.path |
|
|
|
class GroupRetriever(Retriever): |
|
@error_check |
|
def _all(self, **kwargs): |
|
json_data = self.panda.get("{0}.json".format(self.path), kwargs) |
|
return json.loads(json_data) |
|
|
|
@error_check |
|
def new(self, *args, **kwargs): |
|
return self.model_type(self.panda, *args, **kwargs) |
|
|
|
@error_check |
|
def create(self, *args, **kwargs): |
|
return self.new(*args, **kwargs).create(**kwargs) |
|
|
|
@error_check |
|
def find(self, val, **kwargs): |
|
json_data = self.panda.get("{0}/{1}.json".format(self.path, val), **kwargs) |
|
return self.model_type(self.panda, **json.loads(json_data)) |
|
|
|
def all(self, **kwargs): |
|
return [self.model_type(self.panda, **json_attr) for json_attr in self._all(**kwargs)] |
|
|
|
def where(self, pred, **kwargs): |
|
return [self.model_type(self.panda, **json_attr) for json_attr in self._all(**kwargs) if pred(json_attr)] |
|
|
|
class SingleRetriever(Retriever): |
|
@error_check |
|
def get(self, **kwargs): |
|
json_data = self.panda.get("{0}.json".format(self.path), **kwargs) |
|
return self.model_type(self.panda, json.loads(json_data)) |
|
|
|
@error_check |
|
def post(self, **kwargs): |
|
json_data = self.panda.post("{0}.json".format(self.path), **kwargs) |
|
return self.model_type(self.panda, json.loads(json_data)) |
|
|
|
class PandaDict(dict): |
|
def __init__(self, panda, *arg, **kwarg): |
|
self.panda = panda |
|
super(PandaDict, self).__init__(*arg, **kwarg) |
|
|
|
def to_json(self, *args, **kwargs): |
|
return json.dumps(self, *args, **kwargs) |
|
|
|
class PandaModel(PandaDict): |
|
def dup(self): |
|
copy = self.copy() |
|
if "id" in copy: |
|
copy["id"] |
|
return copy |
|
|
|
def reload(self): |
|
json_data = self.panda.get("{0}/{1}.json".format(self.path, self["id"])) |
|
self.clear() |
|
parsed = json.loads(json_data) |
|
self.update(parsed) |
|
|
|
@error_check |
|
def create(self, **kwargs): |
|
json_data = self.panda.post("{0}.json".format(self.path), kwargs) |
|
return self.__class__(self.panda, json.loads(json_data)) |
|
|
|
@error_check |
|
def delete(self, **kwargs): |
|
json_data = self.panda.delete("{0}/{1}.json".format(self.path, self["id"]), kwargs) |
|
return self.__class__(self.panda, json.loads(json_data)) |
|
|
|
class UpdatablePandaModel(PandaModel): |
|
changed_values = {} |
|
|
|
@error_check |
|
def save(self): |
|
put_path = "{0}/{1}.json".format(self.path, self["id"]) |
|
ret = type(self)(self.panda, json.loads(self.panda.put(put_path, self.changed_values))) |
|
if "error" not in ret: |
|
self.changed_values = {} |
|
return ret |
|
|
|
def __setitem__(self, key, val): |
|
self.changed_values[key] = val |
|
super(UpdatablePandaModel, self).__setitem__(key, val) |
|
|
|
|
|
def update(self, *args, **kwargs): |
|
if args: |
|
if len(args) > 1: |
|
raise TypeError("update expected at most 1 arguments, got %d" % len(args)) |
|
other = dict(args[0]) |
|
for key in other: |
|
self[key] = other[key] |
|
for key in kwargs: |
|
self[key] = kwargs[key] |
|
|
|
|
|
def setdefault(self, key, value=None): |
|
if key not in self: |
|
self[key] = value |
|
return self[key] |
|
|
|
class Video(PandaModel): |
|
path = "/videos" |
|
|
|
def encodings(self): |
|
return GroupRetriever(self.panda, Encoding, "/videos/{0}/encodings".format(self["id"])).all() |
|
|
|
def metadata(self): |
|
return SingleRetriever(self.panda, Metadata, "/videos/{0}/metadata".format(self["id"])).get() |
|
|
|
class Cloud(UpdatablePandaModel): |
|
path = "/clouds" |
|
|
|
class Encoding(PandaModel): |
|
path = "/encodings" |
|
|
|
def video(self): |
|
return SingleRetriever(self.panda, Video, "/videos/{0}".format(self["video_id"])).get() |
|
|
|
def profile(self): |
|
key = self["profile_name"] or self["profile_id"] |
|
return SingleRetriever(self.panda, Video, "/profiles/{0}".format(key)).get() |
|
|
|
def cancel(self): |
|
return SingleRetriever(self.panda, PandaDict, "/encodings/{0}/cancel.json".format(self["id"])).post() |
|
|
|
def retry(self): |
|
return SingleRetriever(self.panda, PandaDict, "/encodings/{0}/retry.json".format(self["id"])).post() |
|
|
|
class Profile(UpdatablePandaModel): |
|
path = "/profiles" |
|
|
|
class Notifications(UpdatablePandaModel): |
|
path = "/notifications" |
|
|
|
@error_check |
|
def save(self): |
|
tmp = dict(self) |
|
for event in tmp["events"]: |
|
tmp["events"][event] = str(tmp["events"][event]).lower() |
|
return Notifications(self.panda, json.loads(self.panda.put("/notifications.json", tmp))) |
|
|
|
def delete(self): |
|
raise AttributeError("Notification instance has no attribute 'delete'") |
|
|
|
def reload(self): |
|
json_data = self.panda.get("/notifications.json") |
|
self.clear() |
|
self.update(json.loads(json_data)) |
|
|
|
class Metadata(PandaDict): |
|
pass |
|
|