From c7a6a101fdf644fd8c1ece7388ff1405895f3a4a Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Mon, 13 Jan 2025 09:29:05 +0100 Subject: [PATCH] Allow make_filtering_bound_logger to receive a str for level fixes #665 --- CHANGELOG.md | 2 ++ src/structlog/_native.py | 12 +++++++++++- tests/test_log_levels.py | 10 ++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 598f30df..d85cc191 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,8 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/ - `structlog.stdlib.recreate_defaults()` now also adds `structlog.stdlib.PositionalArgumentsFormatter`. In default native mode, this is done by the loggers at the edge. +- `structlog.make_filtering_bound_logger()` now also accepts a string for *min_level*. + ## Fixed diff --git a/src/structlog/_native.py b/src/structlog/_native.py index dedf8a6c..86bb7d4e 100644 --- a/src/structlog/_native.py +++ b/src/structlog/_native.py @@ -22,6 +22,7 @@ ERROR, INFO, LEVEL_TO_NAME, + NAME_TO_LEVEL, NOTSET, WARNING, ) @@ -70,7 +71,9 @@ async def aexception( return runner -def make_filtering_bound_logger(min_level: int) -> type[FilteringBoundLogger]: +def make_filtering_bound_logger( + min_level: int | str, +) -> type[FilteringBoundLogger]: """ Create a new `FilteringBoundLogger` that only logs *min_level* or higher. @@ -103,12 +106,19 @@ def make_filtering_bound_logger(min_level: int) -> type[FilteringBoundLogger]: `_ for possible values. + If you pass a string, it must be one of: ``critical``, ``error``, + ``warning``, ``info``, ``debug``, ``notset`` (upper/lower case + doesn't matter). + .. versionadded:: 20.2.0 .. versionchanged:: 21.1.0 The returned loggers are now pickleable. .. versionadded:: 20.1.0 The ``log()`` method. .. versionadded:: 22.2.0 Async variants ``alog()``, ``adebug()``, ``ainfo()``, and so forth. + .. versionchanged:: 25.1.0 *min_level* can now be a string. """ + if isinstance(min_level, str): + min_level = NAME_TO_LEVEL[min_level.lower()] return LEVEL_TO_FILTERING_LOGGER[min_level] diff --git a/tests/test_log_levels.py b/tests/test_log_levels.py index 2dec4f08..30aa7a79 100644 --- a/tests/test_log_levels.py +++ b/tests/test_log_levels.py @@ -10,6 +10,7 @@ from structlog import make_filtering_bound_logger from structlog._log_levels import LEVEL_TO_NAME +from structlog._native import _nop from structlog.contextvars import ( bind_contextvars, clear_contextvars, @@ -314,3 +315,12 @@ def test_log_percent(self, bl, cl): bl.info("hey %! %%!") assert [("info", (), {"event": "hey %! %%!"})] == cl.calls + + def test_log_level_str(self): + """ + *min_level* can be a string and the case doesn't matter. + """ + bl = make_filtering_bound_logger("wArNiNg") + + assert bl.warning is not _nop + assert bl.info is _nop