mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2026-01-07 03:56:42 +01:00
fix(clap): adjust option usage to changed API
Discovery API now builds and seems to work even ! More testing will have to be done though to be sure. Related #81
This commit is contained in:
@@ -91,16 +91,12 @@ def mangle_subcommand(name):
|
||||
def ident(name):
|
||||
return mangle_subcommand(name).replace('-', '_')
|
||||
|
||||
# return the identifier of a command for the given name, suitable to address the command field in the docopt structure
|
||||
def cmd_ident(name):
|
||||
return 'cmd_' + ident(name)
|
||||
|
||||
# Similar to cmd_ident, but for arguments
|
||||
def arg_ident(name):
|
||||
return 'arg_' + ident(name)
|
||||
return opt_value(name)
|
||||
|
||||
def flag_ident(name):
|
||||
return 'flag_' + ident(name)
|
||||
def opt_value(name, opt='opt'):
|
||||
return opt + '.value_of("' + mangle_subcommand(name) + '").unwrap_or("")'
|
||||
|
||||
def application_secret_path(program_name):
|
||||
return program_name + '-secret.json'
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
ADD_SCOPE_FN, TREF)
|
||||
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,
|
||||
call_method_ident, arg_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)
|
||||
application_secret_path, DEBUG_FLAG, DEBUG_AUTH_FLAG, CONFIG_DIR_FLAG)
|
||||
|
||||
v_arg = '<%s>' % VALUE_ARG
|
||||
SOPT = 'self.opt.'
|
||||
SOPT = 'self.opt'
|
||||
def to_opt_arg_ident(p):
|
||||
return SOPT + arg_ident(p.name)
|
||||
return opt_value(p.name)
|
||||
|
||||
def borrow_prefix(p):
|
||||
ptype = p.get('type', None)
|
||||
borrow = ''
|
||||
if (ptype not in POD_TYPES or ptype in ('string', None) or p.get('repeated', False)) and ptype is not None:
|
||||
if (ptype not in POD_TYPES or ptype is None or p.get('repeated', False)) and ptype is not None:
|
||||
borrow = '&'
|
||||
return borrow
|
||||
|
||||
@@ -35,17 +35,18 @@ use std::str::FromStr;
|
||||
|
||||
use oauth2::{Authenticator, DefaultAuthenticatorDelegate};
|
||||
use rustc_serialize::json;
|
||||
use clap::ArgMatches;
|
||||
|
||||
struct Engine {
|
||||
opt: Options,
|
||||
struct Engine<'n, 'a> {
|
||||
opt: ArgMatches<'n, 'a>,
|
||||
hub: ${hub_type_name}<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>,
|
||||
}
|
||||
|
||||
|
||||
impl Engine {
|
||||
impl<'n, 'a> Engine<'n, 'a> {
|
||||
% for resource in sorted(c.rta_map.keys()):
|
||||
% for method in sorted(c.rta_map[resource]):
|
||||
fn ${call_method_ident(resource, method)}(&self, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
fn ${call_method_ident(resource, method)}(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Option<api::Error> {
|
||||
${self._method_call_impl(c, resource, method) | indent_all_but_first_by(2)}
|
||||
}
|
||||
@@ -54,35 +55,27 @@ impl Engine {
|
||||
% endfor
|
||||
fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) {
|
||||
let mut err = InvalidOptionsError::new();
|
||||
let mut call_result: Option<api::Error>;
|
||||
let mut call_result: Option<api::Error> = None;
|
||||
let mut err_opt: Option<InvalidOptionsError> = None;
|
||||
## RESOURCE LOOP: check for set primary subcommand
|
||||
match ${SOPT + '.subcommand()'} {
|
||||
% for resource in sorted(c.rta_map.keys()):
|
||||
|
||||
% if loop.first:
|
||||
if \
|
||||
% else:
|
||||
else if \
|
||||
% endif
|
||||
self.opt.${cmd_ident(resource)} {
|
||||
## METHOD LOOP: Check for method subcommand
|
||||
% for method in sorted(c.rta_map[resource]):
|
||||
% if loop.first:
|
||||
if \
|
||||
% else:
|
||||
else if \
|
||||
% endif
|
||||
self.opt.${cmd_ident(method)} {
|
||||
call_result = self.${call_method_ident(resource, method)}(dry_run, &mut err);
|
||||
}\
|
||||
% endfor # each method
|
||||
else {
|
||||
unreachable!();
|
||||
}
|
||||
}\
|
||||
("${mangle_subcommand(resource)}", Some(opt)) => {
|
||||
match opt.subcommand() {
|
||||
% for method in sorted(c.rta_map[resource]):
|
||||
("${mangle_subcommand(method)}", Some(opt)) => {
|
||||
call_result = self.${call_method_ident(resource, method)}(opt, dry_run, &mut err);
|
||||
},
|
||||
% endfor # each method
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingMethodError("${mangle_subcommand(resource)}".to_string()));
|
||||
}
|
||||
}
|
||||
},
|
||||
% endfor # each resource
|
||||
else {
|
||||
unreachable!();
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingCommandError);
|
||||
}
|
||||
}
|
||||
|
||||
if dry_run {
|
||||
@@ -94,9 +87,9 @@ self.opt.${cmd_ident(method)} {
|
||||
}
|
||||
|
||||
// Please note that this call will fail if any part of the opt can't be handled
|
||||
fn new(opt: Options) -> Result<Engine, InvalidOptionsError> {
|
||||
fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> {
|
||||
let (config_dir, secret) = {
|
||||
let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) {
|
||||
let config_dir = match cmn::assure_config_dir_exists(opt.value_of("${CONFIG_DIR_FLAG}").unwrap_or("${CONFIG_DIR}")) {
|
||||
Err(e) => return Err(InvalidOptionsError::single(e, 3)),
|
||||
Ok(p) => p,
|
||||
};
|
||||
@@ -137,7 +130,7 @@ self.opt.${cmd_ident(method)} {
|
||||
</%def>
|
||||
|
||||
<%def name="_debug_client(flag_name)" buffered="True">\
|
||||
if opt.flag_${mangle_ident(flag_name)} {
|
||||
if opt.is_present("${flag_name}") {
|
||||
hyper::Client::with_connector(mock::TeeConnector {
|
||||
connector: hyper::net::HttpConnector(None)
|
||||
})
|
||||
@@ -179,7 +172,7 @@ ${self._request_value_impl(c, request_cli_schema, prop_name, request_prop_type)}
|
||||
% elif p.type != 'string':
|
||||
% if p.get('repeated', False):
|
||||
let ${prop_name}: Vec<${prop_type} = Vec::new();
|
||||
for (arg_id, arg) in ${opt_ident}.iter().enumerate() {
|
||||
for (arg_id, arg) in opt.values_of().unwrap_or(Vec::new()).iter().enumerate() {
|
||||
${prop_name}.push(arg_from_str(&arg, err, "<${mangle_subcommand(p.name)}>", arg_id), "${p.type}"));
|
||||
}
|
||||
% else:
|
||||
@@ -204,7 +197,7 @@ let mut download_mode = false;
|
||||
% endif
|
||||
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() {
|
||||
for parg in opt.values_of("${ident(VALUE_ARG)}").unwrap_or(Vec::new()).iter() {
|
||||
let (key, value) = parse_kv_arg(&*parg, err, false);
|
||||
match key {
|
||||
% for p in optional_props:
|
||||
@@ -267,14 +260,14 @@ let protocol =
|
||||
% else:
|
||||
} else if \
|
||||
% endif
|
||||
${SOPT + cmd_ident(p.protocol)} {
|
||||
${opt_value(p.protocol)} {
|
||||
"${p.protocol}"
|
||||
% endfor # each media param
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
let mut input_file = input_file_from_opts(&${SOPT + arg_ident(FILE_ARG[1:-1])}, err);
|
||||
let mime_type = input_mime_from_opts(&${SOPT + arg_ident(MIME_ARG[1:-1])}, err);
|
||||
let mut input_file = input_file_from_opts(&${opt_value(FILE_ARG)}, err);
|
||||
let mime_type = input_mime_from_opts(&${opt_value(MIME_ARG)}, err);
|
||||
% else:
|
||||
let protocol = "${STANDARD}";
|
||||
% endif # support upload
|
||||
@@ -283,7 +276,7 @@ if dry_run {
|
||||
} else {
|
||||
assert!(err.issues.len() == 0);
|
||||
% if method_default_scope(mc.m):
|
||||
<% scope_opt = SOPT + flag_ident('scope') %>\
|
||||
<% scope_opt = opt_value('scope', SOPT) %>\
|
||||
if ${scope_opt}.len() > 0 {
|
||||
call = call.${ADD_SCOPE_FN}(&${scope_opt});
|
||||
}
|
||||
@@ -291,7 +284,7 @@ if dry_run {
|
||||
## Make the call, handle uploads, handle downloads (also media downloads|json decoding)
|
||||
## TODO: unify error handling
|
||||
% if handle_output:
|
||||
let mut ostream = writer_from_opts(${SOPT + flag_ident(OUTPUT_FLAG)}, &${SOPT + arg_ident(OUT_ARG[1:-1])});
|
||||
let mut ostream = writer_from_opts(opt.value_of("${(OUT_ARG)}"));
|
||||
% endif # handle output
|
||||
match match protocol {
|
||||
% if mc.media_params:
|
||||
@@ -383,7 +376,7 @@ if dry_run {
|
||||
%>\
|
||||
let mut ${request_prop_name} = api::${request_prop_type}::default();
|
||||
let mut field_cursor = FieldCursor::default();
|
||||
for kvarg in ${SOPT + arg_ident(KEY_VALUE_ARG)}.iter() {
|
||||
for kvarg in ${opt_value(KEY_VALUE_ARG)}.iter() {
|
||||
let last_errc = err.issues.len();
|
||||
let (key, value) = parse_kv_arg(&*kvarg, err, false);
|
||||
let mut temp_cursor = field_cursor.clone();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<%
|
||||
from util import (new_context, rust_comment, to_extern_crate_name, library_to_crate_name, library_name,
|
||||
indent_all_but_first_by)
|
||||
from cli import DEBUG_FLAG
|
||||
|
||||
c = new_context(schemas, resources, context.get('methods'))
|
||||
default_user_agent = "google-cli-rust-client/" + cargo.build_version
|
||||
@@ -29,27 +30,26 @@ use clap::{App, SubCommand, Arg};
|
||||
|
||||
mod cmn;
|
||||
|
||||
## ${engine.new(c)}\
|
||||
${engine.new(c)}\
|
||||
|
||||
fn main() {
|
||||
${argparse.new(c) | indent_all_but_first_by(1)}\
|
||||
|
||||
## let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit());
|
||||
## let debug = opts.flag_debug;
|
||||
## match Engine::new(opts) {
|
||||
## Err(err) => {
|
||||
## writeln!(io::stderr(), "{}", err).ok();
|
||||
## env::set_exit_status(err.exit_code);
|
||||
## },
|
||||
## Ok(engine) => {
|
||||
## if let Some(err) = engine.doit() {
|
||||
## if debug {
|
||||
## writeln!(io::stderr(), "{:?}", err).ok();
|
||||
## } else {
|
||||
## writeln!(io::stderr(), "{}", err).ok();
|
||||
## }
|
||||
## env::set_exit_status(1);
|
||||
## }
|
||||
## }
|
||||
## }
|
||||
let debug = matches.is_present("${DEBUG_FLAG}");
|
||||
match Engine::new(matches) {
|
||||
Err(err) => {
|
||||
writeln!(io::stderr(), "{}", err).ok();
|
||||
env::set_exit_status(err.exit_code);
|
||||
},
|
||||
Ok(engine) => {
|
||||
if let Some(err) = engine.doit() {
|
||||
if debug {
|
||||
writeln!(io::stderr(), "{:?}", err).ok();
|
||||
} else {
|
||||
writeln!(io::stderr(), "{}", err).ok();
|
||||
}
|
||||
env::set_exit_status(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,11 +149,11 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option
|
||||
|
||||
// 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<Write> {
|
||||
if !flag || arg == "-" {
|
||||
Box::new(stdout())
|
||||
} else {
|
||||
Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap())
|
||||
pub fn writer_from_opts(arg: Option<&str>) -> Box<Write> {
|
||||
let f = arg.unwrap_or("-");
|
||||
match f {
|
||||
"-" => Box::new(stdout()),
|
||||
_ => Box::new(fs::OpenOptions::new().create(true).write(true).open(f).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,6 +331,8 @@ pub enum CLIError {
|
||||
InvalidKeyValueSyntax(String, bool),
|
||||
Input(InputError),
|
||||
Field(FieldError),
|
||||
MissingCommandError,
|
||||
MissingMethodError(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for CLIError {
|
||||
@@ -348,6 +350,8 @@ impl fmt::Display for CLIError {
|
||||
let hashmap_info = if is_hashmap { "hashmap " } else { "" };
|
||||
writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info)
|
||||
},
|
||||
CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command"),
|
||||
CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the {} command", cmd),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user