Merge "Refactor Api classes to enhance consistency"

This commit is contained in:
Jenkins 2015-01-29 15:00:34 +00:00 committed by Gerrit Code Review
commit 2772f56c3c
6 changed files with 44 additions and 47 deletions

View File

@ -53,5 +53,5 @@ class TestApi(base.TestBase):
self.assertFalse(self.api.validate('test_operation', {}))
def test_invalid_operation(self):
self.assertRaises(errors.InvalidOperation, self.api.validate,
self.assertRaises(errors.InvalidAction, self.api.validate,
'super_secret_op', {})

View File

@ -22,6 +22,7 @@ from zaqar.tests import base
class TestRequest(base.TestBase):
def test_request_deserialized(self):
action = 'message_post'
data = '{"data": "tons of GBs"}'
req = request.Request(content=data)
req = request.Request(action=action, body=data)
self.assertIsInstance(req.deserialized_content, dict)

View File

@ -28,28 +28,28 @@ class Api(object):
schema = {}
validators = {}
def get_schema(self, operation):
"""Returns the schema for an operation
def get_schema(self, action):
"""Returns the schema for an action
:param operation: Operation for which params need
:param action: Action for which params need
to be validated.
:type operation: `six.text_type`
:type action: `six.text_type`
:returns: Operation's schema
:returns: Action's schema
:rtype: dict
:raises: `errors.InvalidOperation` if the operation
:raises: `errors.InvalidAction` if the action
does not exist
"""
try:
return self.schema[operation]
return self.schema[action]
except KeyError:
# TODO(flaper87): gettext support
msg = _('{0} is not a valid operation').format(operation)
raise errors.InvalidOperation(msg)
msg = _('{0} is not a valid action').format(action)
raise errors.InvalidAction(msg)
def validate(self, operation, params):
def validate(self, action, body):
"""Validates the request data
This method relies on jsonschema and exists
@ -57,25 +57,25 @@ class Api(object):
the request. It's not recommended to validate every
request since they are already validated server side.
:param operation: Operation's for which params need
:param action: Action's for which body need
to be validated.
:type operation: `six.text_type`
:param params: Params to validate
:type params: dict
:type action: `six.text_type`
:param body: Params to validate
:type body: dict
:returns: True if the schema is valid, False otherwise
:raises: `errors.InvalidOperation` if the operation
:raises: `errors.InvalidAction` if the action
does not exist
"""
if operation not in self.validators:
schema = self.get_schema(operation)
self.validators[operation] = validators.Draft4Validator(schema)
if action not in self.validators:
schema = self.get_schema(action)
self.validators[action] = validators.Draft4Validator(schema)
try:
self.validators[operation].validate(params)
except jsonschema.ValidationError:
LOG.debug('Operation is invalid.')
self.validators[action].validate(body)
except jsonschema.ValidationError as ex:
LOG.debug('Schema validation failed. %s.' % str(ex))
return False
return True

View File

@ -24,33 +24,29 @@ class Request(object):
Transport will generate a request object and send to this the API to be
processed.
:param operation: Operation to identify the API call being processed,
:param action: Action to identify the API call being processed,
i.e: 'get_queues', 'get_messages'
:type operation: str
:param content: Request's body. Default: None
:type content: str
:param params: Query string params. Default: None
:type params: dict
:type action: str
:param body: Request's body. Default: None
:type body: str
:param headers: Request headers. Default: None
:type headers: dict
:param api: Api entry point. i.e: 'queues.v1'
:type api: `six.text_type`.
"""
def __init__(self, operation='',
content=None, params=None,
headers=None, api=None):
def __init__(self, action,
body=None, headers=None, api=None):
self._api = None
self._api_mod = api
self._operation = operation
self._content = content
self._params = params or {}
self._action = action
self._body = body
self._headers = headers or {}
@decorators.lazy_property()
def deserialized_content(self):
if self._content is not None:
return json.loads(self._content)
if self._body is not None:
return json.loads(self._body)
return None

View File

@ -22,16 +22,16 @@ class Response(object):
an object out of it.
:param request: The request sent to the server.
:type: `zaqar.transport.request.Request`
:param content: Response's content
:type: `six.string_types`
:type request: `zaqar.transport.request.Request`
:param body: Response's body
:type body: `six.string_types`
:param headers: Optional headers returned in the response.
:type: dict
:type headers: dict
"""
__slots__ = ('_request', '_content', '_headers')
__slots__ = ('_request', '_body', '_headers')
def __init__(self, request, content, headers=None):
def __init__(self, request, body, headers=None):
self._request = request
self._content = content
self._body = body
self._headers = headers or {}

View File

@ -22,9 +22,9 @@ class PatternNotFound(Exception):
"""A string did not match the expected pattern or regex."""
class InvalidOperation(Exception):
"""Raised when attempted a non existent operation."""
class InvalidAction(Exception):
"""Raised when attempted a non existent action."""
class ConfigurationError(Exception):
"""An invalid value was used for a Zaqar configuration option."""
"""An invalid value was used for a Zaqar configuration option."""