# Path: sqlalchemy_continuum/utils.py
# def end_tx_column_name(obj):
#     return option(obj, 'end_transaction_column_name')
# 
# def version_class(model):
#     """
#     Return the version class for given SQLAlchemy declarative model class.
# 
#     ::
# 
#         version_class(Article)  # ArticleVersion class
# 
# 
#     :param model: SQLAlchemy declarative model class
# 
#     .. seealso:: :func:`parent_class`
#     """
#     manager = get_versioning_manager(model)
#     try:
#         return manager.version_class_map[model]
#     except KeyError:
#         return model
# 
# def is_session_modified(session):
#     """
#     Return whether or not any of the versioned objects in given session have
#     been either modified or deleted.
# 
#     :param session: SQLAlchemy session object
# 
#     .. seealso:: :func:`is_versioned`
#     .. seealso:: :func:`versioned_objects`
#     """
#     return any(
#         is_modified_or_deleted(obj) for obj in versioned_objects(session)
#     )
# 
# def tx_column_name(obj):
#     return option(obj, 'transaction_column_name')
# 
# def versioned_column_properties(obj_or_class):
#     """
#     Return all versioned column properties for given versioned SQLAlchemy
#     declarative model object.
# 
#     :param obj: SQLAlchemy declarative model object
#     """
#     manager = get_versioning_manager(obj_or_class)
# 
#     cls = obj_or_class if isclass(obj_or_class) else obj_or_class.__class__
# 
#     mapper = sa.inspect(cls)
#     for key, column in mapper.columns.items():
#         # Ignores non table columns
#         if not is_table_column(column):
#             continue
# 
#         if not manager.is_excluded_property(obj_or_class, key):
#             yield getattr(mapper.attrs, key)


from copy import copy
from sqlalchemy_utils import get_primary_keys, identity
from .operation import Operations
from .utils import (
    end_tx_column_name,
    version_class,
    is_session_modified,
    tx_column_name,
    versioned_column_properties
)
import sqlalchemy as sa



class UnitOfWork(object):
    def __init__(self, manager):
        self.manager = manager
        self.reset()

    def reset(self, session=None):
        """
        Reset the internal state of this UnitOfWork object. Normally this is
        called after transaction has been committed or rolled back.
        """
        self.version_session = None
        self.current_transaction = None
        self.operations = Operations()
        self.pending_statements = []
        self.version_objs = {}

    def is_modified(self, session):
        """
        Return whether or not given session has been modified. Session has been
        modified if any versioned property of any version object in given
        session has been modified or if any of the plugins returns that
        session has been modified.

        :param session: SQLAlchemy session object
        """
        return (
            is_session_modified(session) or

# Path: sqlalchemy_continuum/utils.py
# def end_tx_column_name(obj):
#     return option(obj, 'end_transaction_column_name')
# 
# def version_class(model):
#     """
#     Return the version class for given SQLAlchemy declarative model class.
# 
#     ::
# 
#         version_class(Article)  # ArticleVersion class
# 
# 
#     :param model: SQLAlchemy declarative model class
# 
#     .. seealso:: :func:`parent_class`
#     """
#     manager = get_versioning_manager(model)
#     try:
#         return manager.version_class_map[model]
#     except KeyError:
#         return model
# 
# def is_session_modified(session):
#     """
#     Return whether or not any of the versioned objects in given session have
#     been either modified or deleted.
# 
#     :param session: SQLAlchemy session object
# 
#     .. seealso:: :func:`is_versioned`
#     .. seealso:: :func:`versioned_objects`
#     """
#     return any(
#         is_modified_or_deleted(obj) for obj in versioned_objects(session)
#     )
# 
# def tx_column_name(obj):
#     return option(obj, 'transaction_column_name')
# 
# def versioned_column_properties(obj_or_class):
#     """
#     Return all versioned column properties for given versioned SQLAlchemy
#     declarative model object.
# 
#     :param obj: SQLAlchemy declarative model object
#     """
#     manager = get_versioning_manager(obj_or_class)
# 
#     cls = obj_or_class if isclass(obj_or_class) else obj_or_class.__class__
# 
#     mapper = sa.inspect(cls)
#     for key, column in mapper.columns.items():
#         # Ignores non table columns
#         if not is_table_column(column):
#             continue
# 
#         if not manager.is_excluded_property(obj_or_class, key):
#             yield getattr(mapper.attrs, key)


# Path: sqlalchemy_continuum/unit_of_work.py
from copy import copy
from sqlalchemy_utils import get_primary_keys, identity
from .operation import Operations
from .utils import (
    end_tx_column_name,
    version_class,
    is_session_modified,
    tx_column_name,
    versioned_column_properties
)
import sqlalchemy as sa




class UnitOfWork(object):
    def __init__(self, manager):
        self.manager = manager
        self.reset()

    def reset(self, session=None):
        """
        Reset the internal state of this UnitOfWork object. Normally this is
        called after transaction has been committed or rolled back.
        """
        self.version_session = None
        self.current_transaction = None
        self.operations = Operations()
        self.pending_statements = []
        self.version_objs = {}

    def is_modified(self, session):
        """
        Return whether or not given session has been modified. Session has been
        modified if any versioned property of any version object in given
        session has been modified or if any of the plugins returns that
        session has been modified.

        :param session: SQLAlchemy session object
        """
        return (
            is_session_modified(session) or

            any(self.manager.plugins.is_session_modified(session))