kuuko pushed a commit to branch master. http://git.enlightenment.org/bindings/python/python-efl.git/commit/?id=a0ecc4157274d473f056b89207f5dc54a8184e10
commit a0ecc4157274d473f056b89207f5dc54a8184e10 Author: Kai Huuhko <kai.huu...@gmail.com> Date: Thu Jun 5 18:15:38 2014 +0300 Elementary.entry: Fix ref leak in filter callback handling. --- TODO | 1 - efl/elementary/entry.pyx | 65 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/TODO b/TODO index edbf3f9..6dd0f1d 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,6 @@ BUGS * Elm.Map: overlays_show segfaults, scrollers in examples are jumpy * Elementary: when we use custom function callbacks we usually leak some reference around, some examples: - - Entry.markup_filter_append() - Fileselector.custom_filter_append() - Multibuttonentry.format_function_set() - Multibuttonentry.filter_append() diff --git a/efl/elementary/entry.pyx b/efl/elementary/entry.pyx index ce6313f..bacaaca 100644 --- a/efl/elementary/entry.pyx +++ b/efl/elementary/entry.pyx @@ -719,18 +719,21 @@ cdef void py_elm_entry_filter_cb(void *data, Evas_Object *entry, char **text) wi """ cdef: Entry en = object_from_instance(entry) + object ret - cb_func, cb_data = <object>data - try: - ret = cb_func(en, _touni(text[0]), cb_data) - except Exception: - traceback.print_exc() + for cb_func, cb_data in en.markup_filters: + try: + ret = cb_func(en, _touni(text[0]), cb_data) + except Exception: + traceback.print_exc() if ret is None: free(text[0]) text[0] = NULL return + if isinstance(ret, unicode): ret = PyUnicode_AsUTF8String(ret) + text[0] = strdup(<char *>ret) class EntryAnchorInfo(object): @@ -810,6 +813,11 @@ cdef class Entry(LayoutClass): """ + cdef list markup_filters + + def __cinit__(self): + self.markup_filters = [] + def __init__(self, evasObject parent, *args, **kwargs): """By default, entries are: @@ -1403,13 +1411,16 @@ cdef class Entry(LayoutClass): .. versionadded:: 1.8 """ + if not callable(func): + raise TypeError("func must be callable") + + if not self.markup_filters: + elm_entry_markup_filter_append(self.obj, + py_elm_entry_filter_cb, + NULL) + cb_data = (func, data) - # TODO: This is now a ref leak. It should be stored somewhere and - # deleted in the remove method. - Py_INCREF(cb_data) - elm_entry_markup_filter_append(self.obj, - py_elm_entry_filter_cb, - <void *>cb_data) + self.markup_filters.append(cb_data) def markup_filter_prepend(self, func, data=None): """Prepend a markup filter function for text inserted in the entry @@ -1423,11 +1434,16 @@ cdef class Entry(LayoutClass): .. versionadded:: 1.8 """ + if not callable(func): + raise TypeError("func must be callable") + + if not self.markup_filters: + elm_entry_markup_filter_append(self.obj, + py_elm_entry_filter_cb, + NULL) + cb_data = (func, data) - Py_INCREF(cb_data) - elm_entry_markup_filter_prepend(self.obj, - py_elm_entry_filter_cb, - <void *>cb_data) + self.markup_filters.insert(0, cb_data) def markup_filter_remove(self, func, data=None): """Remove a markup filter from the list @@ -1441,11 +1457,24 @@ cdef class Entry(LayoutClass): .. versionadded:: 1.8 """ - cb_data = (func, data) - Py_INCREF(cb_data) + f = None + d = None + lst = self.markup_filters + + for i, (f, d) in enumerate(lst): + if func is f and data is d: + break + + if f is not func or d is not data: + raise ValueError("Callback was not registered with this object.") + + lst.pop(i) + if lst: + return + elm_entry_markup_filter_remove(self.obj, py_elm_entry_filter_cb, - <void *>cb_data) + NULL) @DEPRECATED("1.8", "Use the module level markup_to_utf8() method instead.") def markup_to_utf8(self, string): --