diff --git a/src/mako/api/lib/mbuild.mako b/src/mako/api/lib/mbuild.mako index f48a775b801..71c14fb0a4d 100644 --- a/src/mako/api/lib/mbuild.mako +++ b/src/mako/api/lib/mbuild.mako @@ -11,7 +11,7 @@ DELEGATE_PROPERTY_NAME, struct_type_bounds_s, scope_url_to_variant, re_find_replacements, ADD_PARAM_FN, ADD_PARAM_MEDIA_EXAMPLE, upload_action_fn, METHODS_RESOURCE, method_name_to_variant, unique_type_name, size_to_bytes, method_default_scope, - is_repeated_property) + is_repeated_property, setter_fn_name) def get_parts(part_prop): if not part_prop: @@ -27,12 +27,6 @@ part_desc += ''.join('* *%s*\n' % part for part in parts) part_desc = part_desc[:-1] return part_desc - - def setter_fn_name(p): - fn_name = p.name - if is_repeated_property(p): - fn_name = 'add_' + fn_name - return fn_name %>\ <%namespace name="util" file="../../lib/util.mako"/>\ <%namespace name="lib" file="lib.mako"/>\ diff --git a/src/mako/cli/lib/engine.mako b/src/mako/cli/lib/engine.mako index e940ace6a19..6a6b7b05d9f 100644 --- a/src/mako/cli/lib/engine.mako +++ b/src/mako/cli/lib/engine.mako @@ -1,21 +1,28 @@ <%namespace name="util" file="../../lib/util.mako"/>\ <%! - from util import (hub_type, mangle_ident, indent_all_but_first_by, activity_rust_type) + from util import (hub_type, mangle_ident, indent_all_but_first_by, activity_rust_type, setter_fn_name) from cli import (mangle_subcommand, new_method_context, PARAM_FLAG, STRUCT_FLAG, UPLOAD_FLAG, OUTPUT_FLAG, VALUE_ARG, CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG, - cmd_ident, call_method_ident, arg_ident, POD_TYPES, flag_ident) + cmd_ident, call_method_ident, arg_ident, POD_TYPES, flag_ident, ident) v_arg = '<%s>' % VALUE_ARG SOPT = 'self.opt.' def to_opt_arg_ident(p): return SOPT + arg_ident(p.name) + + def borrow_prefix(p): + ptype = p.get('type', None) + borrow = '' + if ptype not in POD_TYPES or ptype in ('string', None): + borrow = '&' + return borrow %>\ <%def name="new(c)">\ <% hub_type_name = 'api::' + hub_type(c.schemas, util.canonical_name()) %>\ mod cmn; -use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts}; +use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg}; use std::default::Default; use std::str::FromStr; @@ -122,6 +129,7 @@ self.opt.${cmd_ident(method)} { <% mc = new_method_context(resource, method, c) handle_output = mc.response_schema or mc.m.get('supportsMediaDownload', False) + handle_props = mc.optional_props or parameters is not UNDEFINED %>\ ## REQUIRED PARAMETERS % for p in mc.required_props: @@ -141,17 +149,33 @@ let ${prop_name}: ${prop_type} = arg_from_str(&${opt_ident}, err, "<${mangle_sub for p in mc.required_props: borrow = '' # if type is not available, we know it's the request value, which should also be borrowed - ptype = p.get('type', None) - if ptype not in POD_TYPES or ptype in ('string', None): - borrow = '&' + borrow = borrow_prefix(p) arg_name = mangle_ident(p.name) - if ptype == 'string': + if p.get('type', '') == 'string': arg_name = to_opt_arg_ident(p) call_args.append(borrow + arg_name) # end for each required prop %>\ -let call = self.hub.${mangle_ident(resource)}().${mangle_ident(method)}(${', '.join(call_args)}); -## TODO: set parameters +let mut call = self.hub.${mangle_ident(resource)}().${mangle_ident(method)}(${', '.join(call_args)}); +% if handle_props: +<% + optional_props = [p for p in mc.optional_props if not p.get('skip_example', False)] +%>\ +for parg in ${SOPT + arg_ident(VALUE_ARG)}.iter() { + let (key, value) = parse_kv_arg(&*parg, err, "default"); + match key { +% for p in optional_props: + "${ident(p.name)}" => call = call.${mangle_ident(setter_fn_name(p))}(\ + % if p.type != 'string': +arg_from_str(value, err, "${ident(p.name)}", "${p.type}")), + % else: +value), + % endif # handle conversion +% endfor # each property + _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + } +} +% endif # handle call parameters ## TODO: parse upload if dry_run { None diff --git a/src/mako/lib/util.py b/src/mako/lib/util.py index 9d0b9d4bb42..46c14531a99 100644 --- a/src/mako/lib/util.py +++ b/src/mako/lib/util.py @@ -551,6 +551,12 @@ def is_required_property(p): def is_repeated_property(p): return p.get('repeated', False) +def setter_fn_name(p): + fn_name = p.name + if is_repeated_property(p): + fn_name = 'add_' + fn_name + return fn_name + # method_params(...), request_value|None -> (required_properties, optional_properties, part_prop|None) def organize_params(params, request_value): part_prop = None diff --git a/src/rust/cli/cmn.rs b/src/rust/cli/cmn.rs index d319ad170a8..12b5eedcf21 100644 --- a/src/rust/cli/cmn.rs +++ b/src/rust/cli/cmn.rs @@ -12,6 +12,25 @@ use std::io::{Write, Read, stdout}; use std::default::Default; +pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, default: &'static str) + -> (&'a str, &'a str) { + let mut add_err = || err.issues.push(CLIError::InvalidKeyValueSyntax(kv.to_string())); + match kv.rfind('=') { + None => { + add_err(); + return (kv, default) + }, + Some(pos) => { + let key = &kv[..pos]; + if kv.len() <= pos + 1 { + add_err(); + return (key, default) + } + (key, &kv[pos+1..]) + } + } +} + // May panic if we can't open the file - this is anticipated, we can't currently communicate this // kind of error: TODO: fix this architecture :) pub fn writer_from_opts(flag: bool, arg: &str) -> Box { @@ -31,7 +50,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, format!("{}", perr))) + CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) ); Default::default() }, @@ -122,16 +141,23 @@ impl fmt::Display for ConfigurationError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String)), + ParseError((&'static str, &'static str, String, String)), + UnknownParameter(String), + InvalidKeyValueSyntax(String), } impl fmt::Display for CLIError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { CLIError::Configuration(ref err) => writeln!(f, "Configuration -> {}", err), - CLIError::ParseError((arg_name, type_name, ref err_desc)) - => writeln!(f, "Failed to parse argument {} as {} with error: {}", - arg_name, type_name, err_desc), + CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + arg_name, value, type_name, err_desc), + CLIError::UnknownParameter(ref param_name) + => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::InvalidKeyValueSyntax(ref kv) + => writeln!(f, "'{}' does not match =", kv), + } } }