Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import static software.amazon.smithy.python.aws.codegen.AwsConfiguration.REGION;

import java.util.List;
import java.util.Set;
import software.amazon.smithy.aws.traits.auth.SigV4Trait;
import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.model.shapes.ServiceShape;
Expand All @@ -16,6 +15,7 @@
import software.amazon.smithy.python.codegen.CodegenUtils;
import software.amazon.smithy.python.codegen.ConfigProperty;
import software.amazon.smithy.python.codegen.GenerationContext;
import software.amazon.smithy.python.codegen.RuntimeTypes;
import software.amazon.smithy.python.codegen.SmithyPythonDependency;
import software.amazon.smithy.python.codegen.integrations.AuthScheme;
import software.amazon.smithy.python.codegen.integrations.PythonIntegration;
Expand Down Expand Up @@ -98,20 +98,21 @@ public void customize(GenerationContext context) {
// must be accounted for.
context.writerDelegator().useFileWriter(resolver.getDefinitionFile(), resolver.getNamespace(), writer -> {
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP);
writer.addImport("smithy_core.interfaces.auth", "AuthOption", "AuthOptionProtocol");
writer.addImports("smithy_core.auth", Set.of("AuthOption", "AuthParams"));
writer.addImport("smithy_core.shapes", "ShapeID");
writer.pushState();

writer.write("""
def $1L(auth_params: AuthParams[Any, Any]) -> AuthOptionProtocol | None:
return AuthOption(
scheme_id=ShapeID($2S),
def $1L(auth_params: $2T[Any, Any]) -> $3T | None:
return $4T(
scheme_id=$5T($6S),
identity_properties={}, # type: ignore
signer_properties={} # type: ignore
)
""",
SIGV4_OPTION_GENERATOR_NAME,
RuntimeTypes.AUTH_PARAMS,
RuntimeTypes.AUTH_OPTION_INTERFACE,
RuntimeTypes.AUTH_OPTION,
RuntimeTypes.SHAPE_ID,
SigV4Trait.ID.toString());
writer.popState();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@ public ApplicationProtocol getApplicationProtocol(GenerationContext context) {
@Override
public void initializeProtocol(GenerationContext context, PythonWriter writer) {
writer.addDependency(AwsPythonDependency.SMITHY_AWS_CORE.withOptionalDependencies("xml"));
writer.addImport("smithy_aws_core.aio.protocols", "AwsQueryClientProtocol");
var service = context.settings().service(context.model());
var serviceSymbol = context.symbolProvider().toSymbol(service);
var serviceSchema = serviceSymbol.expectProperty(SymbolProperties.SCHEMA);
var version = service.getVersion();
writer.write("AwsQueryClientProtocol($T, $S)", serviceSchema, version);
writer.write("$1T($2T, $3S)", AwsRuntimeTypes.AWS_QUERY_CLIENT_PROTOCOL, serviceSchema, version);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package software.amazon.smithy.python.aws.codegen;

import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.utils.SmithyUnstableApi;

/**
* Pre-defined Symbol constants for AWS-specific framework types used across generators.
*
* <p>Using these symbols with the {@code $T} formatter ensures that all framework type
* references participate in the writer's collision detection system.
*/
@SmithyUnstableApi
public final class AwsRuntimeTypes {

// smithy_aws_core.aio.protocols
public static final Symbol REST_JSON_CLIENT_PROTOCOL = createSymbol(
"aio.protocols",
"RestJsonClientProtocol");
public static final Symbol AWS_QUERY_CLIENT_PROTOCOL = createSymbol(
"aio.protocols",
"AwsQueryClientProtocol");

// smithy_aws_core.identity
public static final Symbol STATIC_CREDENTIALS_RESOLVER = createSymbol(
"identity",
"StaticCredentialsResolver");

// smithy_aws_core.endpoints.standard_regional
public static final Symbol STANDARD_REGIONAL_ENDPOINTS_RESOLVER = createSymbol(
"endpoints.standard_regional",
"StandardRegionalEndpointsResolver");

private AwsRuntimeTypes() {}

private static Symbol createSymbol(String module, String name) {
var namespace = module.isEmpty() ? "smithy_aws_core" : "smithy_aws_core." + module;
return Symbol.builder()
.name(name)
.namespace(namespace, ".")
.addDependency(AwsPythonDependency.SMITHY_AWS_CORE)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,9 @@ public void write(PythonWriter writer, String previousText, InitDefaultEndpointR
.map(ServiceTrait::getEndpointPrefix)
.orElse(context.settings().service().getName());

writer.addImport("smithy_aws_core.endpoints.standard_regional",
"StandardRegionalEndpointsResolver",
"_RegionalResolver");
writer.write(
"self.endpoint_resolver = endpoint_resolver or _RegionalResolver(endpoint_prefix=$S)",
"self.endpoint_resolver = endpoint_resolver or $1T(endpoint_prefix=$2S)",
AwsRuntimeTypes.STANDARD_REGIONAL_ENDPOINTS_RESOLVER,
endpointPrefix);

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public void run() {

private void generateService(PythonWriter writer) {
var serviceSymbol = symbolProvider.toSymbol(service);
writer.addLocallyDefinedSymbol(serviceSymbol);
var configSymbol = CodegenUtils.getConfigSymbol(context.settings());
var pluginSymbol = CodegenUtils.getPluginSymbol(context.settings());
writer.addLogger();
Expand All @@ -71,7 +72,6 @@ private void generateService(PythonWriter writer) {
}

writer.addDependency(SmithyPythonDependency.SMITHY_CORE);
writer.addImport("smithy_core.retries", "RetryStrategyResolver");
writer.write("""
def __init__(self, config: $1T | None = None, plugins: list[$2T] | None = None):
$3C
Expand All @@ -86,12 +86,13 @@ def __init__(self, config: $1T | None = None, plugins: list[$2T] | None = None):
for plugin in client_plugins:
plugin(self._config)

self._retry_strategy_resolver = RetryStrategyResolver()
self._retry_strategy_resolver = $5T()
""",
configSymbol,
pluginSymbol,
writer.consumer(w -> writeConstructorDocs(w, serviceSymbol.getName())),
writer.consumer(w -> writeDefaultPlugins(w, defaultPlugins)));
writer.consumer(w -> writeDefaultPlugins(w, defaultPlugins)),
RuntimeTypes.RETRY_STRATEGY_RESOLVER);

var topDownIndex = TopDownIndex.of(model);
var eventStreamIndex = EventStreamIndex.of(model);
Expand Down Expand Up @@ -209,46 +210,45 @@ private void writeSharedOperationInit(
}

writer.putContext("operation", symbolProvider.toSymbol(operation));
writer.addImport("smithy_core.aio.client", "ClientCall");
writer.addImport("smithy_core.interceptors", "InterceptorChain");
writer.addImport("smithy_core.types", "TypedProperties");
writer.addImport("smithy_core.aio.client", "RequestPipeline");
writer.addImport("smithy_core.exceptions", "ExpectationNotMetError");
writer.addImport("smithy_core.retries", "RetryStrategyOptions");
writer.addImport("smithy_core.interfaces.retries", "RetryStrategy");
writer.addStdlibImport("copy", "deepcopy");

writer.write("""
operation_plugins: list[Plugin] = [
$C
$1C
]
if plugins:
operation_plugins.extend(plugins)
config = deepcopy(self._config)
for plugin in operation_plugins:
plugin(config)
if config.protocol is None or config.transport is None:
raise ExpectationNotMetError("protocol and transport MUST be set on the config to make calls.")
raise $2T("protocol and transport MUST be set on the config to make calls.")

retry_strategy = await self._retry_strategy_resolver.resolve_retry_strategy(
retry_strategy=config.retry_strategy
)

pipeline = RequestPipeline(
pipeline = $3T(
protocol=config.protocol,
transport=config.transport
)
call = ClientCall(
call = $4T(
input=input,
operation=${operation:T},
context=TypedProperties({"config": config}),
interceptor=InterceptorChain(config.interceptors),
context=$5T({"config": config}),
interceptor=$6T(config.interceptors),
auth_scheme_resolver=config.auth_scheme_resolver,
supported_auth_schemes=config.auth_schemes,
endpoint_resolver=config.endpoint_resolver,
retry_strategy=retry_strategy,
)
""", writer.consumer(w -> writeDefaultPlugins(w, defaultPlugins)));
""",
writer.consumer(w -> writeDefaultPlugins(w, defaultPlugins)),
RuntimeTypes.EXPECTATION_NOT_MET_ERROR,
RuntimeTypes.REQUEST_PIPELINE,
RuntimeTypes.CLIENT_CALL,
RuntimeTypes.TYPED_PROPERTIES,
RuntimeTypes.INTERCEPTOR_CHAIN);

}

Expand Down Expand Up @@ -291,14 +291,14 @@ private void generateEventStreamOperation(PythonWriter writer, OperationShape op
// the type declaration so much that it's no better than Any.
if (inputStreamSymbol.isPresent()) {
if (outputStreamSymbol.isPresent()) {
writer.addImport("smithy_core.aio.eventstream", "DuplexEventStream");
writer.putContext("duplexEventStream", RuntimeTypes.DUPLEX_EVENT_STREAM);
var outputDocs = "A `DuplexEventStream` for bidirectional streaming.";
writer.write("""
async def ${operationName:L}(
self,
input: ${input:T},
plugins: list[${plugin:T}] | None = None
) -> DuplexEventStream[${inputStream:T}, ${outputStream:T}, ${output:T}]:
) -> ${duplexEventStream:T}[${inputStream:T}, ${outputStream:T}, ${output:T}]:
${C|}
return await pipeline.duplex_stream(
call,
Expand All @@ -309,14 +309,14 @@ private void generateEventStreamOperation(PythonWriter writer, OperationShape op
""",
writer.consumer(w -> writeSharedOperationInit(w, operation, input, output, outputDocs)));
} else {
writer.addImport("smithy_core.aio.eventstream", "InputEventStream");
writer.putContext("inputEventStream", RuntimeTypes.INPUT_EVENT_STREAM);
var outputDocs = "An `InputEventStream` for client-to-server streaming.";
writer.write("""
async def ${operationName:L}(
self,
input: ${input:T},
plugins: list[${plugin:T}] | None = None
) -> InputEventStream[${inputStream:T}, ${output:T}]:
) -> ${inputEventStream:T}[${inputStream:T}, ${output:T}]:
${C|}
return await pipeline.input_stream(
call,
Expand All @@ -326,14 +326,14 @@ private void generateEventStreamOperation(PythonWriter writer, OperationShape op
writer.consumer(w -> writeSharedOperationInit(w, operation, input, output, outputDocs)));
}
} else {
writer.addImport("smithy_core.aio.eventstream", "OutputEventStream");
writer.putContext("outputEventStream", RuntimeTypes.OUTPUT_EVENT_STREAM);
var outputDocs = "An `OutputEventStream` for server-to-client streaming.";
writer.write("""
async def ${operationName:L}(
self,
input: ${input:T},
plugins: list[${plugin:T}] | None = None
) -> OutputEventStream[${outputStream:T}, ${output:T}]:
) -> ${outputEventStream:T}[${outputStream:T}, ${output:T}]:
${C|}
return await pipeline.output_stream(
call,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,22 @@ private void generateAuthSchemeResolver(
.toList();

writer.pushState(new GenerateHttpAuthSchemeResolverSection(resolvedAuthSchemes));
writer.addLocallyDefinedSymbol(resolverSymbol);
writer.addDependency(SmithyPythonDependency.SMITHY_CORE);
writer.addDependency(SmithyPythonDependency.SMITHY_HTTP);
writer.addImport("smithy_core.interfaces.auth", "AuthOption", "AuthOptionProtocol");
writer.addImport("smithy_core.auth", "AuthParams");
writer.addStdlibImport("typing", "Any");
writer.write("""
class $1L:
def resolve_auth_scheme(self, auth_parameters: AuthParams[Any, Any]) -> list[AuthOptionProtocol]:
auth_options: list[AuthOptionProtocol] = []
def resolve_auth_scheme(self, auth_parameters: $2T[Any, Any]) -> list[$3T]:
auth_options: list[$3T] = []

${2C|}
${3C|}
${4C|}
${5C|}

""",
resolverSymbol.getName(),
RuntimeTypes.AUTH_PARAMS,
RuntimeTypes.AUTH_OPTION_INTERFACE,
writer.consumer(w -> writeOperationAuthOptions(w, supportedAuthSchemes)),
writer.consumer(w -> writeAuthOptions(w, resolvedAuthSchemes)));
writer.popState();
Expand Down
Loading
Loading