deps(python): bump the python group in /backend with 16 updates

Merged
DE
3d ago
+283-274

Bumps the python group in /backend with 16 updates:

PackageFromTo
asgiref3.12.13.13.0
certifi2026.10.192026.10.23
fastapi0.146.00.162.0
googleapis-common-protos1.75.51.76.0
grpcio1.84.01.84.1
httpx22.14.02.16.0
importlib-metadata9.0.110.1.0
multidict7.1.07.2.1
python-dateutil2.9.0.post03.0.0
sse-starlette3.5.03.6.0
starlette1.9.01.10.0
zipp4.1.14.1.2
faststream[kafka]0.7.70.7.8
coverage7.16.27.17.0
pytest-asyncio1.4.01.4.1
ruff0.17.10.17.2

Updates asgiref from 3.12.1 to 3.13.0

Changelog

Sourced from asgiref's changelog.

3.13.0 (2026-10-23)

  • It is now possible to nest ThreadSensitiveContext by providing an explicit executor for thread-sensitive tasks. This enables moving a block of such work away from the parent context's shared worker. (#596)

    The provided executor must run work sequentially and on a single thread, as per ThreadPoolExecutor(max_workers=1), and the calling code is responsible for managing the executor's lifecycle.

    See the README for more details.

  • Local attribute access is now 2-3x faster. Local(...) now uses one of two internal specialisations, selected by thread_critical, instead of checking the mode on every access. (#551)

    As a result Local is now marked @final and raises TypeError if subclassed. Subclassing was never supported, and could not have worked correctly with the specialised implementations.

  • asgiref.timeout.timeout is deprecated, and will be removed in a future release. Move to use asyncio.timeout() instead.

  • Added support for Python 3.15.

  • Dropped support for EOL Python 3.10.

Commits

Updates certifi from 2026.10.19 to 2026.10.23

Commits

Updates fastapi from 0.146.0 to 0.162.0

Release notes

Sourced from fastapi's releases.

0.162.0

Omitted bool and bool | None form fields now use their declared defaults or produce missing-field errors, consistent with other fields and Pydantic behavior. FastAPI no longer infers False for omitted booleans. This applies to individual form parameters, form models, and unions of form models.

Omitted boolean model fields are excluded from model_dump(exclude_unset=True), and their defaults no longer count as submitted fields during union selection. Default factories and validate_default follow the usual rules.

For HTML checkboxes, declare a boolean with a default of False. See Boolean Form Fields.

Breaking Changes

  • 🐛 Restore default handling for omitted boolean form fields. PR #16605 by @​tiangolo.

0.161.1

Fixes

  • 🐛 Fix OpenAPI schemas for standalone nullable form unions. PR #16598 by @​tiangolo.

0.161.0

Features

0.160.0

Query, header, cookie, and form parameter models now apply their extra configuration to all submitted fields in the same parameter location, consistent with Pydantic behavior. This includes fields declared in other models, individual parameters, or dependencies, which were previously excluded.

With extra="forbid", fields outside the model are rejected even if another parameter declares them. With extra="allow", those fields are included as model extras. With the default extra="ignore", they are ignored.

Breaking Changes

  • 🐛 Apply each parameter model's extra configuration to sibling fields. PR #16594 by @​tiangolo.

Internal

0.159.1

Features

0.159.0

Features

  • ✨ Add support for optional query, header, and cookie parameter models. PR #16584 by @​tiangolo.

0.158.2

Features

0.158.1

... (truncated)

Commits

Updates googleapis-common-protos from 1.75.5 to 1.76.0

Release notes

Sourced from googleapis-common-protos's releases.

googleapis-common-protos: v1.76.0

1.76.0 (2026-10-22)

Features

Commits
  • 82b0565 chore: release main (#18711)
  • ab29d5f chore(main): release google-cloud-bigtable 2.50.2 (#18817)
  • 157efe4 feat(bigquery): add column data policies to SchemaField (#18710)
  • ea7299f fix: validate Host header in graph_server request handlers (#17932)
  • b14c2e5 docs(bigquery-storage): mark ReadRows arrow serialization as beta (#18802)
  • 3ccf5ac fix(bigquery): keep the Arrow schema for empty results (#18655)
  • 8ac01b9 feat(bigquery): read Arrow results from explicit destinations (#18654)
  • 6eab34e feat(bigquery-storage): add context manager to ReadRowsStream (#18781)
  • 31d9365 feat(bigquery-storage): send gRPC keepalive pings by default (#18792)
  • 89cbc50 feat(bigquery): share one BigQuery Storage client per Client (#18652)
  • Additional commits viewable in compare view

Updates grpcio from 1.84.0 to 1.84.1

Release notes

Sourced from grpcio's releases.

Release v1.84.1

This is release gRPC Core 1.84.1 (gimbal).

For gRPC documentation, see grpc.io. For previous releases, see Releases.

This release contains refinements, improvements, and bug fixes, with highlights listed below.

Core

  • [Backport][v1.84.x][security] Update gRPC repo roots. (#43700)
Commits
  • b0c0c4f [Release] Bump version to 1.84.1 (on v1.84.x branch) (#43709)
  • 405e6a1 [Backport][v1.84.x][security] Update gRPC repo roots. (#43700)
  • 826616a [Backport][v1.84.x][CI] Various macOS CI reliability fixes (#43701)
  • 49d6985 [PSM Interop][Backport v1.84.x] Update xDS legacy test scripts for health pro...
  • See full diff in compare view

Updates httpx2 from 2.14.0 to 2.16.0

Release notes

Sourced from httpx2's releases.

v2.16.0

Highlights

🍪 Faster requests with large cookie jars

Building the Cookie header no longer scans every cookie in the jar. The client reuses its jar instead of copying it on every request and redirect (#1284), only looks up the domains that can match the request host, and skips the expired cookie sweep until a cookie is due (#1285). With 1,000 cookies across 500 domains, building the Cookie header is about 18 times faster.

Cookies from different domains are now sent from the least to the most specific domain, for example .example.org before sub.example.org, instead of in the order the domains were added. Cookies with longer paths still come first.

httpx2

Changed

  • Look up only the cookie domains that match the request host, and skip the expired cookie sweep until a cookie is due. With 1,000 cookies across 500 domains, building the Cookie header is about 18 times faster. Cookies from different domains are now sent from the least to the most specific domain (#1285).

Fixed

  • Reuse the client cookie jar instead of copying it on every request and redirect. A custom policy set with client.cookies.jar.set_policy() now applies to outgoing requests (#1284).

httpcore2

No changes since 2.15.1. Version bumped to stay in lockstep with httpx2.

Full Changelog: https://github.com/pydantic/httpx2/compare/v2.15.1...v2.16.0

v2.15.1

Highlights

🔒 Flat CPU usage for long-lived clients on Linux

On Linux, the default SSL context is now configured once instead of on every handshake (#1253). With OpenSSL older than 3.4, each handshake added a duplicate certificate lookup path, so CPU usage per request grew over the lifetime of a reused client. Certificate verification is unchanged, and Windows and macOS still use truststore.

httpx2

Fixed

  • Configure the default SSL context once on Linux, instead of on every handshake. With OpenSSL older than 3.4, CPU usage grew over the lifetime of a reused client (#1253).

httpcore2

Fixed

  • Configure the default SSL context once on Linux, instead of on every handshake. With OpenSSL older than 3.4, CPU usage grew over the lifetime of a reused client (#1253).

Full Changelog: https://github.com/pydantic/httpx2/compare/v2.15.0...v2.15.1

v2.15.0

Highlights

🐍 Python 3.11+ required

... (truncated)

Changelog

Sourced from httpx2's changelog.

2.16.0 (October 21st, 2026)

Changed

  • Look up only the cookie domains that match the request host, and skip the expired cookie sweep until a cookie is due. With 1,000 cookies across 500 domains, building the Cookie header is about 18 times faster. Cookies from different domains are now sent from the least to the most specific domain. (#1285)

Fixed

  • Reuse the client cookie jar instead of copying it on every request and redirect. A custom policy set with client.cookies.jar.set_policy() now applies to outgoing requests. (#1284)

2.15.1 (October 19th, 2026)

Fixed

  • Configure the default SSL context once on Linux, instead of on every handshake. With OpenSSL older than 3.4, CPU usage grew over the lifetime of a reused client. (#1253)

2.15.0 (October 19th, 2026)

Removed

  • Drop support for Python 3.10. (#1274)
Commits

Updates importlib-metadata from 9.0.1 to 10.1.0

Changelog

Sourced from importlib-metadata's changelog.

v10.1.0

Features

  • Detecting whether a distribution supplies metadata no longer reads or parses that metadata where the metadata directory can be inspected instead, so retrieving a distribution by name, which prefers the valid candidates, is substantially faster.
  • Reverted the preference for the greater metadata directory added in v9.1.0. The ordering was lexicographic on the directory name and not on the parsed version, so it only approximated a preference for the newer version. Where a path supplies more than one metadata directory for a distribution, discovery once again reports them in the order the path supplies python/cpython#100666

Bugfixes

  • entry_points() now prefers distributions whose metadata is readable, so an empty metadata directory left behind by an unclean upgrade no longer shadows the valid one of the same name and suppresses its entry points. Invalid distributions are deferred to the end of the enumeration rather than dropped. (#534)
  • The preference for valid distributions no longer propagates the MetadataNotFound of a distribution that a provider derived from importlib.metadata, whose exception is a different class from this package's and so escaped the preference rather than marking the distribution invalid.

v10.0.0

Features

  • Added IDistribution and IPackagePath protocols so consumers can target a stable, shared interface across importlib.metadata and importlib_metadata. A provider supplying its own Distribution subclass is warned about only when the class omits members that interface requires, not merely because it derives from importlib.metadata. origin is exempt from that expectation until support for Python 3.12 is dropped, as there is none to inherit before Python 3.13. (#486)

Deprecations and Removals

  • When providers supply objects from importlib.metadata, they are now adapted to the classes from importlib_metadata. (#486)

v9.1.0

... (truncated)

Commits
  • d196fdb Finalize
  • 5d253ae Merge pull request #553 from python/bugfix/534-entry-points-prefer-valid
  • 0aa24f3 Prefer valid distributions when collecting entry points.
  • e52be78 Detect the presence of metadata without reading it.
  • 60bbaca Merge pull request #552 from python/debt/revert-prefer-greater-version
  • 7e162d8 Revert "Prefer the greater metadata directory when a path supplies several."
  • 3be1416 Finalize
  • e3dad22 Merge pull request #505 from python/bugfix/486-local-objects
  • 301b791 Finalize
  • 4b7c45f Avoid a dot in the news fragment id.
  • Additional commits viewable in compare view

Updates multidict from 7.1.0 to 7.2.1

Release notes

Sourced from multidict's releases.

7.2.1

Bug fixes

  • Fixed a regression in 7.2.0 where a subclass of MultiDictProxy or CIMultiDictProxy that converted its argument in its own __init__() raised TypeError before that __init__() ran; such a subclass got an empty multidict until its __init__() set the proxied one -- by @​asvetlov.

    Related issues and pull requests on GitHub: #1824, #1825.


7.2.0 drops Python 3.10, fixes a crash in a proxy built without __init__() and a MemoryError from a huge __length_hint__(), and is otherwise a performance release for the C extension: lookups, adds, updates and deletes each needed a few percent fewer instructions.

Bug fixes

  • Stopped a huge __length_hint__() from raising MemoryError in extend(), update() and merge(); the C extension capped the room it reserved for the hint at the largest table the constructor allocates up front -- by @​asvetlov.

    Related issues and pull requests on GitHub: #1767.

  • Fixed a segmentation fault when using a MultiDictProxy or CIMultiDictProxy built by __new__() without __init__(); __new__() started requiring the proxied multidict, the same argument as the constructor -- by @​asvetlov.

    Related issues and pull requests on GitHub: #1782.

Features

  • Sped up reading a multidict in the C extension. md[key], get() and getone() became up to 7% faster by returning the lookup's result by value instead

... (truncated)

Changelog

Sourced from multidict's changelog.

7.2.1

(2026-10-24)

Bug fixes

  • Fixed a regression in 7.2.0 where a subclass of :class:~multidict.MultiDictProxy or :class:~multidict.CIMultiDictProxy that converted its argument in its own __init__() raised :exc:TypeError before that __init__() ran; such a subclass got an empty multidict until its __init__() set the proxied one -- by :user:asvetlov.

    Related issues and pull requests on GitHub: :issue:1824, :issue:1825.


7.2.0

(2026-10-23)

7.2.0 drops Python 3.10, fixes a crash in a proxy built without __init__() and a :exc:MemoryError from a huge __length_hint__(), and is otherwise a performance release for the C extension: lookups, adds, updates and deletes each needed a few percent fewer instructions.

Bug fixes

  • Stopped a huge __length_hint__() from raising :exc:MemoryError in :meth:~multidict.MultiDict.extend, :meth:~multidict.MultiDict.update and :meth:~multidict.MultiDict.merge; the C extension capped the room it reserved for the hint at the largest table the constructor allocates up front -- by :user:asvetlov.

    Related issues and pull requests on GitHub: :issue:1767.

  • Fixed a segmentation fault when using a :class:~multidict.MultiDictProxy or :class:~multidict.CIMultiDictProxy built by __new__() without __init__(); __new__() started requiring the proxied multidict, the same argument as the constructor -- by :user:asvetlov.

... (truncated)

Commits
  • f50870c Release 7.2.1 (#1826)
  • 6526b96 Let proxy subclasses convert their argument in init() (#1825)
  • 3d08ebe Keep the sdist in the deploy group that makes the Release (#1822)
  • 17b8e41 Build(deps): Bump pypa/cibuildwheel from 4.3.1 to 4.3.2 (#1823)
  • 57ffa0c Fix the huge length hint test on 32-bit builds (#1821)
  • 8dcff50 Release 7.2.0 (#1819)
  • a2cc61c Pin Hypothesis in the MyPy hooks, drop an unused type: ignore (#1820)
  • b933263 Refresh the benchmark tables (#1818)
  • edfc84d Inline the GIL contains lookup, take an add's references after the table is r...
  • b2f65b8 Refresh the benchmark tables (#1816)
  • Additional commits viewable in compare view

Updates python-dateutil from 2.9.0.post0 to 3.0.0

Release notes

Sourced from python-dateutil's releases.

3.0.0

This is the last major version of dateutil that will support any version of Python older than 3.11. The next release will be the 4.x series, which will support Python 3.11 and later. We may release fixes for serious bugs in the 3.0.x series, but there are no plans for new features there.

The biggest change in this release is a rewrite of tz.tzfile, which affects nearly every user of dateutil.tz and changes the UTC offset of nonexistent times (see below). dateutil also now depends on the tzdata package, and no longer ships its own time zone database.

Data updates

  • dateutil no longer bundles a copy of the IANA time zone database. Time zone data now comes from the system (see dateutil.tz.TZPATH) or, failing that, from the new tzdata dependency, so the data version is whatever version of tzdata is installed. (gh pr #1130)

Features

  • Rewrote tz.tzfile based on a backport of the zoneinfo module's pure-Python implementation. This adds support for Version 2 and Version 3 tzfile(5) binaries, resolving issues with timestamps beyond 2038 and "slim" format binaries. (gh issues #462, #1059, gh pr #1130)
  • Added dateutil.tz.TZPATH and dateutil.tz.reset_tzpath to allow for runtime configuration of the IANA time zone data search path. These replace the mutable dateutil.tz.TZPATHS list, which has been removed. (gh pr #1130)
  • dateutil now depends on the tzdata package, which gettz consults after the search path and before the Windows registry. On Windows this means that names that are both IANA keys and Windows time zone names, such as "UTC", now return a tzfile rather than a tzwin. (gh pr #1130)

Bugfixes

  • tz.tzfile now follows PEP 495 for times that fall in a gap: with fold=0 it uses the offset from before the transition, and with fold=1 the offset from after it. Previously it always used the offset from after the transition, so for example datetime(2003, 4, 6, 2, 30, tzinfo=tz.gettz("America/New_York")) had a UTC offset of -04:00, where it now has -05:00, the same as with zoneinfo. (gh pr #1130)
  • tz.tzfile objects for fixed-offset zones, such as tz.gettz("UTC"), now return their offset, DST offset and abbreviation when utcoffset, dst and tzname are called with None, as tz.tzutc, tz.tzoffset and zoneinfo.ZoneInfo do. This means that datetime.time objects with such a zone attached are now aware: time(12, tzinfo=tz.gettz("UTC")).isoformat() is now "12:00:00+00:00" rather than "12:00:00". (gh pr #1130)
  • tz.tzfile now infers dst() from the standard time on both sides of each DST period, rather than only the one before it, and does so for each transition rather than for each local time type. This fixes dst() for double summer time (e.g. in Europe/London in the 1940s), for half-hour DST (e.g. in Pacific/Rarotonga) and where the standard offset changed at the same time as a DST transition (e.g. in America/Bahia_Banderas in 2010). Against the standard offsets in the tz database source, the only remaining errors are in Europe/Paris in 1944 and 1945. (gh pr #1130)
  • Fixed rrulestr raising ValueError on experimental X- parameters in an RRULE line (such as GNOME Evolution's X-EVOLUTION-ENDDATE); these are now ignored as RFC 5545 permits. Fixed by @​yajo (gh pr #1374)
  • Enabled pickling and deepcopy of cached rrule and rruleset instances. The cache setting is preserved, and cached results are regenerated on demand without copying locks or generators. Reported by @​niccokunzmann (gh issue #1369). Fixed by @​Jay1023CN (gh pr #1600).
  • Fixed relativedelta.__ne__ raising TypeError when comparing against an unsupported type such as None; it now returns True. Reported and fixed by @​kevinkt1 (gh issue #1157, gh pr #1158)
  • Raised the minimum version of six to 1.6, fixing No module named 'six.moves' errors with older versions. Reported by @​skytreader (gh issue #1415), fixed by @​jdarias3 (gh pr #1424).

Deprecations

  • Deprecated the dateutil.zoneinfo module. The module now acts as a wrapper around the tzdata package and will be removed in a future version. Users are encouraged to migrate to dateutil.tz.gettz or the standard library's zoneinfo module. dateutil.zoneinfo.rebuild.rebuild no longer does anything, and by default raises RebuildDeprecationWarning as an error; filter the warning to call it as a no-op. (gh pr #1130)
  • Deprecated passing gettz a relative key that refers to a file outside of every directory on TZPATH, such as "../../etc/localtime". By default this now raises dateutil.tz.DeprecatedTzKeyWarning as an error; filter the warning to keep the old behavior for now, or pass an absolute path instead. (gh pr #1130)

Documentation changes

  • Added intersphinx to the docs build and cleaned up some broken links. (gh pr #1463)

Misc

Changelog

Sourced from python-dateutil's changelog.

Version 3.0.0 (2026-10-21)

This is the last major version of dateutil that will support any version of Python older than 3.11. The next release will be the 4.x series, which will support Python 3.11 and later. We may release fixes for serious bugs in the 3.0.x series, but there are no plans for new features there.

The biggest change in this release is a rewrite of tz.tzfile, which affects nearly every user of dateutil.tz and changes the UTC offset of nonexistent times (see below). dateutil also now depends on the tzdata package, and no longer ships its own time zone database.

Data updates

  • dateutil no longer bundles a copy of the IANA time zone database. Time zone data now comes from the system (see dateutil.tz.TZPATH) or, failing that, from the new tzdata dependency, so the data version is whatever version of tzdata is installed. (gh pr #1130)

Features

  • Rewrote tz.tzfile based on a backport of the zoneinfo module's pure-Python implementation. This adds support for Version 2 and Version 3 tzfile(5) binaries, resolving issues with timestamps beyond 2038 and "slim" format binaries. (gh issues #462, #1059, gh pr #1130)
  • Added dateutil.tz.TZPATH and dateutil.tz.reset_tzpath to allow for runtime configuration of the IANA time zone data search path. These replace the mutable dateutil.tz.TZPATHS list, which has been removed. (gh pr #1130)
  • dateutil now depends on the tzdata package, which gettz consults after the search path and before the Windows registry. On Windows this means that names that are both IANA keys and Windows time zone names, such as "UTC", now return a tzfile rather than a tzwin. (gh pr #1130)

Bugfixes

  • tz.tzfile now follows PEP 495 for times that fall in a gap: with fold=0 it uses the offset from before the transition, and with fold=1 the offset from after it. Previously it always used the offset from after the transition, so for example datetime(2003, 4, 6, 2, 30, tzinfo=tz.gettz("America/New_York")) had a UTC offset of -04:00, where it now has -05:00, the same as with zoneinfo. (gh pr #1130)
  • tz.tzfile objects for fixed-offset zones, such as tz.gettz("UTC"), now return their offset, DST offset and abbreviation when utcoffset, dst and tzname are called with None, as tz.tzutc, tz.tzoffset and

... (truncated)

Commits
  • 10f317f Prepare release 3.0.0
  • fabac8d Run the tests against a wheel built once on a recent Python
  • 21b6862 Allow pickling and deepcopy of cached recurrence rules (#1600)
  • bd5fd88 Remove deprecated setuptools usage from the build
  • 962f0a5 Don't fetch an unpinned setuptools_scm via setup_requires
  • db944cf Update the Python version classifiers
  • 3b07521 Test on Python 3.14t, 3.15 and 3.15t
  • 6899421 Fix dateutil/dateutil#1157
  • bc90ab4 Use trusted publishing to upload to PyPI
  • 950abb6 fix(rrule): don't die on experimental properties
  • Additional commits viewable in compare view

Updates sse-starlette from 3.5.0 to 3.6.0

Release notes

Sourced from sse-starlette's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/sysid/sse-starlette/compare/v3.5.1...v3.6.0

v3.5.1

What's Changed

New Contributors

Full Changelog: https://github.com/sysid/sse-starlette/compare/v3.5.0...v3.5.1

Commits
  • 3d3c505 Bump version to 3.6.0
  • 011de6d Merge pull request #230 from sysid/chore/deps-upgrade
  • 4af7807 Merge pull request #229 from sysid/fix/issue218-head-followups
  • ea49b6a build(deps)!: upgrade dependencies and drop Python 3.10
  • 8015d44 test: drop redundant pytest.mark.asyncio markers
  • ec98bad fix: apply send_timeout to HEAD and harden #218 tests
  • f9484b5 Merge pull request #220 from AryanRajMaurya/fix/head-request-should-not-stream
  • 4be92f1 Merge pull request #226 from sysid/dependabot/uv/certifi-2026.10.19
  • e3e78e9 Merge pull request #227 from sysid/dependabot/uv/virtualenv-21.14.13
  • 8779869 chore(deps): bump virtualenv from 21.7.13 to 21.14.13
  • Additional commits viewable in compare view

Updates starlette from 1.9.0 to 1.10.0

Release notes

Sourced from starlette's releases.

Version 1.10.0

📝 Leaner URL-encoded form parsing

Starlette 1.10.0 parses URL-encoded forms with less memory and CPU, no longer drops the last field when a stream ends early, and lets you compare FormData that holds several uploads under one key.

uv pip install starlette==1.10.0
  • Forms with many fields parse faster and use less memory (#3724). FormParser builds each field in the parser callbacks instead of queueing every event and replaying it. On CodSpeed, 1000 fields went from 42.8 ms to 34.9 ms and from 63.5 KB to 54.5 KB, and the max_fields limit case went from 6,880 B to 864 B.
  • The last field is kept when the request stream ends without an empty chunk (#3599). The parser is now finalized once the stream is exhausted, so custom streams that never yield a final b"" no longer lose their last field.
  • FormData with repeated uploads can be compared (#3619). Comparing two FormData objects with several UploadFile values under the same key used to raise TypeError.

⚠️ Behaviour changes

  • Multidict equality keeps the order of values under a repeated key (#3619). Keys can still appear in any order, but QueryParams("a=1&a=2") and QueryParams("a=2&a=1") are no longer equal, matching what getlist() returns.
  • starlette.formparsers.FormMessage is deprecated (#3724). The parser no longer uses it, and FormParser.messages is gone. Calling FormMessage(...) emits a StarletteDeprecationWarning.

🧭 Routing and URL generation

  • Path parameter values that look like a placeholder are kept as they are (#3725). url_path_for("route", category="{id}", id="42") on /{category}/{id} now returns /{id}/42 instead of /42/42. Substitution also got faster, from 549 ns to 520 ns with two parameters and from 1,078 ns to 779 ns with five.
  • Route matching does less work per request (#3665, #3722). Match members are compared by identity, cutting up to 4.9% of the instructions per dispatch in the routing benchmarks.
  • WSGIMiddleware strips root_path only at a path segment boundary (#3718). A request to /application under a root_path of /app no longer becomes /lication.
  • FloatConvertor reports NaN and infinity correctly (#3716). NaN was reported as a negative float.

🛡️ Middleware, responses and config

  • Handled exceptions no longer keep requests alive (#3205). Starlette clears the traceback after an exception handler runs, so an exception instance reused across requests, such as a module-level HTTPException, no longer pins per-request objects in memory.
  • Middlewares accept http.response.start without headers (#3721). BaseHTTPMiddleware, GZipMiddleware and SessionMiddleware default the omitted field to an empty list instead of raising KeyError.
  • FileResponse ignores Range on methods other than GET and HEAD (#3679). A POST endpoint that returns a file now sends the full file, as RFC 9110 requires.
  • Config strips one pair of matching outer quotes from env file values (#3720). KEY='say "hi"' now reads as say "hi" instead of say "hi.

Full changelog: 1.9.0...1.10.0

Changelog

Sourced from starlette's changelog.

1.10.0 (October 24, 2026)

Changed

  • Compare multidicts such as FormData and QueryParams by key while keeping the order of values under a repeated key, so FormData with repeated uploads no longer raises TypeError. QueryParams("a=1&a=2") and QueryParams("a=2&a=1") are no longer equal #3619.
  • Build URL-encoded form fields in the parser callbacks, lowering memory and CPU usage for forms with many fields #3724.
  • Compare Match members by identity during routing #3665 and #3722.

Deprecated

  • Deprecate starlette.formparsers.FormMessage, which is no longer used #3724.

Fixed

  • Parse the last URL-encoded form field when the request stream ends without an em...

    Description has been truncated


    Summary by cubic

    Updates 16 Python dependencies in /backend, including major version bumps to python-dateutil, importlib-metadata, fastapi, and httpx2. The rest are minor or patch releases with bug fixes and performance improvements.

    Breaking changes to verify

    • fastapi no longer infers False for omitted boolean form fields; declared defaults or missing-field errors now apply.
    • python-dateutil 3.0.0 rewrites tz.tzfile so nonexistent-time offsets match zoneinfo, drops its bundled IANA database for a tzdata dependency, and removes TZPATHS.
    • httpx2, multidict, asgiref, and sse-starlette drop Python 3.10, and asgiref.timeout.timeout is deprecated.
    • starlette now treats repeated-key value order as significant in multidict equality and deprecates FormMessage.