mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2025-12-26 17:02:24 +01:00
a building version of the enums-change (cli is broken).
(at least youtube3 builds, the others get generated successfully)
This commit is contained in:
@@ -32,6 +32,8 @@ make:
|
||||
output_dir: src
|
||||
- source: api/call_builders.rs
|
||||
output_dir: src
|
||||
- source: api/enums.rs
|
||||
output_dir: src
|
||||
cargo:
|
||||
keywords: [protocol, web, api]
|
||||
doc_base_url: https://docs.rs
|
||||
|
||||
96
src/generator/lib/enum_utils.py
Normal file
96
src/generator/lib/enum_utils.py
Normal file
@@ -0,0 +1,96 @@
|
||||
from .rust_type import RustType
|
||||
from .types import Base
|
||||
from .util import Context, UNUSED_TYPE_MARKER, schema_markers, canonical_type_name, remove_invalid_chars_in_ident, \
|
||||
singular
|
||||
|
||||
|
||||
def is_property_enum(s: dict) -> bool:
|
||||
enum = s.get("enum")
|
||||
enum_description = s.get("enumDescriptions")
|
||||
if enum is None:
|
||||
return False
|
||||
if enum_description is None:
|
||||
print("could not find enumDescriptions for enum in s", s)
|
||||
return True
|
||||
|
||||
|
||||
def get_enum_type(schema_name: str, property_name: str, t, s) -> RustType:
|
||||
if schema_name is None:
|
||||
# print('schema_name was None:', property_name, t)
|
||||
schema_name = ""
|
||||
if len(schema_name) == 0:
|
||||
schema = ""
|
||||
else:
|
||||
schema = remove_invalid_chars_in_ident(singular(schema_name))
|
||||
name = canonical_type_name(schema
|
||||
+ remove_invalid_chars_in_ident(canonical_type_name(property_name))
|
||||
+ "Enum")
|
||||
# print(name, '\n')
|
||||
return Base(name)
|
||||
|
||||
|
||||
def _add_enum_value(k, pk, pv, enums: dict):
|
||||
if is_property_enum(pv):
|
||||
enum_type = get_enum_type(k, pk, None, None)
|
||||
# print('enum type:', enum_type)
|
||||
enums[enum_type] = (k, pk, enum_type, pv)
|
||||
return enums
|
||||
|
||||
inner_pv = _get_inner_enum(pv)
|
||||
if inner_pv:
|
||||
return _add_enum_value(k, pk, inner_pv, enums)
|
||||
|
||||
return enums
|
||||
|
||||
|
||||
def _get_inner_enum(pv: dict):
|
||||
items = pv.get('items')
|
||||
if items and is_property_enum(items):
|
||||
return items
|
||||
additional = pv.get('additionalProperties')
|
||||
if additional and is_property_enum(additional):
|
||||
return additional
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _parse_method_id(method_id: str, c: Context) -> str:
|
||||
parts = method_id.split('.')
|
||||
if len(parts) != 3:
|
||||
return method_id
|
||||
context = c.rtc_map.get(parts[1])
|
||||
|
||||
if context is None or parts[0] != context:
|
||||
print('context was not equal to first part: ', context, parts[0], method_id)
|
||||
return method_id
|
||||
|
||||
methods = c.rta_map.get(parts[1])
|
||||
if methods is None or parts[2] not in methods:
|
||||
print('third part was not in methods', methods, parts[2], method_id)
|
||||
|
||||
return parts[1]
|
||||
|
||||
|
||||
def find_enums_in_context(c: Context) -> list:
|
||||
enums = {}
|
||||
for k, s in c.schemas.items():
|
||||
if UNUSED_TYPE_MARKER not in schema_markers(s, c, transitive=True):
|
||||
# properties = s.get('properties')
|
||||
# printed_name = False
|
||||
if s.properties:
|
||||
for pv, pk in zip(s.properties.values(), s.properties.keys()):
|
||||
enums = _add_enum_value(k, pk, pv, enums)
|
||||
|
||||
for k, v in c.fqan_map.items():
|
||||
# print(k)
|
||||
k = _parse_method_id(k, c)
|
||||
if v.parameters:
|
||||
for pk, pv in v.parameters.items():
|
||||
enums = _add_enum_value(k, pk, pv, enums)
|
||||
return list(enums.values())
|
||||
|
||||
|
||||
def to_enum_variant_name(name: str) -> str:
|
||||
c_name = canonical_type_name(name)
|
||||
c_name = remove_invalid_chars_in_ident(c_name)
|
||||
return c_name
|
||||
@@ -371,9 +371,16 @@ def nested_type_name(sn, pn):
|
||||
|
||||
# Make properties which are reserved keywords usable
|
||||
def mangle_ident(n):
|
||||
n = camel_to_under(n).replace('-', '.').replace('.', '_').replace('$', '')
|
||||
n = camel_to_under(n)
|
||||
return remove_invalid_chars_in_ident(n)
|
||||
|
||||
|
||||
def remove_invalid_chars_in_ident(n):
|
||||
n = n.replace('-', '.').replace('.', '_').replace('$', '')
|
||||
if n in RESERVED_WORDS:
|
||||
return n + '_'
|
||||
n = n + '_'
|
||||
if n[0] in '0123456789':
|
||||
n = '_' + n
|
||||
return n
|
||||
|
||||
|
||||
@@ -421,6 +428,7 @@ def to_rust_type_inner(
|
||||
allow_optionals=True,
|
||||
_is_recursive=False
|
||||
) -> RustType:
|
||||
from .enum_utils import is_property_enum, get_enum_type
|
||||
def nested_type(nt) -> RustType:
|
||||
if 'items' in nt:
|
||||
nt = nt['items']
|
||||
@@ -448,6 +456,9 @@ def to_rust_type_inner(
|
||||
rt = Option(Box(rt))
|
||||
return wrap_type(rt)
|
||||
try:
|
||||
if is_property_enum(t):
|
||||
x = get_enum_type(schema_name, property_name, t, schemas)
|
||||
return wrap_type(x)
|
||||
# prefer format if present
|
||||
rust_type = RUST_TYPE_MAP[t.get("format", t["type"])]
|
||||
if rust_type == Vec(None):
|
||||
@@ -478,10 +489,10 @@ def is_nested_type(s):
|
||||
|
||||
# convert a rust-type to something that would be taken as input of a function
|
||||
# even though our storage type is different
|
||||
def activity_input_type(schemas, p):
|
||||
def activity_input_type(schemas, p, parent=None):
|
||||
if 'input_type' in p:
|
||||
return p.input_type
|
||||
n = activity_rust_type(schemas, p, allow_optionals=False)
|
||||
n = activity_rust_type(schemas, p, allow_optionals=False, parent=parent)
|
||||
if n == 'String':
|
||||
n = 'str'
|
||||
# pods are copied anyway
|
||||
@@ -580,8 +591,8 @@ def activity_split(fqan: str) -> Tuple[str, str, str]:
|
||||
|
||||
|
||||
# Shorthand to get a type from parameters of activities
|
||||
def activity_rust_type(schemas, p, allow_optionals=True):
|
||||
return to_rust_type(schemas, None, p.name, p, allow_optionals=allow_optionals)
|
||||
def activity_rust_type(schemas, p, allow_optionals=True, parent=None):
|
||||
return to_rust_type(schemas, parent, p.name, p, allow_optionals=allow_optionals)
|
||||
|
||||
|
||||
# the inverse of activity-split, but needs to know the 'name' of the API
|
||||
|
||||
25
src/generator/templates/api/api/enums.rs.mako
Normal file
25
src/generator/templates/api/api/enums.rs.mako
Normal file
@@ -0,0 +1,25 @@
|
||||
<%namespace name="lib" file="../lib/lib.mako"/>\
|
||||
<%namespace name="enum" file="../lib/enum.mako"/>\
|
||||
<%namespace name="util" file="../../../lib/util.mako"/>\
|
||||
<%namespace name="rbuild" file="../lib/rbuild.mako"/>\
|
||||
<%namespace name="mbuild" file="../lib/mbuild.mako"/>\
|
||||
<%namespace name="schema" file="../lib/schema.mako"/>\
|
||||
<%
|
||||
from generator.lib.util import (new_context, hub_type, hub_type_params_s)
|
||||
from generator.lib.enum_utils import (find_enums_in_context)
|
||||
|
||||
c = new_context(schemas, resources)
|
||||
hub_type = hub_type(c.schemas, util.canonical_name())
|
||||
ht_params = hub_type_params_s()
|
||||
|
||||
enums = find_enums_in_context(c)
|
||||
|
||||
default_user_agent = "google-api-rust-client/" + cargo.build_version
|
||||
%>\
|
||||
use super::*;
|
||||
|
||||
|
||||
|
||||
% for schema_name,property_name,enum_type, e in enums:
|
||||
${enum.new(enum_type, e, c)}
|
||||
% endfor
|
||||
@@ -46,3 +46,6 @@ pub use method_builders::*;
|
||||
|
||||
mod call_builders;
|
||||
pub use call_builders::*;
|
||||
|
||||
mod enums;
|
||||
pub use enums::*;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
upload_action_fn, METHODS_BUILDER_MARKER_TRAIT, DELEGATE_TYPE,
|
||||
to_extern_crate_name, rust_doc_sanitize)
|
||||
|
||||
from generator.lib.enum_utils import (to_enum_variant_name)
|
||||
|
||||
def pretty_name(name):
|
||||
return ' '.join(split_camelcase_s(name).split('.'))
|
||||
%>\
|
||||
@@ -64,4 +66,50 @@ impl Default for Scope {
|
||||
${scope_url_to_variant(name, default_url)}
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
</%def>
|
||||
|
||||
|
||||
<%def name="new(enum_type, e, c)">\
|
||||
#[derive(Clone, Copy, Eq, Hash, Debug, PartialEq, Serialize, Deserialize)]
|
||||
% if e.get('description'):
|
||||
/// ${e.description}
|
||||
% endif
|
||||
pub enum ${enum_type} {
|
||||
% for (variant_name,description) in zip(e.get('enum'), e.get('enumDescriptions')):
|
||||
<% #print(variant_name, '=>', description)
|
||||
%>
|
||||
% if description:
|
||||
|
||||
/// ${description}
|
||||
///
|
||||
% endif\
|
||||
/// value:
|
||||
/// "${variant_name}"
|
||||
${to_enum_variant_name(variant_name)},
|
||||
% endfor
|
||||
}
|
||||
|
||||
impl AsRef<str> for ${enum_type} {
|
||||
fn as_ref(&self) -> &str {
|
||||
match *self {
|
||||
% for variant in e.get('enum'):
|
||||
${enum_type}::${to_enum_variant_name(variant)} => "${variant_name}",
|
||||
% endfor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<std::borrow::Cow<'a, str>> for &'a ${enum_type} {
|
||||
fn into(self) -> std::borrow::Cow<'a, str> {
|
||||
self.as_ref().into()
|
||||
}
|
||||
}
|
||||
|
||||
% if e.get('default') is not None:
|
||||
impl Default for ${enum_type} {
|
||||
fn default() -> ${enum_type} {
|
||||
${enum_type}::${to_enum_variant_name(e.get('default'))}
|
||||
}
|
||||
}
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
@@ -125,9 +125,9 @@ pub struct ${ThisType}
|
||||
% for p in params:
|
||||
pub(super) ${property(p.name)}:\
|
||||
% if is_required_property(p):
|
||||
${activity_rust_type(schemas, p, allow_optionals=False)},
|
||||
${activity_rust_type(schemas, p, allow_optionals=False, parent=resource)},
|
||||
% else:
|
||||
${activity_rust_type(schemas, p)},
|
||||
${activity_rust_type(schemas, p, parent=resource)},
|
||||
% endif
|
||||
% endfor
|
||||
## A generic map for additinal parameters. Sometimes you can set some that are documented online only
|
||||
@@ -223,11 +223,11 @@ ${self._setter_fn(resource, method, m, p, part_prop, ThisType, c)}\
|
||||
###############################################################################################
|
||||
<%def name="_setter_fn(resource, method, m, p, part_prop, ThisType, c)">\
|
||||
<%
|
||||
InType = activity_input_type(schemas, p)
|
||||
InType = activity_input_type(schemas, p, parent=resource)
|
||||
|
||||
if is_repeated_property(p):
|
||||
p.repeated = False
|
||||
InType = activity_input_type(schemas, p)
|
||||
InType = activity_input_type(schemas, p, parent=resource)
|
||||
p.repeated = True
|
||||
|
||||
def show_part_info(m, p):
|
||||
@@ -312,7 +312,7 @@ ${self._setter_fn(resource, method, m, p, part_prop, ThisType, c)}\
|
||||
# could also just skip the first element, but ... let's be safe
|
||||
if request_value and request_value.id == p.get(TREF):
|
||||
continue
|
||||
v = rnd_arg_val_for_type(activity_input_type(schemas, p))
|
||||
v = rnd_arg_val_for_type(activity_input_type(schemas, p, parent=resource))
|
||||
# we chose to replace random strings with their meaning, as indicated by the name !
|
||||
if is_string_value(v):
|
||||
v = '"%s"' % p.name
|
||||
@@ -590,7 +590,7 @@ match result {
|
||||
params.push("${p.name}", ${to_string_impl("value")});
|
||||
}
|
||||
% else:
|
||||
params.push("${p.name}", ${to_string_impl(pname)});
|
||||
params.push("${p.name}", &${to_string_impl(pname)});
|
||||
% endif
|
||||
% endfor
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
hub_type_name = hub_type(schemas, util.canonical_name())
|
||||
rb_params = rb_type_params_s(resource, c)
|
||||
ThisType = rb_type(resource) + rb_params
|
||||
parent = resource
|
||||
%>\
|
||||
% if resource == METHODS_RESOURCE:
|
||||
/// A builder providing access to all free methods, which are not associated with a particular resource.
|
||||
@@ -65,7 +66,7 @@ impl${rb_params} ${ThisType} {
|
||||
|
||||
method_args = ''
|
||||
if required_props:
|
||||
method_args = ', ' + ', '.join('%s: %s' % (mangle_ident(p.name), activity_input_type(schemas, p)) for p in required_props)
|
||||
method_args = ', ' + ', '.join('%s: %s' % (mangle_ident(p.name), activity_input_type(schemas, p, parent=parent)) for p in required_props)
|
||||
|
||||
mb_tparams = mb_type_params_s(m)
|
||||
# we would could have information about data requirements for each property in it's dict.
|
||||
|
||||
Reference in New Issue
Block a user