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