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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
run: |
make build-py

- name: Check native Python codegen output
- name: Check Python codegen output
if: ${{ matrix.python-version == '3.12' }}
run: |
make generate-codegen-output-py
Expand Down
7 changes: 6 additions & 1 deletion codegen-output-py/types/.smithy-python-manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
{
"files": {
"README.md": "b070865ebb1dc46192ea8a45f0961e1b0f812dfccd069537cfc04311b3327660",
"pyproject.toml": "c419d5bcb7e49329ae50cab3b1a766446d3d14d40a422328788f93e8b2bbeb2b",
"src/example_types/__init__.py": "6d153749d98df8adfe6264fb74d642917cbf2d6922b9211719dee35483dab943",
"src/example_types/_private/__init__.py": "5384bfdb2df380b6557cc7a71d16891415bccaa87699406e236f752c6415389f",
"src/example_types/_private/schemas.py": "1d708d275049f3f4a86b343c3f38104ef4a7e5bf749a27cd1a490c95c8f9db59",
"src/example_types/models.py": "51aadd47e9971f2b44fabd47e81e4b04d7156aa61b64454b39f4b6d47603ab45",
"src/example_types/models.pyi": "31c14804662d43c11fc6c61d0a49244e5e606b65aadb774df913f6a26e1b135a"
"src/example_types/models.pyi": "31c14804662d43c11fc6c61d0a49244e5e606b65aadb774df913f6a26e1b135a",
"src/example_types/py.typed": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"version": 1
}
5 changes: 5 additions & 0 deletions codegen-output-py/types/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- Code generated by smithy-python-codegen DO NOT EDIT. -->

## example_types Types Package

Example Python codegen output
43 changes: 43 additions & 0 deletions codegen-output-py/types/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Code generated by smithy-python-codegen DO NOT EDIT.

[project]
name = "example_types"
version = "1.0.0"
description = "Example Python codegen output"
readme = "README.md"
requires-python = ">=3.12"
keywords = ["smithy", "example_types"]
license = {text = "Apache-2.0"}
dependencies = [
"smithy-core~=0.10.0",
]

[build-system]
requires = [
"hatchling",
]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = [
"src/example_types",
]

[tool.pyright]
typeCheckingMode = "strict"
reportPrivateUsage = false
reportUnusedFunction = false
reportUnusedVariable = false
reportUnnecessaryComparison = false
reportUnusedClass = false
enableExperimentalFeatures = true
exclude = ["**/models.py"]

[tool.ruff]
target-version = "py312"

[tool.ruff.lint]
ignore = ["F841"]

[tool.ruff.format]
skip-magic-trailing-comma = true
3 changes: 3 additions & 0 deletions codegen-output-py/types/src/example_types/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from __future__ import annotations

__version__: str = "1.0.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from __future__ import annotations
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ public void testCodegen(@TempDir Path tempDir) throws IOException {
assertTrue(models.contains("response_metadata: ResponseMetadata"));
assertTrue(models.contains("response_metadata_:"));

// Event streams are passed through the stream API, not model constructors.
var typecheck = Files.readString(tempDir.resolve("tests/_typecheck.py"));
assertFalse(typecheck.contains("stream=_"));

var schemas = Files.readString(tempDir.resolve("src/weather/_private/schemas.py"));
assertTrue(schemas.contains("example.weather#fakeProtocol"));
assertTrue(schemas.contains("aws.protocols#restJson1"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.traits.DefaultTrait;
import software.amazon.smithy.model.traits.ErrorTrait;
import software.amazon.smithy.model.traits.StreamingTrait;
import software.amazon.smithy.model.traits.TimestampFormatTrait;
import software.amazon.smithy.model.traits.TimestampFormatTrait.Format;
import software.amazon.smithy.python.codegen.writer.PythonWriter;
Expand Down Expand Up @@ -193,6 +194,18 @@ public static boolean isErrorMessage(Model model, MemberShape shape) {
&& model.expectShape(shape.getContainer()).hasTrait(ErrorTrait.class);
}

/**
* Determines whether a member targets an event stream.
*
* @param model The whole service model.
* @param member The member to check.
* @return Returns whether the member targets a streaming union.
*/
public static boolean isEventStreamMember(Model model, MemberShape member) {
var target = model.expectShape(member.getTarget());
return target.isUnionShape() && target.hasTrait(StreamingTrait.class);
}

/**
* Determines whether a member is required in the generated Python constructor — that is,
* neither nullable nor carrying a default value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ private void writeStructUsage(
if (!operationIndex.isInputStructure(shape)) {
for (var member : shape.members()) {
if (CodegenUtils.isRequiredMember(index, member)
&& !CodegenUtils.isErrorMessage(model, member)) {
&& !CodegenUtils.isErrorMessage(model, member)
&& !CodegenUtils.isEventStreamMember(model, member)) {
var memberName = symbolProvider.toMemberName(member);
if (args.length() > 0) {
args.append(", ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import software.amazon.smithy.model.traits.DocumentationTrait;
import software.amazon.smithy.model.traits.EnumValueTrait;
import software.amazon.smithy.model.traits.ErrorTrait;
import software.amazon.smithy.model.traits.StreamingTrait;
import software.amazon.smithy.python.codegen.CodegenUtils;
import software.amazon.smithy.python.codegen.GenerationContext;
import software.amazon.smithy.python.codegen.PythonSettings;
Expand Down Expand Up @@ -117,7 +116,7 @@ private void writeStruct(PythonWriter writer, StructureShape shape) {
var members = shape.members()
.stream()
.filter(m -> !CodegenUtils.isErrorMessage(model, m))
.filter(m -> !isEventStreamMember(m))
.filter(m -> !CodegenUtils.isEventStreamMember(model, m))
.toList();
if (members.isEmpty() && !carriesResponseMetadata(shape)) {
return;
Expand Down Expand Up @@ -164,11 +163,6 @@ private boolean carriesResponseMetadata(Shape shape) {
return shape.hasTrait(ErrorTrait.class) || OperationIndex.of(model).isOutputStructure(shape);
}

private boolean isEventStreamMember(MemberShape member) {
var target = model.expectShape(member.getTarget());
return target.isUnionShape() && target.hasTrait(StreamingTrait.class);
}

private void writeUnion(PythonWriter writer, UnionShape shape) {
var parentSymbol = symbolProvider.toSymbol(shape);
var parentName = parentSymbol.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import software.amazon.smithy.model.traits.ErrorTrait;
import software.amazon.smithy.model.traits.RetryableTrait;
import software.amazon.smithy.model.traits.SensitiveTrait;
import software.amazon.smithy.model.traits.StreamingTrait;
import software.amazon.smithy.python.codegen.CodegenUtils;
import software.amazon.smithy.python.codegen.GenerationContext;
import software.amazon.smithy.python.codegen.PythonSettings;
Expand Down Expand Up @@ -302,21 +301,18 @@ private void writeMemberDocs(MemberShape member) {

private List<MemberShape> filterPropertyMembers(List<MemberShape> members) {
if (!shape.hasTrait(ErrorTrait.class)) {
return members.stream().filter(this::filterEventStreamMember).toList();
return members.stream()
.filter(member -> !CodegenUtils.isEventStreamMember(model, member))
.toList();
}
// We replace modeled message members with a static `message` member. Serialization
// and deserialization will handle assigning them properly.
return members.stream()
.filter(member -> !isErrorMessage(model, member))
.filter(this::filterEventStreamMember)
.filter(member -> !CodegenUtils.isEventStreamMember(model, member))
.collect(Collectors.toList());
}

private boolean filterEventStreamMember(MemberShape member) {
var target = model.expectShape(member.getTarget());
return !(target.isUnionShape() && target.hasTrait(StreamingTrait.class));
}

private String getDefaultValue(PythonWriter writer, MemberShape member) {
// The default value is defined in the model is a exposed as generic
// json, so we need to convert it to the proper type based on the target.
Expand Down Expand Up @@ -412,10 +408,7 @@ def serialize(self, serializer: ${shapeSerializer:T}):
private List<MemberShape> filterMembers() {
return shape.members()
.stream()
.filter(member -> {
var target = model.expectShape(member.getTarget());
return !(target.hasTrait(StreamingTrait.class) && target.isUnionShape());
})
.filter(member -> !CodegenUtils.isEventStreamMember(model, member))
.toList();
}

Expand All @@ -441,10 +434,7 @@ private void generateDeserializeMethod() {
// index tuple would be an unused local.
boolean hasMembers = shape.members()
.stream()
.anyMatch(m -> {
var t = model.expectShape(m.getTarget());
return !(t.hasTrait(StreamingTrait.class) && t.isUnionShape());
});
.anyMatch(member -> !CodegenUtils.isEventStreamMember(model, member));
writer.putContext("hasMembers", hasMembers);

// TODO: either formalize deserialize_kwargs or remove it when http serde is converted
Expand Down Expand Up @@ -558,7 +548,7 @@ private void deserializeMembers(Collection<MemberShape> members) {
for (MemberShape member : members) {
index++;
var target = model.expectShape(member.getTarget());
if (target.hasTrait(StreamingTrait.class) && target.isUnionShape()) {
if (CodegenUtils.isEventStreamMember(model, member)) {
continue;
}
writer.write("""
Expand Down
20 changes: 9 additions & 11 deletions packages/smithy-python/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
# smithy-python

> [!WARNING]
> This package is an experimental scaffold. It does not generate code yet. The
> Java generator in the repository's `codegen` directory remains authoritative.

`smithy-python` will provide Python-native code generation for Smithy models.
The initial command-line interface exposes the planned client and types generation
commands so that their top-level shape can be developed independently from the
generator implementation.
`smithy-python` provides Python-native code generation for Smithy models.
Standalone types generation is available; client generation remains under
development.

```console
smithy-python generate client [OPTIONS]
smithy-python generate types [OPTIONS]
```

After validating their invocation options, both generation commands currently exit
with an error explaining that generation has not been implemented. The package is
included in workspace builds to validate its packaging and entry points.
`generate types` produces an installable package containing compact schemas, lazy
runtime models, and a complete static typing surface. Run
`smithy-python generate types --help` for artifact settings.

`generate client` currently exits with an error explaining that client generation
has not been implemented.
4 changes: 3 additions & 1 deletion packages/smithy-python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ classifiers = [
"Programming Language :: Python :: Free Threading :: 2 - Beta",
"Topic :: Software Development :: Code Generators",
]
dependencies = []
dependencies = [
"packaging",
]

[project.scripts]
smithy-python = "smithy_python.cli:main"
Expand Down
Loading
Loading