Source code for sqlathanor.declarative._primary_key_mixin

# -*- 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.

from sqlalchemy.inspection import inspect

class PrimaryKeyMixin(object):
    """Mixin that provides functionality relating to model class primary key
    columns."""

    def _check_is_model_instance(self):
        # pylint: disable=no-self-use
        return True

    @classmethod
    def get_primary_key_columns(cls):
        """Retrieve the model's primary key columns.

        :returns: :class:`list <python:list>` of
          :class:`Column <sqlalchemy:sqlalchemy.schema.Column>` objects corresponding to
          the table's primary key(s).
        :rtype: :class:`list <python:list>` of
          :class:`Column <sqlalchemy:sqlalchemy.schema.Column>`

        """
        return inspect(cls).primary_key

    @classmethod
    def get_primary_key_column_names(cls):
        """Retrieve the column names for the model's primary key columns.

        :rtype: :class:`list <python:list>` of :class:`str <python:str>`
        """
        return [str(x.name) for x in cls.get_primary_key_columns()]

    @property
    def primary_key_value(self):
        """The instance's primary key.

        .. note::

          If not :obj:`None <python:None>`, this value can always be passed to
          :meth:`Query.get() <sqlalchemy:sqlalchemy.orm.query.Query.get>`.

        .. warning::

          Returns :obj:`None <python:None>` if the instance is pending, in a transient state, or
          does not have a primary key.

        :returns: scalar or :class:`tuple <python:tuple>` value representing the
          primary key. For a composite primary key, the order of identifiers
          corresponds to the order with which the model's primary keys were
          defined. If no primary keys are available, will return :obj:`None <python:None>`.
        :rtype: scalar / :class:`tuple <python:tuple>` / :obj:`None <python:None>`

        """
        if not inspect(self).has_identity or not inspect(self).identity:
            return None

        primary_keys = inspect(self).identity

        if len(primary_keys) == 1:
            return primary_keys[0]

        return primary_keys