///|
pub trait PyObjectInto {
to_py_object(Self) -> @py.PyObject
}
///|
pub impl PyObjectInto for Bool with to_py_object(self) {
@py.PyBool::from(self).obj()
}
///|
pub impl PyObjectInto for Int with to_py_object(self) {
@py.PyInteger::from(self.to_int64()).obj()
}
///|
pub impl PyObjectInto for Int64 with to_py_object(self) {
@py.PyInteger::from(self).obj()
}
///|
pub impl PyObjectInto for Double with to_py_object(self) {
@py.PyFloat::from(self).obj()
}
///|
pub impl PyObjectInto for String with to_py_object(self) {
@py.PyString::from(self).obj()
}
///|
pub impl PyObjectInto for @py.PyObject with to_py_object(self) {
self
}
///|
pub impl PyObjectInto for @py.PyBool with to_py_object(self) {
self.obj()
}
///|
pub impl PyObjectInto for @py.PyInteger with to_py_object(self) {
self.obj()
}
///|
pub impl PyObjectInto for @py.PyFloat with to_py_object(self) {
self.obj()
}
///|
pub impl PyObjectInto for @py.PyString with to_py_object(self) {
self.obj()
}
///|
pub impl PyObjectInto for @py.PyCallable with to_py_object(self) {
self.obj()
}
///|
pub impl PyObjectInto for @py.PyModule with to_py_object(self) {
self.obj()
}
///|
pub impl PyObjectInto for @py.PyDict with to_py_object(self) {
self.obj()
}
///|
pub impl PyObjectInto for @py.PyList with to_py_object(self) {
self.obj()
}
///|
pub impl PyObjectInto for @py.PyObjectEnum with to_py_object(self) {
match self {
PyCallable(x) => x.obj()
PyModule(m) => m.obj()
PyDict(d) => d.obj()
PyList(l) => l.obj()
PyTuple(t) => t.obj()
PyString(s) => s.obj()
PyBool(b) => b.obj()
PyFloat(f) => f.obj()
PyInteger(i) => i.obj()
PyClass(c) => c.obj()
}
}
///|
pub impl[T : PyObjectInto] PyObjectInto for Array[T] with to_py_object(self) {
(self.map(PyObjectInto::to_py_object(_)) |> @py.PyList::from).obj()
}
///|
pub impl[T, U] PyObjectInto for TypedPyTuple2[T, U] with to_py_object(self) {
self.tuple2.obj()
}
///|
struct TypedPyList[T] {
data : @py.PyList
}
///|
struct TypedPyTuple2[A, B] {
tuple2 : @py.PyTuple
}
///|
pub fn[A : PyObjectInto, B : PyObjectInto] TypedPyTuple2::new(
a : A,
b : B,
) -> TypedPyTuple2[A, B] {
let tuple = @py.PyTuple::new(2)
tuple..set(0, a.to_py_object())
tuple..set(1, b.to_py_object())
{ tuple2: tuple }
}
///|
struct TypedPyTuple3[A, B, C] {
tuple3 : @py.PyTuple
}
///|
pub fn[A : PyObjectInto, B : PyObjectInto, C : PyObjectInto] TypedPyTuple3::new(
a : A,
b : B,
c : C,
) -> TypedPyTuple3[A, B, C] {
let tuple = @py.PyTuple::new(3)
tuple..set(0, a.to_py_object())
tuple..set(1, b.to_py_object())
tuple..set(2, c.to_py_object())
{ tuple3: tuple }
}
///|
struct TypedPyDict[V] {
dict : @py.PyDict
}
///|
struct TypedCallable[A, R] {
callable : @py.PyCallable
}
///|
pub fn[A, R] TypedCallable::new(
callable : @py.PyCallable,
) -> TypedCallable[A, R] {
{ callable, }
}
///|
pub fn[V : PyObjectInto] TypedPyDict::new(
kvs : Array[(String, V)],
) -> TypedPyDict[V] {
let dict = @py.PyDict::new()
for v in kvs {
let (k, val) = v
dict.set(k, val.to_py_object())
}
{ dict, }
}
///|
pub impl[T] Show for TypedPyList[T] with output(self, logger) -> Unit {
self.data.output(logger)
}
///|
pub impl[A, B] Show for TypedPyTuple2[A, B] with output(self, logger) -> Unit {
self.tuple2.output(logger)
}
///|
pub impl[A, B, C] Show for TypedPyTuple3[A, B, C] with output(self, logger) -> Unit {
self.tuple3.output(logger)
}
///|
pub impl[V] Show for TypedPyDict[V] with output(self, logger) -> Unit {
self.dict.output(logger)
}
///|
pub fn[A : PyObjectInto, R : PyEnumFrom] TypedCallable::run(
self : TypedCallable[A, R],
a : A,
) -> R raise {
let args = @py.PyTuple::new(1)
args..set(0, a.to_py_object())
let r = self.callable.invoke(args~)
PyEnumFrom::from_py_object(r)
}
///|
pub trait PyEnumFrom {
from_py_object(obj : @py.PyObjectEnum?) -> Self raise ConvError
}
///|
pub impl PyEnumFrom for Bool with from_py_object(obj : @py.PyObjectEnum?) -> Bool raise ConvError {
guard obj is Some(obj) else { raise UnexpectedEmpty }
match obj {
@py.PyObjectEnum::PyBool(py_bool) => py_bool.to_bool()
_ => raise TypeError("Expected PyBool")
}
}
///|
pub impl PyEnumFrom for Int64 with from_py_object(obj : @py.PyObjectEnum?) -> Int64 raise ConvError {
guard obj is Some(obj) else { raise UnexpectedEmpty }
match obj {
@py.PyObjectEnum::PyInteger(py_int) => py_int.to_int64()
_ => raise TypeError("Expected PyInteger")
}
}
///|
pub impl PyEnumFrom for Double with from_py_object(obj : @py.PyObjectEnum?) -> Double raise ConvError {
guard obj is Some(obj) else { raise UnexpectedEmpty }
match obj {
@py.PyObjectEnum::PyFloat(py_float) => py_float.to_double()
_ => raise TypeError("Expected PyFloat")
}
}
///|
pub impl PyEnumFrom for String with from_py_object(obj : @py.PyObjectEnum?) -> String raise ConvError {
guard obj is Some(obj) else { raise UnexpectedEmpty }
match obj {
@py.PyObjectEnum::PyString(py_str) => @py.PyString::to_string(py_str)
_ => raise TypeError("Expected PyString")
}
}
///|
pub impl PyEnumFrom for Int with from_py_object(obj : @py.PyObjectEnum?) -> Int raise ConvError {
guard obj is Some(obj) else { raise UnexpectedEmpty }
match obj {
@py.PyObjectEnum::PyInteger(py_int) => py_int.to_int64().to_int()
_ => raise TypeError("Expected PyInteger")
}
}
///|
pub impl PyEnumFrom for @py.PyObjectEnum with from_py_object(
obj : @py.PyObjectEnum?,
) -> @py.PyObjectEnum raise ConvError {
guard obj is Some(obj) else { raise UnexpectedEmpty }
obj
}
///|
pub impl[A : PyEnumFrom, B : PyEnumFrom] PyEnumFrom for (A, B) with from_py_object(
self,
) {
guard self is Some(self) else { raise UnexpectedEmpty }
match self {
@py.PyObjectEnum::PyTuple(py_tuple) => {
guard py_tuple.len() == 2 else {
raise TypeError("Expected tuple of length 2")
}
let a_obj = py_tuple.get(0)
let b_obj = py_tuple.get(1)
let a = A::from_py_object(a_obj)
let b = B::from_py_object(b_obj)
(a, b)
}
_ => raise TypeError("Expected PyTuple")
}
}
///|
pub impl[A : PyEnumFrom, B : PyEnumFrom, C : PyEnumFrom] PyEnumFrom for (
A,
B,
C,
) with from_py_object(self) {
guard self is Some(self) else { raise UnexpectedEmpty }
match self {
@py.PyObjectEnum::PyTuple(py_tuple) => {
guard py_tuple.len() == 3 else {
raise TypeError("Expected tuple of length 3")
}
let a_obj = py_tuple.get(0)
let b_obj = py_tuple.get(1)
let c_obj = py_tuple.get(2)
let a = A::from_py_object(a_obj)
let b = B::from_py_object(b_obj)
let c = C::from_py_object(c_obj)
(a, b, c)
}
_ => raise TypeError("Expected PyTuple")
}
}
///|
test "python enum from tuple" {
let tuple_obj = TypedPyTuple2::new(42, "hello").tuple2
let py_enum = @py.PyObjectEnum::create(tuple_obj.obj())
let (a, b) : (Int, String) = PyEnumFrom::from_py_object(Some(py_enum))
assert_eq(a, 42)
assert_eq(b, "hello")
}
///|
pub suberror ConvError {
TypeError(String)
UnexpectedEmpty
}