diff --git a/packages/cw-schema-codegen/src/lib.rs b/packages/cw-schema-codegen/src/lib.rs index b56983812..224f90fb8 100644 --- a/packages/cw-schema-codegen/src/lib.rs +++ b/packages/cw-schema-codegen/src/lib.rs @@ -1,3 +1,4 @@ pub mod go; +pub mod python; pub mod rust; pub mod typescript; diff --git a/packages/cw-schema-codegen/src/main.rs b/packages/cw-schema-codegen/src/main.rs index 86cd7a2b4..b8038d315 100644 --- a/packages/cw-schema-codegen/src/main.rs +++ b/packages/cw-schema-codegen/src/main.rs @@ -70,7 +70,8 @@ where Language::Typescript => { cw_schema_codegen::typescript::process_node(output, schema, node) } - Language::Go | Language::Python => todo!(), + Language::Python => cw_schema_codegen::python::process_node(output, schema, node), + Language::Go => todo!(), } })?; diff --git a/packages/cw-schema-codegen/src/python/mod.rs b/packages/cw-schema-codegen/src/python/mod.rs new file mode 100644 index 000000000..74f3d9e00 --- /dev/null +++ b/packages/cw-schema-codegen/src/python/mod.rs @@ -0,0 +1,137 @@ +use self::template::{ + EnumTemplate, EnumVariantTemplate, FieldTemplate, StructTemplate, TypeTemplate, +}; +use heck::ToPascalCase; +use std::{borrow::Cow, io}; + +pub mod template; + +fn expand_node_name<'a>( + schema: &'a cw_schema::SchemaV1, + node: &'a cw_schema::Node, +) -> Cow<'a, str> { + match node.value { + cw_schema::NodeType::Array { items } => { + let items = &schema.definitions[items]; + format!("{}[]", expand_node_name(schema, items)).into() + } + cw_schema::NodeType::Float => "number".into(), + cw_schema::NodeType::Double => "number".into(), + cw_schema::NodeType::Boolean => "boolean".into(), + cw_schema::NodeType::String => "string".into(), + cw_schema::NodeType::Integer { .. } => "string".into(), + cw_schema::NodeType::Binary => "Uint8Array".into(), + cw_schema::NodeType::Optional { inner } => { + let inner = &schema.definitions[inner]; + format!("{} | null", expand_node_name(schema, inner)).into() + } + cw_schema::NodeType::Struct(..) => node.name.as_ref().into(), + cw_schema::NodeType::Tuple { ref items } => { + let items = items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect::>() + .join(", "); + + format!("[{}]", items).into() + } + cw_schema::NodeType::Enum { .. } => node.name.as_ref().into(), + + cw_schema::NodeType::Decimal { .. } => "string".into(), + cw_schema::NodeType::Address => "string".into(), + cw_schema::NodeType::Checksum => todo!(), + cw_schema::NodeType::HexBinary => todo!(), + cw_schema::NodeType::Timestamp => todo!(), + cw_schema::NodeType::Unit => Cow::Borrowed("void"), + } +} + +fn prepare_docs(desc: Option<&str>) -> Cow<'_, [Cow<'_, str>]> { + desc.map(|desc| desc.lines().map(Into::into).collect()) + .unwrap_or(Cow::Borrowed(&[])) +} + +pub fn process_node( + output: &mut O, + schema: &cw_schema::SchemaV1, + node: &cw_schema::Node, +) -> io::Result<()> +where + O: io::Write, +{ + match node.value { + cw_schema::NodeType::Struct(ref sty) => { + let structt = StructTemplate { + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + ty: match sty { + cw_schema::StructType::Unit => TypeTemplate::Unit, + cw_schema::StructType::Named { ref properties } => TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Borrowed(name), + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name(schema, &schema.definitions[prop.value]), + }) + .collect(), + }, + cw_schema::StructType::Tuple { ref items } => TypeTemplate::Tuple( + items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect(), + ), + }, + }; + + writeln!(output, "{structt}")?; + } + cw_schema::NodeType::Enum { ref cases, .. } => { + let enumm = EnumTemplate { + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + variants: cases + .iter() + .map(|(name, case)| EnumVariantTemplate { + name: name.clone(), + docs: prepare_docs(case.description.as_deref()), + ty: match case.value { + cw_schema::EnumValue::Unit => TypeTemplate::Unit, + cw_schema::EnumValue::Tuple { ref items } => { + let items = items + .iter() + .map(|item| { + expand_node_name(schema, &schema.definitions[*item]) + }) + .collect(); + + TypeTemplate::Tuple(items) + } + cw_schema::EnumValue::Named { ref properties, .. } => { + TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Borrowed(name), + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name( + schema, + &schema.definitions[prop.value], + ), + }) + .collect(), + } + } + }, + }) + .collect(), + }; + + writeln!(output, "{enumm}")?; + } + _ => (), + } + + Ok(()) +} diff --git a/packages/cw-schema-codegen/src/python/template.rs b/packages/cw-schema-codegen/src/python/template.rs new file mode 100644 index 000000000..11b860ed9 --- /dev/null +++ b/packages/cw-schema-codegen/src/python/template.rs @@ -0,0 +1,41 @@ +use askama::Template; +use std::borrow::Cow; + +#[derive(Clone)] +pub struct EnumVariantTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, +} + +#[derive(Template)] +#[template(escape = "none", path = "python/enum.tpl.py")] +pub struct EnumTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub variants: Cow<'a, [EnumVariantTemplate<'a>]>, +} + +#[derive(Clone)] +pub struct FieldTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: Cow<'a, str>, +} + +#[derive(Clone)] +pub enum TypeTemplate<'a> { + Unit, + Tuple(Cow<'a, [Cow<'a, str>]>), + Named { + fields: Cow<'a, [FieldTemplate<'a>]>, + }, +} + +#[derive(Template)] +#[template(escape = "none", path = "python/struct.tpl.py")] +pub struct StructTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, +} diff --git a/packages/cw-schema-codegen/templates/python/enum.tpl.py b/packages/cw-schema-codegen/templates/python/enum.tpl.py new file mode 100644 index 000000000..21ee91261 --- /dev/null +++ b/packages/cw-schema-codegen/templates/python/enum.tpl.py @@ -0,0 +1,40 @@ +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +/** +{% for doc in docs %} + * {{ doc }} +{% endfor %} + */ + +type {{ name }} = +{% for variant in variants %} + | + + /** + {% for doc in variant.docs %} + * {{ doc }} + {% endfor %} + */ + + {% match variant.ty %} + {% when TypeTemplate::Unit %} + { "{{ variant.name }}": {} } + {% when TypeTemplate::Tuple with (types) %} + { "{{ variant.name }}": [{{ types|join(", ") }}] } + {% when TypeTemplate::Named with { fields } %} + { "{{ variant.name }}": { + {% for field in fields %} + /** + {% for doc in field.docs %} + * {{ doc }} + {% endfor %} + */ + + {{ field.name }}: {{ field.ty }}; + {% endfor %} + } } + {% endmatch %} +{% endfor %} +; + +export { {{ name }} }; diff --git a/packages/cw-schema-codegen/templates/python/struct.tpl.py b/packages/cw-schema-codegen/templates/python/struct.tpl.py new file mode 100644 index 000000000..08b30d5d4 --- /dev/null +++ b/packages/cw-schema-codegen/templates/python/struct.tpl.py @@ -0,0 +1,30 @@ +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +/** +{% for doc in docs %} + * {{ doc }} +{% endfor %} + */ + +type {{ name }} = +{% match ty %} + {% when TypeTemplate::Unit %} + void + {% when TypeTemplate::Tuple with (types) %} + [{{ types|join(", ") }}] + {% when TypeTemplate::Named with { fields } %} + { + {% for field in fields %} + /** + {% for doc in field.docs %} + * {{ doc }} + {% endfor %} + */ + + {{ field.name }}: {{ field.ty }}; + {% endfor %} + } +{% endmatch %} +; + +export { {{ name }} }; diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__complex_enum.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__complex_enum.snap index d219e9437..e1c4a9758 100644 --- a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__complex_enum.snap +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__complex_enum.snap @@ -1,7 +1,11 @@ --- source: packages/cw-schema-codegen/tests/rust_tpl.rs expression: rendered +snapshot_kind: text --- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + #[doc = "Complex enum"] @@ -18,9 +22,7 @@ pub enum Complex { One ( - - u64, - + u64 ) , diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_enum.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_enum.snap index 876c882b0..cb79d1753 100644 --- a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_enum.snap +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_enum.snap @@ -1,7 +1,11 @@ --- source: packages/cw-schema-codegen/tests/rust_tpl.rs expression: rendered +snapshot_kind: text --- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + #[doc = "Empty enum"] diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_struct.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_struct.snap index 6766ff832..3103d42b2 100644 --- a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_struct.snap +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_struct.snap @@ -1,7 +1,11 @@ --- source: packages/cw-schema-codegen/tests/rust_tpl.rs expression: rendered +snapshot_kind: text --- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + #[doc = "Empty struct"] diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__named_struct.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__named_struct.snap index f37ab2f6b..dd3525ae0 100644 --- a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__named_struct.snap +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__named_struct.snap @@ -1,7 +1,11 @@ --- source: packages/cw-schema-codegen/tests/rust_tpl.rs expression: rendered +snapshot_kind: text --- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + #[doc = "Named struct"] diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__simple_enum.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__simple_enum.snap index c5d5dd0f9..e7ed6b8cf 100644 --- a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__simple_enum.snap +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__simple_enum.snap @@ -1,7 +1,11 @@ --- source: packages/cw-schema-codegen/tests/rust_tpl.rs expression: rendered +snapshot_kind: text --- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + #[doc = "Simple enum"] diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__tuple_struct.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__tuple_struct.snap index 54d55450b..358693556 100644 --- a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__tuple_struct.snap +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__tuple_struct.snap @@ -1,7 +1,11 @@ --- source: packages/cw-schema-codegen/tests/rust_tpl.rs expression: rendered +snapshot_kind: text --- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + #[doc = "Tuple struct"] @@ -10,9 +14,5 @@ pub struct Tuple ( - - u64, - - String, - + u64, String );