class Loader(BaseLoader):
    def read_configuration(self):
def get_database_engine() -> Engine:
def get_session() -> Session:
def close_session(task_id, task, *args, **kwargs):
def get_raven_client() -> Client:
def setup_raven_logging(conf=None, **kwargs):
def report_task_failure(task_id, exception, args, kwargs,
                        traceback, einfo, sender): class Person(Nameable):
    """People i.e. artists, editors."""

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, ForeignKey(Nameable.id), primary_key=True)

    #: (:class:`datetime.date`) The date of birth.
    dob = Column(Date)

    #: (:class:`datetime.date`) The date of death.
    dod = Column(Date)

    #: (:class:`datetime.datetime`) The created time.
    created_at = Column(DateTime(timezone=True),
                        nullable=False,
                        default=now(),
                        index=True)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`TeamMembership`\ s he/she has.
    memberships = relationship('TeamMembership',
                               cascade='delete, merge, save-update',
                               collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of :class:`Team`\ s
    #: he/she belongs to.
    teams = relationship('Team',
                         secondary='team_memberships',
                         collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`cliche.work.Credit`\ s that the person has.
    credits = relationship('Credit',
                           cascade='delete, merge, save-update',
                           collection_class=set)

    __tablename__ = 'people'
    __repr_columns__ = [id]
    __mapper_args__ = {
        'polymorphic_identity': 'people',
    } class Team(Nameable):
    """Teams (including ad-hoc teams)."""

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, ForeignKey(Nameable.id), primary_key=True)

    #: (:class:`datetime.datetime`) The created time.
    created_at = Column(DateTime(timezone=True),
                        nullable=False,
                        default=now(),
                        index=True)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`TeamMembership`\ s that the team has.
    memberships = relationship('TeamMembership',
                               cascade='delete, merge, save-update',
                               collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The members :class:`Person` set.
    members = relationship(Person,
                           secondary='team_memberships',
                           collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`cliche.work.Credit`\ s in which the team was involved.
    credits = relationship('Credit', collection_class=set)

    __tablename__ = 'teams'
    __repr_columns__ = [id]
    __mapper_args__ = {
        'polymorphic_identity': 'teams',
    } class ExternalId(Base):
    """Relationship between two kinds of external works
    This class can be replaced based on the probability of equality."""

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, primary_key=True)

    #: (:class:`int`) foreignkey for works.id
    work_id = Column(Integer, ForeignKey('works.id'), nullable=False)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`cliche.work.Entity`.
    work = relationship(lambda: Work)

    #: (:class:`str`) The namespace of the trope,
    #: both namespace and name determines one trope.
    tvtropes_namespace = Column(String)

    #: (:class:`str`) The name of the trope.
    tvtropes_name = Column(String)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`cliche.services.tvtropes.entities.Entity`.
    tvtropes = relationship('cliche.services.tvtropes.entities.Entity')

    #: (:class:`str`) The namespace of the trope.
    wikipedia_id = Column(String, ForeignKey('wikipedia_entities.name'))

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`cliche.services.wikipedia.work.Entity`.
    wikipedia = relationship('cliche.services.wikipedia.work.Entity')

    __tablename__ = 'external_ids'
    __table_args__ = (
        ForeignKeyConstraint(
            [tvtropes_namespace, tvtropes_name],
            [Tvtropes.namespace, Tvtropes.name]
        ),
    ) class ClicheWikipediaEdge(Base):
    """Correspondence between Works of Cliche and Wikipedia"""

    cliche_id = Column(Integer, ForeignKey('works.id'), primary_key=True)
    cliche_work = relationship(ClicheWork)
    wikipedia_name = Column(String, ForeignKey(Entity.name), primary_key=True)
    wikipedia_work = relationship(Entity)

    confidence = Column(Float, default=0.5, index=True)

    #: (:class:`bool`) used in matching process.
    #: denote available edge in process
    available = Column(Boolean, nullable=False, default=True, index=True)

    __tablename__ = 'cliche_wikipedia_edge'
    __repr_columns__ = cliche_id, wikipedia_name, confidence class Film(Work):
    """Representation of film as an ontology."""
    PROPERTIES = Work.PROPERTIES | {'dbpedia-owl:director'}

    director = Column(String)

    __mapper_args__ = {
        'polymorphic_identity': 'film'
    }

    @classmethod
    def initialize(cls, item):
        temp = super().initialize(item)
        temp.director = item.get('director', None)
        return temp

    def get_identities():
        return 'dbpedia-owl:Film' class Entity(Base):
    """Representation of entities."""
    TYPE_PREDICATES = {}
    PROPERTIES = {
        'dbpedia-owl:wikiPageRevisionID',
        'rdfs:label',
        'dbpprop:country'
    }

    name = Column(String, primary_key=True)
    revision = Column(Integer)
    label = Column(String)
    country = Column(String)
    last_crawled = Column(DateTime(timezone=True), nullable=False)
    type = Column(String(20))

    __tablename__ = 'wikipedia_entities'
    __repr_columns__ = name, revision, label, country
    __mapper_args__ = {
        'polymorphic_on': type,
        'polymorphic_identity': 'entity'
    }

    @classmethod
    def initialize(cls, item):
        return cls(name=item.get('name', None),
                   revision=item.get('wikiPageRevisionID', None),
                   label=item.get('label',
                                  url_to_label(item.get('name', None))),
                   country=url_to_label(item.get('country', None)))

    def get_identities(ontology='Thing'):
        return 'dbpedia-owl:' + ontology class HashableLocale(Locale):
    """Hashable Locale"""

    def __hash__(self):
        return hash('{}_{}'.format(self.language, self.territory)) def setup_sentry():
def get_sentry() -> Sentry:
def index():
def check_login_status():
def template_processor():
def add_login_header(response): class Character(Nameable):
    """Fictional character that appears in creative work."""

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, ForeignKey(Nameable.id), primary_key=True)

    #: (:class:'int') :class:`Character.id` of :attr:`original_character`.
    original_character_id = Column(Integer, ForeignKey('characters.id'))

    #: (:class:'Character') The original character from which this character
    #: is derived.
    original_character = relationship(
        'Character',
        primaryjoin=foreign(original_character_id) == remote(id)
    )

    #: (:class:'collections.abc.MutableSet') The set of :class:`Character`\ s
    #: which is derived from this character
    derived_characters = relationship(
        'Character',
        primaryjoin=remote(original_character_id) == id,
        collection_class=set
    )

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :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'),
                  primary_key=True, default=Role.unknown)

    #: (:class:`int`) :class:`Team.id` of :attr:`team`. (optional)
    team_id = Column(Integer, ForeignKey('teams.id'))

    #: The team which the person belonged when work had been made.
    team = relationship('Team')

    #: (:class:`datetime.datetime`) The date and time on which
    #: the record was created.
    created_at = Column(DateTime(timezone=True), nullable=False,
                        default=now())

    __tablename__ = 'credits'
    __repr_columns__ = person_id, work_id, role, team_id class Franchise(Nameable):
    """Multimedia franchise that is a franchise for which installments
    exist in multiple forms of media, such as books, comic books, and films,
    for example *The Lord of the Rings* and *Iron Man*.
    """

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, ForeignKey(Nameable.id), primary_key=True)

    #: (:class:`int`) :class:`World.id` of :attr:`world`.
    world_id = Column(Integer, ForeignKey('worlds.id'))

    #: (:class:`World`) The world which the franchise belongs to.
    world = relationship('World', foreign_keys=[world_id])

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`WorkFranchise`\ s that the franchise has.
    work_franchises = relationship('WorkFranchise',
                                   cascade='delete, merge, save-update',
                                   collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Work`\ s that belongs to the franchise.
    works = relationship(lambda: Work,
                         secondary='work_franchises',
                         collection_class=set)

    #: (:class:`datetime.datetime`) The date and time on which
    #: the record was created.
    created_at = Column(DateTime(timezone=True), nullable=False,
                        default=now())

    __tablename__ = 'franchises'
    __repr_columns__ = [id]
    __mapper_args__ = {
        'polymorphic_identity': 'franchises',
    } class Genre(Base):
    """Genre of the creative work"""

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, primary_key=True)

    #: (:class:`str`) The name of the genre.
    name = Column(String, nullable=False, index=True)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`WorkGenre`\ s that the genre has.
    work_genres = relationship('WorkGenre',
                               cascade='delete, merge, save-update',
                               collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Work`\ s that fall into the genre.
    works = relationship(lambda: Work,
                         secondary='work_genres',
                         collection_class=set)

    #: (:class:`datetime.datetime`) The date and time on which
    #: the record was created.
    created_at = Column(DateTime(timezone=True),
                        nullable=False,
                        default=now(),
                        index=True)

    __tablename__ = 'genres'
    __repr_columns__ = id, name class Role(enum.Enum):
    """Python enum type to describe role of him/her in making a work."""

    artist = 'artist'
    author = 'author'
    director = 'director'
    editor = 'editor'
    unknown = 'unknown' class Trope(Base):  # FIXME: Temporary, It not extend Nameable.
    """Tropes"""

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, primary_key=True)

    #: (:class:`str`) Trope name
    name = Column(String, nullable=False)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`WorkTrope`.
    work_tropes = relationship('WorkTrope',
                               cascade='delete, merge, save-update',
                               collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Work`.
    works = relationship(lambda: Work, secondary='work_tropes',
                         collection_class=set)

    __tablename__ = 'tropes'
    __repr_columns__ = id, name class Work(Nameable):
    """Creative work(s) that could be a single work like a film, or
    a series of works such as a combic book series and a television series.
    """

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, ForeignKey(Nameable.id), primary_key=True)

    #: (:class:`str`) Work media type.
    media_type = Column(String, nullable=False)

    #: (:class:`datetime.date`) The publication date.
    published_at = Column(Date)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`WorkGenre`\ s that the work has.
    work_genres = relationship('WorkGenre',
                               cascade='delete, merge, save-update',
                               collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Genre`\ s that the work falls into.
    genres = relationship(Genre,
                          secondary='work_genres',
                          collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Credit`\ s that the work has.
    credits = relationship(Credit,
                           cascade='delete, merge, save-update',
                           collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`WorkFranchise`\ s that the work has.
    work_franchises = relationship('WorkFranchise',
                                   cascade='delete, merge, save-update',
                                   collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Franchise`\ s that the work belongs to.
    franchises = relationship(Franchise,
                              secondary='work_franchises',
                              collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Character`\ s that appeared in the work.
    characters = relationship(Character,
                              secondary='work_characters',
                              collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`WorkTrope`.
    work_tropes = relationship(lambda: WorkTrope,
                               cascade='delete, merge, save-update',
                               collection_class=set)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Trope`.
    tropes = relationship(Trope, secondary='work_tropes',
                          collection_class=set)

    #: (:class:`datetime.datetime`) The date and time on which
    #: the record was created.
    created_at = Column(DateTime(timezone=True),
                        nullable=False,
                        default=now(),
                        index=True)

    __tablename__ = 'works'
    __repr_columns__ = [id]
    __mapper_args__ = {
        'polymorphic_identity': 'works',
    } class World(Nameable):
    """Fictional universe that is a self-consistent fictional setting
    with elements that differ from the real world,
    for example *Middle-earth* and *Marvel Cinematic Universe*.
    """

    #: (:class:`int`) The primary key integer.
    id = Column(Integer, ForeignKey(Nameable.id), primary_key=True)

    #: (:class:`collections.abc.MutableSet`) The set of
    #: :class:`Franchise`\ s that belong the world.
    franchises = relationship(Franchise,
                              foreign_keys=[id],
                              collection_class=set)

    #: (:class:`datetime.datetime`) The date and time on which
    #: the record was created.
    created_at = Column(DateTime(timezone=True), nullable=False,
                        default=now())

    __tablename__ = 'worlds'
    __repr_columns__ = [id]
    __mapper_args__ = {
        'polymorphic_identity': 'worlds',
    } DEFAULT_DATABASE_URL = 'sqlite://' @contextlib.contextmanager
def get_session(database_url=None, echo_sql=False):
    engine = get_engine(database_url, echo=echo_sql)
    try:
        metadata = Base.metadata
        metadata.drop_all(bind=engine)
        metadata.create_all(bind=engine)
        session = Session(bind=engine)
        yield session
        session.rollback()
        metadata.drop_all(bind=engine)
    finally:
        engine.dispose()
import datetime
import os
import pathlib
import types
from click.testing import CliRunner
from pytest import fixture, skip, yield_fixture
from sqlalchemy.sql.functions import now
from yaml import dump
from cliche.celery import app as celery_app
from cliche.name import Name
from cliche.people import Person, Team
from cliche.services.align import ExternalId
from cliche.services.wikipedia.work import ClicheWikipediaEdge, Film
from cliche.services.wikipedia.work import Entity as WikipediaEntity
from cliche.services.tvtropes.entities import ClicheTvtropesEdge, Entity
from cliche.sqltypes import HashableLocale as Locale
from cliche.web.app import app
from cliche.work import (Character, Credit, Franchise, Genre, Role,
                         Trope, Work, World)
from .db import DEFAULT_DATABASE_URL, get_session

    def __iadd__(self, module):
        for name in dir(module):
            if not name.startswith('_'):
                setattr(self, name, getattr(module, name))
        return self


@fixture
def fx_people(fx_session):
    """create people: four artists and Peter Jackson"""
    f = FixtureModule('fx_people')

    # create four artists of 'CLAMP' team
    f.clamp_member_1 = Person(dob=datetime.date(1967, 5, 2))
    f.clamp_member_1.names.update({
        Name(nameable=f.clamp_member_1,
             name='Nanase Ohkawa',
             locale=Locale.parse('en_US'))
    })
    fx_session.add(f.clamp_member_1)
    f.clamp_member_2 = Person(dob=datetime.date(1968, 6, 16))
    f.clamp_member_2.names.update({
        Name(nameable=f.clamp_member_2,
             name='Mokona',
             locale=Locale.parse('en_US'))
    })
    fx_session.add(f.clamp_member_2)
    f.clamp_member_3 = Person(dob=datetime.date(1969, 1, 21))
    f.clamp_member_3.names.update({
        Name(nameable=f.clamp_member_3,
             name='Tsubaki Nekoi',
             locale=Locale.parse('en_US'))
    })
    fx_session.add(f.clamp_member_3)
    f.clamp_member_4 = Person(dob=datetime.date(1969, 2, 8))
    f.clamp_member_4.names.update({
        Name(nameable=f.clamp_member_4,
             name='Satsuki Igarashi',
             locale=Locale.parse('en_US'))
    })
    fx_session.add(f.clamp_member_4)

    # create 'Peter Jackson'
    f.peter_jackson = Person(dob=datetime.date(1961, 10, 31))
    f.peter_jackson.names.update({
        Name(nameable=f.peter_jackson,
             name='Peter Jackson',
             locale=Locale.parse('en_US'))
    })
    fx_session.add(f.peter_jackson)

    fx_session.flush()
    return f


@fixture
def fx_teams(fx_session, fx_people):
    """create teams: CLAMP which consists of the four artists"""
    f = FixtureModule('fx_teams')
    f += fx_people

    # create 'CLAMP' team
    f.clamp = Team()
    f.clamp.names.update({
        Name(nameable=f.clamp,
             name='CLAMP',
             locale=Locale.parse('en_US'))
    })
    f.clamp.members.update({f.clamp_member_1,
                            f.clamp_member_2,
                            f.clamp_member_3,
                            f.clamp_member_4})
    fx_session.add(f.clamp)

    fx_session.flush()
    return f


@fixture
def fx_genres(fx_session):
    """create genres: Comic and Romance"""
    f = FixtureModule('fx_genres')
    f.session = fx_session

    # create 'Comic' genre
    f.comic = Genre(name='Comic')
    fx_session.add(f.comic)

    # create 'Romance' genre
    f.romance = Genre(name='Romance')
    fx_session.add(f.romance)
    fx_session.flush()
    return f


@fixture
def fx_external_ids(fx_session):
    f = FixtureModule('fx_external_ids')

    f.jane_eyre = Work()
    f.jane_eyre.names.update({
        Name(nameable=f.jane_eyre,
             name='jane eyre',
             locale=Locale.parse('en_US'))
    })

    f.jane_eyre_wikipedia = WikipediaEntity(
        name='http://dbpedia.org/resource/Jane_Eyre',
        revision=606655259,
        label='Jane Eyre',
        country='England',
        last_crawled=now(),
        type='book',
    )

    f.jane_eyre_ex = ExternalId(
        work_id=f.jane_eyre.id,
        work=f.jane_eyre,
        wikipedia_id=f.jane_eyre_wikipedia.name,

        wikipedia=WikipediaEntity,