Authomatic
is an authorization / authentication
client library for Python web applications
inspired by Alex Vagin’s Simpleauth.
In fact, I almost named it Deadsimpleauth,
but that name would be too long
for a succinct library.

- Tweet

# Source code for authomatic.adapters

    # -*- coding: utf-8 -*-
    """
    Adapters
    --------

    .. contents::
       :backlinks: none

    The :func:`authomatic.login` function needs access to functionality like
    getting the **URL** of the handler where it is being called, getting the **request params** and **cookies** and
    **writing the body**, **headers** and **status** to the response.

    Since implementation of these features varies across Python web frameworks,
    the Authomatic library uses **adapters** to unify these differences into a single interface.

    Available Adapters
    ^^^^^^^^^^^^^^^^^^

    If you are missing an adapter for the framework of your choice,
    please open an `enhancement issue <https://github.com/peterhudec/authomatic/issues>`_
    or consider a contribution to this module by :ref:`implementing <implement_adapters>` one by yourself.
    Its very easy and shouldn't take you more than a few minutes.

    .. autoclass:: DjangoAdapter
        :members:

    .. autoclass:: Webapp2Adapter
        :members:

    .. autoclass:: WebObAdapter
        :members:

    .. autoclass:: WerkzeugAdapter
        :members:

    .. _implement_adapters:

    Implementing an Adapter
    ^^^^^^^^^^^^^^^^^^^^^^^

    Implementing an adapter for a Python web framework is pretty easy.

    Do it by subclassing the :class:`.BaseAdapter` abstract class.
    There are only **six** members that you need to implement.

    Moreover if your framework is based on the |webob|_ or |werkzeug|_ package
    you can subclass the :class:`.WebObAdapter` or :class:`.WerkzeugAdapter` respectively.

    .. autoclass:: BaseAdapter
        :members:

    """

    import abc
    from authomatic.core import Response

    class BaseAdapter(object):
        """
        Base class for platform adapters

        Defines common interface for WSGI framework specific functionality.
        """

        __metaclass__ = abc.ABCMeta

        @abc.abstractproperty
        def params(self):
            """
            Must return a :class:`dict` of all request parameters of any HTTP method.

            :returns:
                :class:`dict`
            """

        @abc.abstractproperty
        def url(self):
            """
            Must return the url of the actual request including path but without query and fragment

            :returns:
                :class:`str`
            """

        @abc.abstractproperty
        def cookies(self):
            """
            Must return cookies as a :class:`dict`.

            :returns:
                :class:`dict`
            """

        @abc.abstractmethod
        def write(self, value):
            """
            Must write specified value to response.

            :param str value:
                String to be written to response.
            """

        @abc.abstractmethod
        def set_header(self, key, value):
            """
            Must set response headers to ``Key: value``.

            :param str key:
                Header name.

            :param str value:
                Header value.
            """

        @abc.abstractmethod
        def set_status(self, status):
            """
            Must set the response status e.g. ``'302 Found'``.

            :param str status:
                The HTTP response status.
            """

    class DjangoAdapter(BaseAdapter):
        """
        Adapter for the |django|_ framework.
        """

        def __init__(self, request, response):
            """
            :param request:
                An instance of the :class:`django.http.HttpRequest` class.

            :param response:
                An instance of the :class:`django.http.HttpResponse` class.
            """
            self.request = request
            self.response = response

        @property
        def params(self):
            return dict(self.request.REQUEST)

        @property
        def url(self):
            return self.request.build_absolute_uri(self.request.path)

        @property
        def cookies(self):
            return dict(self.request.COOKIES)

        def write(self, value):
            self.response.write(value)

        def set_header(self, key, value):
            self.response[key] = value

        def set_status(self, status):
            self.response.status_code = status

    class WebObAdapter(BaseAdapter):
        """Adapter for the |webob|_ package."""

        def __init__(self, request, response):
            """
            :param request:
                A |webob|_ :class:`Request` instance.

            :param response:
                A |webob|_ :class:`Response` instance.
            """
            self.request = request
            self.response = response

        #===========================================================================
        # Request
        #===========================================================================

        @property
        def url(self):
            return self.request.path_url

        @property
        def params(self):
            return dict(self.request.params)

        @property
        def cookies(self):
            return dict(self.request.cookies)

        #===========================================================================
        # Response
        #===========================================================================

        def write(self, value):
            self.response.write(value)

        def set_header(self, key, value):
            self.response.headers[key] = str(value)

        def set_status(self, status):
            self.response.status = status

    class Webapp2Adapter(WebObAdapter):
        """
        Adapter for the |webapp2|_ framework.

        Inherits from the :class:`.WebObAdapter`.
        """

        def __init__(self, handler):
            """
            :param handler:
                A :class:`webapp2.RequestHandler` instance.
            """
            self.request = handler.request
            self.response = handler.response

    class WerkzeugAdapter(BaseAdapter):
        """
        Adapter for |flask|_ and other |werkzeug|_ based frameworks.

        Thanks to `Mark Steve Samson <http://marksteve.com>`_.
        """

        @property
        def params(self):
            return self.request.args

        @property
        def url(self):
            return self.request.base_url

        @property
        def cookies(self):
            return self.request.cookies

        def __init__(self, request, response):
            """
            :param request:
                Instance of the :class:`werkzeug.wrappers.Request` class.

            :param response:
                Instance of the :class:`werkzeug.wrappers.Response` class.
            """

            self.request = request
            self.response = response

        def write(self, value):
            self.response.data += value

        def set_header(self, key, value):
            self.response.headers[key] = value

        def set_status(self, status):
            self.response.status = status