Skip to content

Commit

Permalink
feat(CLI): hashmap handling
Browse files Browse the repository at this point in the history
* with native support for type conversion and error handling
* improved hash-map key-value parsing to at least state that it knows
  it's dealing with a hashmap. Error text is still not what it should
  be because we don't know at runtime (initially) what type we handle.

Fixes #68
Related to #77
  • Loading branch information
Byron committed Apr 22, 2015
1 parent c14ef9a commit b830c1c
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 21 deletions.
32 changes: 18 additions & 14 deletions src/mako/cli/lib/engine.mako
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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, ident, JSON_TYPE_VALUE_MAP,
KEY_VALUE_ARG, to_cli_schema, SchemaEntry, CTYPE_POD, actual_json_type)
KEY_VALUE_ARG, to_cli_schema, SchemaEntry, CTYPE_POD, actual_json_type, CTYPE_MAP)
v_arg = '<%s>' % VALUE_ARG
SOPT = 'self.opt.'
Expand Down Expand Up @@ -172,7 +172,7 @@ if opt.flag_${flag_name} {
opt_ident = to_opt_arg_ident(p)
%>\
% if is_request_value_property(mc, p):
<% request_prop_type = prop_type %>\
<% request_prop_type = prop_type %>\
let mut ${prop_name} = api::${prop_type}::default();
% elif p.type != 'string':
% if p.get('repeated', False):
Expand Down Expand Up @@ -203,7 +203,7 @@ let mut download_mode = false;
let mut call = self.hub.${mangle_ident(resource)}().${mangle_ident(method)}(${', '.join(call_args)});
% if handle_props:
for parg in ${SOPT + arg_ident(VALUE_ARG)}.iter() {
let (key, value) = parse_kv_arg(&*parg, err);
let (key, value) = parse_kv_arg(&*parg, err, false);
match key {
% for p in optional_props:
<%
Expand Down Expand Up @@ -379,7 +379,7 @@ if dry_run {
%>\
let mut field_name = FieldCursor::default();
for kvarg in ${SOPT + arg_ident(KEY_VALUE_ARG)}.iter() {
let (key, value) = parse_kv_arg(&*kvarg, err);
let (key, value) = parse_kv_arg(&*kvarg, err, false);
if let Err(field_err) = field_name.set(&*key) {
err.issues.push(field_err);
}
Expand All @@ -396,26 +396,30 @@ ${init_fn_map[name] | indent_by(4)}
allow_optionals = True
opt_prefix = 'Some('
opt_suffix = ')'
struct_field = 'request.' + '.'.join(t[0] for t in f)
opt_init = 'if ' + struct_field + '.is_none() {\n'
opt_init += ' ' + struct_field + ' = Some(Default::default());\n'
opt_init += '}\n'
opt_access = '.as_mut().unwrap()'
if not allow_optionals_fn(schema):
opt_prefix = opt_suffix = opt_access = ''
struct_field = 'request.' + '.'.join(t[0] for t in f)
opt_prefix = opt_suffix = opt_access = opt_init = ''
%>\
"${pname}" => {
% if init_call:
${init_call}
% endif
% if fe.container_type == CTYPE_POD:
${struct_field} = ${opt_prefix}\
% else:
% if opt_prefix:
if ${struct_field}.is_none() {
${struct_field} = Some(Default::default());
}
% endif
% elif fe.container_type == CTYPE_ARRAY:
${opt_init | indent_all_but_first_by(4)}\
${struct_field}${opt_access}.push(\
% endif
% elif fe.container_type == CTYPE_MAP:
${opt_init | indent_all_but_first_by(4)}\
let (key, value) = parse_kv_arg(${value_unwrap}, err, true);
${struct_field}${opt_access}.insert(key.to_string(), \
% endif # container type handling
% if ptype != 'string':
arg_from_str(${value_unwrap}, err, "${pname}", "${ptype}")\
% else:
Expand Down
15 changes: 8 additions & 7 deletions src/rust/cli/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ impl FieldCursor {
}
}

pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError)
pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: bool)
-> (&'a str, Option<&'a str>) {
let mut add_err = || err.issues.push(CLIError::InvalidKeyValueSyntax(kv.to_string()));
match kv.rfind('=') {
let mut add_err = || err.issues.push(CLIError::InvalidKeyValueSyntax(kv.to_string(),for_hashmap));
match kv.find('=') {
None => {
add_err();
return (kv, None)
Expand Down Expand Up @@ -284,7 +284,7 @@ pub enum CLIError {
Configuration(ConfigurationError),
ParseError((&'static str, &'static str, String, String)),
UnknownParameter(String),
InvalidKeyValueSyntax(String),
InvalidKeyValueSyntax(String, bool),
Input(InputError),
Field(FieldError),
}
Expand All @@ -300,9 +300,10 @@ impl fmt::Display for CLIError {
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 pattern <key>=<value>", kv),

CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => {
let hashmap_info = if is_hashmap { "hashmap " } else { "" };
writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info)
},
}
}
}
Expand Down

0 comments on commit b830c1c

Please sign in to comment.