Skip to content

Commit 8a2dfdd

Browse files
committed
Merge branch 'master' into update-botocore-1.37.3
2 parents 2c20370 + d2d8f2b commit 8a2dfdd

16 files changed

+4385
-2905
lines changed

.github/workflows/ci-cd.yml

Lines changed: 26 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
---
22
name: CI/CD
33

4+
permissions: {}
5+
46
on:
57
merge_group:
68
push:
@@ -22,28 +24,9 @@ env:
2224

2325
jobs:
2426
build:
25-
name: Build distribution 📦
26-
runs-on: ubuntu-24.04
27-
timeout-minutes: 5
28-
29-
steps:
30-
- uses: actions/checkout@v4
31-
- name: Install uv
32-
uses: astral-sh/setup-uv@v5
33-
- name: Build distribution 📦
34-
run: uv build
35-
- name: Check distribution 📦
36-
run: uvx twine check --strict dist/*
37-
- name: Upload distribution 📦
38-
uses: actions/upload-artifact@v4
39-
with:
40-
name: python-package-distributions
41-
path: dist/
27+
uses: ./.github/workflows/reusable-build.yml
4228

4329
test:
44-
name: Test Python ${{ matrix.python-version }} on ${{ matrix.os }}
45-
runs-on: ${{ matrix.os }}
46-
continue-on-error: ${{ matrix.experimental }}
4730
strategy:
4831
matrix:
4932
python-version:
@@ -67,49 +50,35 @@ jobs:
6750
python-version: 3.11
6851
os: ubuntu-24.04
6952
fail-fast: false
70-
env:
71-
UV_FROZEN: 1
72-
timeout-minutes: 5
53+
uses: ./.github/workflows/reusable-test.yml
54+
with:
55+
python-version: ${{ matrix.python-version }}
56+
os: ${{ matrix.os }}
57+
continue-on-error: ${{ matrix.experimental }}
58+
enable-cache: ${{ github.ref_type == 'tag' && 'false' || 'auto' }}
59+
upload-coverage: ${{ matrix.upload-coverage }}
60+
secrets:
61+
# yamllint disable-line rule:line-length
62+
codecov-token: ${{ matrix.upload-coverage && secrets.CODECOV_TOKEN || '' }}
7363

74-
steps:
75-
- name: Checkout
76-
uses: actions/checkout@v4
77-
with:
78-
submodules: true
79-
- name: Install uv
80-
uses: astral-sh/setup-uv@v5
81-
with:
82-
python-version: ${{ matrix.python-version }}
83-
- name: Run pre-commit hooks
84-
run: |
85-
uv run make pre-commit
86-
- name: Run unittests
87-
env:
88-
COLOR: 'yes'
89-
run: |
90-
uv run make mototest
91-
- name: Upload coverage to Codecov
92-
if: ${{ matrix.upload-coverage }}
93-
uses: codecov/codecov-action@v5.4.2
94-
with:
95-
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
96-
files: ./coverage.xml
97-
flags: unittests # optional
98-
name: codecov-umbrella # optional
99-
fail_ci_if_error: true # optional (default = false)
100-
verbose: true # optional (default = false)
64+
zizmor:
65+
uses: ./.github/workflows/reusable-zizmor.yml
66+
permissions:
67+
security-events: write
10168

10269
check: # This job does nothing and is only used for the branch protection
10370
if: always()
10471
needs:
10572
- build
10673
- test
74+
- zizmor
10775
runs-on: ubuntu-24.04
10876
timeout-minutes: 5
10977

11078
steps:
11179
- name: Decide whether the needed jobs succeeded or failed
112-
uses: re-actors/alls-green@release/v1
80+
# yamllint disable-line rule:line-length
81+
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
11382
with:
11483
jobs: ${{ toJSON(needs) }}
11584

@@ -135,7 +104,10 @@ jobs:
135104
path: dist/
136105
- name: Check if distribution 📦 names match git tag
137106
run: |
138-
test -f "dist/aiobotocore-${{ github.ref_name }}.tar.gz"
139-
test -f "dist/aiobotocore-${{ github.ref_name }}-py3-none-any.whl"
107+
test -f "dist/aiobotocore-${REF_NAME}.tar.gz"
108+
test -f "dist/aiobotocore-${REF_NAME}-py3-none-any.whl"
109+
env:
110+
REF_NAME: ${{ github.ref_name }}
140111
- name: Publish distribution 📦 to PyPI
141-
uses: pypa/gh-action-pypi-publish@release/v1
112+
# yamllint disable-line rule:line-length
113+
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4

.github/workflows/reusable-build.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
name: Reusable build
3+
4+
permissions: {}
5+
6+
on:
7+
workflow_call:
8+
9+
env:
10+
FORCE_COLOR: 1
11+
12+
jobs:
13+
build:
14+
name: Build distribution 📦
15+
runs-on: ubuntu-24.04
16+
timeout-minutes: 5
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
persist-credentials: false
22+
- name: Install uv
23+
# yamllint disable-line rule:line-length
24+
uses: astral-sh/setup-uv@c7f87aa956e4c323abf06d5dec078e358f6b4d04 # v6.0.0
25+
with:
26+
# yamllint disable-line rule:line-length
27+
enable-cache: | # zizmor: ignore[cache-poisoning] cache is disabled when publishing to prevent poisoning
28+
${{ github.ref_type == 'tag' && 'false' || 'auto' }}
29+
- name: Build distribution 📦
30+
run: uv build
31+
- name: Check distribution 📦
32+
run: uvx twine check --strict dist/*
33+
- name: Upload distribution 📦
34+
uses: actions/upload-artifact@v4
35+
with:
36+
name: python-package-distributions
37+
path: dist/

.github/workflows/reusable-test.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
name: Reusable test
3+
4+
permissions: {}
5+
6+
on:
7+
workflow_call:
8+
inputs:
9+
python-version:
10+
type: string
11+
required: true
12+
os:
13+
type: string
14+
required: true
15+
continue-on-error:
16+
type: boolean
17+
enable-cache:
18+
type: string
19+
required: true
20+
upload-coverage:
21+
type: boolean
22+
secrets:
23+
codecov-token:
24+
required: false
25+
26+
env:
27+
FORCE_COLOR: 1
28+
29+
jobs:
30+
test:
31+
name: Test Python ${{ inputs.python-version }} on ${{ inputs.os }}
32+
runs-on: ${{ inputs.os }}
33+
continue-on-error: ${{ inputs.continue-on-error }}
34+
env:
35+
UV_FROZEN: 1
36+
timeout-minutes: 5
37+
38+
steps:
39+
- name: Checkout
40+
uses: actions/checkout@v4
41+
with:
42+
persist-credentials: false
43+
submodules: true
44+
- name: Install uv
45+
# yamllint disable-line rule:line-length
46+
uses: astral-sh/setup-uv@c7f87aa956e4c323abf06d5dec078e358f6b4d04 # v6.0.0
47+
with:
48+
python-version: ${{ inputs.python-version }}
49+
enable-cache: ${{ inputs.enable-cache }}
50+
- name: Run pre-commit hooks
51+
run: |
52+
uv run make pre-commit
53+
- name: Run unittests
54+
env:
55+
COLOR: 'yes'
56+
run: |
57+
uv run make mototest
58+
- name: Upload coverage to Codecov
59+
if: ${{ inputs.upload-coverage }}
60+
# yamllint disable-line rule:line-length
61+
uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5.4.2
62+
with:
63+
token: ${{ secrets.codecov-token }} # not required for public repos
64+
files: ./coverage.xml
65+
flags: unittests # optional
66+
name: codecov-umbrella # optional
67+
fail_ci_if_error: true # optional (default = false)
68+
verbose: true # optional (default = false)

.github/workflows/reusable-zizmor.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
name: Reusable zizmor
3+
4+
permissions: {}
5+
6+
on:
7+
workflow_call:
8+
9+
env:
10+
FORCE_COLOR: 1
11+
12+
jobs:
13+
zizmor:
14+
name: zizmor
15+
runs-on: ubuntu-24.04
16+
permissions:
17+
security-events: write
18+
timeout-minutes: 5
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
persist-credentials: false
24+
- name: Install uv
25+
# yamllint disable-line rule:line-length
26+
uses: astral-sh/setup-uv@c7f87aa956e4c323abf06d5dec078e358f6b4d04 # v6.0.0
27+
with:
28+
# yamllint disable-line rule:line-length
29+
enable-cache: | # zizmor: ignore[cache-poisoning] cache is disabled when publishing to prevent poisoning
30+
${{ github.ref_type == 'tag' && 'false' || 'auto' }}
31+
- name: Run zizmor 🌈
32+
run: uvx zizmor --format=sarif . > results.sarif
33+
env:
34+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35+
- name: Upload SARIF file
36+
uses: github/codeql-action/upload-sarif@v3
37+
with:
38+
sarif_file: results.sarif
39+
category: zizmor

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ repos:
2222
args: [--fix]
2323
- id: ruff-format
2424
- repo: https://github.com/astral-sh/uv-pre-commit
25-
rev: 0.6.0
25+
rev: 0.6.17
2626
hooks:
2727
- id: uv-lock
2828
- repo: https://github.com/adrienverge/yamllint

CHANGES.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
Changes
22
-------
33

4-
2.22.0 (2025-04-15)
4+
2.22.0 (2025-04-29)
55
^^^^^^^^^^^^^^^^^^^
6-
* patch `ResponseParser`
6+
* fully patch ``ClientArgsCreator.get_client_args()``
7+
* patch ``AioEndpoint.__init__()``
8+
* patch ``EventStream._parse_event()``, ``ResponseParser`` and subclasses
79
* use SPDX license identifier for project metadata
810
* upstream support for the smithy-rpc-v2-cbor protocol
911
* bump botocore dependency specification

aiobotocore/args.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from .config import AioConfig
88
from .endpoint import DEFAULT_HTTP_SESSION_CLS, AioEndpointCreator
9+
from .parsers import create_parser
910
from .regions import AioEndpointRulesetResolver
1011
from .signers import AioRequestSigner
1112

@@ -94,7 +95,7 @@ def get_client_args(
9495
serializer = botocore.serialize.create_serializer(
9596
protocol, parameter_validation
9697
)
97-
response_parser = botocore.parsers.create_parser(protocol)
98+
response_parser = create_parser(protocol)
9899

99100
ruleset_resolver = self._build_endpoint_resolver(
100101
endpoints_ruleset_data,

aiobotocore/endpoint.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from aiobotocore.httpchecksum import handle_checksum_body
1818
from aiobotocore.httpsession import AIOHTTPSession
19+
from aiobotocore.parsers import AioResponseParserFactory
1920
from aiobotocore.response import StreamingBody
2021

2122
DEFAULT_HTTP_SESSION_CLS = AIOHTTPSession
@@ -57,6 +58,28 @@ async def convert_to_response_dict(http_response, operation_model):
5758

5859

5960
class AioEndpoint(Endpoint):
61+
def __init__(
62+
self,
63+
host,
64+
endpoint_prefix,
65+
event_emitter,
66+
response_parser_factory=None,
67+
http_session=None,
68+
):
69+
if response_parser_factory is None:
70+
response_parser_factory = AioResponseParserFactory()
71+
72+
if http_session is None:
73+
raise ValueError('http_session must be provided')
74+
75+
super().__init__(
76+
host=host,
77+
endpoint_prefix=endpoint_prefix,
78+
event_emitter=event_emitter,
79+
response_parser_factory=response_parser_factory,
80+
http_session=http_session,
81+
)
82+
6083
async def close(self):
6184
await self.http_session.close()
6285

@@ -203,7 +226,6 @@ async def _do_get_response(self, request, operation_model, context):
203226
customized_response_dict=customized_response_dict,
204227
)
205228
parser = self._response_parser_factory.create_parser(protocol)
206-
207229
parsed_response = await parser.parse(
208230
response_dict, operation_model.output_shape
209231
)
@@ -233,7 +255,6 @@ async def _add_modeled_error_fields(
233255
error_shape = service_model.shape_for_error_code(error_code)
234256
if error_shape is None:
235257
return
236-
237258
modeled_parse = await parser.parse(response_dict, error_shape)
238259
# TODO: avoid naming conflicts with ResponseMetadata and Error
239260
parsed_response.update(modeled_parse)

aiobotocore/eventstream.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
EventStreamBuffer,
44
NoInitialResponseError,
55
)
6+
from botocore.exceptions import EventStreamError
67

78

89
class AioEventStream(EventStream):
@@ -14,7 +15,7 @@ def __aiter__(self):
1415

1516
async def __anext__(self):
1617
async for event in self._event_generator:
17-
parsed_event = self._parse_event(event)
18+
parsed_event = await self._parse_event(event)
1819
if parsed_event:
1920
yield parsed_event
2021

@@ -25,6 +26,16 @@ async def _create_raw_event_generator(self):
2526
for event in event_stream_buffer:
2627
yield event # unfortunately no yield from async func support
2728

29+
async def _parse_event(self, event):
30+
response_dict = event.to_response_dict()
31+
parsed_response = await self._parser.parse(
32+
response_dict, self._output_shape
33+
)
34+
if response_dict['status_code'] == 200:
35+
return parsed_response
36+
else:
37+
raise EventStreamError(parsed_response, self._operation_name)
38+
2839
async def get_initial_response(self):
2940
try:
3041
async for event in self._event_generator:

0 commit comments

Comments
 (0)