Skip to content

Commit 8a7a039

Browse files
Release 2026-04-07: merge develop into main
2 parents e393511 + ef4c75c commit 8a7a039

File tree

75 files changed

+3172
-252
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+3172
-252
lines changed

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ updates:
1010
update-types:
1111
- "minor"
1212
- "patch"
13+
cooldown:
14+
default-days: 7
1315
- package-ecosystem: "gradle"
1416
directory: "/codegen"
1517
schedule:
@@ -20,6 +22,8 @@ updates:
2022
update-types:
2123
- "minor"
2224
- "patch"
25+
cooldown:
26+
default-days: 7
2327
- package-ecosystem: "github-actions"
2428
directory: "/"
2529
schedule:
@@ -30,3 +34,5 @@ updates:
3034
update-types:
3135
- "minor"
3236
- "patch"
37+
cooldown:
38+
default-days: 7

.github/workflows/check-license.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ jobs:
1818
with:
1919
persist-credentials: false
2020

21-
- uses: apache/skywalking-eyes/header@7a3b6cc34c5980cede4407ffa06fe553a999245d
21+
- uses: apache/skywalking-eyes/header@6ac35584d6f923b6cb62f1ae8682c5bc60b537e4
2222
with:
2323
mode: check

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ jobs:
3131
distribution: 'corretto'
3232

3333
- name: Setup Gradle
34-
uses: gradle/actions/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884
34+
uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f
3535

3636
- name: Install uv and set the Python version
37-
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b
37+
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
3838
with:
3939
python-version: ${{ matrix.python-version }}
4040
activate-environment: true

.github/workflows/zizmor.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: GitHub Actions Security Analysis with zizmor 🌈
2+
3+
on:
4+
push:
5+
branches: ["develop"]
6+
pull_request:
7+
branches: ["develop"]
8+
9+
permissions: {}
10+
11+
jobs:
12+
zizmor:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
security-events: write
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
19+
with:
20+
persist-credentials: false
21+
22+
- name: Run zizmor 🌈
23+
uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2

Makefile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ build-java: ## Builds the Java code generation packages.
1414
cd codegen && ./gradlew clean build
1515

1616

17-
test-protocols: ## Generates and runs the restJson1 protocol tests.
18-
cd codegen && ./gradlew :protocol-test:build
19-
uv pip install codegen/protocol-test/build/smithyprojections/protocol-test/rest-json-1/python-client-codegen
20-
uv run pytest codegen/protocol-test/build/smithyprojections/protocol-test/rest-json-1/python-client-codegen
17+
test-protocols: ## Generates and runs protocol tests for all supported protocols.
18+
cd codegen && ./gradlew :protocol-test:clean :protocol-test:build
19+
@set -e; for projection_dir in codegen/protocol-test/build/smithyprojections/protocol-test/*/python-client-codegen; do \
20+
uv pip install "$$projection_dir"; \
21+
uv run pytest "$$projection_dir"; \
22+
done
2123

2224

2325
lint-py: ## Runs linters and formatters on the python packages.

codegen/aws/core/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ extra["moduleName"] = "software.amazon.smithy.python.aws.codegen"
1212
dependencies {
1313
implementation(project(":core"))
1414
implementation(libs.smithy.aws.traits)
15+
implementation(libs.smithy.protocol.test.traits)
1516
}

codegen/aws/core/src/main/java/software/amazon/smithy/python/aws/codegen/AwsProtocolsIntegration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
public class AwsProtocolsIntegration implements PythonIntegration {
1717
@Override
1818
public List<ProtocolGenerator> getProtocolGenerators() {
19-
return List.of();
19+
return List.of(new AwsQueryProtocolGenerator());
2020
}
2121
}

codegen/aws/core/src/main/java/software/amazon/smithy/python/aws/codegen/AwsPythonDependency.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ private AwsPythonDependency() {}
2222
*/
2323
public static final PythonDependency SMITHY_AWS_CORE = new PythonDependency(
2424
"smithy_aws_core",
25-
"~=0.4.0",
25+
"~=0.5.0",
2626
PythonDependency.Type.DEPENDENCY,
2727
false);
2828
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package software.amazon.smithy.python.aws.codegen;
6+
7+
import java.util.Set;
8+
import software.amazon.smithy.aws.traits.protocols.AwsQueryTrait;
9+
import software.amazon.smithy.model.shapes.ShapeId;
10+
import software.amazon.smithy.python.codegen.ApplicationProtocol;
11+
import software.amazon.smithy.python.codegen.GenerationContext;
12+
import software.amazon.smithy.python.codegen.HttpProtocolTestGenerator;
13+
import software.amazon.smithy.python.codegen.SymbolProperties;
14+
import software.amazon.smithy.python.codegen.generators.ProtocolGenerator;
15+
import software.amazon.smithy.python.codegen.writer.PythonWriter;
16+
import software.amazon.smithy.utils.SmithyInternalApi;
17+
18+
@SmithyInternalApi
19+
public final class AwsQueryProtocolGenerator implements ProtocolGenerator {
20+
private static final Set<String> TESTS_TO_SKIP = Set.of(
21+
// TODO: support the request compression trait
22+
// https://smithy.io/2.0/spec/behavior-traits.html#smithy-api-requestcompression-trait
23+
"SDKAppliedContentEncoding_awsQuery",
24+
"SDKAppendsGzipAndIgnoresHttpProvidedEncoding_awsQuery",
25+
26+
// TODO: support idempotency token autofill
27+
"QueryProtocolIdempotencyTokenAutoFill",
28+
29+
// This test asserts nan == nan, which is never true.
30+
// We should update the generator to make specific assertions for these.
31+
"AwsQuerySupportsNaNFloatOutputs",
32+
33+
// TODO: support of the endpoint trait
34+
"AwsQueryEndpointTraitWithHostLabel",
35+
"AwsQueryEndpointTrait");
36+
37+
@Override
38+
public ShapeId getProtocol() {
39+
return AwsQueryTrait.ID;
40+
}
41+
42+
@Override
43+
public ApplicationProtocol getApplicationProtocol(GenerationContext context) {
44+
return ApplicationProtocol.createDefaultHttpApplicationProtocol();
45+
}
46+
47+
@Override
48+
public void initializeProtocol(GenerationContext context, PythonWriter writer) {
49+
writer.addDependency(AwsPythonDependency.SMITHY_AWS_CORE.withOptionalDependencies("xml"));
50+
writer.addImport("smithy_aws_core.aio.protocols", "AwsQueryClientProtocol");
51+
var service = context.settings().service(context.model());
52+
var serviceSymbol = context.symbolProvider().toSymbol(service);
53+
var serviceSchema = serviceSymbol.expectProperty(SymbolProperties.SCHEMA);
54+
var version = service.getVersion();
55+
writer.write("AwsQueryClientProtocol($T, $S)", serviceSchema, version);
56+
}
57+
58+
@Override
59+
public void generateProtocolTests(GenerationContext context) {
60+
context.writerDelegator()
61+
.useFileWriter("./tests/test_awsquery_protocol.py", "tests.test_awsquery_protocol", writer -> {
62+
new HttpProtocolTestGenerator(
63+
context,
64+
getProtocol(),
65+
writer,
66+
(shape, testCase) -> TESTS_TO_SKIP.contains(testCase.getId())).run();
67+
});
68+
}
69+
}

codegen/core/src/main/java/software/amazon/smithy/python/codegen/HttpProtocolTestGenerator.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.logging.Logger;
1717
import java.util.stream.Collectors;
1818
import java.util.stream.Stream;
19+
import software.amazon.smithy.aws.traits.auth.SigV4Trait;
1920
import software.amazon.smithy.codegen.core.CodegenException;
2021
import software.amazon.smithy.codegen.core.Symbol;
2122
import software.amazon.smithy.model.Model;
@@ -188,12 +189,14 @@ private void generateRequestTest(OperationShape operation, HttpRequestTestCase t
188189
endpoint_uri="https://$L/$L",
189190
transport = $T(),
190191
retry_strategy=SimpleRetryStrategy(max_attempts=1),
192+
${C|}
191193
)
192194
""",
193195
CodegenUtils.getConfigSymbol(context.settings()),
194196
host,
195197
path,
196-
REQUEST_TEST_ASYNC_HTTP_CLIENT_SYMBOL);
198+
REQUEST_TEST_ASYNC_HTTP_CLIENT_SYMBOL,
199+
(Runnable) this::writeSigV4TestConfig);
197200
}));
198201

199202
// Generate the input using the expected shape and params
@@ -418,6 +421,16 @@ private void compareMediaBlob(HttpMessageTestCase testCase, PythonWriter writer)
418421
""");
419422
return;
420423
}
424+
if (contentType.equals("application/x-www-form-urlencoded")) {
425+
writer.addStdlibImport("urllib.parse", "parse_qsl");
426+
writer.write("""
427+
actual_params = sorted(parse_qsl(actual_body_content.decode(), keep_blank_values=True))
428+
expected_params = sorted(parse_qsl(expected_body_content.decode(), keep_blank_values=True))
429+
assert actual_params == expected_params
430+
431+
""");
432+
return;
433+
}
421434
writer.write("assert actual_body_content == expected_body_content\n");
422435
}
423436

@@ -437,13 +450,15 @@ private void generateResponseTest(OperationShape operation, HttpResponseTestCase
437450
headers=$J,
438451
body=b$S,
439452
),
453+
${C|}
440454
)
441455
""",
442456
CodegenUtils.getConfigSymbol(context.settings()),
443457
RESPONSE_TEST_ASYNC_HTTP_CLIENT_SYMBOL,
444458
testCase.getCode(),
445459
CodegenUtils.toTuples(testCase.getHeaders()),
446-
testCase.getBody().filter(body -> !body.isEmpty()).orElse(""));
460+
testCase.getBody().filter(body -> !body.isEmpty()).orElse(""),
461+
(Runnable) this::writeSigV4TestConfig);
447462
}));
448463
// Create an empty input object to pass
449464
var inputShape = model.expectShape(operation.getInputShape(), StructureShape.class);
@@ -490,13 +505,15 @@ private void generateErrorResponseTest(
490505
headers=$J,
491506
body=b$S,
492507
),
508+
${C|}
493509
)
494510
""",
495511
CodegenUtils.getConfigSymbol(context.settings()),
496512
RESPONSE_TEST_ASYNC_HTTP_CLIENT_SYMBOL,
497513
testCase.getCode(),
498514
CodegenUtils.toTuples(testCase.getHeaders()),
499-
testCase.getBody().orElse(""));
515+
testCase.getBody().orElse(""),
516+
(Runnable) this::writeSigV4TestConfig);
500517
}));
501518
// Create an empty input object to pass
502519
var inputShape = model.expectShape(operation.getInputShape(), StructureShape.class);
@@ -607,6 +624,19 @@ private void writeClientBlock(
607624
});
608625
}
609626

627+
private void writeSigV4TestConfig() {
628+
if (!service.hasTrait(SigV4Trait.class)) {
629+
return;
630+
}
631+
writer.addImport("smithy_aws_core.identity", "StaticCredentialsResolver");
632+
writer.write("""
633+
region="us-east-1",
634+
aws_access_key_id="test-access-key-id",
635+
aws_secret_access_key="test-secret-access-key",
636+
aws_credentials_identity_resolver=StaticCredentialsResolver(),
637+
""");
638+
}
639+
610640
private void writeUtilStubs(Symbol serviceSymbol) {
611641
LOGGER.fine(String.format("Writing utility stubs for %s : %s", serviceSymbol.getName(), protocol.getName()));
612642
writer.addDependency(SmithyPythonDependency.SMITHY_CORE);

0 commit comments

Comments
 (0)