mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2026-02-23 15:49:49 +01:00
feat(builders): request type handling part 1
Now we will generate proper resoure methods builder calls to instaniate the more or less valid method builders. However, it doesn't compile yet, and the 'to_parts()' method on resources is still missing.
This commit is contained in:
@@ -21,7 +21,7 @@ pub trait Resource: MarkerTrait {}
|
|||||||
pub trait ResponseResult: MarkerTrait {}
|
pub trait ResponseResult: MarkerTrait {}
|
||||||
|
|
||||||
/// Identifies types which are used in API requests.
|
/// Identifies types which are used in API requests.
|
||||||
pub trait RequestResult: MarkerTrait {}
|
pub trait RequestValue: MarkerTrait {}
|
||||||
|
|
||||||
/// Identifies types which are only used as part of other types, which
|
/// Identifies types which are only used as part of other types, which
|
||||||
/// usually are carrying the `Resource` trait.
|
/// usually are carrying the `Resource` trait.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,8 @@
|
|||||||
from util import (put_and, rust_test_fn_invisible, rust_doc_test_norun, rust_doc_comment,
|
from util import (put_and, rust_test_fn_invisible, rust_doc_test_norun, rust_doc_comment,
|
||||||
rb_type, mb_type, singular, hub_type, to_fqan, indent_all_but_first_by,
|
rb_type, mb_type, singular, hub_type, to_fqan, indent_all_but_first_by,
|
||||||
method_params, activity_rust_type, mangle_ident, activity_input_type, get_word,
|
method_params, activity_rust_type, mangle_ident, activity_input_type, get_word,
|
||||||
split_camelcase_s, property, is_pod_property, TREF)
|
split_camelcase_s, property, is_pod_property, TREF, method_io, IO_REQUEST,
|
||||||
|
RESOURCE_MARKER, schema_to_required_property, rust_copy_value_s, is_required_property)
|
||||||
%>\
|
%>\
|
||||||
<%namespace name="util" file="util.mako"/>\
|
<%namespace name="util" file="util.mako"/>\
|
||||||
<%namespace name="lib" file="lib.mako"/>\
|
<%namespace name="lib" file="lib.mako"/>\
|
||||||
@@ -16,6 +17,11 @@
|
|||||||
m = c.fqan_map[to_fqan(name, resource, method)]
|
m = c.fqan_map[to_fqan(name, resource, method)]
|
||||||
# an identifier for a property. We prefix them to prevent clashes with the setters
|
# an identifier for a property. We prefix them to prevent clashes with the setters
|
||||||
ThisType = mb_type(resource, method) + "<'a, C, NC, A>"
|
ThisType = mb_type(resource, method) + "<'a, C, NC, A>"
|
||||||
|
|
||||||
|
request_resource = method_io(schemas, c, m, IO_REQUEST, RESOURCE_MARKER)
|
||||||
|
params = method_params(m)
|
||||||
|
if request_resource:
|
||||||
|
params.insert(0, schema_to_required_property(request_resource, 'request'))
|
||||||
%>\
|
%>\
|
||||||
% if 'description' in m:
|
% if 'description' in m:
|
||||||
${m.description | rust_doc_comment}
|
${m.description | rust_doc_comment}
|
||||||
@@ -51,8 +57,13 @@ pub struct ${ThisType}
|
|||||||
|
|
||||||
hub: &'a ${hub_type_name}<C, NC, A>,
|
hub: &'a ${hub_type_name}<C, NC, A>,
|
||||||
## PROPERTIES ###############
|
## PROPERTIES ###############
|
||||||
% for p in method_params(m):
|
% for p in params:
|
||||||
${property(p.name)}: ${activity_rust_type(p)},
|
${property(p.name)}:\
|
||||||
|
% if is_required_property(p):
|
||||||
|
${activity_rust_type(p, allow_optionals=False)},
|
||||||
|
% else:
|
||||||
|
${activity_rust_type(p)},
|
||||||
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +79,7 @@ impl<'a, C, NC, A> ${ThisType} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
## SETTERS ###############
|
## SETTERS ###############
|
||||||
% for p in method_params(m):
|
% for p in params:
|
||||||
${self._setter(resource, method, m, p, ThisType, c)}\
|
${self._setter(resource, method, m, p, ThisType, c)}\
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
@@ -90,11 +101,9 @@ ${self._setter(resource, method, m, p, ThisType, c)}\
|
|||||||
return m.request.get(TREF, 'first') == m.response.get(TREF, 'second')
|
return m.request.get(TREF, 'first') == m.response.get(TREF, 'second')
|
||||||
|
|
||||||
value_name = 'new_value'
|
value_name = 'new_value'
|
||||||
new_value_copied = value_name + '.clone()'
|
new_value_copied = rust_copy_value_s(value_name, InType, p)
|
||||||
if InType == '&str':
|
if not is_required_property(p):
|
||||||
new_value_copied = value_name + '.to_string()'
|
new_value_copied = 'Some(%s)' % new_value_copied
|
||||||
elif is_pod_property(p):
|
|
||||||
new_value_copied = value_name
|
|
||||||
%>\
|
%>\
|
||||||
/// Sets the *${split_camelcase_s(p.name)}* ${get_word(p, 'location')}property to the given value.
|
/// Sets the *${split_camelcase_s(p.name)}* ${get_word(p, 'location')}property to the given value.
|
||||||
///
|
///
|
||||||
@@ -104,7 +113,7 @@ ${self._setter(resource, method, m, p, ThisType, c)}\
|
|||||||
/// This may not always be desirable, as you can obtain (newly generated) parts you cannot pass in,
|
/// This may not always be desirable, as you can obtain (newly generated) parts you cannot pass in,
|
||||||
/// like statistics that are generated server side. Therefore you should use this method to specify
|
/// like statistics that are generated server side. Therefore you should use this method to specify
|
||||||
/// the parts you provide in addition to the ones you want in the response.
|
/// the parts you provide in addition to the ones you want in the response.
|
||||||
% elif p.get('required', False):
|
% elif is_required_property(p):
|
||||||
/// Even though the property as already been set when instantiating this call,
|
/// Even though the property as already been set when instantiating this call,
|
||||||
/// we provide this method for API completeness.
|
/// we provide this method for API completeness.
|
||||||
% endif
|
% endif
|
||||||
@@ -113,7 +122,7 @@ ${self._setter(resource, method, m, p, ThisType, c)}\
|
|||||||
${p.description | rust_doc_comment, indent_all_but_first_by(1)}
|
${p.description | rust_doc_comment, indent_all_but_first_by(1)}
|
||||||
% endif
|
% endif
|
||||||
pub fn ${mangle_ident(p.name)}(&mut self, ${value_name}: ${InType}) -> &mut ${ThisType} {
|
pub fn ${mangle_ident(p.name)}(&mut self, ${value_name}: ${InType}) -> &mut ${ThisType} {
|
||||||
self.${property(p.name)} = Some(${new_value_copied});
|
self.${property(p.name)} = ${new_value_copied};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
<%!
|
<%!
|
||||||
from util import (put_and, rust_test_fn_invisible, rust_doc_test_norun, rust_doc_comment,
|
from util import (put_and, rust_test_fn_invisible, rust_doc_test_norun, rust_doc_comment,
|
||||||
rb_type, singular, hub_type, mangle_ident, mb_type, method_params, property,
|
rb_type, singular, hub_type, mangle_ident, mb_type, method_params, property,
|
||||||
to_fqan, indent_all_but_first_by)
|
to_fqan, indent_all_but_first_by, RESOURCE_MARKER, schema_markers,
|
||||||
|
activity_input_type, TREF, method_io, IO_REQUEST, schema_to_required_property,
|
||||||
|
rust_copy_value_s, is_required_property)
|
||||||
%>\
|
%>\
|
||||||
<%namespace name="util" file="util.mako"/>\
|
<%namespace name="util" file="util.mako"/>\
|
||||||
<%namespace name="lib" file="lib.mako"/>\
|
<%namespace name="lib" file="lib.mako"/>\
|
||||||
@@ -49,6 +51,33 @@ impl<'a, C, NC, A> ${ThisType} {
|
|||||||
<%
|
<%
|
||||||
m = c.fqan_map[to_fqan(name, resource, a)]
|
m = c.fqan_map[to_fqan(name, resource, a)]
|
||||||
RType = mb_type(resource, a)
|
RType = mb_type(resource, a)
|
||||||
|
|
||||||
|
# skip part if we have a request resource. Only resources can have parts
|
||||||
|
# that we can easily deduce
|
||||||
|
request_resource = method_io(schemas, c, m, IO_REQUEST, RESOURCE_MARKER)
|
||||||
|
params = method_params(m)
|
||||||
|
REQUEST_RESOURCE_PROPERTY_NAME = 'request'
|
||||||
|
if request_resource:
|
||||||
|
# resource into property
|
||||||
|
resprop = schema_to_required_property(request_resource, REQUEST_RESOURCE_PROPERTY_NAME)
|
||||||
|
params.insert(0, resprop)
|
||||||
|
|
||||||
|
part_prop = None
|
||||||
|
optional_props = list()
|
||||||
|
required_props = list()
|
||||||
|
for p in params:
|
||||||
|
if is_required_property(p):
|
||||||
|
if request_resource and p.name == 'part':
|
||||||
|
part_prop = p
|
||||||
|
else:
|
||||||
|
required_props.append(p)
|
||||||
|
else:
|
||||||
|
optional_props.append(p)
|
||||||
|
# end for each property
|
||||||
|
|
||||||
|
method_args = ''
|
||||||
|
if required_props:
|
||||||
|
method_args = ', ' + ', '.join('%s: %s' % (mangle_ident(p.name), activity_input_type(p)) for p in required_props)
|
||||||
%>\
|
%>\
|
||||||
|
|
||||||
% if 'description' in m:
|
% if 'description' in m:
|
||||||
@@ -56,10 +85,17 @@ impl<'a, C, NC, A> ${ThisType} {
|
|||||||
///
|
///
|
||||||
${m.description | rust_doc_comment, indent_all_but_first_by(1)}
|
${m.description | rust_doc_comment, indent_all_but_first_by(1)}
|
||||||
% endif
|
% endif
|
||||||
pub fn ${mangle_ident(a)}(&self) -> ${RType}<'a, C, NC, A> {
|
pub fn ${mangle_ident(a)}(&self${method_args}) -> ${RType}<'a, C, NC, A> {
|
||||||
${RType} {
|
${RType} {
|
||||||
hub: self.hub,
|
hub: self.hub,
|
||||||
% for p in method_params(m):
|
% for p in required_props:
|
||||||
|
${property(p.name)}: ${rust_copy_value_s(mangle_ident(p.name), activity_input_type(p), p)},
|
||||||
|
% endfor
|
||||||
|
## auto-generate parts from request resources
|
||||||
|
% if part_prop and request_resource:
|
||||||
|
${property(part_prop.name)}: ${mangle_ident(REQUEST_RESOURCE_PROPERTY_NAME)}.to_parts(),
|
||||||
|
% endif
|
||||||
|
% for p in optional_props:
|
||||||
${property(p.name)}: Default::default(),
|
${property(p.name)}: Default::default(),
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ pub struct ${s.id}\
|
|||||||
% for marker_trait in markers:
|
% for marker_trait in markers:
|
||||||
impl ${marker_trait} for ${s.id} {}
|
impl ${marker_trait} for ${s.id} {}
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
|
% if RESOURCE_MARKER in markers:
|
||||||
|
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="doc(s, c)">\
|
<%def name="doc(s, c)">\
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ DEL_METHOD = 'delete'
|
|||||||
NESTED_TYPE_MARKER = 'is_nested'
|
NESTED_TYPE_MARKER = 'is_nested'
|
||||||
SPACES_PER_TAB = 4
|
SPACES_PER_TAB = 4
|
||||||
|
|
||||||
|
REQUEST_PRIORITY = 100
|
||||||
|
REQUEST_MARKER = 'RequestValue'
|
||||||
|
RESOURCE_MARKER = 'Resource'
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
## @name Filters
|
## @name Filters
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -225,7 +229,7 @@ def activity_input_type(p):
|
|||||||
return '&%s' % n
|
return '&%s' % n
|
||||||
|
|
||||||
def is_pod_property(p):
|
def is_pod_property(p):
|
||||||
return 'format' in p or p.type == 'boolean'
|
return 'format' in p or p.get('type','') == 'boolean'
|
||||||
|
|
||||||
# return an iterator yielding fake-schemas that identify a nested type
|
# return an iterator yielding fake-schemas that identify a nested type
|
||||||
def iter_nested_types(schemas):
|
def iter_nested_types(schemas):
|
||||||
@@ -252,11 +256,11 @@ def schema_markers(s, c):
|
|||||||
# it should have at least one activity that matches it's type to qualify for the Resource trait
|
# it should have at least one activity that matches it's type to qualify for the Resource trait
|
||||||
for fqan, iot in activities.iteritems():
|
for fqan, iot in activities.iteritems():
|
||||||
if activity_name_to_type_name(activity_split(fqan)[0]).lower() == s.id.lower():
|
if activity_name_to_type_name(activity_split(fqan)[0]).lower() == s.id.lower():
|
||||||
res.add('Resource')
|
res.add(RESOURCE_MARKER)
|
||||||
if IO_RESPONSE in iot:
|
if IO_RESPONSE in iot:
|
||||||
res.add('ResponseResult')
|
res.add('ResponseResult')
|
||||||
if IO_REQUEST in iot:
|
if IO_REQUEST in iot:
|
||||||
res.add('RequestResult')
|
res.add(REQUEST_MARKER)
|
||||||
# end for each activity
|
# end for each activity
|
||||||
# end handle activites
|
# end handle activites
|
||||||
|
|
||||||
@@ -319,6 +323,32 @@ def method_params(m, required=None, location=None):
|
|||||||
# end for each parameter
|
# end for each parameter
|
||||||
return sorted(res, key=lambda p: (p.priority, p.name), reverse=True)
|
return sorted(res, key=lambda p: (p.priority, p.name), reverse=True)
|
||||||
|
|
||||||
|
# return the given method's request or response schema (dict), or None.
|
||||||
|
# optionally return only schemas with the given marker trait
|
||||||
|
def method_io(schemas, c, m, type, marker=None):
|
||||||
|
s = schemas.get(m.get('request', dict()).get(TREF))
|
||||||
|
if s is None:
|
||||||
|
return s
|
||||||
|
if s and marker and marker not in schema_markers(s, c):
|
||||||
|
return None
|
||||||
|
return s
|
||||||
|
|
||||||
|
# return string like 'n.clone()', but depending on the type name of tn (e.g. &str -> n.to_string())
|
||||||
|
def rust_copy_value_s(n, tn, p):
|
||||||
|
nc = n + '.clone()'
|
||||||
|
if tn == '&str':
|
||||||
|
nc = n + '.to_string()'
|
||||||
|
elif is_pod_property(p):
|
||||||
|
nc = n
|
||||||
|
return nc
|
||||||
|
|
||||||
|
# convert a schema into a property (for use with rust type generation).
|
||||||
|
# n = name of the property
|
||||||
|
def schema_to_required_property(s, n):
|
||||||
|
return type(s)({'name': n, TREF: s.id, 'priority': REQUEST_PRIORITY})
|
||||||
|
|
||||||
|
def is_required_property(p):
|
||||||
|
return p.get('required', False) or p.get('priority', 0) > 0
|
||||||
|
|
||||||
## -- End Activity Utilities -- @}
|
## -- End Activity Utilities -- @}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pub trait Resource: MarkerTrait {}
|
|||||||
pub trait ResponseResult: MarkerTrait {}
|
pub trait ResponseResult: MarkerTrait {}
|
||||||
|
|
||||||
/// Identifies types which are used in API requests.
|
/// Identifies types which are used in API requests.
|
||||||
pub trait RequestResult: MarkerTrait {}
|
pub trait RequestValue: MarkerTrait {}
|
||||||
|
|
||||||
/// Identifies types which are only used as part of other types, which
|
/// Identifies types which are only used as part of other types, which
|
||||||
/// usually are carrying the `Resource` trait.
|
/// usually are carrying the `Resource` trait.
|
||||||
|
|||||||
Reference in New Issue
Block a user