Skip to content

🐛 fix(win): eliminate lock file race in threaded usage#484

Merged
gaborbernat merged 1 commit intotox-dev:mainfrom
gaborbernat:fix-flaky-windows-threaded-tests
Feb 14, 2026
Merged

🐛 fix(win): eliminate lock file race in threaded usage#484
gaborbernat merged 1 commit intotox-dev:mainfrom
gaborbernat:fix-flaky-windows-threaded-tests

Conversation

@gaborbernat
Copy link
Copy Markdown
Member

@gaborbernat gaborbernat commented Feb 14, 2026

The Windows threaded lock tests flake on CI because _release() calls unlink() after close(), but between those two calls another thread has already acquired an open handle via os.open(). Since CPython's _wopen doesn't set FILE_SHARE_DELETE, Windows refuses the deletion — and the suppressed unlink() just widens the race window for no benefit. On top of that, O_TRUNC in _acquire() maps to CREATE_ALWAYS in CreateFileW, which causes EACCES when truncating a file that other threads hold open, pushing contending threads into the retry loop at the os.open level rather than just at msvcrt.locking.

The fix removes unlink() from _release() entirely — the lock file persists on disk, but _acquire() already handles existing files via O_CREAT, and the base class documents that lock files are not automatically deleted. It also drops O_TRUNC from _acquire(), since lock file content is irrelevant; only the msvcrt.locking byte-range lock provides mutual exclusion. Without O_TRUNC, O_RDWR | O_CREAT maps to OPEN_ALWAYS, which opens without truncation and avoids the write-sharing conflict.

With both race conditions eliminated, the threaded tests no longer need reduced iteration counts on Windows and now run at full Unix-equivalent intensity (100×100 and 10×1000).

@gaborbernat gaborbernat force-pushed the fix-flaky-windows-threaded-tests branch from d7b6ed7 to 28546c7 Compare February 14, 2026 05:35
@gaborbernat gaborbernat changed the title 🐛 fix(test): reduce threaded stress on Windows 🐛 fix(win): eliminate lock file race in threaded usage Feb 14, 2026
On Windows, _release() called unlink() after close(), but between those
calls another thread would already hold an open handle via os.open(),
preventing deletion (Windows can't delete files with open handles).
The suppressed unlink added a syscall that widened the race window for
no benefit. Additionally, O_TRUNC in _acquire() mapped to CREATE_ALWAYS
which caused EACCES when truncating a file with open handles from other
threads, pushing them into the retry loop at the os.open level.

Remove unlink() from _release() — the lock file persists on disk but
_acquire() already handles existing files via O_CREAT. Remove O_TRUNC
from _acquire() — lock file content is irrelevant, only the msvcrt
byte-range lock matters. This lets the threaded tests run at full
Unix-equivalent intensity on Windows.
@gaborbernat gaborbernat force-pushed the fix-flaky-windows-threaded-tests branch from 28546c7 to 3dc2db2 Compare February 14, 2026 05:40
@gaborbernat gaborbernat enabled auto-merge (squash) February 14, 2026 05:41
@gaborbernat gaborbernat disabled auto-merge February 14, 2026 05:50
@gaborbernat gaborbernat merged commit 23b797c into tox-dev:main Feb 14, 2026
31 checks passed
TheoPascoli added a commit to AntaresSimulatorTeam/AntaREST that referenced this pull request Mar 2, 2026
> ℹ️ **Note**
> 
> This PR body was truncated due to platform limits.

This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [MarkupSafe](https://redirect.github.com/pallets/markupsafe)
([changelog](https://markupsafe.palletsprojects.com/page/changes/)) |
`~=2.0.1` → `~=2.1.5` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/markupsafe/2.1.5?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/markupsafe/2.0.1/2.1.5?slim=true)
|
| [PyJWT](https://redirect.github.com/jpadilla/pyjwt) | `~=2.9.0` →
`~=2.11.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/pyjwt/2.11.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pyjwt/2.9.0/2.11.0?slim=true)
|
| [alembic](https://redirect.github.com/sqlalchemy/alembic)
([changelog](https://alembic.sqlalchemy.org/en/latest/changelog.html)) |
`~=1.16.5` → `~=1.18.4` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/alembic/1.18.4?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/alembic/1.16.5/1.18.4?slim=true)
|
| [celery](https://docs.celeryq.dev/)
([source](https://redirect.github.com/celery/celery),
[changelog](https://docs.celeryq.dev/en/stable/changelog.html)) |
`~=5.5.0` → `~=5.6.2` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/celery/5.6.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/celery/5.5.3/5.6.2?slim=true)
|
| [celery-types](https://redirect.github.com/sbdchd/celery-types) |
`~=0.23.0` → `~=0.24.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/celery-types/0.24.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/celery-types/0.23.0/0.24.0?slim=true)
|
| [checksumdir](https://redirect.github.com/cakepietoast/checksumdir) |
`~=1.2.0` → `~=1.3.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/checksumdir/1.3.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/checksumdir/1.2.0/1.3.0?slim=true)
|
| [fastapi](https://redirect.github.com/fastapi/fastapi)
([changelog](https://fastapi.tiangolo.com/release-notes/)) | `==0.130.0`
→ `==0.133.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/fastapi/0.133.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/fastapi/0.130.0/0.133.0?slim=true)
|
| [filelock](https://redirect.github.com/tox-dev/py-filelock) |
`~=3.20.3` → `~=3.24.3` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/filelock/3.24.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/filelock/3.20.3/3.24.3?slim=true)
|
| [httpx](https://redirect.github.com/encode/httpx)
([changelog](https://redirect.github.com/encode/httpx/blob/master/CHANGELOG.md))
| `~=0.27.0` → `~=0.28.1` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/httpx/0.28.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/httpx/0.27.2/0.28.1?slim=true)
|
| [humanize](https://redirect.github.com/python-humanize/humanize)
([changelog](https://redirect.github.com/python-humanize/humanize/releases))
| `~=4.11.0` → `~=4.15.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/humanize/4.15.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/humanize/4.11.0/4.15.0?slim=true)
|
| [mypy](https://redirect.github.com/python/mypy)
([changelog](https://mypy.readthedocs.io/en/latest/changelog.html)) |
`~=1.15.0` → `~=1.19.1` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/mypy/1.19.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/mypy/1.15.0/1.19.1?slim=true)
|
| [numexpr](https://redirect.github.com/pydata/numexpr) | `==2.13.1` →
`==2.14.1` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/numexpr/2.14.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/numexpr/2.13.1/2.14.1?slim=true)
|
| [numpy](https://redirect.github.com/numpy/numpy)
([changelog](https://numpy.org/doc/stable/release)) | `~=2.3.5` →
`~=2.4.2` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/numpy/2.4.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/numpy/2.3.5/2.4.2?slim=true)
|
| [plyer](https://plyer.readthedocs.org/en/latest/) | `~=2.0.0` →
`~=2.1.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/plyer/2.1.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/plyer/2.0.0/2.1.0?slim=true)
|
| [pre-commit](https://redirect.github.com/pre-commit/pre-commit) |
`~=4.1.0` → `~=4.5.1` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/pre-commit/4.5.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pre-commit/4.1.0/4.5.1?slim=true)
|
|
[prometheus-client](https://redirect.github.com/prometheus/client_python)
| `==0.23.1` → `==0.24.1` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/prometheus-client/0.24.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/prometheus-client/0.23.1/0.24.1?slim=true)
|
| [py7zr](https://redirect.github.com/miurahr/py7zr)
([changelog](https://py7zr.readthedocs.io/en/latest/Changelog.html)) |
`~=0.20.6` → `~=0.22.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/py7zr/0.22.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/py7zr/0.20.8/0.22.0?slim=true)
|
| [pyinstaller](https://redirect.github.com/pyinstaller/pyinstaller)
([changelog](https://pyinstaller.org/en/stable/CHANGES.html)) |
`==6.17.0` → `==6.19.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/pyinstaller/6.19.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pyinstaller/6.17.0/6.19.0?slim=true)
|
|
[pyinstaller-hooks-contrib](https://redirect.github.com/pyinstaller/pyinstaller-hooks-contrib)
| `==2025.10` → `==2026.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/pyinstaller-hooks-contrib/2026.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pyinstaller-hooks-contrib/2025.10/2026.0?slim=true)
|
| [redis](https://redirect.github.com/redis/redis-py)
([changelog](https://redirect.github.com/redis/redis-py/releases)) |
`~=5.2.0` → `~=5.3.1` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/redis/5.3.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/redis/5.2.1/5.3.1?slim=true)
|
| [ruff](https://docs.astral.sh/ruff)
([source](https://redirect.github.com/astral-sh/ruff),
[changelog](https://redirect.github.com/astral-sh/ruff/blob/main/CHANGELOG.md))
| `~=0.9.6` → `~=0.15.2` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/ruff/0.15.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/ruff/0.9.10/0.15.2?slim=true)
|
| [types-redis](https://redirect.github.com/python/typeshed)
([changelog](https://redirect.github.com/typeshed-internal/stub_uploader/blob/main/data/changelogs/redis.md))
| `~=4.1.2` → `~=4.6.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/types-redis/4.6.0.20241004?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/types-redis/4.1.22/4.6.0.20241004?slim=true)
|
| [types-requests](https://redirect.github.com/python/typeshed)
([changelog](https://redirect.github.com/typeshed-internal/stub_uploader/blob/main/data/changelogs/requests.md))
| `~=2.27.1` → `~=2.32.4` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/types-requests/2.32.4.20260107?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/types-requests/2.27.31/2.32.4.20260107?slim=true)
|
| [uvicorn](https://redirect.github.com/Kludex/uvicorn)
([changelog](https://uvicorn.dev/release-notes)) | `~=0.37.0` →
`~=0.41.0` |
![age](https://developer.mend.io/api/mc/badges/age/pypi/uvicorn/0.41.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/uvicorn/0.37.0/0.41.0?slim=true)
|

---

### Release Notes

<details>
<summary>pallets/markupsafe (MarkupSafe)</summary>

###
[`v2.1.5`](https://redirect.github.com/pallets/markupsafe/blob/HEAD/CHANGES.rst#Version-215)

[Compare
Source](https://redirect.github.com/pallets/markupsafe/compare/2.1.4...2.1.5)

Released 2024-02-02

- Fix `striptags` not collapsing spaces. :issue:`417`

###
[`v2.1.4`](https://redirect.github.com/pallets/markupsafe/blob/HEAD/CHANGES.rst#Version-214)

[Compare
Source](https://redirect.github.com/pallets/markupsafe/compare/2.1.3...2.1.4)

Released 2024-01-19

- Don't use regular expressions for `striptags`, avoiding a performance
  issue. :pr:`413`

###
[`v2.1.3`](https://redirect.github.com/pallets/markupsafe/blob/HEAD/CHANGES.rst#Version-213)

[Compare
Source](https://redirect.github.com/pallets/markupsafe/compare/2.1.2...2.1.3)

Released 2023-06-02

- Implement `format_map`, `casefold`, `removeprefix`, and `removesuffix`
  methods. :issue:`370`
- Fix static typing for basic `str` methods on `Markup`. :issue:`358`
- Use `Self` for annotating return types. :pr:`379`

###
[`v2.1.2`](https://redirect.github.com/pallets/markupsafe/blob/HEAD/CHANGES.rst#Version-212)

[Compare
Source](https://redirect.github.com/pallets/markupsafe/compare/2.1.1...2.1.2)

Released 2023-01-17

- Fix `striptags` not stripping tags containing newlines.
  :issue:`310`

###
[`v2.1.1`](https://redirect.github.com/pallets/markupsafe/blob/HEAD/CHANGES.rst#Version-211)

[Compare
Source](https://redirect.github.com/pallets/markupsafe/compare/2.1.0...2.1.1)

Released 2022-03-14

- Avoid ambiguous regex matches in `striptags`. :pr:`293`

###
[`v2.1.0`](https://redirect.github.com/pallets/markupsafe/blob/HEAD/CHANGES.rst#Version-210)

[Compare
Source](https://redirect.github.com/pallets/markupsafe/compare/2.0.1...2.1.0)

Released 2022-02-17

- Drop support for Python 3.6. :pr:`262`
- Remove `soft_unicode`, which was previously deprecated. Use
  `soft_str` instead. :pr:`261`
- Raise error on missing single placeholder during string
  interpolation. :issue:`225`
- Disable speedups module for GraalPython. :issue:`277`

</details>

<details>
<summary>jpadilla/pyjwt (PyJWT)</summary>

###
[`v2.11.0`](https://redirect.github.com/jpadilla/pyjwt/blob/HEAD/CHANGELOG.rst#Unreleased-httpsgithubcomjpadillapyjwtcompare2110HEAD)

[Compare
Source](https://redirect.github.com/jpadilla/pyjwt/compare/2.10.1...2.11.0)

Fixed

```

Added
```

###
[`v2.10.1`](https://redirect.github.com/jpadilla/pyjwt/blob/HEAD/CHANGELOG.rst#Unreleased-httpsgithubcomjpadillapyjwtcompare2101HEAD)

[Compare
Source](https://redirect.github.com/jpadilla/pyjwt/compare/2.10.0...2.10.1)

Fixed

```
- Validate key against allowed types for Algorithm family in `#&#8203;964 <https://github.com/jpadilla/pyjwt/pull/964>`__
- Add iterator for JWKSet in `#&#8203;1041 <https://github.com/jpadilla/pyjwt/pull/1041>`__
- Validate `iss` claim is a string during encoding and decoding by @&#8203;pachewise in `#&#8203;1040 <https://github.com/jpadilla/pyjwt/pull/1040>`__
- Improve typing/logic for `options` in decode, decode_complete by @&#8203;pachewise in `#&#8203;1045 <https://github.com/jpadilla/pyjwt/pull/1045>`__
- Declare float supported type for lifespan and timeout by @&#8203;nikitagashkov in `#&#8203;1068 <https://github.com/jpadilla/pyjwt/pull/1068>`__

Added
```

- Docs: Add example of using leeway with nbf by
[@&#8203;djw8605](https://redirect.github.com/djw8605) in `#&#8203;1034
<https://github.com/jpadilla/pyjwt/pull/1034>`\_\_
- Docs: Refactored docs with `autodoc`; added `PyJWS` and
`jwt.algorithms` docs by
[@&#8203;pachewise](https://redirect.github.com/pachewise) in
`#&#8203;1045 <https://github.com/jpadilla/pyjwt/pull/1045>`\_\_
- Docs: Documentation improvements for "sub" and "jti" claims by
[@&#8203;cleder](https://redirect.github.com/cleder) in `#&#8203;1088
<https://github.com/jpadilla/pyjwt/pull/1088>`

###
[`v2.10.0`](https://redirect.github.com/jpadilla/pyjwt/blob/HEAD/CHANGELOG.rst#v2101-httpsgithubcomjpadillapyjwtcompare21002101)

[Compare
Source](https://redirect.github.com/jpadilla/pyjwt/compare/2.9.0...2.10.0)

Fixed

```

- Prevent partial matching of `iss` claim by @&#8203;fabianbadoi in `GHSA-75c5-xw7c-p5pm <https://github.com/jpadilla/pyjwt/security/advisories/GHSA-75c5-xw7c-p5pm>`__
```

</details>

<details>
<summary>celery/celery (celery)</summary>

###
[`v5.6.2`](https://redirect.github.com/celery/celery/blob/HEAD/Changelog.rst#562)

[Compare
Source](https://redirect.github.com/celery/celery/compare/v5.6.1...v5.6.2)

\=====

:release-date: 2026-01-04
:release-by: Tomer Nosrati

What's Changed

```

- Fix recursive WorkController instantiation in DjangoWorkerFixup + AttributeError when pool_cls is a string (#&#8203;10045)
- Bugfix: Revoked tasks now immediately update backend status to REVOKED (#&#8203;9869)
- Prepare for release: v5.6.2 (#&#8203;10049)

.. _version-5.6.1:

5.6.1
=====

:release-date: 2025-12-29
:release-by: Tomer Nosrati

What's Changed
```

- Fix Redis Sentinel ACL authentication support
([#&#8203;10013](https://redirect.github.com/celery/celery/issues/10013))
- Fix: Broker heartbeats not sent during graceful shutdown
([#&#8203;9986](https://redirect.github.com/celery/celery/issues/9986))
- docs
[#&#8203;5410](https://redirect.github.com/celery/celery/issues/5410) --
Document confirm\_publish broker transport option
([#&#8203;10016](https://redirect.github.com/celery/celery/issues/10016))
- close DB pools only in prefork mode
([#&#8203;10020](https://redirect.github.com/celery/celery/issues/10020))
- Fix: Avoid unnecessary Django database connection creation during
cleanup
([#&#8203;10015](https://redirect.github.com/celery/celery/issues/10015))
- reliable prefork detection
([#&#8203;10023](https://redirect.github.com/celery/celery/issues/10023))
- better coverage
([#&#8203;10029](https://redirect.github.com/celery/celery/issues/10029))
- Docs: clarify `result_extended` vs periodic task metadata and show
`headers["periodic_task_name"]` example
([#&#8203;10030](https://redirect.github.com/celery/celery/issues/10030))
- Stop importing pytest\_subtests
([#&#8203;10032](https://redirect.github.com/celery/celery/issues/10032))
- Only use exceptiongroup backport for Python < 3.11
([#&#8203;10033](https://redirect.github.com/celery/celery/issues/10033))
- Prepare for release: v5.6.1
([#&#8203;10037](https://redirect.github.com/celery/celery/issues/10037))

.. \_version-5.6.0:

###
[`v5.6.1`](https://redirect.github.com/celery/celery/blob/HEAD/Changelog.rst#561)

[Compare
Source](https://redirect.github.com/celery/celery/compare/v5.6.0...v5.6.1)

\=====

:release-date: 2025-12-29
:release-by: Tomer Nosrati

What's Changed

```

- Fix Redis Sentinel ACL authentication support (#&#8203;10013)
- Fix: Broker heartbeats not sent during graceful shutdown (#&#8203;9986)
- docs #&#8203;5410 -- Document confirm_publish broker transport option (#&#8203;10016)
- close DB pools only in prefork mode (#&#8203;10020)
- Fix: Avoid unnecessary Django database connection creation during cleanup (#&#8203;10015)
- reliable prefork detection (#&#8203;10023)
- better coverage (#&#8203;10029)
- Docs: clarify `result_extended` vs periodic task metadata and show `headers["periodic_task_name"]` example (#&#8203;10030)
- Stop importing pytest_subtests (#&#8203;10032)
- Only use exceptiongroup backport for Python < 3.11 (#&#8203;10033)
- Prepare for release: v5.6.1 (#&#8203;10037)

.. _version-5.6.0:

5.6.0
=====

:release-date: 2025-11-30
:release-by: Tomer Nosrati

Celery v5.6.0 is now available.

Key Highlights
```

See :ref:`whatsnew-5.6` for a complete overview or read the main
highlights below.

## Python 3.9 Minimum Version

Celery 5.6.0 drops support for Python 3.8 (EOL). The minimum required
Python
version is now 3.9. Users still on Python 3.8 must upgrade their Python
version
before upgrading to Celery 5.6.0.

Additionally, this release includes initial support for Python 3.14.

## SQS: Reverted to `pycurl` from `urllib3`

The switch from `pycurl` to `urllib3` for the SQS transport (introduced
in
Celery 5.5.0 via Kombu) has been reverted due to critical issues
affecting SQS
users:

- Processing throughput dropped from \~100 tasks/sec to \~3/sec in some
environments
- `UnknownOperationException` errors causing container crash loops
- Silent message processing failures with no error logs

Users of the SQS transport must ensure `pycurl` is installed. If you
removed
`pycurl` after upgrading to Celery 5.5.0, you will need to reinstall it.

Contributed by `@auvipy <https://github.com/auvipy>`\_ in
`#&#8203;9620 <https://github.com/celery/celery/pull/9620>`\_.

## Security Fix: Broker Credential Leak Prevention

Fixed a security issue where broker URLs containing passwords were being
logged
in plaintext by the delayed delivery mechanism. Broker credentials are
now
properly sanitized in all log output.

Contributed by `@giancarloromeo <https://github.com/giancarloromeo>`\_
in
`#&#8203;9997 <https://github.com/celery/celery/pull/9997>`\_.

## Memory Leak Fixes

Two significant memory leaks have been fixed in this release:

**Exception Handling Memory Leak**: Fixed a critical memory leak in task
exception
handling that was particularly severe on Python 3.11+ due to enhanced
traceback
data. The fix properly breaks reference cycles in tracebacks to allow
garbage
collection.

Contributed by `@jaiganeshs21 <https://github.com/jaiganeshs21>`\_ in
`#&#8203;9799 <https://github.com/celery/celery/pull/9799>`\_.

**Pending Result Memory Leak**: Fixed a memory leak where `AsyncResult`
subscriptions were not being cleaned up when results were forgotten.

Contributed by `@tsoos99dev <https://github.com/tsoos99dev>`\_ in
`#&#8203;9806 <https://github.com/celery/celery/pull/9806>`\_.

## ETA Task Memory Limit

New configuration option :setting:`worker_eta_task_limit` to prevent
out-of-memory
crashes when workers fetch large numbers of ETA or countdown tasks.
Previously,
workers could exhaust available memory when the broker contained many
scheduled tasks.

Example usage:

.. code-block:: python

```
app.conf.worker_eta_task_limit = 1000
```

Contributed by `@sashu2310 <https://github.com/sashu2310>`\_ in
`#&#8203;9853 <https://github.com/celery/celery/pull/9853>`\_.

## Queue Type Selection for Auto-created Queues

New configuration options allow specifying the queue type and exchange
type when
Celery auto-creates missing queues. This is particularly useful for
RabbitMQ users
who want to use quorum queues with auto-created queues.

Configuration options:

- :setting:`task_create_missing_queue_type`: Sets the queue type for
auto-created
  queues (e.g., `quorum`, `classic`)
- :setting:`task_create_missing_queue_exchange_type`: Sets the exchange
type for
  auto-created queues

Example usage:

.. code-block:: python

```
app.conf.task_create_missing_queue_type = 'quorum'
```

Contributed by `@ghirailghiro <https://github.com/ghirailghiro>`\_ in
`#&#8203;9815 <https://github.com/celery/celery/pull/9815>`\_.

What's Changed

```

- Prepare for release: v5.6.0 (#&#8203;10010)

.. _version-5.6.0rc2:

5.6.0rc2
========

:release-date: 2025-11-22
:release-by: Tomer Nosrati

Celery v5.6.0 Release Candidate 2 is now available for testing.
Please help us test this version and report any issues.

What's Changed
```

- Remove Python 4.0 version condition for pytest dependencies
([#&#8203;9993](https://redirect.github.com/celery/celery/issues/9993))
- Sanitize broker URL in delayed delivery logs (avoid leaking
credentials)
([#&#8203;9997](https://redirect.github.com/celery/celery/issues/9997))
- Don't fail task on timeout during cold shutdown
([#&#8203;9678](https://redirect.github.com/celery/celery/issues/9678))
- Add Py39-314t to CI
([#&#8203;9999](https://redirect.github.com/celery/celery/issues/9999))
- asynpool: Don't return from inside a finally block
([#&#8203;10000](https://redirect.github.com/celery/celery/issues/10000))
- Prepare for (pre) release: v5.6.0rc2
([#&#8203;10005](https://redirect.github.com/celery/celery/issues/10005))

.. \_version-5.6.0rc1:

###
[`v5.6.0`](https://redirect.github.com/celery/celery/blob/HEAD/Changelog.rst#560)

[Compare
Source](https://redirect.github.com/celery/celery/compare/v5.5.3...v5.6.0)

\=====

:release-date: 2025-11-30
:release-by: Tomer Nosrati

Celery v5.6.0 is now available.

Key Highlights

```

See :ref:`whatsnew-5.6` for a complete overview or read the main highlights below.

Python 3.9 Minimum Version
--------------------------

Celery 5.6.0 drops support for Python 3.8 (EOL). The minimum required Python
version is now 3.9. Users still on Python 3.8 must upgrade their Python version
before upgrading to Celery 5.6.0.

Additionally, this release includes initial support for Python 3.14.

SQS: Reverted to ``pycurl`` from ``urllib3``
--------------------------------------------

The switch from ``pycurl`` to ``urllib3`` for the SQS transport (introduced in
Celery 5.5.0 via Kombu) has been reverted due to critical issues affecting SQS
users:

- Processing throughput dropped from ~100 tasks/sec to ~3/sec in some environments
- ``UnknownOperationException`` errors causing container crash loops
- Silent message processing failures with no error logs

Users of the SQS transport must ensure ``pycurl`` is installed. If you removed
``pycurl`` after upgrading to Celery 5.5.0, you will need to reinstall it.

Contributed by `@auvipy <https://github.com/auvipy>`_ in
`#&#8203;9620 <https://github.com/celery/celery/pull/9620>`_.

Security Fix: Broker Credential Leak Prevention
------------------------------------------------

Fixed a security issue where broker URLs containing passwords were being logged
in plaintext by the delayed delivery mechanism. Broker credentials are now
properly sanitized in all log output.

Contributed by `@giancarloromeo <https://github.com/giancarloromeo>`_ in
`#&#8203;9997 <https://github.com/celery/celery/pull/9997>`_.

Memory Leak Fixes
-----------------

Two significant memory leaks have been fixed in this release:

**Exception Handling Memory Leak**: Fixed a critical memory leak in task exception
handling that was particularly severe on Python 3.11+ due to enhanced traceback
data. The fix properly breaks reference cycles in tracebacks to allow garbage
collection.

Contributed by `@jaiganeshs21 <https://github.com/jaiganeshs21>`_ in
`#&#8203;9799 <https://github.com/celery/celery/pull/9799>`_.

**Pending Result Memory Leak**: Fixed a memory leak where ``AsyncResult``
subscriptions were not being cleaned up when results were forgotten.

Contributed by `@tsoos99dev <https://github.com/tsoos99dev>`_ in
`#&#8203;9806 <https://github.com/celery/celery/pull/9806>`_.

ETA Task Memory Limit
---------------------

New configuration option :setting:`worker_eta_task_limit` to prevent out-of-memory
crashes when workers fetch large numbers of ETA or countdown tasks. Previously,
workers could exhaust available memory when the broker contained many scheduled tasks.

Example usage:

.. code-block:: python

    app.conf.worker_eta_task_limit = 1000

Contributed by `@sashu2310 <https://github.com/sashu2310>`_ in
`#&#8203;9853 <https://github.com/celery/celery/pull/9853>`_.

Queue Type Selection for Auto-created Queues
--------------------------------------------

New configuration options allow specifying the queue type and exchange type when
Celery auto-creates missing queues. This is particularly useful for RabbitMQ users
who want to use quorum queues with auto-created queues.

Configuration options:

- :setting:`task_create_missing_queue_type`: Sets the queue type for auto-created
  queues (e.g., ``quorum``, ``classic``)
- :setting:`task_create_missing_queue_exchange_type`: Sets the exchange type for
  auto-created queues

Example usage:

.. code-block:: python

    app.conf.task_create_missing_queue_type = 'quorum'

Contributed by `@ghirailghiro <https://github.com/ghirailghiro>`_ in
`#&#8203;9815 <https://github.com/celery/celery/pull/9815>`_.

What's Changed
```

- Prepare for release: v5.6.0
([#&#8203;10010](https://redirect.github.com/celery/celery/issues/10010))

.. \_version-5.6.0rc2:

</details>

<details>
<summary>cakepietoast/checksumdir (checksumdir)</summary>

###
[`v1.3.0`](https://redirect.github.com/to-mc/checksumdir/releases/tag/1.3.0)

[Compare
Source](https://redirect.github.com/cakepietoast/checksumdir/compare/1.2.0...1.3.0)

Python compatibility

</details>

<details>
<summary>fastapi/fastapi (fastapi)</summary>

###
[`v0.133.0`](https://redirect.github.com/fastapi/fastapi/compare/0.132.1...0.133.0)

[Compare
Source](https://redirect.github.com/fastapi/fastapi/compare/0.132.1...0.133.0)

###
[`v0.132.1`](https://redirect.github.com/fastapi/fastapi/releases/tag/0.132.1)

[Compare
Source](https://redirect.github.com/fastapi/fastapi/compare/0.132.0...0.132.1)

##### Refactors

- ♻️ Refactor logic to handle OpenAPI and Swagger UI escaping data. PR
[#&#8203;14986](https://redirect.github.com/fastapi/fastapi/pull/14986)
by [@&#8203;tiangolo](https://redirect.github.com/tiangolo).

##### Internal

- 👥 Update FastAPI People - Experts. PR
[#&#8203;14972](https://redirect.github.com/fastapi/fastapi/pull/14972)
by [@&#8203;tiangolo](https://redirect.github.com/tiangolo).
- 👷 Allow skipping `benchmark` job in `test` workflow. PR
[#&#8203;14974](https://redirect.github.com/fastapi/fastapi/pull/14974)
by [@&#8203;YuriiMotov](https://redirect.github.com/YuriiMotov).

###
[`v0.132.0`](https://redirect.github.com/fastapi/fastapi/releases/tag/0.132.0)

[Compare
Source](https://redirect.github.com/fastapi/fastapi/compare/0.131.0...0.132.0)

##### Breaking Changes

- 🔒️ Add `strict_content_type` checking for JSON requests. PR
[#&#8203;14978](https://redirect.github.com/fastapi/fastapi/pull/14978)
by [@&#8203;tiangolo](https://redirect.github.com/tiangolo).
- Now FastAPI checks, by default, that JSON requests have a
`Content-Type` header with a valid JSON value, like `application/json`,
and rejects requests that don't.
- If the clients for your app don't send a valid `Content-Type` header
you can disable this with `strict_content_type=False`.
- Check the new docs: [Strict Content-Type
Checking](https://fastapi.tiangolo.com/advanced/strict-content-type/).

##### Internal

- ⬆ Bump flask from 3.1.2 to 3.1.3. PR
[#&#8203;14949](https://redirect.github.com/fastapi/fastapi/pull/14949)
by
[@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot).
- ⬆ Update all dependencies to use `griffelib` instead of `griffe`. PR
[#&#8203;14973](https://redirect.github.com/fastapi/fastapi/pull/14973)
by [@&#8203;svlandeg](https://redirect.github.com/svlandeg).
- 🔨 Fix `FastAPI People` workflow. PR
[#&#8203;14951](https://redirect.github.com/fastapi/fastapi/pull/14951)
by [@&#8203;YuriiMotov](https://redirect.github.com/YuriiMotov).
- 👷 Do not run codspeed with coverage as it's not tracked. PR
[#&#8203;14966](https://redirect.github.com/fastapi/fastapi/pull/14966)
by [@&#8203;tiangolo](https://redirect.github.com/tiangolo).
- 👷 Do not include benchmark tests in coverage to speed up coverage
processing. PR
[#&#8203;14965](https://redirect.github.com/fastapi/fastapi/pull/14965)
by [@&#8203;tiangolo](https://redirect.github.com/tiangolo).

###
[`v0.131.0`](https://redirect.github.com/fastapi/fastapi/releases/tag/0.131.0)

[Compare
Source](https://redirect.github.com/fastapi/fastapi/compare/0.130.0...0.131.0)

##### Breaking Changes

- 🗑️ Deprecate `ORJSONResponse` and `UJSONResponse`. PR
[#&#8203;14964](https://redirect.github.com/fastapi/fastapi/pull/14964)
by [@&#8203;tiangolo](https://redirect.github.com/tiangolo).

</details>

<details>
<summary>tox-dev/py-filelock (filelock)</summary>

###
[`v3.24.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.24.3)

[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.24.2...3.24.3)

<!-- Release notes generated using configuration in .github/release.yml
at 3.24.3 -->

#### What's Changed

- 🐛 fix(ci): add trailing blank line after changelog entries by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#492](https://redirect.github.com/tox-dev/filelock/pull/492)
- 🐛 fix(unix): handle ENOENT race on FUSE/NFS during acquire by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#495](https://redirect.github.com/tox-dev/filelock/pull/495)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.24.2...3.24.3>

###
[`v3.24.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.24.2)

[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.24.1...3.24.2)

<!-- Release notes generated using configuration in .github/release.yml
at 3.24.2 -->

#### What's Changed

- 📝 docs: restructure using Diataxis framework by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#489](https://redirect.github.com/tox-dev/filelock/pull/489)
- 🐛 fix(test): resolve flaky write non-starvation test by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#490](https://redirect.github.com/tox-dev/filelock/pull/490)
- 🐛 fix(rw): close sqlite3 cursors and skip SoftFileLock Windows race by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#491](https://redirect.github.com/tox-dev/filelock/pull/491)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.24.1...3.24.2>

###
[`v3.24.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.24.1)

[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.24.0...3.24.1)

<!-- Release notes generated using configuration in .github/release.yml
at 3.24.1 -->

#### What's Changed

- 🐛 fix(soft): resolve Windows deadlock and test race condition by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#488](https://redirect.github.com/tox-dev/filelock/pull/488)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.24.0...3.24.1>

###
[`v3.24.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.24.0)

[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.23.0...3.24.0)

<!-- Release notes generated using configuration in .github/release.yml
at 3.24.0 -->

#### What's Changed

- 🐛 fix(unix): auto-fallback to SoftFileLock on ENOSYS by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#480](https://redirect.github.com/tox-dev/filelock/pull/480)
- ✨ feat(lock): add poll\_interval to constructor by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#482](https://redirect.github.com/tox-dev/filelock/pull/482)
- 🐛 fix(win): eliminate lock file race in threaded usage by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#484](https://redirect.github.com/tox-dev/filelock/pull/484)
- ✨ feat(mode): respect POSIX default ACL inheritance by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#483](https://redirect.github.com/tox-dev/filelock/pull/483)
- 🐛 fix(api): detect same-thread self-deadlock by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#481](https://redirect.github.com/tox-dev/filelock/pull/481)
- ✨ feat(lock): add cancel\_check to acquire by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#487](https://redirect.github.com/tox-dev/filelock/pull/487)
- ✨ feat(lock): add lifetime parameter for lock expiration by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#486](https://redirect.github.com/tox-dev/filelock/pull/486)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.23.0...3.24.0>

###
[`v3.23.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.23.0)

[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.22.0...3.23.0)

<!-- Release notes generated using configuration in .github/release.yml
at 3.23.0 -->

#### What's Changed

- 📝 docs: add fasteners to similar libraries by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#478](https://redirect.github.com/tox-dev/filelock/pull/478)
- 📝 docs: move from Unlicense to MIT by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#479](https://redirect.github.com/tox-dev/filelock/pull/479)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.22.0...3.23.0>

###
[`v3.22.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.22.0)

[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.21.2...3.22.0)

<!-- Release notes generated using configuration in .github/release.yml
at 3.22.0 -->

#### What's Changed

- ✨ feat(soft): detect and break stale locks by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#476](https://redirect.github.com/tox-dev/filelock/pull/476)
- 🐛 fix(soft): skip stale lock detection on Windows by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#477](https://redirect.github.com/tox-dev/filelock/pull/477)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.21.2...3.22.0>

###
[`v3.21.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.21.2)

[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.21.1...3.21.2)

<!-- Release notes generated using configuration in .github/release.yml
at 3.21.2 -->

#### What's Changed

- 🐛 fix: catch ImportError for missing sqlite3 C library by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#475](https://redirect.github.com/tox-dev/filelock/pull/475)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.21.1...3.21.2>

###
[`v3.21.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.21.1)

[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.21.0...3.21.1)

<!-- Release notes generated using configuration in .github/release.yml
at 3.21.1 -->

#### What's Changed

- 🐛 fix: gracefully handle missing `sqlite3` when importing
`ReadWriteLock` by
[@&#8203;bayandin](https://redirect.github.com/bayandin) in
[tox-dev/filelock#473](https://redirect.github.com/tox-dev/filelock/pull/473)

#### New Contributors

- [@&#8203;bayandin](https://redirect.github.com/bayandin) made their
first contribution in
[tox-dev/filelock#473](https://redirect.github.com/tox-dev/filelock/pull/473)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.21.0...3.21.1>

###
[`v3.21.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.21.0)

<!-- Release notes generated using configuration in .github/release.yml
at 3.21.0 -->

#### What's Changed

- 🔧 chore: modernize tooling and bump deps by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#470](https://redirect.github.com/tox-dev/filelock/pull/470)
- ✨ feat(lock): add SQLite-based ReadWriteLock by
[@&#8203;leventov](https://redirect.github.com/leventov) in
[tox-dev/filelock#399](https://redirect.github.com/tox-dev/filelock/pull/399)
- Enable removal of UNIX lock files by
[@&#8203;sbc100](https://redirect.github.com/sbc100) in
[tox-dev/filelock#408](https://redirect.github.com/tox-dev/filelock/pull/408)
- 👷 ci(release): persist changelog on release by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#471](https://redirect.github.com/tox-dev/filelock/pull/471)
- 👷 ci(release): commit changelog and use release config by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#472](https://redirect.github.com/tox-dev/filelock/pull/472)

#### New Contributors

- [@&#8203;leventov](https://redirect.github.com/leventov) made their
first contribution in
[tox-dev/filelock#399](https://redirect.github.com/tox-dev/filelock/pull/399)
- [@&#8203;sbc100](https://redirect.github.com/sbc100) made their first
contribution in
[tox-dev/filelock#408](https://redirect.github.com/tox-dev/filelock/pull/408)

**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.20.3...3.21.0>

</details>

<details>
<summary>encode/httpx (httpx)</summary>

###
[`v0.28.1`](https://redirect.github.com/encode/httpx/blob/HEAD/CHANGELOG.md#0281-6th-December-2024)

[Compare
Source](https://redirect.github.com/encode/httpx/compare/0.28.0...0.28.1)

- Fix SSL case where `verify=False` together with client side
certificates.

###
[`v0.28.0`](https://redirect.github.com/encode/httpx/blob/HEAD/CHANGELOG.md#0280-28th-November-2024)

[Compare
Source](https://redirect.github.com/encode/httpx/compare/0.27.2...0.28.0)

Be aware that the default *JSON request bodies now use a more compact
representation*. This is generally considered a prefered style, tho may
require updates to test suites.

The 0.28 release includes a limited set of deprecations...

**Deprecations**:

We are working towards a simplified SSL configuration API.

*For users of the standard `verify=True` or `verify=False` cases, or
`verify=<ssl_context>` case this should require no changes. The
following cases have been deprecated...*

- The `verify` argument as a string argument is now deprecated and will
raise warnings.
- The `cert` argument is now deprecated and will raise warnings.

Our revised [SSL documentation](docs/advanced/ssl.md) covers how to
implement the same behaviour with a more constrained API.

**The following changes are also included**:

- The deprecated `proxies` argument has now been removed.
- The deprecated `app` argument has now been removed.
- JSON request bodies use a compact representation.
([#&#8203;3363](https://redirect.github.com/encode/httpx/issues/3363))
- Review URL percent escape sets, based on WHATWG spec.
([#&#8203;3371](https://redirect.github.com/encode/httpx/issues/3371),
[#&#8203;3373](https://redirect.github.com/encode/httpx/issues/3373))
- Ensure `certifi` and `httpcore` are only imported if required.
([#&#8203;3377](https://redirect.github.com/encode/httpx/issues/3377))
- Treat `socks5h` as a valid proxy scheme.
([#&#8203;3178](https://redirect.github.com/encode/httpx/issues/3178))
- Cleanup `Request()` method signature in line with `client.request()`
and `httpx.request()`.
([#&#8203;3378](https://redirect.github.com/encode/httpx/issues/3378))
- Bugfix: When passing `params={}`, always strictly update rather than
merge with an existing querystring.
([#&#8203;3364](https://redirect.github.com/encode/httpx/issues/3364))

</details>

<details>
<summary>python-humanize/humanize (humanize)</summary>

###
[`v4.15.0`](https://redirect.github.com/python-humanize/humanize/releases/tag/4.15.0)

[Compare
Source](https://redirect.github.com/python-humanize/humanize/compare/4.14.0...4.15.0)

#### Added

- Add locale support for decimal separator in `intword`
([#&#8203;287](https://redirect.github.com/python-humanize/humanize/issues/287))
[@&#8203;hugovk](https://redirect.github.com/hugovk)
- Add support for Python 3.15
([#&#8203;275](https://redirect.github.com/python-humanize/humanize/issues/275))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

#### Changed

- Replace pre-commit with prek
([#&#8203;276](https://redirect.github.com/python-humanize/humanize/issues/276))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

#### Fixed

- `naturaldelta`: round the value to nearest unit that makes sense
([#&#8203;272](https://redirect.github.com/python-humanize/humanize/issues/272))
[@&#8203;dangillet](https://redirect.github.com/dangillet)
- Fix plural form for `intword` and improve performance
([#&#8203;273](https://redirect.github.com/python-humanize/humanize/issues/273))
[@&#8203;dangillet](https://redirect.github.com/dangillet)
- Replace `Exception` with more specific `FileNotFoundError`
([#&#8203;286](https://redirect.github.com/python-humanize/humanize/issues/286))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

###
[`v4.14.0`](https://redirect.github.com/python-humanize/humanize/releases/tag/4.14.0)

[Compare
Source](https://redirect.github.com/python-humanize/humanize/compare/4.13.0...4.14.0)

#### Added

- Add Uzbek language
([#&#8203;264](https://redirect.github.com/python-humanize/humanize/issues/264))
[@&#8203;sSimuSs](https://redirect.github.com/sSimuSs)

#### Changed

- Drop support for Python 3.9
([#&#8203;268](https://redirect.github.com/python-humanize/humanize/issues/268))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

###
[`v4.13.0`](https://redirect.github.com/python-humanize/humanize/releases/tag/4.13.0)

[Compare
Source](https://redirect.github.com/python-humanize/humanize/compare/4.12.3...4.13.0)

#### Changed

- Optimise `naturalsize` algorithm by using `math.log`
([#&#8203;253](https://redirect.github.com/python-humanize/humanize/issues/253))
[@&#8203;Zaczero](https://redirect.github.com/Zaczero)

#### Fixed

- Fix `precisedelta` rounding
([#&#8203;254](https://redirect.github.com/python-humanize/humanize/issues/254))
[@&#8203;dangillet](https://redirect.github.com/dangillet)

###
[`v4.12.3`](https://redirect.github.com/python-humanize/humanize/releases/tag/4.12.3)

[Compare
Source](https://redirect.github.com/python-humanize/humanize/compare/4.12.2...4.12.3)

#### Fixed

- Fix regression in `naturalsize` for `float` and `str`
([#&#8203;250](https://redirect.github.com/python-humanize/humanize/issues/250))
[@&#8203;loicleyendecker](https://redirect.github.com/loicleyendecker)
- Improvements for French translation
([#&#8203;248](https://redirect.github.com/python-humanize/humanize/issues/248))
[@&#8203;merwok](https://redirect.github.com/merwok)

###
[`v4.12.2`](https://redirect.github.com/python-humanize/humanize/releases/tag/4.12.2)

[Compare
Source](https://redirect.github.com/python-humanize/humanize/compare/4.12.1...4.12.2)

#### Fixed

- Update license file reference from `LICENSE` to `LICENCE` in
`pyproject.toml`
([#&#8203;243](https://redirect.github.com/python-humanize/humanize/issues/243))
[@&#8203;williamjamir](https://redirect.github.com/williamjamir)
- Update docstring in naturaldelta
([#&#8203;242](https://redirect.github.com/python-humanize/humanize/issues/242))
[@&#8203;teobucci](https://redirect.github.com/teobucci)
- Ignore `sys.monitoring` warning for Python 3.11 and earlier in
coverage.py config
([#&#8203;244](https://redirect.github.com/python-humanize/humanize/issues/244))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

###
[`v4.12.1`](https://redirect.github.com/python-humanize/humanize/releases/tag/4.12.1)

[Compare
Source](https://redirect.github.com/python-humanize/humanize/compare/4.12.0...4.12.1)

#### Fixed

- Fix regression in `naturalsize` for float
([#&#8203;240](https://redirect.github.com/python-humanize/humanize/issues/240))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

###
[`v4.12.0`](https://redirect.github.com/python-humanize/humanize/releases/tag/4.12.0)

[Compare
Source](https://redirect.github.com/python-humanize/humanize/compare/4.11.0...4.12.0)

#### Added

- Add support for Python 3.14 and test PyPy3.11
([#&#8203;235](https://redirect.github.com/python-humanize/humanize/issues/235))
[@&#8203;hugovk](https://redirect.github.com/hugovk)
- Handle en\_GB and en\_US locale
([#&#8203;230](https://redirect.github.com/python-humanize/humanize/issues/230))
[@&#8203;dangillet](https://redirect.github.com/dangillet)
- Release to PyPI using Trusted Publishing
([#&#8203;213](https://redirect.github.com/python-humanize/humanize/issues/213))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

#### Changed

- Defer imports for faster overall import time: 19 ms -> 3 ms
([#&#8203;234](https://redirect.github.com/python-humanize/humanize/issues/234),
[#&#8203;238](https://redirect.github.com/python-humanize/humanize/issues/238))
[@&#8203;hugovk](https://redirect.github.com/hugovk)
- Replace deprecated classifier with licence expression (PEP 639)
([#&#8203;236](https://redirect.github.com/python-humanize/humanize/issues/236))
[@&#8203;hugovk](https://redirect.github.com/hugovk)
- Lint and test with tox-uv
([#&#8203;212](https://redirect.github.com/python-humanize/humanize/issues/212))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

#### Fixed

- Fix overflow issue in `naturalsize` with `np.int32` input
([#&#8203;218](https://redirect.github.com/python-humanize/humanize/issues/218))
[@&#8203;Toprak2](https://redirect.github.com/Toprak2)
- Fix pt\_BR locale
([#&#8203;216](https://redirect.github.com/python-humanize/humanize/issues/216))
[@&#8203;cuducos](https://redirect.github.com/cuducos)
- Generate translation binaries during release
([#&#8203;232](https://redirect.github.com/python-humanize/humanize/issues/232))
[@&#8203;hugovk](https://redirect.github.com/hugovk)

</details>

<details>
<summary>python/mypy (mypy)</summary>

###
[`v1.19.1`](https://redirect.github.com/python/mypy/blob/HEAD/CHANGELOG.md#Mypy-1191)

[Compare
Source](https://redirect.github.com/python/mypy/compare/v1.19.0...v1.19.1)

- Fix noncommutative joins with bounded TypeVars (Shantanu, PR
[20345](https://redirect.github.com/python/mypy/pull/20345))
- Respect output format for cached runs by serializing raw errors in
cache metas (Ivan Levkivskyi, PR
[20372](https://redirect.github.com/python/mypy/pull/20372))
- Allow `types.NoneType` in match cases (A5rocks, PR
[20383](https://redirect.github.com/python/mypy/pull/20383))
- Fix mypyc generator regression with empty tuple (BobTheBuidler, PR
[20371](https://redirect.github.com/python/mypy/pull/20371))
- Fix crash involving Unpack-ed TypeVarTuple (Shantanu, PR
[20323](https://redirect.github.com/python/mypy/pull/20323))
- Fix crash on star import of redefinition (Ivan Levkivskyi, PR
[20333](https://redirect.github.com/python/mypy/pull/20333))
- Fix crash on typevar with forward ref used in other module (Ivan
Levkivskyi, PR
[20334](https://redirect.github.com/python/mypy/pull/20334))
- Fail with an explicit error on PyPy (Ivan Levkivskyi, PR
[20389](https://redirect.github.com/python/mypy/pull/20389))

###
[`v1.19.0`](https://redirect.github.com/python/mypy/compare/v1.18.2...v1.19.0)

[Compare
Source](https://redirect.github.com/python/mypy/compare/v1.18.2...v1.19.0)

###
[`v1.18.2`](https://redirect.github.com/python/mypy/blob/HEAD/CHANGELOG.md#Mypy-1182)

[Compare
Source](https://redirect.github.com/python/mypy/compare/v1.18.1...v1.18.2)

- Fix crash on recursive alias (Ivan Levkivskyi, PR
[19845](https://redirect.github.com/python/mypy/pull/19845))
- Add additional guidance for stubtest errors when runtime is
`object.__init__` (Stephen Morton, PR
[19733](https://redirect.github.com/python/mypy/pull/19733))
- Fix handling of None values in f-string expressions in mypyc
(BobTheBuidler, PR
[19846](https://redirect.github.com/python/mypy/pull/19846))

###
[`v1.18.1`](https://redirect.github.com/python/mypy/compare/v1.17.1...v1.18.1)

[Compare
Source](https://redirect.github.com/python/mypy/compare/v1.17.1...v1.18.1)

###
[`v1.17.1`](https://redirect.github.com/python/mypy/blob/HEAD/CHANGELOG.md#Mypy-1171)

[Compare
Source](https://redirect.github.com/python/mypy/compare/v1.17.0...v1.17.1)

- Retain `None` as constraints bottom if no bottoms were provided
(Stanislav Terliakov, PR
[19485](https://redirect.github.com/python/mypy/pull/19485))
- Fix "ignored exception in `hasattr`" in dmypy (Stanislav Terliakov, PR
[19428](https://redirect.github.com/python/mypy/pull/19428))
- Prevent a crash when InitVar is redefined with a method in a subclass
(Stanislav Terliakov, PR
[19453](https://redirect.github.com/python/mypy/pull/19453))

###
[`v1.17.0`](https://redirect.github.com/python/mypy/compare/v1.16.1...v1.17.0)

[Compare
Source](https://redirect.github.com/python/mypy/compare/v1.16.1...v1.17.0)

###
[`v1.16.1`](https://redirect.github.com/python/mypy/compare/v1.16.0...v1.16.1)

[Compare
Source](https://redirect.github.com/python/mypy/compare/v1.16.0...v1.16.1)

###
[`v1.16.0`](https://redirect.github.com/python/mypy/compare/v1.15.0...v1.16.0)

[Compare
Source](https://redirect.github.com/python/mypy/compare/v1.15.0...v1.16.0)

</details>

<details>
<summary>pydata/numexpr (numexpr)</summary>

###
[`v2.14.1`](https://redirect.github.com/pydata/numexpr/blob/HEAD/RELEASE_NOTES.rst#Changes-from-2141-to-2142)

[Compare
Source](https://redirect.github.com/pydata/numexpr/compare/v2.14.0...v2.14.1)

- **Under development.**

###
[`v2.14.0`](https://redirect.github.com/pydata/numexpr/blob/HEAD/RELEASE_NOTES.rst#Changes-from-2140-to-2141)

[Compare
Source](https://redirect.github.com/pydata/numexpr/compare/v2.13.1...v2.14.0)

- Rolled back static typing support to ensure compatibiity with NumPy
1.26.
- Added CI tests for NumPy 1.26

</details>

<details>
<summary>numpy/numpy (numpy)</summary>

###
[`v2.4.2`](https://redirect.github.com/numpy/numpy/compare/v2.4.1...v2.4.2)

[Compare
Source](https://redirect.github.com/numpy/numpy/compare/v2.4.1...v2.4.2)

###
[`v2.4.1`](https://redirect.github.com/numpy/numpy/releases/tag/v2.4.1):
2.4.1 (Jan 10, 2026)

[Compare
Source](https://redirect.github.com/numpy/numpy/compare/v2.4.0...v2.4.1)

##### NumPy 2.4.1 Release Notes

The NumPy 2.4.1 is a patch release that fixes bugs discoved after the
2.4.0 release. In particular, the typo `SeedlessSequence` is preserved
to
enable wheels using the random Cython API and built against NumPy <
2.4.0
to run without errors.

This release supports Python versions 3.11-3.14

##### Contributors

A total of 9 people contributed to this release. People with a "+" by
their
names contributed a patch for the first time.

- Alexander Shadchin
- Bill Tompkins +
- Charles Harris
- Joren Hammudoglu
- Marten van Kerkwijk
- Nathan Goldbaum
- Raghuveer Devulapalli
- Ralf Gommers
- Sebastian Berg

##### Pull requests merged

A total of 15 pull requests were merged for this release.

- [#&#8203;30490](https://redirect.github.com/numpy/numpy/pull/30490):
MAINT: Prepare 2.4.x for further development
- [#&#8203;30503](https://redirect.github.com/numpy/numpy/pull/30503):
DOC: `numpy.select`: fix `default` parameter docstring...
- [#&#8203;30504](https://redirect.github.com/numpy/numpy/pull/30504):
REV: Revert part of
[#&#8203;30164](https://redirect.github.com/numpy/numpy/issues/30164)
([#&#8203;30500](https://redirect.github.com/numpy/numpy/issues/30500))
- [#&#8203;30506](https://redirect.github.com/numpy/numpy/pull/30506):
TYP: `numpy.select`: allow passing array-like `default`...
- [#&#8203;30507](https://redirect.github.com/numpy/numpy/pull/30507):
MNT: use if constexpr for compile-time branch selection
- [#&#8203;30513](https://redirect.github.com/numpy/numpy/pull/30513):
BUG: Fix leak in flat assignment iterator
- [#&#8203;30516](https://redirect.github.com/numpy/numpy/pull/30516):
BUG: fix heap overflow in fixed-width string multiply
([#&#8203;30511](https://redirect.github.com/numpy/numpy/issues/30511))
- [#&#8203;30523](https://redirect.github.com/numpy/numpy/pull/30523):
BUG: Ensure summed weights returned by np.average always are...
- [#&#8203;30527](https://redirect.github.com/numpy/numpy/pull/30527):
TYP: Fix return type of histogram2d
- [#&#8203;30594](https://redirect.github.com/numpy/numpy/pull/30594):
MAINT: avoid passing ints to random functions that take double...
- [#&#8203;30595](https://redirect.github.com/numpy/numpy/pull/30595):
BLD: Avoiding conflict with pygit2 for static build
- [#&#8203;30596](https://redirect.github.com/numpy/numpy/pull/30596):
MAINT: Fix msvccompiler missing error on FreeBSD
- [#&#8203;30608](https://redirect.github.com/numpy/numpy/pull/30608):
BLD: update vendored Meson to 1.9.2
- [#&#8203;30620](https://redirect.github.com/numpy/numpy/pull/30620):
ENH: use more fine-grained critical sections in array coercion...
- [#&#8203;30623](https://redirect.github.com/numpy/numpy/pull/30623):
BUG: Undo result type change of quantile/percentile but keep...

###
[`v2.4.0`](https://redirect.github.com/numpy/numpy/releases/tag/v2.4.0):
2.4.0 (Dec 20, 2025)

[Compare
Source](https://redirect.github.com/numpy/numpy/compare/v2.3.5...v2.4.0)

##### NumPy 2.4.0 Release Notes

The NumPy 2.4.0 release continues the work to improve free threaded
Python
support, user dtypes implementation, and annotations. There are many
expired
deprecations and bug fixes as well.

This release supports Python versions 3.11-3.14

##### Highlights

Apart from annotations and `same_value` kwarg, the 2.4 highlights are
mostly
of interest to downstream developers. They should help in implementing
new user
dtypes.

- Many annotation improvements. In particular, runtime signature
introspection.
- New `casting` kwarg `'same_value'` for casting by value.
- New `PyUFunc_AddLoopsFromSpec` function that can be used to add user
sort
  loops using the `ArrayMethod` API.
- New `__numpy_dtype__` protocol.

##### Deprecations

##### Setting the `strides` attribute is deprecated

Setting the strides attribute is now deprecated since mutating
an array is unsafe if an array is shared, especially by multiple
threads. As an alternative, you can create a new view (no copy) via:

- `np.lib.stride_tricks.strided_window_view` if applicable,
- `np.lib.stride_tricks.as_strided` for the general case,
- or the `np.ndarray` constructor (`buffer` is the original array) for a
  light-weight version.

([gh-28925](https://redirect.github.com/numpy/numpy/pull/28925))

##### Positional `out` argument to `np.maximum`, `np.minimum` is
deprecated

Passing the output array `out` positionally to `numpy.maximum` and
`numpy.minimum` is deprecated. For example, `np.maximum(a, b, c)` will
emit
a deprecation warning, since `c` is treated as the output buffer rather
than
a third input.

Always pass the output with the keyword form, e.g. `np.maximum(a, b,
out=c)`.
This makes intent clear and simplifies type annotations.

([gh-29052](https://redirect.github.com/numpy/numpy/pull/29052))

##### `align=` must be passed as boolean to `np.dtype()`

When creating a new `dtype` a `VisibleDeprecationWarning` will be given
if
`align=` is not a boolean. This is mainly to prevent accidentally
passing a
subarray align flag where it has no effect, such as `np.dtype("f8", 3)`
instead of `np.dtype(("f8", 3))`. We strongly suggest to always pass
`align=` as a keyword argument.

([gh-29301](https://redirect.github.com/numpy/numpy/pull/29301))

##### Assertion and warning control utilities are deprecated

`np.testing.assert_warns` and `np.testing.suppress_warnings` are
deprecated. Use `warnings.catch_warnings`, `warnings.filterwarnings`,
`pytest.warns`, or `pytest.filterwarnings` instead.

([gh-29550](https://redirect.github.com/numpy/numpy/pull/29550))

##### `np.fix` is pending deprecation

The `numpy.fix` function will be deprecated in a future release. It is
recommended to use `numpy.trunc` instead, as it provides the same
functionality of truncating decimal values to their integer parts.
Static type
checkers might already report a warning for the use of `numpy.fix`.

([gh-30168](https://redirect.github.com/numpy/numpy/pull/30168))

##### in-place modification of `ndarray.shape` is pending deprecation

Setting the `ndarray.shape` attribute directly will be deprecated in a
future
release. Instead of modifying the shape in place, it is recommended to
use the
`numpy.reshape` function. Static type checkers might already report a
warning for assignments to `ndarray.shape`.

([gh-30282](https://redirect.github.com/numpy/numpy/pull/30282))

##### Deprecation of `numpy.lib.user_array.container`

The `numpy.lib.user_array.container` class is deprecated and will be
removed
in a future version.

([gh-30284](https://redirect.github.com/numpy/numpy/pull/30284))

##### Expired deprecations

##### Removed deprecated `MachAr` runtime discovery mechanism.

([gh-29836](https://redirect.github.com/numpy/numpy/pull/29836))

##### Raise `TypeError` on attempt to convert array with `ndim > 0` to
scalar

Conversion of an array with `ndim > 0` to a scalar was deprecated in
NumPy
1.25. Now, attempting to do so raises `TypeError`. Ensure you extract a
single element from your array before performing this operation.

([gh-29841](https://redirect.github.com/numpy/numpy/pull/29841))

##### Removed numpy.linalg.linalg and numpy.fft.helper

The following were deprecated in Nu

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Theo Pascoli <theo.pascoli@rte-france.com>
gaborbernat added a commit to gaborbernat/filelock that referenced this pull request Mar 9, 2026
In version 3.25.0, PR tox-dev#484 removed lock file cleanup on Windows to fix
threading race conditions where unlink() would fail when other threads
held open handles. This created a regression where single-threaded usage
(the common case) left orphaned lock files, breaking user expectations
and diverging from Unix behavior where lock files are cleaned up.

Restore opportunistic cleanup with suppressed OSError. This provides the
expected behavior for single-threaded scenarios where the file deletes
successfully after close(), while gracefully handling multi-threaded
failures by silently suppressing deletion errors when other threads hold
handles. The suppressed exception preserves thread-safety from PR tox-dev#484
while fixing the orphaned lock file issue for typical usage.
gaborbernat added a commit that referenced this pull request Mar 9, 2026
Version 3.25.0 introduced a regression on Windows where lock files were
no longer cleaned up after release, leaving orphaned `.lock` files on
disk. 🗑️ Users upgrading from 3.18.0 reported that their single-threaded
applications now leave persistent lock files, breaking the expected
behavior and diverging from how Unix platforms work (where lock files
are cleaned up).

The regression came from PR #484, which removed the `unlink()` call to
fix threading race conditions. While that fix correctly addressed
multi-threaded scenarios where Windows cannot delete files with open
handles, it sacrificed cleanup for the common single-threaded use case
where deletion would succeed.

This fix restores opportunistic cleanup by attempting to unlink the lock
file after closing it, with errors suppressed via `suppress(OSError)`. ✨
In single-threaded scenarios, the file deletes successfully and users
get the expected behavior. In multi-threaded scenarios where other
threads hold handles, the deletion fails silently and the lock file
persists, preserving the thread-safety guarantees from PR #484.

The test suite is updated to remove the Windows skip condition from
`test_lock_file_removed_after_release`, as Windows now supports cleanup
in typical usage patterns.

Closes #509
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant