Skip to content

Commit fc49079

Browse files
author
Tomasz Kulik
committed
feat: Add Python codegen
1 parent 6c6e2ad commit fc49079

File tree

12 files changed

+421
-31
lines changed

12 files changed

+421
-31
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
members = ["packages/*"]
3-
exclude = ["contracts"]
3+
exclude = ["contracts", "packages/cw-schema-codegen/playground"]
44

55
# Resolver has to be set explicitly in workspaces
66
# due to https://github.com/rust-lang/cargo/issues/9956
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

packages/cw-schema-codegen/playground/Cargo.lock

Lines changed: 96 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "serialization"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[features]
7+
deserialize = []
8+
9+
[dependencies]
10+
serde = { version = "1.0.215", features = ["derive", "serde_derive"] }
11+
serde_json = "1.0.133"
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
from dataclasses import dataclass, field
2+
from dataclasses_json import dataclass_json, config
3+
from typing import Optional, Iterable
4+
import sys
5+
import json
6+
7+
8+
# TODO tkulik: try to get rid of the `dataclasses_json` dependency
9+
10+
11+
enum_field = lambda: field(default=None, metadata=config(exclude=lambda x: x is None))
12+
13+
@dataclass_json
14+
@dataclass
15+
class SomeEnum:
16+
class VariantIndicator:
17+
pass
18+
19+
class Field3Type:
20+
a: str
21+
b: int
22+
23+
class Field5Type:
24+
a: Iterable['SomeEnum']
25+
26+
Field1: Optional[VariantIndicator] = enum_field()
27+
Field2: Optional[tuple[int, int]] = enum_field()
28+
Field3: Optional[Field3Type] = enum_field()
29+
Field4: Optional[Iterable['SomeEnum']] = enum_field()
30+
Field5: Optional[Field5Type] = enum_field()
31+
32+
def deserialize(json):
33+
if not ":" in json:
34+
if json == '"Field1"':
35+
return SomeEnum(Field1=SomeEnum.VariantIndicator())
36+
else:
37+
raise Exception(f"Deserialization error, undefined variant: {json}")
38+
else:
39+
return SomeEnum.from_json(json)
40+
41+
def serialize(self):
42+
if self.Field1 is not None:
43+
return '"Field1"'
44+
else:
45+
return SomeEnum.to_json(self)
46+
47+
@dataclass_json
48+
@dataclass
49+
class UnitStructure:
50+
def deserialize(json):
51+
if json == "null":
52+
return UnitStructure()
53+
else:
54+
Exception(f"Deserialization error, undefined value: {json}")
55+
56+
def serialize(self):
57+
return 'null'
58+
59+
@dataclass_json
60+
@dataclass
61+
class TupleStructure:
62+
Tuple: tuple[int, str, int]
63+
64+
def deserialize(json):
65+
return TupleStructure.from_json(f'{{ "Tuple": {json} }}')
66+
67+
def serialize(self):
68+
return json.dumps(self.Tuple)
69+
70+
@dataclass_json
71+
@dataclass
72+
class NamedStructure:
73+
a: str
74+
b: int
75+
c: Iterable['SomeEnum']
76+
77+
def deserialize(json):
78+
return NamedStructure.from_json(json)
79+
80+
def serialize(self):
81+
return self.to_json()
82+
83+
###
84+
### TESTS:
85+
###
86+
87+
for (index, input) in enumerate(sys.stdin):
88+
input = input.rstrip()
89+
try:
90+
if index < 5:
91+
deserialized = SomeEnum.deserialize(input)
92+
elif index == 5:
93+
deserialized = UnitStructure.deserialize(input)
94+
elif index == 6:
95+
deserialized = TupleStructure.deserialize(input)
96+
else:
97+
deserialized = NamedStructure.deserialize(input)
98+
except:
99+
raise(Exception(f"This json can't be deserialized: {input}"))
100+
serialized = deserialized.serialize()
101+
print(serialized)
102+
103+
104+
# def handle_msg(json):
105+
# a = SomeEnum.deserialize(json)
106+
# if a.Field1 is not None:
107+
# print("SomeEnum::Field1")
108+
# elif a.Field2 is not None:
109+
# print(a.Field2[0])
110+
# print(a.Field2[1])
111+
# elif a.Field3 is not None:
112+
# print(a.Field3)
113+
# elif a.Field4 is not None:
114+
# print(a.Field4)
115+
# elif a.Field5 is not None:
116+
# print(a.Field5)
117+
118+
# handle_msg('"Field1"')
119+
# handle_msg('{"Field2": [10, 12]}')
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
use serde::{Deserialize, Serialize};
3+
4+
5+
#[derive(Serialize, Deserialize)]
6+
pub enum SomeEnum {
7+
Field1,
8+
Field2(u32, u32),
9+
Field3 {
10+
a: String,
11+
b: u32
12+
},
13+
Field4(Box<SomeEnum>),
14+
Field5 { a: Box<SomeEnum> },
15+
}
16+
17+
#[derive(Serialize, Deserialize)]
18+
pub struct UnitStructure;
19+
20+
#[derive(Serialize, Deserialize)]
21+
pub struct TupleStructure(u32, String, u128);
22+
23+
#[derive(Serialize, Deserialize)]
24+
pub struct NamedStructure {
25+
a: String,
26+
b: u8,
27+
c: SomeEnum
28+
}
29+
30+
31+
#[cfg(not(feature = "deserialize"))]
32+
fn main() {
33+
println!("{}", serde_json::to_string(&SomeEnum::Field1).unwrap());
34+
println!("{}", serde_json::to_string(&SomeEnum::Field2(10, 23)).unwrap());
35+
println!("{}", serde_json::to_string(&SomeEnum::Field3 {a: "sdf".to_string(), b: 12}).unwrap());
36+
println!("{}", serde_json::to_string(&SomeEnum::Field4(Box::new(SomeEnum::Field1))).unwrap());
37+
println!("{}", serde_json::to_string(&SomeEnum::Field5 { a: Box::new(SomeEnum::Field1) }).unwrap());
38+
println!("{}", serde_json::to_string(&UnitStructure {}).unwrap());
39+
println!("{}", serde_json::to_string(&TupleStructure(10, "aasdf".to_string(), 2)).unwrap());
40+
println!("{}", serde_json::to_string(&NamedStructure {a: "awer".to_string(), b: 4, c: SomeEnum::Field1}).unwrap());
41+
}
42+
43+
#[cfg(feature = "deserialize")]
44+
fn main() {
45+
use std::io::BufRead;
46+
for (index, line) in std::io::BufReader::new(std::io::stdin()).lines().enumerate() {
47+
let line = line.unwrap();
48+
println!("{line}");
49+
if index < 5 {
50+
let _: SomeEnum = serde_json::from_str(&line).unwrap();
51+
} else if index == 5 {
52+
let _: UnitStructure = serde_json::from_str(&line).unwrap();
53+
} else if index == 6 {
54+
let _: TupleStructure = serde_json::from_str(&line).unwrap();
55+
} else {
56+
let _: NamedStructure = serde_json::from_str(&line).unwrap();
57+
}
58+
}
59+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cargo run | python playground.py | cargo run --features "deserialize"

packages/cw-schema-codegen/src/python/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ fn expand_node_name<'a>(
4343
cw_schema::NodeType::HexBinary => todo!(),
4444
cw_schema::NodeType::Timestamp => todo!(),
4545
cw_schema::NodeType::Unit => Cow::Borrowed("void"),
46+
_ => todo!()
4647
}
4748
}
4849

@@ -82,6 +83,7 @@ where
8283
.map(|item| expand_node_name(schema, &schema.definitions[*item]))
8384
.collect(),
8485
),
86+
_ => todo!()
8587
},
8688
};
8789

@@ -123,6 +125,7 @@ where
123125
.collect(),
124126
}
125127
}
128+
_ => todo!()
126129
},
127130
})
128131
.collect(),

0 commit comments

Comments
 (0)