~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

Viewing changes to lib/sqlalchemy/orm/scoping.py

  • Committer: Bazaar Package Importer
  • Author(s): Piotr Ożarowski
  • Date: 2011-08-01 23:18:16 UTC
  • mfrom: (1.4.15 upstream) (16.1.14 experimental)
  • Revision ID: james.westby@ubuntu.com-20110801231816-6lx797pi3q1fpqst
Tags: 0.7.2-1
* New upstream release
* Bump minimum required python-mako version to 0.4.1 (closes: 635898)

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
# This module is part of SQLAlchemy and is released under
5
5
# the MIT License: http://www.opensource.org/licenses/mit-license.php
6
6
 
7
 
import sqlalchemy.exceptions as sa_exc
8
 
from sqlalchemy.util import ScopedRegistry, ThreadLocalRegistry, \
9
 
                            to_list, get_cls_kwargs, deprecated,\
10
 
                            warn
11
 
from sqlalchemy.orm import (
12
 
    EXT_CONTINUE, MapperExtension, class_mapper, object_session
13
 
    )
 
7
from sqlalchemy import exc as sa_exc
 
8
from sqlalchemy.util import ScopedRegistry, ThreadLocalRegistry, warn
 
9
from sqlalchemy.orm import class_mapper
14
10
from sqlalchemy.orm import exc as orm_exc
15
11
from sqlalchemy.orm.session import Session
16
12
 
20
16
 
21
17
class ScopedSession(object):
22
18
    """Provides thread-local management of Sessions.
23
 
 
24
 
    Usage::
25
 
 
 
19
    
 
20
    Typical invocation is via the :func:`.scoped_session`
 
21
    function::
 
22
    
26
23
      Session = scoped_session(sessionmaker())
27
24
 
28
 
    ... use Session normally.
29
 
 
30
 
    The internal registry is accessible as well,
 
25
    The internal registry is accessible,
31
26
    and by default is an instance of :class:`.ThreadLocalRegistry`.
32
27
 
 
28
    See also: :ref:`unitofwork_contextual`.
33
29
 
34
30
    """
35
31
 
39
35
            self.registry = ScopedRegistry(session_factory, scopefunc)
40
36
        else:
41
37
            self.registry = ThreadLocalRegistry(session_factory)
42
 
        self.extension = _ScopedExt(self)
43
38
 
44
39
    def __call__(self, **kwargs):
45
40
        if kwargs:
64
59
            self.registry().close()
65
60
        self.registry.clear()
66
61
 
67
 
    @deprecated("0.5", ":meth:`.ScopedSession.mapper` is deprecated.  "
68
 
        "Please see http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper "
69
 
        "for information on how to replicate its behavior.")
70
 
    def mapper(self, *args, **kwargs):
71
 
        """return a :func:`.mapper` function which associates this ScopedSession with the Mapper.
72
 
 
73
 
        """
74
 
 
75
 
        from sqlalchemy.orm import mapper
76
 
 
77
 
        extension_args = dict((arg, kwargs.pop(arg))
78
 
                              for arg in get_cls_kwargs(_ScopedExt)
79
 
                              if arg in kwargs)
80
 
 
81
 
        kwargs['extension'] = extension = to_list(kwargs.get('extension', []))
82
 
        if extension_args:
83
 
            extension.append(self.extension.configure(**extension_args))
84
 
        else:
85
 
            extension.append(self.extension)
86
 
        return mapper(*args, **kwargs)
87
 
 
88
62
    def configure(self, **kwargs):
89
63
        """reconfigure the sessionmaker used by this ScopedSession."""
90
64
 
157
131
for prop in ('close_all', 'object_session', 'identity_key'):
158
132
    setattr(ScopedSession, prop, clslevel(prop))
159
133
 
160
 
class _ScopedExt(MapperExtension):
161
 
    def __init__(self, context, validate=False, save_on_init=True):
162
 
        self.context = context
163
 
        self.validate = validate
164
 
        self.save_on_init = save_on_init
165
 
        self.set_kwargs_on_init = True
166
 
 
167
 
    def validating(self):
168
 
        return _ScopedExt(self.context, validate=True)
169
 
 
170
 
    def configure(self, **kwargs):
171
 
        return _ScopedExt(self.context, **kwargs)
172
 
 
173
 
    def instrument_class(self, mapper, class_):
174
 
        class query(object):
175
 
            def __getattr__(s, key):
176
 
                return getattr(self.context.registry().query(class_), key)
177
 
            def __call__(s):
178
 
                return self.context.registry().query(class_)
179
 
            def __get__(self, instance, cls):
180
 
                return self
181
 
 
182
 
        if not 'query' in class_.__dict__:
183
 
            class_.query = query()
184
 
 
185
 
        if self.set_kwargs_on_init and class_.__init__ is object.__init__:
186
 
            class_.__init__ = self._default__init__(mapper)
187
 
 
188
 
    def _default__init__(ext, mapper):
189
 
        def __init__(self, **kwargs):
190
 
            for key, value in kwargs.iteritems():
191
 
                if ext.validate:
192
 
                    if not mapper.get_property(key, resolve_synonyms=False,
193
 
                                               raiseerr=False):
194
 
                        raise sa_exc.ArgumentError(
195
 
                            "Invalid __init__ argument: '%s'" % key)
196
 
                setattr(self, key, value)
197
 
        return __init__
198
 
 
199
 
    def init_instance(self, mapper, class_, oldinit, instance, args, kwargs):
200
 
        if self.save_on_init:
201
 
            session = kwargs.pop('_sa_session', None)
202
 
            if session is None:
203
 
                session = self.context.registry()
204
 
            session._save_without_cascade(instance)
205
 
        return EXT_CONTINUE
206
 
 
207
 
    def init_failed(self, mapper, class_, oldinit, instance, args, kwargs):
208
 
        sess = object_session(instance)
209
 
        if sess:
210
 
            sess.expunge(instance)
211
 
        return EXT_CONTINUE
212
 
 
213
 
    def dispose_class(self, mapper, class_):
214
 
        if hasattr(class_, 'query'):
215
 
            delattr(class_, 'query')