Source code for connexion_sql_utils.base_mixin_abc

# -*- coding: utf-8 -*-
"""
base_mixin_abc.py
~~~~~~~~~~~~~~~~~

This module contains an abc class that can be used to check that the
correct interface is defined to use the ``crud`` methods.  Nothing
actually inherits from this class as it breaks when making an
``sqlalchemy.ext.declarative:declarative_base``, but it is helpful
for ``issubclass`` and ``isinstance`` checks.


When inheriting from this package's :class:`BaseMixin` then one only
needs to implement a ``session_maker`` method.


"""
import abc
import contextlib


def _check_mro(Cls, key) -> bool:
    """Helper to check the mro for a class for the given method/attribute name

    :param Cls:  The class to check
    :param key:  The attribute name to check for in the ``__mro__``

    """
    check = any(key in Base.__dict__ for Base in Cls.__mro__ if
                hasattr(Base, '__dict__'))
    return check


[docs]class BaseMixinABC(metaclass=abc.ABCMeta): """Used to test validity of a mixin. The mixin can not directly inherit from this abc class because of inheritance conflicts with sqlalchemy's declarative base class, however if a mixin declares all the required methods, then it will pass an ``isinstance`` or an ``issubclass`` check. The mixin in this package declares all of the methods except the ``session_maker`` method which should be implemented once you create a ``sqlalchemy.orm.sessionmaker`` Example:: engine = create_engine(DB_URI) session = scoped_session(sessionmaker(bind=engine)) class MyBase(BaseMixin): @staticmethod def session_maker(): return session() DbModel = declarative_base(cls=MyBase) assert issubclass(DbModel, BaseMixinABC) # True Then all of your sqlalchemy models could inherit from the ``DbModel``. """ @staticmethod @abc.abstractmethod
[docs] def session_maker(): # pragma: no cover """Return an :class:`sqlalchemy.orm.Session` to be used in the other methods. """ pass
@classmethod @abc.abstractmethod
[docs] def query_by(cls, **kwargs): # pragma: no cover """Query the database model with the given criteria. This is used as you would use ``filter_by`` on an sqlalchemy query. And should always return a list of items. """ pass
@classmethod @abc.abstractmethod
[docs] def get_id(cls, id): # pragma: no cover """Query the database for a single item by it's unique id. """ pass
@abc.abstractmethod
[docs] def save(self): # pragma: no cover """Save an instance to the database. """ pass
@abc.abstractmethod
[docs] def update(self, **kwargs): # pragma: no cover """Update an instance's attributes and save to the database. """ pass
@abc.abstractmethod
[docs] def delete(self): # pragma: no cover """Delete an instance from the database. """ pass
@abc.abstractmethod
[docs] def dump(self): # pragma: no cover """Return a json representation of the instance. This is also used as the str() representation of an instance. """ pass
@abc.abstractmethod def _asDict(self): # pragma: no cover """Create a dict representation of an instance, this is typically used to create the json representation. """ pass @classmethod @contextlib.contextmanager @abc.abstractmethod
[docs] def session_scope(cls): # pragma: no cover """A context manager for a session, should yield a :class:`sqlalchemy.orm.Session` """ yield
def __str__(self) -> str: """Return a json representation. """ return self.dump() @classmethod def __subclasshook__(cls, Cls): if cls is BaseMixinABC: check_keys = ('query_by', 'get_id', 'delete', 'update', 'save', 'session_scope', '_asDict', 'dump', 'session_maker') if all(map(lambda x: _check_mro(Cls, x), check_keys)): return True return NotImplemented