mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2026-02-23 15:49:49 +01:00
feat(builder): Partial MethodBuilder impl
Including documentation at least on the method builder part. The great thing is that fully working examples are now included on every type ! Now more involved part starts ... namely setting up the individual call method signatures.
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
<%
|
||||
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)
|
||||
mb_type, singular, rust_test_fn_invisible, put_and)
|
||||
nested_schemas = list(iter_nested_types(schemas))
|
||||
|
||||
c = new_context(resources)
|
||||
|
||||
hub_type = canonical_type_name(canonicalName)
|
||||
|
||||
%>\
|
||||
<%namespace name="lib" file="lib/lib.mako"/>\
|
||||
<%namespace name="mutil" file="lib/util.mako"/>\
|
||||
@@ -32,7 +33,7 @@ use std::marker::PhantomData;
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::RefCell;
|
||||
|
||||
pub use cmn::{Hub, Resource, Part, ResponseResult, RequestResult, NestedType};
|
||||
pub use cmn::{Hub, MethodBuilder, Resource, Part, ResponseResult, RequestResult, NestedType};
|
||||
|
||||
// ########
|
||||
// HUB ###
|
||||
@@ -45,7 +46,7 @@ pub use cmn::{Hub, Resource, Part, ResponseResult, RequestResult, NestedType};
|
||||
/// Instantiate a new hub
|
||||
///
|
||||
<%block filter="rust_doc_comment">\
|
||||
${lib.hub_usage_example()}\
|
||||
<%lib:hub_usage_example/>\
|
||||
</%block>
|
||||
pub struct ${hub_type}<C, NC, A> {
|
||||
client: RefCell<C>,
|
||||
@@ -67,6 +68,12 @@ impl<'a, C, NC, A> ${hub_type}<C, NC, A>
|
||||
_m: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
% for resource in sorted(c.rta_map.keys()):
|
||||
pub fn ${resource}(&'a self) -> ${mb_type(resource)}<'a, C, NC, A> {
|
||||
${mb_type(resource)} { hub: &self }
|
||||
}
|
||||
% endfor
|
||||
}
|
||||
|
||||
|
||||
@@ -84,4 +91,39 @@ ${schema.new(s, c)}
|
||||
## We have to find them and process them as normal types
|
||||
% for s in nested_schemas:
|
||||
${schema.new(s, c)}
|
||||
% endfor
|
||||
% endfor
|
||||
|
||||
// ###################
|
||||
// MethodBuilders ###
|
||||
// #################
|
||||
|
||||
% for resource, methods in c.rta_map.iteritems():
|
||||
/// A builder providing access to all methods supported on *${singular(resource)}* resources.
|
||||
/// It is usually not used directly, but through the `${hub_type}` hub.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Instantiate a resource builder
|
||||
///
|
||||
<%block filter="rust_doc_test_norun, rust_doc_comment">\
|
||||
${mutil.test_prelude()}\
|
||||
|
||||
<%block filter="rust_test_fn_invisible">\
|
||||
${lib.test_hub(canonical_type_name(canonicalName))}\
|
||||
|
||||
// Usually you wouldn't stick this into a variable, but keep calling `MethodBuilders`
|
||||
// like ${put_and(sorted('`%s(...)`' % f for f in methods))}
|
||||
let rb = hub.${resource}();
|
||||
</%block>
|
||||
</%block>
|
||||
pub struct ${mb_type(resource)}<'a, C, NC, A>
|
||||
where NC: 'a,
|
||||
C: 'a,
|
||||
A: 'a, {
|
||||
|
||||
hub: &'a ${hub_type}<C, NC, A>
|
||||
}
|
||||
|
||||
impl<'a, C, NC, A> MethodBuilder for ${mb_type(resource)}<'a, C, NC, A> {}
|
||||
% endfor
|
||||
|
||||
|
||||
@@ -12,19 +12,13 @@
|
||||
# fr == fattest resource, the fatter, the more important, right ?
|
||||
fr = None
|
||||
fr = sorted(schemas.values(), key=lambda s: (len(c.sta_map.get(s.id, [])), len(s.get('properties', []))), reverse=True)[0]
|
||||
|
||||
# resouce -> [activity, ...]
|
||||
amap = dict()
|
||||
for an in c.fqan_map:
|
||||
resource, activity = activity_split(an)
|
||||
amap.setdefault(resource, list()).append(activity)
|
||||
%>\
|
||||
# Features
|
||||
|
||||
Handle the following *Resources* with ease ...
|
||||
|
||||
% for r in sorted(amap.keys()):
|
||||
* ${split_camelcase_s(r)} (${put_and(md_italic(sorted(amap[r])))})
|
||||
% for r in sorted(c.rta_map.keys()):
|
||||
* ${split_camelcase_s(r)} (${put_and(md_italic(sorted(c.rta_map[r])))})
|
||||
% endfor
|
||||
|
||||
# Structure of this Library
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<%! from util import (schema_markers, rust_doc_comment, mangle_ident, to_rust_type, put_and, IO_TYPES, activity_split) %>\
|
||||
<%! from util import (schema_markers, rust_doc_comment, mangle_ident, to_rust_type, put_and,
|
||||
IO_TYPES, activity_split, enclose_in)
|
||||
%>\
|
||||
## Create new schema with everything.
|
||||
## 's' contains the schema structure from json to build
|
||||
<%def name="new(s, c)">\
|
||||
@@ -34,8 +36,7 @@ ${s.get('description', 'There is no detailed description.')}
|
||||
# Activities
|
||||
|
||||
This type is used in activities, which are methods you may call on this type or where this type is involved in.
|
||||
The list links the activity name, along with information about where it is used (one of ${put_and(list('*%s*' % t
|
||||
for t in IO_TYPES))}).
|
||||
The list links the activity name, along with information about where it is used (one of ${put_and(enclose_in('*', IO_TYPES))}).
|
||||
|
||||
${''.join("* %s (%s)\n" % (activity_split(a)[1], iot and '|'.join(iot) or 'none')
|
||||
for a, iot in c.sta_map[s.id].iteritems())}
|
||||
|
||||
@@ -101,8 +101,17 @@ def put_and(l):
|
||||
return l[0]
|
||||
return ', '.join(l[:-1]) + ' and ' + l[-1]
|
||||
|
||||
# ['foo', ...] with e == '*' -> ['*foo*', ...]
|
||||
def enclose_in(e, l):
|
||||
return ['%s%s%s' % (e, s, e) for s in l]
|
||||
|
||||
def md_italic(l):
|
||||
return ['*%s*' % s for s in l]
|
||||
return enclose_in('*', l)
|
||||
|
||||
def singular(s):
|
||||
if s[-1] == 's':
|
||||
return s[:-1]
|
||||
return s
|
||||
|
||||
def split_camelcase_s(s):
|
||||
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1 \2', s)
|
||||
@@ -226,44 +235,6 @@ def schema_markers(s, c):
|
||||
# -------------------------
|
||||
## @name Activity Utilities
|
||||
# @{
|
||||
|
||||
# Returns (A, B) where
|
||||
# A: { SchemaTypeName -> { fqan -> ['request'|'response', ...]}
|
||||
# B: { fqan -> activity_method_data }
|
||||
# fqan = fully qualified activity name
|
||||
def build_activity_mappings(activities):
|
||||
res = dict()
|
||||
fqan = dict()
|
||||
for an, a in activities.iteritems():
|
||||
if 'methods' not in a:
|
||||
continue
|
||||
for mn, m in a.methods.iteritems():
|
||||
assert m.id not in fqan
|
||||
fqan[m.id] = m
|
||||
for in_out_type_name in IO_TYPES:
|
||||
t = m.get(in_out_type_name, None)
|
||||
if t is None:
|
||||
continue
|
||||
tn = to_rust_type(None, None, t, allow_optionals=False)
|
||||
info = res.setdefault(tn, dict())
|
||||
io_info = info.setdefault(m.id, [])
|
||||
io_info.append(in_out_type_name)
|
||||
# end for each io type
|
||||
|
||||
# handle delete/getrating/(possibly others)
|
||||
# delete: has no response or request
|
||||
# getrating: response is a 'SomethingResult', which is still related to activities name
|
||||
# the latter is used to deduce the resource name
|
||||
an, _ = activity_split(m.id)
|
||||
tn = activity_name_to_type_name(an)
|
||||
info = res.setdefault(tn, dict())
|
||||
if m.id not in info:
|
||||
info.setdefault(m.id, [])
|
||||
# end handle other cases
|
||||
# end for each method
|
||||
# end for each activity
|
||||
return res, fqan
|
||||
|
||||
# return (name, method)
|
||||
def activity_split(fqan):
|
||||
t = fqan.split('.')
|
||||
@@ -281,12 +252,54 @@ def iter_acitivities(c):
|
||||
## -- End Activity Utilities -- @}
|
||||
|
||||
|
||||
Context = collections.namedtuple('Context', ['sta_map', 'fqan_map'])
|
||||
Context = collections.namedtuple('Context', ['sta_map', 'fqan_map', 'rta_map'])
|
||||
|
||||
# return a newly build context from the given data
|
||||
def new_context(resources):
|
||||
# Returns (A, B) where
|
||||
# A: { SchemaTypeName -> { fqan -> ['request'|'response', ...]}
|
||||
# B: { fqan -> activity_method_data }
|
||||
# fqan = fully qualified activity name
|
||||
def build_activity_mappings(activities):
|
||||
res = dict()
|
||||
fqan = dict()
|
||||
for an, a in activities.iteritems():
|
||||
if 'methods' not in a:
|
||||
continue
|
||||
for mn, m in a.methods.iteritems():
|
||||
assert m.id not in fqan
|
||||
fqan[m.id] = m
|
||||
for in_out_type_name in IO_TYPES:
|
||||
t = m.get(in_out_type_name, None)
|
||||
if t is None:
|
||||
continue
|
||||
tn = to_rust_type(None, None, t, allow_optionals=False)
|
||||
info = res.setdefault(tn, dict())
|
||||
io_info = info.setdefault(m.id, [])
|
||||
io_info.append(in_out_type_name)
|
||||
# end for each io type
|
||||
|
||||
# handle delete/getrating/(possibly others)
|
||||
# delete: has no response or request
|
||||
# getrating: response is a 'SomethingResult', which is still related to activities name
|
||||
# the latter is used to deduce the resource name
|
||||
an, _ = activity_split(m.id)
|
||||
tn = activity_name_to_type_name(an)
|
||||
info = res.setdefault(tn, dict())
|
||||
if m.id not in info:
|
||||
info.setdefault(m.id, [])
|
||||
# end handle other cases
|
||||
# end for each method
|
||||
# end for each activity
|
||||
return res, fqan
|
||||
# end utility
|
||||
|
||||
sta_map, fqan_map = build_activity_mappings(resources)
|
||||
return Context(sta_map, fqan_map)
|
||||
rta_map = dict()
|
||||
for an in fqan_map:
|
||||
resource, activity = activity_split(an)
|
||||
rta_map.setdefault(resource, list()).append(activity)
|
||||
return Context(sta_map, fqan_map, rta_map)
|
||||
|
||||
# Expects v to be 'v\d+', throws otherwise
|
||||
def to_api_version(v):
|
||||
@@ -296,3 +309,7 @@ def to_api_version(v):
|
||||
# build a full library name (non-canonical)
|
||||
def library_name(name, version):
|
||||
return name + to_api_version(version)
|
||||
|
||||
# return type name of a resource builder, from a resource name
|
||||
def mb_type(r):
|
||||
return "%sMethodBuilder" % canonical_type_name(r)
|
||||
|
||||
@@ -5,6 +5,9 @@ use std::marker::MarkerTrait;
|
||||
/// The hub allows to access all resource methods more easily.
|
||||
pub trait Hub: MarkerTrait {}
|
||||
|
||||
/// Identifies types for building methods of a particular type
|
||||
pub trait MethodBuilder: 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 {}
|
||||
|
||||
@@ -43,7 +43,7 @@ impl<'a, C, NC, A> YouTube<C, NC, A>
|
||||
}
|
||||
|
||||
pub fn videos(&'a self) -> videos::Service<'a, C, NC, A> {
|
||||
videos::Service::new(&self.client, &self.auth)
|
||||
videos::Service::new(&self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ use rustc_serialize;
|
||||
use hyper;
|
||||
use oauth2;
|
||||
|
||||
use super::super::YouTube;
|
||||
|
||||
/// Reresents all aspects of a youtube video resource. May only be partially
|
||||
/// available
|
||||
#[derive(RustcEncodable, RustcDecodable, Default, Clone)]
|
||||
@@ -75,10 +77,7 @@ pub struct Service<'a, C, NC, A>
|
||||
C: 'a,
|
||||
A: 'a, {
|
||||
|
||||
client: &'a RefCell<C>,
|
||||
auth: &'a RefCell<A>,
|
||||
|
||||
_m: PhantomData<NC>
|
||||
hub: &'a YouTube<C, NC, A>
|
||||
}
|
||||
|
||||
impl<'a, C, NC, A> Service<'a, C, NC, A>
|
||||
@@ -86,21 +85,15 @@ impl<'a, C, NC, A> Service<'a, C, NC, A>
|
||||
C: BorrowMut<hyper::Client<NC>> + 'a,
|
||||
A: oauth2::GetToken + 'a {
|
||||
|
||||
pub fn new(client: &'a RefCell<C>, authenticator: &'a RefCell<A>) -> Service<'a, C, NC, A> {
|
||||
Service {
|
||||
client: client,
|
||||
auth: authenticator,
|
||||
_m: PhantomData,
|
||||
}
|
||||
pub fn new(hub: &'a YouTube<C, NC, A>) -> Service<'a, C, NC, A> {
|
||||
Service { hub: hub }
|
||||
}
|
||||
|
||||
pub fn insert(&self, parts: &str, video: &Video) -> VideosInsertBuilder<'a, C, NC, A> {
|
||||
VideosInsertBuilder {
|
||||
client: self.client,
|
||||
auth: self.auth,
|
||||
hub: self.hub,
|
||||
video: video.clone(),
|
||||
parts: parts.to_string(),
|
||||
_m: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,12 +103,9 @@ pub struct VideosInsertBuilder<'a, C, NC, A>
|
||||
C: 'a,
|
||||
A: 'a {
|
||||
|
||||
client: &'a RefCell<C>,
|
||||
auth: &'a RefCell<A>,
|
||||
hub: &'a YouTube<C, NC, A>,
|
||||
video: Video,
|
||||
parts: String,
|
||||
|
||||
_m: PhantomData<NC>
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user