Unverified Commit 861d1d89 authored by Burak's avatar Burak Committed by GitHub
Browse files

Python: Support `document` type (#2188)

* Add Python wrapper for `aws_smithy_types::Document`

* Remove unused type

* Make sure Python SSDKs uses Python specific `Document` type

* Allow Python specific `Document` type to be used in serialization and deserialization

* Make `pyo3/extension-module` a default feature

* Add `PythonServerTypesTest`

* Fix linting issues
parent efd1508e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig
 * For a dependency that is used in the client, or in both the client and the server, use [CargoDependency] directly.
 */
object PythonServerCargoDependency {
    val PyO3: CargoDependency = CargoDependency("pyo3", CratesIo("0.17"), features = setOf("extension-module"))
    val PyO3: CargoDependency = CargoDependency("pyo3", CratesIo("0.17"))
    val PyO3Asyncio: CargoDependency = CargoDependency("pyo3-asyncio", CratesIo("0.17"), features = setOf("attributes", "tokio-runtime"))
    val Tokio: CargoDependency = CargoDependency("tokio", CratesIo("1.20.1"), features = setOf("full"))
    val Tracing: CargoDependency = CargoDependency("tracing", CratesIo("0.1"))
+3 −0
Original line number Diff line number Diff line
@@ -22,4 +22,7 @@ object PythonServerRuntimeType {

    fun dateTime(runtimeConfig: RuntimeConfig) =
        PythonServerCargoDependency.smithyHttpServerPython(runtimeConfig).toType().resolve("types::DateTime")

    fun document(runtimeConfig: RuntimeConfig) =
        PythonServerCargoDependency.smithyHttpServerPython(runtimeConfig).toType().resolve("types::Document")
}
+5 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.server.python.smithy
import software.amazon.smithy.codegen.core.Symbol
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.BlobShape
import software.amazon.smithy.model.shapes.DocumentShape
import software.amazon.smithy.model.shapes.ListShape
import software.amazon.smithy.model.shapes.MapShape
import software.amazon.smithy.model.shapes.MemberShape
@@ -80,6 +81,10 @@ class PythonServerSymbolVisitor(
    override fun blobShape(shape: BlobShape?): Symbol {
        return PythonServerRuntimeType.blob(runtimeConfig).toSymbol()
    }

    override fun documentShape(shape: DocumentShape?): Symbol {
        return PythonServerRuntimeType.document(runtimeConfig).toSymbol()
    }
}

/**
+22 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
package software.amazon.smithy.rust.codegen.server.python.smithy.customizations

import com.moandjiezana.toml.TomlWriter
import software.amazon.smithy.rust.codegen.core.rustlang.Feature
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
import software.amazon.smithy.rust.codegen.core.rustlang.docs
import software.amazon.smithy.rust.codegen.core.rustlang.rust
@@ -57,6 +58,7 @@ class PubUsePythonTypes(private val codegenContext: ServerCodegenContext) : LibR
                rustBlock("pub mod python_types") {
                    rust("pub use #T;", PythonServerRuntimeType.blob(codegenContext.runtimeConfig).toSymbol())
                    rust("pub use #T;", PythonServerRuntimeType.dateTime(codegenContext.runtimeConfig).toSymbol())
                    rust("pub use #T;", PythonServerRuntimeType.document(codegenContext.runtimeConfig).toSymbol())
                }
            }
            else -> emptySection
@@ -114,6 +116,24 @@ class PyProjectTomlDecorator : ServerCodegenDecorator {
    }
}

/**
 * Adds `pyo3/extension-module` feature to default features.
 *
 * To be able to run `cargo test` with PyO3 we need two things:
 *  - Make `pyo3/extension-module` optional and default
 *  - Run tests with `cargo test --no-default-features`
 * See: https://pyo3.rs/main/faq#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror
 */
class PyO3ExtensionModuleDecorator : ServerCodegenDecorator {
    override val name: String = "PyO3ExtensionModuleDecorator"
    override val order: Byte = 0

    override fun extras(codegenContext: ServerCodegenContext, rustCrate: RustCrate) {
        // Add `pyo3/extension-module` to default features.
        rustCrate.mergeFeature(Feature("extension-module", true, listOf("pyo3/extension-module")))
    }
}

val DECORATORS = listOf(
    /**
     * Add the [InternalServerError] error to all operations.
@@ -128,4 +148,6 @@ val DECORATORS = listOf(
    PythonExportModuleDecorator(),
    // Generate `pyproject.toml` for the crate.
    PyProjectTomlDecorator(),
    // Add PyO3 extension module feature.
    PyO3ExtensionModuleDecorator(),
)
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

package software.amazon.smithy.rust.codegen.server.python.smithy.testutil

import software.amazon.smithy.build.PluginContext
import software.amazon.smithy.model.Model
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeCrateLocation
import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext
import software.amazon.smithy.rust.codegen.core.util.runCommand
import software.amazon.smithy.rust.codegen.server.python.smithy.PythonServerCodegenVisitor
import software.amazon.smithy.rust.codegen.server.python.smithy.customizations.DECORATORS
import software.amazon.smithy.rust.codegen.server.smithy.customizations.ServerRequiredCustomizations
import software.amazon.smithy.rust.codegen.server.smithy.customize.CombinedServerCodegenDecorator
import java.io.File
import java.nio.file.Path

val TestRuntimeConfig =
    RuntimeConfig(runtimeCrateLocation = RuntimeCrateLocation.Path(File("../../rust-runtime").absolutePath))

fun generatePythonServerPluginContext(model: Model) =
    generatePluginContext(model, runtimeConfig = TestRuntimeConfig)

fun executePythonServerCodegenVisitor(pluginCtx: PluginContext) {
    val codegenDecorator: CombinedServerCodegenDecorator =
        CombinedServerCodegenDecorator.fromClasspath(
            pluginCtx,
            CombinedServerCodegenDecorator(DECORATORS + ServerRequiredCustomizations()),
        )
    PythonServerCodegenVisitor(pluginCtx, codegenDecorator).execute()
}

fun cargoTest(workdir: Path) =
    // `--no-default-features` is required to disable `pyo3/extension-module` which causes linking errors
    // see `PyO3ExtensionModuleDecorator`'s comments fore more detail.
    "cargo test --no-default-features".runCommand(
        workdir,
        mapOf(
            // Those are required to run tests on macOS, see: https://pyo3.rs/main/building_and_distribution#macos
            "CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS" to "-C link-arg=-undefined -C link-arg=dynamic_lookup",
            "CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS" to "-C link-arg=-undefined -C link-arg=dynamic_lookup",
        ),
    )
Loading