Source code for sqlathanor.automap

# -*- coding: utf-8 -*-

# The lack of a module docstring for this module is **INTENTIONAL**.
# The module is imported into the documentation using Sphinx's autodoc
# extension, and its member function documentation is automatically incorporated
# there as needed.

import sqlalchemy

try:
    from sqlalchemy.ext.automap import automap_base as SA_automap_base
    SUPPORTS_AUTOMAP = True
except ImportError:
    SUPPORTS_AUTOMAP = False
    SA_automap_base = bool

from validator_collection import checkers

from sqlathanor import BaseModel
from sqlathanor.errors import SQLAlchemySupportError


[docs]def automap_base(declarative_base = None, **kwargs): """Produce a declarative automap base. This function produces a new base class that is a product of the :class:`AutomapBase <sqlalchemy:sqlalchemy.ext.automap.AutomapBase>` class as well as a declarative base that you supply. If no declarative base is supplied, then the **SQLAthanor** default :class:`BaseModel <sqlathanor.declarative.BaseModel>` will be used, to provide serialization/de-serialization support to the resulting automapped base class. :param declarative_base: The declarative base class that is to be combined with the :class:`AutomapBase <sqlalchemy:sqlalchemy.ext.automap.AutomapBase>` class to construct the resulting automapped :term:`model class`. To ensure that **SQLAthanor** :term:`serialization`/:term:`de-serialization` functionality is provided to your automapped model class, make sure that the value provided is produced by :func:`sqlathanor.declarative_base() <sqlathanor.declarative.declarative_base>` or otherwise inherits from :class:`sqlathanor.declarative.BaseModel`. If ``None``, will default to :class:`sqlathanor.declarative.BaseModel`. :type declarative_base: The declarative base model to combine with the automapped :term:`model class` produced. :param kwargs: Passed to :func:`declarative_base() <sqlalchemy:sqlalchemy.ext.declarative.declarative_base>` :type kwargs: keyword arguments :returns: A :class:`AutomapBase <sqlalchemy:sqlalchemy.ext.automap.AutomapBase>` that can reflect your database schema structure with auto-generated declarative models that support **SQLAthanor** serialization/de-serialization. :rtype: :class:`AutomapBase <sqlalchemy:sqlalchemy.ext.automap.AutomapBase>` :raises SQLAlchemySupportError: if called in an environment where `SQLAlchemy`_ is installed with a version less than 0.9.1 (which introduces automap support). """ # pylint: disable=redefined-variable-type if not SUPPORTS_AUTOMAP: raise SQLAlchemySupportError( 'automap is only available in SQLAlchemy v.0.9.1 and higher, ' + \ 'but you are using %s. Please upgrade.' % sqlalchemy.__version__ ) if declarative_base is None: cls = BaseModel elif isinstance(declarative_base, BaseModel) or declarative_base == BaseModel: cls = declarative_base elif isinstance(declarative_base, tuple): for item in declarative_base: if item == BaseModel or isinstance(item, BaseModel): cls = declarative_base break else: cls = kwargs.pop('cls', None) if cls is None and checkers.is_iterable(declarative_base): class_list = [BaseModel] class_list.extend([x for x in declarative_base]) elif cls is None and not checkers.is_iterable(declarative_base): class_list = [BaseModel, declarative_base] elif checkers.is_iterable(cls) and checkers.is_iterable(declarative_base): class_list = [BaseModel] class_list.extend([x for x in cls]) class_list.extend([x for x in declarative_base]) elif cls is not None and checkers.is_iterable(declarative_base): class_list = [BaseModel, cls] class_list.extend([x for x in declarative_base]) elif cls is not None and not checkers.is_iterable(declarative_base): class_list = [BaseModel, cls, declarative_base] for item in class_list[1:]: if item == BaseModel or isinstance(item, BaseModel): class_list = class_list[1:] break cls = tuple(x for x in class_list) automapped_base = SA_automap_base(declarative_base = cls, **kwargs) return automapped_base