mirror of https://github.com/exaloop/codon.git
Add __try_from_py__ API
parent
f3f3e7ee91
commit
732dfcbab3
|
@ -109,6 +109,7 @@ PyErr_SetString = Function[[cobj, cobj], NoneType](cobj())
|
||||||
Py_None = cobj()
|
Py_None = cobj()
|
||||||
Py_True = cobj()
|
Py_True = cobj()
|
||||||
Py_False = cobj()
|
Py_False = cobj()
|
||||||
|
Py_Ellipsis = cobj()
|
||||||
Py_NotImplemented = cobj()
|
Py_NotImplemented = cobj()
|
||||||
Py_LT = 0
|
Py_LT = 0
|
||||||
Py_LE = 1
|
Py_LE = 1
|
||||||
|
@ -117,6 +118,18 @@ Py_NE = 3
|
||||||
Py_GT = 4
|
Py_GT = 4
|
||||||
Py_GE = 5
|
Py_GE = 5
|
||||||
|
|
||||||
|
# types
|
||||||
|
PyLong_Type = cobj()
|
||||||
|
PyFloat_Type = cobj()
|
||||||
|
PyBool_Type = cobj()
|
||||||
|
PyUnicode_Type = cobj()
|
||||||
|
PyComplex_Type = cobj()
|
||||||
|
PyList_Type = cobj()
|
||||||
|
PyDict_Type = cobj()
|
||||||
|
PySet_Type = cobj()
|
||||||
|
PyTuple_Type = cobj()
|
||||||
|
PySlice_Type = cobj()
|
||||||
|
|
||||||
# exceptions
|
# exceptions
|
||||||
PyExc_BaseException = cobj()
|
PyExc_BaseException = cobj()
|
||||||
PyExc_Exception = cobj()
|
PyExc_Exception = cobj()
|
||||||
|
@ -269,7 +282,18 @@ def init_handles_dlopen(py_handle: cobj):
|
||||||
global Py_None
|
global Py_None
|
||||||
global Py_True
|
global Py_True
|
||||||
global Py_False
|
global Py_False
|
||||||
|
global Py_Ellipsis
|
||||||
global Py_NotImplemented
|
global Py_NotImplemented
|
||||||
|
global PyLong_Type
|
||||||
|
global PyFloat_Type
|
||||||
|
global PyBool_Type
|
||||||
|
global PyUnicode_Type
|
||||||
|
global PyComplex_Type
|
||||||
|
global PyList_Type
|
||||||
|
global PyDict_Type
|
||||||
|
global PySet_Type
|
||||||
|
global PyTuple_Type
|
||||||
|
global PySlice_Type
|
||||||
global PyExc_BaseException
|
global PyExc_BaseException
|
||||||
global PyExc_Exception
|
global PyExc_Exception
|
||||||
global PyExc_NameError
|
global PyExc_NameError
|
||||||
|
@ -384,7 +408,18 @@ def init_handles_dlopen(py_handle: cobj):
|
||||||
Py_None = dlsym(py_handle, "_Py_NoneStruct")
|
Py_None = dlsym(py_handle, "_Py_NoneStruct")
|
||||||
Py_True = dlsym(py_handle, "_Py_TrueStruct")
|
Py_True = dlsym(py_handle, "_Py_TrueStruct")
|
||||||
Py_False = dlsym(py_handle, "_Py_FalseStruct")
|
Py_False = dlsym(py_handle, "_Py_FalseStruct")
|
||||||
|
Py_Ellipsis = dlsym(py_handle, "_Py_EllipsisObject")
|
||||||
Py_NotImplemented = dlsym(py_handle, "_Py_NotImplementedStruct")
|
Py_NotImplemented = dlsym(py_handle, "_Py_NotImplementedStruct")
|
||||||
|
PyLong_Type = dlsym(py_handle, "PyLong_Type")
|
||||||
|
PyFloat_Type = dlsym(py_handle, "PyFloat_Type")
|
||||||
|
PyBool_Type = dlsym(py_handle, "PyBool_Type")
|
||||||
|
PyUnicode_Type = dlsym(py_handle, "PyUnicode_Type")
|
||||||
|
PyComplex_Type = dlsym(py_handle, "PyComplex_Type")
|
||||||
|
PyList_Type = dlsym(py_handle, "PyList_Type")
|
||||||
|
PyDict_Type = dlsym(py_handle, "PyDict_Type")
|
||||||
|
PySet_Type = dlsym(py_handle, "PySet_Type")
|
||||||
|
PyTuple_Type = dlsym(py_handle, "PyTuple_Type")
|
||||||
|
PySlice_Type = dlsym(py_handle, "PySlice_Type")
|
||||||
PyExc_BaseException = Ptr[cobj](dlsym(py_handle, "PyExc_BaseException"))[0]
|
PyExc_BaseException = Ptr[cobj](dlsym(py_handle, "PyExc_BaseException"))[0]
|
||||||
PyExc_Exception = Ptr[cobj](dlsym(py_handle, "PyExc_Exception"))[0]
|
PyExc_Exception = Ptr[cobj](dlsym(py_handle, "PyExc_Exception"))[0]
|
||||||
PyExc_NameError = Ptr[cobj](dlsym(py_handle, "PyExc_NameError"))[0]
|
PyExc_NameError = Ptr[cobj](dlsym(py_handle, "PyExc_NameError"))[0]
|
||||||
|
@ -500,7 +535,18 @@ def init_handles_static():
|
||||||
from C import _Py_NoneStruct: cobj
|
from C import _Py_NoneStruct: cobj
|
||||||
from C import _Py_TrueStruct: cobj
|
from C import _Py_TrueStruct: cobj
|
||||||
from C import _Py_FalseStruct: cobj
|
from C import _Py_FalseStruct: cobj
|
||||||
|
from C import _Py_EllipsisObject: cobj
|
||||||
from C import _Py_NotImplementedStruct: cobj
|
from C import _Py_NotImplementedStruct: cobj
|
||||||
|
from C import PyLong_Type: cobj as _PyLong_Type
|
||||||
|
from C import PyFloat_Type: cobj as _PyFloat_Type
|
||||||
|
from C import PyBool_Type: cobj as _PyBool_Type
|
||||||
|
from C import PyUnicode_Type: cobj as _PyUnicode_Type
|
||||||
|
from C import PyComplex_Type: cobj as _PyComplex_Type
|
||||||
|
from C import PyList_Type: cobj as _PyList_Type
|
||||||
|
from C import PyDict_Type: cobj as _PyDict_Type
|
||||||
|
from C import PySet_Type: cobj as _PySet_Type
|
||||||
|
from C import PyTuple_Type: cobj as _PyTuple_Type
|
||||||
|
from C import PySlice_Type: cobj as _PySlice_Type
|
||||||
from C import PyExc_BaseException: cobj as _PyExc_BaseException
|
from C import PyExc_BaseException: cobj as _PyExc_BaseException
|
||||||
from C import PyExc_Exception: cobj as _PyExc_Exception
|
from C import PyExc_Exception: cobj as _PyExc_Exception
|
||||||
from C import PyExc_NameError: cobj as _PyExc_NameError
|
from C import PyExc_NameError: cobj as _PyExc_NameError
|
||||||
|
@ -615,7 +661,18 @@ def init_handles_static():
|
||||||
global Py_None
|
global Py_None
|
||||||
global Py_True
|
global Py_True
|
||||||
global Py_False
|
global Py_False
|
||||||
|
global Py_Ellipsis
|
||||||
global Py_NotImplemented
|
global Py_NotImplemented
|
||||||
|
global PyLong_Type
|
||||||
|
global PyFloat_Type
|
||||||
|
global PyBool_Type
|
||||||
|
global PyUnicode_Type
|
||||||
|
global PyComplex_Type
|
||||||
|
global PyList_Type
|
||||||
|
global PyDict_Type
|
||||||
|
global PySet_Type
|
||||||
|
global PyTuple_Type
|
||||||
|
global PySlice_Type
|
||||||
global PyExc_BaseException
|
global PyExc_BaseException
|
||||||
global PyExc_Exception
|
global PyExc_Exception
|
||||||
global PyExc_NameError
|
global PyExc_NameError
|
||||||
|
@ -730,7 +787,18 @@ def init_handles_static():
|
||||||
Py_None = __ptr__(_Py_NoneStruct).as_byte()
|
Py_None = __ptr__(_Py_NoneStruct).as_byte()
|
||||||
Py_True = __ptr__(_Py_TrueStruct).as_byte()
|
Py_True = __ptr__(_Py_TrueStruct).as_byte()
|
||||||
Py_False = __ptr__(_Py_FalseStruct).as_byte()
|
Py_False = __ptr__(_Py_FalseStruct).as_byte()
|
||||||
|
Py_Ellipsis = __ptr__(_Py_EllipsisObject).as_byte()
|
||||||
Py_NotImplemented = __ptr__(_Py_NotImplementedStruct).as_byte()
|
Py_NotImplemented = __ptr__(_Py_NotImplementedStruct).as_byte()
|
||||||
|
PyLong_Type = __ptr__(_PyLong_Type).as_byte()
|
||||||
|
PyFloat_Type = __ptr__(_PyFloat_Type).as_byte()
|
||||||
|
PyBool_Type = __ptr__(_PyBool_Type).as_byte()
|
||||||
|
PyUnicode_Type = __ptr__(_PyUnicode_Type).as_byte()
|
||||||
|
PyComplex_Type = __ptr__(_PyComplex_Type).as_byte()
|
||||||
|
PyList_Type = __ptr__(_PyList_Type).as_byte()
|
||||||
|
PyDict_Type = __ptr__(_PyDict_Type).as_byte()
|
||||||
|
PySet_Type = __ptr__(_PySet_Type).as_byte()
|
||||||
|
PyTuple_Type = __ptr__(_PyTuple_Type).as_byte()
|
||||||
|
PySlice_Type = __ptr__(_PySlice_Type).as_byte()
|
||||||
PyExc_BaseException = _PyExc_BaseException
|
PyExc_BaseException = _PyExc_BaseException
|
||||||
PyExc_Exception = _PyExc_Exception
|
PyExc_Exception = _PyExc_Exception
|
||||||
PyExc_NameError = _PyExc_NameError
|
PyExc_NameError = _PyExc_NameError
|
||||||
|
@ -1148,6 +1216,14 @@ def _get_identifier(typ: str) -> pyobj:
|
||||||
def _isinstance(what: pyobj, typ: pyobj) -> bool:
|
def _isinstance(what: pyobj, typ: pyobj) -> bool:
|
||||||
return bool(pyobj.exc_wrap(PyObject_IsInstance(what.p, typ.p)))
|
return bool(pyobj.exc_wrap(PyObject_IsInstance(what.p, typ.p)))
|
||||||
|
|
||||||
|
@tuple
|
||||||
|
class _PyObject_Struct:
|
||||||
|
refcnt: int
|
||||||
|
pytype: cobj
|
||||||
|
|
||||||
|
def _is_type(o: cobj, t: cobj):
|
||||||
|
return Ptr[_PyObject_Struct](o)[0].pytype == t
|
||||||
|
|
||||||
|
|
||||||
# Type conversions
|
# Type conversions
|
||||||
|
|
||||||
|
@ -1160,6 +1236,9 @@ class NoneType:
|
||||||
def __from_py__(i: cobj) -> None:
|
def __from_py__(i: cobj) -> None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def __try_from_py__(i: cobj) -> Optional[NoneType]:
|
||||||
|
return
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class int:
|
class int:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1168,6 +1247,11 @@ class int:
|
||||||
def __from_py__(i: cobj) -> int:
|
def __from_py__(i: cobj) -> int:
|
||||||
return pyobj.exc_wrap(PyLong_AsLong(i))
|
return pyobj.exc_wrap(PyLong_AsLong(i))
|
||||||
|
|
||||||
|
def __try_from_py__(i: cobj) -> Optional[int]:
|
||||||
|
if _is_type(i, PyLong_Type):
|
||||||
|
return PyLong_AsLong(i)
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class float:
|
class float:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1176,6 +1260,11 @@ class float:
|
||||||
def __from_py__(d: cobj) -> float:
|
def __from_py__(d: cobj) -> float:
|
||||||
return pyobj.exc_wrap(PyFloat_AsDouble(d))
|
return pyobj.exc_wrap(PyFloat_AsDouble(d))
|
||||||
|
|
||||||
|
def __try_from_py__(d: cobj) -> Optional[float]:
|
||||||
|
if _is_type(d, PyFloat_Type):
|
||||||
|
return PyFloat_AsDouble(d)
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class bool:
|
class bool:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1184,6 +1273,11 @@ class bool:
|
||||||
def __from_py__(b: cobj) -> bool:
|
def __from_py__(b: cobj) -> bool:
|
||||||
return pyobj.exc_wrap(PyObject_IsTrue(b)) != 0
|
return pyobj.exc_wrap(PyObject_IsTrue(b)) != 0
|
||||||
|
|
||||||
|
def __try_from_py__(b: cobj) -> Optional[bool]:
|
||||||
|
if _is_type(b, PyBool_Type):
|
||||||
|
return PyObject_IsTrue(b) != 0
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class byte:
|
class byte:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1192,6 +1286,12 @@ class byte:
|
||||||
def __from_py__(c: cobj) -> byte:
|
def __from_py__(c: cobj) -> byte:
|
||||||
return str.__from_py__(c).ptr[0]
|
return str.__from_py__(c).ptr[0]
|
||||||
|
|
||||||
|
def __try_from_py__(c: cobj) -> Optional[byte]:
|
||||||
|
x = str.__try_from_py__(c)
|
||||||
|
if x is None or len(x) != 1:
|
||||||
|
return None
|
||||||
|
return x.ptr[0]
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class str:
|
class str:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1200,6 +1300,11 @@ class str:
|
||||||
def __from_py__(s: cobj) -> str:
|
def __from_py__(s: cobj) -> str:
|
||||||
return pyobj.exc_wrap(pyobj.to_str(s, "strict"))
|
return pyobj.exc_wrap(pyobj.to_str(s, "strict"))
|
||||||
|
|
||||||
|
def __try_from_py__(s: cobj) -> Optional[str]:
|
||||||
|
if _is_type(s, PyUnicode_Type):
|
||||||
|
return pyobj.to_str(s, "strict")
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class complex:
|
class complex:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1210,6 +1315,13 @@ class complex:
|
||||||
imag = pyobj.exc_wrap(PyComplex_ImagAsDouble(c))
|
imag = pyobj.exc_wrap(PyComplex_ImagAsDouble(c))
|
||||||
return complex(real, imag)
|
return complex(real, imag)
|
||||||
|
|
||||||
|
def __try_from_py__(c: cobj) -> Optional[complex]:
|
||||||
|
if _is_type(c, PyComplex_Type):
|
||||||
|
real = PyComplex_RealAsDouble(c)
|
||||||
|
imag = PyComplex_ImagAsDouble(c)
|
||||||
|
return complex(real, imag)
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class List:
|
class List:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1231,6 +1343,19 @@ class List:
|
||||||
t.append(T.__from_py__(elem))
|
t.append(T.__from_py__(elem))
|
||||||
return t
|
return t
|
||||||
|
|
||||||
|
def __try_from_py__(v: cobj) -> Optional[List[T]]:
|
||||||
|
if _is_type(v, PyList_Type):
|
||||||
|
n = PyObject_Length(v)
|
||||||
|
t = List[T](n)
|
||||||
|
for i in range(n):
|
||||||
|
elem = PyList_GetItem(v, i)
|
||||||
|
x = T.__try_from_py__(elem)
|
||||||
|
if x is None:
|
||||||
|
return None
|
||||||
|
t.append(x)
|
||||||
|
return t
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class Dict:
|
class Dict:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1253,6 +1378,21 @@ class Dict:
|
||||||
b[k] = v
|
b[k] = v
|
||||||
return b
|
return b
|
||||||
|
|
||||||
|
def __try_from_py__(d: cobj) -> Optional[Dict[K, V]]:
|
||||||
|
if _is_type(d, PyDict_Type):
|
||||||
|
b = dict[K, V]()
|
||||||
|
pos = 0
|
||||||
|
k_ptr = cobj()
|
||||||
|
v_ptr = cobj()
|
||||||
|
while PyDict_Next(d, __ptr__(pos), __ptr__(k_ptr), __ptr__(v_ptr)):
|
||||||
|
k = K.__try_from_py__(k_ptr)
|
||||||
|
v = V.__try_from_py__(v_ptr)
|
||||||
|
if k is None or v is None:
|
||||||
|
return None
|
||||||
|
b[k] = v
|
||||||
|
return b
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class Set:
|
class Set:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1276,6 +1416,23 @@ class Set:
|
||||||
pyobj.decref(s_iter)
|
pyobj.decref(s_iter)
|
||||||
return b
|
return b
|
||||||
|
|
||||||
|
def __try_from_py__(s: cobj) -> Optional[Set[K]]:
|
||||||
|
if _is_type(s, PySet_Type):
|
||||||
|
b = set[K]()
|
||||||
|
s_iter = PyObject_GetIter(s)
|
||||||
|
while True:
|
||||||
|
k_ptr = PyIter_Next(s_iter)
|
||||||
|
if not k_ptr:
|
||||||
|
break
|
||||||
|
k = K.__try_from_py__(k_ptr)
|
||||||
|
if k is None:
|
||||||
|
return None
|
||||||
|
pyobj.decref(k_ptr)
|
||||||
|
b.add(k)
|
||||||
|
pyobj.decref(s_iter)
|
||||||
|
return b
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class DynamicTuple:
|
class DynamicTuple:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1294,6 +1451,18 @@ class DynamicTuple:
|
||||||
p[i] = T.__from_py__(PyTuple_GetItem(t, i))
|
p[i] = T.__from_py__(PyTuple_GetItem(t, i))
|
||||||
return DynamicTuple(p, n)
|
return DynamicTuple(p, n)
|
||||||
|
|
||||||
|
def __try_from_py__(t: cobj) -> Optional[DynamicTuple[T]]:
|
||||||
|
if _is_type(t, PyTuple_Type):
|
||||||
|
n = PyTuple_Size(t)
|
||||||
|
p = Ptr[T](n)
|
||||||
|
for i in range(n):
|
||||||
|
x = T.__try_from_py__(PyTuple_GetItem(t, i))
|
||||||
|
if x is None:
|
||||||
|
return None
|
||||||
|
p[i] = x
|
||||||
|
return DynamicTuple(p, n)
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class Slice:
|
class Slice:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1312,6 +1481,15 @@ class Slice:
|
||||||
pyobj.exc_wrap(PySlice_Unpack(s, __ptr__(start), __ptr__(stop), __ptr__(step)))
|
pyobj.exc_wrap(PySlice_Unpack(s, __ptr__(start), __ptr__(stop), __ptr__(step)))
|
||||||
return Slice(Optional(start), Optional(stop), Optional(step))
|
return Slice(Optional(start), Optional(stop), Optional(step))
|
||||||
|
|
||||||
|
def __try_from_py__(s: cobj) -> Optional[Slice]:
|
||||||
|
if _is_type(s, PySlice_Type):
|
||||||
|
start = 0
|
||||||
|
stop = 0
|
||||||
|
step = 0
|
||||||
|
PySlice_Unpack(s, __ptr__(start), __ptr__(stop), __ptr__(step))
|
||||||
|
return Slice(Optional(start), Optional(stop), Optional(step))
|
||||||
|
return None
|
||||||
|
|
||||||
@extend
|
@extend
|
||||||
class Optional:
|
class Optional:
|
||||||
def __to_py__(self) -> cobj:
|
def __to_py__(self) -> cobj:
|
||||||
|
@ -1326,6 +1504,12 @@ class Optional:
|
||||||
else:
|
else:
|
||||||
return Optional[T](T.__from_py__(o))
|
return Optional[T](T.__from_py__(o))
|
||||||
|
|
||||||
|
def __try_from_py__(o: cobj) -> Optional[Optional[T]]:
|
||||||
|
if o == Py_None:
|
||||||
|
return Optional[Optional[T]]()
|
||||||
|
else:
|
||||||
|
return Optional[Optional[T]](T.__try_from_py__(o))
|
||||||
|
|
||||||
|
|
||||||
__pyenv__: Optional[pyobj] = None
|
__pyenv__: Optional[pyobj] = None
|
||||||
def _____(): __pyenv__ # make it global!
|
def _____(): __pyenv__ # make it global!
|
||||||
|
|
Loading…
Reference in New Issue