Skip to content

Commit c8d7355

Browse files
committed
Client cutover
1 parent 527b874 commit c8d7355

11 files changed

Lines changed: 45 additions & 150 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
## Unreleased
44

5+
## v0.5.0
6+
7+
### Breaking Changes
8+
9+
* Removed the deprecated unprefixed aliases for generated AWS service clients.
10+
Imports such as `BedrockRuntimeClient` must now use the `Async`-prefixed name,
11+
such as `AsyncBedrockRuntimeClient`.
12+
* Changed all generated AWS clients to use `AIOHTTPClient` as their default
13+
transport, including services configured for HTTP/2 or event streaming.
14+
Applications that require the CRT transport, such as those using
15+
bidirectional event streams, must install the generated client's `awscrt`
16+
extra and explicitly configure `AWSCRTHTTPClient`.
17+
* Removed the legacy `Config` class from generated AWS clients in favor of the
18+
service-specific, async-resolved `Async<SdkId>Config` class, such as
19+
`AsyncBedrockRuntimeConfig`. Explicit configuration must now be resolved with
20+
`await Async<SdkId>Config.resolve(...)` before it is passed to the client.
21+
522
## v0.4.0
623

724
### Breaking Changes

‎codegen/aws/core/src/it/java/software/amazon/smithy/python/codegen/test/AwsCodegenTest.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public void testCodegen(@TempDir Path tempDir) throws IOException {
5454
assertTrue(config.contains("auth_schemes = dict(self.auth_schemes or {})"));
5555
assertTrue(config.contains("auth_schemes[scheme.scheme_id] = scheme"));
5656
assertTrue(config.contains("self.auth_schemes = auth_schemes"));
57+
assertTrue(config.contains("default_factory=lambda: AIOHTTPClient()"));
58+
assertFalse(config.contains("from smithy_http.aio.crt import AWSCRTHTTPClient"));
5759

5860
var client = Files.readString(tempDir.resolve("src/restjson/client.py"));
5961
assertInOrder(

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

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,10 @@
66

77
import java.util.LinkedHashMap;
88
import java.util.List;
9-
import java.util.Locale;
109
import java.util.Set;
1110
import software.amazon.smithy.aws.traits.ServiceTrait;
1211
import software.amazon.smithy.codegen.core.Symbol;
13-
import software.amazon.smithy.model.knowledge.EventStreamIndex;
1412
import software.amazon.smithy.model.knowledge.ServiceIndex;
15-
import software.amazon.smithy.model.knowledge.TopDownIndex;
16-
import software.amazon.smithy.model.node.ArrayNode;
17-
import software.amazon.smithy.model.node.StringNode;
18-
import software.amazon.smithy.model.shapes.OperationShape;
1913
import software.amazon.smithy.python.codegen.CodegenUtils;
2014
import software.amazon.smithy.python.codegen.ConfigProperty;
2115
import software.amazon.smithy.python.codegen.GenerationContext;
@@ -295,13 +289,8 @@ public void write(PythonWriter writer, String previousText, AsyncConfigSection s
295289
// transport FieldSpec
296290
writer.write("\"transport\": $T(", fieldSpecSymbol);
297291
writer.indent();
298-
if (usesHttp2(context)) {
299-
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("awscrt"));
300-
writer.write("default_factory=lambda: $T(),", RuntimeTypes.AWS_CRT_HTTP_CLIENT);
301-
} else {
302-
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("aiohttp"));
303-
writer.write("default_factory=lambda: $T(),", RuntimeTypes.AIOHTTP_CLIENT);
304-
}
292+
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("aiohttp"));
293+
writer.write("default_factory=lambda: $T(),", RuntimeTypes.AIOHTTP_CLIENT);
305294
writer.dedent();
306295
writer.write("),");
307296

@@ -367,29 +356,5 @@ private static void writeAsyncDefaultAuthSchemes(GenerationContext context, Pyth
367356
writer.closeBlock("}");
368357
}
369358

370-
private static boolean usesHttp2(GenerationContext context) {
371-
var configuration = context.applicationProtocol().configuration();
372-
var httpVersions = configuration.getArrayMember("http")
373-
.orElse(ArrayNode.arrayNode())
374-
.getElementsAs(StringNode.class)
375-
.stream()
376-
.map(node -> node.getValue().toLowerCase(Locale.ENGLISH))
377-
.toList();
378-
379-
if (httpVersions.contains("h2")) {
380-
return true;
381-
}
382-
383-
var eventIndex = EventStreamIndex.of(context.model());
384-
var topDownIndex = TopDownIndex.of(context.model());
385-
for (OperationShape operation : topDownIndex.getContainedOperations(context.settings().service())) {
386-
if (eventIndex.getInputInfo(operation).isPresent()
387-
|| eventIndex.getOutputInfo(operation).isPresent()) {
388-
return true;
389-
}
390-
}
391-
392-
return false;
393-
}
394359
}
395360
}

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

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,18 @@
44
*/
55
package software.amazon.smithy.python.aws.codegen;
66

7-
import java.util.Set;
87
import software.amazon.smithy.aws.traits.ServiceTrait;
98
import software.amazon.smithy.codegen.core.Symbol;
109
import software.amazon.smithy.codegen.core.SymbolProvider;
1110
import software.amazon.smithy.model.Model;
1211
import software.amazon.smithy.model.shapes.MemberShape;
1312
import software.amazon.smithy.model.shapes.Shape;
1413
import software.amazon.smithy.python.codegen.PythonSettings;
15-
import software.amazon.smithy.python.codegen.SymbolProperties;
1614
import software.amazon.smithy.python.codegen.integrations.PythonIntegration;
1715
import software.amazon.smithy.utils.StringUtils;
1816

1917
public final class AwsServiceIdIntegration implements PythonIntegration {
2018

21-
/**
22-
* SDK IDs of the AWS clients that were published under the unprefixed
23-
* {@code <SdkId>Client} name before the {@code Async} prefix was adopted.
24-
*
25-
* <p>Only these clients generate a deprecated alias for the old name so that
26-
* existing imports keep working. New clients are generated with the
27-
* {@code Async}-prefixed name from the start and need no alias. This set can
28-
* be removed once the aliases are dropped.
29-
*/
30-
private static final Set<String> LEGACY_ALIAS_SDK_IDS = Set.of(
31-
"Bedrock Runtime",
32-
"ConnectHealth",
33-
"Lex Runtime V2",
34-
"Polly",
35-
"QBusiness",
36-
"SageMaker Runtime HTTP2",
37-
"Transcribe Streaming");
38-
3919
@Override
4020
public SymbolProvider decorateSymbolProvider(Model model, PythonSettings settings, SymbolProvider symbolProvider) {
4121
return new ServiceIdSymbolProvider(symbolProvider);
@@ -55,13 +35,7 @@ public Symbol toSymbol(Shape shape) {
5535
if (shape.isServiceShape() && shape.hasTrait(ServiceTrait.class)) {
5636
var serviceTrait = shape.expectTrait(ServiceTrait.class);
5737
var baseClientName = StringUtils.capitalize(serviceTrait.getSdkId() + "Client").replace(" ", "");
58-
var symbolBuilder = symbol.toBuilder().name("Async" + baseClientName);
59-
// Only clients that already shipped under the unprefixed name get a
60-
// backwards-compatible alias; new clients start life Async-prefixed.
61-
if (LEGACY_ALIAS_SDK_IDS.contains(serviceTrait.getSdkId())) {
62-
symbolBuilder.putProperty(SymbolProperties.DEPRECATED_ALIAS, baseClientName);
63-
}
64-
symbol = symbolBuilder.build();
38+
symbol = symbol.toBuilder().name("Async" + baseClientName).build();
6539
}
6640
return symbol;
6741
}

‎codegen/aws/core/src/test/java/software/amazon/smithy/python/aws/codegen/AwsServiceIdIntegrationTest.java‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,29 @@
1313
import software.amazon.smithy.model.shapes.ShapeId;
1414
import software.amazon.smithy.python.codegen.PythonSettings;
1515
import software.amazon.smithy.python.codegen.PythonSymbolProvider;
16-
import software.amazon.smithy.python.codegen.SymbolProperties;
1716

1817
public class AwsServiceIdIntegrationTest {
1918

2019
private static final String NS = "smithy.example";
2120

2221
@Test
23-
public void testLegacyClientGetsAsyncNameWithDeprecatedAlias() {
22+
public void testFormerlyAliasedClientGetsAsyncNameWithoutAlias() {
23+
// "Bedrock Runtime" shipped under the unprefixed name and used to carry a
24+
// deprecated alias; it must now be Async-prefixed with no alias residue.
2425
var symbol = toServiceSymbol("Bedrock Runtime");
2526

2627
assertEquals("AsyncBedrockRuntimeClient", symbol.getName());
27-
assertEquals("BedrockRuntimeClient", symbol.expectProperty(SymbolProperties.DEPRECATED_ALIAS));
28+
assertFalse(symbol.getTypedProperties().containsValue("BedrockRuntimeClient"));
2829
}
2930

3031
@Test
31-
public void testNewClientGetsAsyncNameWithoutDeprecatedAlias() {
32+
public void testNeverAliasedClientGetsAsyncNameWithoutAlias() {
33+
// "Weather" never shipped an unprefixed name; it must be Async-prefixed and,
34+
// like every other client, carry no alias.
3235
var symbol = toServiceSymbol("Weather");
3336

3437
assertEquals("AsyncWeatherClient", symbol.getName());
35-
assertFalse(symbol.getProperty(SymbolProperties.DEPRECATED_ALIAS).isPresent());
38+
assertFalse(symbol.getTypedProperties().containsValue("WeatherClient"));
3639
}
3740

3841
private static Symbol toServiceSymbol(String sdkId) {

‎codegen/build.gradle.kts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515

1616
allprojects {
1717
group = "software.amazon.smithy.python"
18-
version = "0.4.0"
18+
version = "0.5.0"
1919
}

‎codegen/core/src/it/java/software/amazon/smithy/python/codegen/test/PythonCodegenTest.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,9 @@ public void testCodegen(@TempDir Path tempDir) throws IOException {
4949
assertFalse(client.contains("max_attempts="));
5050
assertTrue(client.contains("async def close(self) -> None:"));
5151
assertTrue(client.contains("if self._closed:"));
52+
53+
var config = Files.readString(tempDir.resolve("src/weather/config.py"));
54+
assertTrue(config.contains("self.transport = transport or AIOHTTPClient()"));
55+
assertFalse(config.contains("self.transport = transport or AWSCRTHTTPClient()"));
5256
}
5357
}

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

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -177,29 +177,6 @@ async def __aexit__(
177177
}
178178
});
179179

180-
serviceSymbol.getProperty(SymbolProperties.DEPRECATED_ALIAS).ifPresent(alias -> {
181-
writer.addStdlibImport("typing", "TYPE_CHECKING");
182-
writer.addStdlibImport("typing", "Any");
183-
writer.addStdlibImport("warnings");
184-
writer.write("""
185-
186-
if TYPE_CHECKING:
187-
# Deprecated alias for backwards compatibility, to be removed.
188-
$1L = $2L
189-
190-
191-
def __getattr__(name: str) -> Any:
192-
if name == $1S:
193-
warnings.warn(
194-
"$1L is deprecated, use $2L instead. "
195-
"This alias will be removed in a future version.",
196-
DeprecationWarning,
197-
stacklevel=2,
198-
)
199-
return $2L
200-
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
201-
""", alias, serviceSymbol.getName());
202-
});
203180
}
204181

205182
private void writeDefaultPlugins(PythonWriter writer, Collection<SymbolReference> plugins) {

‎codegen/core/src/main/java/software/amazon/smithy/python/codegen/SymbolProperties.java‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,5 @@ public final class SymbolProperties {
7777
*/
7878
public static final Property<Boolean> IMPORTABLE = Property.named("nonImportable");
7979

80-
/**
81-
* Contains a deprecated name for the symbol that is generated as an alias
82-
* for backwards compatibility. This is only used for services.
83-
*/
84-
public static final Property<String> DEPRECATED_ALIAS = Property.named("deprecatedAlias");
85-
8680
private SymbolProperties() {}
8781
}

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

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,11 @@
88
import java.util.Collection;
99
import java.util.Comparator;
1010
import java.util.List;
11-
import java.util.Locale;
1211
import java.util.TreeSet;
1312
import software.amazon.smithy.aws.traits.ServiceTrait;
1413
import software.amazon.smithy.codegen.core.Symbol;
15-
import software.amazon.smithy.model.knowledge.EventStreamIndex;
1614
import software.amazon.smithy.model.knowledge.ServiceIndex;
1715
import software.amazon.smithy.model.knowledge.TopDownIndex;
18-
import software.amazon.smithy.model.node.ArrayNode;
19-
import software.amazon.smithy.model.node.StringNode;
20-
import software.amazon.smithy.model.shapes.OperationShape;
2116
import software.amazon.smithy.python.codegen.CodegenUtils;
2217
import software.amazon.smithy.python.codegen.ConfigProperty;
2318
import software.amazon.smithy.python.codegen.GenerationContext;
@@ -154,57 +149,20 @@ private static List<ConfigProperty> getProtocolProperties(GenerationContext cont
154149

155150
if (context.applicationProtocol().isHttpProtocol()) {
156151
properties.addAll(HTTP_PROPERTIES);
157-
if (usesHttp2(context)) {
158-
transportBuilder
159-
.initialize(writer -> {
160-
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("awscrt"));
161-
writer.write("self.transport = transport or $T()",
162-
RuntimeTypes.AWS_CRT_HTTP_CLIENT);
163-
});
164-
165-
} else {
166-
transportBuilder
167-
.initialize(writer -> {
168-
writer.addDependency(
169-
SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("aiohttp"));
170-
writer.write("self.transport = transport or $T()",
171-
RuntimeTypes.AIOHTTP_CLIENT);
172-
});
173-
}
152+
transportBuilder
153+
.initialize(writer -> {
154+
writer.addDependency(
155+
SmithyPythonDependency.SMITHY_HTTP.withOptionalDependencies("aiohttp"));
156+
writer.write("self.transport = transport or $T()",
157+
RuntimeTypes.AIOHTTP_CLIENT);
158+
});
174159
}
175160

176161
properties.add(protocolBuilder.build());
177162
properties.add(transportBuilder.build());
178163
return properties;
179164
}
180165

181-
private static boolean usesHttp2(GenerationContext context) {
182-
var configuration = context.applicationProtocol().configuration();
183-
var httpVersions = configuration.getArrayMember("http")
184-
.orElse(ArrayNode.arrayNode())
185-
.getElementsAs(StringNode.class)
186-
.stream()
187-
.map(node -> node.getValue().toLowerCase(Locale.ENGLISH))
188-
.toList();
189-
190-
// An explicit http2 configuration
191-
if (httpVersions.contains("h2")) {
192-
return true;
193-
}
194-
195-
// enable CRT/http2 client if the service supports any event streams (single or bi-directional)
196-
// TODO: Long term, only bi-directional evenstreams strictly require h2
197-
var eventIndex = EventStreamIndex.of(context.model());
198-
var topDownIndex = TopDownIndex.of(context.model());
199-
for (OperationShape operation : topDownIndex.getContainedOperations(context.settings().service())) {
200-
if (eventIndex.getInputInfo(operation).isPresent() || eventIndex.getOutputInfo(operation).isPresent()) {
201-
return true;
202-
}
203-
}
204-
205-
return false;
206-
}
207-
208166
private static List<ConfigProperty> getAuthProperties(GenerationContext context) {
209167
return List.of(
210168
ConfigProperty.builder()

0 commit comments

Comments
 (0)