python-efl/scripts/converters.py

191 lines
4.0 KiB
Python

import logging
log = logging.getLogger("efl.eolian.conv")
import re
import keyword
from efl import eolian
docstring_replacements = (
("@brief ", ""),
(re.compile(r"@ingroup .+", re.S), r""),
(re.compile(r"@see (.+)(?!@)"), r":see: \1"),
("@return ", ":return: "),
(re.compile(r"@(note|warning) "), r".. \1:: "),
(re.compile(r"@(p|c) (\w+)"), r"``\2``"),
(re.compile(r"@(b) (\w+)"), r"**\2**"),
(re.compile(r"@(i) (\w+)"), r"*\2*"),
("EINA_TRUE", "True"),
("EINA_FALSE", "False"),
("NULL", "None"),
)
builtin_types = ( # automatically converted by cython
"byte",
"ubyte",
#"char",
"short",
"ushort",
"int",
"uint",
"long",
"ulong",
"llong",
"ullong",
"int8",
"uint8",
"int16",
"uint16",
"int32",
"uint32",
"int64",
"uint64",
"int128",
"uint128",
"size",
"ssize",
"intptr",
"uintptr",
"ptrdiff",
#"time",
"float",
"double",
#"bool",
#"void",
"Evas_Coord",
"Evas_Real"
)
complex_types = (
"Eina_List"
)
mapping_in = {
# c_type: pyx_type
"bool": "bint",
"char": "",
"Evas_Object": "_Eo_Base",
"Eo": "_Eo_Base",
}
conversions_in = {
# c_type: conversion
"bool": None,
"char": "if isinstance({0}, unicode): {0} = PyUnicode_AsUTF8String({0})",
"Evas_Object": None,
"Eo": None,
}
mapping_out = {
# c_type: pyx_type
"bool": "bint",
"char": "unicode",
"Elm_Object_Item": "_ObjectItem",
"Evas_Object": "_Eo_Base",
"Eo": "_Eo_Base",
}
conversions_out = {
# c_type: conversion
"bool": "bool({0})",
"char": '{0}.decode("utf-8")',
"Elm_Object_Item *": 'object_item_to_python({0})',
"Evas_Object *": 'object_from_instance({0})',
"Eo": 'object_from_instance({0})',
}
class EolianTypeError(TypeError):
pass
def conv_cls_name(name):
s = name.split("_")
if len(s) > 1:
return s[0], "_".join(s[1:])
else:
return name, name
def remove_type_prefixes(ctype):
for t in "const ", "unsigned ", "short ":
ctype = ctype.replace(t, "")
return ctype
def convert_in_param(tp, param_name, is_nonull=None):
c_type = tp.c_type
if tp.type == eolian.TypeType.POINTER:
tp = tp.base_type
if tp.type == eolian.TypeType.CLASS:
return None, "Eo", "{0}.obj".format(param_name)
key = tp.name if tp.name else c_type
if key in builtin_types:
return "", c_type, param_name
if not key in mapping_in:
raise EolianTypeError("Unknown IN type: %s" % (key))
conv_expr = conversions_in.get(key)
if conv_expr is not None:
conv_expr = conv_expr.format(param_name)
conv_t = mapping_in[key]
#if conv_t is None:
#conv_t = ""
if not is_nonull:
key = "<{0}>{1} if {1} is not None else NULL".format(c_type, param_name)
if keyword.iskeyword(param_name):
param_name += "_"
return conv_expr, conv_t, param_name
def convert_out_param(tp, param_name):
if tp.type == eolian.TypeType.POINTER:
tp = tp.base_type
if tp.type == eolian.TypeType.CLASS:
# TODO: set obj
return tp.c_type, param_name
key = tp.name if tp.name else tp.c_type
if key in builtin_types:
return tp.c_type, param_name
if not key in mapping_out:
raise EolianTypeError("Unknown OUT type: %s" % (key))
conv = conversions_out.get(key)
if conv:
param_name = conv.format(param_name)
if keyword.iskeyword(param_name):
param_name += "_"
return tp.c_type, param_name
def conv_type_ret(tp):
if tp.type == eolian.TypeType.POINTER:
tp = tp.base_type
c_type = tp.c_type
key = tp.name if tp.name else c_type
if key in builtin_types:
return c_type, c_type
py_t = mapping_out.get(key)
if py_t is None:
raise EolianTypeError("Unknown RET type: %s" % (key))
py_ret_type = py_t[0]
return py_ret_type, c_type