use sigil_stitch::code_block::CodeBlock;
use sigil_stitch::lang::python::Python;
use sigil_stitch::spec::enum_variant_spec::EnumVariantSpec;
use sigil_stitch::spec::field_spec::FieldSpec;
use sigil_stitch::spec::file_spec::FileSpec;
use sigil_stitch::spec::fun_spec::FunSpec;
use sigil_stitch::spec::modifiers::TypeKind;
use sigil_stitch::spec::parameter_spec::ParameterSpec;
use sigil_stitch::spec::type_spec::TypeSpec;
use sigil_stitch::type_name::TypeName;
use super::golden;
#[test]
fn test_dataclass() {
let file = FileSpec::builder_with("config.py", Python::new())
.add_type(
TypeSpec::builder("Config", TypeKind::Class)
.doc("Application configuration.")
.annotation(CodeBlock::of("@dataclass", ()).unwrap())
.add_field(
FieldSpec::builder("name", TypeName::primitive("str"))
.build()
.unwrap(),
)
.add_field(
FieldSpec::builder("port", TypeName::primitive("int"))
.build()
.unwrap(),
)
.add_field(
FieldSpec::builder("debug", TypeName::primitive("bool"))
.initializer(CodeBlock::of("False", ()).unwrap())
.build()
.unwrap(),
)
.build()
.unwrap(),
)
.build()
.unwrap();
let output = file.render(80).unwrap();
golden::assert_golden("python/dataclass.py", &output);
}
#[test]
fn test_class_with_methods() {
let file = FileSpec::builder_with("service.py", Python::new())
.add_type(
TypeSpec::builder("UserService", TypeKind::Class)
.doc("Service for managing users.")
.add_field(
FieldSpec::builder("_repo", TypeName::primitive("UserRepository"))
.build()
.unwrap(),
)
.add_method(
FunSpec::builder("get_user")
.add_param(ParameterSpec::new("self", TypeName::primitive("")).unwrap())
.add_param(
ParameterSpec::new("user_id", TypeName::primitive("str")).unwrap(),
)
.returns(TypeName::primitive("User"))
.body(CodeBlock::of("return self._repo.find(user_id)", ()).unwrap())
.build()
.unwrap(),
)
.add_method(
FunSpec::builder("save_user")
.add_param(ParameterSpec::new("self", TypeName::primitive("")).unwrap())
.add_param(ParameterSpec::new("user", TypeName::primitive("User")).unwrap())
.returns(TypeName::primitive("None"))
.body(CodeBlock::of("self._repo.save(user)", ()).unwrap())
.build()
.unwrap(),
)
.build()
.unwrap(),
)
.build()
.unwrap();
let output = file.render(80).unwrap();
golden::assert_golden("python/class_with_methods.py", &output);
}
#[test]
fn test_class_with_bases() {
let base = TypeName::primitive("BaseService");
let auth = TypeName::primitive("Authenticatable");
let file = FileSpec::builder_with("admin.py", Python::new())
.add_type(
TypeSpec::builder("AdminService", TypeKind::Class)
.extends(base)
.implements(auth)
.add_method(
FunSpec::builder("is_admin")
.add_param(ParameterSpec::new("self", TypeName::primitive("")).unwrap())
.returns(TypeName::primitive("bool"))
.body(CodeBlock::of("return True", ()).unwrap())
.build()
.unwrap(),
)
.build()
.unwrap(),
)
.build()
.unwrap();
let output = file.render(80).unwrap();
golden::assert_golden("python/class_with_bases.py", &output);
}
#[test]
fn test_protocol() {
let protocol = TypeName::importable("typing", "Protocol");
let file = FileSpec::builder_with("repo.py", Python::new())
.add_type(
TypeSpec::builder("Repository", TypeKind::Interface)
.doc("Repository defines data access methods.")
.extends(protocol)
.add_method(
FunSpec::builder("find_by_id")
.add_param(ParameterSpec::new("self", TypeName::primitive("")).unwrap())
.add_param(ParameterSpec::new("id", TypeName::primitive("str")).unwrap())
.returns(TypeName::primitive("Entity"))
.build()
.unwrap(),
)
.add_method(
FunSpec::builder("save")
.add_param(ParameterSpec::new("self", TypeName::primitive("")).unwrap())
.add_param(
ParameterSpec::new("entity", TypeName::primitive("Entity")).unwrap(),
)
.returns(TypeName::primitive("None"))
.build()
.unwrap(),
)
.build()
.unwrap(),
)
.build()
.unwrap();
let output = file.render(80).unwrap();
golden::assert_golden("python/protocol.py", &output);
}
#[test]
fn test_enum() {
let enum_base = TypeName::importable("enum", "Enum");
let tb = TypeSpec::builder("Direction", TypeKind::Enum)
.extends(enum_base)
.add_variant(
EnumVariantSpec::builder("UP")
.value(CodeBlock::of("'UP'", ()).unwrap())
.build()
.unwrap(),
)
.add_variant(
EnumVariantSpec::builder("DOWN")
.value(CodeBlock::of("'DOWN'", ()).unwrap())
.build()
.unwrap(),
)
.add_variant(
EnumVariantSpec::builder("LEFT")
.value(CodeBlock::of("'LEFT'", ()).unwrap())
.build()
.unwrap(),
)
.add_variant(
EnumVariantSpec::builder("RIGHT")
.value(CodeBlock::of("'RIGHT'", ()).unwrap())
.build()
.unwrap(),
);
let file = FileSpec::builder_with("direction.py", Python::new())
.add_type(tb.build().unwrap())
.build()
.unwrap();
let output = file.render(80).unwrap();
golden::assert_golden("python/enum.py", &output);
}