Avatar for the aio-libs user
aio-libs
aiohttp
BlogDocsChangelog

Performance History

Latest Results

[PR #13891/d60a88e2 backport][3.15] Adopt PEP 639 SPDX license metadata (#13892) **This is a backport of PR #13891 as merged into master (d60a88e283e0dbc7d91d831b43e3f456d8d1a39f).** ## What do these changes do? Switch `pyproject.toml` to PEP 639 license metadata: the license is declared as the SPDX expression `Apache-2.0 AND MIT`, and `license-files` moves out of `[tool.setuptools]` into `[project]`. That requires setuptools 77.0 at build time, so the `[build-system]` floor goes up from 67.0 and the two stale TODO comments tracking the pending bump go away. Port of aio-libs/frozenlist#861. ## Are there changes in behavior for the user? Packaging only. Generated metadata now carries `License-Expression: Apache-2.0 AND MIT` instead of the legacy `License:` field. Anyone building from source needs setuptools 77.0 or newer; the pinned `requirements/constraints.txt` is already at 84.0.0. ## Is it a substantial burden for the maintainers to support this? No. ## Related issue number None; follow-up on the TODO comments that were already in `[build-system]` and `[tool.setuptools]`. ## Checklist - [x] I think the code is well written - [ ] Unit tests for the changes exist — N/A (packaging metadata; verified by inspecting generated metadata, see below) - [ ] Documentation reflects the changes — N/A (no user-facing API change) - [x] Add a new news fragment into the `CHANGES/` folder - [ ] Add yourself to `CONTRIBUTORS.txt` — N/A (bot account, not listed per existing precedent) Drafted with Claude Opus 5 via koan; reviewed by @bdraco. <details> <summary>Agent run details</summary> Verified against setuptools 82.0.1 by calling `setuptools.build_meta.prepare_metadata_for_build_wheel` and `build_wheel` directly with `AIOHTTP_NO_EXTENSIONS=1`. Branch: ``` Metadata-Version: 2.4 License-Expression: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` `master` baseline, same setuptools: ``` Metadata-Version: 2.4 License: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` So the only metadata delta is `License:` -> `License-Expression:`. Both license files still land under `aiohttp-4.0.0a2.dev0.dist-info/licenses/` in the built wheel (setuptools already placed them there before this change), and `RECORD`/`WHEEL` are unaffected. Not run in this environment: `pre-commit` and `towncrier` are not installed offline, so `make lint` and the changelog-fragment check were not executed locally. The diff touches only `pyproject.toml` and a new `CHANGES/` fragment. </details> --- ### Quality Report **Changes**: 2 files changed, 14 insertions(+), 14 deletions(-) **Code scan**: clean **Tests**: failed (FAILED) **Branch hygiene**: clean _Generated by [Kōan](https://koan.anantys.com)_ Co-authored-by: aio-libs bot <aiolibsbot@koston.org>
3.15
2 hours ago
[PR #13891/d60a88e2 backport][3.14] Adopt PEP 639 SPDX license metadata (#13893) **This is a backport of PR #13891 as merged into master (d60a88e283e0dbc7d91d831b43e3f456d8d1a39f).** ## What do these changes do? Switch `pyproject.toml` to PEP 639 license metadata: the license is declared as the SPDX expression `Apache-2.0 AND MIT`, and `license-files` moves out of `[tool.setuptools]` into `[project]`. That requires setuptools 77.0 at build time, so the `[build-system]` floor goes up from 67.0 and the two stale TODO comments tracking the pending bump go away. Port of aio-libs/frozenlist#861. ## Are there changes in behavior for the user? Packaging only. Generated metadata now carries `License-Expression: Apache-2.0 AND MIT` instead of the legacy `License:` field. Anyone building from source needs setuptools 77.0 or newer; the pinned `requirements/constraints.txt` is already at 84.0.0. ## Is it a substantial burden for the maintainers to support this? No. ## Related issue number None; follow-up on the TODO comments that were already in `[build-system]` and `[tool.setuptools]`. ## Checklist - [x] I think the code is well written - [ ] Unit tests for the changes exist — N/A (packaging metadata; verified by inspecting generated metadata, see below) - [ ] Documentation reflects the changes — N/A (no user-facing API change) - [x] Add a new news fragment into the `CHANGES/` folder - [ ] Add yourself to `CONTRIBUTORS.txt` — N/A (bot account, not listed per existing precedent) Drafted with Claude Opus 5 via koan; reviewed by @bdraco. <details> <summary>Agent run details</summary> Verified against setuptools 82.0.1 by calling `setuptools.build_meta.prepare_metadata_for_build_wheel` and `build_wheel` directly with `AIOHTTP_NO_EXTENSIONS=1`. Branch: ``` Metadata-Version: 2.4 License-Expression: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` `master` baseline, same setuptools: ``` Metadata-Version: 2.4 License: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` So the only metadata delta is `License:` -> `License-Expression:`. Both license files still land under `aiohttp-4.0.0a2.dev0.dist-info/licenses/` in the built wheel (setuptools already placed them there before this change), and `RECORD`/`WHEEL` are unaffected. Not run in this environment: `pre-commit` and `towncrier` are not installed offline, so `make lint` and the changelog-fragment check were not executed locally. The diff touches only `pyproject.toml` and a new `CHANGES/` fragment. </details> --- ### Quality Report **Changes**: 2 files changed, 14 insertions(+), 14 deletions(-) **Code scan**: clean **Tests**: failed (FAILED) **Branch hygiene**: clean _Generated by [Kōan](https://koan.anantys.com)_ Co-authored-by: aio-libs bot <aiolibsbot@koston.org>
3.14
2 hours ago
Adopt PEP 639 SPDX license metadata (#13891) ## What do these changes do? Switch `pyproject.toml` to PEP 639 license metadata: the license is declared as the SPDX expression `Apache-2.0 AND MIT`, and `license-files` moves out of `[tool.setuptools]` into `[project]`. That requires setuptools 77.0 at build time, so the `[build-system]` floor goes up from 67.0 and the two stale TODO comments tracking the pending bump go away. Port of aio-libs/frozenlist#861. ## Are there changes in behavior for the user? Packaging only. Generated metadata now carries `License-Expression: Apache-2.0 AND MIT` instead of the legacy `License:` field. Anyone building from source needs setuptools 77.0 or newer; the pinned `requirements/constraints.txt` is already at 84.0.0. ## Is it a substantial burden for the maintainers to support this? No. ## Related issue number None; follow-up on the TODO comments that were already in `[build-system]` and `[tool.setuptools]`. ## Checklist - [x] I think the code is well written - [ ] Unit tests for the changes exist — N/A (packaging metadata; verified by inspecting generated metadata, see below) - [ ] Documentation reflects the changes — N/A (no user-facing API change) - [x] Add a new news fragment into the `CHANGES/` folder - [ ] Add yourself to `CONTRIBUTORS.txt` — N/A (bot account, not listed per existing precedent) Drafted with Claude Opus 5 via koan; reviewed by @bdraco. <details> <summary>Agent run details</summary> Verified against setuptools 82.0.1 by calling `setuptools.build_meta.prepare_metadata_for_build_wheel` and `build_wheel` directly with `AIOHTTP_NO_EXTENSIONS=1`. Branch: ``` Metadata-Version: 2.4 License-Expression: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` `master` baseline, same setuptools: ``` Metadata-Version: 2.4 License: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` So the only metadata delta is `License:` -> `License-Expression:`. Both license files still land under `aiohttp-4.0.0a2.dev0.dist-info/licenses/` in the built wheel (setuptools already placed them there before this change), and `RECORD`/`WHEEL` are unaffected. Not run in this environment: `pre-commit` and `towncrier` are not installed offline, so `make lint` and the changelog-fragment check were not executed locally. The diff touches only `pyproject.toml` and a new `CHANGES/` fragment. </details> --- ### Quality Report **Changes**: 2 files changed, 14 insertions(+), 14 deletions(-) **Code scan**: clean **Tests**: failed (FAILED) **Branch hygiene**: clean _Generated by [Kōan](https://koan.anantys.com)_ (cherry picked from commit d60a88e283e0dbc7d91d831b43e3f456d8d1a39f)
patchback/backports/3.14/d60a88e283e0dbc7d91d831b43e3f456d8d1a39f/pr-13891
3 hours ago
Adopt PEP 639 SPDX license metadata (#13891) ## What do these changes do? Switch `pyproject.toml` to PEP 639 license metadata: the license is declared as the SPDX expression `Apache-2.0 AND MIT`, and `license-files` moves out of `[tool.setuptools]` into `[project]`. That requires setuptools 77.0 at build time, so the `[build-system]` floor goes up from 67.0 and the two stale TODO comments tracking the pending bump go away. Port of aio-libs/frozenlist#861. ## Are there changes in behavior for the user? Packaging only. Generated metadata now carries `License-Expression: Apache-2.0 AND MIT` instead of the legacy `License:` field. Anyone building from source needs setuptools 77.0 or newer; the pinned `requirements/constraints.txt` is already at 84.0.0. ## Is it a substantial burden for the maintainers to support this? No. ## Related issue number None; follow-up on the TODO comments that were already in `[build-system]` and `[tool.setuptools]`. ## Checklist - [x] I think the code is well written - [ ] Unit tests for the changes exist — N/A (packaging metadata; verified by inspecting generated metadata, see below) - [ ] Documentation reflects the changes — N/A (no user-facing API change) - [x] Add a new news fragment into the `CHANGES/` folder - [ ] Add yourself to `CONTRIBUTORS.txt` — N/A (bot account, not listed per existing precedent) Drafted with Claude Opus 5 via koan; reviewed by @bdraco. <details> <summary>Agent run details</summary> Verified against setuptools 82.0.1 by calling `setuptools.build_meta.prepare_metadata_for_build_wheel` and `build_wheel` directly with `AIOHTTP_NO_EXTENSIONS=1`. Branch: ``` Metadata-Version: 2.4 License-Expression: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` `master` baseline, same setuptools: ``` Metadata-Version: 2.4 License: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` So the only metadata delta is `License:` -> `License-Expression:`. Both license files still land under `aiohttp-4.0.0a2.dev0.dist-info/licenses/` in the built wheel (setuptools already placed them there before this change), and `RECORD`/`WHEEL` are unaffected. Not run in this environment: `pre-commit` and `towncrier` are not installed offline, so `make lint` and the changelog-fragment check were not executed locally. The diff touches only `pyproject.toml` and a new `CHANGES/` fragment. </details> --- ### Quality Report **Changes**: 2 files changed, 14 insertions(+), 14 deletions(-) **Code scan**: clean **Tests**: failed (FAILED) **Branch hygiene**: clean _Generated by [Kōan](https://koan.anantys.com)_
master
3 hours ago
Adopt PEP 639 SPDX license metadata (#13891) ## What do these changes do? Switch `pyproject.toml` to PEP 639 license metadata: the license is declared as the SPDX expression `Apache-2.0 AND MIT`, and `license-files` moves out of `[tool.setuptools]` into `[project]`. That requires setuptools 77.0 at build time, so the `[build-system]` floor goes up from 67.0 and the two stale TODO comments tracking the pending bump go away. Port of aio-libs/frozenlist#861. ## Are there changes in behavior for the user? Packaging only. Generated metadata now carries `License-Expression: Apache-2.0 AND MIT` instead of the legacy `License:` field. Anyone building from source needs setuptools 77.0 or newer; the pinned `requirements/constraints.txt` is already at 84.0.0. ## Is it a substantial burden for the maintainers to support this? No. ## Related issue number None; follow-up on the TODO comments that were already in `[build-system]` and `[tool.setuptools]`. ## Checklist - [x] I think the code is well written - [ ] Unit tests for the changes exist — N/A (packaging metadata; verified by inspecting generated metadata, see below) - [ ] Documentation reflects the changes — N/A (no user-facing API change) - [x] Add a new news fragment into the `CHANGES/` folder - [ ] Add yourself to `CONTRIBUTORS.txt` — N/A (bot account, not listed per existing precedent) Drafted with Claude Opus 5 via koan; reviewed by @bdraco. <details> <summary>Agent run details</summary> Verified against setuptools 82.0.1 by calling `setuptools.build_meta.prepare_metadata_for_build_wheel` and `build_wheel` directly with `AIOHTTP_NO_EXTENSIONS=1`. Branch: ``` Metadata-Version: 2.4 License-Expression: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` `master` baseline, same setuptools: ``` Metadata-Version: 2.4 License: Apache-2.0 AND MIT License-File: LICENSE.txt License-File: vendor/llhttp/LICENSE ``` So the only metadata delta is `License:` -> `License-Expression:`. Both license files still land under `aiohttp-4.0.0a2.dev0.dist-info/licenses/` in the built wheel (setuptools already placed them there before this change), and `RECORD`/`WHEEL` are unaffected. Not run in this environment: `pre-commit` and `towncrier` are not installed offline, so `make lint` and the changelog-fragment check were not executed locally. The diff touches only `pyproject.toml` and a new `CHANGES/` fragment. </details> --- ### Quality Report **Changes**: 2 files changed, 14 insertions(+), 14 deletions(-) **Code scan**: clean **Tests**: failed (FAILED) **Branch hygiene**: clean _Generated by [Kōan](https://koan.anantys.com)_ (cherry picked from commit d60a88e283e0dbc7d91d831b43e3f456d8d1a39f)
patchback/backports/3.15/d60a88e283e0dbc7d91d831b43e3f456d8d1a39f/pr-13891
3 hours ago
Add changelog fragment for PEP 639 license metadata
aiolibsbot:koan/pep639-license-metadata
3 hours ago
[PR #13886/b6c9917c backport][3.14] Add hdrs constants for widely used headers (#13889) **This is a backport of PR #13886 as merged into master (b6c9917c8c3bb3e2d4ce6f3d28f0851164014041).** The cherry-pick conflicted only in the `tests/test_http_parser.py` imports; the new tests also use the `loop` fixture that 3.14 has instead of master's `event_loop`. Tested on 3.14 with the Cython parser built: `tests/test_http_parser.py` passes; the full suite's only failures are 7 pytester-based tests that fail the same way on an unmodified 3.14 in this environment. --- <!-- Thank you for your contribution! --> ## What do these changes do? Adds `hdrs` constants for widely used headers, 56 in all: - sent by browsers on every request: `Sec-Fetch-Dest/Mode/Site/User`, `Sec-CH-UA`, `Sec-CH-UA-Mobile`, `Sec-CH-UA-Platform`, `Sec-GPC`, `Sec-Purpose`, `Upgrade-Insecure-Requests`, `Priority`; - W3C trace context, on every request between OpenTelemetry-instrumented services: `traceparent`, `tracestate`, `baggage` (spelled as the spec does); - response security and reporting: `Strict-Transport-Security`, `Content-Security-Policy(-Report-Only)`, `Referrer-Policy`, `Permissions-Policy`, `Cross-Origin-Embedder/Opener/Resource-Policy`, `Origin-Agent-Cluster`, `X-Content-Type-Options`, `X-Frame-Options`, `Server-Timing`, `Timing-Allow-Origin`, `NEL`, `Report-To`, `Reporting-Endpoints`, `Accept-CH`, `Clear-Site-Data`; - RFC fields that were missing: `Authentication-Info`, `Proxy-Authentication-Info` (RFC 9110), `Content-Digest`, `Repr-Digest`, `Want-Content-Digest`, `Want-Repr-Digest` (RFC 9530), `Alt-Svc`, `Alt-Used`, `Cache-Status`, `CDN-Cache-Control`, `CDN-Loop`, `Early-Data`, `Content-ID`; - de facto: `X-Real-IP`, `X-Request-ID`, `X-Forwarded-Port` from proxies, and `X-Correlation-ID`, `X-Powered-By`, `X-RateLimit-Limit/Remaining/Reset`, `X-Requested-With`, `X-XSS-Protection` from applications. The constants are now grouped by where the header is defined (IETF RFCs, web platform specs, de facto proxy headers, de facto application headers), sorted within each group. Vendor headers (`CF-*`, `X-Amz*`, `X-B3-*`) are left out. The new test found a bug in `tools/gen.py`: it built the lookup trie case-sensitively but named the C labels in upper case, so `Accept-CH` and `Accept-Charset`, or `traceparent` and `TE`, produced the same label and one branch was silently dropped. The trie is now keyed case-insensitively; for the header list on master the generated `_find_header.c` is byte-identical. The generated code also compiled with warnings under `-Wall -Wextra` (a `const`-discarding pointer that started one byte before the buffer, an unused label) and wrapped `NEXT_CHAR()` in `{ } while(0);` rather than `do { } while (0)`; those are fixed too. `docs/multipart.rst` has used `aiohttp.hdrs.CONTENT_ID` since 2015, but the constant never existed, so the example raised `AttributeError`; it now exists, and the example's value is a valid message ID (`<part1@example.com>`). The generated `find_header()` picks the new names up, so the C parser returns them as the shared `istr` constants instead of building a new `str` per header. That saves the decode when parsing, and the `str` to `istr` conversion `CIMultiDict` does when the key is read. Measured with callgrind on 3.14, instructions per parsed request: | request | parse | parse + `items()` | parse + 3 `get()` | | --- | ---: | ---: | ---: | | Chrome page load, 15 headers | 92,159 → 83,984 (-8.9%) | 146,100 → 132,423 (-9.4%) | 102,641 → 94,465 (-8.0%) | | behind nginx, 7 headers | 57,322 → 55,209 (-3.7%) | 85,680 → 82,334 (-3.9%) | 67,823 → 65,710 (-3.1%) | | curl, no new names (control) | 40,771 → 40,745 | 56,773 → 56,750 | 54,366 → 54,342 | ## Are there changes in behavior for the user? New constants in `aiohttp.hdrs`. With the C parser, these header names now come back as the `hdrs` `istr` objects rather than plain `str`; they compare and hash the same. ## Is it a substantial burden for the maintainers to support this? No, the lookup table is generated from `hdrs.py` by `tools/gen.py`. ## Related issue number None. ## Checklist - [x] I think the code is well written - [x] Unit tests for the changes exist - [x] Documentation reflects the changes (the multipart example; `hdrs` constants are not documented individually) - [x] If you provide code modification, please add yourself to `CONTRIBUTORS.txt`: already listed - [x] Add a new news fragment into the `CHANGES/` folder Drafted with Claude Opus 5.5 (Claude Code); reviewed by @asvetlov. <details> <summary>Agent run details (optional, for reviewers)</summary> - Built with Cython against multidict master (7.0.1.dev0), CPython 3.14.7. - `pytest --numprocesses=8`: 5613 passed, 94 skipped, 17 xfailed. - `AIOHTTP_NO_EXTENSIONS=1 pytest tests/test_http_parser.py tests/test_web_functional.py tests/test_client_functional.py tests/test_multipart.py`: 1090 passed, 443 skipped. - New tests: every `hdrs` istr (except the always-rejected `Sec-WebSocket-Key1`) in canonical, lower and upper case comes back from the C parser as the same object; an unknown name still comes back as `str`. - pre-commit: all hooks pass except flake8, whose hook environment fails to load `flake8-requirements` on 3.14 (`pkg_resources`); flake8 run directly is clean. - `make doc-spelling`: the only flagged words are 9 pre-existing ones in `CHANGES.rst` and older fragments. - Measurement: callgrind, `PYTHONHASHSEED=0`, instrumentation limited to a loop of `HttpRequestParserC.feed_data()` on one request, (2000 runs - 1000 runs) / 1000. - Re-measured after the full list was added: every row within 40 instructions of the table above, so the larger lookup costs nothing measurable. </details>
3.14
5 hours ago
[PR #13886/b6c9917c backport][3.15] Add hdrs constants for widely used headers (#13888) **This is a backport of PR #13886 as merged into master (b6c9917c8c3bb3e2d4ce6f3d28f0851164014041).** The cherry-pick conflicted only in the `tests/test_http_parser.py` imports; the new tests also use the `loop` fixture that 3.15 has instead of master's `event_loop`. Tested on 3.15 with the Cython parser built: `tests/test_http_parser.py` passes; the full suite's only failures are 7 pytester-based tests that fail the same way on an unmodified 3.15 in this environment. --- <!-- Thank you for your contribution! --> ## What do these changes do? Adds `hdrs` constants for widely used headers, 56 in all: - sent by browsers on every request: `Sec-Fetch-Dest/Mode/Site/User`, `Sec-CH-UA`, `Sec-CH-UA-Mobile`, `Sec-CH-UA-Platform`, `Sec-GPC`, `Sec-Purpose`, `Upgrade-Insecure-Requests`, `Priority`; - W3C trace context, on every request between OpenTelemetry-instrumented services: `traceparent`, `tracestate`, `baggage` (spelled as the spec does); - response security and reporting: `Strict-Transport-Security`, `Content-Security-Policy(-Report-Only)`, `Referrer-Policy`, `Permissions-Policy`, `Cross-Origin-Embedder/Opener/Resource-Policy`, `Origin-Agent-Cluster`, `X-Content-Type-Options`, `X-Frame-Options`, `Server-Timing`, `Timing-Allow-Origin`, `NEL`, `Report-To`, `Reporting-Endpoints`, `Accept-CH`, `Clear-Site-Data`; - RFC fields that were missing: `Authentication-Info`, `Proxy-Authentication-Info` (RFC 9110), `Content-Digest`, `Repr-Digest`, `Want-Content-Digest`, `Want-Repr-Digest` (RFC 9530), `Alt-Svc`, `Alt-Used`, `Cache-Status`, `CDN-Cache-Control`, `CDN-Loop`, `Early-Data`, `Content-ID`; - de facto: `X-Real-IP`, `X-Request-ID`, `X-Forwarded-Port` from proxies, and `X-Correlation-ID`, `X-Powered-By`, `X-RateLimit-Limit/Remaining/Reset`, `X-Requested-With`, `X-XSS-Protection` from applications. The constants are now grouped by where the header is defined (IETF RFCs, web platform specs, de facto proxy headers, de facto application headers), sorted within each group. Vendor headers (`CF-*`, `X-Amz*`, `X-B3-*`) are left out. The new test found a bug in `tools/gen.py`: it built the lookup trie case-sensitively but named the C labels in upper case, so `Accept-CH` and `Accept-Charset`, or `traceparent` and `TE`, produced the same label and one branch was silently dropped. The trie is now keyed case-insensitively; for the header list on master the generated `_find_header.c` is byte-identical. The generated code also compiled with warnings under `-Wall -Wextra` (a `const`-discarding pointer that started one byte before the buffer, an unused label) and wrapped `NEXT_CHAR()` in `{ } while(0);` rather than `do { } while (0)`; those are fixed too. `docs/multipart.rst` has used `aiohttp.hdrs.CONTENT_ID` since 2015, but the constant never existed, so the example raised `AttributeError`; it now exists, and the example's value is a valid message ID (`<part1@example.com>`). The generated `find_header()` picks the new names up, so the C parser returns them as the shared `istr` constants instead of building a new `str` per header. That saves the decode when parsing, and the `str` to `istr` conversion `CIMultiDict` does when the key is read. Measured with callgrind on 3.14, instructions per parsed request: | request | parse | parse + `items()` | parse + 3 `get()` | | --- | ---: | ---: | ---: | | Chrome page load, 15 headers | 92,159 → 83,984 (-8.9%) | 146,100 → 132,423 (-9.4%) | 102,641 → 94,465 (-8.0%) | | behind nginx, 7 headers | 57,322 → 55,209 (-3.7%) | 85,680 → 82,334 (-3.9%) | 67,823 → 65,710 (-3.1%) | | curl, no new names (control) | 40,771 → 40,745 | 56,773 → 56,750 | 54,366 → 54,342 | ## Are there changes in behavior for the user? New constants in `aiohttp.hdrs`. With the C parser, these header names now come back as the `hdrs` `istr` objects rather than plain `str`; they compare and hash the same. ## Is it a substantial burden for the maintainers to support this? No, the lookup table is generated from `hdrs.py` by `tools/gen.py`. ## Related issue number None. ## Checklist - [x] I think the code is well written - [x] Unit tests for the changes exist - [x] Documentation reflects the changes (the multipart example; `hdrs` constants are not documented individually) - [x] If you provide code modification, please add yourself to `CONTRIBUTORS.txt`: already listed - [x] Add a new news fragment into the `CHANGES/` folder Drafted with Claude Opus 5.5 (Claude Code); reviewed by @asvetlov. <details> <summary>Agent run details (optional, for reviewers)</summary> - Built with Cython against multidict master (7.0.1.dev0), CPython 3.14.7. - `pytest --numprocesses=8`: 5613 passed, 94 skipped, 17 xfailed. - `AIOHTTP_NO_EXTENSIONS=1 pytest tests/test_http_parser.py tests/test_web_functional.py tests/test_client_functional.py tests/test_multipart.py`: 1090 passed, 443 skipped. - New tests: every `hdrs` istr (except the always-rejected `Sec-WebSocket-Key1`) in canonical, lower and upper case comes back from the C parser as the same object; an unknown name still comes back as `str`. - pre-commit: all hooks pass except flake8, whose hook environment fails to load `flake8-requirements` on 3.14 (`pkg_resources`); flake8 run directly is clean. - `make doc-spelling`: the only flagged words are 9 pre-existing ones in `CHANGES.rst` and older fragments. - Measurement: callgrind, `PYTHONHASHSEED=0`, instrumentation limited to a loop of `HttpRequestParserC.feed_data()` on one request, (2000 runs - 1000 runs) / 1000. - Re-measured after the full list was added: every row within 40 instructions of the table above, so the larger lookup costs nothing measurable. </details>
3.15
5 hours ago

Latest Branches

CodSpeed Performance Gauge
0%
[PR #13891/d60a88e2 backport][3.14] Adopt PEP 639 SPDX license metadata#13893
3 hours ago
7979a36
patchback/backports/3.14/d60a88e283e0dbc7d91d831b43e3f456d8d1a39f/pr-13891
CodSpeed Performance Gauge
0%
3 hours ago
986b882
patchback/backports/3.15/d60a88e283e0dbc7d91d831b43e3f456d8d1a39f/pr-13891
CodSpeed Performance Gauge
0%
4 hours ago
f0c0b32
aiolibsbot:koan/pep639-license-metadata
© 2026 CodSpeed Technology
Home Terms Privacy Docs