class BaseProcessor(object):
    NAME = None

    def process_raw(self, raw_doc, **kwargs):
        pass  # pragma: no cover

    def process_normalized(self, raw_doc, normalized, **kwargs):
        pass  # pragma: no cover

@@ -1,8 +1,135 @@
+import six%0Aimport json%0Afrom abc import abstractproperty, abstractmethod%0A%0Afrom requests.structures import CaseInsensitiveDict%0A%0A%0A
 class Ba
@@ -324,28 +324,1605 @@
    pass  # pragma: no cover%0A
+%0A%0Aclass BaseHarvesterResponse(object):%0A    %22%22%22A parody of requests.response but stored in a database for caching%0A    Should reflect all methods of a response object%0A    Contains an additional field time_made, self-explanatory%0A    %22%22%22%0A%0A    class DoesNotExist(Exception):%0A        pass%0A%0A    @abstractproperty%0A    def method(self):%0A        raise NotImplementedError%0A%0A    @abstractproperty%0A    def url(self):%0A        raise NotImplementedError%0A%0A    @abstractproperty%0A    def ok(self):%0A        raise NotImplementedError%0A%0A    @abstractproperty%0A    def content(self):%0A        raise NotImplementedError%0A%0A    @abstractproperty%0A    def encoding(self):%0A        raise NotImplementedError%0A%0A    @abstractproperty%0A    def headers_str(self):%0A        raise NotImplementedError%0A%0A    @abstractproperty%0A    def status_code(self):%0A        raise NotImplementedError%0A%0A    @abstractproperty%0A    def time_made(self):%0A        raise NotImplementedError%0A%0A    @classmethod%0A    @abstractmethod%0A    def get(self, url=None, method=None):%0A        raise NotImplementedError%0A%0A    @abstractmethod%0A    def save(self):%0A        raise NotImplementedError%0A%0A    @abstractmethod%0A    def update(self, **kwargs):%0A        raise NotImplementedError%0A%0A    def json(self):%0A        try:%0A            content = self.content.decode('utf-8')%0A        except AttributeError:  # python 3eeeee!%0A            content = self.content%0A        return json.loads(content)%0A%0A    @property%0A    def headers(self):%0A        return CaseInsensitiveDict(json.loads(self.headers_str))%0A%0A    @property%0A    def text(self):%0A        return six.u(self.content)%0A

Add definition of abstract harvester model