# Path: cliche/orm.py
# def make_repr(self):
# def get_alembic_config(engine):
# def initialize_database(engine):
# def get_database_revision(engine):
#     def get_revision(rev, context):
# def upgrade_database(engine, revision='head'):
#     def upgrade(rev, context):
#         def update_current_rev(old, new):
# def downgrade_database(engine, revision):
# def import_all_modules(dry_run=False):  # FIXME
# 
# Path: cliche/sqltypes.py
# class EnumType(TypeDecorator, SchemaType):
#     """Custom enum type to be used as :class:`enum.Enum`in Python standard
#     library. It inherits :class:`sqlalchemy.types.SchemaType` since it
#     requires schema-level DDL. PostgreSQL ENUM type defined in an Alembic
#     script must be explicitly created/dropped.
#     """
# 
#     impl = Enum
# 
#     def __init__(self, enum_class: enum.Enum, **kw):
#         if not issubclass(enum_class, enum.Enum):
#             raise TypeError('expected enum.Enum subtype')
#         super().__init__(*(m.name for m in enum_class), **kw)
#         self._enum_class = enum_class
# 
#     def process_bind_param(self, value, dialect):
#         return value.name
# 
#     def process_result_value(self, value, dialect):
#         return self._enum_class[value]
# 
#     def _set_parent(self, column):
#         self.impl._set_parent(column)
# 
#     @property
#     def python_type(self):
#         return self._enum_class
# 
# def prevent_discriminator_from_changing(col):
#     def set_discriminator(target, value, oldvalue, initiator):
#         oldvalue_is_none = (
#             oldvalue.__class__ != _symbol or oldvalue.name != 'NO_VALUE'
#         )
#         value_is_wrong = (
#             value != target.__mapper_args__['polymorphic_identity']
#         )
#         if oldvalue_is_none or value_is_wrong:
#             raise AttributeError('discriminator column cannot be changed')
# 
#     event.listen(col, 'set', set_discriminator)


import enum
from sqlalchemy.orm import foreign, relationship, remote
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.sql.functions import now
from sqlalchemy.types import Date, DateTime, Integer, String
from .name import Nameable
from .orm import Base
from .sqltypes import EnumType, prevent_discriminator_from_changing
    #: :class:`Work`\ s in which the character appeared.
    works = relationship('cliche.work.Work',
                         secondary='work_characters',
                         collection_class=set)

    __tablename__ = 'characters'
    __repr_columns__ = [id]
    __mapper_args__ = {
        'polymorphic_identity': 'characters',
    }


class Credit(Base):
    """Relationship between the work, the person, and the team.
    Describe that the person participated in making the work.
    """

    #: (:class:`int`) :class:`Work.id` of :attr:`work`.
    work_id = Column(Integer, ForeignKey('works.id'), primary_key=True)

    #: (:class:`Work`) The work which the :attr:`person` made.
    work = relationship(lambda: Work)

    #: (:class:`int`) :class:`cliche.people.Person.id` of :attr:`person`.
    person_id = Column(Integer, ForeignKey('people.id'), primary_key=True)

    #: (:class:`cliche.people.Person`) The person who made the :attr:`work`.
    person = relationship('Person')

    #: The person's role in making the work.

# Path: cliche/orm.py
# def make_repr(self):
# def get_alembic_config(engine):
# def initialize_database(engine):
# def get_database_revision(engine):
#     def get_revision(rev, context):
# def upgrade_database(engine, revision='head'):
#     def upgrade(rev, context):
#         def update_current_rev(old, new):
# def downgrade_database(engine, revision):
# def import_all_modules(dry_run=False):  # FIXME
# 
# Path: cliche/sqltypes.py
# class EnumType(TypeDecorator, SchemaType):
#     """Custom enum type to be used as :class:`enum.Enum`in Python standard
#     library. It inherits :class:`sqlalchemy.types.SchemaType` since it
#     requires schema-level DDL. PostgreSQL ENUM type defined in an Alembic
#     script must be explicitly created/dropped.
#     """
# 
#     impl = Enum
# 
#     def __init__(self, enum_class: enum.Enum, **kw):
#         if not issubclass(enum_class, enum.Enum):
#             raise TypeError('expected enum.Enum subtype')
#         super().__init__(*(m.name for m in enum_class), **kw)
#         self._enum_class = enum_class
# 
#     def process_bind_param(self, value, dialect):
#         return value.name
# 
#     def process_result_value(self, value, dialect):
#         return self._enum_class[value]
# 
#     def _set_parent(self, column):
#         self.impl._set_parent(column)
# 
#     @property
#     def python_type(self):
#         return self._enum_class
# 
# def prevent_discriminator_from_changing(col):
#     def set_discriminator(target, value, oldvalue, initiator):
#         oldvalue_is_none = (
#             oldvalue.__class__ != _symbol or oldvalue.name != 'NO_VALUE'
#         )
#         value_is_wrong = (
#             value != target.__mapper_args__['polymorphic_identity']
#         )
#         if oldvalue_is_none or value_is_wrong:
#             raise AttributeError('discriminator column cannot be changed')
# 
#     event.listen(col, 'set', set_discriminator)


# Path: cliche/work.py
import enum
from sqlalchemy.orm import foreign, relationship, remote
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.sql.functions import now
from sqlalchemy.types import Date, DateTime, Integer, String
from .name import Nameable
from .orm import Base
from .sqltypes import EnumType, prevent_discriminator_from_changing

    #: :class:`Work`\ s in which the character appeared.
    works = relationship('cliche.work.Work',
                         secondary='work_characters',
                         collection_class=set)

    __tablename__ = 'characters'
    __repr_columns__ = [id]
    __mapper_args__ = {
        'polymorphic_identity': 'characters',
    }


class Credit(Base):
    """Relationship between the work, the person, and the team.
    Describe that the person participated in making the work.
    """

    #: (:class:`int`) :class:`Work.id` of :attr:`work`.
    work_id = Column(Integer, ForeignKey('works.id'), primary_key=True)

    #: (:class:`Work`) The work which the :attr:`person` made.
    work = relationship(lambda: Work)

    #: (:class:`int`) :class:`cliche.people.Person.id` of :attr:`person`.
    person_id = Column(Integer, ForeignKey('people.id'), primary_key=True)

    #: (:class:`cliche.people.Person`) The person who made the :attr:`work`.
    person = relationship('Person')

    #: The person's role in making the work.

    role = Column(EnumType(Role, name='credits_role'),