smithy-python 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,60 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ """The embedded subset of the Smithy prelude.
4
+
5
+ Only the shapes that model members and relationships can target are embedded.
6
+ Trait-definition shapes are intentionally omitted: trait keys are not resolved
7
+ as references, and later stages never generate or inspect trait definitions.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from collections.abc import Mapping
13
+ from types import MappingProxyType
14
+ from typing import Any, Final
15
+
16
+ _P: Final = "smithy.api#"
17
+
18
+ _SIMPLE: Final = (
19
+ ("String", "string"),
20
+ ("Blob", "blob"),
21
+ ("BigInteger", "bigInteger"),
22
+ ("BigDecimal", "bigDecimal"),
23
+ ("Timestamp", "timestamp"),
24
+ ("Document", "document"),
25
+ ("Boolean", "boolean"),
26
+ ("Byte", "byte"),
27
+ ("Short", "short"),
28
+ ("Integer", "integer"),
29
+ ("Long", "long"),
30
+ ("Float", "float"),
31
+ ("Double", "double"),
32
+ )
33
+
34
+ _PRIMITIVE: Final = (
35
+ ("PrimitiveBoolean", "boolean", False),
36
+ ("PrimitiveByte", "byte", 0),
37
+ ("PrimitiveShort", "short", 0),
38
+ ("PrimitiveInteger", "integer", 0),
39
+ ("PrimitiveLong", "long", 0),
40
+ ("PrimitiveFloat", "float", 0),
41
+ ("PrimitiveDouble", "double", 0),
42
+ )
43
+
44
+
45
+ def prelude_ast() -> Mapping[str, Mapping[str, Any]]:
46
+ """Return a fresh JSON AST ``shapes`` mapping for the embedded prelude."""
47
+ shapes: dict[str, Mapping[str, Any]] = {}
48
+ for name, type_name in _SIMPLE:
49
+ shapes[_P + name] = {"type": type_name}
50
+ for name, type_name, default in _PRIMITIVE:
51
+ shapes[_P + name] = {
52
+ "type": type_name,
53
+ "traits": {_P + "default": default},
54
+ }
55
+ shapes[_P + "Unit"] = {
56
+ "type": "structure",
57
+ "members": {},
58
+ "traits": {_P + "unitType": {}},
59
+ }
60
+ return MappingProxyType(shapes)
@@ -0,0 +1,115 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ """Shape identifiers."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import re
8
+ from dataclasses import dataclass
9
+ from typing import Final, Self
10
+
11
+ from ..exceptions import InvalidShapeIdError
12
+
13
+ _IDENTIFIER: Final = r"_*[A-Za-z][A-Za-z0-9_]*"
14
+ _IDENTIFIER_RE: Final = re.compile(_IDENTIFIER)
15
+ _NAMESPACE_RE: Final = re.compile(rf"{_IDENTIFIER}(?:\.{_IDENTIFIER})*")
16
+
17
+ PRELUDE_NAMESPACE: Final = "smithy.api"
18
+
19
+
20
+ @dataclass(frozen=True, slots=True)
21
+ class ShapeId:
22
+ """A Smithy shape ID: ``namespace#Name`` or ``namespace#Name$member``.
23
+
24
+ Shape IDs are hashable and totally ordered by (namespace, name, member),
25
+ with the root shape sorting before its members.
26
+ """
27
+
28
+ namespace: str
29
+ name: str
30
+ member: str | None = None
31
+
32
+ def __post_init__(self) -> None:
33
+ if not _NAMESPACE_RE.fullmatch(self.namespace):
34
+ raise InvalidShapeIdError(
35
+ f"Invalid shape ID namespace {self.namespace!r} in {self._raw()!r}"
36
+ )
37
+ if not _IDENTIFIER_RE.fullmatch(self.name):
38
+ raise InvalidShapeIdError(
39
+ f"Invalid shape ID name {self.name!r} in {self._raw()!r}"
40
+ )
41
+ if self.member is not None and not _IDENTIFIER_RE.fullmatch(self.member):
42
+ raise InvalidShapeIdError(
43
+ f"Invalid shape ID member {self.member!r} in {self._raw()!r}"
44
+ )
45
+
46
+ @classmethod
47
+ def from_string(cls, value: str, *, default_namespace: str | None = None) -> Self:
48
+ """Parse an absolute or relative shape ID.
49
+
50
+ Relative IDs (no ``#``) are resolved against ``default_namespace``;
51
+ without one they are rejected.
52
+ """
53
+ if "#" in value:
54
+ namespace, _, rest = value.partition("#")
55
+ if "#" in rest:
56
+ raise InvalidShapeIdError(f"Invalid shape ID {value!r}")
57
+ elif default_namespace is not None:
58
+ namespace, rest = default_namespace, value
59
+ else:
60
+ raise InvalidShapeIdError(
61
+ f"Invalid shape ID {value!r}: expected an absolute shape ID "
62
+ "of the form namespace#Name"
63
+ )
64
+ name, sep, member = rest.partition("$")
65
+ try:
66
+ return cls(namespace, name, member if sep else None)
67
+ except InvalidShapeIdError:
68
+ raise InvalidShapeIdError(f"Invalid shape ID {value!r}") from None
69
+
70
+ @property
71
+ def is_member(self) -> bool:
72
+ """Whether this ID refers to a member."""
73
+ return self.member is not None
74
+
75
+ @property
76
+ def root(self) -> ShapeId:
77
+ """This ID without its member component."""
78
+ if self.member is None:
79
+ return self
80
+ return ShapeId(self.namespace, self.name)
81
+
82
+ def with_member(self, member: str) -> ShapeId:
83
+ """Return the ID of ``member`` within this shape."""
84
+ return ShapeId(self.namespace, self.name, member)
85
+
86
+ def __str__(self) -> str:
87
+ return self._raw()
88
+
89
+ def _raw(self) -> str:
90
+ base = f"{self.namespace}#{self.name}"
91
+ return base if self.member is None else f"{base}${self.member}"
92
+
93
+ def _key(self) -> tuple[str, str, bool, str]:
94
+ return (self.namespace, self.name, self.member is not None, self.member or "")
95
+
96
+ def __lt__(self, other: ShapeId) -> bool:
97
+ return self._key() < other._key()
98
+
99
+ def __le__(self, other: ShapeId) -> bool:
100
+ return self._key() <= other._key()
101
+
102
+ def __gt__(self, other: ShapeId) -> bool:
103
+ return self._key() > other._key()
104
+
105
+ def __ge__(self, other: ShapeId) -> bool:
106
+ return self._key() >= other._key()
107
+
108
+
109
+ def as_shape_id(
110
+ value: ShapeId | str, *, default_namespace: str | None = None
111
+ ) -> ShapeId:
112
+ """Coerce a string or ShapeId to a ShapeId."""
113
+ if isinstance(value, ShapeId):
114
+ return value
115
+ return ShapeId.from_string(value, default_namespace=default_namespace)
@@ -0,0 +1,251 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ """Shape types and the flattened, immutable shape classes."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from collections.abc import Mapping
8
+ from dataclasses import dataclass, field
9
+ from enum import StrEnum
10
+ from types import MappingProxyType
11
+ from typing import Final
12
+
13
+ from ._shape_id import PRELUDE_NAMESPACE, ShapeId, as_shape_id
14
+
15
+ type Node = None | bool | int | float | str | tuple[Node, ...] | Mapping[str, Node]
16
+ """A deeply immutable JSON value: arrays are tuples, objects read-only mappings."""
17
+
18
+ type JsonValue = (
19
+ None | bool | int | float | str | list[JsonValue] | dict[str, JsonValue]
20
+ )
21
+ """A mutable JSON value, as produced by :func:`to_json`."""
22
+
23
+
24
+ def to_json(node: Node) -> JsonValue:
25
+ """Return a mutable copy of a node, e.g. for ``json.dumps`` or editing."""
26
+ if isinstance(node, Mapping):
27
+ return {k: to_json(v) for k, v in node.items()}
28
+ if isinstance(node, tuple):
29
+ return [to_json(v) for v in node]
30
+ return node
31
+
32
+
33
+ class ShapeType(StrEnum):
34
+ """Every shape type in the Smithy 2.0 semantic model, including members."""
35
+
36
+ BLOB = "blob"
37
+ BOOLEAN = "boolean"
38
+ STRING = "string"
39
+ BYTE = "byte"
40
+ SHORT = "short"
41
+ INTEGER = "integer"
42
+ LONG = "long"
43
+ FLOAT = "float"
44
+ DOUBLE = "double"
45
+ BIG_INTEGER = "bigInteger"
46
+ BIG_DECIMAL = "bigDecimal"
47
+ TIMESTAMP = "timestamp"
48
+ DOCUMENT = "document"
49
+ ENUM = "enum"
50
+ INT_ENUM = "intEnum"
51
+ LIST = "list"
52
+ MAP = "map"
53
+ STRUCTURE = "structure"
54
+ UNION = "union"
55
+ MEMBER = "member"
56
+ SERVICE = "service"
57
+ RESOURCE = "resource"
58
+ OPERATION = "operation"
59
+
60
+
61
+ SIMPLE_TYPES: Final = frozenset(
62
+ {
63
+ ShapeType.BLOB,
64
+ ShapeType.BOOLEAN,
65
+ ShapeType.STRING,
66
+ ShapeType.BYTE,
67
+ ShapeType.SHORT,
68
+ ShapeType.INTEGER,
69
+ ShapeType.LONG,
70
+ ShapeType.FLOAT,
71
+ ShapeType.DOUBLE,
72
+ ShapeType.BIG_INTEGER,
73
+ ShapeType.BIG_DECIMAL,
74
+ ShapeType.TIMESTAMP,
75
+ ShapeType.DOCUMENT,
76
+ }
77
+ )
78
+
79
+ MIXIN_TRAIT: Final = ShapeId(PRELUDE_NAMESPACE, "mixin")
80
+ UNIT: Final = ShapeId(PRELUDE_NAMESPACE, "Unit")
81
+
82
+ _EMPTY_TRAITS: Final[Mapping[ShapeId, Node]] = MappingProxyType({})
83
+ _EMPTY_MEMBERS: Final[Mapping[str, MemberShape]] = MappingProxyType({})
84
+
85
+
86
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
87
+ class Shape:
88
+ """Base class of every shape.
89
+
90
+ Shapes are already mixin-flattened: ``members`` and ``traits`` include
91
+ everything inherited from mixins, in a deterministic order. Instances are
92
+ immutable; trait values are deeply frozen :data:`Node` values (use
93
+ :func:`to_json` for a mutable copy). Equality is identity.
94
+ """
95
+
96
+ id: ShapeId
97
+ type: ShapeType
98
+ traits: Mapping[ShapeId, Node] = _EMPTY_TRAITS
99
+ """Trait ID to JSON node value, in merge order (see the loader docs)."""
100
+ mixins: tuple[ShapeId, ...] = ()
101
+ """The mixins this shape declared, in declaration order.
102
+
103
+ Informational only: members, traits, and properties already include
104
+ everything inherited from these mixins.
105
+ """
106
+ members: Mapping[str, MemberShape] = _EMPTY_MEMBERS
107
+ """Members by name, in order: inherited mixin members, then local ones."""
108
+
109
+ def has_trait(self, trait: ShapeId | str) -> bool:
110
+ """Whether the shape has a trait; relative names resolve to smithy.api."""
111
+ return _trait_id(trait) in self.traits
112
+
113
+ def get_trait(self, trait: ShapeId | str) -> Node:
114
+ """Return a trait value or None if absent (use has_trait for presence)."""
115
+ return self.traits.get(_trait_id(trait))
116
+
117
+ @property
118
+ def is_mixin(self) -> bool:
119
+ """Whether the shape is marked with ``@mixin``."""
120
+ return MIXIN_TRAIT in self.traits
121
+
122
+
123
+ def _trait_id(trait: ShapeId | str) -> ShapeId:
124
+ return as_shape_id(trait, default_namespace=PRELUDE_NAMESPACE)
125
+
126
+
127
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
128
+ class SimpleShape(Shape):
129
+ """A blob, boolean, string, numeric, timestamp, or document shape."""
130
+
131
+
132
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
133
+ class MemberShape(Shape):
134
+ """A member of an aggregate shape; its ID is rooted at its container."""
135
+
136
+ type: ShapeType = ShapeType.MEMBER
137
+ target: ShapeId
138
+
139
+ @property
140
+ def container(self) -> ShapeId:
141
+ """ID of the shape that contains this member."""
142
+ return self.id.root
143
+
144
+ @property
145
+ def name(self) -> str:
146
+ """The member name."""
147
+ assert self.id.member is not None # noqa: S101 - invariant
148
+ return self.id.member
149
+
150
+
151
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
152
+ class ListShape(Shape):
153
+ """A list shape; ``members`` contains exactly ``member``."""
154
+
155
+ @property
156
+ def member(self) -> MemberShape:
157
+ return self.members["member"]
158
+
159
+
160
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
161
+ class MapShape(Shape):
162
+ """A map shape; ``members`` contains ``key`` then ``value``."""
163
+
164
+ @property
165
+ def key(self) -> MemberShape:
166
+ return self.members["key"]
167
+
168
+ @property
169
+ def value(self) -> MemberShape:
170
+ return self.members["value"]
171
+
172
+
173
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
174
+ class StructureShape(Shape):
175
+ """A structure shape."""
176
+
177
+
178
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
179
+ class UnionShape(Shape):
180
+ """A union shape."""
181
+
182
+
183
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
184
+ class EnumShape(Shape):
185
+ """A string enum; member values live in ``smithy.api#enumValue``."""
186
+
187
+
188
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
189
+ class IntEnumShape(Shape):
190
+ """An integer enum; member values live in ``smithy.api#enumValue``."""
191
+
192
+
193
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
194
+ class ServiceShape(Shape):
195
+ """A service shape."""
196
+
197
+ version: str | None = None
198
+ operations: tuple[ShapeId, ...] = ()
199
+ resources: tuple[ShapeId, ...] = ()
200
+ errors: tuple[ShapeId, ...] = ()
201
+ rename: Mapping[ShapeId, str] = field(default_factory=lambda: MappingProxyType({}))
202
+
203
+
204
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
205
+ class ResourceShape(Shape):
206
+ """A resource shape."""
207
+
208
+ identifiers: Mapping[str, ShapeId] = field(
209
+ default_factory=lambda: MappingProxyType({})
210
+ )
211
+ properties: Mapping[str, ShapeId] = field(
212
+ default_factory=lambda: MappingProxyType({})
213
+ )
214
+ create: ShapeId | None = None
215
+ put: ShapeId | None = None
216
+ read: ShapeId | None = None
217
+ update: ShapeId | None = None
218
+ delete: ShapeId | None = None
219
+ list: ShapeId | None = None
220
+ operations: tuple[ShapeId, ...] = ()
221
+ collection_operations: tuple[ShapeId, ...] = ()
222
+ resources: tuple[ShapeId, ...] = ()
223
+
224
+
225
+ @dataclass(frozen=True, slots=True, kw_only=True, eq=False)
226
+ class OperationShape(Shape):
227
+ """An operation shape.
228
+
229
+ An absent ``input`` or ``output`` is ``smithy.api#Unit``, matching Smithy's
230
+ semantic model; explicit and implicit Unit are indistinguishable.
231
+ """
232
+
233
+ input: ShapeId = UNIT
234
+ output: ShapeId = UNIT
235
+ errors: tuple[ShapeId, ...] = ()
236
+
237
+
238
+ SHAPE_CLASSES: Final[Mapping[ShapeType, type[Shape]]] = MappingProxyType(
239
+ {
240
+ **dict.fromkeys(SIMPLE_TYPES, SimpleShape),
241
+ ShapeType.LIST: ListShape,
242
+ ShapeType.MAP: MapShape,
243
+ ShapeType.STRUCTURE: StructureShape,
244
+ ShapeType.UNION: UnionShape,
245
+ ShapeType.ENUM: EnumShape,
246
+ ShapeType.INT_ENUM: IntEnumShape,
247
+ ShapeType.SERVICE: ServiceShape,
248
+ ShapeType.RESOURCE: ResourceShape,
249
+ ShapeType.OPERATION: OperationShape,
250
+ }
251
+ )
smithy_python/py.typed ADDED
File without changes
@@ -0,0 +1,157 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ """Service and data-shape selection on a loaded semantic model."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from collections.abc import Iterator
8
+ from dataclasses import dataclass
9
+
10
+ from .exceptions import InvalidInvocationError, InvalidShapeIdError, ModelError
11
+ from .model import (
12
+ MemberShape,
13
+ Model,
14
+ OperationShape,
15
+ ResourceShape,
16
+ ServiceShape,
17
+ Shape,
18
+ ShapeId,
19
+ ShapeType,
20
+ )
21
+
22
+
23
+ @dataclass(frozen=True, slots=True)
24
+ class Selection:
25
+ """Selected service and eligible data shapes in original model order."""
26
+
27
+ service: ServiceShape | None
28
+ shapes: tuple[Shape, ...]
29
+ excluded_count: int
30
+ """Eligible data shapes omitted by the service closure (zero without a service)."""
31
+
32
+
33
+ def select_shapes(
34
+ model: Model, *, service_id: str | None = None, require_service: bool = False
35
+ ) -> Selection:
36
+ """Select data for generation from an already loaded, flattened model.
37
+
38
+ Service selection failures raise ``InvalidInvocationError``. Without a
39
+ service, case-insensitive data-shape name conflicts raise ``ModelError``.
40
+ This stage neither validates Smithy semantics nor writes output.
41
+ """
42
+ service = resolve_service(
43
+ model, service_id=service_id, require_service=require_service
44
+ )
45
+ eligible = tuple(
46
+ shape
47
+ for shape in model.iter_shapes()
48
+ if shape.type
49
+ not in (
50
+ ShapeType.SERVICE,
51
+ ShapeType.OPERATION,
52
+ ShapeType.RESOURCE,
53
+ ShapeType.MEMBER,
54
+ )
55
+ and not shape.is_mixin
56
+ and not shape.has_trait("trait")
57
+ )
58
+ if service is None:
59
+ _check_names(eligible)
60
+ return Selection(service=None, shapes=eligible, excluded_count=0)
61
+
62
+ visited: set[ShapeId] = set()
63
+ pending = [service.id]
64
+ while pending:
65
+ shape_id = pending.pop()
66
+ if shape_id in visited:
67
+ continue
68
+ visited.add(shape_id)
69
+ pending.extend(_references(model.get_shape(shape_id)))
70
+
71
+ selected = tuple(shape for shape in eligible if shape.id in visited)
72
+ return Selection(
73
+ service=service, shapes=selected, excluded_count=len(eligible) - len(selected)
74
+ )
75
+
76
+
77
+ def _references(shape: Shape) -> Iterator[ShapeId]:
78
+ # Only semantic relationships are edges, never trait nodes, rename entries,
79
+ # or mixin declarations (the loader has already flattened their contents).
80
+ for member in shape.members.values():
81
+ yield member.target
82
+ if isinstance(shape, MemberShape):
83
+ yield shape.target
84
+ elif isinstance(shape, ServiceShape):
85
+ yield from shape.operations
86
+ yield from shape.resources
87
+ yield from shape.errors
88
+ elif isinstance(shape, OperationShape):
89
+ yield shape.input
90
+ yield shape.output
91
+ yield from shape.errors
92
+ elif isinstance(shape, ResourceShape):
93
+ yield from shape.identifiers.values()
94
+ yield from shape.properties.values()
95
+ for operation in (
96
+ shape.create,
97
+ shape.put,
98
+ shape.read,
99
+ shape.update,
100
+ shape.delete,
101
+ shape.list,
102
+ ):
103
+ if operation is not None:
104
+ yield operation
105
+ yield from shape.operations
106
+ yield from shape.collection_operations
107
+ yield from shape.resources
108
+
109
+
110
+ def _check_names(shapes: tuple[Shape, ...]) -> None:
111
+ by_name: dict[str, list[ShapeId]] = {}
112
+ for shape in shapes:
113
+ by_name.setdefault(shape.id.name.casefold(), []).append(shape.id)
114
+ conflicts = [ids for ids in by_name.values() if len(ids) > 1]
115
+ if conflicts:
116
+ details = "; ".join(
117
+ ", ".join(str(shape_id) for shape_id in ids) for ids in conflicts
118
+ )
119
+ raise ModelError(f"Case-insensitive data shape name conflicts: {details}")
120
+
121
+
122
+ def resolve_service(
123
+ model: Model, *, service_id: str | None = None, require_service: bool = False
124
+ ) -> ServiceShape | None:
125
+ """Resolve an absolute service ID or the sole non-mixin service.
126
+
127
+ Invalid or ambiguous selections raise :class:`InvalidInvocationError`.
128
+ """
129
+ if service_id is not None:
130
+ try:
131
+ shape_id = ShapeId.from_string(service_id)
132
+ except InvalidShapeIdError as error:
133
+ raise InvalidInvocationError(f"--service: {error}") from error
134
+ if shape_id.is_member:
135
+ raise InvalidInvocationError(
136
+ f"--service {service_id!r} is a member ID, not a service"
137
+ )
138
+ shape = model.find_shape(shape_id)
139
+ if shape is None:
140
+ raise InvalidInvocationError(f"--service {service_id!r} is not defined")
141
+ if not isinstance(shape, ServiceShape):
142
+ raise InvalidInvocationError(f"--service {service_id!r} is not a service")
143
+ if shape.is_mixin:
144
+ raise InvalidInvocationError(f"--service {service_id!r} is a mixin")
145
+ return shape
146
+
147
+ services = model.services()
148
+ if len(services) > 1:
149
+ candidates = ", ".join(str(service.id) for service in services)
150
+ raise InvalidInvocationError(
151
+ f"Multiple services found; select one with --service: {candidates}"
152
+ )
153
+ if services:
154
+ return services[0]
155
+ if require_service:
156
+ raise InvalidInvocationError("Client generation requires a service")
157
+ return None
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.5
2
+ Name: smithy-python
3
+ Version: 0.1.0
4
+ Summary: A Smithy code generator for Python clients and types.
5
+ Project-URL: Changelog, https://github.com/smithy-lang/smithy-python/blob/develop/packages/smithy-python/CHANGELOG.md
6
+ Project-URL: Code, https://github.com/smithy-lang/smithy-python/tree/develop/packages/smithy-python/
7
+ Project-URL: Issue tracker, https://github.com/smithy-lang/smithy-python/issues
8
+ Author: Amazon Web Services
9
+ License: Apache License 2.0
10
+ License-File: NOTICE
11
+ Keywords: codegen,sdk,smithy
12
+ Classifier: Development Status :: 2 - Pre-Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Natural Language :: English
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
24
+ Classifier: Programming Language :: Python :: Implementation :: CPython
25
+ Classifier: Topic :: Software Development :: Code Generators
26
+ Requires-Python: >=3.12
27
+ Description-Content-Type: text/markdown
28
+
29
+ # smithy-python
30
+
31
+ > [!WARNING]
32
+ > This package is an experimental scaffold. It does not generate code yet. The
33
+ > Java generator in the repository's `codegen` directory remains authoritative.
34
+
35
+ `smithy-python` will provide Python-native code generation for Smithy models.
36
+ The initial command-line interface exposes the planned client and types generation
37
+ commands so that their top-level shape can be developed independently from the
38
+ generator implementation.
39
+
40
+ ```console
41
+ smithy-python generate client [OPTIONS]
42
+ smithy-python generate types [OPTIONS]
43
+ ```
44
+
45
+ After validating their invocation options, both generation commands currently exit
46
+ with an error explaining that generation has not been implemented. The package is
47
+ included in workspace builds to validate its packaging and entry points.
@@ -0,0 +1,18 @@
1
+ smithy_python/__init__.py,sha256=TYc2ZwzNfYTsMhGUavAo7icqsC0mLg-n72wdROvgAsM,190
2
+ smithy_python/__main__.py,sha256=k8QDgjDBeX6t-Kk934IctxdYkfSUyVpVDah4yKBaQcw,187
3
+ smithy_python/cli.py,sha256=lcHI12FVGAN0OX5ZWzOnwLOvZAexTHV5m8pzSb1g3ds,5982
4
+ smithy_python/environment.py,sha256=4N-E_8P_a-YNGoa0XtzQifeoSDdWdVCh-LgWn6wdkas,1359
5
+ smithy_python/exceptions.py,sha256=2HEVrOGGymv1OyC0izM8YJq1sCKKWIovbk_UHAu2Pj8,835
6
+ smithy_python/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ smithy_python/selection.py,sha256=oIAn4gRN9eVN3VDjuSMXNrzUhzdb-TgSdIsrD8vOmqw,5373
8
+ smithy_python/model/__init__.py,sha256=kq_nBh2wldOrOqsxlQQjPtqEuiJCIoodBh9laIFIs_M,1268
9
+ smithy_python/model/_loader.py,sha256=pRUkx9mJzeHp2HecoC_aliMy3XU6AYG6c3aPCrkMV-I,21226
10
+ smithy_python/model/_model.py,sha256=dbPvZ6ZEp8B2N6vuHifX2qLuSbhWJHIgY8avx8GQz1M,4872
11
+ smithy_python/model/_prelude.py,sha256=UUjJ29cL5WciRFqqNh2Zj9I52TUVCyzYIuN2RIKbOok,1814
12
+ smithy_python/model/_shape_id.py,sha256=Jky_-TwiZd1k-SKRqqqmydGfhrar8ITQxir22YoBQgw,3942
13
+ smithy_python/model/_shapes.py,sha256=hzL0654EMxKkfOkOvd7OA6-d4JHhXz3r92XqRfoY1Mo,7603
14
+ smithy_python-0.1.0.dist-info/METADATA,sha256=t6rpLxKqChGqOajmHP_Uz8FuysD-zDxNFSl3tJG3spE,2128
15
+ smithy_python-0.1.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
16
+ smithy_python-0.1.0.dist-info/entry_points.txt,sha256=MbnKGy68WZXMhKsryaaGzekHxS8racdfA6mF5VS4QxI,57
17
+ smithy_python-0.1.0.dist-info/licenses/NOTICE,sha256=1CkO1kwu3Q_OHYTj-d-yiBJA_lNN73a4zSntavaD4oc,67
18
+ smithy_python-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ smithy-python = smithy_python.cli:main
@@ -0,0 +1 @@
1
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.