Permalink
Browse files

Merge branch 'api'

  • Loading branch information...
2 parents ff35771 + 6e5f4d1 commit 7354a998da1adee3efb218e609f30cb355ec2449 @smacleod smacleod committed Feb 1, 2013
View
@@ -2,6 +2,7 @@ Lead Developers:
* Christian Hammond
* David Trowbridge
+ * Steven MacLeod
Contributors:
@@ -34,6 +35,7 @@ Contributors:
* Jan Koprowski
* Jason Felice
* Jeremy Bettis
+ * John Sintal
* Karsten Verelst
* Laurent Nicolas
* Lepton Wu
View
@@ -0,0 +1,15 @@
+from rbtools.api.transport.sync import SyncTransport
+
+
+class RBClient(object):
+ """Entry point for accessing RB resources through the web API.
+
+ By default the synchronous transport will be used. To use a
+ different transport, provide the transport class in the
+ 'transport_cls' parameter.
+ """
+ def __init__(self, url, transport_cls=SyncTransport, *args, **kwargs):
+ self._transport = transport_cls(url, *args, **kwargs)
+
+ def get_root(self, *args, **kwargs):
+ return self._transport.get_root(*args, **kwargs)
View
@@ -0,0 +1,46 @@
+import json
+
+from rbtools.api.utils import parse_mimetype
+
+
+DECODER_MAP = {}
+
+
+def DefaultDecoder(payload):
+ """Default decoder for API payloads.
+
+ The default decoder is used when a decoder is not found in the
+ DECODER_MAP. This will stick the body of the response into the
+ 'data' field.
+ """
+ return {
+ 'resource': {
+ 'data': payload,
+ },
+ }
+
+DEFAULT_DECODER = DefaultDecoder
+
+
+def JsonDecoder(payload):
+ return json.loads(payload)
+
+DECODER_MAP['application/json'] = JsonDecoder
+
+
+def decode_response(payload, mime_type):
+ """Decode a Web API response.
+
+ The body of a Web API response will be decoded into a dictionary,
+ according to the provided mime_type.
+ """
+ mime = parse_mimetype(mime_type)
+
+ format = '%s/%s' % (mime['main_type'], mime['format'])
+
+ if format in DECODER_MAP:
+ decoder = DECODER_MAP[format]
+ else:
+ decoder = DEFAULT_DECODER
+
+ return decoder(payload)
View
@@ -15,3 +15,26 @@ def __str__(self):
return '%s (%s)' % (self.rsp['err']['msg'], code_str)
else:
return code_str
+
+
+class AuthorizationError(APIError):
+ pass
+
+
+class ServerInterfaceError(Exception):
+ def __init__(self, msg, *args, **kwargs):
+ Exception.__init__(self, *args, **kwargs)
+ self.msg = msg
+
+ def __str__(self):
+ return self.msg
+
+
+API_ERROR_TYPE = {
+ 401: AuthorizationError,
+}
+
+
+def create_api_error(http_status, *args, **kwargs):
+ error_type = API_ERROR_TYPE.get(http_status, APIError)
+ return error_type(http_status, *args, **kwargs)
View
@@ -0,0 +1,47 @@
+from rbtools.api.resource import CountResource, \
+ ResourceItem, \
+ ResourceList, \
+ RESOURCE_MAP
+from rbtools.api.utils import rem_mime_format
+
+
+SPECIAL_KEYS = set(('links', 'total_results', 'stat', 'count'))
+
+
+def create_resource(payload, url, mime_type=None, item_mime_type=None,
+ guess_token=True):
+ """Construct and return a resource object.
+
+ The mime type will be used to find a resource specific base class.
+ Alternatively, if no resource specific base class exists, one of
+ the generic base classes, Resource or ResourceList, will be used.
+
+ If an item mime type is provided, it will be used by list
+ resources to construct item resources from the list.
+
+ If 'guess_token' is True, we will try and guess what key the
+ resources body lives under. If False, we assume that the resource
+ body is the body of the payload itself. This is important for
+ constructing Item resources from a resource list.
+ """
+
+ # Determine the key for the resources data.
+ token = None
+
+ if guess_token:
+ other_keys = set(payload.keys()).difference(SPECIAL_KEYS)
+ if len(other_keys) == 1:
+ token = other_keys.pop()
+
+ # Select the base class for the resource.
+ if 'count' in payload:
+ resource_class = CountResource
+ elif mime_type and rem_mime_format(mime_type) in RESOURCE_MAP:
+ resource_class = RESOURCE_MAP[rem_mime_format(mime_type)]
+ elif token and isinstance(payload[token], list):
+ resource_class = ResourceList
+ else:
+ resource_class = ResourceItem
+
+ return resource_class(payload, url, token=token,
+ item_mime_type=item_mime_type)
Oops, something went wrong.

0 comments on commit 7354a99

Please sign in to comment.