diff --git a/src/mako/lib/lib.mako b/src/mako/lib/lib.mako index 5832082bcd0..cb18b69b689 100644 --- a/src/mako/lib/lib.mako +++ b/src/mako/lib/lib.mako @@ -6,7 +6,7 @@ find_fattest_resource, build_all_params, pass_through, parts_from_params, REQUEST_MARKER_TRAIT, RESPONSE_MARKER_TRAIT, supports_scopes, to_api_version, to_fqan, METHODS_RESOURCE, ADD_PARAM_MEDIA_EXAMPLE, PROTOCOL_TYPE_INFO, enclose_in, - upload_action_fn, unique_type_name, schema_doc_format) + upload_action_fn, unique_type_name, schema_doc_format, METHODS_BUILDER_MARKER_TRAIT) def pretty_name(name): return ' '.join(split_camelcase_s(name).split('.')) @@ -23,7 +23,7 @@ # fr == fattest resource, the fatter, the more important, right ? fr = find_fattest_resource(c) hub_url = 'struct.' + hub_type(c.schemas, util.canonical_name()) + '.html' - method_builder_url = 'trait.' + CALL_BUILDER_MARKERT_TRAIT + '.html' + call_builder_url = 'trait.' + CALL_BUILDER_MARKERT_TRAIT + '.html' delegate_url = 'trait.Delegate.html' request_trait_url = 'trait.' + REQUEST_MARKER_TRAIT + '.html' response_trait_url = 'trait.' + RESPONSE_MARKER_TRAIT + '.html' @@ -132,15 +132,19 @@ The API is structured into the following primary items: * **${link('Hub', hub_url)}** * a central object to maintain state and allow accessing all *Activities* + * creates ${link('*Method Builders*', 'trait.' + METHODS_BUILDER_MARKER_TRAIT + '.html')} which in turn + allow access to individual ${link('*Call Builders*', call_builder_url)} * **${link('Resources', 'trait.' + RESOURCE_MARKER_TRAIT + '.html')}** * primary types that you can apply *Activities* to * a collection of properties and *Parts* * **${link('Parts', part_trait_url)}** * a collection of properties * never directly used in *Activities* -* **${link('Activities', method_builder_url)}** +* **${link('Activities', call_builder_url)}** * operations to apply to *Resources* +All *structures* are marked with applicable traits to further categorize them and ease browsing. + Generally speaking, you can invoke *Activities* like this: ```Rust,ignore @@ -187,7 +191,7 @@ ${link('Hub Delegate', delegate_url)}, or the ${link('Authenticator Delegate', u When delegates handle errors or intermediate values, they may have a chance to instruct the system to retry. This makes the system potentially resilient to all kinds of errors. -${'##'} Uploads and Downlods +${'##'} Uploads and Downloads If a method supports downloads, the response body, which is part of the ${link('Result', 'enum.Result.html')}, should be read by you to obtain the media. If such a method also supports a ${link('Response Result', 'trait.ResponseResult.html')}, it will return that by default. @@ -201,7 +205,7 @@ ${put_and(md_italic(PROTOCOL_TYPE_INFO.keys()))}. The distinctiveness of each is ${'##'} Customization and Callbacks You may alter the way an `${api.terms.action}()` method is called by providing a ${link('delegate', delegate_url)} to the -${link('Method Builder', method_builder_url)} before making the final `${api.terms.action}()` call. +${link('Method Builder', call_builder_url)} before making the final `${api.terms.action}()` call. Respective methods will be called to provide progress information, as well as determine whether the system should retry on failure. @@ -210,13 +214,14 @@ The ${link('delegate trait', delegate_url)} is default-implemented, allowing you ${'##'} Optional Parts in Server-Requests All structures provided by this library are made to be ${link('enocodable', request_trait_url)} and -${link('decodable', response_trait_url)} via json. Optionals are used to indicate that partial requests are responses are valid. -Most optionals are are considered ${link('Parts', part_trait_url)} which are identifyable by name, which will be sent to +${link('decodable', response_trait_url)} via *json*. Optionals are used to indicate that partial requests are responses +are valid. +Most optionals are are considered ${link('Parts', part_trait_url)} which are identifiable by name, which will be sent to the server to indicate either the set parts of the request or the desired parts in the response. ${'##'} Builder Arguments -Using ${link('method builders', method_builder_url)}, you are able to prepare an action call by repeatedly calling it's methods. +Using ${link('method builders', call_builder_url)}, you are able to prepare an action call by repeatedly calling it's methods. These will always take a single argument, for which the following statements are true. * [PODs][wiki-pod] are handed by copy diff --git a/src/mako/lib/mbuild.mako b/src/mako/lib/mbuild.mako index 9d0926b3706..0f2854517fc 100644 --- a/src/mako/lib/mbuild.mako +++ b/src/mako/lib/mbuild.mako @@ -361,7 +361,7 @@ match result { Result::HttpError(err) => println!("HTTPERROR: {:?}", err), Result::MissingAPIKey => println!("Auth: Missing API Key - used if there are no scopes"), Result::MissingToken => println!("OAuth2: Missing Token"), - Result::Cancelled => println!("Operation cancelled by user"), + Result::Cancelled => println!("Operation canceled by user"), Result::UploadSizeLimitExceeded(size, max_size) => println!("Upload size too big: {} of {}", size, max_size), Result::Failure(_) => println!("General Failure (hyper::client::Response doesn't print)"), Result::FieldClash(clashed_field) => println!("You added custom parameter which is part of builder: {:?}", clashed_field), diff --git a/src/mako/lib/rbuild.mako b/src/mako/lib/rbuild.mako index c1cd60aca99..f9e0cf39a4b 100644 --- a/src/mako/lib/rbuild.mako +++ b/src/mako/lib/rbuild.mako @@ -5,7 +5,8 @@ activity_input_type, TREF, IO_REQUEST, schema_to_required_property, rust_copy_value_s, is_required_property, organize_params, REQUEST_VALUE_PROPERTY_NAME, build_all_params, rb_type_params_s, hub_type_params_s, mb_type_params_s, mb_additional_type_params, - struct_type_bounds_s, METHODS_RESOURCE) + struct_type_bounds_s, METHODS_RESOURCE, SPACES_PER_TAB, prefix_all_but_first_with, + METHODS_BUILDER_MARKER_TRAIT) %>\ <%namespace name="util" file="util.mako"/>\ <%namespace name="lib" file="lib.mako"/>\ @@ -48,7 +49,7 @@ pub struct ${ThisType} hub: &'a ${hub_type_name}${hub_type_params_s()}, } -impl${rb_params} MethodsBuilder for ${ThisType} {} +impl${rb_params} ${METHODS_BUILDER_MARKER_TRAIT} for ${ThisType} {} ## Builder Creators Methods #################### impl${rb_params} ${ThisType} { @@ -81,6 +82,18 @@ impl${rb_params} ${ThisType} { /// ${m.description | rust_doc_comment, indent_all_but_first_by(1)} % endif + % if required_props: + /// + /// # Arguments + /// + % for p in required_props: +<% + arg_prefix = "/// * `" + p.name + "` - " +%>\ + ${arg_prefix}${p.get('description', "No description provided.") + | prefix_all_but_first_with(' ' * SPACES_PER_TAB + '///' + ' ' * (len(arg_prefix) - len('///')))} + % endfor + % endif pub fn ${mangle_ident(a)}${type_params}(&self${method_args}) -> ${RType}${mb_tparams} { ${RType} { hub: self.hub, diff --git a/src/mako/lib/util.py b/src/mako/lib/util.py index a240135f96f..22c7e20d700 100644 --- a/src/mako/lib/util.py +++ b/src/mako/lib/util.py @@ -65,6 +65,7 @@ RESPONSE_MARKER_TRAIT = 'ResponseResult' RESOURCE_MARKER_TRAIT = 'Resource' CALL_BUILDER_MARKERT_TRAIT = 'CallBuilder' +METHODS_BUILDER_MARKER_TRAIT = 'MethodsBuilder' PART_MARKER_TRAIT = 'Part' NESTED_MARKER_TRAIT = 'NestedType' REQUEST_VALUE_PROPERTY_NAME = 'request' @@ -85,11 +86,14 @@ }, 'resumable' : { 'arg_name': 'resumeable_stream', - 'description': """Upload media in a resumeable fashion. + 'description': """Upload media in a resumable fashion. Even if the upload fails or is interrupted, it can be resumed for a certain amount of time as the server maintains state temporarily. -TODO: Write more about how delegation works in this particular case.""", +The delegate will be asked for an `upload_url()`, and if not provided, will be asked to store an upload URL +that was provided by the server, using `store_upload_url(...)`. The upload will be done in chunks, the delegate +may specify the `chunk_size()` and may cancel the operation before each chunk is uploaded, using +`cancel_chunk_upload(...)`.""", 'default': 'fs::File', 'suffix': '_resumable', 'example_value': 'fs::File::open("file.ext").unwrap(), "application/octet-stream".parse().unwrap()' @@ -146,20 +150,30 @@ def unindent_inner(s): return re_linestart.sub(' ' * tabs * SPACES_PER_TAB, s) return unindent_inner -# tabs: 1 tabs is 4 spaces -def indent_all_but_first_by(tabs): +# Prepend prefix to each line but the first +def prefix_all_but_first_with(prefix): def indent_inner(s): try: i = s.index('\n') except ValueError: f = s - p = '' + p = None else: f = s[:i+1] p = s[i+1:] - return f + re_linestart.sub(' ' * (tabs * SPACES_PER_TAB), p) + if p is None: + return f + return f + re_linestart.sub(prefix, p) return indent_inner + +# tabs: 1 tabs is 4 spaces +def indent_all_but_first_by(indent, indent_in_tabs=True): + if indent_in_tabs: + indent *= SPACES_PER_TAB + spaces = ' ' * indent + return prefix_all_but_first_with(spaces) + # add 4 spaces to the beginning of a line. # useful if you have defs embedded in an unindent block - they need to counteract. # It's a bit itchy, but logical diff --git a/src/rust/cmn.rs b/src/rust/cmn.rs index db9fd299493..196d1d6e23a 100644 --- a/src/rust/cmn.rs +++ b/src/rust/cmn.rs @@ -103,12 +103,15 @@ pub trait Delegate { /// information if he is interesting in knowing more context when further calls to it /// are made. /// The matching `finished()` call will always be made, no matter whether or not the API - /// request was sucessfull. That way, the delgate may easily maintain a clean state + /// request was successful. That way, the delegate may easily maintain a clean state /// between various API calls. fn begin(&mut self, MethodInfo) {} /// Called whenever there is an [HttpError](http://hyperium.github.io/hyper/hyper/error/enum.HttpError.html), usually if there are network problems. /// + /// If you choose to retry after a duration, the duration should be chosen using the + /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). + /// /// Return retry information. fn http_error(&mut self, &hyper::HttpError) -> Retry { Retry::Abort @@ -131,7 +134,7 @@ pub trait Delegate { /// Called during resumable uploads to provide a URL for the impending upload. /// It was saved after a previous call to `store_upload_url(...)`, and if not None, /// will be used instead of asking the server for a new upload URL. - /// This is useful in case a previous resumable upload was aborted/cancelled, but should now + /// This is useful in case a previous resumable upload was aborted/canceled, but should now /// be resumed. /// The returned URL will be used exactly once - if it fails again and the delegate allows /// to retry, we will ask the server for a new upload URL. @@ -152,8 +155,8 @@ pub trait Delegate { /// /// # Arguments /// - /// `json_encoded_value` - The json-encoded value which failed to decode. - /// `json_decode_error` - The decoder error + /// * `json_encoded_value` - The json-encoded value which failed to decode. + /// * `json_decode_error` - The decoder error fn response_json_decode_error(&mut self, json_encoded_value: &str, json_decode_error: &serde::json::Error) { let _ = json_encoded_value; let _ = json_decode_error; @@ -164,6 +167,9 @@ pub trait Delegate { /// depends on the used API method. /// The delegate should check the status, header and decoded json error to decide /// whether to retry or not. In the latter case, the underlying call will fail. + /// + /// If you choose to retry after a duration, the duration should be chosen using the + /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). fn http_failure(&mut self, _: &hyper::client::Response, Option) -> Retry { Retry::Abort } @@ -195,8 +201,8 @@ pub trait Delegate { /// /// # Arguments /// - /// `is_success` - a true value indicates the operation was successful. If false, you should - /// discard all values stored during `store_upload_url`. + /// * `is_success` - a true value indicates the operation was successful. If false, you should + /// discard all values stored during `store_upload_url`. fn finished(&mut self, is_success: bool) { let _ = is_success; }