123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- # sqlalchemy/pool/dbapi_proxy.py
- # Copyright (C) 2005-2022 the SQLAlchemy authors and contributors
- # <see AUTHORS file>
- #
- # This module is part of SQLAlchemy and is released under
- # the MIT License: https://www.opensource.org/licenses/mit-license.php
- """DBAPI proxy utility.
- Provides transparent connection pooling on top of a Python DBAPI.
- This is legacy SQLAlchemy functionality that is not typically used
- today.
- """
- from .impl import QueuePool
- from .. import util
- from ..util import threading
- proxies = {}
- @util.deprecated(
- "1.3",
- "The :func:`.pool.manage` function is deprecated, and will be "
- "removed in a future release.",
- )
- def manage(module, **params):
- r"""Return a proxy for a DB-API module that automatically
- pools connections.
- Given a DB-API 2.0 module and pool management parameters, returns
- a proxy for the module that will automatically pool connections,
- creating new connection pools for each distinct set of connection
- arguments sent to the decorated module's connect() function.
- :param module: a DB-API 2.0 database module
- :param poolclass: the class used by the pool module to provide
- pooling. Defaults to :class:`.QueuePool`.
- :param \**params: will be passed through to *poolclass*
- """
- try:
- return proxies[module]
- except KeyError:
- return proxies.setdefault(module, _DBProxy(module, **params))
- def clear_managers():
- """Remove all current DB-API 2.0 managers.
- All pools and connections are disposed.
- """
- for manager in proxies.values():
- manager.close()
- proxies.clear()
- class _DBProxy(object):
- """Layers connection pooling behavior on top of a standard DB-API module.
- Proxies a DB-API 2.0 connect() call to a connection pool keyed to the
- specific connect parameters. Other functions and attributes are delegated
- to the underlying DB-API module.
- """
- def __init__(self, module, poolclass=QueuePool, **kw):
- """Initializes a new proxy.
- module
- a DB-API 2.0 module
- poolclass
- a Pool class, defaulting to QueuePool
- Other parameters are sent to the Pool object's constructor.
- """
- self.module = module
- self.kw = kw
- self.poolclass = poolclass
- self.pools = {}
- self._create_pool_mutex = threading.Lock()
- def close(self):
- for key in list(self.pools):
- del self.pools[key]
- def __del__(self):
- self.close()
- def __getattr__(self, key):
- return getattr(self.module, key)
- def get_pool(self, *args, **kw):
- key = self._serialize(*args, **kw)
- try:
- return self.pools[key]
- except KeyError:
- with self._create_pool_mutex:
- if key not in self.pools:
- kw.pop("sa_pool_key", None)
- pool = self.poolclass(
- lambda: self.module.connect(*args, **kw), **self.kw
- )
- self.pools[key] = pool
- return pool
- else:
- return self.pools[key]
- def connect(self, *args, **kw):
- """Activate a connection to the database.
- Connect to the database using this DBProxy's module and the given
- connect arguments. If the arguments match an existing pool, the
- connection will be returned from the pool's current thread-local
- connection instance, or if there is no thread-local connection
- instance it will be checked out from the set of pooled connections.
- If the pool has no available connections and allows new connections
- to be created, a new database connection will be made.
- """
- return self.get_pool(*args, **kw).connect()
- def dispose(self, *args, **kw):
- """Dispose the pool referenced by the given connect arguments."""
- key = self._serialize(*args, **kw)
- try:
- del self.pools[key]
- except KeyError:
- pass
- def _serialize(self, *args, **kw):
- if "sa_pool_key" in kw:
- return kw["sa_pool_key"]
- return tuple(list(args) + [(k, kw[k]) for k in sorted(kw)])
|