root/galaxy-central/eggs/SQLAlchemy-0.5.6_dev_r6498-py2.6.egg/sqlalchemy/orm/scoping.py @ 3

リビジョン 3, 7.2 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1# scoping.py
2# Copyright (C) the SQLAlchemy authors and contributors
3#
4# This module is part of SQLAlchemy and is released under
5# the MIT License: http://www.opensource.org/licenses/mit-license.php
6
7import sqlalchemy.exceptions as sa_exc
8from sqlalchemy.util import ScopedRegistry, ThreadLocalRegistry, \
9                            to_list, get_cls_kwargs, deprecated
10from sqlalchemy.orm import (
11    EXT_CONTINUE, MapperExtension, class_mapper, object_session
12    )
13from sqlalchemy.orm import exc as orm_exc
14from sqlalchemy.orm.session import Session
15
16
17__all__ = ['ScopedSession']
18
19
20class ScopedSession(object):
21    """Provides thread-local management of Sessions.
22
23    Usage::
24
25      Session = scoped_session(sessionmaker(autoflush=True))
26
27      ... use session normally.
28
29    """
30
31    def __init__(self, session_factory, scopefunc=None):
32        self.session_factory = session_factory
33        if scopefunc:
34            self.registry = ScopedRegistry(session_factory, scopefunc)
35        else:
36            self.registry = ThreadLocalRegistry(session_factory)
37        self.extension = _ScopedExt(self)
38
39    def __call__(self, **kwargs):
40        if kwargs:
41            scope = kwargs.pop('scope', False)
42            if scope is not None:
43                if self.registry.has():
44                    raise sa_exc.InvalidRequestError("Scoped session is already present; no new arguments may be specified.")
45                else:
46                    sess = self.session_factory(**kwargs)
47                    self.registry.set(sess)
48                    return sess
49            else:
50                return self.session_factory(**kwargs)
51        else:
52            return self.registry()
53
54    def remove(self):
55        if self.registry.has():
56            self.registry().close()
57        self.registry.clear()
58
59    @deprecated("Session.mapper is deprecated.  "
60        "Please see http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper "
61        "for information on how to replicate its behavior.")
62    def mapper(self, *args, **kwargs):
63        """return a mapper() function which associates this ScopedSession with the Mapper.
64       
65        DEPRECATED.
66       
67        """
68
69        from sqlalchemy.orm import mapper
70
71        extension_args = dict((arg, kwargs.pop(arg))
72                              for arg in get_cls_kwargs(_ScopedExt)
73                              if arg in kwargs)
74
75        kwargs['extension'] = extension = to_list(kwargs.get('extension', []))
76        if extension_args:
77            extension.append(self.extension.configure(**extension_args))
78        else:
79            extension.append(self.extension)
80        return mapper(*args, **kwargs)
81
82    def configure(self, **kwargs):
83        """reconfigure the sessionmaker used by this ScopedSession."""
84
85        self.session_factory.configure(**kwargs)
86
87    def query_property(self, query_cls=None):
88        """return a class property which produces a `Query` object against the
89        class when called.
90
91        e.g.::
92            Session = scoped_session(sessionmaker())
93
94            class MyClass(object):
95                query = Session.query_property()
96
97            # after mappers are defined
98            result = MyClass.query.filter(MyClass.name=='foo').all()
99
100        Produces instances of the session's configured query class by
101        default.  To override and use a custom implementation, provide
102        a ``query_cls`` callable.  The callable will be invoked with
103        the class's mapper as a positional argument and a session
104        keyword argument.
105
106        There is no limit to the number of query properties placed on
107        a class.
108
109        """
110        class query(object):
111            def __get__(s, instance, owner):
112                try:
113                    mapper = class_mapper(owner)
114                    if mapper:
115                        if query_cls:
116                            # custom query class
117                            return query_cls(mapper, session=self.registry())
118                        else:
119                            # session's configured query class
120                            return self.registry().query(mapper)
121                except orm_exc.UnmappedClassError:
122                    return None
123        return query()
124
125def instrument(name):
126    def do(self, *args, **kwargs):
127        return getattr(self.registry(), name)(*args, **kwargs)
128    return do
129for meth in Session.public_methods:
130    setattr(ScopedSession, meth, instrument(meth))
131
132def makeprop(name):
133    def set(self, attr):
134        setattr(self.registry(), name, attr)
135    def get(self):
136        return getattr(self.registry(), name)
137    return property(get, set)
138for prop in ('bind', 'dirty', 'deleted', 'new', 'identity_map', 'is_active'):
139    setattr(ScopedSession, prop, makeprop(prop))
140
141def clslevel(name):
142    def do(cls, *args, **kwargs):
143        return getattr(Session, name)(*args, **kwargs)
144    return classmethod(do)
145for prop in ('close_all', 'object_session', 'identity_key'):
146    setattr(ScopedSession, prop, clslevel(prop))
147
148class _ScopedExt(MapperExtension):
149    def __init__(self, context, validate=False, save_on_init=True):
150        self.context = context
151        self.validate = validate
152        self.save_on_init = save_on_init
153        self.set_kwargs_on_init = True
154
155    def validating(self):
156        return _ScopedExt(self.context, validate=True)
157
158    def configure(self, **kwargs):
159        return _ScopedExt(self.context, **kwargs)
160
161    def instrument_class(self, mapper, class_):
162        class query(object):
163            def __getattr__(s, key):
164                return getattr(self.context.registry().query(class_), key)
165            def __call__(s):
166                return self.context.registry().query(class_)
167            def __get__(self, instance, cls):
168                return self
169
170        if not 'query' in class_.__dict__:
171            class_.query = query()
172
173        if self.set_kwargs_on_init and class_.__init__ is object.__init__:
174            class_.__init__ = self._default__init__(mapper)
175
176    def _default__init__(ext, mapper):
177        def __init__(self, **kwargs):
178            for key, value in kwargs.items():
179                if ext.validate:
180                    if not mapper.get_property(key, resolve_synonyms=False,
181                                               raiseerr=False):
182                        raise sa_exc.ArgumentError(
183                            "Invalid __init__ argument: '%s'" % key)
184                setattr(self, key, value)
185        return __init__
186
187    def init_instance(self, mapper, class_, oldinit, instance, args, kwargs):
188        if self.save_on_init:
189            session = kwargs.pop('_sa_session', None)
190            if session is None:
191                session = self.context.registry()
192            session._save_without_cascade(instance)
193        return EXT_CONTINUE
194
195    def init_failed(self, mapper, class_, oldinit, instance, args, kwargs):
196        sess = object_session(instance)
197        if sess:
198            sess.expunge(instance)
199        return EXT_CONTINUE
200
201    def dispose_class(self, mapper, class_):
202        if hasattr(class_, '__init__') and hasattr(class_.__init__, '_oldinit'):
203            if class_.__init__._oldinit is not None:
204                class_.__init__ = class_.__init__._oldinit
205            else:
206                delattr(class_, '__init__')
207        if hasattr(class_, 'query'):
208            delattr(class_, 'query')
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。