From 2b1b8ecc0b939f0d4d87b3a9e6c79ec1e965f24e Mon Sep 17 00:00:00 2001 From: r266-tech Date: Mon, 23 Mar 2026 03:16:36 +0800 Subject: [PATCH] Add consistent snake_case/camelCase aliases for is_enabled_for & getEffectiveLevel Fixes #779: BoundLogger and BoundLoggerFilteringAtNotset now both support both / and /. Previously: - BoundLoggerFilteringAtNotset only had snake_case (is_enabled_for, get_effective_level) - BoundLogger only had camelCase (isEnabledFor, getEffectiveLevel) This caused AttributeError when the same code path hit both classes. --- src/structlog/_native.py | 2 ++ src/structlog/stdlib.py | 24 ++++++++++++++++++------ src/structlog/typing.py | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/structlog/_native.py b/src/structlog/_native.py index 4d0926de..27c42236 100644 --- a/src/structlog/_native.py +++ b/src/structlog/_native.py @@ -238,7 +238,9 @@ async def alog( # Introspection meths["is_enabled_for"] = lambda self, level: level >= min_level + meths["isEnabledFor"] = meths["is_enabled_for"] meths["get_effective_level"] = lambda self: min_level + meths["getEffectiveLevel"] = meths["get_effective_level"] return type( f"BoundLoggerFilteringAt{LEVEL_TO_NAME.get(min_level, 'Notset').capitalize()}", diff --git a/src/structlog/stdlib.py b/src/structlog/stdlib.py index 2ed978fd..69890972 100644 --- a/src/structlog/stdlib.py +++ b/src/structlog/stdlib.py @@ -394,6 +394,24 @@ def callHandlers(self, record: logging.LogRecord) -> None: """ self._logger.callHandlers(record) + def isEnabledFor(self, level: int) -> bool: + """ + Calls :meth:`logging.Logger.isEnabledFor` with unmodified arguments. + """ + return self._logger.isEnabledFor(level) + + def is_enabled_for(self, level: int) -> bool: + """ + Alias for :meth:`isEnabledFor` for snake_case consistency. + """ + return self.isEnabledFor(level) + + def get_effective_level(self) -> int: + """ + Alias for :meth:`getEffectiveLevel` for snake_case consistency. + """ + return self.getEffectiveLevel() + def getEffectiveLevel(self) -> int: """ Calls :meth:`logging.Logger.getEffectiveLevel` with unmodified @@ -401,12 +419,6 @@ def getEffectiveLevel(self) -> int: """ return self._logger.getEffectiveLevel() - def isEnabledFor(self, level: int) -> bool: - """ - Calls :meth:`logging.Logger.isEnabledFor` with unmodified arguments. - """ - return self._logger.isEnabledFor(level) - def getChild(self, suffix: str) -> logging.Logger: """ Calls :meth:`logging.Logger.getChild` with unmodified arguments. diff --git a/src/structlog/typing.py b/src/structlog/typing.py index 2cfd9cb2..e408fc11 100644 --- a/src/structlog/typing.py +++ b/src/structlog/typing.py @@ -198,6 +198,13 @@ def is_enabled_for(self, level: int) -> bool: .. versionadded:: 25.1.0 """ + def isEnabledFor(self, level: int) -> bool: + """ + Alias for :meth:`is_enabled_for`. + + .. versionadded:: 25.2.0 + """ + def get_effective_level(self) -> int: """ Return the effective level of the logger. @@ -205,6 +212,13 @@ def get_effective_level(self) -> int: .. versionadded:: 25.1.0 """ + def getEffectiveLevel(self) -> int: + """ + Alias for :meth:`get_effective_level`. + + .. versionadded:: 25.2.0 + """ + def debug(self, event: str, *args: Any, **kw: Any) -> Any: """ Log ``event % args`` with **kw** at **debug** level.