diff --git a/etc/api/shared.yaml b/etc/api/shared.yaml index c9f5c22496..4a6a1f6cff 100644 --- a/etc/api/shared.yaml +++ b/etc/api/shared.yaml @@ -3,6 +3,11 @@ api: # exclude APIs which currently don't build correctly. State the reason for the exclusion as well # to allow looking at it at a later point. - + terms: + # how to actually do something with the API + action: doit + # when a resource is supposed to be uploaded + upload_action: upload # Contains values shared among all API implementations directories: # directory under which all generated sources should reside diff --git a/etc/api/type-api.yaml b/etc/api/type-api.yaml index 320a2868a7..a109a3ace8 100644 --- a/etc/api/type-api.yaml +++ b/etc/api/type-api.yaml @@ -1,10 +1,5 @@ api: base_path: "etc/api" - terms: - # how to actually do something with the API - action: doit - # when a resource is supposed to be uploaded - upload_action: upload properties: # additional fields specified by the user params: '_additional_params' diff --git a/etc/api/type-cli.yaml b/etc/api/type-cli.yaml index 5aedc05bb4..785063fe53 100644 --- a/etc/api/type-cli.yaml +++ b/etc/api/type-cli.yaml @@ -26,6 +26,6 @@ cargo: keywords: [cli] is_executable: YES dependencies: - - docopt = "*" - - docopt_macros = "*" + - docopt = "= 0.6.59" + - docopt_macros = "= 0.6.59" - rustc-serialize = "*" diff --git a/src/mako/cli/lib/cli.py b/src/mako/cli/lib/cli.py index 89a29a88eb..03e6983961 100644 --- a/src/mako/cli/lib/cli.py +++ b/src/mako/cli/lib/cli.py @@ -81,6 +81,10 @@ def ident(name): def cmd_ident(name): return 'cmd_' + ident(name) +# Similar to cmd_ident, but for arguments +def arg_ident(name): + return 'arg_' + ident(name) + # Returns identifier for method dealing with options for the given resource-method pair def call_method_ident(resource, method): return '_%s_%s' % (ident(resource), ident(method)) diff --git a/src/mako/cli/lib/engine.mako b/src/mako/cli/lib/engine.mako index d8b5a9e9bd..1bc09d67e6 100644 --- a/src/mako/cli/lib/engine.mako +++ b/src/mako/cli/lib/engine.mako @@ -1,9 +1,9 @@ <%namespace name="util" file="../../lib/util.mako"/>\ <%! - from util import hub_type + from util import (hub_type, mangle_ident, indent_all_but_first_by, activity_rust_type) 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) + cmd_ident, call_method_ident, arg_ident, POD_TYPES) v_arg = '<%s>' % VALUE_ARG %>\ @@ -12,13 +12,14 @@ hub_type_name = 'api::' + hub_type(c.schemas, util.canonical_name()) %>\ mod cmn; -use cmn::{InvalidOptionsError, JsonTokenStorage}; +use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage}; +use std::default::Default; +use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; struct Engine { opt: Options, - config_dir: String, hub: ${hub_type_name}>, } @@ -26,15 +27,16 @@ struct Engine { impl Engine { % 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) -> Option { - ${self._method_call_impl(c, resource, method)}\ + fn ${call_method_ident(resource, method)}(&self, dry_run: bool, err: &mut InvalidOptionsError) + -> Option { + ${self._method_call_impl(c, resource, method) | indent_all_but_first_by(2)} } % endfor # each method % endfor fn _doit(&self, dry_run: bool) -> (Option, Option) { let mut err = InvalidOptionsError::new(); - let mut call_result: Option = None; + let mut call_result: Option; let mut err_opt: Option = None; ## RESOURCE LOOP: check for set primary subcommand @@ -95,7 +97,6 @@ self.opt.${cmd_ident(method)} { }, None); let engine = Engine { opt: opt, - config_dir: config_dir, hub: ${hub_type_name}::new(hyper::Client::new(), auth), }; @@ -113,6 +114,67 @@ self.opt.${cmd_ident(method)} { } -<%def name="_method_call_impl(c, resource, method)">\ -None +<%def name="_method_call_impl(c, resource, method)" buffered="True">\ +<% + mc = new_method_context(resource, method, c) + ## if is_request_value_property(mc, p): + ## continue + ## args.append('<%s>' % mangle_subcommand(p.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) + opt_ident = 'self.opt.' + arg_ident(p.name) +%>\ + % if is_request_value_property(mc, p): +let ${prop_name}: api::${prop_type} = Default::default(); + % else: +let ${prop_name}: ${prop_type} = \ + % if p.type == 'string': +${opt_ident}.clone(); + % else: + + match FromStr::from_str(&${opt_ident}) { + Err(perr) => { + err.issues.push(CLIError::ParseError(format!("Failed to parse argument <${mangle_subcommand(p.name)}> as ${p.type} with error: {}", perr))); + Default::default() + }, + Ok(v) => v, + }; + % endif # handle argument type + % endif # handle request value +% endfor # each required parameter +<% + call_args = list() + 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', 'string') + if ptype not in POD_TYPES or ptype == 'string': + borrow = '&' + call_args.append(borrow + mangle_ident(p.name)) + # end for each required prop +%>\ +let call = self.hub.${mangle_ident(resource)}().${mangle_ident(method)}(${', '.join(call_args)}); +## TODO: set parameters +## TODO: parse upload and output information +if dry_run { + None +} else { + ## Make the call, handle uploads, handle downloads (also media downloads|json decoding) + ## TODO: unify error handling + % if mc.media_params: + return None + % else: + match call.${api.terms.action}() { + Err(api_err) => Some(api_err), + Ok(res) => { + println!("DEBUG: {:?}", res); + None + } + } + % endif +}\ \ No newline at end of file diff --git a/src/mako/cli/main.rs.mako b/src/mako/cli/main.rs.mako index 51de7cf663..f120f5592d 100644 --- a/src/mako/cli/main.rs.mako +++ b/src/mako/cli/main.rs.mako @@ -12,6 +12,7 @@ #![feature(plugin, exit_status)] #![plugin(docopt_macros)] +#![allow(unused_variables, unused_imports, dead_code)] extern crate docopt; extern crate yup_oauth2 as oauth2; diff --git a/src/rust/cli/cmn.rs b/src/rust/cli/cmn.rs index de0d1977ab..4d722c2277 100644 --- a/src/rust/cli/cmn.rs +++ b/src/rust/cli/cmn.rs @@ -95,12 +95,14 @@ impl fmt::Display for ConfigurationError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), + ParseError(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::Configuration(ref err) => writeln!(f, "Configuration -> {}", err), + CLIError::ParseError(ref desc) => desc.fmt(f), } } }