Files
edx-platform/lms/lib/comment_client/models.py
Greg Price 7abaecd8b7 Improve forum error handling
CommentClientError now has sane subclasses that are meaningfully
distinct, and each subclass is handled appropriately. Errors raised by
the requests library are no longer handled by turning them into
CommentClientErrors, since there is no meaningful handling we can do,
and this way we will get more visibility into why errors are occurring.
Also, HTTP status codes from the comments service indicating client
error are correctly passed through to the client.
2013-10-28 11:23:06 -04:00

132 lines
4.4 KiB
Python

from .utils import *
class Model(object):
accessible_fields = ['id']
updatable_fields = ['id']
initializable_fields = ['id']
base_url = None
default_retrieve_params = {}
DEFAULT_ACTIONS_WITH_ID = ['get', 'put', 'delete']
DEFAULT_ACTIONS_WITHOUT_ID = ['get_all', 'post']
DEFAULT_ACTIONS = DEFAULT_ACTIONS_WITH_ID + DEFAULT_ACTIONS_WITHOUT_ID
def __init__(self, *args, **kwargs):
self.attributes = extract(kwargs, self.accessible_fields)
self.retrieved = False
def __getattr__(self, name):
if name == 'id':
return self.attributes.get('id', None)
try:
return self.attributes[name]
except KeyError:
if self.retrieved or self.id is None:
raise AttributeError("Field {0} does not exist".format(name))
self.retrieve()
return self.__getattr__(name)
def __setattr__(self, name, value):
if name == 'attributes' or name not in self.accessible_fields:
super(Model, self).__setattr__(name, value)
else:
self.attributes[name] = value
def __getitem__(self, key):
if key not in self.accessible_fields:
raise KeyError("Field {0} does not exist".format(key))
return self.attributes.get(key)
def __setitem__(self, key, value):
if key not in self.accessible_fields:
raise KeyError("Field {0} does not exist".format(key))
self.attributes.__setitem__(key, value)
def items(self, *args, **kwargs):
return self.attributes.items(*args, **kwargs)
def get(self, *args, **kwargs):
return self.attributes.get(*args, **kwargs)
def to_dict(self):
self.retrieve()
return self.attributes
def retrieve(self, *args, **kwargs):
if not self.retrieved:
self._retrieve(*args, **kwargs)
self.retrieved = True
return self
def _retrieve(self, *args, **kwargs):
url = self.url(action='get', params=self.attributes)
response = perform_request('get', url, self.default_retrieve_params)
self.update_attributes(**response)
@classmethod
def find(cls, id):
return cls(id=id)
def update_attributes(self, *args, **kwargs):
for k, v in kwargs.items():
if k in self.accessible_fields:
self.__setattr__(k, v)
else:
raise AttributeError("Field {0} does not exist".format(k))
def updatable_attributes(self):
return extract(self.attributes, self.updatable_fields)
def initializable_attributes(self):
return extract(self.attributes, self.initializable_fields)
@classmethod
def before_save(cls, instance):
pass
@classmethod
def after_save(cls, instance):
pass
def save(self):
self.before_save(self)
if self.id: # if we have id already, treat this as an update
url = self.url(action='put', params=self.attributes)
response = perform_request('put', url, self.updatable_attributes())
else: # otherwise, treat this as an insert
url = self.url(action='post', params=self.attributes)
response = perform_request('post', url, self.initializable_attributes())
self.retrieved = True
self.update_attributes(**response)
self.after_save(self)
def delete(self):
url = self.url(action='delete', params=self.attributes)
response = perform_request('delete', url)
self.retrieved = True
self.update_attributes(**response)
@classmethod
def url_with_id(cls, params={}):
return cls.base_url + '/' + str(params['id'])
@classmethod
def url_without_id(cls, params={}):
return cls.base_url
@classmethod
def url(cls, action, params={}):
if cls.base_url is None:
raise CommentClientRequestError("Must provide base_url when using default url function")
if action not in cls.DEFAULT_ACTIONS:
raise ValueError("Invalid action {0}. The supported action must be in {1}".format(action, str(cls.DEFAULT_ACTIONS)))
elif action in cls.DEFAULT_ACTIONS_WITH_ID:
try:
return cls.url_with_id(params)
except KeyError:
raise CommentClientRequestError("Cannot perform action {0} without id".format(action))
else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now
return cls.url_without_id()