Skip to content

Revive for modern Python (2.0): native async, pyproject packaging, CI#754

Merged
dchaplinsky merged 5 commits into
masterfrom
claude/modernize-aiohttp-validate
Jul 19, 2026
Merged

Revive for modern Python (2.0): native async, pyproject packaging, CI#754
dchaplinsky merged 5 commits into
masterfrom
claude/modernize-aiohttp-validate

Conversation

@dchaplinsky

Copy link
Copy Markdown
Owner

The library has been unusable on Python 3.11+ since October 2022: the decorator is built on @asyncio.coroutine, which was removed in 3.11, so decorating any handler raises AttributeError. This PR brings it back to life.

Core

  • Rewritten with native async/await; behavior preserved, all original tests pass. Plain (non-async) handlers remain supported.
  • New: handlers may return a (data, status) tuple to set the response status code — closes How i can return custom response status? #180.
  • Handler signature (data, request) now documented in the README — answers How to retrieve original aiohttp handler request object? #246 (the original request object was always the second argument).
  • __ALL__ typo (which was also accidentally a tuple) fixed to a proper __all__; type hints + py.typed.

Packaging

  • setup.py/setup.cfg/Makefile/tox.ini/.travis.yml/travis_pypi_setup.py/requirements_dev.txt/MANIFEST.in and the stale sphinx skeleton replaced by a single pyproject.toml.
  • Version single-sourced as 2.0 (the repo previously carried three conflicting versions: setup.py 1.2.0, __version__ 0.1.1, PyPI 1.1.0).
  • Removed the console_scripts entry point pointing at aiohttp_validate.cli — a module that never existed, so installed scripts crashed on invocation.
  • Dependencies floor-bumped: aiohttp>=3.8, jsonschema>=3.0, requires-python >= 3.9 — addresses Outdated requirements #130.

Tests / CI

  • Tests modernized for current aiohttp/pytest-aiohttp (the removed loop argument), plus new coverage for the status tuple and sync handlers: 9 tests, verified locally against aiohttp 3.14.1 + jsonschema 4.26.
  • tests.yml: CPython 3.9–3.13 matrix. publish.yml: PyPI trusted publishing on v* tags or manual dispatch (one-time PyPI setup: publisher for aiohttp_validate, workflow publish.yml, environment pypi).

Merging this also renders the 18 open bot PRs (pyup/dependabot) obsolete — their target files no longer exist.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ha16zNy2fDMdrZBMQGgpBt


Generated by Claude Code

dchaplinsky and others added 5 commits July 19, 2026 14:40
- Rewrite the decorator with native async/await: asyncio.coroutine was
  removed in Python 3.11, which made the library unusable there. Plain
  (non-async) handlers remain supported via inspect.iscoroutinefunction
- Handlers may return a (data, status) tuple to set the response status
  code (closes the long-standing request in #180)
- Document the handler signature (data, request) in README, answering #246
- Fix __ALL__ typo (a misnamed tuple) to a proper __all__
- Replace setup.py/setup.cfg/Makefile/tox/travis/pyup scaffolding with
  pyproject.toml: version 2.0 (single-sourced; the repo previously carried
  three conflicting versions), requires-python >=3.9, aiohttp>=3.8,
  jsonschema>=3.0, py.typed marker; drop the console_scripts entry point
  that referenced a module that never existed; remove the stale sphinx
  skeleton
- Modernize tests for current aiohttp/pytest-aiohttp (no loop argument),
  add coverage for the status tuple and sync handlers
- tests.yml: matrix on CPython 3.9-3.13; publish.yml: PyPI trusted
  publishing on v* tags or manual dispatch
- README badges and examples refreshed; HISTORY updated

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha16zNy2fDMdrZBMQGgpBt
- inspect.iscoroutinefunction is evaluated once at decoration time
  instead of on every request
- The (data, status) shape check excludes bools and its collision case
  (response data that is itself a 2-tuple ending in an int) is documented
  in the docstring and README
- _raise_exception is annotated NoReturn so type checkers see the truth

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha16zNy2fDMdrZBMQGgpBt
New tests for the previously uncovered branches: the type-mismatch error
formatting path, plain-class (non-web.View) method handlers, ready
StreamResponse passthrough, the bool-tuple non-hijack guarantee, and
tuple response data serializing as a JSON array.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha16zNy2fDMdrZBMQGgpBt
…ecker

- A plain (non-async) handler returning an awaitable is awaited again,
  matching the old asyncio.coroutine behavior the async rewrite dropped
- jsonschema validator instances are built once at decoration time
  instead of per request
- New optional format_checker argument, passed through to the validator,
  for opt-in string format validation
- HISTORY now explicitly flags the (data, status) breaking edge case
- 16 tests, 100% line coverage

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha16zNy2fDMdrZBMQGgpBt
- Calling the handler and awaiting the result if it is awaitable covers
  coroutine functions and plain callables alike, so the hoisted
  iscoroutinefunction dispatch is gone entirely
- format_checker is typed as Optional[FormatChecker] instead of Any
- Validator setup uses single conditional bindings

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha16zNy2fDMdrZBMQMGgpBt
@dchaplinsky
dchaplinsky merged commit 479ade8 into master Jul 19, 2026
5 checks passed
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.

How i can return custom response status?

1 participant