From 2438241447da810e2b3dee0d441286c5c2701e02 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Mon, 16 Oct 2023 11:46:34 +0200 Subject: [PATCH] Make instances of BoundLoggerLazyProxy BindableLoggers on Python 3.12 Fixes #560 --- CHANGELOG.md | 5 +++++ src/structlog/_config.py | 5 +++++ src/structlog/threadlocal.py | 2 +- tests/test_config.py | 11 +++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc418de2..68e5ce48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,11 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/ ## [Unreleased](https://github.com/hynek/structlog/compare/23.2.0...HEAD) +### Fixed + +- The return value from `get_logger()` (a `BoundLoggerLazyProxy`) now passes `isinstance`-checks against `structlog.typing.BindableLogger` on Python 3.12. + + ## [23.2.0](https://github.com/hynek/structlog/compare/23.1.0...23.2.0) - 2023-10-09 diff --git a/src/structlog/_config.py b/src/structlog/_config.py index 718bcfb6..0263b054 100644 --- a/src/structlog/_config.py +++ b/src/structlog/_config.py @@ -315,6 +315,11 @@ class BoundLoggerLazyProxy: .. versionchanged:: 0.4.0 Added support for *logger_factory_args*. """ + # fulfill BindableLogger protocol without carrying accidental state + @property + def _context(self) -> dict[str, str]: + return {} + def __init__( self, logger: WrappedLogger | None, diff --git a/src/structlog/threadlocal.py b/src/structlog/threadlocal.py index 6ddb75df..a1cfd86b 100644 --- a/src/structlog/threadlocal.py +++ b/src/structlog/threadlocal.py @@ -119,7 +119,7 @@ def as_immutable(logger: TLLogger) -> TLLogger: """ _deprecated() if isinstance(logger, BoundLoggerLazyProxy): - logger = logger.bind() # type: ignore[assignment] + logger = logger.bind() try: ctx = logger._context._tl.dict_.__class__( # type: ignore[union-attr] diff --git a/tests/test_config.py b/tests/test_config.py index 5e741d5d..f9a9f8eb 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -26,6 +26,7 @@ get_logger, wrap_logger, ) +from structlog.typing import BindableLogger @pytest.fixture(name="proxy") @@ -56,6 +57,16 @@ class Foo(metaclass=abc.ABCMeta): Foo() +def test_lazy_logger_is_an_instance_of_bindable_logger(): + """ + The BoundLoggerLazyProxy returned by get_logger fulfills the BindableLogger + protocol. + + See https://github.com/hynek/structlog/issues/560 + """ + assert isinstance(get_logger(), BindableLogger) + + def test_default_context_class(): """ Default context class is dict.