Skip to content

Commit

Permalink
feat: Add Python codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
kulikthebird committed Nov 21, 2024
1 parent cc10b12 commit 121bfb4
Show file tree
Hide file tree
Showing 12 changed files with 421 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
members = ["packages/*"]
exclude = ["contracts"]
exclude = ["contracts", "packages/cw-schema-codegen/playground"]

# Resolver has to be set explicitly in workspaces
# due to https://github.com/rust-lang/cargo/issues/9956
Expand Down
1 change: 1 addition & 0 deletions packages/cw-schema-codegen/playground/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
96 changes: 96 additions & 0 deletions packages/cw-schema-codegen/playground/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions packages/cw-schema-codegen/playground/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "serialization"
version = "0.1.0"
edition = "2021"

[features]
deserialize = []

[dependencies]
serde = { version = "1.0.215", features = ["derive", "serde_derive"] }
serde_json = "1.0.133"
119 changes: 119 additions & 0 deletions packages/cw-schema-codegen/playground/playground.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from dataclasses import dataclass, field
from dataclasses_json import dataclass_json, config
from typing import Optional, Iterable
import sys
import json


# TODO tkulik: try to get rid of the `dataclasses_json` dependency


enum_field = lambda: field(default=None, metadata=config(exclude=lambda x: x is None))

@dataclass_json
@dataclass
class SomeEnum:
class VariantIndicator:
pass

class Field3Type:
a: str
b: int

class Field5Type:
a: Iterable['SomeEnum']

Field1: Optional[VariantIndicator] = enum_field()
Field2: Optional[tuple[int, int]] = enum_field()
Field3: Optional[Field3Type] = enum_field()
Field4: Optional[Iterable['SomeEnum']] = enum_field()
Field5: Optional[Field5Type] = enum_field()

def deserialize(json):
if not ":" in json:
if json == '"Field1"':
return SomeEnum(Field1=SomeEnum.VariantIndicator())
else:
raise Exception(f"Deserialization error, undefined variant: {json}")
else:
return SomeEnum.from_json(json)

def serialize(self):
if self.Field1 is not None:
return '"Field1"'
else:
return SomeEnum.to_json(self)

@dataclass_json
@dataclass
class UnitStructure:
def deserialize(json):
if json == "null":
return UnitStructure()
else:
Exception(f"Deserialization error, undefined value: {json}")

def serialize(self):
return 'null'

@dataclass_json
@dataclass
class TupleStructure:
Tuple: tuple[int, str, int]

def deserialize(json):
return TupleStructure.from_json(f'{{ "Tuple": {json} }}')

def serialize(self):
return json.dumps(self.Tuple)

@dataclass_json
@dataclass
class NamedStructure:
a: str
b: int
c: Iterable['SomeEnum']

def deserialize(json):
return NamedStructure.from_json(json)

def serialize(self):
return self.to_json()

###
### TESTS:
###

for (index, input) in enumerate(sys.stdin):
input = input.rstrip()
try:
if index < 5:
deserialized = SomeEnum.deserialize(input)
elif index == 5:
deserialized = UnitStructure.deserialize(input)
elif index == 6:
deserialized = TupleStructure.deserialize(input)
else:
deserialized = NamedStructure.deserialize(input)
except:
raise(Exception(f"This json can't be deserialized: {input}"))
serialized = deserialized.serialize()
print(serialized)


# def handle_msg(json):
# a = SomeEnum.deserialize(json)
# if a.Field1 is not None:
# print("SomeEnum::Field1")
# elif a.Field2 is not None:
# print(a.Field2[0])
# print(a.Field2[1])
# elif a.Field3 is not None:
# print(a.Field3)
# elif a.Field4 is not None:
# print(a.Field4)
# elif a.Field5 is not None:
# print(a.Field5)

# handle_msg('"Field1"')
# handle_msg('{"Field2": [10, 12]}')
59 changes: 59 additions & 0 deletions packages/cw-schema-codegen/playground/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

use serde::{Deserialize, Serialize};


#[derive(Serialize, Deserialize)]
pub enum SomeEnum {
Field1,
Field2(u32, u32),
Field3 {
a: String,
b: u32
},
Field4(Box<SomeEnum>),
Field5 { a: Box<SomeEnum> },
}

#[derive(Serialize, Deserialize)]
pub struct UnitStructure;

#[derive(Serialize, Deserialize)]
pub struct TupleStructure(u32, String, u128);

#[derive(Serialize, Deserialize)]
pub struct NamedStructure {
a: String,
b: u8,
c: SomeEnum
}


#[cfg(not(feature = "deserialize"))]
fn main() {
println!("{}", serde_json::to_string(&SomeEnum::Field1).unwrap());
println!("{}", serde_json::to_string(&SomeEnum::Field2(10, 23)).unwrap());
println!("{}", serde_json::to_string(&SomeEnum::Field3 {a: "sdf".to_string(), b: 12}).unwrap());
println!("{}", serde_json::to_string(&SomeEnum::Field4(Box::new(SomeEnum::Field1))).unwrap());
println!("{}", serde_json::to_string(&SomeEnum::Field5 { a: Box::new(SomeEnum::Field1) }).unwrap());
println!("{}", serde_json::to_string(&UnitStructure {}).unwrap());
println!("{}", serde_json::to_string(&TupleStructure(10, "aasdf".to_string(), 2)).unwrap());
println!("{}", serde_json::to_string(&NamedStructure {a: "awer".to_string(), b: 4, c: SomeEnum::Field1}).unwrap());
}

#[cfg(feature = "deserialize")]
fn main() {
use std::io::BufRead;
for (index, line) in std::io::BufReader::new(std::io::stdin()).lines().enumerate() {
let line = line.unwrap();
println!("{line}");
if index < 5 {
let _: SomeEnum = serde_json::from_str(&line).unwrap();
} else if index == 5 {
let _: UnitStructure = serde_json::from_str(&line).unwrap();
} else if index == 6 {
let _: TupleStructure = serde_json::from_str(&line).unwrap();
} else {
let _: NamedStructure = serde_json::from_str(&line).unwrap();
}
}
}
1 change: 1 addition & 0 deletions packages/cw-schema-codegen/playground/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cargo run | python playground.py | cargo run --features "deserialize"
3 changes: 3 additions & 0 deletions packages/cw-schema-codegen/src/python/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ fn expand_node_name<'a>(
cw_schema::NodeType::HexBinary => todo!(),
cw_schema::NodeType::Timestamp => todo!(),
cw_schema::NodeType::Unit => Cow::Borrowed("void"),
_ => todo!()
}
}

Expand Down Expand Up @@ -82,6 +83,7 @@ where
.map(|item| expand_node_name(schema, &schema.definitions[*item]))
.collect(),
),
_ => todo!()
},
};

Expand Down Expand Up @@ -123,6 +125,7 @@ where
.collect(),
}
}
_ => todo!()
},
})
.collect(),
Expand Down
Loading

0 comments on commit 121bfb4

Please sign in to comment.