Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ jobs:
- uses: actions/setup-python@v5
with:
# Keep in sync with tox.ini/docs & .readthedocs.yaml
python-version: "3.12"
python-version: "3.13"
- uses: hynek/setup-cached-uv@v2

- run: >
Expand Down
26 changes: 11 additions & 15 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,16 @@ build:
os: ubuntu-lts-latest
tools:
# Keep version in sync with tox.ini/docs and ci.yml/docs.
python: "3.12"
jobs:
# Need the tags to calculate the version.
post_checkout:
- git fetch --tags
python: "3.13"
commands:
# Need the tags to calculate the version (sometimes).
- git fetch --tags
- asdf plugin add uv
- asdf install uv latest
- asdf global uv latest

# Replace versions in sponsor URLs.
pre_build:
- python -Im pip install tox-uv
- python -Im tox run -e docs-sponsors
- uvx --with tox-uv tox run -e docs-sponsors
- uvx --with tox-uv tox run -e docs -- $READTHEDOCS_OUTPUT

python:
install:
- method: pip
path: .
extra_requirements:
- docs
sphinx:
configuration: docs/conf.py
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions docs/_static/custom.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url('https://rsms.me/inter/inter.css');
@import url(https://fonts.bunny.net/css?family=b612:400,400i,700,700i);
@import url('https://assets.hynek.me/css/bm.css');


Expand All @@ -9,12 +9,12 @@

@supports (font-variation-settings: normal) {
:root {
font-family: InterVariable, sans-serif;
font-family: 'B612', sans-serif;
}
}


/* Hide ToC caption text within the main body (but leave them in the side-bar). */
#furo-main-content span.caption-text {
display: none;
}
}
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
html_theme_options = {
"top_of_page_buttons": [],
"light_css_variables": {
"font-stack": "Inter, sans-serif",
"font-stack": "B612, sans-serif",
"font-stack--monospace": "BerkeleyMono, MonoLisa, ui-monospace, "
"SFMono-Regular, Menlo, Consolas, Liberation Mono, monospace",
},
Expand Down
12 changes: 11 additions & 1 deletion src/structlog/_native.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
ERROR,
INFO,
LEVEL_TO_NAME,
NAME_TO_LEVEL,
NOTSET,
WARNING,
)
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -103,12 +106,19 @@ def make_filtering_bound_logger(min_level: int) -> type[FilteringBoundLogger]:
<https://docs.python.org/3/library/logging.html#levels>`_ 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]

Expand Down
10 changes: 10 additions & 0 deletions tests/test_log_levels.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
7 changes: 4 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ commands =

[testenv:docs]
# Keep base_python in sync with ci.yml/docs and .readthedocs.yaml.
base_python = py312
base_python = py313
extras = docs
commands =
sphinx-build -n -T -W -b html -d {envtmpdir}/doctrees docs docs/_build/html
sphinx-build -n -T -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
sphinx-build -n -T -W -b html -d {envtmpdir}/doctrees docs {posargs:docs/_build/}html
sphinx-build -n -T -W -b doctest -d {envtmpdir}/doctrees docs {posargs:docs/_build/}html


[testenv:docs-watch]
package = editable
Expand Down
Loading