diff --git a/etc/api/type-cli.yaml b/etc/api/type-cli.yaml index b24978eeb8c..c0be0a3b189 100644 --- a/etc/api/type-cli.yaml +++ b/etc/api/type-cli.yaml @@ -28,4 +28,4 @@ cargo: dependencies: - strsim = "0.4" - yup-hyper-mock = "1.0" - - clap = "1.5" + - clap = "2.0" diff --git a/src/mako/cli/lib/argparse.mako b/src/mako/cli/lib/argparse.mako index 3aed9da168f..914af44b676 100644 --- a/src/mako/cli/lib/argparse.mako +++ b/src/mako/cli/lib/argparse.mako @@ -4,8 +4,8 @@ from util import (put_and, supports_scopes, api_index, indent_by, enclose_in, put_and) 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, - CONFIG_DIR_FLAG, KEY_VALUE_ARG, to_docopt_arg, DEBUG_FLAG, DEBUG_AUTH_FLAG, MODE_ARG, SCOPE_ARG, + CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG, + CONFIG_DIR_FLAG, KEY_VALUE_ARG, to_docopt_arg, DEBUG_FLAG, DEBUG_AUTH_FLAG, MODE_ARG, SCOPE_ARG, CONFIG_DIR_ARG, FILE_FLAG, MIME_FLAG, subcommand_md_filename) def rust_boolean(v): @@ -50,7 +50,7 @@ ${util.program_name()} [options] if mc.optional_props or parameters is not UNDEFINED: args.append('[-%s %s]...' % (PARAM_FLAG, '<%s>' % VALUE_ARG)) # end paramters - + if mc.response_schema or mc.m.get('supportsMediaDownload', False): args.append('[-%s <%s>]' % (OUTPUT_FLAG, OUT_ARG)) # handle output @@ -63,19 +63,19 @@ ${util.program_name()} [options] Configuration: % if supports_scopes(auth): [--${SCOPE_FLAG} <${SCOPE_ARG}>]... - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + Specify the authentication a method should be executed in. Each scope + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. % endif scopes --${CONFIG_DIR_FLAG} <${CONFIG_DIR_ARG}> - A directory into which we will store our persistent data. Defaults to + A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation. [default: ${CONFIG_DIR}] --${DEBUG_FLAG} - Output all server communication to standard error. `tx` and `rx` are placed + Output all server communication to standard error. `tx` and `rx` are placed into the same stream. --${DEBUG_AUTH_FLAG} - Output all communication related to authentication to standard error. `tx` + Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream. @@ -83,7 +83,7 @@ Configuration: <%def name="new(c)" buffered="True">\ <% - doc_url_base = cargo.doc_base_url + '/' + os.path.dirname(api_index(cargo.doc_base_url, name, + doc_url_base = cargo.doc_base_url + '/' + os.path.dirname(api_index(cargo.doc_base_url, name, version, make, check_exists=False)) url_info = "All documentation details can be found at " + doc_url_base @@ -113,7 +113,7 @@ Configuration: )) global_args.append(( - DEBUG_FLAG, + DEBUG_FLAG, "Output all server communication to standard error. `tx` and `rx` are placed " "into the same stream.", None, @@ -145,7 +145,7 @@ let upload_value_names = ["${MODE_ARG}", "${FILE_ARG}"]; % endif let arg_data = [ % for resource in sorted(c.rta_map.keys()): -<% +<% methods = sorted(c.rta_map[resource]) %>\ <%block filter="indent_by(4)">\ @@ -202,7 +202,7 @@ let arg_data = [ True, )) # end paramters - + if mc.response_schema or mc.m.get('supportsMediaDownload', False): args.append(( OUTPUT_FLAG, @@ -213,7 +213,7 @@ let arg_data = [ )) # handle output %>\ - ("${mangle_subcommand(method)}", + ("${mangle_subcommand(method)}", ${rust_optional(mc.m.get('description'))}, "Details at ${doc_url_base}/${os.path.splitext(subcommand_md_filename(resource, method))[0]}", vec![ @@ -255,7 +255,7 @@ let mut app = App::new("${util.program_name()}") % endif % endfor -for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { +for &(main_command_name, about, ref subcommands) in arg_data.iter() { let mut mcmd = SubCommand::with_name(main_command_name).about(about); for &(sub_command_name, ref desc, url_info, ref args) in subcommands { @@ -266,7 +266,7 @@ for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { scmd = scmd.after_help(url_info); for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { - let arg_name_str = + let arg_name_str = match (arg_name, flag) { (&Some(an), _ ) => an, (_ , &Some(f)) => f, @@ -309,4 +309,4 @@ for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { app = app.subcommand(mcmd); } - \ No newline at end of file + diff --git a/src/mako/cli/lib/cli.py b/src/mako/cli/lib/cli.py index 4b99468a57e..d478db304ce 100644 --- a/src/mako/cli/lib/cli.py +++ b/src/mako/cli/lib/cli.py @@ -39,8 +39,8 @@ re_splitters = re.compile(r"%s ([\w\-\.]+)\n(.*?)\n%s" % (SPLIT_START, SPLIT_END), re.MULTILINE|re.DOTALL) -MethodContext = collections.namedtuple('MethodContext', ['m', 'response_schema', 'params', 'request_value', - 'media_params' ,'required_props', 'optional_props', +MethodContext = collections.namedtuple('MethodContext', ['m', 'response_schema', 'params', 'request_value', + 'media_params' ,'required_props', 'optional_props', 'part_prop']) CTYPE_POD = 'pod' @@ -93,9 +93,9 @@ def new_method_context(resource, method, c): response_schema = util.method_response(c, m) params, request_value = util.build_all_params(c, m) media_params = util.method_media_params(m) - required_props, optional_props, part_prop = util.organize_params(params, request_value) + required_props, optional_props, part_prop = util.organize_params(params, request_value) - return MethodContext(m, response_schema, params, request_value, media_params, + return MethodContext(m, response_schema, params, request_value, media_params, required_props, optional_props, part_prop) def comma_sep_fields(fields): @@ -129,7 +129,7 @@ def opt_value(name, opt='opt', default=''): return opt + '.value_of("' + mangle_subcommand(name) + ('").unwrap_or("%s")' % default) def opt_values(name, opt='opt'): - return opt + '.values_of("' + mangle_subcommand(name) + '").unwrap_or(Vec::new()).iter()' + return opt + '.values_of("' + mangle_subcommand(name) + '").map(|i|i.collect()).unwrap_or(Vec::new()).iter()' def application_secret_path(program_name): return program_name + '-secret.json' @@ -149,7 +149,7 @@ def docopt_mode(protocols): return mode # Returns a possibly remapped type, based on its name. -# Useful to map strings to more suitable types, i.e. counts +# Useful to map strings to more suitable types, i.e. counts def actual_json_type(name, type): if type == 'string' and 'Count' in name: return 'int64' @@ -209,7 +209,7 @@ def dup_property(): return res -# Convert the given cli-schema (result from to_cli_schema(schema)) to a yaml-like string. It's suitable for +# Convert the given cli-schema (result from to_cli_schema(schema)) to a yaml-like string. It's suitable for # documentation only def cli_schema_to_yaml(schema, prefix=''): if not prefix: diff --git a/src/mako/cli/lib/engine.mako b/src/mako/cli/lib/engine.mako index 23c73807744..7cfe9c796f5 100644 --- a/src/mako/cli/lib/engine.mako +++ b/src/mako/cli/lib/engine.mako @@ -4,11 +4,11 @@ upload_action_fn, is_schema_with_optionals, schema_markers, indent_by, method_default_scope, ADD_SCOPE_FN, TREF, enclose_in) from cli import (mangle_subcommand, new_method_context, PARAM_FLAG, STRUCT_FLAG, OUTPUT_FLAG, VALUE_ARG, - CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG, + CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG, call_method_ident, POD_TYPES, opt_value, ident, JSON_TYPE_VALUE_MAP, KEY_VALUE_ARG, to_cli_schema, SchemaEntry, CTYPE_POD, actual_json_type, CTYPE_MAP, CTYPE_ARRAY, - application_secret_path, DEBUG_FLAG, DEBUG_AUTH_FLAG, CONFIG_DIR_FLAG, req_value, MODE_ARG, - opt_values, SCOPE_ARG, CONFIG_DIR_ARG, DEFAULT_MIME, field_vec, comma_sep_fields, JSON_TYPE_TO_ENUM_MAP, + application_secret_path, DEBUG_FLAG, DEBUG_AUTH_FLAG, CONFIG_DIR_FLAG, req_value, MODE_ARG, + opt_values, SCOPE_ARG, CONFIG_DIR_ARG, DEFAULT_MIME, field_vec, comma_sep_fields, JSON_TYPE_TO_ENUM_MAP, CTYPE_TO_ENUM_MAP) v_arg = '<%s>' % VALUE_ARG @@ -31,7 +31,7 @@ <% hub_type_name = 'api::' + hub_type(c.schemas, util.canonical_name()) %>\ -use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, +use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, calltype_from_str, remove_json_null_values, ComplexType, JsonType, JsonTypeInfo}; @@ -47,24 +47,24 @@ enum DoitError { ApiError(api::Error), } -struct Engine<'n, 'a> { - opt: ArgMatches<'n, 'a>, +struct Engine<'n> { + opt: ArgMatches<'n>, hub: ${hub_type_name}>, gp: ${"Vec<&'static str>"}, gpm: Vec<(&'static str, &'static str)>, } -impl<'n, 'a> Engine<'n, 'a> { +impl<'n> Engine<'n> { % for resource in sorted(c.rta_map.keys()): % for method in sorted(c.rta_map[resource]): - fn ${call_method_ident(resource, method)}(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + fn ${call_method_ident(resource, method)}(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError) -> Result<(), DoitError> { ${self._method_call_impl(c, resource, method) | indent_all_but_first_by(2)} } % endfor # each method -% endfor +% endfor fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); let mut call_result: Result<(), DoitError> = Ok(()); @@ -103,14 +103,14 @@ impl<'n, 'a> Engine<'n, 'a> { } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { + fn new(opt: ArgMatches<'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { let config_dir = match cmn::assure_config_dir_exists(opt.value_of("${CONFIG_DIR_ARG}").unwrap_or("${CONFIG_DIR}")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; - match cmn::application_secret_from_directory(&config_dir, "${application_secret_path(util.program_name())}", + match cmn::application_secret_from_directory(&config_dir, "${application_secret_path(util.program_name())}", "${api.credentials.replace('"', r'\"')}") { Ok(secret) => (config_dir, secret), Err(e) => return Err(InvalidOptionsError::single(e, 4)) @@ -124,7 +124,7 @@ impl<'n, 'a> Engine<'n, 'a> { db_dir: config_dir.clone(), }, None); - let client = + let client = ${self._debug_client(DEBUG_FLAG) | indent_all_but_first_by(3)}; <% gpm = gen_global_parameter_names(parameters) %>\ let engine = Engine { @@ -173,7 +173,7 @@ if opt.is_present("${flag_name}") { optional_prop_names = set(p.name for p in optional_props) track_download_flag = (not mc.media_params and - supports_media_download and + supports_media_download and (parameters is not UNDEFINED and 'alt' in parameters) or ('alt' in optional_prop_names)) handle_props = optional_props or parameters is not UNDEFINED if mc.request_value: @@ -184,7 +184,7 @@ if opt.is_present("${flag_name}") { %>\ ## REQUIRED PARAMETERS % for p in mc.required_props: -<% +<% prop_name = mangle_ident(p.name) prop_type = activity_rust_type(c.schemas, p, allow_optionals=False) %>\ @@ -192,7 +192,7 @@ if opt.is_present("${flag_name}") { <% request_prop_type = prop_type %>\ ${self._request_value_impl(c, request_cli_schema, prop_name, request_prop_type)}\ % elif p.type != 'string': - % if p.get('repeated', False): + % if p.get('repeated', False): let ${prop_name}: Vec<${prop_type} = Vec::new(); for (arg_id, arg) in ${opt_values(mangle_subcommand(p.name))}.enumerate() { ${prop_name}.push(arg_from_str(&arg, err, "<${mangle_subcommand(p.name)}>", arg_id), "${p.type}")); @@ -226,7 +226,7 @@ for parg in ${opt_values(VALUE_ARG)} { let (key, value) = parse_kv_arg(&*parg, err, false); match key { % for p in optional_props: -<% +<% ptype = actual_json_type(p.name, p.type) value_unwrap = 'value.unwrap_or("%s")' % JSON_TYPE_VALUE_MAP[ptype] %>\ @@ -263,7 +263,7 @@ ${value_unwrap}\ } } if !found { - err.issues.push(CLIError::UnknownParameter(key.to_string(), + err.issues.push(CLIError::UnknownParameter(key.to_string(), {let mut v = Vec::new(); v.extend(self.gp.iter().map(|v|*v)); % if comma_sep_fields(optional_prop_names): @@ -276,7 +276,7 @@ ${value_unwrap}\ } % endif # handle call parameters % if mc.media_params: -let vals = opt.values_of("${MODE_ARG}").unwrap(); +let vals = opt.values_of("${MODE_ARG}").unwrap().collect::>(); let protocol = calltype_from_str(vals[0], [${', '.join('"%s"' % mp.protocol for mp in mc.media_params)}].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(${opt_value(MIME_ARG, default=DEFAULT_MIME)}, err); @@ -390,10 +390,10 @@ for kvarg in ${opt_values(KEY_VALUE_ARG)} { } continue; } - + ## This type-annotation is not required in nightly (or newer rustc) ## TODO(ST): try to remove it once there is a newer stable - let type_info: Option<(&'static str, JsonTypeInfo)> = + let type_info: Option<(&'static str, JsonTypeInfo)> = match &temp_cursor.to_string()[..] { % for schema, fe, f in schema_fields: <% @@ -416,4 +416,4 @@ for kvarg in ${opt_values(KEY_VALUE_ARG)} { } } let mut ${request_prop_name}: api::${request_prop_type} = json::value::from_value(object).unwrap(); - \ No newline at end of file +