import abc
from ..compat import add_metaclass

_session_factory = None


@add_metaclass(abc.ABCMeta)
class SQLResource(object):
    """Base class for resources based on SQLAlchemy ORM models.
    """

    @abc.abstractproperty
    def context_query(self):
        """A SQLAlchemy query which is used to find a SQLAlchemy object.
        """
        raise NotImplemented()

    def __init__(self, request):
        global _session_factory
        assert _session_factory is not None, \
                "config.set_sqlalchemy_session_factory must be called."
        params = request.matchdict
        self.context = _session_factory.execute(self.context_query, params).first()
        if self.context is None:
            raise KeyError('Resource not found')


def set_sqlalchemy_session_factory(config, sql_session_factory):
    """Configure the SQLAlchemy session factory.

    This function should not be used directly, but as a method if the
    ``config`` object.

    .. code-block:: python

       config.set_sqlalchemy_session_factory(DBSession)

    This function must be called if you use SQL resources. If you forget to do
    this any attempt to access a SQL resource will trigger an assertion
    exception.

    :param sql_session_factory: A factory function to return a SQLAlchemy
        session. This is generally a :ref:`scoped_session
        <sqlalchemy:sqlalchemy.orm.scoping.scoped_session>` instance, and
        commonly called ``Session`` or ``DBSession``.
    """
    global _session_factory
    _session_factory = sql_session_factory


def includeme(config):
    """Configure SQLAlchemy integration.

    You should not call this function directly, but use
    :py:func:`pyramid.config.Configurator.include` to initialise the REST
    toolkit. After you have done this you must call
    :py:func:`config.set_sqlalchemy_session_factory` to register your
    SQLALchemy session factory.

    .. code-block:: python

       config = Configurator()
       config.include('rest_toolkit')
       config.set_sqlalchemy_session_factory(DBSession)
    """
    config.add_directory('set_sqlalchemy_session_factory',
            set_sqlalchemy_session_factory)

@@ -38,16 +38,164 @@
 etaclass
+%0Afrom ..abc import DeletableResource%0Afrom ..abc import EditableResource%0Afrom ..abc import ViewableResource%0Afrom sqlalchemy.orm import object_session
 %0A%0A_sessi
@@ -260,22 +260,69 @@
 esource(
-object
+DeletableResource, EditableResource, ViewableResource
 ):%0A    %22
@@ -947,16 +947,644 @@
 ound')%0A%0A
+    def to_dict(self):%0A        data = %7B%7D%0A        columns = self.context_query._primary_entity.entity_zero.columns%0A        for column in columns:%0A            data%5Bcolumn%5D = getattr(self.context, column)%0A        return data%0A%0A    def update_from_dict(self, data, partial=False):%0A        columns = self.context_query._primary_entity.entity_zero.columns%0A        for column in columns:%0A            if partial:%0A                setattr(self.context, column, data.get(column))%0A            else:%0A                setattr(self.context, column, data%5Bcolumn%5D)%0A%0A    def delete(self):%0A        object_session(self.context).delete(self.context)%0A%0A
 %0Adef set

Implement ABCs for SQLResource