From c3a9f1e8e594172ac783f0b9c76e093a534674ee Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 14 Apr 2015 21:18:57 +0200 Subject: [PATCH] feat(CLI): interpret output arguments For now we don't properly handle errors when opening files, but the code is there. Will panic in next commit. Related to #63 --- src/mako/cli/lib/cli.py | 3 +++ src/mako/cli/lib/engine.mako | 28 ++++++++++++++++++---------- src/rust/cli/cmn.rs | 19 ++++++++++++++++++- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/mako/cli/lib/cli.py b/src/mako/cli/lib/cli.py index 03e6983961a..51b06c2d141 100644 --- a/src/mako/cli/lib/cli.py +++ b/src/mako/cli/lib/cli.py @@ -85,6 +85,9 @@ def cmd_ident(name): def arg_ident(name): return 'arg_' + ident(name) +def flag_ident(name): + return 'flag_' + 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 af66ffc59b6..19d25ca292a 100644 --- a/src/mako/cli/lib/engine.mako +++ b/src/mako/cli/lib/engine.mako @@ -3,18 +3,19 @@ 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, arg_ident, POD_TYPES) + cmd_ident, call_method_ident, arg_ident, POD_TYPES, flag_ident) v_arg = '<%s>' % VALUE_ARG - def to_opt_ident(p): - return 'self.opt.' + arg_ident(p.name) + SOPT = 'self.opt.' + def to_opt_arg_ident(p): + return SOPT + arg_ident(p.name) %>\ <%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}; +use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts}; use std::default::Default; use std::str::FromStr; @@ -119,16 +120,14 @@ self.opt.${cmd_ident(method)} { <%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)) + handle_output = mc.response_schema or mc.m.get('supportsMediaDownload', False) %>\ ## 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 = to_opt_ident(p) + opt_ident = to_opt_arg_ident(p) %>\ % if is_request_value_property(mc, p): let ${prop_name}: api::${prop_type} = Default::default(); @@ -146,13 +145,13 @@ let ${prop_name}: ${prop_type} = arg_from_str(&${opt_ident}, err, "<${mangle_sub borrow = '&' arg_name = mangle_ident(p.name) if ptype == 'string': - arg_name = to_opt_ident(p) + 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 -## TODO: parse upload and output information +## TODO: parse upload if dry_run { None } else { @@ -162,6 +161,15 @@ if dry_run { % if mc.media_params: return None % else: + % if handle_output: + let ostream = match writer_from_opts(${SOPT + flag_ident(OUTPUT_FLAG)}, &${SOPT + arg_ident(OUT_ARG[1:-1])}) { + Err(cli_err) => { + err.issues.push(cli_err); + return None + }, + Ok(bs) => bs, + }; + % endif # handle output match call.${api.terms.action}() { Err(api_err) => Some(api_err), Ok(res) => { diff --git a/src/rust/cli/cmn.rs b/src/rust/cli/cmn.rs index 02940b292b6..5d0d1ca3d45 100644 --- a/src/rust/cli/cmn.rs +++ b/src/rust/cli/cmn.rs @@ -8,10 +8,27 @@ use std::fmt; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::io::{Write, Read}; +use std::io::{Write, Read, stdout}; use std::default::Default; +// 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) -> Result, CLIError> { + if !flag && arg == "-" { + Ok(Box::new(stdout())) + } else { + match fs::OpenOptions::new().create(true).write(true).open(arg) { + Err(io_err) => { + Err(CLIError::Configuration( + ConfigurationError::IOError((arg.to_string(), io_err)) + )) + }, + Ok(f) => Ok(Box::new(f)), + } + } +} + pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, arg_name: &'static str,