Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
bc147a4
Only build in RTD and only doctests in CI (#691)
hynek Jan 16, 2025
4350cdd
Try if test PyPI will deduct the correct license with lower 2.3 metadata
hynek Jan 16, 2025
02d072a
Makes no difference
hynek Jan 16, 2025
3eab3e9
Fix changelog headings
hynek Jan 16, 2025
c5803e8
Consistency
hynek Jan 16, 2025
a38a5ac
Prepare 25.1.0
hynek Jan 16, 2025
2197fbc
Start new development cycle
hynek Jan 16, 2025
177f346
docs: stdlib polish
hynek Jan 21, 2025
fe29e5c
update ruff
hynek Jan 21, 2025
20f246f
docset: ust --icon-2x instead of cp
hynek Jan 22, 2025
0fe9840
sponsors: add Privacy Solutions
hynek Jan 22, 2025
a35ee31
Add white background
hynek Jan 22, 2025
42452dc
Fix aspect
hynek Jan 22, 2025
03b5143
Typing: return Self in stdlib.BoundLogger (#694)
k4nar Jan 27, 2025
4eb2646
Add changelog entry for #694
hynek Jan 27, 2025
d8f4e6e
pre-commit autoupdate
hynek Jan 27, 2025
c2de5c3
Include notes when logging exceptions (#684)
camillol Feb 3, 2025
66e22d2
pre-commit update
hynek Feb 3, 2025
ea7cac4
expose RichTracebackFormatter for imports in structlog.dev (#699)
keongalvin Feb 19, 2025
768931a
expose LogfmtRenderer for imports (#701)
keongalvin Feb 25, 2025
08aba07
[pre-commit.ci] pre-commit autoupdate (#704)
pre-commit-ci[bot] Mar 6, 2025
7555f0c
sponsors: update tiers
hynek Mar 6, 2025
2f0cc42
run cog
hynek Mar 6, 2025
3a7006d
Clarify sentence about get_logger() arguments (#706)
ttrei Mar 7, 2025
1600b0f
TimeStamper() now uses TZ-aware objects (#709)
hynek Mar 8, 2025
482fbab
update ruff
hynek Mar 11, 2025
e948850
Prepare 25.2.0
hynek Mar 11, 2025
244fde4
Start new development cycle
hynek Mar 11, 2025
414047d
update Ruff
hynek Apr 8, 2025
1b8680e
TimeStamper now returns UTC timezone for custom format string. (#713)
m-endra Apr 25, 2025
4c844e8
docs: polish changelog
hynek Apr 25, 2025
637dce6
update ruff
hynek Apr 25, 2025
edfa953
Prepare 25.3.0
hynek Apr 25, 2025
677d00b
Start new development cycle
hynek Apr 25, 2025
4ce82b0
docs: fix typo
hynek May 1, 2025
3c275ea
[pre-commit.ci] pre-commit autoupdate (#722)
pre-commit-ci[bot] May 5, 2025
2e8e34f
docs/threadlocal: mention #591
hynek May 9, 2025
12d04df
Add 3.14 (#723)
hynek May 28, 2025
12494f1
Mention the logging fixes are for the next 3.13 point release too
hynek May 28, 2025
02e1243
update Ruff
hynek May 28, 2025
d887c00
Use dependency groups (#725)
hynek May 29, 2025
de3dfc8
fix ExceptionPrettyPrinter custom formatter support (#724)
anujdas May 29, 2025
f07c136
tracebacks: Handle ExceptionGroup (#720)
sscherfke May 29, 2025
5d9c7f8
docs: clarify compat
hynek May 29, 2025
bcc2df8
docs: add missing link
hynek May 29, 2025
5e57018
Make Dr Zizmor happy
hynek May 29, 2025
034f067
Add explanation
hynek May 29, 2025
ea14fda
Oxford!
hynek May 29, 2025
d948027
Update Ruff
hynek May 29, 2025
e941e33
ci: work around weird new failure in Mypy 1.16
hynek May 30, 2025
57e165b
Make Mypy 1.16 pass
hynek May 30, 2025
d38385c
Prepare 25.4.0
hynek Jun 2, 2025
480ae5f
Start new development cycle
hynek Jun 2, 2025
bc753c2
ci: fix Pyright job name
hynek Jul 4, 2025
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
12 changes: 9 additions & 3 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ test -d .venv || uv venv --python python$(cat .python-version-default)
Change into the newly created directory and after activating a virtual environment, install an editable version of this project along with its tests requirements:

```console
$ pip install -e .[dev] # or `uv pip install -e .[dev]`
$ pip install -e . --group dev # or `uv pip install -e . --group dev`
```

Now you can run the test suite:
Expand All @@ -93,14 +93,20 @@ $ tox run -e docs-watch

This will build the documentation, watch for changes, and rebuild it whenever you save a file.

To just build the documentation and run doctests, use:
To just build the documentation and exit immediately use:

```console
$ tox run -e docs
$ tox run -e docs-build
```

You will find the built documentation in `docs/_build/html`.

To run doctests:

```console
$ tox run -e docs-doctests
```


## Code

Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ jobs:


pyright:
name: Pyright Codebase
name: Pyright API
runs-on: ubuntu-latest
needs: build-package
steps:
Expand All @@ -171,7 +171,7 @@ jobs:


docs:
name: Build docs & run doctests
name: Run doctests
needs: build-package
runs-on: ubuntu-latest
steps:
Expand All @@ -189,7 +189,7 @@ jobs:

- run: >
uvx --with tox-uv
tox run -e docs
tox run -e docs-doctests


install-dev:
Expand All @@ -209,7 +209,7 @@ jobs:
- uses: hynek/setup-cached-uv@v2

- run: uv venv
- run: uv pip install -e .[dev]
- run: uv pip install -e . --group dev

- run: .venv/bin/python -Ic 'import structlog; print(structlog.__version__)'
if: runner.os != 'Windows'
Expand All @@ -232,7 +232,7 @@ jobs:

steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
with:
jobs: ${{ toJSON(needs) }}

Expand Down
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ ci:

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.1
rev: v0.11.12
hooks:
- id: ruff
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format

Expand All @@ -17,10 +17,10 @@ repos:
args: [tests]

- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
rev: v2.4.1
hooks:
- id: codespell
args: [-L, alog]
args: [-L, alog, -L, abl]

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
Expand Down
21 changes: 11 additions & 10 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ build:
tools:
# Keep version in sync with tox.ini/docs and ci.yml/docs.
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
jobs:
create_environment:
# Need the tags to calculate the version (sometimes).
- git fetch --tags

- uvx --with tox-uv tox run -e docs-sponsors
- uvx --with tox-uv tox run -e docs -- $READTHEDOCS_OUTPUT
- asdf plugin add uv
- asdf install uv latest
- asdf global uv latest

sphinx:
configuration: docs/conf.py
build:
html:
- uvx --with tox-uv tox run -e docs-sponsors
- uvx --with tox-uv tox run -e docs-build -- $READTHEDOCS_OUTPUT
70 changes: 61 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,65 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/
<!-- changelog follows -->


## [Unreleased](https://github.com/hynek/structlog/compare/24.4.0...HEAD)
## [Unreleased](https://github.com/hynek/structlog/compare/25.4.0...HEAD)


## [25.4.0](https://github.com/hynek/structlog/compare/25.3.0...25.4.0) - 2025-06-02

### Added

- Support for Python 3.14 and Python 3.13.4.

Python 3.14 has an backwards-incompatible change to `logging.Logger.isEnabledFor()` (it now always returns False if a log entry is in flight) that has been backported to 3.13.4 (expected on 2025-06-03).
It mainly affects `structlog.stdlib.filter_by_level()`.
[#723](https://github.com/hynek/structlog/pull/723)

- `structlog.tracebacks` now handles [exception groups](https://docs.python.org/3/library/exceptions.html#exception-groups).
`structlog.tracebacks.Stack` has two new fields, `is_group: bool` and `exceptions: list[Trace]`.
This works similarly to what Rich v14.0.0 does.
[#720](https://github.com/hynek/structlog/pull/720)


### Fixed

- `structlog.processors.ExceptionPrettyPrinter` now respects the *exception_formatter* arguments instead of always using the default formatter.
[#724](https://github.com/hynek/structlog/pull/724)


## [25.3.0](https://github.com/hynek/structlog/compare/25.2.0...25.3.0) - 2025-04-25

### Fixed

- `structlog.processors.TimeStamper` now again uses timestamps using UTC for custom format strings when `utc=True`.
[#713](https://github.com/hynek/structlog/pull/713)


## [25.2.0](https://github.com/hynek/structlog/compare/25.1.0...25.2.0) - 2025-03-11

### Added

- `structlog.tracebacks.Stack` now includes an `exc_notes` field reflecting the notes attached to the exception.
[#684](https://github.com/hynek/structlog/pull/684)


### Changed

- `structlog.stdlib.BoundLogger`'s binding-related methods now also return `Self`.
[#694](https://github.com/hynek/structlog/pull/694)

- `structlog.processors.TimeStamper` now produces internally timezone-aware `datetime` objects.
Default output hasn't changed, but you can now use `%z` in your *fmt* string.
[#709](https://github.com/hynek/structlog/pull/709)


### Fixed

- Expose `structlog.dev.RichTracebackFormatter` for imports.
[#699](https://github.com/hynek/structlog/pull/699)
- Expose `structlog.processors.LogfmtRenderer` for imports.
[#701](https://github.com/hynek/structlog/pull/701)

## [25.1.0](https://github.com/hynek/structlog/compare/24.4.0...25.1.0) - 2025-01-16

### Added

Expand All @@ -26,16 +84,14 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/
[#689](https://github.com/hynek/structlog/pull/689)


## Changed
### Changed

- `structlog.typing.BindableLogger` protocol now returns `Self` instead of `BindableLogger`.
This adds a dependency on [*typing-extensions*](https://pypi.org/project/typing-extensions/) for Pythons older than 3.11.

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

- `structlog.dev.ConsoleRenderer` will quote string value with special characters.

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

- `structlog.stdlib.recreate_defaults()` now also adds `structlog.stdlib.PositionalArgumentsFormatter`.
Expand All @@ -44,28 +100,24 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/
- `structlog.make_filtering_bound_logger()` now also accepts a string for *min_level*.


## Fixed
### Fixed

- Fix handling calls to `{logger}.exception()` outside of exception blocks.
Depending on the structlog configuration,
this either resulted in an event dict key `exception: "MISSING"` or lead to an error.
Now, an invalid or missing `exc_info` will just be ignored.
This means, that calling `{logger}.exception()` outside of an exception block is basically the same as calling `{logger}.error()`.

[#634](https://github.com/hynek/structlog/issues/634)
[#680](https://github.com/hynek/structlog/pull/680)

- Instantiating `structlog.dev.ConsoleRenderer` does not mutate the passed *styles* dict anymore.

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

- The native `FilteringBoundLogger.fatal()` method now maps to the critical level, as it does in the standard library.
Note that the level is discouraged to use there, so we recommend to stick to `error()` or `critical()`.

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

- `structlog.tracebacks.ExceptionDictTransformer` now actually accepts `None` for `locals_max_length` and `locals_max_string`.

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


Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ for sponsor in tomllib.loads(pathlib.Path("pyproject.toml").read_text())["tool"]
<a href="https://www.variomedia.de/"><img title="Variomedia AG" src="docs/_static/sponsors/Variomedia.svg" width="190" /></a>
<a href="https://tidelift.com/?utm_source=lifter&utm_medium=referral&utm_campaign=hynek"><img title="Tidelift" src="docs/_static/sponsors/Tidelift.svg" width="190" /></a>
<a href="https://klaviyo.com/"><img title="Klaviyo" src="docs/_static/sponsors/Klaviyo.svg" width="190" /></a>
<a href="https://privacy-solutions.org/"><img title="Privacy Solutions" src="docs/_static/sponsors/Privacy-Solutions.svg" width="190" /></a>
<a href="https://www.emsys-renewables.com/"><img title="emsys renewables" src="docs/_static/sponsors/emsys-renewables.svg" width="190" /></a>
<a href="https://filepreviews.io/"><img title="FilePreviews" src="docs/_static/sponsors/FilePreviews.svg" width="190" /></a>
<a href="https://polar.sh/"><img title="Polar" src="docs/_static/sponsors/Polar.svg" width="190" /></a>
Expand Down
1 change: 1 addition & 0 deletions docs/_static/sponsors/Privacy-Solutions.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ API Reference
... 1 / 0
... except ZeroDivisionError:
... log.exception("Cannot compute!")
{"event": "Cannot compute!", "exception": [{"exc_type": "ZeroDivisionError", "exc_value": "division by zero", "syntax_error": null, "is_cause": false, "frames": [{"filename": "<doctest default[3]>", "lineno": 2, "name": "<module>", "locals": {..., "var": "'spam'"}}]}]}
{"event": "Cannot compute!", "exception": [{"exc_type": "ZeroDivisionError", "exc_value": "division by zero", "exc_notes": [], "syntax_error": null, "is_cause": false, "frames": [{"filename": "<doctest default[3]>", "lineno": 2, "name": "<module>", "locals": {..., "var": "'spam'"}}], "is_group": false, "exceptions": []}]}

.. autoclass:: KeyValueRenderer

Expand Down
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ It's a callable that returns the logger that gets wrapped and returned.
In the simplest case, it's a function that returns a logger -- or just a class.
But you can also pass in an instance of a class with a `__call__` method for more complicated setups.

These will be passed to the logger factories.
The arguments you pass to `structlog.get_logger()` will be passed to the logger factory.
For example, if you use `structlog.get_logger("a name")` and configure *structlog* to use the standard library {class}`~structlog.stdlib.LoggerFactory`, which has support for positional parameters, the returned logger will have the name `"a name"`.

For the common cases of standard library logging and Twisted logging, *structlog* comes with two factories built right in:
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ for sponsor in tomllib.loads(pathlib.Path("pyproject.toml").read_text())["tool"]
<a href="https://www.variomedia.de/"><img title="Variomedia AG" src="_static/sponsors/Variomedia.svg" width="190" /></a>
<a href="https://tidelift.com/?utm_source=lifter&utm_medium=referral&utm_campaign=hynek"><img title="Tidelift" src="_static/sponsors/Tidelift.svg" width="190" /></a>
<a href="https://klaviyo.com/"><img title="Klaviyo" src="_static/sponsors/Klaviyo.svg" width="190" /></a>
<a href="https://privacy-solutions.org/"><img title="Privacy Solutions" src="_static/sponsors/Privacy-Solutions.svg" width="190" /></a>
<a href="https://www.emsys-renewables.com/"><img title="emsys renewables" src="_static/sponsors/emsys-renewables.svg" width="190" /></a>
<a href="https://filepreviews.io/"><img title="FilePreviews" src="_static/sponsors/FilePreviews.svg" width="190" /></a>
<a href="https://polar.sh/"><img title="Polar" src="_static/sponsors/Polar.svg" width="190" /></a>
Expand Down
Loading
Loading