deb-python-gabbi/gabbi/handlers/base.py
Ryan James Spencer ac0243df46 Add optional test param for custom content handlers (#212)
Add optional `test` param for custom content handlers

This resolves #211.

`multipart/form-data` transmission requires modifying the `Content-Type`
header with a `boundary` section identifier, and as such a custom
content handler would not have previously had access to the running test
case it was working on. This should hopefully be useful for other custom
content handlers in the future.
2017-04-02 17:37:58 +01:00

114 lines
3.7 KiB
Python

#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Base classes for response and content handlers."""
from gabbi.exception import GabbiFormatError
class ResponseHandler(object):
"""Add functionality for making assertions about an HTTP response.
A subclass may implement two methods: ``action`` and ``preprocess``.
``preprocess`` takes one argument, the ``TestCase``. It is called exactly
once for each test before looping across the assertions. It is used,
rarely, to copy the ``test.output`` into a useful form (such as a parsed
DOM).
``action`` takes two or three arguments. If ``test_key_value`` is a list
``action`` is called with the test case and a single list item. If
``test_key_value`` is a dict then ``action`` is called with the test case
and a key and value pair.
"""
test_key_suffix = ''
test_key_value = []
def __init__(self):
self._register()
def __call__(self, test):
if test.test_data[self._key]:
self.preprocess(test)
if type(self.test_key_value) != type(test.test_data[self._key]):
raise GabbiFormatError(
"%s in '%s' has incorrect type, must be %s"
% (self._key, test.test_data['name'],
type(self.test_key_value)))
for item in test.test_data[self._key]:
try:
value = test.test_data[self._key][item]
except (TypeError, KeyError):
value = None
self.action(test, item, value=value)
def preprocess(self, test):
"""Do any pre-single-test preprocessing."""
pass
def action(self, test, item, value=None):
"""Test an individual entry for this response handler.
If the entry is a key value pair the key is in item and the
value in value. Otherwise the entry is considered a single item
from a list.
"""
pass
def _register(self):
"""Register this handler on the provided test class."""
self.response_handler = None
self.content_handler = None
if self.test_key_suffix:
self._key = 'response_%s' % self.test_key_suffix
self.test_base = {self._key: self.test_key_value}
self.response_handler = self
if hasattr(self, 'accepts'):
self.content_handler = self
def __eq__(self, other):
if isinstance(other, ResponseHandler):
return self.__class__ == other.__class__
return False
def __ne__(self, other):
return not self.__eq__(other)
class ContentHandler(ResponseHandler):
"""A subclass of ResponseHandlers that adds content handling."""
@staticmethod
def accepts(content_type):
"""Return True if this handler can handler this type."""
return False
@classmethod
def replacer(cls, response_data, path):
"""Return the string that is replacing RESPONSE."""
return path
@staticmethod
def dumps(data, pretty=False, test=None):
"""Return structured data as a string.
If pretty is true, prettify.
"""
return data
@staticmethod
def loads(data):
"""Create structured (Python) data from a stream."""
return data