1
|
|
|
# -*- coding: utf-8 -*- |
|
|
|
|
2
|
|
|
from sqlalchemy import engine_from_config |
3
|
|
|
from sqlalchemy.event import listen |
4
|
|
|
from sqlalchemy.orm import sessionmaker |
5
|
|
|
from sqlalchemy.orm import configure_mappers |
6
|
|
|
import zope.sqlalchemy |
7
|
|
|
from .meta import DeclarativeBase |
8
|
|
|
from .revision_protection import prevent_content_revision_delete |
9
|
|
|
# import or define all models here to ensure they are attached to the |
10
|
|
|
# Base.metadata prior to any initialization routines |
11
|
|
|
from tracim.models.auth import User, Group, Permission |
|
|
|
|
12
|
|
|
from tracim.models.data import Content, ContentRevisionRO |
|
|
|
|
13
|
|
|
|
14
|
|
|
# run configure_mappers after defining all of the models to ensure |
15
|
|
|
# all relationships can be setup |
16
|
|
|
configure_mappers() |
17
|
|
|
|
18
|
|
|
|
19
|
|
|
def get_engine(settings, prefix='sqlalchemy.'): |
|
|
|
|
20
|
|
|
return engine_from_config(settings, prefix) |
21
|
|
|
|
22
|
|
|
|
23
|
|
|
def get_session_factory(engine): |
|
|
|
|
24
|
|
|
factory = sessionmaker(expire_on_commit=False) |
25
|
|
|
factory.configure(bind=engine) |
26
|
|
|
return factory |
27
|
|
|
|
28
|
|
|
|
29
|
|
|
def get_tm_session(session_factory, transaction_manager): |
30
|
|
|
""" |
31
|
|
|
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction. |
32
|
|
|
|
33
|
|
|
This function will hook the _session to the transaction manager which |
34
|
|
|
will take care of committing any changes. |
35
|
|
|
|
36
|
|
|
- When using pyramid_tm it will automatically be committed or aborted |
37
|
|
|
depending on whether an exception is raised. |
38
|
|
|
|
39
|
|
|
- When using scripts you should wrap the _session in a manager yourself. |
40
|
|
|
For example:: |
41
|
|
|
|
42
|
|
|
import transaction |
43
|
|
|
|
44
|
|
|
engine = get_engine(settings) |
45
|
|
|
session_factory = get_session_factory(engine) |
46
|
|
|
with transaction.manager: |
47
|
|
|
dbsession = get_tm_session(session_factory, transaction.manager) |
48
|
|
|
|
49
|
|
|
""" |
50
|
|
|
dbsession = session_factory() |
51
|
|
|
zope.sqlalchemy.register( |
52
|
|
|
dbsession, transaction_manager=transaction_manager) |
53
|
|
|
listen(dbsession, 'before_flush', prevent_content_revision_delete) |
54
|
|
|
return dbsession |
55
|
|
|
|
56
|
|
|
|
57
|
|
|
def includeme(config): |
58
|
|
|
""" |
59
|
|
|
Initialize the model for a Pyramid app. |
60
|
|
|
|
61
|
|
|
Activate this setup using ``config.include('tracim.models')``. |
62
|
|
|
|
63
|
|
|
""" |
64
|
|
|
settings = config.get_settings() |
65
|
|
|
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager' |
66
|
|
|
|
67
|
|
|
# use pyramid_tm to hook the transaction lifecycle to the request |
68
|
|
|
config.include('pyramid_tm') |
69
|
|
|
|
70
|
|
|
# use pyramid_retry to retry a request when transient exceptions occur |
71
|
|
|
config.include('pyramid_retry') |
72
|
|
|
|
73
|
|
|
session_factory = get_session_factory(get_engine(settings)) |
74
|
|
|
config.registry['dbsession_factory'] = session_factory |
75
|
|
|
|
76
|
|
|
# make request.dbsession available for use in Pyramid |
77
|
|
|
config.add_request_method( |
78
|
|
|
# r.tm is the transaction manager used by pyramid_tm |
79
|
|
|
lambda r: get_tm_session(session_factory, r.tm), |
80
|
|
|
'dbsession', |
81
|
|
|
reify=True |
82
|
|
|
) |
83
|
|
|
|
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.