from typing import TypeVar
from typing import Union
+from .util import py38
from .util.typing import Literal
_IT = TypeVar("_IT", bound="Identified")
selected_level = self.logger.getEffectiveLevel()
if level >= selected_level:
+ if py38:
+ kwargs["stacklevel"] = kwargs.get("stacklevel", 1) + 1
+
self.logger._log(level, msg, args, **kwargs)
def isEnabledFor(self, level: int) -> bool:
class TransactionContextLoggingTest(fixtures.TestBase):
+ __only_on__ = "sqlite"
+
+ @testing.fixture()
+ def plain_assert_buf(self, plain_logging_engine):
+ buf = logging.handlers.BufferingHandler(100)
+ for log in [
+ logging.getLogger("sqlalchemy.engine"),
+ ]:
+ log.addHandler(buf)
+
+ def go(expected):
+ assert buf.buffer
+
+ buflines = [rec.msg % rec.args for rec in buf.buffer]
+
+ eq_(buflines, expected)
+ buf.flush()
+
+ yield go
+ for log in [
+ logging.getLogger("sqlalchemy.engine"),
+ ]:
+ log.removeHandler(buf)
+
@testing.fixture()
def assert_buf(self, logging_engine):
buf = logging.handlers.BufferingHandler(100)
e.connect().close()
return e
+ @testing.fixture()
+ def plain_logging_engine(self, testing_engine):
+ # deliver an engine with logging using the plain logging API,
+ # not the echo parameter
+ log = logging.getLogger("sqlalchemy.engine")
+ existing_level = log.level
+ log.setLevel(logging.DEBUG)
+
+ try:
+ e = testing_engine()
+ e.connect().close()
+ yield e
+ finally:
+ log.setLevel(existing_level)
+
def test_begin_once_block(self, logging_engine, assert_buf):
with logging_engine.begin():
pass
]
)
+ def test_logging_compatibility(
+ self, plain_assert_buf, plain_logging_engine
+ ):
+ """ensure plain logging doesn't produce API errors.
+
+ Added as part of #7612
+
+ """
+ e = plain_logging_engine
+
+ with e.connect() as conn:
+ result = conn.exec_driver_sql("select 1")
+ result.all()
+
+ plain_assert_buf(
+ [
+ "BEGIN (implicit)",
+ "select 1",
+ "[raw sql] ()",
+ "Col ('1',)",
+ "Row (1,)",
+ "ROLLBACK",
+ ]
+ )
+
+ @testing.requires.python38
+ def test_log_messages_have_correct_metadata_plain(
+ self, plain_logging_engine
+ ):
+ """test #7612"""
+ self._test_log_messages_have_correct_metadata(plain_logging_engine)
+
+ @testing.requires.python38
+ def test_log_messages_have_correct_metadata_echo(self, logging_engine):
+ """test #7612"""
+ self._test_log_messages_have_correct_metadata(logging_engine)
+
+ def _test_log_messages_have_correct_metadata(self, logging_engine):
+ buf = logging.handlers.BufferingHandler(100)
+ log = logging.getLogger("sqlalchemy.engine")
+ try:
+ log.addHandler(buf)
+
+ with logging_engine.connect().execution_options(
+ isolation_level="AUTOCOMMIT"
+ ) as conn:
+ conn.begin()
+ conn.rollback()
+ finally:
+ log.removeHandler(buf)
+
+ assert len(buf.buffer) >= 2
+
+ # log messages must originate from functions called 'begin'/'rollback'
+ logging_functions = {rec.funcName for rec in buf.buffer}
+ assert any(
+ "begin" in fn for fn in logging_functions
+ ), logging_functions
+ assert any(
+ "rollback" in fn for fn in logging_functions
+ ), logging_functions
+
+ # log messages must originate from different lines
+ log_lines = {rec.lineno for rec in buf.buffer}
+ assert len(log_lines) > 1, log_lines
+ buf.flush()
+
class LoggingTokenTest(fixtures.TestBase):
def setup_test(self):