Replace wrong simplification of vec of vec of strings

In Keystone.user MFA rules are vec of vec of strings. Current simplification
renders it as vec of strings loosing one level. Also indicate to the user array
parameters are actually arrays.

Change-Id: I382aa157b4b4286daf91f08af001a5db0247a88f
This commit is contained in:
Artem Goncharov
2025-03-19 15:50:14 +01:00
parent c3b231fb89
commit 5d8e2552b1
4 changed files with 67 additions and 13 deletions

View File

@@ -181,7 +181,10 @@ class Array(BaseCombinedType):
@property
def builder_macros(self):
macros = {"setter(into)"}
if isinstance(self.item_type, Array):
macros = {"private"}
else:
macros = {"setter(into)"}
return macros
def get_sample(self):
@@ -196,6 +199,13 @@ class Array(BaseCombinedType):
def clap_macros(self) -> set[str]:
return self.item_type.clap_macros
@property
def requires_builder_private_setter(self):
if isinstance(self.item_type, Array):
return True
else:
return False
class CommaSeparatedList(BaseCombinedType):
item_type: BasePrimitiveType | BaseCombinedType | BaseCompoundType
@@ -246,11 +256,16 @@ class Dictionary(BaseCombinedType):
class StructField(BaseModel):
local_name: str
remote_name: str
description: str | None = None
_description: str | None = None
data_type: BasePrimitiveType | BaseCombinedType | BaseCompoundType
is_optional: bool = True
is_nullable: bool = False
def __init__(self, description: str | None = None, **data):
super().__init__(**data)
if description is not None:
self._description = description
@property
def type_hint(self):
typ_hint = self.data_type.type_hint
@@ -258,6 +273,11 @@ class StructField(BaseModel):
typ_hint = f"Option<{typ_hint}>"
return typ_hint
@property
def description(self):
"""Description getter necessary for being able to override the property"""
return self._description
class Struct(BaseCompoundType):
base_type: str = "struct"

View File

@@ -187,6 +187,15 @@ class StructInputField(common_rust.StructField):
macros.add('help_heading = "Body parameters"')
return f"#[arg({', '.join(sorted(macros))})]"
@property
def description(self):
description = super().description
if isinstance(self.data_type, ArrayInput):
return (
description or ""
) + "\n\nParameter is an array, may be provided multiple times."
return description
class StructInput(common_rust.Struct):
field_type_class_: Type[common_rust.StructField] = StructInputField
@@ -376,6 +385,11 @@ class ArrayInput(common_rust.Array):
def clap_macros(self):
macros: set[str] = {"long", "action=clap::ArgAction::Append"}
macros.update(self.item_type.clap_macros)
if isinstance(self.item_type, ArrayInput):
macros.add("value_parser=parse_json")
macros.add(
f'value_name="[{self.item_type.item_type.type_hint}] as JSON"'
)
return macros
@@ -602,17 +616,6 @@ class RequestTypeManager(common_rust.TypeManager):
original_data_type=original_data_type,
item_type=JsonValue(),
)
elif isinstance(item_type, model.Array) and isinstance(
item_type.item_type, model.ConstraintString
):
original_data_type = self.convert_model(item_type)
typ = self.data_type_mapping[model.Array](
description=common_rust.sanitize_rust_docstrings(
type_model.description
),
original_data_type=original_data_type,
item_type=String(),
)
elif isinstance(type_model, model.Dictionary):
if isinstance(type_model.value_type, model.Dictionary):
original_data_type = self.convert_model(type_model.value_type)

View File

@@ -69,6 +69,10 @@ class ArrayInput(common_rust.Array):
result: str = source_var_name
if isinstance(self.item_type, common_rust.BaseCompoundType):
result += f".iter().flat_map(|x| TryFrom::try_from(x)).collect::<Vec<{'::'.join(sdk_mod_path)}::{self.item_type.name}>>()"
elif isinstance(self.item_type, ArrayInput) and isinstance(
self.item_type.item_type, common_rust.BasePrimitiveType
):
result += f".iter().cloned()"
elif isinstance(self.item_type, common_rust.BaseCombinedType):
if into:
result += ".iter()"

View File

@@ -134,6 +134,28 @@ Option
}
{%- endmacro %}
{%- macro sdk_builder_setter_vec_vec(field) %}
{%- set is_opt = False if field.data_type.__class__.__name__ != "Option" else True %}
{%- set dt = field.data_type if not is_opt else field.data_type.item_type %}
{{ macros.docstring(field.description, indent=4) }}
pub fn {{ field.local_name }}<I1, I2, V>(&mut self, iter: I1) -> &mut Self
where
I1: Iterator<Item = I2>,
I2: IntoIterator<Item = V>,
V: Into<{{ dt.item_type.item_type.type_hint }}>,
{
self.{{ field.local_name }}
{%- if field.is_optional %}
.get_or_insert(None)
{%- endif %}
.get_or_insert_with(Vec::new)
.extend(
iter.map(|x| Vec::from_iter(x.into_iter().map(Into::into)))
);
self
}
{%- endmacro %}
{#- Create DeriveBuilder setter method #}
{%- macro sdk_builder_setter(field) %}
{%- set dtc = field.data_type.__class__.__name__ %}
@@ -142,6 +164,8 @@ Option
{{ sdk_builder_setter_btreemap(field) }}
{%- elif dtc == "BTreeSet" or subdtc == "BTreeSet" %}
{{ sdk_builder_setter_btreeset(field) }}
{%- elif dtc == "Array" and subdtc == "Array" %}
{{ sdk_builder_setter_vec_vec(field) }}
{%- endif %}
{%- endmacro %}
@@ -358,6 +382,9 @@ Some({{ val }})
serde_json::from_value::<{{ sdk_mod_path[-1] }}::{{ original_type.name }}>(v.to_owned()))
.collect::<Vec<{{ sdk_mod_path[-1] }}:: {{ original_type.name }}>>();
{{ dst_var }}.{{ param.remote_name }}({{ builder_name }});
{%- elif param.data_type.item_type.__class__.__name__ == "ArrayInput" and param.data_type.item_type.__class__.__name__ == "ArrayInput" %}
{#- Array of Arrays - we should have the SDK setter for that #}
{{ dst_var }}.{{ param.remote_name }}({{ val_var }}.into_iter());
{%- elif param.data_type.item_type.__class__.__name__ == "String" and original_item_type.__class__.__name__ == "StructInput" %}
{#- Single field structure replaced with only string #}
{%- set original_type = param.data_type.item_type.original_data_type %}