Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Python] Support more testing model #2541

Merged
merged 24 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a7f86c5
Remove parameter from `Protocol`s `structuredDataParser`, `structured…
david-perez Apr 4, 2023
80bd255
Remove the TypeConversionGenerator class in favor of using
crisidev Apr 4, 2023
146ec10
Make the additionaParserCustomizations default to empty list
crisidev Apr 4, 2023
f125bc0
Merge branch 'main' into oxipy-testing-models
crisidev Apr 4, 2023
3a92f64
Fix merge conflict
crisidev Apr 4, 2023
b0fe123
Merge branch 'main' into oxipy-testing-models
crisidev Apr 5, 2023
e5d7256
Merge branch 'main' into oxipy-testing-models
crisidev Apr 5, 2023
84fe43a
Fix missing ;
crisidev Apr 5, 2023
b050d37
Use better defaults when checking for customizations
crisidev Apr 5, 2023
aada4fb
Use better defaults when checking for customizations
crisidev Apr 5, 2023
22ffc07
Add HttpBindingCustomization and relax the datetime symbol check
crisidev Apr 5, 2023
39b4907
Support recursive shapes and add a lot more models to the tests
crisidev Apr 5, 2023
38b5efd
Merge branch 'main' into oxipy-testing-models
crisidev Apr 6, 2023
bb8ba57
Support naming obstacle course
crisidev Apr 6, 2023
b35454e
Merge branch 'main' into oxipy-testing-models
crisidev Apr 6, 2023
5259205
Merge branch 'main' into oxipy-testing-models
crisidev Apr 8, 2023
0b34887
Merge branch 'main' into oxipy-testing-models
crisidev Apr 11, 2023
af419d5
Merge branch 'main' into oxipy-testing-models
crisidev Apr 11, 2023
87dbc4c
Add support for constrained blobs conversions
crisidev Apr 11, 2023
716fd59
Support constraint traits
crisidev Apr 11, 2023
70fb1c4
Merge branch 'main' into oxipy-testing-models
crisidev Apr 11, 2023
740ddb9
Try to generate the full diff
crisidev Apr 11, 2023
6f39c1a
A better way of checking if we need to go into the Timestamp branch
crisidev Apr 12, 2023
1a555d1
Remove wheels folder
crisidev Apr 12, 2023
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@ target/

# tools
.tool-versions

# python
__pycache__

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ sealed class HttpBindingSection(name: String) : Section(name) {

data class AfterDeserializingIntoAHashMapOfHttpPrefixHeaders(val memberShape: MemberShape) :
HttpBindingSection("AfterDeserializingIntoAHashMapOfHttpPrefixHeaders")

data class AfterDeserializingIntoADateTimeOfHttpHeaders(val memberShape: MemberShape) :
HttpBindingSection("AfterDeserializingIntoADateTimeOfHttpHeaders")
}

typealias HttpBindingCustomization = NamedCustomization<HttpBindingSection>
Expand Down Expand Up @@ -353,7 +356,7 @@ class HttpBindingGenerator(
rustType to targetShape
}
val parsedValue = safeName()
if (coreType == dateTime) {
if (coreShape.isTimestampShape()) {
val timestampFormat =
index.determineTimestampFormat(
memberShape,
Expand All @@ -362,10 +365,14 @@ class HttpBindingGenerator(
)
val timestampFormatType = RuntimeType.parseTimestampFormat(codegenTarget, runtimeConfig, timestampFormat)
rust(
"let $parsedValue: Vec<${coreType.render()}> = #T::many_dates(headers, #T)?;",
"let $parsedValue: Vec<${coreType.render()}> = #T::many_dates(headers, #T)?",
headerUtil,
timestampFormatType,
)
for (customization in customizations) {
customization.section(HttpBindingSection.AfterDeserializingIntoADateTimeOfHttpHeaders(memberShape))(this)
}
rust(";")
} else if (coreShape.isPrimitive()) {
rust(
"let $parsedValue = #T::read_many_primitive::<${coreType.render()}>(headers)?;",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.core.smithy.canUseDefault
import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization
import software.amazon.smithy.rust.codegen.core.smithy.customize.Section
import software.amazon.smithy.rust.codegen.core.smithy.generators.TypeConversionGenerator
import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator
import software.amazon.smithy.rust.codegen.core.smithy.generators.renderUnknownVariant
import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName
Expand All @@ -61,6 +60,12 @@ import software.amazon.smithy.utils.StringUtils
*/
sealed class JsonParserSection(name: String) : Section(name) {
data class BeforeBoxingDeserializedMember(val shape: MemberShape) : JsonParserSection("BeforeBoxingDeserializedMember")

data class AfterTimestampDeserializedMember(val shape: MemberShape) : JsonParserSection("AfterTimestampDeserializedMember")

data class AfterBlobDeserializedMember(val shape: MemberShape) : JsonParserSection("AfterBlobDeserializedMember")

data class AfterDocumentDeserializedMember(val shape: MemberShape) : JsonParserSection("AfterDocumentDeserializedMember")
}

/**
Expand Down Expand Up @@ -94,7 +99,6 @@ class JsonParserGenerator(
private val runtimeConfig = codegenContext.runtimeConfig
private val codegenTarget = codegenContext.target
private val smithyJson = CargoDependency.smithyJson(runtimeConfig).toType()
private val typeConversionGenerator = TypeConversionGenerator(model, symbolProvider, runtimeConfig)
private val protocolFunctions = ProtocolFunctions(codegenContext)
private val codegenScope = arrayOf(
"Error" to smithyJson.resolve("deserialize::error::DeserializeError"),
Expand Down Expand Up @@ -276,13 +280,13 @@ class JsonParserGenerator(
is StringShape -> deserializeString(target)
is BooleanShape -> rustTemplate("#{expect_bool_or_null}(tokens.next())?", *codegenScope)
is NumberShape -> deserializeNumber(target)
is BlobShape -> deserializeBlob()
is BlobShape -> deserializeBlob(memberShape)
is TimestampShape -> deserializeTimestamp(target, memberShape)
is CollectionShape -> deserializeCollection(target)
is MapShape -> deserializeMap(target)
is StructureShape -> deserializeStruct(target)
is UnionShape -> deserializeUnion(target)
is DocumentShape -> rustTemplate("Some(#{expect_document}(tokens)?)", *codegenScope)
is DocumentShape -> deserializeDocument(memberShape)
else -> PANIC("unexpected shape: $target")
}
val symbol = symbolProvider.toSymbol(memberShape)
Expand All @@ -294,11 +298,21 @@ class JsonParserGenerator(
}
}

private fun RustWriter.deserializeBlob() {
private fun RustWriter.deserializeDocument(member: MemberShape) {
rustTemplate("Some(#{expect_document}(tokens)?)", *codegenScope)
for (customization in customizations) {
customization.section(JsonParserSection.AfterDocumentDeserializedMember(member))(this)
}
}

private fun RustWriter.deserializeBlob(member: MemberShape) {
rustTemplate(
"#{expect_blob_or_null}(tokens.next())?",
*codegenScope,
)
for (customization in customizations) {
customization.section(JsonParserSection.AfterBlobDeserializedMember(member))(this)
}
}

private fun RustWriter.deserializeStringInner(target: StringShape, escapedStrName: String) {
Expand Down Expand Up @@ -349,9 +363,12 @@ class JsonParserGenerator(
)
val timestampFormatType = RuntimeType.parseTimestampFormat(codegenTarget, runtimeConfig, timestampFormat)
rustTemplate(
"#{expect_timestamp_or_null}(tokens.next(), #{T})?#{ConvertFrom:W}",
"T" to timestampFormatType, "ConvertFrom" to typeConversionGenerator.convertViaFrom(shape), *codegenScope,
"#{expect_timestamp_or_null}(tokens.next(), #{T})?",
"T" to timestampFormatType, *codegenScope,
)
for (customization in customizations) {
customization.section(JsonParserSection.AfterTimestampDeserializedMember(member))(this)
}
}

private fun RustWriter.deserializeCollection(shape: CollectionShape) {
Expand Down
45 changes: 40 additions & 5 deletions codegen-server-test/python/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,49 @@ val allCodegenTests = "../../codegen-core/common-test-models".let { commonModels
// TODO(https://github.com/awslabs/smithy-rs/issues/1401) `@uniqueItems` is used.
extraConfig = """, "codegen": { "ignoreUnsupportedConstraints": true } """,
),
// TODO(https://github.com/awslabs/smithy-rs/issues/2476)
CodegenTest(
"aws.protocoltests.json#JsonProtocol",
"json_rpc11",
extraConfig = """, "codegen": { "ignoreUnsupportedConstraints": true } """,
),
CodegenTest("aws.protocoltests.json10#JsonRpc10", "json_rpc10"),
CodegenTest("aws.protocoltests.restjson#RestJson", "rest_json"),
CodegenTest(
"aws.protocoltests.restjson#RestJsonExtras",
"rest_json_extras",
imports = listOf("$commonModels/rest-json-extras.smithy"),
),
// TODO(https://github.com/awslabs/smithy-rs/issues/2551)
// CodegenTest(
// "aws.protocoltests.json#JsonProtocol",
// "json_rpc11",
// "aws.protocoltests.restjson.validation#RestJsonValidation",
// "rest_json_validation",
// // `@range` trait is used on floating point shapes, which we deliberately don't want to support.
// // See https://github.com/awslabs/smithy-rs/issues/1401.
// extraConfig = """, "codegen": { "ignoreUnsupportedConstraints": true } """,
// ),
// TODO(https://github.com/awslabs/smithy-rs/issues/2479)
// CodegenTest("aws.protocoltests.json10#JsonRpc10", "json_rpc10"),
CodegenTest(
"com.amazonaws.constraints#ConstraintsService",
"constraints",
imports = listOf("$commonModels/constraints.smithy"),
),
CodegenTest(
"com.amazonaws.constraints#ConstraintsService",
"constraints_without_public_constrained_types",
imports = listOf("$commonModels/constraints.smithy"),
extraConfig = """, "codegen": { "publicConstrainedTypes": false } """,
),
CodegenTest(
"com.amazonaws.constraints#UniqueItemsService",
"unique_items",
imports = listOf("$commonModels/unique-items.smithy"),
),
CodegenTest(
"naming_obs_structs#NamingObstacleCourseStructs",
"naming_test_structs",
imports = listOf("$commonModels/naming-obstacle-course-structs.smithy"),
),
CodegenTest("casing#ACRONYMInside_Service", "naming_test_casing", imports = listOf("$commonModels/naming-obstacle-course-casing.smithy")),
CodegenTest("crate#Config", "naming_test_ops", imports = listOf("$commonModels/naming-obstacle-course-ops.smithy")),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.server.python.smithy
import software.amazon.smithy.build.PluginContext
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.knowledge.NullableIndex
import software.amazon.smithy.model.shapes.BlobShape
import software.amazon.smithy.model.shapes.MemberShape
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.model.shapes.ServiceShape
Expand All @@ -22,6 +23,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProviderConfig
import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ErrorImplGenerator
import software.amazon.smithy.rust.codegen.core.util.getTrait
import software.amazon.smithy.rust.codegen.core.util.isEventStream
import software.amazon.smithy.rust.codegen.server.python.smithy.generators.ConstrainedPythonBlobGenerator
import software.amazon.smithy.rust.codegen.server.python.smithy.generators.PythonApplicationGenerator
import software.amazon.smithy.rust.codegen.server.python.smithy.generators.PythonServerEnumGenerator
import software.amazon.smithy.rust.codegen.server.python.smithy.generators.PythonServerEventStreamErrorGenerator
Expand All @@ -30,6 +32,7 @@ import software.amazon.smithy.rust.codegen.server.python.smithy.generators.Pytho
import software.amazon.smithy.rust.codegen.server.python.smithy.generators.PythonServerOperationHandlerGenerator
import software.amazon.smithy.rust.codegen.server.python.smithy.generators.PythonServerStructureGenerator
import software.amazon.smithy.rust.codegen.server.python.smithy.generators.PythonServerUnionGenerator
import software.amazon.smithy.rust.codegen.server.python.smithy.protocols.PythonServerProtocolLoader
import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext
import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenVisitor
import software.amazon.smithy.rust.codegen.server.smithy.ServerModuleDocProvider
Expand All @@ -42,8 +45,9 @@ import software.amazon.smithy.rust.codegen.server.smithy.createInlineModuleCreat
import software.amazon.smithy.rust.codegen.server.smithy.customize.ServerCodegenDecorator
import software.amazon.smithy.rust.codegen.server.smithy.generators.UnconstrainedUnionGenerator
import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.ServerProtocol
import software.amazon.smithy.rust.codegen.server.smithy.protocols.ServerProtocolLoader
import software.amazon.smithy.rust.codegen.server.smithy.isDirectlyConstrained
import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput
import software.amazon.smithy.rust.codegen.server.smithy.withModuleOrWithStructureBuilderModule

/**
* Entrypoint for Python server-side code generation. This class will walk the in-memory model and
Expand All @@ -68,10 +72,10 @@ class PythonServerCodegenVisitor(
val baseModel = baselineTransform(context.model)
val service = settings.getService(baseModel)
val (protocol, generator) =
ServerProtocolLoader(
PythonServerProtocolLoader(
codegenDecorator.protocols(
service.id,
ServerProtocolLoader.DefaultProtocols,
PythonServerProtocolLoader.defaultProtocols(settings.runtimeConfig),
),
)
.protocolFor(context.model, service)
Expand Down Expand Up @@ -258,4 +262,21 @@ class PythonServerCodegenVisitor(
}
}
}

override fun blobShape(shape: BlobShape) {
logger.info("[python-server-codegen] Generating a service $shape")
super.blobShape(shape)

if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) {
rustCrate.withModuleOrWithStructureBuilderModule(ServerRustModule.Model, shape, codegenContext) {
ConstrainedPythonBlobGenerator(
codegenContext,
rustCrate.createInlineModuleCreator(),
this,
shape,
validationExceptionConversionGenerator,
).render()
}
}
}
}
Loading