1212from typing import BinaryIO , Final
1313
1414from . import __version__
15+ from . import dependencies as _dependencies
16+ from . import files as _files
17+ from . import generation as _generation
18+ from . import model as _model
19+ from . import models as _models
20+ from . import selection as _selection
21+ from . import symbols as _symbols
22+ from . import types as _types
1523from .environment import PluginEnvironment
16- from .exceptions import CodegenError , InvalidInvocationError
17- from .model import load_model
18- from .selection import select_shapes
24+ from .exceptions import (
25+ CodegenError ,
26+ InvalidInvocationError ,
27+ SelectorSyntaxError ,
28+ )
1929
2030__all__ = ["main" ]
2131
2636
2737@dataclass (frozen = True , slots = True )
2838class _Invocation :
29- artifact : str
3039 model_source : bytes
3140 output_dir : Path
32- environment : PluginEnvironment
3341
3442
3543def main (
@@ -48,32 +56,29 @@ def main(
4856
4957 try :
5058 invocation = _resolve_invocation (args , environ = environ , stdin = stdin )
59+ model = _model .load_model (invocation .model_source )
60+ if args .artifact == "types" :
61+ selection = _generate_types (args , invocation .output_dir , model )
62+ else :
63+ selection = _selection .select_shapes (
64+ model ,
65+ service_id = args .service ,
66+ require_service = True ,
67+ )
5168 except InvalidInvocationError as error :
5269 sys .stderr .write (f"smithy-python: error: { error } \n " )
5370 return 2
5471 except (CodegenError , OSError ) as error :
5572 sys .stderr .write (f"smithy-python: error: { error } \n " )
5673 return 1
5774
58- try :
59- model = load_model (invocation .model_source )
60- selection = select_shapes (
61- model ,
62- service_id = args .service ,
63- require_service = invocation .artifact == "client" ,
64- )
65- except InvalidInvocationError as error :
66- sys .stderr .write (f"smithy-python: error: { error } \n " )
67- return 2
68- except CodegenError as error :
69- sys .stderr .write (f"smithy-python: error: { error } \n " )
70- return 1
71-
7275 if selection .excluded_count and selection .service is not None :
7376 sys .stderr .write (
7477 f"smithy-python: excluded { selection .excluded_count } eligible data shape(s) "
7578 f"outside the closure of service { selection .service .id } \n "
7679 )
80+ if args .artifact == "types" :
81+ return 0
7782 sys .stderr .write (_GENERATION_NOT_IMPLEMENTED .format (artifact = args .artifact ))
7883 return 1
7984
@@ -93,11 +98,36 @@ def _create_parser() -> argparse.ArgumentParser:
9398 generate = commands .add_parser ("generate" , help = "Generate Python source" )
9499 artifacts = generate .add_subparsers (dest = "artifact" , required = True )
95100 common = _common_artifact_options ()
96- for name , help_text in (
97- ("client" , "Generate a client package" ),
98- ("types" , "Generate a standalone types package" ),
99- ):
100- artifacts .add_parser (name , help = help_text , parents = [common ])
101+ artifacts .add_parser ("client" , help = "Generate a client package" , parents = [common ])
102+ types = artifacts .add_parser (
103+ "types" , help = "Generate a standalone types package" , parents = [common ]
104+ )
105+ types .add_argument (
106+ "--package" ,
107+ required = True ,
108+ help = "Import package and distribution name for the generated artifact." ,
109+ )
110+ types .add_argument (
111+ "--package-version" ,
112+ required = True ,
113+ type = _non_empty ,
114+ help = "Version for the generated package." ,
115+ )
116+ types .add_argument (
117+ "--package-description" ,
118+ help = 'Package description; defaults to "<package> types package".' ,
119+ )
120+ types .add_argument (
121+ "--selector" ,
122+ type = _parse_selector ,
123+ default = _selection .Selector .identity (),
124+ help = "Smithy selector used to narrow generated declaration roots." ,
125+ )
126+ types .add_argument (
127+ "--generate-inputs-and-outputs" ,
128+ action = "store_true" ,
129+ help = "Include operation input and output structures as generation roots." ,
130+ )
101131
102132 return parser
103133
@@ -175,8 +205,65 @@ def _resolve_invocation(
175205 raise InvalidInvocationError ("Expected a Smithy JSON AST model" )
176206
177207 return _Invocation (
178- artifact = args .artifact ,
179208 model_source = model_source ,
180209 output_dir = output_dir ,
181- environment = environment ,
182210 )
211+
212+
213+ def _generate_types (
214+ args : argparse .Namespace ,
215+ output_dir : Path ,
216+ model : _model .Model ,
217+ ) -> _selection .Selection :
218+ description = args .package_description or f"{ args .package } types package"
219+ settings = _generation .TypesSettings (
220+ package = args .package ,
221+ package_version = args .package_version ,
222+ package_description = description ,
223+ selector = args .selector ,
224+ generate_inputs_and_outputs = args .generate_inputs_and_outputs ,
225+ )
226+ selection = _selection .select_type_shapes (
227+ model ,
228+ service_id = args .service ,
229+ selector = settings .selector ,
230+ generate_inputs_and_outputs = settings .generate_inputs_and_outputs ,
231+ )
232+ try :
233+ symbols = _symbols .SymbolProvider (
234+ model ,
235+ selection ,
236+ package = settings .package ,
237+ reserved_member_names = _models ._model_reserved_member_names ( # pyright: ignore[reportPrivateUsage]
238+ model
239+ ),
240+ )
241+ except ValueError as error :
242+ raise InvalidInvocationError (str (error )) from error
243+
244+ dependencies = _dependencies .DependencySet ()
245+ context = _generation .GenerationContext (
246+ model = model ,
247+ selection = selection ,
248+ settings = settings ,
249+ symbols = symbols ,
250+ plan = _generation .GenerationPlan .from_selection (model , selection , symbols ),
251+ dependencies = dependencies ,
252+ files = _files .FileManifest (dependencies ),
253+ )
254+ _types .TypesGenerator ().generate (context )
255+ context .files .commit (output_dir )
256+ return selection
257+
258+
259+ def _parse_selector (value : str ) -> _selection .Selector :
260+ try :
261+ return _selection .Selector .parse (value )
262+ except SelectorSyntaxError as error :
263+ raise argparse .ArgumentTypeError (str (error )) from error
264+
265+
266+ def _non_empty (value : str ) -> str :
267+ if not value :
268+ raise argparse .ArgumentTypeError ("expected a non-empty value" )
269+ return value
0 commit comments