characteristics.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. # engine/characteristics.py
  2. # Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: https://www.opensource.org/licenses/mit-license.php
  7. from __future__ import annotations
  8. import abc
  9. import typing
  10. from typing import Any
  11. from typing import ClassVar
  12. if typing.TYPE_CHECKING:
  13. from .base import Connection
  14. from .interfaces import DBAPIConnection
  15. from .interfaces import Dialect
  16. class ConnectionCharacteristic(abc.ABC):
  17. """An abstract base for an object that can set, get and reset a
  18. per-connection characteristic, typically one that gets reset when the
  19. connection is returned to the connection pool.
  20. transaction isolation is the canonical example, and the
  21. ``IsolationLevelCharacteristic`` implementation provides this for the
  22. ``DefaultDialect``.
  23. The ``ConnectionCharacteristic`` class should call upon the ``Dialect`` for
  24. the implementation of each method. The object exists strictly to serve as
  25. a dialect visitor that can be placed into the
  26. ``DefaultDialect.connection_characteristics`` dictionary where it will take
  27. effect for calls to :meth:`_engine.Connection.execution_options` and
  28. related APIs.
  29. .. versionadded:: 1.4
  30. """
  31. __slots__ = ()
  32. transactional: ClassVar[bool] = False
  33. @abc.abstractmethod
  34. def reset_characteristic(
  35. self, dialect: Dialect, dbapi_conn: DBAPIConnection
  36. ) -> None:
  37. """Reset the characteristic on the DBAPI connection to its default
  38. value."""
  39. @abc.abstractmethod
  40. def set_characteristic(
  41. self, dialect: Dialect, dbapi_conn: DBAPIConnection, value: Any
  42. ) -> None:
  43. """set characteristic on the DBAPI connection to a given value."""
  44. def set_connection_characteristic(
  45. self,
  46. dialect: Dialect,
  47. conn: Connection,
  48. dbapi_conn: DBAPIConnection,
  49. value: Any,
  50. ) -> None:
  51. """set characteristic on the :class:`_engine.Connection` to a given
  52. value.
  53. .. versionadded:: 2.0.30 - added to support elements that are local
  54. to the :class:`_engine.Connection` itself.
  55. """
  56. self.set_characteristic(dialect, dbapi_conn, value)
  57. @abc.abstractmethod
  58. def get_characteristic(
  59. self, dialect: Dialect, dbapi_conn: DBAPIConnection
  60. ) -> Any:
  61. """Given a DBAPI connection, get the current value of the
  62. characteristic.
  63. """
  64. def get_connection_characteristic(
  65. self, dialect: Dialect, conn: Connection, dbapi_conn: DBAPIConnection
  66. ) -> Any:
  67. """Given a :class:`_engine.Connection`, get the current value of the
  68. characteristic.
  69. .. versionadded:: 2.0.30 - added to support elements that are local
  70. to the :class:`_engine.Connection` itself.
  71. """
  72. return self.get_characteristic(dialect, dbapi_conn)
  73. class IsolationLevelCharacteristic(ConnectionCharacteristic):
  74. """Manage the isolation level on a DBAPI connection"""
  75. transactional: ClassVar[bool] = True
  76. def reset_characteristic(
  77. self, dialect: Dialect, dbapi_conn: DBAPIConnection
  78. ) -> None:
  79. dialect.reset_isolation_level(dbapi_conn)
  80. def set_characteristic(
  81. self, dialect: Dialect, dbapi_conn: DBAPIConnection, value: Any
  82. ) -> None:
  83. dialect._assert_and_set_isolation_level(dbapi_conn, value)
  84. def get_characteristic(
  85. self, dialect: Dialect, dbapi_conn: DBAPIConnection
  86. ) -> Any:
  87. return dialect.get_isolation_level(dbapi_conn)
  88. class LoggingTokenCharacteristic(ConnectionCharacteristic):
  89. """Manage the 'logging_token' option of a :class:`_engine.Connection`.
  90. .. versionadded:: 2.0.30
  91. """
  92. transactional: ClassVar[bool] = False
  93. def reset_characteristic(
  94. self, dialect: Dialect, dbapi_conn: DBAPIConnection
  95. ) -> None:
  96. pass
  97. def set_characteristic(
  98. self, dialect: Dialect, dbapi_conn: DBAPIConnection, value: Any
  99. ) -> None:
  100. raise NotImplementedError()
  101. def set_connection_characteristic(
  102. self,
  103. dialect: Dialect,
  104. conn: Connection,
  105. dbapi_conn: DBAPIConnection,
  106. value: Any,
  107. ) -> None:
  108. if value:
  109. conn._message_formatter = lambda msg: "[%s] %s" % (value, msg)
  110. else:
  111. del conn._message_formatter
  112. def get_characteristic(
  113. self, dialect: Dialect, dbapi_conn: DBAPIConnection
  114. ) -> Any:
  115. raise NotImplementedError()
  116. def get_connection_characteristic(
  117. self, dialect: Dialect, conn: Connection, dbapi_conn: DBAPIConnection
  118. ) -> Any:
  119. return conn._execution_options.get("logging_token", None)