a building version of the enums-change (cli is broken).

(at least youtube3 builds, the others get generated successfully)
This commit is contained in:
OMGeeky
2023-10-22 19:43:20 +02:00
parent cf0248f0f3
commit 8fc78fe0ae
8 changed files with 200 additions and 14 deletions

View File

@@ -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

View 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

View File

@@ -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

View 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

View File

@@ -46,3 +46,6 @@ pub use method_builders::*;
mod call_builders;
pub use call_builders::*;
mod enums;
pub use enums::*;

View File

@@ -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>

View File

@@ -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

View File

@@ -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.