from libc.stdint cimport uintptr_t from cpython cimport PyUnicode_AsUTF8String from efl.eina cimport eina_inlist_count, EINA_LOG_DOM_DBG, \ EINA_LOG_DOM_INFO, EINA_LOG_DOM_WARN, EINA_LOG_DOM_ERR, EINA_LOG_DOM_CRIT from efl.utils.conversions cimport _ctouni, eina_list_strings_to_python_list from efl.utils.logger cimport add_logger cdef int EOLIAN_DOM = add_logger("efl.eolian").eina_log_domain from efl.utils.enum import IntEnum class FunctionType(IntEnum): """Function Type""" UNRESOLVED = EOLIAN_UNRESOLVED PROPERTY = EOLIAN_PROPERTY PROP_SET = EOLIAN_PROP_SET PROP_GET = EOLIAN_PROP_GET METHOD = EOLIAN_METHOD CTOR = EOLIAN_CTOR class ParameterDir(IntEnum): """Parameter Direction""" IN = EOLIAN_IN_PARAM OUT = EOLIAN_OUT_PARAM INOUT = EOLIAN_INOUT_PARAM class ClassType(IntEnum): """Class Type""" UNKNOWN = EOLIAN_CLASS_UNKNOWN_TYPE REGULAR = EOLIAN_CLASS_REGULAR ABSTRACT = EOLIAN_CLASS_ABSTRACT MIXIN = EOLIAN_CLASS_MIXIN INTERFACE = EOLIAN_CLASS_INTERFACE class FunctionScope(IntEnum): """Function Scope""" PUBLIC = EOLIAN_SCOPE_PUBLIC PROTECTED = EOLIAN_SCOPE_PROTECTED cdef list eina_list_obj_to_python_list(const Eina_List *lst, type cls): cdef: list ret = list() while lst: if lst.data == NULL: EINA_LOG_DOM_DBG( EOLIAN_DOM, "Eina lists data pointer is NULL", NULL ) lst = lst.next if cls is Class: o = eolian_class_to_python_obj(lst.data) elif cls is Function: o = eolian_func_to_python_obj(lst.data) elif cls is FunctionParameter: o = eolian_func_param_to_python_obj(lst.data) elif cls is Type: o = eolian_type_to_python_obj(lst.data) elif cls is Implement: o = eolian_implement_to_python_obj(lst.data) elif cls is Event: o = eolian_event_to_python_obj(lst.data) else: EINA_LOG_DOM_WARN( EOLIAN_DOM, "Unknown type for conversion", NULL ) return ret.append(o) lst = lst.next return ret cdef Class eolian_class_to_python_obj(Eolian_Class o): if o == NULL: EINA_LOG_DOM_DBG( EOLIAN_DOM, "Eolian_Class is NULL", NULL ) return None cdef Class ret = Class.__new__(Class) ret._set_obj(o) return ret cdef Function eolian_func_to_python_obj(Eolian_Function o): if o == NULL: EINA_LOG_DOM_DBG( EOLIAN_DOM, "Eolian_Function is NULL", NULL ) return None cdef Function ret = Function.__new__(Function) ret._set_obj(o) return ret cdef FunctionParameter eolian_func_param_to_python_obj( Eolian_Function_Parameter o): if o == NULL: EINA_LOG_DOM_DBG( EOLIAN_DOM, "Eolian_Function_Parameter is NULL", NULL ) return None cdef FunctionParameter ret = FunctionParameter.__new__(FunctionParameter) ret._set_obj(o) return ret cdef Type eolian_type_to_python_obj(Eolian_Type o): if o == NULL: EINA_LOG_DOM_DBG( EOLIAN_DOM, "Eolian_Type is NULL", NULL ) return None cdef Type ret = Type.__new__(Type) ret._set_obj(o) return ret cdef Implement eolian_implement_to_python_obj(Eolian_Implement o): if o == NULL: EINA_LOG_DOM_DBG( EOLIAN_DOM, "Eolian_Implement is NULL", NULL ) return None cdef Implement ret = Implement.__new__(Implement) ret._set_obj(o) return ret cdef Event eolian_event_to_python_obj(Eolian_Event o): if o == NULL: EINA_LOG_DOM_DBG( EOLIAN_DOM, "Eolian_Event is NULL", NULL ) return None cdef Event ret = Event.__new__(Event) ret._set_obj(o) return ret def eo_file_parse(filename): """Parse a given .eo file and fill the database. During parsing, the class described into the .eo file is created with all the information related to this class. :param filename: Name of the file to parse. """ if isinstance(filename, unicode): filename = PyUnicode_AsUTF8String(filename) cdef bint ret = eolian_eo_file_parse(filename) if not ret: EINA_LOG_DOM_WARN(EOLIAN_DOM, "Failure in directory_scan()", NULL) return ret def init(): """Init Eolian. :rtype: int """ EINA_LOG_DOM_INFO(EOLIAN_DOM, "Initializing efl.eolian", NULL) return eolian_init() def shutdown(): """Shutdown Eolian. :rtype: int """ EINA_LOG_DOM_INFO(EOLIAN_DOM, "Shutting down efl.eolian", NULL) return eolian_shutdown() def directory_scan(directory): """Scan the given directory and search for .eo files. The found files are just open to extract the class name. :param dir: the directory to scan :return: True on success, False otherwise. """ if isinstance(directory, unicode): directory = PyUnicode_AsUTF8String(directory) cdef bint ret = eolian_directory_scan(directory) if not ret: EINA_LOG_DOM_WARN(EOLIAN_DOM, "Failure in directory_scan()", NULL) return ret def all_eo_files_parse(): """Force parsing of all the files located in the directories given in eolian_directory_scan.. :return: True on success, False otherwise. :see: :py:func:`directory_scan` """ cdef bint ret = eolian_all_eo_files_parse() if not ret: EINA_LOG_DOM_WARN(EOLIAN_DOM, "Failure in all_eo_files_parse()", NULL) return ret def show(Class klass=None): """Show information about a given class. If klass is None, this function will print information of all the classes stored into the database. :param klass: the class to show """ cdef bint ret = eolian_show( klass.klass if klass is not None else NULL ) if not ret: EINA_LOG_DOM_WARN(EOLIAN_DOM, "Failure in show()", NULL) return ret def class_find_by_name(class_name): """Finds a class by its name :param class_name: name of the class to find. :return: the class """ if isinstance(class_name, unicode): class_name = PyUnicode_AsUTF8String(class_name) cdef Eolian_Class klass = eolian_class_find_by_name(class_name) if klass is NULL: return None else: return eolian_class_to_python_obj(klass) def class_find_by_file(file_name): """Finds a class by its location (.eo file) :param file_name: filename where the class is stored. :return: the class stored in the file """ if isinstance(file_name, unicode): file_name = PyUnicode_AsUTF8String(file_name) return eolian_class_to_python_obj( eolian_class_find_by_file(file_name) ) cdef class Class(object): cdef Eolian_Class klass cdef _set_obj(self, Eolian_Class obj): self.klass = obj def __init__(self): pass def __repr__(self): return ( "<%s (full_name=%s, filename=%s, type=%s, inherits=%r, " "description=%s)>" % ( self.name, self.full_name, self.filename, self.type, self.inherits_list, self.description.replace('\n', ' ') if self.description else \ None )) property filename: """Returns the name of the file containing the given class. :type: string """ def __get__(self): return _ctouni(eolian_class_file_get(self.klass)) property full_name: """Returns the full name of the given class. :type: string The full name and the name of a class will be different if namespaces are used. """ def __get__(self): return _ctouni(eolian_class_full_name_get(self.klass)) property name: """Returns the name of the given class. :type: string """ def __get__(self): return _ctouni(eolian_class_name_get(self.klass)) property namespaces_list: """Returns the namespaces list of the given class. :type: list of strings """ def __get__(self): return eina_list_strings_to_python_list( eolian_class_namespaces_list_get(self.klass) ) property type: """Returns the class type of the given class :type: :class:`ClassType` """ def __get__(self): return ClassType(eolian_class_type_get(self.klass)) property description: """Returns the description of a class. :type: string """ def __get__(self): return _ctouni(eolian_class_description_get(self.klass)) property legacy_prefix: """Returns the legacy prefix of a class :type: string """ def __get__(self): return _ctouni(eolian_class_legacy_prefix_get(self.klass)) property eo_prefix: """Returns the eo prefix of a class :type: string """ def __get__(self): return _ctouni(eolian_class_eo_prefix_get(self.klass)) property data_type: """Returns the data type of a class :type: string """ def __get__(self): return _ctouni(eolian_class_data_type_get(self.klass)) property inherits_list: """Returns the names list of the inherit classes of a class :type: list of strings """ def __get__(self): return eina_list_strings_to_python_list( eolian_class_inherits_list_get(self.klass) ) def functions_list_get(self, Eolian_Function_Type func_type): """Returns a list of functions of a class. :param func_type: type of the functions to insert into the list. :return: the list of Eolian_Function """ return eina_list_obj_to_python_list( eolian_class_functions_list_get( self.klass, func_type ), Function ) property implements: """Get the list of overriding functions defined in a class. :type: list of :py:class:`Implement` """ def __get__(self): return eina_list_obj_to_python_list( eolian_class_implements_list_get(self.klass), Implement ) property events: """Get the list of events defined in a class. :type: list of :py:class:`Event` """ def __get__(self): return eina_list_obj_to_python_list( eolian_class_events_list_get(self.klass), Event ) property constructor_enabled: """Indicates if the class constructor has to invoke a non-generated class constructor function. :type: bool """ def __get__(self): return bool(eolian_class_ctor_enable_get(self.klass)) property destructor_enabled: """Indicates if the class destructor has to invoke a non-generated class destructor function. :type: bool """ def __get__(self): return bool(eolian_class_dtor_enable_get(self.klass)) def function_find_by_name(self, func_name, Eolian_Function_Type f_type): """Find a function in a class by its name and type :param func_name: name of the function :param f_type: type of the function :return: the function id if found, None otherwise. """ if isinstance(func_name, unicode): func_name = PyUnicode_AsUTF8String(func_name) return eolian_func_to_python_obj( eolian_class_function_find_by_name( self.klass, func_name, f_type ) ) def class_names_list_get(): """Returns the names list of all the classes stored into the database. :return: the list Returns the list of class names of the database """ return eina_list_strings_to_python_list(eolian_class_names_list_get()) cdef class Function(object): cdef Eolian_Function function_id cdef _set_obj(self, Eolian_Function obj): self.function_id = obj def __init__(self): pass def __repr__(self): return ( "<%s (type=%s, scope=%s, is_const=%r)>" % ( self.name, self.type, self.scope, self.object_is_const, )) property type: """Returns the type of a function :type: :class:`FunctionType` """ def __get__(self): return FunctionType(eolian_function_type_get(self.function_id)) property scope: """Returns the scope of a function :type: :class:`FunctionScope` """ def __get__(self): return FunctionScope(eolian_function_scope_get(self.function_id)) property name: """Returns the name of a function :type: string """ def __get__(self): return _ctouni(eolian_function_name_get(self.function_id)) def data_get(self, key): """Returns a specific data for a function. :param key: key to access the data :return: the data. """ if isinstance(key, unicode): key = PyUnicode_AsUTF8String(key) return _ctouni(eolian_function_data_get(self.function_id, key)) def is_virtual_pure_get(self, Eolian_Function_Type f_type): """Indicates if a function is virtual pure. :return: True if virtual pure, False otherwise.. """ return bool(eolian_function_is_virtual_pure(self.function_id, f_type)) def description_get(self, key): """Returns a specific description for a function. :param key: key to access the description :return: the description. """ if isinstance(key, unicode): key = PyUnicode_AsUTF8String(key) return _ctouni(eolian_function_data_get(self.function_id, key)) def parameter_get(self, param_name): """Returns a parameter of a function pointed by its id. :param param_name: Name of the parameter :return: a handle to this parameter. """ if isinstance(param_name, unicode): param_name = PyUnicode_AsUTF8String(param_name) return eolian_func_param_to_python_obj( eolian_function_parameter_get( self.function_id, param_name ) ) property property_keys_list: """Returns a list of keys params of a given function. :type: list of :py:class:`FunctionParameter` """ def __get__(self): return eina_list_obj_to_python_list( eolian_property_keys_list_get(self.function_id), FunctionParameter ) property property_values_list: """Returns a list of values params of a given function. :type: list of :py:class:`FunctionParameter` """ def __get__(self): return eina_list_obj_to_python_list( eolian_property_values_list_get(self.function_id), FunctionParameter ) property parameters_list: """Returns a list of parameter handles for a method/ctor/dtor. :type: list of :py:class:`FunctionParameter` """ def __get__(self): return eina_list_obj_to_python_list( eolian_parameters_list_get(self.function_id), FunctionParameter ) def return_type_get(self, Eolian_Function_Type ftype): """Get the return type of a function. :param ftype: type of the function :return: the return type of the function The type of the function is needed because a given function can represent a property, that can be set and get functions. """ return _ctouni(eolian_function_return_type_get( self.function_id, ftype )) def return_types_list_get(self, Eolian_Function_Type ftype): """Get a list of all the types of a function return :param ftype: Function Type :return: the types of the function return """ return eolian_type_to_python_obj( eolian_function_return_types_list_get( self.function_id, ftype ) ) def return_dflt_value_get(self, Eolian_Function_Type ftype): """Get the return default value of a function. :param ftype: type of the function :return: the return default value of the function The return default value is needed to return an appropriate value if an error occurs (eo_do failure...). The default value is not mandatory, so None can be returned. """ return _ctouni(eolian_function_return_dflt_value_get( self.function_id, ftype )) def return_comment_get(self, Eolian_Function_Type ftype): """Get the return comment of a function. :param ftype: type of the function :return: the return comment of the function The type of the function is needed because a given function can represent a property, that can be set and get functions. """ return _ctouni(eolian_function_return_comment_get( self.function_id, ftype )) def return_is_warn_unused_get(self, Eolian_Function_Type ftype): """Indicates if a function return is warn-unused. :param ftype: type of the function :return: True is warn-unused, False otherwise. The type of the function is needed because a given function can represent a property, that can be set and get functions. """ return bool(eolian_function_return_is_warn_unused( self.function_id, ftype )) property object_is_const: """Indicates if a function object is const. :return: True if the object is const, False otherwise """ def __get__(self): return bool(eolian_function_object_is_const(self.function_id)) cdef class FunctionParameter(object): cdef Eolian_Function_Parameter param cdef _set_obj(self, Eolian_Function_Parameter obj): self.param = obj def __init__(self): pass def __repr__(self): info = self.information return ( "<%s (type=%s, direction=%s, is_nonull=%r, description=%s)>" % ( info[2], info[1], info[0], self.is_nonull, info[3].replace('\n', ' ') if info[3] else None )) property information: """Get information about a function parameter :type: :class:`ParameterDir` direction, string type, string name, string description """ def __get__(self): cdef: Eolian_Parameter_Dir param_dir const char *type const char *name const char *description eolian_parameter_information_get( self.param, ¶m_dir, &type, &name, &description ) return ( ParameterDir(param_dir), _ctouni(type), _ctouni(name), _ctouni(description) ) property type: """Get type of a parameter :type: string """ def __get__(self): return _ctouni(eolian_parameter_type_get(self.param)) property types_list: """Get a list of all the types of a parameter :type: :py:class:`Type` """ def __get__(self): return eolian_type_to_python_obj( eolian_parameter_types_list_get(self.param) ) property name: """Get name of a parameter :type: string """ def __get__(self): return _ctouni(eolian_parameter_name_get(self.param)) def const_attribute_get(self, bint is_get): """Indicates if a parameter has a const attribute. This function is relevant for properties, to know if a parameter is a const parameter in the get operation. :param bool is_get: indicates if the information needed is for get or set. :return: True if const in get, False otherwise """ return bool(eolian_parameter_const_attribute_get(self.param, is_get)) property is_nonull: """Indicates if a parameter cannot be NULL. :type: bool """ def __get__(self): return bool(eolian_parameter_is_nonull(self.param)) cdef class Type(object): """A type iterator An Eolian type is an inlist of basic C types. For example: ``Eina_List * `` contains two basic types. The first Eolian type of the list stores ``Eina_List *``, the next one ``Eo *``. :return: C type, ownership (indicates if the ownership has to pass to the caller/callee.) :rtype: (string, bool) """ cdef Eolian_Type etype cdef _set_obj(self, Eolian_Type obj): self.etype = obj def __iter__(self): return self def __next__(self): cdef: const char *type Eina_Bool own Eolian_Type etype if self.etype == NULL: raise StopIteration etype = eolian_type_information_get( self.etype, &type, &own ) self.etype = etype return _ctouni(type), bool(own) def __len__(self): return eina_inlist_count(self.etype) cdef class Implement(object): cdef Eolian_Implement impl cdef _set_obj(self, Eolian_Implement obj): self.impl = obj def __init__(self): pass def __repr__(self): info = self.information if not info: info = (None, None, None) return ( "<%s (class=%r, function=%r, type=%r)>" % ( self.full_name, info[0], info[1], info[2], )) property full_name: """Get full string of an overriding function (implement). :type: string """ def __get__(self): return _ctouni(eolian_implement_full_name_get(self.impl)) property information: """Get information about an overriding function (implement). :type: overridden :py:class:`Class`, overridden :py:class:`Function`, overridden :class:`FunctionType` """ def __get__(self): cdef: Eolian_Class klass Eolian_Function function Eolian_Function_Type type if not eolian_implement_information_get(self.impl, &klass, &function, &type ): EINA_LOG_DOM_WARN( EOLIAN_DOM, "Fetching info for %s failed", eolian_implement_full_name_get(self.impl) ) return None return ( eolian_class_to_python_obj(klass), eolian_func_to_python_obj(function), FunctionType(type) ) cdef class Event(object): cdef Eolian_Event event cdef _set_obj(self, Eolian_Event obj): self.event = obj def __init__(self): pass def __repr__(self): info = self.information if info: return ( "<%s (type=%s, description=%s)>" % ( info[0], info[1], info[2] )) else: return "" property information: """Get information about an event. :type: name of the event (string), type of the event (string), description of the event (string) """ def __get__(self): cdef: const char *event_name const char *event_type const char *event_desc if not eolian_class_event_information_get( self.event, &event_name, &event_type, &event_desc ): EINA_LOG_DOM_WARN( EOLIAN_DOM, "Fetching info for an event failed", NULL ) return None return ( _ctouni(event_name), _ctouni(event_type), _ctouni(event_desc) ) def type_find_by_alias(alias): """Find the type for a certain alias :param alias: alias of the type definition :return: real type of the type definition """ if isinstance(alias, unicode): alias = PyUnicode_AsUTF8String(alias) return eolian_type_to_python_obj( eolian_type_find_by_alias(alias) )