diff --git a/gen/youtube3/README.md b/gen/youtube3/README.md index 9ff8020c6c..eeed44c776 100644 --- a/gen/youtube3/README.md +++ b/gen/youtube3/README.md @@ -60,7 +60,7 @@ let r = hub.videos().delete(...).do() ``` The `resource()` and `activity(...)` calls create [builders][builder-pattern]. The second one dealing with `Activities` -supports various methods to configure the impending operation. It is made such that all required arguments have to be +supports various methods to configure the impending operation (not shown here). It is made such that all required arguments have to be specified right away (i.e. `(...)`), whereas all optional ones can be [build up][builder-pattern] as desired. The `do()` method performs the actual communication with the server and returns the respective result. @@ -68,9 +68,34 @@ The `do()` method performs the actual communication with the server and returns ## Instantiating the Hub +```Rust +extern crate hyper; +extern crate "yup-oauth2" as oauth2; +extern crate "rustc-serialize" as rustc_serialize; +extern crate youtube3; + +use oauth2::{Authenticator, DefaultAuthenticatorDelegate, ApplicationSecret, MemoryStorage}; +use std::default::Default; + +use youtube3::YouTube; + +// Get an ApplicationSecret instance by some means. It contains the `client_id` and `client_secret`, +// among other things. +let secret: ApplicationSecret = Default::default(); +// Instantiate the authenticator. It will choose a suitable authentication flow for you, +// unless you replace `None` with the desired Flow +// Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about what's going on +// You probably want to bring in your own `TokenStorage` to persist tokens and retrieve them from storage. +let auth = Authenticator::new(&secret, DefaultAuthenticatorDelegate, + hyper::Client::new(), + ::default(), None); +let mut hub = YouTube::new(hyper::Client::new(), auth); +``` + +**TODO** Example calls - there should soon be a generator able to do that with proper inputs ## About error handling -## About costumization +## About Customization/Callbacks [builder-pattern]: http://en.wikipedia.org/wiki/Builder_pattern [google-go-api]: https://github.com/google/google-api-go-client diff --git a/gen/youtube3/src/cmn.rs b/gen/youtube3/src/cmn.rs index ccbad6cc41..d55dbfa1df 100644 --- a/gen/youtube3/src/cmn.rs +++ b/gen/youtube3/src/cmn.rs @@ -2,6 +2,11 @@ // DO NOT EDIT use std::marker::MarkerTrait; +/// Identifies the Hub. There is only one per library, this trait is supposed +/// to make intended use more explicit. +/// The hub allows to access all resource methods more easily. +pub trait Hub: MarkerTrait {} + /// Identifies types which can be inserted and deleted. /// Types with this trait are most commonly used by clients of this API. pub trait Resource: MarkerTrait {} diff --git a/gen/youtube3/src/lib.rs b/gen/youtube3/src/lib.rs index b7f40d6b0c..685297a4b2 100644 --- a/gen/youtube3/src/lib.rs +++ b/gen/youtube3/src/lib.rs @@ -57,7 +57,7 @@ //! ``` //! //! The `resource()` and `activity(...)` calls create [builders][builder-pattern]. The second one dealing with `Activities` -//! supports various methods to configure the impending operation. It is made such that all required arguments have to be +//! supports various methods to configure the impending operation (not shown here). It is made such that all required arguments have to be //! specified right away (i.e. `(...)`), whereas all optional ones can be [build up][builder-pattern] as desired. //! The `do()` method performs the actual communication with the server and returns the respective result. //! @@ -65,9 +65,36 @@ //! //! ## Instantiating the Hub //! +//! ```test_harness,no_run +//! extern crate hyper; +//! extern crate "yup-oauth2" as oauth2; +//! extern crate "rustc-serialize" as rustc_serialize; +//! extern crate youtube3; +//! +//! # #[test] fn egal() { +//! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, ApplicationSecret, MemoryStorage}; +//! use std::default::Default; +//! +//! use youtube3::YouTube; +//! +//! // Get an ApplicationSecret instance by some means. It contains the `client_id` and `client_secret`, +//! // among other things. +//! let secret: ApplicationSecret = Default::default(); +//! // Instantiate the authenticator. It will choose a suitable authentication flow for you, +//! // unless you replace `None` with the desired Flow +//! // Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about what's going on +//! // You probably want to bring in your own `TokenStorage` to persist tokens and retrieve them from storage. +//! let auth = Authenticator::new(&secret, DefaultAuthenticatorDelegate, +//! hyper::Client::new(), +//! ::default(), None); +//! let mut hub = YouTube::new(hyper::Client::new(), auth); +//! # } +//! ``` +//! +//! **TODO** Example calls - there should soon be a generator able to do that with proper inputs //! ## About error handling //! -//! ## About costumization +//! ## About Customization/Callbacks //! //! [builder-pattern]: http://en.wikipedia.org/wiki/Builder_pattern //! [google-go-api]: https://github.com/google/google-api-go-client @@ -77,14 +104,77 @@ #![feature(core)] #![allow(non_snake_case)] +extern crate hyper; extern crate "rustc-serialize" as rustc_serialize; extern crate "yup-oauth2" as oauth2; mod cmn; use std::collections::HashMap; +use std::marker::PhantomData; +use std::borrow::BorrowMut; +use std::cell::RefCell; + +pub use cmn::{Hub, Resource, Part, ResponseResult, RequestResult, NestedType}; + +// ######## +// HUB ### +// ###### + +/// Central instance to access all YouTube related resource activities +/// +/// # Examples +/// +/// Instantiate a new hub +/// +/// ```test_harness,no_run +/// extern crate hyper; +/// extern crate "yup-oauth2" as oauth2; +/// extern crate "rustc-serialize" as rustc_serialize; +/// extern crate youtube3; +/// +/// # #[test] fn egal() { +/// use oauth2::{Authenticator, DefaultAuthenticatorDelegate, ApplicationSecret, MemoryStorage}; +/// use std::default::Default; +/// +/// use youtube3::YouTube; +/// +/// // Get an ApplicationSecret instance by some means. It contains the `client_id` and `client_secret`, +/// // among other things. +/// let secret: ApplicationSecret = Default::default(); +/// // Instantiate the authenticator. It will choose a suitable authentication flow for you, +/// // unless you replace `None` with the desired Flow +/// // Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about what's going on +/// // You probably want to bring in your own `TokenStorage` to persist tokens and retrieve them from storage. +/// let auth = Authenticator::new(&secret, DefaultAuthenticatorDelegate, +/// hyper::Client::new(), +/// ::default(), None); +/// let mut hub = YouTube::new(hyper::Client::new(), auth); +/// # } +/// ``` +/// +pub struct YouTube { + client: RefCell, + auth: RefCell, + _m: PhantomData +} + +impl<'a, C, NC, A> Hub for YouTube {} + +impl<'a, C, NC, A> YouTube + where NC: hyper::net::NetworkConnector, + C: BorrowMut> + 'a, + A: oauth2::GetToken { + + pub fn new(client: C, authenticator: A) -> YouTube { + YouTube { + client: RefCell::new(client), + auth: RefCell::new(authenticator), + _m: PhantomData, + } + } +} -pub use cmn::{Resource, Part, ResponseResult, RequestResult, NestedType}; // ############ // SCHEMAS ### diff --git a/src/mako/README.md.mako b/src/mako/README.md.mako index 73f3b72b09..75e131829f 100644 --- a/src/mako/README.md.mako +++ b/src/mako/README.md.mako @@ -9,5 +9,5 @@ The `${util.library_name()}` library allows access to all features of *${canonicalName}*. -${lib.docs(c)} +${lib.docs(c, rust_doc=False)} <%lib:license /> \ No newline at end of file diff --git a/src/mako/lib.rs.mako b/src/mako/lib.rs.mako index 819b832452..69ca9fd4f0 100644 --- a/src/mako/lib.rs.mako +++ b/src/mako/lib.rs.mako @@ -1,8 +1,12 @@ <% - from util import (iter_nested_types, new_context, rust_comment, rust_module_doc_comment, ) + from util import (iter_nested_types, new_context, rust_comment, rust_doc_comment, + rust_module_doc_comment, rust_doc_test_norun, canonical_type_name, + rust_test_fn_invisible) nested_schemas = list(iter_nested_types(schemas)) - c = new_context(resources) + c = new_context(resources) + + hub_type = canonical_type_name(canonicalName) %>\ <%namespace name="lib" file="lib/lib.mako"/>\ <%namespace name="mutil" file="lib/util.mako"/>\ @@ -17,14 +21,54 @@ ${lib.docs(c)} #![feature(core)] #![allow(non_snake_case)] +extern crate hyper; extern crate "rustc-serialize" as rustc_serialize; extern crate "yup-oauth2" as oauth2; mod cmn; use std::collections::HashMap; +use std::marker::PhantomData; +use std::borrow::BorrowMut; +use std::cell::RefCell; + +pub use cmn::{Hub, Resource, Part, ResponseResult, RequestResult, NestedType}; + +// ######## +// HUB ### +// ###### + +/// Central instance to access all ${hub_type} related resource activities +/// +/// # Examples +/// +/// Instantiate a new hub +/// +<%block filter="rust_doc_comment">\ +${lib.hub_usage_example()}\ + +pub struct ${hub_type} { + client: RefCell, + auth: RefCell, + _m: PhantomData +} + +impl<'a, C, NC, A> Hub for ${hub_type} {} + +impl<'a, C, NC, A> ${hub_type} + where NC: hyper::net::NetworkConnector, + C: BorrowMut> + 'a, + A: oauth2::GetToken { + + pub fn new(client: C, authenticator: A) -> ${hub_type} { + ${hub_type} { + client: RefCell::new(client), + auth: RefCell::new(authenticator), + _m: PhantomData, + } + } +} -pub use cmn::{Resource, Part, ResponseResult, RequestResult, NestedType}; // ############ // SCHEMAS ### diff --git a/src/mako/lib/lib.mako b/src/mako/lib/lib.mako index 65319e8918..b2d6eec209 100644 --- a/src/mako/lib/lib.mako +++ b/src/mako/lib/lib.mako @@ -1,7 +1,10 @@ -<%! from util import (activity_split, put_and, md_italic, split_camelcase_s) %>\ +<%! from util import (activity_split, put_and, md_italic, split_camelcase_s, canonical_type_name, + rust_test_fn_invisible, rust_doc_test_norun, rust_doc_comment, markdown_rust_block) %>\ <%namespace name="util" file="util.mako"/>\ -<%def name="docs(c)">\ +## If rust-doc is True, examples will be made to work for rust doc tests. Otherwise they are set +## for github markdown. +<%def name="docs(c, rust_doc=True)">\ <% # fr == fattest resource, the fatter, the more important, right ? fr = None @@ -54,7 +57,7 @@ let r = hub.${resource}().${activity}(...).${api.terms.action}() ``` The `resource()` and `activity(...)` calls create [builders][builder-pattern]. The second one dealing with `Activities` -supports various methods to configure the impending operation. It is made such that all required arguments have to be +supports various methods to configure the impending operation (not shown here). It is made such that all required arguments have to be specified right away (i.e. `(...)`), whereas all optional ones can be [build up][builder-pattern] as desired. The `${api.terms.action}()` method performs the actual communication with the server and returns the respective result. @@ -62,15 +65,57 @@ The `${api.terms.action}()` method performs the actual communication with the se ${'##'} Instantiating the Hub +${self.hub_usage_example(rust_doc)}\ + +**TODO** Example calls - there should soon be a generator able to do that with proper inputs ${'##'} About error handling -${'##'} About costumization +${'##'} About Customization/Callbacks [builder-pattern]: http://en.wikipedia.org/wiki/Builder_pattern [google-go-api]: https://github.com/google/google-api-go-client +## Sets up a hub ready for use. You must wrap it into a test function for it to work +## Needs test_prelude. +<%def name="test_hub(hub_type)">\ +use oauth2::{Authenticator, DefaultAuthenticatorDelegate, ApplicationSecret, MemoryStorage}; +use std::default::Default; + +use ${util.library_name()}::${hub_type}; + +// Get an ApplicationSecret instance by some means. It contains the `client_id` and `client_secret`, +// among other things. +let secret: ApplicationSecret = Default::default(); +// Instantiate the authenticator. It will choose a suitable authentication flow for you, +// unless you replace `None` with the desired Flow +// Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about what's going on +// You probably want to bring in your own `TokenStorage` to persist tokens and retrieve them from storage. +let auth = Authenticator::new(&secret, DefaultAuthenticatorDelegate, + hyper::Client::new(), + ::default(), None); +let mut hub = ${hub_type}::new(hyper::Client::new(), auth);\ + + +## You will still have to set the filter for your comment type - either nothing, or rust_doc_comment ! +<%def name="hub_usage_example(rust_doc=True)">\ +<% + test_filter = rust_test_fn_invisible + main_filter = rust_doc_test_norun + if not rust_doc: + test_filter = lambda s: s + main_filter = markdown_rust_block +%>\ +<%block filter="main_filter">\ +${util.test_prelude()}\ + +<%block filter="test_filter">\ +${self.test_hub(canonical_type_name(canonicalName))}\ + + + + <%def name="license()">\ # License The **${util.library_name()}** library was generated by ${put_and(copyright.authors)}, and is placed diff --git a/src/mako/lib/util.mako b/src/mako/lib/util.mako index 8101652bdf..bc4e2bcda9 100644 --- a/src/mako/lib/util.mako +++ b/src/mako/lib/util.mako @@ -21,4 +21,13 @@ ${cargo.repo_base_url}/${OUTPUT_DIR}\ <%def name="library_name()">\ ${util.library_name(name, version)}\ + + +## All crates and standard `use` declaration, required for all examples +## Must be outside of a test function +<%def name="test_prelude()">\ +extern crate hyper; +extern crate "yup-oauth2" as oauth2; +extern crate "rustc-serialize" as rustc_serialize; +extern crate ${self.library_name()}; \ No newline at end of file diff --git a/src/mako/lib/util.py b/src/mako/lib/util.py index 9119948ce2..57295457c5 100644 --- a/src/mako/lib/util.py +++ b/src/mako/lib/util.py @@ -43,12 +43,27 @@ def rust_comment(s): def hash_comment(s): return re_linestart.sub('# ', s) +# return s, with trailing newline +def trailing_newline(s): + if not s.endswith('\n'): + return s + '\n' + return s + +# a rust test that doesn't run though +def rust_doc_test_norun(s): + return "```test_harness,no_run\n%s```" % trailing_newline(s) + +# a rust code block in (github) markdown +def markdown_rust_block(s): + return "```Rust\n%s```" % trailing_newline(s) + +# wraps s into an invisible doc test function. +def rust_test_fn_invisible(s): + return "# #[test] fn egal() {\n%s# }" % trailing_newline(s) + # markdown comments def markdown_comment(s): - nl = '' - if not s.endswith('\n'): - nl = '\n' - return "" % (s, nl) + return "" % trailing_newline(s) # escape each string in l with "s" and return the new list def estr(l): @@ -84,7 +99,10 @@ def split_camelcase_s(s): # ------------------------------------------------------------------------------ ## @{ - +# Return transformed string that could make a good type name +def canonical_type_name(s): + # can't use s.capitalize() as it will lower-case the remainder of the string + return s[:1].upper() + s[1:] def nested_type_name(sn, pn): return sn + pn.capitalize() @@ -194,7 +212,7 @@ def schema_markers(s, c): # Returns (A, B) where # A: { SchemaTypeName -> { fqan -> ['request'|'response', ...]} -# B: { fqan -> activity_method } +# B: { fqan -> activity_method_data } # fqan = fully qualified activity name def build_activity_mappings(activities): res = dict() @@ -239,6 +257,10 @@ def activity_split(fqan): def activity_name_to_type_name(an): return an.capitalize()[:-1] +# yields (resource, activity, activity_data) +def iter_acitivities(c): + return ((activity_split(an) + [a]) for an, a in c.fqan_map.iteritems()) + ## -- End Activity Utilities -- @} diff --git a/src/rust/cmn.rs b/src/rust/cmn.rs index 8dde454d26..928c549f0b 100644 --- a/src/rust/cmn.rs +++ b/src/rust/cmn.rs @@ -1,5 +1,10 @@ use std::marker::MarkerTrait; +/// Identifies the Hub. There is only one per library, this trait is supposed +/// to make intended use more explicit. +/// The hub allows to access all resource methods more easily. +pub trait Hub: MarkerTrait {} + /// Identifies types which can be inserted and deleted. /// Types with this trait are most commonly used by clients of this API. pub trait Resource: MarkerTrait {}