Skip to content

Commit 6c6e2ad

Browse files
author
Tomasz Kulik
committed
feat: Python codegen init
1 parent 4de3214 commit 6c6e2ad

File tree

12 files changed

+257
-1
lines changed

12 files changed

+257
-1
lines changed

packages/cw-schema-codegen/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod go;
2+
pub mod python;
23
pub mod rust;
34
pub mod typescript;

packages/cw-schema-codegen/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ where
7070
Language::Typescript => {
7171
cw_schema_codegen::typescript::process_node(output, schema, node)
7272
}
73-
Language::Go | Language::Python => todo!(),
73+
Language::Python => cw_schema_codegen::python::process_node(output, schema, node),
74+
Language::Go => todo!(),
7475
}
7576
})?;
7677

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
use self::template::{
2+
EnumTemplate, EnumVariantTemplate, FieldTemplate, StructTemplate, TypeTemplate,
3+
};
4+
use heck::ToPascalCase;
5+
use std::{borrow::Cow, io};
6+
7+
pub mod template;
8+
9+
fn expand_node_name<'a>(
10+
schema: &'a cw_schema::SchemaV1,
11+
node: &'a cw_schema::Node,
12+
) -> Cow<'a, str> {
13+
match node.value {
14+
cw_schema::NodeType::Array { items } => {
15+
let items = &schema.definitions[items];
16+
format!("{}[]", expand_node_name(schema, items)).into()
17+
}
18+
cw_schema::NodeType::Float => "number".into(),
19+
cw_schema::NodeType::Double => "number".into(),
20+
cw_schema::NodeType::Boolean => "boolean".into(),
21+
cw_schema::NodeType::String => "string".into(),
22+
cw_schema::NodeType::Integer { .. } => "string".into(),
23+
cw_schema::NodeType::Binary => "Uint8Array".into(),
24+
cw_schema::NodeType::Optional { inner } => {
25+
let inner = &schema.definitions[inner];
26+
format!("{} | null", expand_node_name(schema, inner)).into()
27+
}
28+
cw_schema::NodeType::Struct(..) => node.name.as_ref().into(),
29+
cw_schema::NodeType::Tuple { ref items } => {
30+
let items = items
31+
.iter()
32+
.map(|item| expand_node_name(schema, &schema.definitions[*item]))
33+
.collect::<Vec<_>>()
34+
.join(", ");
35+
36+
format!("[{}]", items).into()
37+
}
38+
cw_schema::NodeType::Enum { .. } => node.name.as_ref().into(),
39+
40+
cw_schema::NodeType::Decimal { .. } => "string".into(),
41+
cw_schema::NodeType::Address => "string".into(),
42+
cw_schema::NodeType::Checksum => todo!(),
43+
cw_schema::NodeType::HexBinary => todo!(),
44+
cw_schema::NodeType::Timestamp => todo!(),
45+
cw_schema::NodeType::Unit => Cow::Borrowed("void"),
46+
}
47+
}
48+
49+
fn prepare_docs(desc: Option<&str>) -> Cow<'_, [Cow<'_, str>]> {
50+
desc.map(|desc| desc.lines().map(Into::into).collect())
51+
.unwrap_or(Cow::Borrowed(&[]))
52+
}
53+
54+
pub fn process_node<O>(
55+
output: &mut O,
56+
schema: &cw_schema::SchemaV1,
57+
node: &cw_schema::Node,
58+
) -> io::Result<()>
59+
where
60+
O: io::Write,
61+
{
62+
match node.value {
63+
cw_schema::NodeType::Struct(ref sty) => {
64+
let structt = StructTemplate {
65+
name: node.name.clone(),
66+
docs: prepare_docs(node.description.as_deref()),
67+
ty: match sty {
68+
cw_schema::StructType::Unit => TypeTemplate::Unit,
69+
cw_schema::StructType::Named { ref properties } => TypeTemplate::Named {
70+
fields: properties
71+
.iter()
72+
.map(|(name, prop)| FieldTemplate {
73+
name: Cow::Borrowed(name),
74+
docs: prepare_docs(prop.description.as_deref()),
75+
ty: expand_node_name(schema, &schema.definitions[prop.value]),
76+
})
77+
.collect(),
78+
},
79+
cw_schema::StructType::Tuple { ref items } => TypeTemplate::Tuple(
80+
items
81+
.iter()
82+
.map(|item| expand_node_name(schema, &schema.definitions[*item]))
83+
.collect(),
84+
),
85+
},
86+
};
87+
88+
writeln!(output, "{structt}")?;
89+
}
90+
cw_schema::NodeType::Enum { ref cases, .. } => {
91+
let enumm = EnumTemplate {
92+
name: node.name.clone(),
93+
docs: prepare_docs(node.description.as_deref()),
94+
variants: cases
95+
.iter()
96+
.map(|(name, case)| EnumVariantTemplate {
97+
name: name.clone(),
98+
docs: prepare_docs(case.description.as_deref()),
99+
ty: match case.value {
100+
cw_schema::EnumValue::Unit => TypeTemplate::Unit,
101+
cw_schema::EnumValue::Tuple { ref items } => {
102+
let items = items
103+
.iter()
104+
.map(|item| {
105+
expand_node_name(schema, &schema.definitions[*item])
106+
})
107+
.collect();
108+
109+
TypeTemplate::Tuple(items)
110+
}
111+
cw_schema::EnumValue::Named { ref properties, .. } => {
112+
TypeTemplate::Named {
113+
fields: properties
114+
.iter()
115+
.map(|(name, prop)| FieldTemplate {
116+
name: Cow::Borrowed(name),
117+
docs: prepare_docs(prop.description.as_deref()),
118+
ty: expand_node_name(
119+
schema,
120+
&schema.definitions[prop.value],
121+
),
122+
})
123+
.collect(),
124+
}
125+
}
126+
},
127+
})
128+
.collect(),
129+
};
130+
131+
writeln!(output, "{enumm}")?;
132+
}
133+
_ => (),
134+
}
135+
136+
Ok(())
137+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use askama::Template;
2+
use std::borrow::Cow;
3+
4+
#[derive(Clone)]
5+
pub struct EnumVariantTemplate<'a> {
6+
pub name: Cow<'a, str>,
7+
pub docs: Cow<'a, [Cow<'a, str>]>,
8+
pub ty: TypeTemplate<'a>,
9+
}
10+
11+
#[derive(Template)]
12+
#[template(escape = "none", path = "python/enum.tpl.py")]
13+
pub struct EnumTemplate<'a> {
14+
pub name: Cow<'a, str>,
15+
pub docs: Cow<'a, [Cow<'a, str>]>,
16+
pub variants: Cow<'a, [EnumVariantTemplate<'a>]>,
17+
}
18+
19+
#[derive(Clone)]
20+
pub struct FieldTemplate<'a> {
21+
pub name: Cow<'a, str>,
22+
pub docs: Cow<'a, [Cow<'a, str>]>,
23+
pub ty: Cow<'a, str>,
24+
}
25+
26+
#[derive(Clone)]
27+
pub enum TypeTemplate<'a> {
28+
Unit,
29+
Tuple(Cow<'a, [Cow<'a, str>]>),
30+
Named {
31+
fields: Cow<'a, [FieldTemplate<'a>]>,
32+
},
33+
}
34+
35+
#[derive(Template)]
36+
#[template(escape = "none", path = "python/struct.tpl.py")]
37+
pub struct StructTemplate<'a> {
38+
pub name: Cow<'a, str>,
39+
pub docs: Cow<'a, [Cow<'a, str>]>,
40+
pub ty: TypeTemplate<'a>,
41+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# This code is @generated by cw-schema-codegen. Do not modify this manually.
2+
3+
/**
4+
{% for doc in docs %}
5+
* {{ doc }}
6+
{% endfor %}
7+
*/
8+
9+
type {{ name }} =
10+
{% for variant in variants %}
11+
|
12+
13+
/**
14+
{% for doc in variant.docs %}
15+
* {{ doc }}
16+
{% endfor %}
17+
*/
18+
19+
{% match variant.ty %}
20+
{% when TypeTemplate::Unit %}
21+
{ "{{ variant.name }}": {} }
22+
{% when TypeTemplate::Tuple with (types) %}
23+
{ "{{ variant.name }}": [{{ types|join(", ") }}] }
24+
{% when TypeTemplate::Named with { fields } %}
25+
{ "{{ variant.name }}": {
26+
{% for field in fields %}
27+
/**
28+
{% for doc in field.docs %}
29+
* {{ doc }}
30+
{% endfor %}
31+
*/
32+
33+
{{ field.name }}: {{ field.ty }};
34+
{% endfor %}
35+
} }
36+
{% endmatch %}
37+
{% endfor %}
38+
;
39+
40+
export { {{ name }} };
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This code is @generated by cw-schema-codegen. Do not modify this manually.
2+
3+
/**
4+
{% for doc in docs %}
5+
* {{ doc }}
6+
{% endfor %}
7+
*/
8+
9+
type {{ name }} =
10+
{% match ty %}
11+
{% when TypeTemplate::Unit %}
12+
void
13+
{% when TypeTemplate::Tuple with (types) %}
14+
[{{ types|join(", ") }}]
15+
{% when TypeTemplate::Named with { fields } %}
16+
{
17+
{% for field in fields %}
18+
/**
19+
{% for doc in field.docs %}
20+
* {{ doc }}
21+
{% endfor %}
22+
*/
23+
24+
{{ field.name }}: {{ field.ty }};
25+
{% endfor %}
26+
}
27+
{% endmatch %}
28+
;
29+
30+
export { {{ name }} };

packages/cw-schema-codegen/tests/snapshots/rust_tpl__complex_enum.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
source: packages/cw-schema-codegen/tests/rust_tpl.rs
33
expression: rendered
4+
snapshot_kind: text
45
---
56
// This code is @generated by cw-schema-codegen. Do not modify this manually.
67

packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_enum.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
source: packages/cw-schema-codegen/tests/rust_tpl.rs
33
expression: rendered
4+
snapshot_kind: text
45
---
56
// This code is @generated by cw-schema-codegen. Do not modify this manually.
67

packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_struct.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
source: packages/cw-schema-codegen/tests/rust_tpl.rs
33
expression: rendered
4+
snapshot_kind: text
45
---
56
// This code is @generated by cw-schema-codegen. Do not modify this manually.
67

packages/cw-schema-codegen/tests/snapshots/rust_tpl__named_struct.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
source: packages/cw-schema-codegen/tests/rust_tpl.rs
33
expression: rendered
4+
snapshot_kind: text
45
---
56
// This code is @generated by cw-schema-codegen. Do not modify this manually.
67

0 commit comments

Comments
 (0)