Eolian: WIP
This commit is contained in:
parent
6b45d3429d
commit
a795ec8c10
|
@ -20,14 +20,16 @@ from cpython cimport PyObject, Py_INCREF, Py_DECREF, PyUnicode_AsUTF8String
|
|||
from libc.stdint cimport uintptr_t
|
||||
from efl.eina cimport Eina_Bool, \
|
||||
Eina_Hash, eina_hash_string_superfast_new, eina_hash_add, eina_hash_del, \
|
||||
eina_hash_find, EINA_LOG_DOM_DBG, EINA_LOG_DOM_INFO
|
||||
eina_hash_find, EINA_LOG_DOM_DBG, EINA_LOG_DOM_INFO, \
|
||||
eina_hash_pointer_new
|
||||
from efl.c_eo cimport Eo as cEo, eo_init, eo_shutdown, eo_del, eo_do, \
|
||||
eo_class_name_get, eo_class_get, eo_base_class_get,\
|
||||
eo_key_data_set, eo_key_data_get, eo_key_data_del, \
|
||||
eo_event_callback_add, eo_event_callback_del, EO_EV_DEL, \
|
||||
eo_parent_get, eo_parent_set, Eo_Event_Description, \
|
||||
eo_event_freeze, eo_event_thaw, eo_event_freeze_count_get, \
|
||||
eo_event_global_freeze, eo_event_global_thaw, eo_event_global_freeze_count_get
|
||||
eo_event_global_freeze, eo_event_global_thaw, \
|
||||
eo_event_global_freeze_count_get
|
||||
|
||||
cimport efl.eo.enums as enums
|
||||
|
||||
|
@ -193,6 +195,30 @@ cdef Eina_Bool _eo_event_del_cb(void *data, cEo *obj,
|
|||
|
||||
return enums.EO_CALLBACK_STOP
|
||||
|
||||
cdef Eina_Bool _py_efl_eo_event_cb(
|
||||
void *data, cEo *obj, const Eo_Event_Description *desc, void *event_info):
|
||||
|
||||
cdef:
|
||||
void* tmp
|
||||
bint ret
|
||||
Eo o
|
||||
|
||||
func = <object>data
|
||||
o = object_from_instance(obj)
|
||||
|
||||
# create event description python object
|
||||
|
||||
tmp = eina_hash_find(o.event_conv_mapping, desc)
|
||||
if tmp == NULL:
|
||||
py_ev_info_obj = None
|
||||
else:
|
||||
py_ev_info_cls = <object>tmp
|
||||
# use a generic class and set some conv func??
|
||||
#py_ev_info_obj = py_ev_info_cls.__new__(py_ev_info_cls)
|
||||
|
||||
#ret = func(py_ev_desc, py_ev_info_obj) # o as first param?
|
||||
#return ret
|
||||
|
||||
|
||||
cdef class Eo(object):
|
||||
"""
|
||||
|
@ -204,6 +230,8 @@ cdef class Eo(object):
|
|||
# c globals declared in eo.pxd (to make the class available to others)
|
||||
|
||||
def __cinit__(self):
|
||||
self.event_desc_mapping = eina_hash_string_superfast_new(NULL)
|
||||
self.event_conv_mapping = eina_hash_pointer_new(NULL)
|
||||
self.data = dict()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -296,7 +324,49 @@ cdef class Eo(object):
|
|||
|
||||
:return: the freeze count
|
||||
:rtype: int
|
||||
|
||||
|
||||
"""
|
||||
cdef int fcount = <int>eo_do(self.obj, eo_event_freeze_count_get())
|
||||
return fcount
|
||||
|
||||
def event_callback_add(self, event_name, func):
|
||||
cdef:
|
||||
void *desc
|
||||
const char *ev_name
|
||||
|
||||
if isinstance(event_name, unicode):
|
||||
event_name = PyUnicode_AsUTF8String(event_name)
|
||||
|
||||
ev_name = event_name
|
||||
|
||||
desc = eina_hash_find(self.event_desc_mapping, ev_name)
|
||||
if desc is NULL:
|
||||
raise RuntimeError("Unknown Eo event name: %s" % (event_name))
|
||||
|
||||
eo_event_callback_add(
|
||||
<Eo_Event_Description *>desc,
|
||||
_py_efl_eo_event_cb,
|
||||
<const void *>func
|
||||
)
|
||||
Py_INCREF(func)
|
||||
|
||||
def event_callback_del(self, event_name, func):
|
||||
cdef:
|
||||
void *desc
|
||||
const char *ev_name
|
||||
|
||||
if isinstance(event_name, unicode):
|
||||
event_name = PyUnicode_AsUTF8String(event_name)
|
||||
|
||||
ev_name = event_name
|
||||
|
||||
desc = eina_hash_find(self.event_desc_mapping, ev_name)
|
||||
if desc is NULL:
|
||||
raise RuntimeError("Unknown Eo event name: %s" % (event_name))
|
||||
|
||||
eo_event_callback_del(
|
||||
<Eo_Event_Description *>desc,
|
||||
_py_efl_eo_event_cb,
|
||||
<const void *>func
|
||||
)
|
||||
Py_DECREF(func)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
from efl.eina cimport Eina_Bool
|
||||
|
||||
cdef extern from "*":
|
||||
cdef extern from *:
|
||||
struct CFILE "__FILE__"
|
||||
struct CLINE "__LINE__"
|
||||
struct CFUNC "__FUNCTION__"
|
||||
|
|
|
@ -161,6 +161,7 @@ cdef extern from "Eina.h":
|
|||
unsigned int eina_list_count(Eina_List *list)
|
||||
|
||||
Eina_Hash *eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb)
|
||||
Eina_Hash *eina_hash_pointer_new(Eina_Free_Cb data_free_cb)
|
||||
Eina_Bool eina_hash_add(Eina_Hash *hash, const void *key, const void *data)
|
||||
Eina_Bool eina_hash_del(Eina_Hash *hash, const void *key, const void *data)
|
||||
void *eina_hash_find(Eina_Hash *hash, const void *key)
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
# along with this Python-EFL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from efl.c_eo cimport Eo as cEo
|
||||
from efl.eina cimport Eina_Hash
|
||||
|
||||
cdef:
|
||||
class Eo(object):
|
||||
cdef:
|
||||
cEo *obj
|
||||
Eina_Hash *event_desc_mapping
|
||||
Eina_Hash *event_conv_mapping
|
||||
readonly dict data
|
||||
|
||||
int _set_obj(self, cEo *obj) except 0
|
||||
|
|
|
@ -6,6 +6,9 @@ import keyword
|
|||
|
||||
from efl import eolian
|
||||
|
||||
class EolianTypeError(Exception):
|
||||
pass
|
||||
|
||||
docstring_replacements = (
|
||||
("@brief ", ""),
|
||||
(re.compile(r"@ingroup .+", re.S), r""),
|
||||
|
@ -95,16 +98,20 @@ conversions_out = {
|
|||
}
|
||||
|
||||
|
||||
class EolianTypeError(TypeError):
|
||||
pass
|
||||
|
||||
|
||||
def conv_cls_name(name):
|
||||
s = name.split("_")
|
||||
def conv_cls_name(cls):
|
||||
if cls.namespaces:
|
||||
lib_name = ".".join(map(unicode.lower, cls.namespaces))
|
||||
name = cls.name
|
||||
else:
|
||||
s = cls.name.split("_")
|
||||
if len(s) > 1:
|
||||
return s[0], "_".join(s[1:])
|
||||
lib_name = s[0]
|
||||
name = "_".join(s[1:])
|
||||
else:
|
||||
return name, name
|
||||
lib_name = s
|
||||
name = s
|
||||
|
||||
return lib_name, name
|
||||
|
||||
|
||||
def remove_type_prefixes(ctype):
|
||||
|
@ -188,3 +195,7 @@ def conv_type_ret(tp):
|
|||
py_ret_type = py_t[0]
|
||||
|
||||
return py_ret_type, c_type
|
||||
|
||||
def event_conversion_get(tp):
|
||||
if tp.type != eolian.TypeType.UNKNOWN:
|
||||
return "Eo_Event_%s" % tp.name
|
||||
|
|
|
@ -37,9 +37,12 @@ eolian.init()
|
|||
|
||||
|
||||
from converters import convert_in_param, convert_out_param, conv_type_ret, \
|
||||
conv_cls_name, EolianTypeError
|
||||
conv_cls_name, EolianTypeError, event_conversion_get
|
||||
|
||||
|
||||
class EolianSkip(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Generator(object):
|
||||
|
||||
|
@ -97,10 +100,11 @@ class Generator(object):
|
|||
#self.write(docs, wrapped=True)
|
||||
#self.write('"""')
|
||||
|
||||
def printout(self, filepath=None):
|
||||
def printout(self, filepath=None, append=False):
|
||||
result = "\n".join(self.result)
|
||||
if filepath:
|
||||
with open(filepath, "w") as f:
|
||||
mode = "a" if append else "w"
|
||||
with open(filepath, mode) as f:
|
||||
f.write(result.encode("utf-8"))
|
||||
f.write("\n")
|
||||
log.info(filepath + " written")
|
||||
|
@ -336,7 +340,7 @@ class Function(object):
|
|||
ret = self.RET_PARAM
|
||||
try:
|
||||
ret_type = convert_out_param(ret_type, ret)
|
||||
except Exception:
|
||||
except EolianTypeError:
|
||||
gen.write("# FIXME: Unknown return type")
|
||||
gen.dedent()
|
||||
raise
|
||||
|
@ -482,11 +486,7 @@ class Class(object):
|
|||
class_counter[cls.name] += 1
|
||||
|
||||
self.c_name = cls.name
|
||||
if cls.namespaces:
|
||||
self.lib_name = ".".join(map(unicode.lower, cls.namespaces))
|
||||
self.name = cls.name
|
||||
else:
|
||||
self.lib_name, self.name = conv_cls_name(cls.name)
|
||||
self.lib_name, self.name = conv_cls_name(cls)
|
||||
|
||||
header_path = cls.filename
|
||||
if not header_path:
|
||||
|
@ -505,8 +505,8 @@ class Class(object):
|
|||
|
||||
self.prefix = prefix
|
||||
|
||||
#if cls.type == eolian.ClassType.REGULAR: # or cls.type == eolian.ClassType.MIXIN:
|
||||
self.ctor.append(Constructor(cls.constructors, prefix))
|
||||
if cls.type == eolian.ClassType.REGULAR: # or cls.type == eolian.ClassType.MIXIN:
|
||||
self.ctor.append(Constructor(cls.constructors, prefix))
|
||||
|
||||
props = cls.functions_get(eolian.FunctionType.PROPERTY)
|
||||
for prop in props:
|
||||
|
@ -568,10 +568,16 @@ class Class(object):
|
|||
if i_cls.type == eolian.ClassType.INTERFACE or \
|
||||
i_cls.type == eolian.ClassType.MIXIN:
|
||||
continue
|
||||
if i_cls.full_name == "Eo.Base":
|
||||
inherits.append("Eo")
|
||||
continue
|
||||
lib_name, name = conv_cls_name(i_cls)
|
||||
#i = i.rpartition(".")[2]
|
||||
inherits.append("_" + name)
|
||||
else:
|
||||
log.warn("Class %s is unknown" % (i))
|
||||
i = i.rpartition(".")[2]
|
||||
inherits.append("_" + i)
|
||||
log.warn("Inherited class %s is unknown" % (i))
|
||||
i = i.rpartition(".")[2]
|
||||
inherits.append("_" + i)
|
||||
if len(inherits) > 1:
|
||||
log.error(
|
||||
"Multiple inheritance is not supported in extension classes.\n"
|
||||
|
@ -586,12 +592,24 @@ class Class(object):
|
|||
gen.write("cdef class _%s(%s):" % (self.name, inherits))
|
||||
gen.indent()
|
||||
|
||||
gen.write("def __cinit__(self):")
|
||||
gen.indent()
|
||||
for o in self.events:
|
||||
try:
|
||||
o.generate(gen)
|
||||
except EolianTypeError:
|
||||
log.info("Skipping %r because of unknown type", o)
|
||||
except Exception:
|
||||
log.exception("Error while generating %r", o)
|
||||
gen.dedent()
|
||||
gen.write()
|
||||
|
||||
if not self.ctor and not self.props and not self.methods:
|
||||
gen.write("pass")
|
||||
else:
|
||||
for o in (
|
||||
self.ctor +
|
||||
list(self.events)
|
||||
self.ctor #+
|
||||
#list(self.events)
|
||||
):
|
||||
try:
|
||||
o.generate(gen)
|
||||
|
@ -625,11 +643,15 @@ class Class(object):
|
|||
if i_cls.type == eolian.ClassType.REGULAR or \
|
||||
i_cls.type == eolian.ClassType.ABSTRACT:
|
||||
continue
|
||||
lib_name, name = conv_cls_name(i_cls)
|
||||
#i = i.rpartition(".")[2]
|
||||
else:
|
||||
log.warn("Class %s is unknown" % (i))
|
||||
l, n = conv_cls_name(i)
|
||||
inherits.append("_" + n)
|
||||
imports.append((l, "_" + n))
|
||||
i = i.rpartition(".")
|
||||
lib_name, name = i[0], i[2]
|
||||
|
||||
inherits.append("_" + name)
|
||||
imports.append((lib_name, "_" + name))
|
||||
|
||||
for l, n in imports:
|
||||
l = l.lower()
|
||||
|
@ -652,6 +674,8 @@ class Class(object):
|
|||
gen.dedent()
|
||||
gen.dedent()
|
||||
gen.write()
|
||||
gen.write('_object_mapping_register("%s", %s)' % (self.c_name, self.name))
|
||||
gen.write()
|
||||
|
||||
|
||||
class File(object):
|
||||
|
@ -662,33 +686,13 @@ class File(object):
|
|||
self.cls = eolian.Class.get_by_file(filepath)
|
||||
if not self.cls:
|
||||
raise RuntimeError("Could not get class from %s" % (filepath))
|
||||
if self.cls.full_name.startswith("Eo."):
|
||||
raise EolianSkip("Skipping Eo class")
|
||||
self.gencls = Class.parse(self.cls)
|
||||
|
||||
def cdefs_generate(self):
|
||||
gen = self.pyxgen
|
||||
|
||||
# gen.write('cdef extern from "*":')
|
||||
# gen.indent()
|
||||
# gen.write('struct CFILE "__FILE__"')
|
||||
# gen.write('struct CLINE "__LINE__"')
|
||||
# gen.write('struct CFUNC "__FUNCTION__"')
|
||||
# gen.dedent()
|
||||
# gen.write()
|
||||
|
||||
# gen.write('cdef extern from "Eina.h":')
|
||||
# gen.indent()
|
||||
# gen.write('Eina_Bool eina_main_loop_is(void)')
|
||||
# gen.dedent()
|
||||
# gen.write()
|
||||
|
||||
# gen.write('cdef extern from "Eo.h":')
|
||||
# gen.indent()
|
||||
#gen.write('Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, Eina_Bool is_main_loop, const char *file, const char *func, int line)')
|
||||
# gen.write('Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, const char *file, const char *func, int line)')
|
||||
#gen.write('void _eo_do_end(const Eo **ojb)')
|
||||
# gen.dedent()
|
||||
# gen.write()
|
||||
|
||||
gen.write('cdef extern from "%s":' % (self.gencls.header_path))
|
||||
gen.indent()
|
||||
|
||||
|
@ -750,24 +754,32 @@ class File(object):
|
|||
|
||||
def py_generate(self):
|
||||
py_path = os.path.join(args.output, "__init__" + ".py")
|
||||
if os.path.exists(py_path):
|
||||
os.remove(py_path)
|
||||
|
||||
self.gencls.py_generate(self.pygen)
|
||||
|
||||
self.pygen.printout(filepath=py_path)
|
||||
self.pygen.printout(filepath=py_path, append=True)
|
||||
|
||||
|
||||
class Event(object):
|
||||
def __init__(self, event):
|
||||
self.event = event
|
||||
#print(event)
|
||||
|
||||
def cdef_generate(self, gen):
|
||||
gen.write("enum: %s" % (self.event.c_name))
|
||||
|
||||
def generate(self, gen):
|
||||
pass
|
||||
gen.write(
|
||||
'eina_hash_set(self.event_desc_mapping, "%s", %s)' % (
|
||||
self.event.name, self.event.c_name
|
||||
)
|
||||
)
|
||||
conv = event_conversion_get(self.event.type)
|
||||
if conv:
|
||||
gen.write(
|
||||
'eina_hash_set(self.event_conv_mapping, %s, %s)' % (
|
||||
self.event.c_name, conv
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class_counter = Counter()
|
||||
|
@ -775,6 +787,9 @@ generated_class_counter = Counter()
|
|||
function_counter = Counter()
|
||||
generated_function_counter = Counter()
|
||||
|
||||
py_path = os.path.join(args.output, "__init__" + ".py")
|
||||
if os.path.exists(py_path):
|
||||
os.remove(py_path)
|
||||
|
||||
for path in args.paths:
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
|
@ -788,6 +803,8 @@ for path in args.paths:
|
|||
|
||||
try:
|
||||
eolf = File(filename)
|
||||
except EolianSkip:
|
||||
continue
|
||||
except Exception:
|
||||
log.exception("Exception while creating %s" % (filename))
|
||||
continue
|
||||
|
@ -804,6 +821,12 @@ for path in args.paths:
|
|||
log.exception("Exception while generating pyx for %s" % (filename))
|
||||
continue
|
||||
|
||||
try:
|
||||
eolf.py_generate()
|
||||
except Exception:
|
||||
log.exception("Exception while generating py for %s" % (filename))
|
||||
continue
|
||||
|
||||
|
||||
def report():
|
||||
print("===============================================")
|
||||
|
|
Loading…
Reference in New Issue