1from sqlalchemy import engine_from_config
2from sqlalchemy.orm import sessionmaker
3from sqlalchemy.orm import configure_mappers
4import zope.sqlalchemy
5
6# import or define all models here to ensure they are attached to the
7# Base.metadata prior to any initialization routines
8from .page import Page  # noqa
9from .user import User  # noqa
10
11# run configure_mappers after defining all of the models to ensure
12# all relationships can be setup
13configure_mappers()
14
15
16def get_engine(settings, prefix='sqlalchemy.'):
17    return engine_from_config(settings, prefix)
18
19
20def get_session_factory(engine):
21    factory = sessionmaker()
22    factory.configure(bind=engine)
23    return factory
24
25
26def get_tm_session(session_factory, transaction_manager):
27    """
28    Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
29
30    This function will hook the session to the transaction manager which
31    will take care of committing any changes.
32
33    - When using pyramid_tm it will automatically be committed or aborted
34      depending on whether an exception is raised.
35
36    - When using scripts you should wrap the session in a manager yourself.
37      For example::
38
39          import transaction
40
41          engine = get_engine(settings)
42          session_factory = get_session_factory(engine)
43          with transaction.manager:
44              dbsession = get_tm_session(session_factory, transaction.manager)
45
46    """
47    dbsession = session_factory()
48    zope.sqlalchemy.register(
49        dbsession, transaction_manager=transaction_manager)
50    return dbsession
51
52
53def includeme(config):
54    """
55    Initialize the model for a Pyramid app.
56
57    Activate this setup using ``config.include('tutorial.models')``.
58
59    """
60    settings = config.get_settings()
61
62    # use pyramid_tm to hook the transaction lifecycle to the request
63    config.include('pyramid_tm')
64
65    session_factory = get_session_factory(get_engine(settings))
66    config.registry['dbsession_factory'] = session_factory
67
68    # make request.dbsession available for use in Pyramid
69    config.add_request_method(
70        # r.tm is the transaction manager used by pyramid_tm
71        lambda r: get_tm_session(session_factory, r.tm),
72        'dbsession',
73        reify=True
74    )
75