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_True = cobj()
|
||||
Py_False = cobj()
|
||||
Py_Ellipsis = cobj()
|
||||
Py_NotImplemented = cobj()
|
||||
Py_LT = 0
|
||||
Py_LE = 1
|
||||
|
@ -117,6 +118,18 @@ Py_NE = 3
|
|||
Py_GT = 4
|
||||
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
|
||||
PyExc_BaseException = cobj()
|
||||
PyExc_Exception = cobj()
|
||||
|
@ -269,7 +282,18 @@ def init_handles_dlopen(py_handle: cobj):
|
|||
global Py_None
|
||||
global Py_True
|
||||
global Py_False
|
||||
global Py_Ellipsis
|
||||
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_Exception
|
||||
global PyExc_NameError
|
||||
|
@ -384,7 +408,18 @@ def init_handles_dlopen(py_handle: cobj):
|
|||
Py_None = dlsym(py_handle, "_Py_NoneStruct")
|
||||
Py_True = dlsym(py_handle, "_Py_TrueStruct")
|
||||
Py_False = dlsym(py_handle, "_Py_FalseStruct")
|
||||
Py_Ellipsis = dlsym(py_handle, "_Py_EllipsisObject")
|
||||
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_Exception = Ptr[cobj](dlsym(py_handle, "PyExc_Exception"))[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_TrueStruct: cobj
|
||||
from C import _Py_FalseStruct: cobj
|
||||
from C import _Py_EllipsisObject: 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_Exception: cobj as _PyExc_Exception
|
||||
from C import PyExc_NameError: cobj as _PyExc_NameError
|
||||
|
@ -615,7 +661,18 @@ def init_handles_static():
|
|||
global Py_None
|
||||
global Py_True
|
||||
global Py_False
|
||||
global Py_Ellipsis
|
||||
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_Exception
|
||||
global PyExc_NameError
|
||||
|
@ -730,7 +787,18 @@ def init_handles_static():
|
|||
Py_None = __ptr__(_Py_NoneStruct).as_byte()
|
||||
Py_True = __ptr__(_Py_TrueStruct).as_byte()
|
||||
Py_False = __ptr__(_Py_FalseStruct).as_byte()
|
||||
Py_Ellipsis = __ptr__(_Py_EllipsisObject).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_Exception = _PyExc_Exception
|
||||
PyExc_NameError = _PyExc_NameError
|
||||
|
@ -1148,6 +1216,14 @@ def _get_identifier(typ: str) -> pyobj:
|
|||
def _isinstance(what: pyobj, typ: pyobj) -> bool:
|
||||
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
|
||||
|
||||
|
@ -1160,6 +1236,9 @@ class NoneType:
|
|||
def __from_py__(i: cobj) -> None:
|
||||
return
|
||||
|
||||
def __try_from_py__(i: cobj) -> Optional[NoneType]:
|
||||
return
|
||||
|
||||
@extend
|
||||
class int:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1168,6 +1247,11 @@ class int:
|
|||
def __from_py__(i: cobj) -> int:
|
||||
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
|
||||
class float:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1176,6 +1260,11 @@ class float:
|
|||
def __from_py__(d: cobj) -> float:
|
||||
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
|
||||
class bool:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1184,6 +1273,11 @@ class bool:
|
|||
def __from_py__(b: cobj) -> bool:
|
||||
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
|
||||
class byte:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1192,6 +1286,12 @@ class byte:
|
|||
def __from_py__(c: cobj) -> byte:
|
||||
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
|
||||
class str:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1200,6 +1300,11 @@ class str:
|
|||
def __from_py__(s: cobj) -> str:
|
||||
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
|
||||
class complex:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1210,6 +1315,13 @@ class complex:
|
|||
imag = pyobj.exc_wrap(PyComplex_ImagAsDouble(c))
|
||||
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
|
||||
class List:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1231,6 +1343,19 @@ class List:
|
|||
t.append(T.__from_py__(elem))
|
||||
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
|
||||
class Dict:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1253,6 +1378,21 @@ class Dict:
|
|||
b[k] = v
|
||||
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
|
||||
class Set:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1276,6 +1416,23 @@ class Set:
|
|||
pyobj.decref(s_iter)
|
||||
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
|
||||
class DynamicTuple:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1294,6 +1451,18 @@ class DynamicTuple:
|
|||
p[i] = T.__from_py__(PyTuple_GetItem(t, i))
|
||||
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
|
||||
class Slice:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1312,6 +1481,15 @@ class Slice:
|
|||
pyobj.exc_wrap(PySlice_Unpack(s, __ptr__(start), __ptr__(stop), __ptr__(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
|
||||
class Optional:
|
||||
def __to_py__(self) -> cobj:
|
||||
|
@ -1326,6 +1504,12 @@ class Optional:
|
|||
else:
|
||||
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
|
||||
def _____(): __pyenv__ # make it global!
|
||||
|
|
Loading…
Reference in New Issue