Source code for restpose.resource

# -*- coding: utf-8 -
#
# This file is part of the restpose python module, released under the MIT
# license.  See the COPYING file for more information.

"""
Resources for RestPose.

This module provides a convenient interface to the resources exposed via HTTP
by the RestPose server.

"""

from .version import __version__
from .errors import RestPoseError
import restkit
import json
import six
import sys

[docs]class RestPoseResponse(restkit.Response): """A response from the RestPose server. In addition to the properties exposed by :mod:`restkit:restkit.Response`, this exposes a `json` property, to decode JSON responses automatically. """ @property
[docs] def json(self): """Get the response body as JSON. :returns: The response body as a python object, decoded from JSON, if the response Content-Type was application/json. :raises: an exception if the Content-Type is not application/json, or the body is not valid JSON. :raises: :exc:`RestPoseError` if the status code returned is not one of the supplied status codes. """ ctype = self.headers.get('Content-Type') if ctype == 'application/json': return json.loads(self.body_string()) raise RestPoseError("Unexpected return content type: %s" % ctype)
[docs] def expect_status(self, *expected): """Check that the status code is one of a set of expected codes. :param expected: The expected status codes. :raises: :exc:`RestPoseError` if the status code returned is not one of the supplied status codes. """ if self.status_int not in expected: raise RestPoseError("Unexpected return status: %d" % self.status_int) return self
[docs]class RestPoseResource(restkit.Resource): """A resource providing access to a RestPose server. This may be subclassed and provided to :class:`restpose.Server`, to allow requests to be monitored or modified. For example, a logging subclass could be used to record requests and their responses. """ #: The user agent to send when making requests. user_agent = 'restpose_python/%s' % __version__ def __init__(self, uri, **client_opts): """Initialise the resource. :param uri: The full URI for the resource. :param client_opts: Any options to be passed to :class:`restkit.Resource`. """ client_opts['response_class'] = RestPoseResponse super(RestPoseResource, self).__init__(uri=uri, **client_opts)
[docs] def request(self, method, path=None, payload=None, headers=None, **params): """Perform a request. :param method: the HTTP method to use, as a string. :param path: The path to request. :param payload: A payload to send as the request body; may be a file-like object, or a string, or a structure to send encoded as a JSON object. :param headers: A dictionary of headers. If not already set, Accept and User-Agent headers will be added to this, and if there is a JSON payload, the Content-Type will be set to application/json. :param params: A dictionary of parameters to add to the request URI. """ headers = headers or {} headers.setdefault('Accept', 'application/json') headers.setdefault('User-Agent', self.user_agent) if payload is not None: if not hasattr(payload, 'read') and \ not isinstance(payload, six.string_types): payload = json.dumps(payload).encode('utf-8') headers.setdefault('Content-Type', 'application/json') try: resp = super(RestPoseResource, self).request( method, path=path, payload=payload, headers=headers, **params) except restkit.ResourceError: e = sys.exc_info()[1] # Python 2/3 compatibility # Unpack any errors which are in JSON format. msg = getattr(e, 'msg', '') msgobj = None if e.response and msg: ctype = e.response.headers.get('Content-Type') if ctype == 'application/json': msgobj = json.loads(msg) if msgobj is not None: e.msg = msgobj.get('err', '') e.msgobj = msgobj raise return resp

Project Versions