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
11 changes: 8 additions & 3 deletions codegen-output-py/types/.smithy-python-manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
{
"files": {
"src/example_types/_private/schemas.py": "1d708d275049f3f4a86b343c3f38104ef4a7e5bf749a27cd1a490c95c8f9db59",
"src/example_types/models.py": "51aadd47e9971f2b44fabd47e81e4b04d7156aa61b64454b39f4b6d47603ab45",
"src/example_types/models.pyi": "31c14804662d43c11fc6c61d0a49244e5e606b65aadb774df913f6a26e1b135a"
"README.md": "b070865ebb1dc46192ea8a45f0961e1b0f812dfccd069537cfc04311b3327660",
"pyproject.toml": "3b4edeff9fe5c4641d8729e49abfa1e7c1936484d0512ad273a3724ebb54f40a",
"src/example_types/__init__.py": "27ea4bc5ba93a6fc6e1f11e9784565de24e9249f0d3e77a9e2fb64fa47d11012",
"src/example_types/_private/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"src/example_types/_private/schemas.py": "b3c1dd3b1ab8511ef45cca22cf415726aec599edfd457b30cdb22482bcd5b799",
"src/example_types/models.py": "262a8c40dce4fb282aca6b17214296db0c4fc1da526a50a3155cde0fe7344b6b",
"src/example_types/models.pyi": "36be0dc7d1d9402394e531d782fab2392d55cc60a949a1bcae4c4f469de6cc11",
"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
36 changes: 36 additions & 0 deletions codegen-output-py/types/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 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"

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

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

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

from smithy_core._schema_compact import StaticSchema

n0 = "example"
Expand Down
4 changes: 1 addition & 3 deletions codegen-output-py/types/src/example_types/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import annotations

from smithy_core._dynamic_models import ModelRegistry
from smithy_core.exceptions import ModeledError

Expand Down Expand Up @@ -43,7 +41,7 @@ class ServiceError(ModeledError):
}

_MODEL_NAMES = (*tuple(_MODEL_INDEX), "Unit")
__all__ = ("ServiceError", *_MODEL_NAMES)
__all__ = ("ServiceError", *_MODEL_NAMES) # pyright: ignore[reportUnsupportedDunderAll]


_registry = ModelRegistry(
Expand Down
2 changes: 0 additions & 2 deletions codegen-output-py/types/src/example_types/models.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import annotations

from dataclasses import dataclass
from enum import IntEnum, StrEnum
from typing import Self
Expand Down
Empty file.
13 changes: 7 additions & 6 deletions designs/codegen/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ The `types` command accepts:
* `--package-version`
* `--package-description`
* `--selector`
* `--generate-inputs-and-outputs`
* `--include-operation-io`

`package` and `package-version` are required. The package identifies the
generated import package and follows the validation rules in `SymbolProvider`.
Expand All @@ -129,7 +129,7 @@ Types generation never infers a service. The options apply in this order:
2. `--selector` narrows those declaration shapes. The default identity selector
keeps every candidate.
3. Input and output structures are removed as roots unless
`--generate-inputs-and-outputs` is set.
`--include-operation-io` is set.
4. Member-target dependencies of the remaining declarations are added
transitively.

Expand Down Expand Up @@ -382,16 +382,17 @@ model names:

```python
_MODEL_NAMES = tuple(_MODEL_INDEX)
__all__ = ("ServiceError", *_MODEL_NAMES)
__all__ = ("ServiceError", *_MODEL_NAMES) # pyright: ignore[reportUnsupportedDunderAll]


def __dir__() -> list[str]:
return sorted({*globals(), *__all__})
```

This keeps Ruff from reporting `F822` for lazy exports. Star imports read
`__all__` and resolve each model through module `__getattr__`. Computing
`__dir__` from the index does not construct model classes.
This keeps Ruff from reporting `F822` for lazy exports. The targeted Pyright
suppression replaces excluding the complete runtime module from analysis. Star
imports read `__all__` and resolve each model through module `__getattr__`.
Computing `__dir__` from the index does not construct model classes.

Model member access uses the schema's dense member indexes where positional
dispatch is required. Name maps remain dictionaries where lookup is by a wire
Expand Down
38 changes: 21 additions & 17 deletions designs/codegen/writer.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,30 @@ decides which declarations, fields, and defaults to write.
from smithy_python.symbols import TypeReference
from smithy_python.writer import PythonWriter

node = TypeReference("Node", "example.models", nullable=True)
leaf = TypeReference("Leaf", "example.models", nullable=True)
writer = PythonWriter("example.models")
writer.line("class Leaf:")
with writer.indent():
writer.line("pass")
writer.line()
writer.line("class Node:")
with writer.indent():
writer.line("children: ", TypeReference("list", "builtins", (node,)))
writer.line("children: ", TypeReference("list", "builtins", (leaf,)))
writer.line("amount: ", TypeReference("Decimal", "decimal"))
source = writer.render()
```

The result is:

```python
from __future__ import annotations

from decimal import Decimal


class Leaf:
pass

class Node:
children: list[Node | None]
children: list[Leaf | None]
amount: Decimal
```

Expand Down Expand Up @@ -56,9 +61,9 @@ symbol provider ensures that declaration and field names are unique.
current indentation. `line()` writes a blank line without spaces.
* `indent()` adds four spaces inside a context manager and restores indentation
even when the block raises an exception.
* `render()` returns source ending in a newline, with a future-annotations
header, sorted imports and the body in written order. It does not modify the
writer. Adding another reference can change aliases in the next render.
* `render()` returns source ending in a newline, with sorted imports and the body
in written order. It does not modify the writer. Adding another reference can
change aliases in the next render.

Raw text is trusted Python, not a template. To find names, `render()` parses
the written lines with the Python 3.12 grammar, with a unique placeholder
Expand All @@ -69,9 +74,8 @@ later Python versions will reject them. Callers supply blank lines between
declarations.

The analysis reads the syntax tree rather than `symtable`, whose results change
between Python versions and omit annotations under `from __future__ import
annotations`. A reference joined to raw text, such as `obj.` followed by a
reference, has no scope of its own. It is treated as visible to every local
between Python versions. A reference joined to raw text, such as `obj.` followed
by a reference, has no scope of its own. It is treated as visible to every local
name.

Pass every builtin or imported name as a type reference, not just annotations.
Expand Down Expand Up @@ -104,9 +108,9 @@ level: `list[str | None]` differs from `list[str] | None`. The `None` literal
stays `None`, including when marked nullable. Only that literal can omit its
module. Other module-less references raise `CodegenError`.

Generated source targets Python 3.12+. The future import permits references to
classes defined later, including recursive types. These are annotations, not
expressions to evaluate while defining classes.
Generated source targets Python 3.12+. References in runtime annotations must
name classes that have already been defined. Stub annotations can refer to
classes defined later.

* Builtins normally use `str`, `int`, `list[T]` and `dict[K, V]`.
* Types in the current module use their bare names without imports.
Expand Down Expand Up @@ -135,9 +139,9 @@ without recording dependencies.

## Names that collide

An import uses a module-derived alias when its name matches a module-level
name, a local name visible where it is referenced, a builtin, the future
import's `annotations` name, or another imported type.
An import uses a module-derived alias when its name matches a module-level name,
a local name visible where it is referenced, a builtin, or another imported
type.
For example, `decimal.Decimal` becomes `_decimal_Decimal`. Dots in a module
path become underscores. All imports sharing a short name receive aliases,
regardless of the order they were written.
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.
Loading