summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/pool
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-02-17 13:43:04 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-03-01 09:09:02 -0500
commita4bb502cf95ea3523e4d383c4377e50f402d7d52 (patch)
tree124400f741b6b91f0e9e582b510268607394dfaa /lib/sqlalchemy/pool
parent60fca2ac8cf44bdaf68552ab5c69854a6776c73c (diff)
downloadsqlalchemy-a4bb502cf95ea3523e4d383c4377e50f402d7d52.tar.gz
pep-484 for engine
All modules in sqlalchemy.engine are strictly typed with the exception of cursor, default, and reflection. cursor and default pass with non-strict typing, reflection is waiting on the multi-reflection refactor. Behavioral changes: * create_connect_args() methods return a tuple of list, dict, rather than a list of list, dict * removed allow_chars parameter from pyodbc connector ._get_server_version_info() method * the parameter list passed to do_executemany is now a list in all cases. previously, this was being run through dialect.execute_sequence_format, which defaults to tuple and was only intended for individual tuple params. * broke up dialect.dbapi into dialect.import_dbapi class method and dialect.dbapi module object. added a deprecation path for legacy dialects. it's not really feasible to type a single attr as a classmethod vs. module type. The "type_compiler" attribute also has this problem with greater ability to work around, left that one for now. * lots of constants changing to be Enum, so that we can type them. for fixed tuple-position constants in cursor.py / compiler.py (which are used to avoid the speed overhead of namedtuple), using Literal[value] which seems to work well * some tightening up in Row regarding __getitem__, which we can do since we are on full 2.0 style result use * altered the set_connection_execution_options and set_engine_execution_options event flows so that the dictionary of options may be mutated within the event hook, where it will then take effect as the actual options used. Previously, changing the dict would be silently ignored which seems counter-intuitive and not very useful. * A lot of DefaultDialect/DefaultExecutionContext methods and attributes, including underscored ones, move to interfaces. This is not fully ideal as it means the Dialect/ExecutionContext interfaces aren't publicly subclassable directly, but their current purpose is more of documentation for dialect authors who should (and certainly are) still be subclassing the DefaultXYZ versions in all cases Overall, Result was the most extremely difficult class hierarchy to type here as this hierarchy passes through largely amorphous "row" datatypes throughout, which can in fact by all kinds of different things, like raw DBAPI rows, or Row objects, or "scalar"/Any, but at the same time these types have meaning so I tried still maintaining some level of semantic markings for these, it highlights how complex Result is now, as it's trying to be extremely efficient and inlined while also being very open-ended and extensible. Change-Id: I98b75c0c09eab5355fc7a33ba41dd9874274f12a
Diffstat (limited to 'lib/sqlalchemy/pool')
-rw-r--r--lib/sqlalchemy/pool/__init__.py4
-rw-r--r--lib/sqlalchemy/pool/base.py139
2 files changed, 75 insertions, 68 deletions
diff --git a/lib/sqlalchemy/pool/__init__.py b/lib/sqlalchemy/pool/__init__.py
index 2c52a7065..1fc77243a 100644
--- a/lib/sqlalchemy/pool/__init__.py
+++ b/lib/sqlalchemy/pool/__init__.py
@@ -18,8 +18,8 @@ SQLAlchemy connection pool.
"""
from . import events
-from .base import _AdhocProxiedConnection
-from .base import _ConnectionFairy
+from .base import _AdhocProxiedConnection as _AdhocProxiedConnection
+from .base import _ConnectionFairy as _ConnectionFairy
from .base import _ConnectionRecord
from .base import _finalize_fairy
from .base import ConnectionPoolEntry as ConnectionPoolEntry
diff --git a/lib/sqlalchemy/pool/base.py b/lib/sqlalchemy/pool/base.py
index 18d268182..c1008de5f 100644
--- a/lib/sqlalchemy/pool/base.py
+++ b/lib/sqlalchemy/pool/base.py
@@ -41,6 +41,7 @@ if TYPE_CHECKING:
from ..engine.interfaces import DBAPICursor
from ..engine.interfaces import Dialect
from ..event import _Dispatch
+ from ..event import _DispatchCommon
from ..event import _ListenerFnType
from ..event import dispatcher
@@ -132,7 +133,7 @@ class Pool(log.Identified, event.EventTarget):
events: Optional[List[Tuple[_ListenerFnType, str]]] = None,
dialect: Optional[Union[_ConnDialect, Dialect]] = None,
pre_ping: bool = False,
- _dispatch: Optional[_Dispatch[Pool]] = None,
+ _dispatch: Optional[_DispatchCommon[Pool]] = None,
):
"""
Construct a Pool.
@@ -443,78 +444,72 @@ class ManagesConnection:
"""
- @property
- def driver_connection(self) -> Optional[Any]:
- """The "driver level" connection object as used by the Python
- DBAPI or database driver.
+ driver_connection: Optional[Any]
+ """The "driver level" connection object as used by the Python
+ DBAPI or database driver.
- For traditional :pep:`249` DBAPI implementations, this object will
- be the same object as that of
- :attr:`.ManagesConnection.dbapi_connection`. For an asyncio database
- driver, this will be the ultimate "connection" object used by that
- driver, such as the ``asyncpg.Connection`` object which will not have
- standard pep-249 methods.
+ For traditional :pep:`249` DBAPI implementations, this object will
+ be the same object as that of
+ :attr:`.ManagesConnection.dbapi_connection`. For an asyncio database
+ driver, this will be the ultimate "connection" object used by that
+ driver, such as the ``asyncpg.Connection`` object which will not have
+ standard pep-249 methods.
- .. versionadded:: 1.4.24
+ .. versionadded:: 1.4.24
- .. seealso::
+ .. seealso::
- :attr:`.ManagesConnection.dbapi_connection`
+ :attr:`.ManagesConnection.dbapi_connection`
- :ref:`faq_dbapi_connection`
+ :ref:`faq_dbapi_connection`
- """
- raise NotImplementedError()
+ """
- @util.dynamic_property
- def info(self) -> Dict[str, Any]:
- """Info dictionary associated with the underlying DBAPI connection
- referred to by this :class:`.ManagesConnection` instance, allowing
- user-defined data to be associated with the connection.
+ info: Dict[str, Any]
+ """Info dictionary associated with the underlying DBAPI connection
+ referred to by this :class:`.ManagesConnection` instance, allowing
+ user-defined data to be associated with the connection.
- The data in this dictionary is persistent for the lifespan
- of the DBAPI connection itself, including across pool checkins
- and checkouts. When the connection is invalidated
- and replaced with a new one, this dictionary is cleared.
+ The data in this dictionary is persistent for the lifespan
+ of the DBAPI connection itself, including across pool checkins
+ and checkouts. When the connection is invalidated
+ and replaced with a new one, this dictionary is cleared.
- For a :class:`.PoolProxiedConnection` instance that's not associated
- with a :class:`.ConnectionPoolEntry`, such as if it were detached, the
- attribute returns a dictionary that is local to that
- :class:`.ConnectionPoolEntry`. Therefore the
- :attr:`.ManagesConnection.info` attribute will always provide a Python
- dictionary.
+ For a :class:`.PoolProxiedConnection` instance that's not associated
+ with a :class:`.ConnectionPoolEntry`, such as if it were detached, the
+ attribute returns a dictionary that is local to that
+ :class:`.ConnectionPoolEntry`. Therefore the
+ :attr:`.ManagesConnection.info` attribute will always provide a Python
+ dictionary.
- .. seealso::
+ .. seealso::
- :attr:`.ManagesConnection.record_info`
+ :attr:`.ManagesConnection.record_info`
- """
- raise NotImplementedError()
+ """
- @util.dynamic_property
- def record_info(self) -> Optional[Dict[str, Any]]:
- """Persistent info dictionary associated with this
- :class:`.ManagesConnection`.
+ record_info: Optional[Dict[str, Any]]
+ """Persistent info dictionary associated with this
+ :class:`.ManagesConnection`.
- Unlike the :attr:`.ManagesConnection.info` dictionary, the lifespan
- of this dictionary is that of the :class:`.ConnectionPoolEntry`
- which owns it; therefore this dictionary will persist across
- reconnects and connection invalidation for a particular entry
- in the connection pool.
+ Unlike the :attr:`.ManagesConnection.info` dictionary, the lifespan
+ of this dictionary is that of the :class:`.ConnectionPoolEntry`
+ which owns it; therefore this dictionary will persist across
+ reconnects and connection invalidation for a particular entry
+ in the connection pool.
- For a :class:`.PoolProxiedConnection` instance that's not associated
- with a :class:`.ConnectionPoolEntry`, such as if it were detached, the
- attribute returns None. Contrast to the :attr:`.ManagesConnection.info`
- dictionary which is never None.
+ For a :class:`.PoolProxiedConnection` instance that's not associated
+ with a :class:`.ConnectionPoolEntry`, such as if it were detached, the
+ attribute returns None. Contrast to the :attr:`.ManagesConnection.info`
+ dictionary which is never None.
- .. seealso::
+ .. seealso::
- :attr:`.ManagesConnection.info`
+ :attr:`.ManagesConnection.info`
- """
- raise NotImplementedError()
+ """
def invalidate(
self, e: Optional[BaseException] = None, soft: bool = False
@@ -618,7 +613,7 @@ class _ConnectionRecord(ConnectionPoolEntry):
dbapi_connection: Optional[DBAPIConnection]
@property
- def driver_connection(self) -> Optional[Any]:
+ def driver_connection(self) -> Optional[Any]: # type: ignore[override] # mypy#4125 # noqa E501
if self.dbapi_connection is None:
return None
else:
@@ -637,11 +632,11 @@ class _ConnectionRecord(ConnectionPoolEntry):
_soft_invalidate_time: float = 0
@util.memoized_property
- def info(self) -> Dict[str, Any]:
+ def info(self) -> Dict[str, Any]: # type: ignore[override] # mypy#4125
return {}
@util.memoized_property
- def record_info(self) -> Optional[Dict[str, Any]]:
+ def record_info(self) -> Optional[Dict[str, Any]]: # type: ignore[override] # mypy#4125 # noqa E501
return {}
@classmethod
@@ -1048,7 +1043,7 @@ class _AdhocProxiedConnection(PoolProxiedConnection):
"""
- __slots__ = ("dbapi_connection", "_connection_record")
+ __slots__ = ("dbapi_connection", "_connection_record", "_is_valid")
dbapi_connection: DBAPIConnection
_connection_record: ConnectionPoolEntry
@@ -1060,9 +1055,10 @@ class _AdhocProxiedConnection(PoolProxiedConnection):
):
self.dbapi_connection = dbapi_connection
self._connection_record = connection_record
+ self._is_valid = True
@property
- def driver_connection(self) -> Any:
+ def driver_connection(self) -> Any: # type: ignore[override] # mypy#4125
return self._connection_record.driver_connection
@property
@@ -1071,10 +1067,21 @@ class _AdhocProxiedConnection(PoolProxiedConnection):
@property
def is_valid(self) -> bool:
- raise AttributeError("is_valid not implemented by this proxy")
+ """Implement is_valid state attribute.
+
+ for the adhoc proxied connection it's assumed the connection is valid
+ as there is no "invalidate" routine.
+
+ """
+ return self._is_valid
- @util.dynamic_property
- def record_info(self) -> Optional[Dict[str, Any]]:
+ def invalidate(
+ self, e: Optional[BaseException] = None, soft: bool = False
+ ) -> None:
+ self._is_valid = False
+
+ @property
+ def record_info(self) -> Optional[Dict[str, Any]]: # type: ignore[override] # mypy#4125 # noqa E501
return self._connection_record.record_info
def cursor(self, *args: Any, **kwargs: Any) -> DBAPICursor:
@@ -1140,7 +1147,7 @@ class _ConnectionFairy(PoolProxiedConnection):
_connection_record: Optional[_ConnectionRecord]
@property
- def driver_connection(self) -> Optional[Any]:
+ def driver_connection(self) -> Optional[Any]: # type: ignore[override] # mypy#4125 # noqa E501
if self._connection_record is None:
return None
return self._connection_record.driver_connection
@@ -1305,17 +1312,17 @@ class _ConnectionFairy(PoolProxiedConnection):
@property
def is_detached(self) -> bool:
- return self._connection_record is not None
+ return self._connection_record is None
@util.memoized_property
- def info(self) -> Dict[str, Any]:
+ def info(self) -> Dict[str, Any]: # type: ignore[override] # mypy#4125
if self._connection_record is None:
return {}
else:
return self._connection_record.info
- @util.dynamic_property
- def record_info(self) -> Optional[Dict[str, Any]]:
+ @property
+ def record_info(self) -> Optional[Dict[str, Any]]: # type: ignore[override] # mypy#4125 # noqa E501
if self._connection_record is None:
return None
else: