22Request details for a CLI Operation
33"""
44
5+ from openapi3 .schemas import Schema
6+
57from linodecli .baked .parsing import simplify_description
8+ from linodecli .baked .util import _aggregate_schema_properties
69
710
811class OpenAPIRequestArg :
@@ -134,66 +137,68 @@ def _parse_request_model(schema, prefix=None, parent=None, depth=0):
134137 """
135138 args = []
136139
137- if schema .properties is not None :
138- for k , v in schema .properties .items ():
139- if v .type == "object" and not v .readOnly and v .properties :
140- # nested objects receive a prefix and are otherwise parsed normally
141- pref = prefix + "." + k if prefix else k
142-
143- args += _parse_request_model (
144- v ,
145- prefix = pref ,
140+ properties , required = _aggregate_schema_properties (schema )
141+
142+ if properties is None :
143+ return args
144+
145+ for k , v in properties .items ():
146+ if (
147+ v .type == "object"
148+ and not v .readOnly
149+ and len (_aggregate_schema_properties (v )[0 ]) > 0
150+ ):
151+ # nested objects receive a prefix and are otherwise parsed normally
152+ pref = prefix + "." + k if prefix else k
153+
154+ args += _parse_request_model (
155+ v ,
156+ prefix = pref ,
157+ parent = parent ,
158+ # NOTE: We do not increment the depth because dicts do not have
159+ # parent arguments.
160+ depth = depth ,
161+ )
162+ elif (
163+ v .type == "array"
164+ and v .items
165+ and v .items .type == "object"
166+ and v .extensions .get ("linode-cli-format" ) != "json"
167+ ):
168+ # handle lists of objects as a special case, where each property
169+ # of the object in the list is its own argument
170+ pref = prefix + "." + k if prefix else k
171+
172+ # Support specifying this list as JSON
173+ args .append (
174+ OpenAPIRequestArg (
175+ k ,
176+ v .items ,
177+ False ,
178+ prefix = prefix ,
179+ is_parent = True ,
146180 parent = parent ,
147- # NOTE: We do not increment the depth because dicts do not have
148- # parent arguments.
149181 depth = depth ,
150182 )
151- elif (
152- v .type == "array"
153- and v .items
154- and v .items .type == "object"
155- and v .extensions .get ("linode-cli-format" ) != "json"
156- ):
157- # handle lists of objects as a special case, where each property
158- # of the object in the list is its own argument
159- pref = prefix + "." + k if prefix else k
160-
161- # Support specifying this list as JSON
162- args .append (
163- OpenAPIRequestArg (
164- k ,
165- v .items ,
166- False ,
167- prefix = prefix ,
168- is_parent = True ,
169- parent = parent ,
170- depth = depth ,
171- )
172- )
183+ )
173184
174- args += _parse_request_model (
175- v .items ,
176- prefix = pref ,
177- parent = pref ,
178- depth = depth + 1 ,
179- )
180- else :
181- # required fields are defined in the schema above the property, so
182- # we have to check here if required fields are defined/if this key
183- # is among them and pass it into the OpenAPIRequestArg class.
184- required = False
185- if schema .required :
186- required = k in schema .required
187- args .append (
188- OpenAPIRequestArg (
189- k ,
190- v ,
191- required ,
192- prefix = prefix ,
193- parent = parent ,
194- depth = depth ,
195- )
185+ args += _parse_request_model (
186+ v .items ,
187+ prefix = pref ,
188+ parent = pref ,
189+ depth = depth + 1 ,
190+ )
191+ else :
192+ args .append (
193+ OpenAPIRequestArg (
194+ k ,
195+ v ,
196+ k in required ,
197+ prefix = prefix ,
198+ parent = parent ,
199+ depth = depth ,
196200 )
201+ )
197202
198203 return args
199204
@@ -212,15 +217,35 @@ def __init__(self, request):
212217 :type request: openapi3.MediaType
213218 """
214219 self .required = request .schema .required
220+
215221 schema_override = request .extensions .get ("linode-cli-use-schema" )
222+
223+ schema = request .schema
224+
216225 if schema_override :
217226 override = type (request )(
218227 request .path , {"schema" : schema_override }, request ._root
219228 )
220229 override ._resolve_references ()
221- self .attrs = _parse_request_model (override .schema )
222- else :
223- self .attrs = _parse_request_model (request .schema )
230+ schema = override .schema
231+
232+ self .attrs = _parse_request_model (schema )
233+
234+ # attr_routes stores all attribute routes defined using oneOf.
235+ # For example, config-create uses one of to isolate HTTP, HTTPS, and TCP request attributes
236+ self .attr_routes = {}
237+
238+ if schema .oneOf is not None :
239+ for entry in schema .oneOf :
240+ entry_schema = Schema (schema .path , entry , request ._root )
241+ if entry_schema .title is None :
242+ raise ValueError (
243+ f"No title for oneOf entry in { schema .path } "
244+ )
245+
246+ self .attr_routes [entry_schema .title ] = _parse_request_model (
247+ entry_schema
248+ )
224249
225250
226251class OpenAPIFilteringRequest :
@@ -249,3 +274,6 @@ def __init__(self, response_model):
249274
250275 # actually parse out what we can filter by
251276 self .attrs = [c for c in response_model .attrs if c .filterable ]
277+
278+ # This doesn't apply since we're building from the response model
279+ self .attr_routes = {}
0 commit comments