From 52cf847a0f2c410ea06703e97e450137352aefe5 Mon Sep 17 00:00:00 2001 From: "jack.burridge" Date: Tue, 27 Jan 2026 07:52:02 +0000 Subject: [PATCH 1/3] ci(tests): remove use of secret when pushing codecov results --- .github/workflows/tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6a7973b..dedc189 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,6 +4,9 @@ on: branches: main pull_request: branches: main +permissions: + contents: read + id-token: write env: FORCE_COLOR: 1 jobs: @@ -52,4 +55,4 @@ jobs: - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v5 with: - token: ${{ secrets.CODECOV_TOKEN }} + use_oidc: true From 1d08f55e9f594bfdfb497ab5a28916939e094846 Mon Sep 17 00:00:00 2001 From: "jack.burridge" Date: Tue, 27 Jan 2026 08:20:17 +0000 Subject: [PATCH 2/3] ci(publish): remove secret when publishing packages --- .github/workflows/publish.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3167ea3..7c9c09a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,6 +2,9 @@ name: Publish on: push: tags: ["*"] +permissions: + id-token: write + contents: read jobs: publish: name: Publish @@ -14,5 +17,3 @@ jobs: run: uv build --all-packages - name: Publish run: uv publish - env: - UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN }} From 5d7f85949dcb1caeca759eac9957486bb601f9cb Mon Sep 17 00:00:00 2001 From: "jack.burridge" Date: Tue, 27 Jan 2026 08:20:53 +0000 Subject: [PATCH 3/3] perf(asyncfast): avoid json.loads when validating payloads --- packages/asyncfast/src/asyncfast/__init__.py | 11 +++---- .../asyncfast/tests_asyncfast/test_message.py | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/packages/asyncfast/src/asyncfast/__init__.py b/packages/asyncfast/src/asyncfast/__init__.py index 54f7e5b..26dbe82 100644 --- a/packages/asyncfast/src/asyncfast/__init__.py +++ b/packages/asyncfast/src/asyncfast/__init__.py @@ -1,6 +1,5 @@ import asyncio import inspect -import json import re from collections import Counter from collections.abc import AsyncGenerator @@ -689,11 +688,11 @@ def _generate_payload( ) -> Generator[tuple[str, Any], None, None]: if self.payload: name, field = self.payload - payload = message_receive_event.get("payload") - payload_obj = None if payload is None else json.loads(payload) - value = field.type_adapter.validate_python( - payload_obj, from_attributes=True - ) + payload: bytes | None = message_receive_event.get("payload") + if payload is None: + value = field.type_adapter.validate_python(None) + else: + value = field.type_adapter.validate_json(payload) yield name, value def _generate_bindings( diff --git a/packages/asyncfast/tests_asyncfast/test_message.py b/packages/asyncfast/tests_asyncfast/test_message.py index 5fc3fdb..fc8dfa7 100644 --- a/packages/asyncfast/tests_asyncfast/test_message.py +++ b/packages/asyncfast/tests_asyncfast/test_message.py @@ -62,6 +62,37 @@ async def topic_handler(payload: MessagePayload) -> None: test_mock.assert_called_once_with(MessagePayload(id=1)) +async def test_message_payload_optional() -> None: + app = AsyncFast() + + class MessagePayload(BaseModel): + id: int + + test_mock = Mock() + + @app.channel("topic") + async def topic_handler(payload: MessagePayload | None) -> None: + test_mock(payload) + + message_scope: MessageScope = { + "type": "message", + "amgi": {"version": "1.0", "spec_version": "1.0"}, + "address": "topic", + } + message_receive_event: MessageReceiveEvent = { + "type": "message.receive", + "id": "id-1", + "headers": [], + } + await app( + message_scope, + AsyncMock(side_effect=[message_receive_event]), + AsyncMock(), + ) + + test_mock.assert_called_once_with(None) + + async def test_message_payload_sync() -> None: app = AsyncFast()