Skip to content

Commit

Permalink
Support Python 3.13 (#327)
Browse files Browse the repository at this point in the history
* Support Python 3.13

* Support Python 3.13

* Use the right 3.13

* Try to enforce Python version

* Fix min python version

* Sync dependencies

* Fix linters

* Drop 3.7

* Don't drop 3.7

* Update hypercorn

* Fix 3.7

* Readd 3.7 support sentence
  • Loading branch information
Kludex authored Sep 20, 2024
1 parent 01bf7a6 commit ab163ef
Show file tree
Hide file tree
Showing 12 changed files with 487 additions and 527 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4

Expand All @@ -25,7 +25,7 @@ jobs:
run: uv python install ${{ matrix.python-version }}

- name: Install dependencies
run: uv sync --frozen
run: uv sync --python ${{ matrix.python-version }} --frozen

- name: Run tests
run: scripts/test
Expand Down
29 changes: 16 additions & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ Hello. Contributions to this project are highly encouraged and appreciated. This

## Contents

- [Creating a pull request](#creating-a-pull-request)
* [Setting up the repository](#setting-up-the-repository)
- [Developing the project locally](#developing-the-project-locally)
* [Setup](#setup)
* [Test](#test)
+ [Coverage requirements](#coverage-requirements)
* [Lint](#lint)
+ [Code style and formatting](#code-style-and-formatting)
+ [Static type checking](#static-type-checking)
- [Using the issue tracker](#using-the-issue-tracker)
* [Technical support](#technical-support)
* [Feature requests](#feature-requests)
- [Contributing to Mangum](#contributing-to-mangum)
- [Contents](#contents)
- [Creating a pull request](#creating-a-pull-request)
- [Setting up the repository](#setting-up-the-repository)
- [Developing the project locally](#developing-the-project-locally)
- [Setup](#setup)
- [Test](#test)
- [Coverage requirements](#coverage-requirements)
- [Lint](#lint)
- [Code style and formatting](#code-style-and-formatting)
- [Static type checking](#static-type-checking)
- [Using the issue tracker](#using-the-issue-tracker)
- [Technical support](#technical-support)
- [Feature requests](#feature-requests)
- [Thank you](#thank-you)

## Creating a pull request

Expand Down Expand Up @@ -65,7 +68,7 @@ python -m venv venv
pip install -r requirements.txt
```

This environment is used to run the tests for Python versions 3.7, 3.8, 3.9, and 3.10.
This environment is used to run the tests for Python versions 3.8, 3.9, 3.10, 3.11, 3.12 and 3.13.

### Test

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Mangum is an adapter for running [ASGI](https://asgi.readthedocs.io/en/latest/)

- Event handlers for API Gateway [HTTP](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html) and [REST](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html) APIs, [Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html), [Function URLs](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html), and [CloudFront Lambda@Edge](https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html).

- Compatibility with ASGI application frameworks, such as [Starlette](https://www.starlette.io/), [FastAPI](https://fastapi.tiangolo.com/), [Quart](https://pgjones.gitlab.io/quart/) and [Django](https://www.djangoproject.com/).
- Compatibility with ASGI application frameworks, such as [Starlette](https://www.starlette.io/), [FastAPI](https://fastapi.tiangolo.com/), [Quart](https://pgjones.gitlab.io/quart/) and [Django](https://www.djangoproject.com/).

- Support for binary media types and payload compression in API Gateway using GZip or Brotli.

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Mangum is an adapter for running [ASGI](https://asgi.readthedocs.io/en/latest/)

- Event handlers for API Gateway [HTTP](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html) and [REST](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html) APIs, [Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html), [Function URLs](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html), and [CloudFront Lambda@Edge](https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html).

- Compatibility with ASGI application frameworks, such as [Starlette](https://www.starlette.io/), [FastAPI](https://fastapi.tiangolo.com/), [Quart](https://pgjones.gitlab.io/quart/) and [Django](https://www.djangoproject.com/).
- Compatibility with ASGI application frameworks, such as [Starlette](https://www.starlette.io/), [FastAPI](https://fastapi.tiangolo.com/), [Quart](https://pgjones.gitlab.io/quart/) and [Django](https://www.djangoproject.com/).

- Support for binary media types and payload compression in API Gateway using GZip or Brotli.

Expand Down
1 change: 0 additions & 1 deletion mangum/handlers/alb.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ def body(self) -> bytes:

@property
def scope(self) -> Scope:

headers = transform_headers(self.event)
list_headers = [list(x) for x in headers]
# Unique headers. If there are duplicates, it will use the last defined.
Expand Down
1 change: 0 additions & 1 deletion mangum/protocols/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ async def send(self, message: Message) -> None:
self.headers = message.get("headers", [])
self.state = HTTPCycleState.RESPONSE
elif self.state is HTTPCycleState.RESPONSE and message["type"] == "http.response.body":

body = message.get("body", b"")
more_body = message.get("more_body", False)
self.buffer.write(body)
Expand Down
2 changes: 0 additions & 2 deletions mangum/protocols/lifespan.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,12 @@ async def run(self) -> None:
async def receive(self) -> Message:
"""Awaited by the application to receive ASGI `lifespan` events."""
if self.state is LifespanCycleState.CONNECTING:

# Connection established. The next event returned by the queue will be
# `lifespan.startup` to inform the application that the connection is
# ready to receive lfiespan messages.
self.state = LifespanCycleState.STARTUP

elif self.state is LifespanCycleState.STARTUP:

# Connection shutting down. The next event returned by the queue will be
# `lifespan.shutdown` to inform the application that the connection is now
# closing so that it may perform cleanup.
Expand Down
18 changes: 12 additions & 6 deletions mangum/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ def get_remaining_time_in_millis(self) -> int:


class ASGI(Protocol):
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: ... # pragma: no cover
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
... # pragma: no cover


LifespanMode: TypeAlias = Literal["auto", "on", "off"]
Expand All @@ -120,15 +121,20 @@ class LambdaConfig(TypedDict):


class LambdaHandler(Protocol):
def __init__(self, *args: Any) -> None: ... # pragma: no cover
def __init__(self, *args: Any) -> None:
... # pragma: no cover

@classmethod
def infer(cls, event: LambdaEvent, context: LambdaContext, config: LambdaConfig) -> bool: ... # pragma: no cover
def infer(cls, event: LambdaEvent, context: LambdaContext, config: LambdaConfig) -> bool:
... # pragma: no cover

@property
def body(self) -> bytes: ... # pragma: no cover
def body(self) -> bytes:
... # pragma: no cover

@property
def scope(self) -> Scope: ... # pragma: no cover
def scope(self) -> Scope:
... # pragma: no cover

def __call__(self, response: Response) -> dict: ... # pragma: no cover
def __call__(self, response: Response) -> dict:
... # pragma: no cover
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ authors = [
]
description = "AWS Lambda support for ASGI applications"
readme = "README.md"
requires-python = ">=3.8"
requires-python = ">=3.7"
classifiers = [
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
Expand All @@ -20,6 +20,9 @@ classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Internet :: WWW/HTTP",
]
dependencies = ["typing_extensions"]
Expand All @@ -33,6 +36,8 @@ dev-dependencies = [
"flake8",
"starlette",
"quart",
"hypercorn<0.15.0; python_version < '3.8'",
"hypercorn>=0.15.0; python_version >= '3.8'",
"mypy",
"brotli",
"brotli-asgi",
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[flake8]
max-line-length = 120
ignore = E203, W503, E704
ignore = E203, W503, E704, E231
per-file-ignores =
tests/conftest.py:E501
tests/test_http.py:E501
Expand Down
3 changes: 2 additions & 1 deletion tests/test_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from mangum.types import Receive, Scope, Send


async def app(scope: Scope, receive: Receive, send: Send): ...
async def app(scope: Scope, receive: Receive, send: Send):
...


def test_default_settings():
Expand Down
Loading

0 comments on commit ab163ef

Please sign in to comment.