New python bindings for eolian
authorDave Andreoli <dave@gurumeditation.it>
Thu, 28 Dec 2017 12:49:03 +0000 (13:49 +0100)
committerWonki Kim <wonki_.kim@samsung.com>
Wed, 10 Jan 2018 11:08:13 +0000 (20:08 +0900)
This are manually written ctype bindings for eolian, that means they
run on the standard python library (nothing to install) and can run
without any build step (in fact ctypes just open the so/dll file at runtime)

Next step will be (soon) a template based generator for eolian that will
be a lot of fun :)

src/scripts/pyolian/eolian.py [new file with mode: 0644]
src/scripts/pyolian/eolian_lib.py [new file with mode: 0644]
src/scripts/pyolian/test_eolian.py [new file with mode: 0755]

diff --git a/src/scripts/pyolian/eolian.py b/src/scripts/pyolian/eolian.py
new file mode 100644 (file)
index 0000000..f74f350
--- /dev/null
@@ -0,0 +1,1294 @@
+#!/usr/bin/env python3
+# encoding: utf-8
+"""
+Pyolian: ctypes bindings for the eolian library.
+
+This file (along with eolian_lib.py) implement full pythonic eolian bindings.
+
+Those bindings are designed to work at runtime without any prepare/compilation
+steps required. The only requirement is that we can find the eolian.so/dll
+somwhere built in the source tree, look at eolian_lib.py to see the searchs
+performed.
+
+You can directly use the python API provided here if you need direct access
+to eolian, or we suggest to look at the template-based generator.py if you just
+need to generate some sort of text files out of the eolian database.
+
+"""
+from enum import IntEnum
+from ctypes import cast, byref, c_char_p, c_void_p
+
+from eolian_lib import lib
+
+
+###  Eolian Enums  ############################################################
+
+class Eolian_Function_Type(IntEnum):
+    UNRESOLVED = 0
+    PROPERTY = 1
+    PROP_SET = 2
+    PROP_GET = 3
+    METHOD = 4
+    FUNCTION_POINTER = 5
+
+class Eolian_Parameter_Dir(IntEnum):
+    UNKNOWN = 0
+    IN = 1
+    OUT = 2
+    INOUT = 3
+
+class Eolian_Class_Type(IntEnum):
+    UNKNOWN_TYPE = 0
+    REGULAR = 1
+    ABSTRACT = 2
+    MIXIN = 3
+    INTERFACE = 4
+
+class Eolian_Object_Scope(IntEnum):
+    UNKNOWN = 0
+    PUBLIC = 1
+    PRIVATE = 2
+    PROTECTED = 3
+
+class Eolian_Typedecl_Type(IntEnum):
+    UNKNOWN = 0
+    STRUCT = 1
+    STRUCT_OPAQUE = 2
+    ENUM = 3
+    ALIAS = 4
+    FUNCTION_POINTER = 5
+
+class Eolian_Type_Type(IntEnum):
+    UNKNOWN_TYPE = 0
+    VOID = 1
+    REGULAR = 2
+    CLASS = 3
+    UNDEFINED = 4
+
+class Eolian_Type_Builtin_Type(IntEnum):
+    INVALID = 0
+    BYTE = 1
+    UBYTE = 2
+    CHAR = 3
+    SHORT = 4
+    USHORT = 5
+    INT = 6
+    UINT = 7
+    LONG = 8
+    ULONG = 9
+    LLONG = 10
+    ULLONG = 11
+
+    INT8 = 12
+    UINT8 = 13
+    INT16 = 14
+    UINT16 = 15
+    INT32 = 16
+    UINT32 = 17
+    INT64 = 18
+    UINT64 = 19
+    INT128 = 20
+    UINT128 = 21
+
+    SIZE = 22
+    SSIZE = 23
+    INTPTR = 24
+    UINTPTR = 25
+    PTRDIFF = 26
+
+    TIME = 27
+
+    FLOAT = 28
+    DOUBLE = 29
+
+    BOOL = 30
+    VOID = 31
+
+    ACCESSOR = 32
+    ARRAY = 33
+    ITERATOR = 34
+    HASH = 35
+    LIST = 36
+    INARRAY = 37
+    INLIST = 38
+
+    FUTURE = 39
+
+    ANY_VALUE = 40
+    ANY_VALUE_PTR = 41
+
+    MSTRING = 42
+    STRING = 43
+    STRINGSHARE = 44
+
+    VOID_PTR = 45
+    FREE_CB = 46
+
+class Eolian_C_Type_Type(IntEnum):
+    DEFAULT = 0
+    PARAM = 1
+    RETURN = 2
+
+class Eolian_Expression_Type(IntEnum):
+    UNKNOWN = 0
+    INT = 1
+    UINT = 2
+    LONG = 3
+    ULONG = 4
+    LLONG = 5
+    ULLONG = 6
+    FLOAT = 7
+    DOUBLE = 8
+    STRING = 9
+    CHAR = 10
+    NULL = 11
+    BOOL = 12
+    NAME = 13
+    UNARY = 14
+    BINARY = 15
+
+class Eolian_Expression_Mask(IntEnum):
+    SINT   = 1 << 0
+    UINT   = 1 << 1
+    INT    = SINT | UINT
+    FLOAT  = 1 << 2
+    BOOL   = 1 << 3
+    STRING = 1 << 4
+    CHAR   = 1 << 5
+    NULL   = 1 << 6
+    SIGNED = SINT | FLOAT
+    NUMBER = INT | FLOAT
+    ALL    = NUMBER | BOOL | STRING | CHAR | NULL
+
+class Eolian_Variable_Type(IntEnum):
+    UNKNOWN = 0
+    CONSTANT = 1
+    GLOBAL = 2
+
+class Eolian_Binary_Operator(IntEnum):
+    INVALID = 0
+    ADD = 1  # + int, float
+    SUB = 2  # - int, float
+    MUL = 3  # * int, float
+    DIV = 4  # / int, float
+    MOD = 5  # % int
+    EQ = 6  # == all types
+    NQ = 7  # != all types
+    GT = 8  # >  int, float
+    LT = 9  # <  int, float
+    GE = 10  # >= int, float
+    LE = 11  # <= int, float
+    AND = 12  # && all types
+    OR =  13  # || all types
+    BAND = 14  # &  int
+    BOR =  15  # |  int
+    BXOR = 16  # ^  int
+    LSH =  17  # << int
+    RSH =  18  # >> int
+
+class Eolian_Unary_Operator(IntEnum):
+    INVALID = 0
+    UNM = 1  # - sint
+    UNP = 2  # + sint
+    NOT = 3   # ! int, float, bool
+    BNOT = 4  # ~ int
+
+class Eolian_Declaration_Type(IntEnum):
+    UNKNOWN = 0
+    CLASS = 1
+    ALIAS = 2
+    STRUCT = 3
+    ENUM = 4
+    VAR = 5
+
+class Eolian_Doc_Token_Type(IntEnum):
+    UNKNOWN = 0
+    TEXT = 1
+    REF = 2
+    MARK_NOTE = 3
+    MARK_WARNING = 4
+    MARK_REMARK = 5
+    MARK_TODO = 6
+    MARKUP_MONOSPACE = 7
+
+class Eolian_Doc_Ref_Type(IntEnum):
+    INVALID = 0
+    CLASS = 1
+    FUNC = 2
+    EVENT = 3
+    ALIAS = 4
+    STRUCT = 5
+    STRUCT_FIELD = 6
+    ENUM = 7
+    ENUM_FIELD = 8
+    VAR = 9
+
+
+###  internal Classes  ########################################################
+
+class Iterator(object):
+    """ Generic eina iterator wrapper """
+    def __init__(self, conv_func, iterator):
+        self.next = self.__next__ # py2 compat
+        self._conv = conv_func
+        self._iter = c_void_p(iterator)
+        self._tmp = c_void_p(0)
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        if not self._iter or not self._iter.value:
+            print("NULL Iterator... Error ?")
+            raise StopIteration
+        if not lib.eina_iterator_next(self._iter, byref(self._tmp)):
+            lib.eina_iterator_free(self._iter)
+            raise StopIteration
+        return self._conv(self._tmp)
+
+    def free(self):
+        lib.eina_iterator_free(self._iter)
+
+
+class EolianBaseObject(object):
+    def __init__(self, c_obj_pointer):
+        if isinstance(c_obj_pointer, c_void_p):
+            self._obj = c_void_p(c_obj_pointer.value)
+        elif isinstance(c_obj_pointer, int):
+            self._obj = c_void_p(c_obj_pointer)
+        else:
+            raise TypeError('Invalid constructor of type: %s for class: %s' % (
+                            type(c_obj_pointer), self.__class__.__name__))
+
+
+###  Main Eolian Unit  ########################################################
+
+class Eolian_Unit(EolianBaseObject):
+    def class_get_by_name(self, class_name):
+        c_cls = lib.eolian_class_get_by_name(self._obj, _str_to_bytes(class_name))
+        return Class(c_cls) if c_cls else None
+
+    def class_get_by_file(self, file_name):
+        c_cls = lib.eolian_class_get_by_file(self._obj, _str_to_bytes(file_name))
+        return Class(c_cls) if c_cls else None
+
+    @property
+    def all_classes(self):
+        return Iterator(Class, lib.eolian_all_classes_get(self._obj))
+
+    @property
+    def typedecl_all_enums(self):
+        return Iterator(Typedecl, lib.eolian_typedecl_all_enums_get(self._obj))
+
+    def typedecl_enum_get_by_name(self, name):
+        c_tdecl = lib.eolian_typedecl_enum_get_by_name(self._obj, _str_to_bytes(name))
+        return Typedecl(c_tdecl) if c_tdecl else None
+
+    def typedecl_enums_get_by_file(self, fname):
+        return Iterator(Typedecl,
+            lib.eolian_typedecl_enums_get_by_file(self._obj, _str_to_bytes(fname)))
+
+    @property
+    def typedecl_all_structs(self):
+        return Iterator(Typedecl, lib.eolian_typedecl_all_structs_get(self._obj))
+
+    def typedecl_struct_get_by_name(self, name):
+        c_tdecl = lib.eolian_typedecl_struct_get_by_name(self._obj, _str_to_bytes(name))
+        return Typedecl(c_tdecl) if c_tdecl else None
+
+    def typedecl_structs_get_by_file(self, fname):
+        return Iterator(Typedecl,
+            lib.eolian_typedecl_structs_get_by_file(self._obj, _str_to_bytes(fname)))
+
+    @property
+    def typedecl_all_aliases(self):
+        return Iterator(Typedecl, lib.eolian_typedecl_all_aliases_get(self._obj))
+
+    def typedecl_alias_get_by_name(self, name):
+        c_tdecl = lib.eolian_typedecl_alias_get_by_name(self._obj, _str_to_bytes(name))
+        return Typedecl(c_tdecl) if c_tdecl else None
+
+    def typedecl_aliases_get_by_file(self, fname):
+        return Iterator(Typedecl,
+            lib.eolian_typedecl_aliases_get_by_file(self._obj, _str_to_bytes(fname)))
+
+    @property
+    def variable_all_constants(self):
+        return Iterator(Variable, lib.eolian_variable_all_constants_get(self._obj))
+
+    def variable_constant_get_by_name(self, name):
+        c_var = lib.eolian_variable_constant_get_by_name(self._obj, _str_to_bytes(name))
+        return Variable(c_var) if c_var else None
+
+    def variable_constants_get_by_file(self, fname):
+        return Iterator(Variable,
+            lib.eolian_variable_constants_get_by_file(self._obj, _str_to_bytes(fname)))
+
+    @property
+    def variable_all_globals(self):
+        return Iterator(Variable, lib.eolian_variable_all_globals_get(self._obj))
+
+    def variable_global_get_by_name(self, name):
+        c_var = lib.eolian_variable_global_get_by_name(self._obj, _str_to_bytes(name))
+        return Variable(c_var) if c_var else None
+
+    def variable_globals_get_by_file(self, fname):
+        return Iterator(Variable,
+            lib.eolian_variable_globals_get_by_file(self._obj, _str_to_bytes(fname)))
+
+    @property
+    def all_declarations(self):
+        return Iterator(Declaration, lib.eolian_all_declarations_get(self._obj))
+
+    def declaration_get_by_name(self, name):
+        c_decl = lib.eolian_declaration_get_by_name(self._obj, _str_to_bytes(name))
+        return Declaration(c_decl) if c_decl else None
+
+    def declarations_get_by_file(self, fname):
+        return Iterator(Declaration,
+            lib.eolian_declarations_get_by_file(self._obj, _str_to_bytes(fname)))
+
+
+class Eolian(Eolian_Unit):
+    def __init__(self):
+        self._obj = lib.eolian_new()  # Eolian *
+
+    def __del__(self):
+        # TODO I'm not sure about this, It is automatically called on gc, that
+        #      is fired after atexit (eolian_shutdown). Thus causing a segfault
+        #      if the user do not call del before exit.
+        lib.eolian_free(self._obj)
+
+    def file_parse(self, filepath):
+        c_unit = lib.eolian_file_parse(self._obj, _str_to_bytes(filepath))
+        return Eolian_Unit(c_unit) if c_unit else None
+
+    @property
+    def all_eo_file_paths(self):
+        return Iterator(_str_to_py, lib.eolian_all_eo_file_paths_get(self._obj))
+
+    @property
+    def all_eot_file_paths(self):
+        return Iterator(_str_to_py, lib.eolian_all_eot_file_paths_get(self._obj))
+
+    @property
+    def all_eo_files(self):
+        return Iterator(_str_to_py, lib.eolian_all_eo_files_get(self._obj))
+
+    @property
+    def all_eot_files(self):
+        return Iterator(_str_to_py, lib.eolian_all_eot_files_get(self._obj))
+
+    def directory_scan(self, dir_path):
+        return bool(lib.eolian_directory_scan(self._obj, _str_to_bytes(dir_path)))
+
+    def system_directory_scan(self):
+        return bool(lib.eolian_system_directory_scan(self._obj))
+
+    def all_eo_files_parse(self):
+        return bool(lib.eolian_all_eo_files_parse(self._obj))
+
+    def all_eot_files_parse(self):
+        return bool(lib.eolian_all_eot_files_parse(self._obj))
+
+
+###  Eolian Classes  ##########################################################
+
+class Class(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Class '{0.full_name}', {0.type!s}>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_class_name_get(self._obj))
+
+    @property
+    def full_name(self):
+        return _str_to_py(lib.eolian_class_full_name_get(self._obj))
+
+    @property
+    def c_name(self):
+        s = lib.eolian_class_c_name_get(self._obj)
+        ret = _str_to_py(s)
+        lib.eina_stringshare_del(c_void_p(s))
+        return ret
+
+    @property
+    def c_get_function_name(self):
+        s = lib.eolian_class_c_get_function_name_get(self._obj)
+        ret = _str_to_py(s)
+        lib.eina_stringshare_del(c_void_p(s))
+        return ret
+
+    @property
+    def type(self):
+        return Eolian_Class_Type(lib.eolian_class_type_get(self._obj))
+    
+    @property
+    def data_type(self):
+        return _str_to_py(lib.eolian_class_data_type_get(self._obj))
+
+    @property
+    def c_data_type(self):
+        s = lib.eolian_class_c_data_type_get(self._obj)
+        ret = _str_to_py(s)
+        lib.eina_stringshare_del(c_void_p(s))
+        return ret
+
+    @property
+    def legacy_prefix(self):
+        return _str_to_py(lib.eolian_class_legacy_prefix_get(self._obj))
+
+    @property
+    def eo_prefix(self):
+        return _str_to_py(lib.eolian_class_eo_prefix_get(self._obj))
+
+    @property
+    def event_prefix(self):
+        return _str_to_py(lib.eolian_class_event_prefix_get(self._obj))
+
+    @property
+    def documentation(self):
+        c_doc = lib.eolian_class_documentation_get(self._obj)
+        return Documentation(c_doc) if c_doc else None
+
+    @property
+    def constructors(self):
+        return Iterator(Constructor, lib.eolian_class_constructors_get(self._obj))
+
+    @property
+    def events(self):
+        return Iterator(Event, lib.eolian_class_events_get(self._obj))
+
+    def event_get_by_name(self, event_name):
+        c_event = lib.eolian_class_event_get_by_name(self._obj,
+                                                     _str_to_bytes(event_name))
+        return Event(c_event) if c_event else None
+
+    @property
+    def inherits(self):
+        return Iterator(Class, lib.eolian_class_inherits_get(self._obj))
+
+    @property
+    def inherits_full(self):
+        L = []
+        def do_class_recursive(cls):
+            for other in cls.inherits:
+                if not other in L:
+                    L.append(other)
+                do_class_recursive(other)
+
+        do_class_recursive(self)
+        return L
+
+    @property
+    def base_class(self):
+        inherits = list(self.inherits)
+        if len(inherits) > 0:
+            return inherits[0]
+
+    @property
+    def namespaces(self):
+        return Iterator(_str_to_py, lib.eolian_class_namespaces_get(self._obj))
+
+    @property
+    def file(self):
+        return _str_to_py(lib.eolian_class_file_get(self._obj))
+
+    @property
+    def ctor_enable(self):
+        return bool(lib.eolian_class_ctor_enable_get(self._obj))
+
+    @property
+    def dtor_enable(self):
+        return bool(lib.eolian_class_dtor_enable_get(self._obj))
+
+    def function_get_by_name(self, func_name,
+                             ftype=Eolian_Function_Type.UNRESOLVED):
+        f = lib.eolian_class_function_get_by_name(self._obj,
+                                                  _str_to_bytes(func_name),
+                                                  ftype)
+        return Function(f) if f else None
+
+    def functions_get(self, ftype):
+        return Iterator(Function, lib.eolian_class_functions_get(self._obj, ftype))
+    @property
+    def methods(self):
+        return self.functions_get(Eolian_Function_Type.METHOD)
+
+    @property
+    def properties(self):
+        return self.functions_get(Eolian_Function_Type.PROPERTY)
+
+    @property
+    def implements(self):
+        return Iterator(Implement, lib.eolian_class_implements_get(self._obj))
+
+    @property
+    def parts(self):
+        return Iterator(Part, lib.eolian_class_parts_get(self._obj))
+
+
+class Part(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Part '{0.name}'>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_part_name_get(self._obj))
+
+    @property
+    def class_(self):
+        return Class(lib.eolian_part_class_get(self._obj))
+
+    @property
+    def documentation(self):
+        c_doc = lib.eolian_part_documentation_get(self._obj)
+        return Documentation(c_doc) if c_doc else None
+
+
+class Constructor(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Constructor '{0.full_name}', optional={0.is_optional}>".format(self)
+
+    @property
+    def full_name(self):
+        return _str_to_py(lib.eolian_constructor_full_name_get(self._obj))
+
+    @property
+    def function(self):
+        return Function(lib.eolian_constructor_function_get(self._obj))
+
+    @property
+    def is_optional(self):
+        return bool(lib.eolian_constructor_is_optional(self._obj))
+
+    @property
+    def class_(self):
+        return Class(lib.eolian_constructor_class_get(self._obj))
+
+
+class Event(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Event '{0.name}', c_name='{0.c_name}'>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_event_name_get(self._obj))
+
+    @property
+    def c_name(self):
+        s = lib.eolian_event_c_name_get(self._obj)
+        ret = _str_to_py(s)
+        lib.eina_stringshare_del(c_void_p(s))
+        return ret
+
+    @property
+    def type(self):
+        c_type = lib.eolian_event_type_get(self._obj)
+        return Type(c_type) if c_type else None
+
+    @property
+    def documentation(self):
+        c_doc = lib.eolian_event_documentation_get(self._obj)
+        return Documentation(c_doc) if c_doc else None
+
+    @property
+    def scope(self):
+        return Eolian_Object_Scope(lib.eolian_event_scope_get(self._obj))
+
+    @property
+    def is_beta(self):
+        return bool(lib.eolian_event_is_beta(self._obj))
+
+    @property
+    def is_hot(self):
+        return bool(lib.eolian_event_is_hot(self._obj))
+
+    @property
+    def is_restart(self):
+        return bool(lib.eolian_event_is_restart(self._obj))
+
+
+class Function(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Function '{0.name}'>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_function_name_get(self._obj))
+
+    def full_c_name_get(self, ftype, use_legacy=False):
+        s = lib.eolian_function_full_c_name_get(self._obj, ftype, use_legacy)
+        ret = _str_to_py(s)
+        lib.eina_stringshare_del(c_void_p(s))
+        return ret
+
+    @property
+    def full_c_method_name(self):
+        return self.full_c_name_get(Eolian_Function_Type.METHOD)
+
+    @property
+    def full_c_getter_name(self):
+        return self.full_c_name_get(Eolian_Function_Type.PROP_GET)
+    
+    @property
+    def full_c_setter_name(self):
+        return self.full_c_name_get(Eolian_Function_Type.PROP_SET)
+
+    @property
+    def full_c_method_name_legacy(self):
+        return self.full_c_name_get(Eolian_Function_Type.METHOD, True)
+
+    @property
+    def full_c_getter_name_legacy(self):
+        return self.full_c_name_get(Eolian_Function_Type.PROP_GET, True)
+    
+    @property
+    def full_c_setter_name_legacy(self):
+        return self.full_c_name_get(Eolian_Function_Type.PROP_SET, True)
+    
+    @property
+    def type(self):
+        return Eolian_Function_Type(lib.eolian_function_type_get(self._obj))
+
+    def scope_get(self, ftype):
+        return Eolian_Object_Scope(lib.eolian_function_scope_get(self._obj, ftype))
+
+    @property
+    def method_scope(self):
+        return self.scope_get(Eolian_Function_Type.METHOD)
+
+    @property
+    def getter_scope(self):
+        return self.scope_get(Eolian_Function_Type.PROP_GET)
+
+    @property
+    def setter_scope(self):
+        return self.scope_get(Eolian_Function_Type.PROP_SET)
+
+    def legacy_get(self, ftype):
+        return _str_to_py(lib.eolian_function_legacy_get(self._obj, ftype))
+    
+    def is_legacy_only(self, ftype):
+        return bool(lib.eolian_function_is_legacy_only(self._obj, ftype))
+
+    @property
+    def is_class(self):
+        return bool(lib.eolian_function_is_class(self._obj))
+
+    @property
+    def is_beta(self):
+        return bool(lib.eolian_function_is_beta(self._obj))
+
+    @property
+    def object_is_const(self):
+        return bool(lib.eolian_function_object_is_const(self._obj))
+
+    @property
+    def class_(self):
+        c_cls = lib.eolian_function_class_get(self._obj)
+        return Class(c_cls) if c_cls else None
+
+    def is_constructor(self, klass):
+        return bool(lib.eolian_function_is_constructor(self._obj, klass._obj))
+
+    #  @property
+    #  def is_function_pointer(self):
+        #  return bool(lib.eolian_function_is_function_pointer(self._obj))
+
+    @property
+    def parameters(self):
+        return Iterator(Function_Parameter,
+                        lib.eolian_function_parameters_get(self._obj))
+
+    def values_get(self, ftype):
+        return Iterator(Function_Parameter,
+                        lib.eolian_property_values_get(self._obj, ftype))
+
+    @property
+    def getter_values(self):
+        return self.values_get(Eolian_Function_Type.PROP_GET)
+
+    @property
+    def setter_values(self):
+        return self.values_get(Eolian_Function_Type.PROP_SET)
+
+    def return_type_get(self, ftype):
+        c_type = lib.eolian_function_return_type_get(self._obj, ftype)
+        return Type(c_type) if c_type else None
+
+    def return_default_value(self, ftye):
+        c_expr = lib.eolian_function_return_default_value_get(sel._obj, ftype)
+        return Expression(c_expr) if c_expr else None
+        
+    def return_documentation(self, ftype):
+        c_doc = lib.eolian_function_return_documentation_get(self._obj, ftype)
+        return Documentation(c_doc) if c_doc else None
+
+    def return_is_warn_unused(self, ftype):
+        return bool(lib.eolian_function_return_is_warn_unused(self._obj, ftype))
+
+    @property
+    def method_return_type(self):
+        return self.return_type_get(Eolian_Function_Type.METHOD)
+
+    @property
+    def getter_return_type(self):
+        return self.return_type_get(Eolian_Function_Type.PROP_GET)
+
+    @property
+    def setter_return_type(self):
+        return self.return_type_get(Eolian_Function_Type.PROP_SET)
+    
+    @property
+    def prop_readable(self):
+        # TODO: maybe there is a better way to do this...
+        ftype = Eolian_Function_Type.PROP_GET
+        scope = lib.eolian_function_scope_get(self._obj, ftype)
+        return True if scope != Eolian_Object_Scope.UNKNOWN else False
+
+    @property
+    def prop_writable(self):
+        # TODO: maybe there is a better way to do this...
+        ftype = Eolian_Function_Type.PROP_SET
+        scope = lib.eolian_function_scope_get(self._obj, ftype)
+        return True if scope != Eolian_Object_Scope.UNKNOWN else False
+
+    @property
+    def implement(self):
+        c_impl = lib.eolian_function_implement_get(self._obj)
+        return Implement(c_impl) if c_impl else None
+
+
+class Function_Parameter(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Function_Parameter '{0.name}', type={0.type}," \
+               " optional={0.is_optional}, nullable={0.is_nullable}>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_parameter_name_get(self._obj))
+
+    # @property
+    # def name_fixed(self):
+        # name = _str_to_py(lib.eolian_parameter_name_get(self._obj))
+        # if name in PY_KW:
+            # return name + '_'
+        # return name
+
+    # name = name_fixed
+
+    @property
+    def direction(self):
+        return Eolian_Parameter_Dir(lib.eolian_parameter_direction_get(self._obj))
+
+    @property
+    def documentation(self):
+        c_doc = lib.eolian_parameter_documentation_get(self._obj)
+        return Documentation(c_doc) if c_doc else None
+
+    @property
+    def is_nonull(self):
+        return bool(lib.eolian_parameter_is_nonull(self._obj))
+
+    @property
+    def is_nullable(self):
+        return bool(lib.eolian_parameter_is_nullable(self._obj))
+
+    @property
+    def is_optional(self):
+        return bool(lib.eolian_parameter_is_optional(self._obj))
+
+    @property
+    def type(self):
+        c_type = lib.eolian_parameter_type_get(self._obj)
+        return Type(c_type) if c_type else None
+
+    @property
+    def default_value(self):
+        c_expr = lib.eolian_parameter_default_value_get(self._obj)
+        return Expression(c_expr) if c_expr else None
+
+
+class Implement(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Implement '{0.full_name}'>".format(self)
+
+    @property
+    def full_name(self):
+        return _str_to_py(lib.eolian_implement_full_name_get(self._obj))
+
+    @property
+    def class_(self):
+        c_cls = lib.eolian_implement_class_get(self._obj)
+        return Class(c_cls) if c_cls else None
+
+    def function_get(self, ftype=Eolian_Function_Type.UNRESOLVED):
+        c_func = lib.eolian_implement_function_get(self._obj, ftype)
+        return Function(c_func) if c_func else None
+    # TODO implement util properties for function_get
+
+    def documentation_get(self, ftype=Eolian_Function_Type.METHOD):
+        c_doc = lib.eolian_implement_documentation_get(self._obj, ftype)
+        return Documentation(c_doc) if c_doc else None
+    # TODO implement util properties for documentation_get
+
+    def is_auto(self, ftype=Eolian_Function_Type.METHOD):
+        return bool(lib.eolian_implement_is_auto(self._obj, ftype))
+    # TODO implement util properties for is_auto
+
+    def is_empty(self, ftype=Eolian_Function_Type.METHOD):
+        return bool(lib.eolian_implement_is_empty(self._obj, ftype))
+    # TODO implement util properties for is_empty
+
+    def is_pure_virtual(self, ftype=Eolian_Function_Type.METHOD):
+        return bool(lib.eolian_implement_is_pure_virtual(self._obj, ftype))
+    # TODO implement util properties for is_pure_virtual
+
+    @property
+    def is_prop_set(self):
+        return bool(lib.eolian_implement_is_prop_set(self._obj))
+
+    @property
+    def is_prop_get(self):
+        return bool(lib.eolian_implement_is_prop_get(self._obj))
+
+
+class Type(EolianBaseObject):  # OK  (4 eolian issue)
+    def __repr__(self):
+        #  return "<eolian.Type '{0.full_name}', type: {0.type!s}, c_type: '{0.c_type}'>".format(self)
+        return "<eolian.Type '{0.full_name}', type={0.type!s}>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_type_name_get(self._obj))
+
+    @property
+    def full_name(self):
+        return _str_to_py(lib.eolian_type_full_name_get(self._obj))
+
+    @property
+    def namespaces(self):
+        return Iterator(_str_to_py,
+                        lib.eolian_type_namespaces_get(self._obj))
+
+    @property
+    def free_func(self):
+        return _str_to_py(lib.eolian_type_free_func_get(self._obj))
+
+    @property
+    def type(self):
+        return Eolian_Type_Type(lib.eolian_type_type_get(self._obj))
+
+    @property
+    def builtin_type(self):
+        return Eolian_Type_Builtin_Type(lib.eolian_type_builtin_type_get(self._obj))
+
+    # TODO FIXME STRANGE API (need Eolian_Unit*)
+    #  @property
+    #  def c_type(self):
+        #  return _str_to_py(lib.eolian_type_c_type_get(self._obj))
+
+    # TODO FIXME STRANGE API (need Eolian_Unit*)
+    #  @property
+    #  def typedecl(self):
+        #  c_tdecl = lib.eolian_type_typedecl_get(self._obj)
+        #  return Typedecl(c_tdecl) if c_tdecl else None
+
+    @property
+    def base_type(self):
+        c_type = lib.eolian_type_base_type_get(self._obj)
+        return Type(c_type) if c_type else None 
+
+    @property
+    def next_type(self):
+        c_type = lib.eolian_type_next_type_get(self._obj)
+        return Type(c_type) if c_type else None 
+
+    # TODO FIXME STRANGE API (need Eolian_Unit*)
+    #  @property
+    #  def aliased_base(self):
+        #  c_type = lib.eolian_type_aliased_base_get(self._obj)
+        #  return Type(c_type) if c_type else None 
+
+    # TODO FIXME STRANGE API (need Eolian_Unit*)
+    #  @property
+    #  def class_(self):
+        #  c_cls = lib.eolian_type_class_get(self._obj)
+        #  return Class(c_cls) if c_cls else None
+
+    @property
+    def file(self):
+        return _str_to_py(lib.eolian_type_file_get(self._obj))
+
+    @property
+    def is_owned(self):
+        return bool(lib.eolian_type_is_owned(self._obj))
+
+    @property
+    def is_const(self):
+        return bool(lib.eolian_type_is_const(self._obj))
+
+    @property
+    def is_ptr(self):
+        return bool(lib.eolian_type_is_ptr(self._obj))
+
+
+class Typedecl(EolianBaseObject):  # OK (2 TODO)
+    def __repr__(self):
+        return "<eolian.Typedecl '{0.full_name}', type={0.type!s}>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_typedecl_name_get(self._obj))
+
+    @property
+    def full_name(self):
+        return _str_to_py(lib.eolian_typedecl_full_name_get(self._obj))
+
+    @property
+    def file(self):
+        return _str_to_py(lib.eolian_typedecl_file_get(self._obj))
+
+    @property
+    def type(self):
+        return Eolian_Typedecl_Type(lib.eolian_typedecl_type_get(self._obj))
+
+    # TODO FIX THIS, need Eolian_Unit* param  ???
+    #  @property
+    #  def c_type(self):
+        #  return _str_to_py(lib.eolian_typedecl_c_type_get(self._obj))
+
+    @property
+    def namespaces(self):
+        return Iterator(_str_to_py,
+                        lib.eolian_typedecl_namespaces_get(self._obj))
+
+    @property
+    def free_func(self):
+        return _str_to_py(lib.eolian_typedecl_free_func_get(self._obj))
+
+    @property
+    def is_extern(self):
+        return bool(lib.eolian_typedecl_is_extern(self._obj))
+
+    @property
+    def enum_fields(self):
+        return Iterator(Enum_Type_Field,
+                        lib.eolian_typedecl_enum_fields_get(self._obj))
+
+    def enum_field_get(self, field):
+        c_field = lib.eolian_typedecl_enum_field_get(self._obj, _str_to_bytes(field))
+        return Enum_Type_Field(c_field) if c_field else None
+
+    @property
+    def struct_fields(self):
+        return Iterator(Struct_Type_Field,
+                        lib.eolian_typedecl_struct_fields_get(self._obj)) 
+
+    def struct_field_get(self, field):
+        c_field = lib.eolian_typedecl_struct_field_get(self._obj, _str_to_bytes(field))
+        return Struct_Type_Field(c_field) if c_field else None
+
+    @property
+    def base_type(self):
+        c_type = lib.eolian_typedecl_base_type_get(self._obj)
+        return Type(c_type) if c_type else None
+
+    # TODO FIX THIS, need Eolian_Unit* param  ???
+    #  @property
+    #  def aliased_base(self):
+        #  c_type = lib.eolian_typedecl_aliased_base_get(self._obj)
+        #  return Type(c_type) if c_type else None
+
+    @property
+    def documentation(self):
+        c_doc = lib.eolian_typedecl_documentation_get(self._obj)
+        return Documentation(c_doc) if c_doc else None
+
+    @property
+    def enum_legacy_prefix(self):
+        return _str_to_py(lib.eolian_typedecl_enum_legacy_prefix_get(self._obj))
+
+    @property
+    def function_pointer(self):
+        c_func = lib.eolian_typedecl_function_pointer_get(self._obj)
+        return Function(c_func) if c_func else None
+
+
+class Enum_Type_Field(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Enum_Type_Field '{0.name}', c_name='{0.c_name}'>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_typedecl_enum_field_name_get(self._obj))
+
+    @property
+    def c_name(self):
+        s = lib.eolian_typedecl_enum_field_c_name_get(self._obj)
+        ret = _str_to_py(s)
+        lib.eina_stringshare_del(c_void_p(s))
+        return ret
+
+    @property
+    def value(self):
+        c_expr = lib.eolian_typedecl_enum_field_value_get(self._obj, True)
+        return Expression(c_expr) if c_expr else None
+
+    @property
+    def documentation(self):
+        c_doc = lib.eolian_typedecl_enum_field_documentation_get(self._obj)
+        return Documentation(c_doc) if c_doc else None
+
+
+class Struct_Type_Field(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Struct_Type_Field '{0.name}', type={0.type!s}>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_typedecl_struct_field_name_get(self._obj))
+
+    @property
+    def type(self):
+        c_type = lib.eolian_typedecl_struct_field_type_get(self._obj)
+        return Type(c_type) if c_type else None
+    
+    @property
+    def documentation(self):
+        c_doc = lib.eolian_typedecl_struct_field_documentation_get(self._obj)
+        return Documentation(c_doc) if c_doc else None
+
+
+class Expression(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Expression type={0.type!s}, serialize='{0.serialize}'>".format(self)
+
+    @property
+    def type(self):
+        return Eolian_Expression_Type(lib.eolian_expression_type_get(self._obj))
+
+    # TODO: EAPI Eolian_Value eolian_expression_value_get(const Eolian_Expression *expr);
+
+    @property
+    def serialize(self):
+        s = lib.eolian_expression_serialize(self._obj)
+        ret = _str_to_py(s)
+        lib.eina_stringshare_del(c_void_p(s))
+        return ret
+    
+    @property
+    def binary_operator(self):
+        c_op = lib.eolian_expression_binary_operator_get(self._obj)
+        return Eolian_Binary_Operator(c_op) if c_op is not None else None
+
+    @property
+    def binary_lhs(self):
+        c_expr = lib.eolian_expression_binary_lhs_get(self._obj)
+        return Expression(c_expr) if c_expr else None
+
+    @property
+    def binary_rhs(self):
+        c_expr = lib.eolian_expression_binary_rhs_get(self._obj)
+        return Expression(c_expr) if c_expr else None
+
+    @property
+    def unary_operator(self):
+        c_op = lib.eolian_expression_unary_operator_get(self._obj)
+        return Eolian_Unary_Operator(c_op) if c_op is not None else None
+
+    @property
+    def unary_expression(self):
+        c_expr = lib.eolian_expression_unary_expression_get(self._obj)
+        return Expression(c_expr) if c_expr is not None else None
+
+
+class Variable(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Variable '{0.full_name}', type={0.type!s}, file={0.file}>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_variable_name_get(self._obj))
+
+    @property
+    def full_name(self):
+        return _str_to_py(lib.eolian_variable_full_name_get(self._obj))
+
+    @property
+    def namespaces(self):
+        return Iterator(_str_to_py,
+                        lib.eolian_variable_namespaces_get(self._obj))
+
+    @property
+    def type(self):
+        return Eolian_Variable_Type(lib.eolian_variable_type_get(self._obj))
+
+    @property
+    def value(self):
+        c_expr = lib.eolian_variable_value_get(self._obj)
+        return Expression(c_expr) if c_expr else None
+
+    @property
+    def file(self):
+        return _str_to_py(lib.eolian_variable_file_get(self._obj))
+
+    @property
+    def base_type(self):
+        c_type = lib.eolian_variable_base_type_get(self._obj)
+        return Type(c_type) if c_type else None
+
+    @property
+    def is_extern(self):
+        return bool(lib.eolian_variable_is_extern(self._obj))
+    
+    
+    @property
+    def documentation(self):
+        c_doc = lib.eolian_variable_documentation_get(self._obj)
+        return Documentation(c_doc) if c_doc else None
+
+
+class Declaration(EolianBaseObject):
+    def __repr__(self):
+        return "<eolian.Declaration '{0.name}'>".format(self)
+
+    @property
+    def name(self):
+        return _str_to_py(lib.eolian_declaration_name_get(self._obj))
+
+    @property
+    def type(self):
+        return Eolian_Declaration_Type(lib.eolian_declaration_type_get(self._obj))
+
+    @property
+    def class_(self):
+        c_cls = lib.eolian_declaration_class_get(self._obj)
+        return Class(c_cls) if c_cls else None
+
+    @property
+    def data_type(self):
+        c_typedec = lib.eolian_declaration_data_type_get(self._obj)
+        return Typedecl(c_typedec) if c_typedec else None
+
+    @property
+    def variable(self):
+        c_var = lib.eolian_declaration_variable_get(self._obj)
+        return Variable(c_var) if c_var else None
+
+
+class Documentation(EolianBaseObject):
+    # def __repr__(self):
+        # return "<eolian.Documentation '{0.name}'>".format(self)
+
+    # this is too much for py, just use string.split('\n\n')
+    # def string_split(self, string):
+    #    c_list = lib.eolian_documentation_string_split
+
+    @property
+    def summary(self):
+        return _str_to_py(lib.eolian_documentation_summary_get(self._obj))
+
+    @property
+    def description(self):
+        return _str_to_py(lib.eolian_documentation_description_get(self._obj))
+
+    @property
+    def since(self):
+        return _str_to_py(lib.eolian_documentation_since_get(self._obj))
+
+
+###  internal string encode/decode  ###########################################
+
+def _str_to_bytes(s):
+    return s.encode('utf-8')
+
+def _str_to_py(s):
+    if s is None:
+        return None    
+    if isinstance(s, bytes):
+        return s.decode('utf-8')
+    if isinstance(s, c_char_p):
+        return s.value.decode('utf-8')
+    if isinstance(s, c_void_p):
+        return cast(s, c_char_p).value.decode('utf-8')
+    if isinstance(s, int):
+        return cast(s, c_char_p).value.decode('utf-8')
+    print('WARNING !!!!!!!!! Unknown type: %s' % type(s))
+
+
+###  module init/shutdown  ####################################################
+
+import atexit
+lib.eolian_init()
+atexit.register(lambda: lib.eolian_shutdown())
+
+
+
+###  API coverage statistics  #################################################
+
+if __name__ == '__main__':
+    import sys
+    import os
+    import re
+
+    # find Eolian.h in source tree
+    script_path = os.path.dirname(os.path.realpath(__file__))
+    eolian_header = os.path.join(script_path, '..', '..', 'lib', 'eolian', 'Eolian.h')
+    eolian_header = os.path.abspath(eolian_header)
+
+    # prepare the two regexp
+    flags = re.S | re.M
+    DEFINED_RE = re.compile('^EAPI[\w\n *]*(eolian_\w*)\([\w *,]*\);', flags)
+    USED_RE = re.compile('lib\.(eolian_[\w]*)\(', flags)
+
+    # extract all EAPI functions from Eolian.h
+    defined_funcs = []
+    with open(eolian_header, 'r') as fh:
+        header = fh.read()
+        for match in re.finditer(DEFINED_RE, header):
+            func_name = match.group(1)
+            defined_funcs.append(func_name)
+    defined_funcs = set(defined_funcs)
+
+    # extract all called functions in eolian.py (this file)
+    used_funcs = []
+    with open(__file__, 'r') as fh:
+        source = fh.read()
+        for match in re.finditer(USED_RE, source):
+            func_name = match.group(1)
+            used_funcs.append(func_name)
+    used_funcs = set(used_funcs)
+
+    # show general info
+    num_def = len(defined_funcs)
+    num_usd = len(used_funcs)
+    print('Pyolian coverage results')
+    print('========================')
+    print('Found %d functions defined in Eolian.h (%s)' % (num_def, eolian_header))
+    print('Found %d functions used in eolian.py (hopefully not commented out)' % num_usd)
+    print('Total API coverage %.1f%%' % (num_usd / num_def * 100))
+    print()
+
+    # list all missing functions
+    missing = defined_funcs - used_funcs
+    print('{} Missing functions in eolian.py'.format(len(missing)))
+    print('=================================')
+    for i, func_name in enumerate(sorted(missing), 1):
+        print('{:02d}. {}'.format(i, func_name))
+    print()
+
+    # List all functions found in Eolian.h  (--all option)
+    if '--all' in sys.argv:
+        print('{} functions found in Eolian.h'.format(num_def))
+        print('===============================')
+        for i, func_name in enumerate(sorted(defined_funcs), 1):
+            print('{:03d}. {}'.format(i, func_name))
+        print()
+    else:
+        print('Additional arguments')
+        print('====================')
+        print(' --all   To list all functions')
+        print()
diff --git a/src/scripts/pyolian/eolian_lib.py b/src/scripts/pyolian/eolian_lib.py
new file mode 100644 (file)
index 0000000..5553d06
--- /dev/null
@@ -0,0 +1,757 @@
+#!/usr/bin/env python3
+# encoding: utf-8
+
+from ctypes import CDLL, c_bool, c_int, c_uint, c_char_p, c_void_p
+from ctypes.util import find_library
+
+import os
+
+
+# load the eolian so/dll already built in source tree
+script_path = os.path.dirname(os.path.realpath(__file__))
+root_path = os.path.abspath(os.path.join(script_path, '..', '..', '..'))
+
+search_in = (
+    os.path.join(root_path, 'src', 'lib', 'eolian', '.libs'),
+    os.path.join(root_path, 'build', 'src', 'lib', 'eolian'),
+)
+
+search_names = ('libeolian.so', 'eolian.dll')
+
+file_path = None
+for lib_dir in search_in:
+    for name in search_names:
+        f = os.path.join(lib_dir, name)
+        if os.path.exists(f):
+            file_path = f
+
+if not file_path:
+    raise RuntimeError('Error: cannot find a built eolian library in source tree')
+
+lib = CDLL(file_path)
+
+
+# EAPI int eolian_init(void);
+lib.eolian_init.argtypes = []
+lib.eolian_init.restype = c_int
+
+# EAPI int eolian_shutdown(void);
+lib.eolian_shutdown.argtypes = []
+lib.eolian_shutdown.restype = c_int
+
+# EAPI Eolian *eolian_new(void);
+lib.eolian_new.argtypes = []
+lib.eolian_new.restype = c_void_p
+
+# EAPI void eolian_free(Eolian *state);
+lib.eolian_free.argtypes = [c_void_p,]
+lib.eolian_free.restype = None
+
+# EAPI const Eolian_Unit *eolian_file_parse(Eolian *state, const char *filepath);
+lib.eolian_file_parse.argtypes = [c_void_p, c_char_p]
+lib.eolian_file_parse.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_all_eo_file_paths_get(const Eolian *state);
+lib.eolian_all_eo_file_paths_get.argtypes = [c_void_p,]
+lib.eolian_all_eo_file_paths_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_all_eot_file_paths_get(const Eolian *state);
+lib.eolian_all_eot_file_paths_get.argtypes = [c_void_p,]
+lib.eolian_all_eot_file_paths_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_all_eo_files_get(const Eolian *state);
+lib.eolian_all_eo_files_get.argtypes = [c_void_p,]
+lib.eolian_all_eo_files_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_all_eot_files_get(const Eolian *state);
+lib.eolian_all_eot_files_get.argtypes = [c_void_p,]
+lib.eolian_all_eot_files_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_directory_scan(Eolian *state, const char *dir);
+lib.eolian_directory_scan.argtypes = [c_void_p, c_char_p]
+lib.eolian_directory_scan.restype = c_bool
+
+# EAPI Eina_Bool eolian_system_directory_scan(Eolian *state);
+lib.eolian_system_directory_scan.argtypes = [c_void_p,]
+lib.eolian_system_directory_scan.restype = c_bool
+
+# EAPI Eina_Bool eolian_all_eo_files_parse(Eolian *state);
+lib.eolian_all_eo_files_parse.argtypes = [c_void_p,]
+lib.eolian_all_eo_files_parse.restype = c_bool
+
+# EAPI Eina_Bool eolian_all_eot_files_parse(Eolian *state);
+lib.eolian_all_eot_files_parse.argtypes = [c_void_p,]
+lib.eolian_all_eot_files_parse.restype = c_bool
+
+# EAPI const Eolian_Class *eolian_class_get_by_name(const Eolian_Unit *unit, const char *class_name);
+lib.eolian_class_get_by_name.argtypes = [c_void_p, c_char_p]
+lib.eolian_class_get_by_name.restype = c_void_p
+
+# EAPI const Eolian_Class *eolian_class_get_by_file(const Eolian_Unit *unit, const char *file_name);
+lib.eolian_class_get_by_file.argtypes = [c_void_p, c_char_p]
+lib.eolian_class_get_by_file.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_class_file_get(const Eolian_Class *klass);
+lib.eolian_class_file_get.argtypes = [c_void_p,]
+lib.eolian_class_file_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_class_full_name_get(const Eolian_Class *klass);
+lib.eolian_class_full_name_get.argtypes = [c_void_p,]
+lib.eolian_class_full_name_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_class_name_get(const Eolian_Class *klass);
+lib.eolian_class_name_get.argtypes = [c_void_p,]
+lib.eolian_class_name_get.restype = c_char_p
+
+# EAPI Eina_Iterator *eolian_class_namespaces_get(const Eolian_Class *klass);
+lib.eolian_class_namespaces_get.argtypes = [c_void_p,]
+lib.eolian_class_namespaces_get.restype = c_void_p
+
+# EAPI Eolian_Class_Type eolian_class_type_get(const Eolian_Class *klass);
+lib.eolian_class_type_get.argtypes = [c_void_p,]
+lib.eolian_class_type_get.restype = c_int
+
+# EAPI Eina_Iterator *eolian_all_classes_get(const Eolian_Unit *unit);
+lib.eolian_all_classes_get.argtypes = [c_void_p,]
+lib.eolian_all_classes_get.restype = c_void_p
+
+# EAPI const Eolian_Documentation *eolian_class_documentation_get(const Eolian_Class *klass);
+lib.eolian_class_documentation_get.argtypes = [c_void_p,]
+lib.eolian_class_documentation_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_class_legacy_prefix_get(const Eolian_Class *klass);
+lib.eolian_class_legacy_prefix_get.argtypes = [c_void_p,]
+lib.eolian_class_legacy_prefix_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_class_eo_prefix_get(const Eolian_Class *klass);
+lib.eolian_class_eo_prefix_get.argtypes = [c_void_p,]
+lib.eolian_class_eo_prefix_get.restype = c_char_p
+
+# EAPI Eina_Stringshare* eolian_class_event_prefix_get(const Eolian_Class *klass);
+lib.eolian_class_event_prefix_get.argtypes = [c_void_p,]
+lib.eolian_class_event_prefix_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_class_data_type_get(const Eolian_Class *klass);
+lib.eolian_class_data_type_get.argtypes = [c_void_p,]
+lib.eolian_class_data_type_get.restype = c_char_p
+
+# EAPI Eina_Iterator *eolian_class_inherits_get(const Eolian_Class *klass);
+lib.eolian_class_inherits_get.argtypes = [c_void_p,]
+lib.eolian_class_inherits_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_class_functions_get(const Eolian_Class *klass, Eolian_Function_Type func_type);
+lib.eolian_class_functions_get.argtypes = [c_void_p, c_int]
+lib.eolian_class_functions_get.restype = c_void_p
+
+# EAPI Eolian_Function_Type eolian_function_type_get(const Eolian_Function *function_id);
+lib.eolian_function_type_get.argtypes = [c_void_p,]
+lib.eolian_function_type_get.restype = c_int
+
+# EAPI Eolian_Object_Scope eolian_function_scope_get(const Eolian_Function *function_id, Eolian_Function_Type ftype);
+lib.eolian_function_scope_get.argtypes = [c_void_p, c_int]
+lib.eolian_function_scope_get.restype = c_int
+
+# EAPI Eina_Stringshare *eolian_function_name_get(const Eolian_Function *function_id);
+lib.eolian_function_name_get.argtypes = [c_void_p,]
+lib.eolian_function_name_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_function_full_c_name_get(const Eolian_Function *function_id, Eolian_Function_Type ftype, Eina_Bool use_legacy);
+lib.eolian_function_full_c_name_get.argtypes = [c_void_p, c_int, c_bool]
+lib.eolian_function_full_c_name_get.restype = c_void_p  # Stringshare TO BE FREED
+
+# EAPI const Eolian_Function *eolian_class_function_get_by_name(const Eolian_Class *klass, const char *func_name, Eolian_Function_Type f_type);
+lib.eolian_class_function_get_by_name.argtypes = [c_void_p, c_char_p, c_int]
+lib.eolian_class_function_get_by_name.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_function_legacy_get(const Eolian_Function *function_id, Eolian_Function_Type f_type);
+lib.eolian_function_legacy_get.argtypes = [c_void_p, c_int]
+lib.eolian_function_legacy_get.restype = c_char_p
+
+# EAPI const Eolian_Implement *eolian_function_implement_get(const Eolian_Function *function_id);
+lib.eolian_function_implement_get.argtypes = [c_void_p,]
+lib.eolian_function_implement_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_function_is_legacy_only(const Eolian_Function *function_id, Eolian_Function_Type ftype);
+lib.eolian_function_is_legacy_only.argtypes = [c_void_p, c_int]
+lib.eolian_function_is_legacy_only.restype = c_bool
+
+# EAPI Eina_Bool eolian_function_is_class(const Eolian_Function *function_id);
+lib.eolian_function_is_class.argtypes = [c_void_p,]
+lib.eolian_function_is_class.restype = c_bool
+
+# EAPI Eina_Bool eolian_function_is_beta(const Eolian_Function *function_id);
+lib.eolian_function_is_beta.argtypes = [c_void_p,]
+lib.eolian_function_is_beta.restype = c_bool
+
+# EAPI Eina_Bool eolian_function_is_constructor(const Eolian_Function *function_id, const Eolian_Class *klass);
+lib.eolian_function_is_constructor.argtypes = [c_void_p,c_void_p,]
+lib.eolian_function_is_constructor.restype = c_bool
+
+# TODO FIXME
+# EAPI Eina_Bool eolian_function_is_function_pointer(const Eolian_Function *function_id);
+#  lib.eolian_function_is_function_pointer.argtypes = [c_void_p,]
+#  lib.eolian_function_is_function_pointer.restype = c_bool
+
+# EAPI Eina_Iterator *eolian_function_parameters_get(const Eolian_Function *function_id);
+lib.eolian_function_parameters_get.argtypes = [c_void_p,]
+lib.eolian_function_parameters_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_property_keys_get(const Eolian_Function *foo_id, Eolian_Function_Type ftype);
+lib.eolian_property_keys_get.argtypes = [c_void_p, c_int]
+lib.eolian_property_keys_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_property_values_get(const Eolian_Function *foo_id, Eolian_Function_Type ftype);
+lib.eolian_property_values_get.argtypes = [c_void_p, c_int]
+lib.eolian_property_values_get.restype = c_void_p
+
+# EAPI Eolian_Parameter_Dir eolian_parameter_direction_get(const Eolian_Function_Parameter *param);
+lib.eolian_parameter_direction_get.argtypes = [c_void_p,]
+lib.eolian_parameter_direction_get.restype = c_int
+
+# EAPI const Eolian_Type *eolian_parameter_type_get(const Eolian_Function_Parameter *param);
+lib.eolian_parameter_type_get.argtypes = [c_void_p,]
+lib.eolian_parameter_type_get.restype = c_void_p
+
+# EAPI const Eolian_Expression *eolian_parameter_default_value_get(const Eolian_Function_Parameter *param);
+lib.eolian_parameter_default_value_get.argtypes = [c_void_p,]
+lib.eolian_parameter_default_value_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_parameter_name_get(const Eolian_Function_Parameter *param);
+lib.eolian_parameter_name_get.argtypes = [c_void_p,]
+lib.eolian_parameter_name_get.restype = c_char_p
+
+# EAPI const Eolian_Documentation *eolian_parameter_documentation_get(const Eolian_Function_Parameter *param);
+lib.eolian_parameter_documentation_get.argtypes = [c_void_p,]
+lib.eolian_parameter_documentation_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_parameter_is_nonull(const Eolian_Function_Parameter *param_desc);
+lib.eolian_parameter_is_nonull.argtypes = [c_void_p,]
+lib.eolian_parameter_is_nonull.restype = c_bool
+
+# EAPI Eina_Bool eolian_parameter_is_nullable(const Eolian_Function_Parameter *param_desc);
+lib.eolian_parameter_is_nullable.argtypes = [c_void_p,]
+lib.eolian_parameter_is_nullable.restype = c_bool
+
+# EAPI Eina_Bool eolian_parameter_is_optional(const Eolian_Function_Parameter *param_desc);
+lib.eolian_parameter_is_optional.argtypes = [c_void_p,]
+lib.eolian_parameter_is_optional.restype = c_bool
+
+# EAPI const Eolian_Type *eolian_function_return_type_get(const Eolian_Function *function_id, Eolian_Function_Type ftype);
+lib.eolian_function_return_type_get.argtypes = [c_void_p, c_int]
+lib.eolian_function_return_type_get.restype = c_void_p
+
+# EAPI const Eolian_Expression * eolian_function_return_default_value_get(const Eolian_Function *foo_id, Eolian_Function_Type ftype);
+lib.eolian_function_return_default_value_get.argtypes = [c_void_p, c_int]
+lib.eolian_function_return_default_value_get.restype = c_void_p
+
+# EAPI const Eolian_Documentation *eolian_function_return_documentation_get(const Eolian_Function *foo_id, Eolian_Function_Type ftype);
+lib.eolian_function_return_documentation_get.argtypes = [c_void_p, c_int]
+lib.eolian_function_return_documentation_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_function_return_is_warn_unused(const Eolian_Function *foo_id, Eolian_Function_Type ftype);
+lib.eolian_function_return_is_warn_unused.argtypes = [c_void_p, c_int]
+lib.eolian_function_return_is_warn_unused.restype = c_bool
+
+# EAPI Eina_Bool eolian_function_object_is_const(const Eolian_Function *function_id);
+lib.eolian_function_object_is_const.argtypes = [c_void_p,]
+lib.eolian_function_object_is_const.restype = c_bool
+
+# EAPI const Eolian_Class *eolian_function_class_get(const Eolian_Function *function_id);
+lib.eolian_function_class_get.argtypes = [c_void_p,]
+lib.eolian_function_class_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_implement_full_name_get(const Eolian_Implement *impl);
+lib.eolian_implement_full_name_get.argtypes = [c_void_p,]
+lib.eolian_implement_full_name_get.restype = c_char_p
+
+# EAPI const Eolian_Class *eolian_implement_class_get(const Eolian_Implement *impl);
+lib.eolian_implement_class_get.argtypes = [c_void_p,]
+lib.eolian_implement_class_get.restype = c_void_p
+
+# EAPI const Eolian_Function *eolian_implement_function_get(const Eolian_Implement *impl, Eolian_Function_Type *func_type);
+lib.eolian_implement_function_get.argtypes = [c_void_p, c_int]
+lib.eolian_implement_function_get.restype = c_void_p
+
+# EAPI const Eolian_Documentation *eolian_implement_documentation_get(const Eolian_Implement *impl, Eolian_Function_Type f_type);
+lib.eolian_implement_documentation_get.argtypes = [c_void_p, c_int]
+lib.eolian_implement_documentation_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_implement_is_auto(const Eolian_Implement *impl, Eolian_Function_Type f_type);
+lib.eolian_implement_is_auto.argtypes = [c_void_p, c_int]
+lib.eolian_implement_is_auto.restype = c_bool
+
+# EAPI Eina_Bool eolian_implement_is_empty(const Eolian_Implement *impl, Eolian_Function_Type f_type);
+lib.eolian_implement_is_empty.argtypes = [c_void_p, c_int]
+lib.eolian_implement_is_empty.restype = c_bool
+
+# EAPI Eina_Bool eolian_implement_is_pure_virtual(const Eolian_Implement *impl, Eolian_Function_Type f_type);
+lib.eolian_implement_is_pure_virtual.argtypes = [c_void_p, c_int]
+lib.eolian_implement_is_pure_virtual.restype = c_bool
+
+# EAPI Eina_Bool eolian_implement_is_prop_get(const Eolian_Implement *impl);
+lib.eolian_implement_is_prop_get.argtypes = [c_void_p,]
+lib.eolian_implement_is_prop_get.restype = c_bool
+
+# EAPI Eina_Bool eolian_implement_is_prop_set(const Eolian_Implement *impl);
+lib.eolian_implement_is_prop_set.argtypes = [c_void_p,]
+lib.eolian_implement_is_prop_set.restype = c_bool
+
+# EAPI Eina_Iterator *eolian_class_implements_get(const Eolian_Class *klass);
+lib.eolian_class_implements_get.argtypes = [c_void_p,]
+lib.eolian_class_implements_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_constructor_full_name_get(const Eolian_Constructor *ctor);
+lib.eolian_constructor_full_name_get.argtypes = [c_void_p,]
+lib.eolian_constructor_full_name_get.restype = c_char_p
+
+# EAPI const Eolian_Class *eolian_constructor_class_get(const Eolian_Constructor *ctor);
+lib.eolian_constructor_class_get.argtypes = [c_void_p,]
+lib.eolian_constructor_class_get.restype = c_void_p
+
+# EAPI const Eolian_Function *eolian_constructor_function_get(const Eolian_Constructor *ctor);
+lib.eolian_constructor_function_get.argtypes = [c_void_p,]
+lib.eolian_constructor_function_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_constructor_is_optional(const Eolian_Constructor *ctor);
+lib.eolian_constructor_is_optional.argtypes = [c_void_p,]
+lib.eolian_constructor_is_optional.restype = c_bool
+
+# EAPI Eina_Iterator *eolian_class_constructors_get(const Eolian_Class *klass);
+lib.eolian_class_constructors_get.argtypes = [c_void_p,]
+lib.eolian_class_constructors_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_class_events_get(const Eolian_Class *klass);
+lib.eolian_class_events_get.argtypes = [c_void_p,]
+lib.eolian_class_events_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_event_name_get(const Eolian_Event *event);
+lib.eolian_event_name_get.argtypes = [c_void_p,]
+lib.eolian_event_name_get.restype = c_char_p
+
+# EAPI const Eolian_Type *eolian_event_type_get(const Eolian_Event *event);
+lib.eolian_event_type_get.argtypes = [c_void_p,]
+lib.eolian_event_type_get.restype = c_void_p
+
+# EAPI const Eolian_Documentation *eolian_event_documentation_get(const Eolian_Event *event);
+lib.eolian_event_documentation_get.argtypes = [c_void_p,]
+lib.eolian_event_documentation_get.restype = c_void_p
+
+# EAPI Eolian_Object_Scope eolian_event_scope_get(const Eolian_Event *event);
+lib.eolian_event_scope_get.argtypes = [c_void_p,]
+lib.eolian_event_scope_get.restype = c_int
+
+# EAPI Eina_Bool eolian_event_is_beta(const Eolian_Event *event);
+lib.eolian_event_is_beta.argtypes = [c_void_p,]
+lib.eolian_event_is_beta.restype = c_bool
+
+# EAPI Eina_Bool eolian_event_is_hot(const Eolian_Event *event);
+lib.eolian_event_is_hot.argtypes = [c_void_p,]
+lib.eolian_event_is_hot.restype = c_bool
+
+# EAPI Eina_Bool eolian_event_is_restart(const Eolian_Event *event);
+lib.eolian_event_is_restart.argtypes = [c_void_p,]
+lib.eolian_event_is_restart.restype = c_bool
+
+# EAPI Eina_Iterator *eolian_class_parts_get(const Eolian_Class *klass);
+lib.eolian_class_parts_get.argtypes = [c_void_p,]
+lib.eolian_class_parts_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_part_name_get(const Eolian_Part *part);
+lib.eolian_part_name_get.argtypes = [c_void_p,]
+lib.eolian_part_name_get.restype = c_char_p
+
+# EAPI const Eolian_Class *eolian_part_class_get(const Eolian_Part *part);
+lib.eolian_part_class_get.argtypes = [c_void_p,]
+lib.eolian_part_class_get.restype = c_void_p
+
+# EAPI const Eolian_Documentation *eolian_part_documentation_get(const Eolian_Part *part);
+lib.eolian_part_documentation_get.argtypes = [c_void_p,]
+lib.eolian_part_documentation_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_event_c_name_get(const Eolian_Event *event);
+lib.eolian_event_c_name_get.argtypes = [c_void_p,]
+lib.eolian_event_c_name_get.restype = c_void_p  # Stringshare TO BE FREED
+
+# EAPI const Eolian_Event *eolian_class_event_get_by_name(const Eolian_Class *klass, const char *event_name);
+lib.eolian_class_event_get_by_name.argtypes = [c_void_p, c_char_p]
+lib.eolian_class_event_get_by_name.restype = c_void_p
+
+# EAPI Eina_Bool eolian_class_ctor_enable_get(const Eolian_Class *klass);
+lib.eolian_class_ctor_enable_get.argtypes = [c_void_p,]
+lib.eolian_class_ctor_enable_get.restype = c_bool
+
+# EAPI Eina_Bool eolian_class_dtor_enable_get(const Eolian_Class *klass);
+lib.eolian_class_dtor_enable_get.argtypes = [c_void_p,]
+lib.eolian_class_dtor_enable_get.restype = c_bool
+
+# EAPI Eina_Stringshare *eolian_class_c_get_function_name_get(const Eolian_Class *klass);
+lib.eolian_class_c_get_function_name_get.argtypes = [c_void_p,]
+lib.eolian_class_c_get_function_name_get.restype = c_void_p  # Stringshare TO BE FREED
+
+# EAPI Eina_Stringshare *eolian_class_c_name_get(const Eolian_Class *klass);
+lib.eolian_class_c_name_get.argtypes = [c_void_p,]
+lib.eolian_class_c_name_get.restype = c_void_p  # Stringshare TO BE FREED
+
+# EAPI Eina_Stringshare *eolian_class_c_data_type_get(const Eolian_Class *klass);
+lib.eolian_class_c_data_type_get.argtypes = [c_void_p,]
+lib.eolian_class_c_data_type_get.restype = c_void_p  # Stringshare TO BE FREED
+
+# EAPI const Eolian_Typedecl *eolian_typedecl_alias_get_by_name(const Eolian_Unit *unit, const char *name);
+lib.eolian_typedecl_alias_get_by_name.argtypes = [c_void_p, c_char_p]
+lib.eolian_typedecl_alias_get_by_name.restype = c_void_p
+
+# EAPI const Eolian_Typedecl *eolian_typedecl_struct_get_by_name(const Eolian_Unit *unit, const char *name);
+lib.eolian_typedecl_struct_get_by_name.argtypes = [c_void_p, c_char_p]
+lib.eolian_typedecl_struct_get_by_name.restype = c_void_p
+
+# EAPI const Eolian_Typedecl *eolian_typedecl_enum_get_by_name(const Eolian_Unit *unit, const char *name);
+lib.eolian_typedecl_enum_get_by_name.argtypes = [c_void_p, c_char_p]
+lib.eolian_typedecl_enum_get_by_name.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_typedecl_aliases_get_by_file(const Eolian_Unit *unit, const char *fname);
+lib.eolian_typedecl_aliases_get_by_file.argtypes = [c_void_p, c_char_p]
+lib.eolian_typedecl_aliases_get_by_file.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_typedecl_structs_get_by_file(const Eolian_Unit *unit, const char *fname);
+lib.eolian_typedecl_structs_get_by_file.argtypes = [c_void_p, c_char_p]
+lib.eolian_typedecl_structs_get_by_file.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_typedecl_enums_get_by_file(const Eolian_Unit *unit, const char *fname);
+lib.eolian_typedecl_enums_get_by_file.argtypes = [c_void_p, c_char_p]
+lib.eolian_typedecl_enums_get_by_file.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_typedecl_all_aliases_get(const Eolian_Unit *unit);
+lib.eolian_typedecl_all_aliases_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_all_aliases_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_typedecl_all_structs_get(const Eolian_Unit *unit);
+lib.eolian_typedecl_all_structs_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_all_structs_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_typedecl_all_enums_get(const Eolian_Unit *unit);
+lib.eolian_typedecl_all_enums_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_all_enums_get.restype = c_void_p
+
+# EAPI Eolian_Typedecl_Type eolian_typedecl_type_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_type_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_type_get.restype = c_int
+
+# EAPI Eina_Iterator *eolian_typedecl_struct_fields_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_struct_fields_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_struct_fields_get.restype = c_void_p
+
+# EAPI const Eolian_Struct_Type_Field *eolian_typedecl_struct_field_get(const Eolian_Typedecl *tp, const char *field);
+lib.eolian_typedecl_struct_field_get.argtypes = [c_void_p, c_char_p]
+lib.eolian_typedecl_struct_field_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_typedecl_struct_field_name_get(const Eolian_Struct_Type_Field *fl);
+lib.eolian_typedecl_struct_field_name_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_struct_field_name_get.restype = c_char_p
+
+# EAPI const Eolian_Documentation *eolian_typedecl_struct_field_documentation_get(const Eolian_Struct_Type_Field *fl);
+lib.eolian_typedecl_struct_field_documentation_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_struct_field_documentation_get.restype = c_void_p
+
+# EAPI const Eolian_Type *eolian_typedecl_struct_field_type_get(const Eolian_Struct_Type_Field *fl);
+lib.eolian_typedecl_struct_field_type_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_struct_field_type_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_typedecl_enum_fields_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_enum_fields_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_enum_fields_get.restype = c_void_p
+
+# EAPI const Eolian_Enum_Type_Field *eolian_typedecl_enum_field_get(const Eolian_Typedecl *tp, const char *field);
+lib.eolian_typedecl_enum_field_get.argtypes = [c_void_p, c_char_p]
+lib.eolian_typedecl_enum_field_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_typedecl_enum_field_name_get(const Eolian_Enum_Type_Field *fl);
+lib.eolian_typedecl_enum_field_name_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_enum_field_name_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_typedecl_enum_field_c_name_get(const Eolian_Enum_Type_Field *fl);
+lib.eolian_typedecl_enum_field_c_name_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_enum_field_c_name_get.restype = c_void_p  # Stringshare TO BE FREED
+
+# EAPI const Eolian_Documentation *eolian_typedecl_enum_field_documentation_get(const Eolian_Enum_Type_Field *fl);
+lib.eolian_typedecl_enum_field_documentation_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_enum_field_documentation_get.restype = c_void_p
+
+# EAPI const Eolian_Expression *eolian_typedecl_enum_field_value_get(const Eolian_Enum_Type_Field *fl, Eina_Bool force);
+lib.eolian_typedecl_enum_field_value_get.argtypes = [c_void_p, c_bool]
+lib.eolian_typedecl_enum_field_value_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_typedecl_enum_legacy_prefix_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_enum_legacy_prefix_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_enum_legacy_prefix_get.restype = c_char_p
+
+# EAPI const Eolian_Documentation *eolian_typedecl_documentation_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_documentation_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_documentation_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_typedecl_file_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_file_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_file_get.restype = c_char_p
+
+# EAPI const Eolian_Type *eolian_typedecl_base_type_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_base_type_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_base_type_get.restype = c_void_p
+
+# TODO FIXME STRANGE API (need Eolian_Unit*)
+# EAPI const Eolian_Type *eolian_typedecl_aliased_base_get(const Eolian_Unit *unit, const Eolian_Typedecl *tp);
+#  lib.eolian_typedecl_aliased_base_get.argtypes = [c_void_p, c_void_p,]
+#  lib.eolian_typedecl_aliased_base_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_typedecl_is_extern(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_is_extern.argtypes = [c_void_p,]
+lib.eolian_typedecl_is_extern.restype = c_bool
+
+# TODO FIXME STRANGE API (need Eolian_Unit*)
+# EAPI Eina_Stringshare *eolian_typedecl_c_type_get(const Eolian_Unit *unit, const Eolian_Typedecl *tp);
+#  lib.eolian_typedecl_c_type_get.argtypes = [c_void_p,]
+#  lib.eolian_typedecl_c_type_get.restype = None
+
+# EAPI Eina_Stringshare *eolian_typedecl_name_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_name_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_name_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_typedecl_full_name_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_full_name_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_full_name_get.restype = c_char_p
+
+# EAPI Eina_Iterator *eolian_typedecl_namespaces_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_namespaces_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_namespaces_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_typedecl_free_func_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_free_func_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_free_func_get.restype = c_char_p
+
+# EAPI const Eolian_Function *eolian_typedecl_function_pointer_get(const Eolian_Typedecl *tp);
+lib.eolian_typedecl_function_pointer_get.argtypes = [c_void_p,]
+lib.eolian_typedecl_function_pointer_get.restype = c_void_p
+
+# EAPI Eolian_Type_Type eolian_type_type_get(const Eolian_Type *tp);
+lib.eolian_type_type_get.argtypes = [c_void_p,]
+lib.eolian_type_type_get.restype = c_int
+
+# EAPI Eolian_Type_Builtin_Type eolian_type_builtin_type_get(const Eolian_Type *tp);
+lib.eolian_type_builtin_type_get.argtypes = [c_void_p,]
+lib.eolian_type_builtin_type_get.restype = c_int
+
+# EAPI Eina_Stringshare *eolian_type_file_get(const Eolian_Type *tp);
+lib.eolian_type_file_get.argtypes = [c_void_p,]
+lib.eolian_type_file_get.restype = c_char_p
+
+# EAPI const Eolian_Type *eolian_type_base_type_get(const Eolian_Type *tp);
+lib.eolian_type_base_type_get.argtypes = [c_void_p,]
+lib.eolian_type_base_type_get.restype = c_void_p
+
+# EAPI const Eolian_Type *eolian_type_next_type_get(const Eolian_Type *tp);
+lib.eolian_type_next_type_get.argtypes = [c_void_p,]
+lib.eolian_type_next_type_get.restype = c_void_p
+
+# TODO FIXME STRANGE API (need Eolian_Unit*)
+# EAPI const Eolian_Typedecl *eolian_type_typedecl_get(const Eolian_Unit *unit, const Eolian_Type *tp);
+#  lib.eolian_type_typedecl_get.argtypes = [c_void_p,]
+#  lib.eolian_type_typedecl_get.restype = c_void_p
+
+# TODO FIXME STRANGE API (need Eolian_Unit*)
+# EAPI const Eolian_Type *eolian_type_aliased_base_get(const Eolian_Unit *unit, const Eolian_Type *tp);
+#  lib.eolian_type_aliased_base_get.argtypes = [c_void_p,]
+#  lib.eolian_type_aliased_base_get.restype = c_void_p
+
+# TODO FIXME STRANGE API (need Eolian_Unit*)
+# EAPI const Eolian_Class *eolian_type_class_get(const Eolian_Unit *unit, const Eolian_Type *tp);
+#  lib.eolian_type_class_get.argtypes = [c_void_p,]
+#  lib.eolian_type_class_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_type_is_owned(const Eolian_Type *tp);
+lib.eolian_type_is_owned.argtypes = [c_void_p,]
+lib.eolian_type_is_owned.restype = c_bool
+
+# EAPI Eina_Bool eolian_type_is_const(const Eolian_Type *tp);
+lib.eolian_type_is_const.argtypes = [c_void_p,]
+lib.eolian_type_is_const.restype = c_bool
+
+# EAPI Eina_Bool eolian_type_is_ptr(const Eolian_Type *tp);
+lib.eolian_type_is_ptr.argtypes = [c_void_p,]
+lib.eolian_type_is_ptr.restype = c_bool
+
+# TODO FIXME STRANGE API (need Eolian_Unit*)
+# EAPI Eina_Stringshare *eolian_type_c_type_get(const Eolian_Unit *unit, const Eolian_Type *tp, Eolian_C_Type_Type ctype);
+#  lib.eolian_type_c_type_get.argtypes = [c_void_p,]
+#  lib.eolian_type_c_type_get.restype = c_void_p  # Stringshare TO BE FREED
+
+# EAPI Eina_Stringshare *eolian_type_name_get(const Eolian_Type *tp);
+lib.eolian_type_name_get.argtypes = [c_void_p,]
+lib.eolian_type_name_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_type_full_name_get(const Eolian_Type *tp);
+lib.eolian_type_full_name_get.argtypes = [c_void_p,]
+lib.eolian_type_full_name_get.restype = c_char_p
+
+# EAPI Eina_Iterator *eolian_type_namespaces_get(const Eolian_Type *tp);
+lib.eolian_type_namespaces_get.argtypes = [c_void_p,]
+lib.eolian_type_namespaces_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_type_free_func_get(const Eolian_Type *tp);
+lib.eolian_type_free_func_get.argtypes = [c_void_p,]
+lib.eolian_type_free_func_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_expression_serialize(const Eolian_Expression *expr);
+lib.eolian_expression_serialize.argtypes = [c_void_p,]
+lib.eolian_expression_serialize.restype = c_void_p  # Stringshare TO BE FREED
+
+# EAPI Eolian_Expression_Type eolian_expression_type_get(const Eolian_Expression *expr);
+lib.eolian_expression_type_get.argtypes = [c_void_p,]
+lib.eolian_expression_type_get.restype = c_int
+
+# EAPI Eolian_Binary_Operator eolian_expression_binary_operator_get(const Eolian_Expression *expr);
+lib.eolian_expression_binary_operator_get.argtypes = [c_void_p,]
+lib.eolian_expression_binary_operator_get.restype = c_int
+
+# EAPI const Eolian_Expression *eolian_expression_binary_lhs_get(const Eolian_Expression *expr);
+lib.eolian_expression_binary_lhs_get.argtypes = [c_void_p,]
+lib.eolian_expression_binary_lhs_get.restype = c_void_p
+
+# EAPI const Eolian_Expression *eolian_expression_binary_rhs_get(const Eolian_Expression *expr);
+lib.eolian_expression_binary_rhs_get.argtypes = [c_void_p,]
+lib.eolian_expression_binary_rhs_get.restype = c_void_p
+
+# EAPI Eolian_Unary_Operator eolian_expression_unary_operator_get(const Eolian_Expression *expr);
+lib.eolian_expression_unary_operator_get.argtypes = [c_void_p,]
+lib.eolian_expression_unary_operator_get.restype = c_int
+
+# EAPI const Eolian_Expression *eolian_expression_unary_expression_get(const Eolian_Expression *expr);
+lib.eolian_expression_unary_expression_get.argtypes = [c_void_p,]
+lib.eolian_expression_unary_expression_get.restype = c_void_p
+
+# EAPI const Eolian_Variable *eolian_variable_global_get_by_name(const Eolian_Unit *unit, const char *name);
+lib.eolian_variable_global_get_by_name.argtypes = [c_void_p, c_char_p]
+lib.eolian_variable_global_get_by_name.restype = c_void_p
+
+# EAPI const Eolian_Variable *eolian_variable_constant_get_by_name(const Eolian_Unit *unit, const char *name);
+lib.eolian_variable_constant_get_by_name.argtypes = [c_void_p, c_char_p]
+lib.eolian_variable_constant_get_by_name.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_variable_globals_get_by_file(const Eolian_Unit *unit, const char *fname);
+lib.eolian_variable_globals_get_by_file.argtypes = [c_void_p, c_char_p]
+lib.eolian_variable_globals_get_by_file.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_variable_constants_get_by_file(const Eolian_Unit *unit, const char *fname);
+lib.eolian_variable_constants_get_by_file.argtypes = [c_void_p, c_char_p]
+lib.eolian_variable_constants_get_by_file.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_variable_all_constants_get(const Eolian_Unit *unit);
+lib.eolian_variable_all_constants_get.argtypes = [c_void_p,]
+lib.eolian_variable_all_constants_get.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_variable_all_globals_get(const Eolian_Unit *unit);
+lib.eolian_variable_all_globals_get.argtypes = [c_void_p,]
+lib.eolian_variable_all_globals_get.restype = c_void_p
+
+# EAPI Eolian_Variable_Type eolian_variable_type_get(const Eolian_Variable *var);
+lib.eolian_variable_type_get.argtypes = [c_void_p,]
+lib.eolian_variable_type_get.restype = c_int
+
+# EAPI const Eolian_Documentation *eolian_variable_documentation_get(const Eolian_Variable *var);
+lib.eolian_variable_documentation_get.argtypes = [c_void_p,]
+lib.eolian_variable_documentation_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_variable_file_get(const Eolian_Variable *var);
+lib.eolian_variable_file_get.argtypes = [c_void_p,]
+lib.eolian_variable_file_get.restype = c_char_p
+
+# EAPI const Eolian_Type *eolian_variable_base_type_get(const Eolian_Variable *var);
+lib.eolian_variable_base_type_get.argtypes = [c_void_p,]
+lib.eolian_variable_base_type_get.restype = c_void_p
+
+# EAPI const Eolian_Expression *eolian_variable_value_get(const Eolian_Variable *var);
+lib.eolian_variable_value_get.argtypes = [c_void_p,]
+lib.eolian_variable_value_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_variable_name_get(const Eolian_Variable *var);
+lib.eolian_variable_name_get.argtypes = [c_void_p,]
+lib.eolian_variable_name_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_variable_full_name_get(const Eolian_Variable *var);
+lib.eolian_variable_full_name_get.argtypes = [c_void_p,]
+lib.eolian_variable_full_name_get.restype = c_char_p
+
+# EAPI Eina_Iterator *eolian_variable_namespaces_get(const Eolian_Variable *var);
+lib.eolian_variable_namespaces_get.argtypes = [c_void_p,]
+lib.eolian_variable_namespaces_get.restype = c_void_p
+
+# EAPI Eina_Bool eolian_variable_is_extern(const Eolian_Variable *var);
+lib.eolian_variable_is_extern.argtypes = [c_void_p,]
+lib.eolian_variable_is_extern.restype = c_bool
+
+# EAPI const Eolian_Declaration *eolian_declaration_get_by_name(const Eolian_Unit *unit, const char *name);
+lib.eolian_declaration_get_by_name.argtypes = [c_void_p, c_char_p]
+lib.eolian_declaration_get_by_name.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_declarations_get_by_file(const Eolian *state, const char *fname);
+lib.eolian_declarations_get_by_file.argtypes = [c_void_p, c_char_p]
+lib.eolian_declarations_get_by_file.restype = c_void_p
+
+# EAPI Eina_Iterator *eolian_all_declarations_get(const Eolian_Unit *unit);
+lib.eolian_all_declarations_get.argtypes = [c_void_p,]
+lib.eolian_all_declarations_get.restype = c_void_p
+
+# EAPI Eolian_Declaration_Type eolian_declaration_type_get(const Eolian_Declaration *decl);
+lib.eolian_declaration_type_get.argtypes = [c_void_p,]
+lib.eolian_declaration_type_get.restype = c_int
+
+# EAPI Eina_Stringshare *eolian_declaration_name_get(const Eolian_Declaration *decl);
+lib.eolian_declaration_name_get.argtypes = [c_void_p,]
+lib.eolian_declaration_name_get.restype = c_char_p
+
+# EAPI const Eolian_Class *eolian_declaration_class_get(const Eolian_Declaration *decl);
+lib.eolian_declaration_class_get.argtypes = [c_void_p,]
+lib.eolian_declaration_class_get.restype = c_void_p
+
+# EAPI const Eolian_Typedecl *eolian_declaration_data_type_get(const Eolian_Declaration *decl);
+lib.eolian_declaration_data_type_get.argtypes = [c_void_p,]
+lib.eolian_declaration_data_type_get.restype = c_void_p
+
+# EAPI const Eolian_Variable *eolian_declaration_variable_get(const Eolian_Declaration *decl);
+lib.eolian_declaration_variable_get.argtypes = [c_void_p,]
+lib.eolian_declaration_variable_get.restype = c_void_p
+
+# EAPI Eina_Stringshare *eolian_documentation_summary_get(const Eolian_Documentation *doc);
+lib.eolian_documentation_summary_get.argtypes = [c_void_p,]
+lib.eolian_documentation_summary_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_documentation_description_get(const Eolian_Documentation *doc);
+lib.eolian_documentation_description_get.argtypes = [c_void_p,]
+lib.eolian_documentation_description_get.restype = c_char_p
+
+# EAPI Eina_Stringshare *eolian_documentation_since_get(const Eolian_Documentation *doc);
+lib.eolian_documentation_since_get.argtypes = [c_void_p,]
+lib.eolian_documentation_since_get.restype = c_char_p
+
+# NOT IMPLEMENTED
+# EAPI Eina_List *eolian_documentation_string_split(const char *doc);
+#  lib.eolian_documentation_string_split.argtypes = [c_char_p,]
+#  lib.eolian_documentation_string_split.restype = c_void_p
+
+#  # EAPI const char *eolian_documentation_tokenize(const char *doc, Eolian_Doc_Token *ret);
+lib.eolian_documentation_tokenize.argtypes = [c_char_p, c_void_p]
+lib.eolian_documentation_tokenize.restype = c_char_p
+
+# EAPI void eolian_doc_token_init(Eolian_Doc_Token *tok);
+lib.eolian_doc_token_init.argtypes = [c_void_p,]
+lib.eolian_doc_token_init.restype = None
+
+# EAPI Eolian_Doc_Token_Type eolian_doc_token_type_get(const Eolian_Doc_Token *tok);
+lib.eolian_doc_token_type_get.argtypes = [c_void_p,]
+lib.eolian_doc_token_type_get.restype = c_int
+
+# EAPI char *eolian_doc_token_text_get(const Eolian_Doc_Token *tok);
+lib.eolian_doc_token_text_get.argtypes = [c_void_p,]
+lib.eolian_doc_token_text_get.restype = c_void_p  # char* TO BE FREED
+
+# EAPI Eolian_Doc_Ref_Type eolian_doc_token_ref_get(const Eolian_Unit *unit, const Eolian_Doc_Token *tok, const void **data, const void **data2);
+#  lib.eolian_doc_token_ref_get.argtypes = [c_void_p, c_void_p, ???, ???]
+#  lib.eolian_doc_token_ref_get.restype = c_int
+
diff --git a/src/scripts/pyolian/test_eolian.py b/src/scripts/pyolian/test_eolian.py
new file mode 100755 (executable)
index 0000000..fa9869d
--- /dev/null
@@ -0,0 +1,440 @@
+#!/usr/bin/env python3
+# encoding: utf-8
+"""
+Pyolian test suite.
+
+Just run this file to execute the full suite.
+
+A return value of 0 means all test passed successfully.
+
+"""
+import os
+import unittest
+
+import eolian
+
+
+# Use .eo files from the source tree (not the installed ones)
+script_path = os.path.dirname(os.path.realpath(__file__))
+root_path = os.path.abspath(os.path.join(script_path, '..', '..', '..'))
+SCAN_FOLDER = os.path.join(root_path, 'src', 'lib')
+
+# the main Eolian unit state
+state = None
+
+
+class TestEolianUnit(unittest.TestCase):
+    def test_file_listing(self):
+        l = list(state.all_eo_file_paths)
+        self.assertGreater(len(l), 400)
+        self.assertTrue(l[0].endswith('.eo'))
+
+        l = list(state.all_eo_files)
+        self.assertGreater(len(l), 400)
+        self.assertTrue(l[0].endswith('.eo'))
+
+        l = list(state.all_eot_file_paths)
+        self.assertGreater(len(l), 10)
+        self.assertTrue(l[0].endswith('.eot'))
+        
+        l = list(state.all_eot_files)
+        self.assertGreater(len(l), 10)
+        self.assertTrue(l[0].endswith('.eot'))
+
+    def test_enum_listing(self):
+        l = list(state.typedecl_enums_get_by_file('efl_ui_win.eo'))
+        self.assertGreater(len(l), 5)
+        self.assertIsInstance(l[0], eolian.Typedecl)
+        self.assertEqual(l[0].type, eolian.Eolian_Typedecl_Type.ENUM)
+
+        all_count = 0
+        for enum in state.typedecl_all_enums:
+            self.assertIsInstance(enum, eolian.Typedecl)
+            self.assertEqual(enum.type, eolian.Eolian_Typedecl_Type.ENUM)
+            all_count += 1
+        self.assertGreater(all_count, 50)
+
+    def test_struct_listing(self):
+        l = list(state.typedecl_structs_get_by_file('eina_types.eot'))
+        self.assertGreater(len(l), 10)
+        self.assertIsInstance(l[0], eolian.Typedecl)
+        self.assertIn(l[0].type, (
+                        eolian.Eolian_Typedecl_Type.STRUCT,
+                        eolian.Eolian_Typedecl_Type.STRUCT_OPAQUE))
+
+        all_count = 0
+        for struct in state.typedecl_all_structs:
+            self.assertIsInstance(struct, eolian.Typedecl)
+            self.assertIn(struct.type, (
+                            eolian.Eolian_Typedecl_Type.STRUCT,
+                            eolian.Eolian_Typedecl_Type.STRUCT_OPAQUE))
+            all_count += 1
+        self.assertGreater(all_count, 50)
+
+    def test_alias_listing(self):
+        l = list(state.typedecl_aliases_get_by_file('edje_types.eot'))
+        self.assertGreater(len(l), 5)
+        self.assertIsInstance(l[0], eolian.Typedecl)
+
+        all_count = 0
+        for alias in state.typedecl_all_aliases:
+            self.assertIsInstance(alias, eolian.Typedecl)
+            self.assertIn(alias.type, (
+                            eolian.Eolian_Typedecl_Type.ALIAS,
+                            eolian.Eolian_Typedecl_Type.FUNCTION_POINTER)) # TODO is this correct ??
+            all_count += 1
+        self.assertGreater(all_count, 10)
+
+    def test_variable_listing(self):
+        l = list(state.variable_all_constants)
+        self.assertGreater(len(l), 2)
+        self.assertIsInstance(l[0], eolian.Variable)
+
+        l = list(state.variable_all_globals)
+        self.assertGreater(len(l), 20)
+        self.assertIsInstance(l[0], eolian.Variable)
+
+        l = list(state.variable_constants_get_by_file('efl_gfx_stack.eo'))
+        self.assertGreater(len(l), 1)
+        self.assertIsInstance(l[0], eolian.Variable)
+
+        l = list(state.variable_globals_get_by_file('efl_net_http_types.eot'))
+        self.assertGreater(len(l), 10)
+        self.assertIsInstance(l[0], eolian.Variable)
+
+    def test_declaration_listing(self):
+        l = list(state.declarations_get_by_file('eina_types.eot'))
+        self.assertGreater(len(l), 10)
+        self.assertIsInstance(l[0], eolian.Declaration)
+
+        l = list(state.all_declarations)
+        self.assertGreater(len(l), 100)
+        self.assertIsInstance(l[0], eolian.Declaration)
+
+    def test_class_listing(self):
+        all_count = 0
+        for cls in state.all_classes:
+            self.assertIsInstance(cls, eolian.Class)
+            all_count += 1
+        self.assertGreater(all_count, 400)
+
+
+class TestEolianClass(unittest.TestCase):
+    def test_class(self):
+        cls = state.class_get_by_file('efl_loop_timer.eo')
+        self.assertIsInstance(cls, eolian.Class)
+
+        cls = state.class_get_by_name('Efl.Loop.Timer')
+        self.assertIsInstance(cls, eolian.Class)
+
+        self.assertEqual(cls.name, 'Timer')
+        self.assertEqual(cls.full_name, 'Efl.Loop.Timer')
+        self.assertEqual(cls.file, 'efl_loop_timer.eo')
+        self.assertEqual(list(cls.namespaces), ['Efl', 'Loop'])
+        self.assertEqual(cls.type, eolian.Eolian_Class_Type.REGULAR)
+        self.assertIsInstance(cls.documentation, eolian.Documentation)
+        self.assertEqual(cls.legacy_prefix, 'ecore_timer')
+        self.assertIsNone(cls.eo_prefix)  # TODO fin a class with a value
+        self.assertIsNone(cls.event_prefix)  # TODO same as above
+        self.assertIsNone(cls.data_type)  # TODO same as above
+        self.assertEqual(len(list(cls.inherits)), 1)
+        self.assertFalse(cls.ctor_enable)
+        self.assertFalse(cls.dtor_enable)
+        self.assertEqual(cls.c_get_function_name, 'efl_loop_timer_class_get')
+        self.assertEqual(cls.c_name, 'EFL_LOOP_TIMER_CLASS')
+        self.assertEqual(cls.c_data_type, 'Efl_Loop_Timer_Data')
+        self.assertEqual([f.name for f in cls.methods], ['reset','loop_reset','delay'])
+        self.assertEqual([f.name for f in cls.properties], ['interval','pending'])
+        self.assertGreater(len(list(cls.implements)), 5)
+        self.assertIsInstance(list(cls.implements)[0], eolian.Implement)
+
+
+class TestEolianFunction(unittest.TestCase):
+    def test_function(self):
+        cls = state.class_get_by_name('Efl.Loop.Timer')
+        f = cls.function_get_by_name('delay')
+        self.assertIsInstance(f, eolian.Function)
+        self.assertEqual(f.name, 'delay')
+        self.assertEqual(f.type, eolian.Eolian_Function_Type.METHOD)
+        self.assertEqual(f.method_scope, eolian.Eolian_Object_Scope.PUBLIC)
+        self.assertEqual(f.getter_scope, eolian.Eolian_Object_Scope.UNKNOWN)  # TODO correct?
+        self.assertEqual(f.setter_scope, eolian.Eolian_Object_Scope.UNKNOWN)  # TODO correct?
+        self.assertEqual(f.full_c_method_name, 'efl_loop_timer_delay')
+        self.assertEqual(f.full_c_getter_name, 'efl_loop_timer_delay_get')
+        self.assertEqual(f.full_c_setter_name, 'efl_loop_timer_delay_set')
+        self.assertEqual(f.full_c_method_name_legacy, 'ecore_timer_delay')
+        self.assertEqual(f.full_c_getter_name_legacy, 'ecore_timer_delay_get')
+        self.assertEqual(f.full_c_setter_name_legacy, 'ecore_timer_delay_set')
+        self.assertIsNone(f.method_return_type)  # TODO correct ?
+        self.assertIsNone(f.setter_return_type)  # TODO correct ?
+        self.assertIsNone(f.getter_return_type)  # TODO correct ?    
+        self.assertFalse(f.is_legacy_only(eolian.Eolian_Function_Type.PROP_GET))
+        self.assertFalse(f.is_class)
+        self.assertFalse(f.is_beta)
+        self.assertFalse(f.is_constructor(cls))
+        #  # #assert f.is_function_pointer == False  # TODO broken somehow
+        self.assertEqual(len(list(f.getter_values)), 1)
+        self.assertEqual(len(list(f.getter_values)), 1)
+        self.assertEqual(len(list(f.parameters)), 1)
+        self.assertFalse(f.return_is_warn_unused(eolian.Eolian_Function_Type.METHOD))
+        self.assertFalse(f.object_is_const)
+        self.assertEqual(f.class_.full_name, 'Efl.Loop.Timer')
+
+    def test_function_parameter(self):
+        cls = state.class_get_by_name('Efl.Loop.Timer')
+        f = cls.function_get_by_name('delay')
+        p = list(f.parameters)[0]
+        self.assertEqual(p.direction, eolian.Eolian_Parameter_Dir.IN)
+        self.assertEqual(p.name, 'add')
+        self.assertIsNone(p.default_value)
+        self.assertFalse(p.is_nonull)  # TODO is correct ?? 'add' can be null?
+        self.assertFalse(p.is_nullable)
+        self.assertFalse(p.is_optional)
+        self.assertEqual(p.type.name, 'double')
+        self.assertIsInstance(p.documentation, eolian.Documentation)
+
+
+class TestEolianImplement(unittest.TestCase):
+    def test_implement(self):
+        cls = state.class_get_by_name('Efl.Loop.Timer')
+        f = cls.function_get_by_name('delay')
+        im = f.implement
+        self.assertIsInstance(im, eolian.Implement)
+        self.assertEqual(im.full_name, 'Efl.Loop.Timer.delay')
+        self.assertIsInstance(im.class_, eolian.Class)
+        self.assertIsInstance(im.function_get(), eolian.Function) # TODO is UNRESOLVED correct ?
+        self.assertIsInstance(im.documentation_get(), eolian.Documentation) # TODO is UNRESOLVED correct ?
+        self.assertFalse(im.is_auto())
+        self.assertFalse(im.is_empty())
+        self.assertFalse(im.is_pure_virtual())
+        self.assertFalse(im.is_prop_set)
+        self.assertFalse(im.is_prop_get)
+
+
+class TestEolianEvent(unittest.TestCase):
+    def test_event(self):
+        cls = state.class_get_by_name('Efl.Loop.Timer')
+        self.assertEqual([e.name for e in cls.events], ['tick'])
+        ev = cls.event_get_by_name('tick')
+        self.assertIsInstance(ev, eolian.Event)
+        self.assertEqual(ev.name, 'tick')
+        self.assertEqual(ev.c_name, 'EFL_LOOP_TIMER_EVENT_TICK')
+        self.assertIsNone(ev.type)  # TODO is this correct
+        self.assertIsInstance(ev.documentation, eolian.Documentation)
+        self.assertEqual(ev.scope, eolian.Eolian_Object_Scope.PUBLIC)
+        self.assertFalse(ev.is_beta)
+        self.assertFalse(ev.is_hot)
+        self.assertFalse(ev.is_restart)
+
+
+class TestEolianPart(unittest.TestCase):
+    def test_part(self):
+        cls = state.class_get_by_name('Efl.Ui.Popup')
+        parts = list(cls.parts)
+        self.assertGreater(len(parts), 0)
+
+        part = parts[0]
+        self.assertEqual(part.name, 'backwall')
+        self.assertIsInstance(part.class_, eolian.Class)
+        self.assertEqual(part.class_.full_name, 'Efl.Ui.Popup.Part')
+        self.assertIsInstance(part.documentation, eolian.Documentation)
+
+
+class TestEolianConstructor(unittest.TestCase):
+    def test_constructor(self):
+        cls = state.class_get_by_name('Efl.Ui.Win')
+        ctors = list(cls.constructors)
+        self.assertGreater(len(ctors), 0)
+        ctor = ctors[0]
+        self.assertIsInstance(ctor, eolian.Constructor)
+        self.assertEqual(ctor.full_name, 'Efl.Ui.Win.win_name')
+        self.assertFalse(ctor.is_optional)
+        self.assertIsInstance(ctor.class_, eolian.Class)
+        self.assertEqual(ctor.class_.full_name, 'Efl.Ui.Win')
+        self.assertIsInstance(ctor.function, eolian.Function)
+        self.assertEqual(ctor.function.name, 'win_name')
+
+
+class TestEolianDocumentation(unittest.TestCase):
+    def test_documentation(self):
+        td = state.class_get_by_name('Efl.Net.Control')
+        doc = td.documentation
+        self.assertIsInstance(doc, eolian.Documentation)
+        self.assertIsInstance(doc.summary, str)
+        self.assertGreater(len(doc.summary), 10)
+        self.assertIsInstance(doc.description, str)
+        self.assertGreater(len(doc.description), 20)
+        self.assertEqual(doc.since, '1.19')
+
+
+class TestEolianVariable(unittest.TestCase):
+    def test_variable_global(self):
+        var = state.variable_global_get_by_name('Efl.Net.Http.Error.BAD_CONTENT_ENCODING')
+        self.assertIsInstance(var, eolian.Variable)
+        self.assertEqual(var.full_name, 'Efl.Net.Http.Error.BAD_CONTENT_ENCODING')
+        self.assertEqual(var.name, 'BAD_CONTENT_ENCODING')
+        self.assertEqual(var.type, eolian.Eolian_Variable_Type.GLOBAL)
+        self.assertEqual(var.file, 'efl_net_http_types.eot')
+        self.assertFalse(var.is_extern)
+        self.assertEqual(list(var.namespaces), ['Efl','Net','Http','Error'])
+        self.assertIsInstance(var.documentation, eolian.Documentation)
+        self.assertIsInstance(var.base_type, eolian.Type)
+        self.assertIsNone(var.value)  # TODO is None correct here? no value?
+
+    def test_variable_constant(self):
+        var = state.variable_constant_get_by_name('Efl.Gfx.Size.Hint.Fill')
+        self.assertIsInstance(var, eolian.Variable)
+        self.assertEqual(var.full_name, 'Efl.Gfx.Size.Hint.Fill')
+        self.assertEqual(var.name, 'Fill')
+        self.assertEqual(var.type, eolian.Eolian_Variable_Type.CONSTANT)
+        self.assertEqual(var.file, 'efl_gfx_size_hint.eo')
+        self.assertFalse(var.is_extern)
+        self.assertEqual(list(var.namespaces), ['Efl','Gfx','Size','Hint'])
+        self.assertIsInstance(var.documentation, eolian.Documentation)
+        self.assertIsInstance(var.base_type, eolian.Type)
+        self.assertIsInstance(var.value, eolian.Expression)
+        self.assertEqual(float(var.value.serialize), +1.0)
+
+
+class TestEolianTypedecl(unittest.TestCase):
+    def test_typedecl_enum(self):
+        td = state.typedecl_enum_get_by_name('Efl.Net.Http.Version')
+        self.assertIsInstance(td, eolian.Typedecl)
+        self.assertEqual(td.name, 'Version')
+        self.assertEqual(td.full_name, 'Efl.Net.Http.Version')
+        self.assertEqual(td.file, 'efl_net_http_types.eot')
+        self.assertEqual(list(td.namespaces), ['Efl','Net','Http'])
+        self.assertIsInstance(td.documentation, eolian.Documentation)
+        self.assertIsNone(td.base_type)  # TODO find a better test
+        self.assertIsNone(td.free_func)  # TODO find a better test
+        self.assertIsNone(td.function_pointer)  # TODO find a better test
+        self.assertFalse(td.is_extern)
+        self.assertEqual(len(list(td.enum_fields)), 3)
+
+    def test_typedecl_enum_field(self):
+        td = state.typedecl_enum_get_by_name('Efl.Net.Http.Version')
+        field = td.enum_field_get('v1_0')
+        self.assertIsInstance(field, eolian.Enum_Type_Field)
+        self.assertEqual(field.name, 'v1_0')
+        self.assertEqual(field.c_name, 'EFL_NET_HTTP_VERSION_V1_0')
+        self.assertIsInstance(field.documentation, eolian.Documentation)
+        self.assertIsInstance(field.value, eolian.Expression)
+
+    def test_typedecl_struct(self):
+        td = state.typedecl_struct_get_by_name('Efl.Gfx.Color32')
+        self.assertIsInstance(td, eolian.Typedecl)
+        self.assertEqual(td.name, 'Color32')
+        self.assertEqual(td.full_name, 'Efl.Gfx.Color32')
+        self.assertEqual(td.file, 'efl_canvas_filter_internal.eo')
+        self.assertEqual(list(td.namespaces), ['Efl','Gfx'])
+        self.assertIsInstance(td.documentation, eolian.Documentation)
+        self.assertIsNone(td.base_type)  # TODO find a better test
+        self.assertIsNone(td.free_func)  # TODO find a better test
+        self.assertIsNone(td.function_pointer)  # TODO find a better test
+        self.assertFalse(td.is_extern)
+        self.assertEqual(len(list(td.struct_fields)), 4)
+
+    def test_typedecl_struct_field(self):
+        td = state.typedecl_struct_get_by_name('Efl.Gfx.Color32')
+        field = td.struct_field_get('b')
+        self.assertIsInstance(field, eolian.Struct_Type_Field)
+        self.assertEqual(field.name, 'b')
+        self.assertIsInstance(field.type, eolian.Type)
+        self.assertIsInstance(field.documentation, eolian.Documentation)
+
+    def test_typedecl_alias(self):
+        alias = state.typedecl_alias_get_by_name('Eina.Error')
+        self.assertIsInstance(alias, eolian.Typedecl)
+        self.assertEqual(alias.name, 'Error')
+
+
+class TestEolianType(unittest.TestCase):
+    def test_type_regular(self):
+        cls = state.class_get_by_name('Efl.Loop.Timer')
+        func = cls.function_get_by_name('delay')
+        param = list(func.parameters)[0]
+        t = param.type
+        self.assertIsInstance(t, eolian.Type)
+        self.assertEqual(t.name, 'double')
+        self.assertEqual(t.full_name, 'double')
+        self.assertEqual(t.type, eolian.Eolian_Type_Type.REGULAR)
+        self.assertEqual(t.builtin_type, eolian.Eolian_Type_Builtin_Type.DOUBLE)
+        self.assertEqual(t.file, 'efl_loop_timer.eo')
+        self.assertIsNone(t.base_type)  # TODO find a better test
+        self.assertIsNone(t.next_type)  # TODO find a better test
+        self.assertFalse(t.is_owned)
+        self.assertFalse(t.is_const)
+        self.assertFalse(t.is_ptr)
+        #  self.assertEqual(list(t.namespaces), [])   # TODO find a better test
+        self.assertIsNone(t.free_func)  # TODO find a better test
+
+
+class TestEolianDeclaration(unittest.TestCase):
+    def test_declaration(self):
+        d = state.declaration_get_by_name('Eina.File')
+        self.assertIsInstance(d, eolian.Declaration)
+        self.assertEqual(d.name, 'Eina.File')
+        self.assertEqual(d.type, eolian.Eolian_Declaration_Type.STRUCT)
+        #  self.assertIsNone(d.class_)  # TODO find a better test
+        #  self.assertIsNone(d.variable)  # TODO find a better test
+        self.assertIsInstance(d.data_type, eolian.Typedecl)
+        self.assertEqual(d.data_type.full_name, 'Eina.File')
+
+
+class TestEolianExpression(unittest.TestCase):
+    def test_expression_simple(self):
+        td = state.typedecl_enum_get_by_name('Efl.Net.Http.Version')
+        field = td.enum_field_get('v1_0')
+        exp = field.value
+        self.assertIsInstance(exp, eolian.Expression)
+        self.assertEqual(exp.type, eolian.Eolian_Expression_Type.INT)
+        self.assertEqual(exp.serialize, '100')
+
+    def test_expression_unary(self):
+        var = state.variable_constant_get_by_name('Efl.Gfx.Size.Hint.Fill')
+        exp = var.value
+        self.assertIsInstance(exp, eolian.Expression)
+        self.assertEqual(exp.type, eolian.Eolian_Expression_Type.UNARY)
+        self.assertEqual(float(exp.serialize), 1.0)  # TODO is this a bug? isn't -1.0 ?
+        self.assertEqual(exp.unary_operator, eolian.Eolian_Unary_Operator.UNM)
+        unary = exp.unary_expression
+        self.assertIsInstance(unary, eolian.Expression)
+        self.assertEqual(unary.type, eolian.Eolian_Expression_Type.DOUBLE)
+        self.assertEqual(float(exp.serialize), 1.0)
+        
+        # TODO test_expression_binary
+        #  exp.binary_operator # TODO find a better test (only works for BINARY expr)
+        #  exp.binary_lhs # TODO find a better test (only works for BINARY expr)
+        #  exp.binary_rhs # TODO find a better test (only works for BINARY expr)
+
+
+
+if __name__ == '__main__':
+    # create main eolian state
+    state = eolian.Eolian()
+    if not isinstance(state, eolian.Eolian):
+        raise(RuntimeError('Eolian, failed to create Eolian state'))
+
+    # eolian system scan (BROKEN)
+    #  if not state.system_directory_scan():
+        #  raise(RuntimeError('Eolian, failed to scan system directories'))
+
+    # eolian source tree scan
+    if not state.directory_scan(SCAN_FOLDER):
+        raise(RuntimeError('Eolian, failed to scan source directory'))
+
+    # Parse all known eo files
+    if not state.all_eot_files_parse():
+        raise(RuntimeError('Eolian, failed to parse all EOT files'))
+        
+    if not state.all_eo_files_parse():
+        raise(RuntimeError('Eolian, failed to parse all EO files'))
+
+    # start the test suite
+    suite = unittest.main(verbosity=2, exit=False)
+
+    # cleanup (or it will segfault on gc, that happend after atexit)
+    del state
+
+    # exit 0 (success) or 1 (failure)
+    exit(0 if suite.result.wasSuccessful() else 1)