Skip to content

Commit fa278a9

Browse files
committed
fix(CLI): request value parsing compiles and inits
Therefore, you can now actually make the call and the program will not crash due to uninitialized Options. Fixes #64
1 parent bf22bef commit fa278a9

1 file changed

Lines changed: 46 additions & 10 deletions

File tree

src/mako/cli/lib/engine.mako

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<%namespace name="util" file="../../lib/util.mako"/>\
22
<%!
33
from util import (hub_type, mangle_ident, indent_all_but_first_by, activity_rust_type, setter_fn_name, ADD_PARAM_FN,
4-
upload_action_fn, is_schema_with_optionals, schema_markers)
4+
upload_action_fn, is_schema_with_optionals, schema_markers, indent_by)
55
from cli import (mangle_subcommand, new_method_context, PARAM_FLAG, STRUCT_FLAG, UPLOAD_FLAG, OUTPUT_FLAG, VALUE_ARG,
66
CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG,
77
cmd_ident, call_method_ident, arg_ident, POD_TYPES, flag_ident, ident, JSON_TYPE_VALUE_MAP,
@@ -148,6 +148,8 @@ self.opt.${cmd_ident(method)} {
148148
handle_props = optional_props or parameters is not UNDEFINED
149149
if mc.request_value:
150150
request_cli_schema = to_cli_schema(c, mc.request_value)
151+
152+
request_prop_type = None
151153
%>\
152154
## REQUIRED PARAMETERS
153155
% for p in mc.required_props:
@@ -157,6 +159,7 @@ self.opt.${cmd_ident(method)} {
157159
opt_ident = to_opt_arg_ident(p)
158160
%>\
159161
% if is_request_value_property(mc, p):
162+
<% request_prop_type = prop_type %>\
160163
let mut ${prop_name}: api::${prop_type} = Default::default();
161164
% elif p.type != 'string':
162165
let ${prop_name}: ${prop_type} = arg_from_str(&${opt_ident}, err, "<${mangle_subcommand(p.name)}>", "${p.type}");
@@ -240,36 +243,60 @@ ${value_unwrap}\
240243
<%
241244
allow_optionals_fn = lambda s: is_schema_with_optionals(schema_markers(s, c, transitive=False))
242245
243-
def flatten_schema_fields(schema, res, cur=list()):
246+
def flatten_schema_fields(schema, res, init_fn_map, cur=list(), init_call=None):
244247
if len(cur) == 0:
248+
init_call = ''
245249
cur = list()
246250
247251
opt_access = '.as_mut().unwrap()'
248-
if not allow_optionals_fn(schema):
252+
allow_optionals = allow_optionals_fn(schema)
253+
parent_init_call = init_call
254+
if not allow_optionals:
249255
opt_access = ''
250256
for fn, f in schema.fields.iteritems():
251-
252257
cur.append(['%s%s' % (mangle_ident(fn), opt_access), fn])
253258
if isinstance(f, SchemaEntry):
254259
cur[-1][0] = mangle_ident(fn)
255-
res.append((schema, f, list(cur)))
260+
res.append((init_call, schema, f, list(cur)))
256261
else:
257-
flatten_schema_fields(f, res, cur)
262+
if allow_optionals:
263+
init_fn_name = 'request_%s_init' % '_'.join(mangle_ident(t[1]) for t in cur)
264+
init_call = init_fn_name + '(&mut request);'
265+
struct_field = 'request.' + '.'.join('%s%s' % (mangle_ident(t[1]), opt_access) for t in cur[:-1])
266+
if len(cur) > 1:
267+
struct_field += '.'
268+
struct_field += mangle_ident(cur[-1][1])
269+
init_fn = "fn %s(request: &mut api::%s) {\n" % (init_fn_name, request_prop_type)
270+
if parent_init_call:
271+
pcall = parent_init_call[:parent_init_call.index('(')] + "(request)"
272+
init_fn += " %s;\n" % pcall
273+
init_fn += " if %s.is_none() {\n" % struct_field
274+
init_fn += " %s = Some(Default::default());\n" % struct_field
275+
init_fn += " }\n"
276+
init_fn += "}\n"
277+
278+
init_fn_map[init_fn_name] = init_fn
279+
# end handle init
280+
flatten_schema_fields(f, res, init_fn_map, cur, init_call)
258281
cur.pop()
259282
# endfor
260283
# end utility
261284
262285
schema_fields = list()
263-
flatten_schema_fields(request_cli_schema, schema_fields)
286+
init_fn_map = dict()
287+
flatten_schema_fields(request_cli_schema, schema_fields, init_fn_map)
264288
%>\
265289
let mut field_name: FieldCursor = Default::default();
266290
for kvarg in ${SOPT + arg_ident(KEY_VALUE_ARG)}.iter() {
267291
let (key, value) = parse_kv_arg(&*kvarg, err);
268292
if let Err(field_err) = field_name.set(&*key) {
269293
err.issues.push(field_err);
270294
}
295+
% for name in sorted(init_fn_map.keys()):
296+
${init_fn_map[name] | indent_by(4)}
297+
% endfor
271298
match &field_name.to_string()[..] {
272-
% for schema, fe, f in schema_fields:
299+
% for init_call, schema, fe, f in schema_fields:
273300
<%
274301
# TODO: Deduplicate !
275302
ptype = fe.actual_property.type
@@ -281,16 +308,25 @@ for kvarg in ${SOPT + arg_ident(KEY_VALUE_ARG)}.iter() {
281308
allow_optionals = True
282309
opt_prefix = 'Some('
283310
opt_suffix = ')'
311+
opt_access = '.as_mut().unwrap()'
284312
if not allow_optionals_fn(schema):
285-
opt_prefix = opt_suffix = ''
313+
opt_prefix = opt_suffix = opt_access = ''
286314
287315
struct_field = 'request.' + '.'.join(t[0] for t in f)
288316
%>\
289317
"${pname}" => {
318+
% if init_call:
319+
${init_call}
320+
% endif
290321
% if fe.container_type == CTYPE_POD:
291322
${struct_field} = ${opt_prefix}\
292323
% else:
293-
${struct_field}.push(\
324+
% if opt_prefix:
325+
if ${struct_field}.is_none() {
326+
${struct_field} = Some(Default::default());
327+
}
328+
% endif
329+
${struct_field}${opt_access}.push(\
294330
% endif
295331
% if ptype != 'string':
296332
arg_from_str(${value_unwrap}, err, "${pname}", "${ptype}")\

0 commit comments

Comments
 (0)