Skip to content

Commit f578cb1

Browse files
authored
Merge pull request #429 from smithy-lang/pure-python-request-pipeline
Pure python request pipeline
2 parents 5d91da0 + cff549c commit f578cb1

Some content is hidden

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

45 files changed

+1424
-3695
lines changed

CHANGES.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,13 @@
22

33
## Unreleased
44

5-
* Description of change. (Issue Number)
5+
### Breaking Changes
6+
7+
* Removed the `http_client` config option in favor of the generic `transport`.
8+
9+
### Features
10+
11+
* Removed code-generated protocol implementations in favor of hand-written
12+
implementations based on schemas.
13+
* Moved documentation for structure members into doc strings after the member's
14+
dataclass field declaration.

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public class AwsAuthIntegration implements PythonIntegration {
3232

3333
@Override
3434
public List<RuntimeClientPlugin> getClientPlugins(GenerationContext context) {
35+
if (!hasSigV4Auth(context)) {
36+
return List.of();
37+
}
3538
return List.of(
3639
RuntimeClientPlugin.builder()
3740
.servicePredicate((model, service) -> service.hasTrait(SigV4Trait.class))
@@ -61,6 +64,24 @@ public List<RuntimeClientPlugin> getClientPlugins(GenerationContext context) {
6164
.nullable(true)
6265
.build())
6366
.addConfigProperty(REGION)
67+
.addConfigProperty(ConfigProperty.builder()
68+
.name("aws_access_key_id")
69+
.type(Symbol.builder().name("str").build())
70+
.documentation("The identifier for a secret access key.")
71+
.nullable(true)
72+
.build())
73+
.addConfigProperty(ConfigProperty.builder()
74+
.name("aws_secret_access_key")
75+
.type(Symbol.builder().name("str").build())
76+
.nullable(true)
77+
.documentation("A secret access key that can be used to sign requests.")
78+
.build())
79+
.addConfigProperty(ConfigProperty.builder()
80+
.name("aws_session_token")
81+
.type(Symbol.builder().name("str").build())
82+
.documentation("An access key ID that identifies temporary security credentials.")
83+
.nullable(true)
84+
.build())
6485
.authScheme(new Sigv4AuthScheme())
6586
.build());
6687
}
@@ -70,7 +91,6 @@ public void customize(GenerationContext context) {
7091
if (!hasSigV4Auth(context)) {
7192
return;
7293
}
73-
var trait = context.settings().service(context.model()).expectTrait(SigV4Trait.class);
7494
var resolver = CodegenUtils.getHttpAuthSchemeResolverSymbol(context.settings());
7595

7696
// Add a function that generates the http auth option for api key auth.
@@ -91,8 +111,7 @@ public void customize(GenerationContext context) {
91111
)
92112
""",
93113
SIGV4_OPTION_GENERATOR_NAME,
94-
SigV4Trait.ID.toString(),
95-
trait.getName());
114+
SigV4Trait.ID.toString());
96115
writer.popState();
97116
});
98117
}

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

Lines changed: 77 additions & 730 deletions
Large diffs are not rendered by default.

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,6 @@ public void generateService(GenerateServiceDirective<GenerationContext, PythonSe
124124
if (protocolGenerator == null) {
125125
return;
126126
}
127-
128-
protocolGenerator.generateSharedSerializerComponents(directive.context());
129-
protocolGenerator.generateRequestSerializers(directive.context());
130-
131-
protocolGenerator.generateSharedDeserializerComponents(directive.context());
132-
protocolGenerator.generateResponseDeserializers(directive.context());
133-
134127
protocolGenerator.generateProtocolTests(directive.context());
135128
}
136129

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ private void generateRequestTest(OperationShape operation, HttpRequestTestCase t
186186
writer.write("""
187187
config = $T(
188188
endpoint_uri="https://$L/$L",
189-
http_client = $T(),
189+
transport = $T(),
190190
retry_strategy=SimpleRetryStrategy(max_attempts=1),
191191
)
192192
""",
@@ -432,7 +432,7 @@ private void generateResponseTest(OperationShape operation, HttpResponseTestCase
432432
writer.write("""
433433
config = $T(
434434
endpoint_uri="https://example.com",
435-
http_client = $T(
435+
transport = $T(
436436
status=$L,
437437
headers=$J,
438438
body=b$S,
@@ -485,7 +485,7 @@ private void generateErrorResponseTest(
485485
writer.write("""
486486
config = $T(
487487
endpoint_uri="https://example.com",
488-
http_client = $T(
488+
transport = $T(
489489
status=$L,
490490
headers=$J,
491491
body=b$S,

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ public final class SmithyPythonDependency {
7373
Type.DEPENDENCY,
7474
false);
7575

76+
/**
77+
* Smithy core functionality for AWS.
78+
*/
79+
public static final PythonDependency SMITHY_AWS_CORE = new PythonDependency(
80+
"smithy_aws_core",
81+
"<0.1.0",
82+
Type.DEPENDENCY,
83+
false);
84+
7685
/**
7786
* testing framework used in generated functional tests.
7887
*/

codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/ConfigGenerator.java

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -117,38 +117,58 @@ public ConfigGenerator(PythonSettings settings, GenerationContext context) {
117117
this.settings = settings;
118118
}
119119

120-
private static List<ConfigProperty> getHttpProperties(GenerationContext context) {
121-
var properties = new ArrayList<ConfigProperty>(HTTP_PROPERTIES.size() + 2);
122-
var clientBuilder = ConfigProperty.builder()
123-
.name("http_client")
120+
private static List<ConfigProperty> getProtocolProperties(GenerationContext context) {
121+
var properties = new ArrayList<ConfigProperty>();
122+
var protocolBuilder = ConfigProperty.builder()
123+
.name("protocol")
124124
.type(Symbol.builder()
125-
.name("HTTPClient")
126-
.namespace("smithy_http.aio.interfaces", ".")
127-
.addDependency(SmithyPythonDependency.SMITHY_HTTP)
125+
.name("ClientProtocol[Any, Any]")
126+
.addReference(Symbol.builder()
127+
.name("ClientProtocol")
128+
.namespace("smithy_core.aio.interfaces", ".")
129+
.build())
130+
.build())
131+
.documentation("The protocol to serialize and deserialize requests with.")
132+
.initialize(w -> {
133+
w.write("self.protocol = protocol or ${C|}",
134+
w.consumer(writer -> context.protocolGenerator().initializeProtocol(context, writer)));
135+
});
136+
137+
var transportBuilder = ConfigProperty.builder()
138+
.name("transport")
139+
.type(Symbol.builder()
140+
.name("ClientTransport[Any, Any]")
141+
.addReference(Symbol.builder()
142+
.name("ClientTransport")
143+
.namespace("smithy_core.aio.interfaces", ".")
144+
.build())
128145
.build())
129-
.documentation("The HTTP client used to make requests.")
130-
.nullable(false);
146+
.documentation("The transport to use to send requests (e.g. an HTTP client).");
131147

132-
if (usesHttp2(context)) {
133-
clientBuilder
134-
.initialize(writer -> {
135-
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("awscrt"));
136-
writer.addImport("smithy_http.aio.crt", "AWSCRTHTTPClient");
137-
writer.write("self.http_client = http_client or AWSCRTHTTPClient()");
138-
});
148+
if (context.applicationProtocol().isHttpProtocol()) {
149+
properties.addAll(HTTP_PROPERTIES);
150+
if (usesHttp2(context)) {
151+
transportBuilder
152+
.initialize(writer -> {
153+
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("awscrt"));
154+
writer.addImport("smithy_http.aio.crt", "AWSCRTHTTPClient");
155+
writer.write("self.transport = transport or AWSCRTHTTPClient()");
156+
});
139157

140-
} else {
141-
clientBuilder
142-
.initialize(writer -> {
143-
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("aiohttp"));
144-
writer.addImport("smithy_http.aio.aiohttp", "AIOHTTPClient");
145-
writer.write("self.http_client = http_client or AIOHTTPClient()");
146-
});
158+
} else {
159+
transportBuilder
160+
.initialize(writer -> {
161+
writer.addDependency(
162+
SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("aiohttp"));
163+
writer.addImport("smithy_http.aio.aiohttp", "AIOHTTPClient");
164+
writer.write("self.transport = transport or AIOHTTPClient()");
165+
});
166+
}
147167
}
148-
properties.add(clientBuilder.build());
149168

150-
properties.addAll(HTTP_PROPERTIES);
151-
return List.copyOf(properties);
169+
properties.add(protocolBuilder.build());
170+
properties.add(transportBuilder.build());
171+
return properties;
152172
}
153173

154174
private static boolean usesHttp2(GenerationContext context) {
@@ -289,6 +309,7 @@ private void generateConfig(GenerationContext context, PythonWriter writer) {
289309
// Initialize a set of config properties with our base properties.
290310
var properties = new TreeSet<>(Comparator.comparing(ConfigProperty::name));
291311
properties.addAll(BASE_PROPERTIES);
312+
properties.addAll(getProtocolProperties(context));
292313

293314
// Add in auth configuration if the service supports auth.
294315
var serviceIndex = ServiceIndex.of(context.model());
@@ -297,13 +318,6 @@ private void generateConfig(GenerationContext context, PythonWriter writer) {
297318
writer.onSection(new AddAuthHelper());
298319
}
299320

300-
// Smithy is transport agnostic, so we don't add http-related properties by default.
301-
// Nevertheless, HTTP is the most common use case so we standardize those settings
302-
// and add them in if the protocol is going to need them.
303-
if (context.applicationProtocol().isHttpProtocol()) {
304-
properties.addAll(getHttpProperties(context));
305-
}
306-
307321
var model = context.model();
308322
var service = context.settings().service(model);
309323

codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/MemberDeserializerGenerator.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import software.amazon.smithy.model.shapes.StructureShape;
2929
import software.amazon.smithy.model.shapes.TimestampShape;
3030
import software.amazon.smithy.model.shapes.UnionShape;
31+
import software.amazon.smithy.model.traits.StreamingTrait;
3132
import software.amazon.smithy.python.codegen.GenerationContext;
3233
import software.amazon.smithy.python.codegen.SymbolProperties;
3334
import software.amazon.smithy.python.codegen.writer.PythonWriter;
@@ -100,7 +101,11 @@ private void writeSchema() {
100101

101102
@Override
102103
public Void blobShape(BlobShape shape) {
103-
writeDeserializer(shape);
104+
if (shape.hasTrait(StreamingTrait.class)) {
105+
writeDeserializer("data_stream");
106+
} else {
107+
writeDeserializer(shape);
108+
}
104109
return null;
105110
}
106111

codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/MemberSerializerGenerator.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import software.amazon.smithy.model.shapes.StructureShape;
3030
import software.amazon.smithy.model.shapes.TimestampShape;
3131
import software.amazon.smithy.model.shapes.UnionShape;
32+
import software.amazon.smithy.model.traits.StreamingTrait;
3233
import software.amazon.smithy.python.codegen.GenerationContext;
3334
import software.amazon.smithy.python.codegen.SymbolProperties;
3435
import software.amazon.smithy.python.codegen.writer.PythonWriter;
@@ -107,7 +108,11 @@ private void writeSchema() {
107108

108109
@Override
109110
public Void blobShape(BlobShape shape) {
110-
writeSerializer(shape);
111+
if (shape.hasTrait(StreamingTrait.class)) {
112+
writeSerializer("data_stream");
113+
} else {
114+
writeSerializer(shape);
115+
}
111116
return null;
112117
}
113118

0 commit comments

Comments
 (0)