def __init__(self, session_factory, scopefunc=None): self.session_factory = session_factory if scopefunc: self.registry = ScopedRegistry(session_factory, scopefunc) else: self.registry = ThreadLocalRegistry(session_factory) self.extension = _ScopedExt(self)
def init(connection_uri, echo=False, scopefunc=None): """Initialize the session. Args: connection_uri (str): The connection uri, such as "postgrseql://*****:*****@localhost/dbname" echo (bool): Echo SQL statements to stdout. Useful for debugging. scopefunc (func): Optional function which defines the current scope. See http://docs.sqlalchemy.org/en/latest/orm/contextual.html#sqlalchemy.orm.scoping.scoped_session.__init__ for more information. If this is not passed, the "thread-local" scope will be assumed. """ global engine, session from frf.models import Model if 'postgres' in connection_uri: engine = create_engine(connection_uri, echo=echo, json_serializer=serialize, json_deserializer=deserialize) else: engine = create_engine(connection_uri, echo=echo) if scopefunc is not None: session.registry = ScopedRegistry(session.session_factory, scopefunc=scopefunc) else: session.registry = ThreadLocalRegistry(session.session_factory) session.configure(bind=engine) Model.query = _QueryProperty(session)
def __init__(self, session_factory, scopefunc=None): """Construct a new :class:`.scoped_session`. :param session_factory: a factory to create new :class:`.Session` instances. This is usually, but not necessarily, an instance of :class:`.sessionmaker`. :param scopefunc: optional function which defines the current scope. If not passed, the :class:`.scoped_session` object assumes "thread-local" scope, and will use a Python ``threading.local()`` in order to maintain the current :class:`.Session`. If passed, the function should return a hashable token; this token will be used as the key in a dictionary in order to store and retrieve the current :class:`.Session`. """ self.session_factory = session_factory if scopefunc: self.registry = ScopedRegistry(session_factory, scopefunc) else: self.registry = ThreadLocalRegistry(session_factory)
class ScopedSession(object): """Provides thread-local management of Sessions. Typical invocation is via the :func:`.scoped_session` function:: Session = scoped_session(sessionmaker()) The internal registry is accessible, and by default is an instance of :class:`.ThreadLocalRegistry`. See also: :ref:`unitofwork_contextual`. """ def __init__(self, session_factory, scopefunc=None): self.session_factory = session_factory if scopefunc: self.registry = ScopedRegistry(session_factory, scopefunc) else: self.registry = ThreadLocalRegistry(session_factory) def __call__(self, **kwargs): if kwargs: scope = kwargs.pop('scope', False) if scope is not None: if self.registry.has(): raise sa_exc.InvalidRequestError( "Scoped session is already present; " "no new arguments may be specified.") else: sess = self.session_factory(**kwargs) self.registry.set(sess) return sess else: return self.session_factory(**kwargs) else: return self.registry() def remove(self): """Dispose of the current contextual session.""" if self.registry.has(): self.registry().close() self.registry.clear() def configure(self, **kwargs): """reconfigure the sessionmaker used by this ScopedSession.""" if self.registry.has(): warn('At least one scoped session is already present. ' ' configure() can not affect sessions that have ' 'already been created.') self.session_factory.configure(**kwargs) def query_property(self, query_cls=None): """return a class property which produces a `Query` object against the class when called. e.g.:: Session = scoped_session(sessionmaker()) class MyClass(object): query = Session.query_property() # after mappers are defined result = MyClass.query.filter(MyClass.name=='foo').all() Produces instances of the session's configured query class by default. To override and use a custom implementation, provide a ``query_cls`` callable. The callable will be invoked with the class's mapper as a positional argument and a session keyword argument. There is no limit to the number of query properties placed on a class. """ class query(object): def __get__(s, instance, owner): try: mapper = class_mapper(owner) if mapper: if query_cls: # custom query class return query_cls(mapper, session=self.registry()) else: # session's configured query class return self.registry().query(mapper) except orm_exc.UnmappedClassError: return None return query()
class ScopedSession(object): """Provides thread-local management of Sessions. Usage:: Session = scoped_session(sessionmaker(autoflush=True)) ... use session normally. """ def __init__(self, session_factory, scopefunc=None): self.session_factory = session_factory if scopefunc: self.registry = ScopedRegistry(session_factory, scopefunc) else: self.registry = ThreadLocalRegistry(session_factory) self.extension = _ScopedExt(self) def __call__(self, **kwargs): if kwargs: scope = kwargs.pop('scope', False) if scope is not None: if self.registry.has(): raise sa_exc.InvalidRequestError("Scoped session is already present; no new arguments may be specified.") else: sess = self.session_factory(**kwargs) self.registry.set(sess) return sess else: return self.session_factory(**kwargs) else: return self.registry() def remove(self): if self.registry.has(): self.registry().close() self.registry.clear() @deprecated("Session.mapper is deprecated. " "Please see http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper " "for information on how to replicate its behavior.") def mapper(self, *args, **kwargs): """return a mapper() function which associates this ScopedSession with the Mapper. DEPRECATED. """ from sqlalchemy.orm import mapper extension_args = dict((arg, kwargs.pop(arg)) for arg in get_cls_kwargs(_ScopedExt) if arg in kwargs) kwargs['extension'] = extension = to_list(kwargs.get('extension', [])) if extension_args: extension.append(self.extension.configure(**extension_args)) else: extension.append(self.extension) return mapper(*args, **kwargs) def configure(self, **kwargs): """reconfigure the sessionmaker used by this ScopedSession.""" self.session_factory.configure(**kwargs) def query_property(self, query_cls=None): """return a class property which produces a `Query` object against the class when called. e.g.:: Session = scoped_session(sessionmaker()) class MyClass(object): query = Session.query_property() # after mappers are defined result = MyClass.query.filter(MyClass.name=='foo').all() Produces instances of the session's configured query class by default. To override and use a custom implementation, provide a ``query_cls`` callable. The callable will be invoked with the class's mapper as a positional argument and a session keyword argument. There is no limit to the number of query properties placed on a class. """ class query(object): def __get__(s, instance, owner): try: mapper = class_mapper(owner) if mapper: if query_cls: # custom query class return query_cls(mapper, session=self.registry()) else: # session's configured query class return self.registry().query(mapper) except orm_exc.UnmappedClassError: return None return query()
class ScopedSession(object): """Provides thread-local management of Sessions. Usage:: Session = scoped_session(sessionmaker()) ... use Session normally. The internal registry is accessible as well, and by default is an instance of :class:`.ThreadLocalRegistry`. """ def __init__(self, session_factory, scopefunc=None): self.session_factory = session_factory if scopefunc: self.registry = ScopedRegistry(session_factory, scopefunc) else: self.registry = ThreadLocalRegistry(session_factory) def __call__(self, **kwargs): if kwargs: scope = kwargs.pop("scope", False) if scope is not None: if self.registry.has(): raise sa_exc.InvalidRequestError( "Scoped session is already present; " "no new arguments may be specified." ) else: sess = self.session_factory(**kwargs) self.registry.set(sess) return sess else: return self.session_factory(**kwargs) else: return self.registry() def remove(self): """Dispose of the current contextual session.""" if self.registry.has(): self.registry().close() self.registry.clear() def configure(self, **kwargs): """reconfigure the sessionmaker used by this ScopedSession.""" if self.registry.has(): warn( "At least one scoped session is already present. " " configure() can not affect sessions that have " "already been created." ) self.session_factory.configure(**kwargs) def query_property(self, query_cls=None): """return a class property which produces a `Query` object against the class when called. e.g.:: Session = scoped_session(sessionmaker()) class MyClass(object): query = Session.query_property() # after mappers are defined result = MyClass.query.filter(MyClass.name=='foo').all() Produces instances of the session's configured query class by default. To override and use a custom implementation, provide a ``query_cls`` callable. The callable will be invoked with the class's mapper as a positional argument and a session keyword argument. There is no limit to the number of query properties placed on a class. """ class query(object): def __get__(s, instance, owner): try: mapper = class_mapper(owner) if mapper: if query_cls: # custom query class return query_cls(mapper, session=self.registry()) else: # session's configured query class return self.registry().query(mapper) except orm_exc.UnmappedClassError: return None return query()
class scoped_session(object): """Provides scoped management of :class:`.Session` objects. See :ref:`unitofwork_contextual` for a tutorial. """ session_factory = None """The `session_factory` provided to `__init__` is stored in this attribute and may be accessed at a later time. This can be useful when a new non-scoped :class:`.Session` or :class:`.Connection` to the database is needed.""" def __init__(self, session_factory, scopefunc=None): """Construct a new :class:`.scoped_session`. :param session_factory: a factory to create new :class:`.Session` instances. This is usually, but not necessarily, an instance of :class:`.sessionmaker`. :param scopefunc: optional function which defines the current scope. If not passed, the :class:`.scoped_session` object assumes "thread-local" scope, and will use a Python ``threading.local()`` in order to maintain the current :class:`.Session`. If passed, the function should return a hashable token; this token will be used as the key in a dictionary in order to store and retrieve the current :class:`.Session`. """ self.session_factory = session_factory if scopefunc: self.registry = ScopedRegistry(session_factory, scopefunc) else: self.registry = ThreadLocalRegistry(session_factory) def __call__(self, **kw): r"""Return the current :class:`.Session`, creating it using the :attr:`.scoped_session.session_factory` if not present. :param \**kw: Keyword arguments will be passed to the :attr:`.scoped_session.session_factory` callable, if an existing :class:`.Session` is not present. If the :class:`.Session` is present and keyword arguments have been passed, :exc:`~sqlalchemy.exc.InvalidRequestError` is raised. """ if kw: if self.registry.has(): raise sa_exc.InvalidRequestError( "Scoped session is already present; " "no new arguments may be specified.") else: sess = self.session_factory(**kw) self.registry.set(sess) return sess else: return self.registry() def remove(self): """Dispose of the current :class:`.Session`, if present. This will first call :meth:`.Session.close` method on the current :class:`.Session`, which releases any existing transactional/connection resources still being held; transactions specifically are rolled back. The :class:`.Session` is then discarded. Upon next usage within the same scope, the :class:`.scoped_session` will produce a new :class:`.Session` object. """ if self.registry.has(): self.registry().close() self.registry.clear() def configure(self, **kwargs): """reconfigure the :class:`.sessionmaker` used by this :class:`.scoped_session`. See :meth:`.sessionmaker.configure`. """ if self.registry.has(): self._logger.warning( "At least one scoped session is already present. " " configure() can not affect sessions that have " "already been created.") self.session_factory.configure(**kwargs)
def __init__(self, session_factory): self._session_factory = session_factory self._registry = ThreadLocalRegistry(session_factory)
class ExplicitSessionManager(object): """A thread-safe explicit session manager. This provides the following semantics: - Sessions are started via a contextmanager. - Using the ExplicitSessionManager (typically via Model.query) is invalid. - Entering a Session context opens a transaction and returns a session recursively. - Provides a query_property that can only be used within a transaction. - A transaction can *only* be opened by a context manager. """ def __init__(self, session_factory): self._session_factory = session_factory self._registry = ThreadLocalRegistry(session_factory) def configure(self, **config): self._session_factory.configure(**config) def __enter__(self): if not self._registry.has(): sess = self._session_factory() self._registry.set(sess) else: sess = self._registry() return sess.__enter__() def begin(self): return self.__enter__() def __exit__(self, type, value, traceback): if self._registry.has(): sess = self._registry() sess.__exit__(type, value, traceback) def remove(self): """Close the associated session and disconnect.""" if self._registry.has(): self._registry().close() self._registry.clear() def query_property(self, query_cls=None): class query(object): def __get__(s, instance, owner): try: mapper = class_mapper(owner) if mapper: if not self._registry.has() or not self._registry()._depth: raise InvalidRequestError('Cannot access %s.query outside transaction, use with session: ...' % owner.__name__) if query_cls: # custom query class return query_cls(mapper, session=self._registry()) else: # session's configured query class return self._registry().query(mapper) except UnmappedClassError: return None return query() def __getattr__(self, name): """Proxy all attribute access to current session.""" if not self._registry.has(): raise InvalidRequestError('No transaction is active, use "with session: ..."') return getattr(self._registry(), name)
class ScopedSession(object): """Provides thread-local management of Sessions. Usage:: Session = scoped_session(sessionmaker(autoflush=True)) ... use session normally. """ def __init__(self, session_factory, scopefunc=None): self.session_factory = session_factory if scopefunc: self.registry = ScopedRegistry(session_factory, scopefunc) else: self.registry = ThreadLocalRegistry(session_factory) self.extension = _ScopedExt(self) def __call__(self, **kwargs): if kwargs: scope = kwargs.pop('scope', False) if scope is not None: if self.registry.has(): raise sa_exc.InvalidRequestError( "Scoped session is already present; no new arguments may be specified." ) else: sess = self.session_factory(**kwargs) self.registry.set(sess) return sess else: return self.session_factory(**kwargs) else: return self.registry() def remove(self): """Dispose of the current contextual session.""" if self.registry.has(): self.registry().close() self.registry.clear() @deprecated( "Session.mapper is deprecated. " "Please see http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper " "for information on how to replicate its behavior.") def mapper(self, *args, **kwargs): """return a mapper() function which associates this ScopedSession with the Mapper. DEPRECATED. """ from sqlalchemy.orm import mapper extension_args = dict((arg, kwargs.pop(arg)) for arg in get_cls_kwargs(_ScopedExt) if arg in kwargs) kwargs['extension'] = extension = to_list(kwargs.get('extension', [])) if extension_args: extension.append(self.extension.configure(**extension_args)) else: extension.append(self.extension) return mapper(*args, **kwargs) def configure(self, **kwargs): """reconfigure the sessionmaker used by this ScopedSession.""" self.session_factory.configure(**kwargs) def query_property(self, query_cls=None): """return a class property which produces a `Query` object against the class when called. e.g.:: Session = scoped_session(sessionmaker()) class MyClass(object): query = Session.query_property() # after mappers are defined result = MyClass.query.filter(MyClass.name=='foo').all() Produces instances of the session's configured query class by default. To override and use a custom implementation, provide a ``query_cls`` callable. The callable will be invoked with the class's mapper as a positional argument and a session keyword argument. There is no limit to the number of query properties placed on a class. """ class query(object): def __get__(s, instance, owner): try: mapper = class_mapper(owner) if mapper: if query_cls: # custom query class return query_cls(mapper, session=self.registry()) else: # session's configured query class return self.registry().query(mapper) except orm_exc.UnmappedClassError: return None return query()
class ExplicitSessionManager(object): """A thread-safe explicit session manager. This provides the following semantics: - Sessions are started via a contextmanager. - Using the ExplicitSessionManager (typically via Model.query) is invalid. - Entering a Session context opens a transaction and returns a session recursively. - Provides a query_property that can only be used within a transaction. - A transaction can *only* be opened by a context manager. """ def __init__(self, session_factory): self._session_factory = session_factory self._registry = ThreadLocalRegistry(session_factory) def configure(self, **config): self._session_factory.configure(**config) def __enter__(self): if not self._registry.has(): sess = self._session_factory() self._registry.set(sess) else: sess = self._registry() return sess.__enter__() def begin(self): return self.__enter__() def __exit__(self, type, value, traceback): if self._registry.has(): sess = self._registry() sess.__exit__(type, value, traceback) def remove(self): """Close the associated session and disconnect.""" if self._registry.has(): self._registry().close() self._registry.clear() def query_property(self, query_cls=None): class query(object): def __get__(s, instance, owner): try: mapper = class_mapper(owner) if mapper: if not self._registry.has() or not self._registry( )._depth: raise InvalidRequestError( 'Cannot access %s.query outside transaction, use with session: ...' % owner.__name__) if query_cls: # custom query class return query_cls(mapper, session=self._registry()) else: # session's configured query class return self._registry().query(mapper) except UnmappedClassError: return None return query() def __getattr__(self, name): """Proxy all attribute access to current session.""" if not self._registry.has(): raise InvalidRequestError( 'No transaction is active, use "with session: ..."') return getattr(self._registry(), name)