Skip to content

Commit

Permalink
Add string interpolation to FilteringBoundLogger
Browse files Browse the repository at this point in the history
  • Loading branch information
hynek committed Oct 7, 2022
1 parent 6bd5e01 commit 52af044
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 25 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ jobs:
fail-fast: false
matrix:
python-version:
# mypy on 3.7 fails but there's nothing we can do about it
- "3.8"
- "3.9"
- "3.10"
Expand All @@ -128,6 +129,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
# Keep in sync with tox.ini/docs & readthedocs.yml
python-version: "3.10"
- run: python -m pip install --upgrade wheel tox

Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ So please make sure to **always** properly configure your applications.
Please use [`importlib.metadata`](https://docs.python.org/3.10/library/importlib.metadata.html) instead (for Python 3.7: the [*importlib-metadata*](https://pypi.org/project/importlib-metadata/) PyPI package).


### Added

- `FilteringBoundLogger` (used by default) now allows for string interpolation using positional arguments:

```pycon
>>> log.info("Hello %s! The answer is %d.", "World", 42, x=1)
2022-10-07 10:04.31 [info ] Hello World! The answer is 42. x=1
```

[#454](https://github.com/hynek/structlog/pull/454)


### Changed

- The build backend has been switched to [*Hatch*](https://hatch.pypa.io/).
Expand Down
2 changes: 1 addition & 1 deletion readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ formats: all
build:
os: ubuntu-20.04
tools:
# Keep version in sync with tox.ini (docs and gh-actions).
# Keep version in sync with tox.ini/docs and ci.yml/docs
python: "3.10"

python:
Expand Down
4 changes: 2 additions & 2 deletions src/structlog/_log_levels.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ def make_method(level: int) -> Callable[..., Any]:

name = _LEVEL_TO_NAME[level]

def meth(self: Any, event: str, **kw: Any) -> Any:
return self._proxy_to_logger(name, event, **kw)
def meth(self: Any, event: str, *args: Any, **kw: Any) -> Any:
return self._proxy_to_logger(name, event % args, **kw)

meth.__name__ = name

Expand Down
44 changes: 23 additions & 21 deletions src/structlog/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ class FilteringBoundLogger(BindableLogger, Protocol):
The only way to instantiate one is using `make_filtering_bound_logger`.
.. versionadded:: 20.2.0
.. versionadded:: 22.2.0
String interpolation using positional arguments.
"""

def bind(self, **new_values: Any) -> FilteringBoundLogger:
Expand Down Expand Up @@ -181,53 +183,53 @@ def new(self, **new_values: Any) -> FilteringBoundLogger:
.. versionadded:: 22.1.0
"""

def debug(self, event: str, **kw: Any) -> Any:
def debug(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **debug** level.
Log ``event % args`` with **kw** at **debug** level.
"""

def info(self, event: str, **kw: Any) -> Any:
def info(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **info** level.
Log ``event % args`` with **kw** at **info** level.
"""

def warning(self, event: str, **kw: Any) -> Any:
def warning(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **warn** level.
Log ``event % args`` with **kw** at **warn** level.
"""

def warn(self, event: str, **kw: Any) -> Any:
def warn(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **warn** level.
Log ``event % args`` with **kw** at **warn** level.
"""

def error(self, event: str, **kw: Any) -> Any:
def error(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **error** level.
Log ``event % args`` with **kw** at **error** level.
"""

def err(self, event: str, **kw: Any) -> Any:
def err(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **error** level.
Log ``event % args`` with **kw** at **error** level.
"""

def fatal(self, event: str, **kw: Any) -> Any:
def fatal(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **critical** level.
Log ``event % args`` with **kw** at **critical** level.
"""

def exception(self, event: str, **kw: Any) -> Any:
def exception(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **error** level and ensure that ``exc_info``
is set in the event dictionary.
Log ``event % args`` with **kw** at **error** level and ensure that
``exc_info`` is set in the event dictionary.
"""

def critical(self, event: str, **kw: Any) -> Any:
def critical(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **critical** level.
Log ``event % args`` with **kw** at **critical** level.
"""

def msg(self, event: str, **kw: Any) -> Any:
def msg(self, event: str, *args: Any, **kw: Any) -> Any:
"""
Log *event* with **kw** at **info** level.
Log ``event % args`` with **kw** at **info** level.
"""
8 changes: 8 additions & 0 deletions tests/test_log_levels.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,11 @@ def test_pickle(self, level):
bl = make_filtering_bound_logger(level)

assert bl == pickle.loads(pickle.dumps(bl))

def test_pos_args(self, bl, cl):
"""
Positional arguments are used for string interpolation.
"""
bl.info("hello %s -- %d!", "world", 42)

assert [("info", (), {"event": "hello world -- 42!"})] == cl.calls
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ignore = E203,W503,W504
# We don't run pre-commit in CI, because we use pre-commit.ci.
[gh-actions]
python =
3.7: py37 # mypy on 3.7 fails but there's nothing we can do about it
3.7: py37
3.8: py38
3.9: py39
3.10: py310
Expand Down
3 changes: 3 additions & 0 deletions typing_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,6 @@ def typecheck_filtering_return() -> None:
structlog.processors.JSONRenderer(),
]
)

fbl: FilteringBoundLogger = structlog.get_logger()
fbl.info("Hello %s! The answer is %d.", "World", 42, x=1)

0 comments on commit 52af044

Please sign in to comment.