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):

-- 


Reply via email to