[pygobject/gio-liststore-sort: 9/9] Add overrides for Gio.ListStore.sort and Gio.ListStore.insert_sorted. Fixes #130
- From: Christoph Reiter <creiter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject/gio-liststore-sort: 9/9] Add overrides for Gio.ListStore.sort and Gio.ListStore.insert_sorted. Fixes #130
- Date: Sat, 21 Apr 2018 04:07:17 +0000 (UTC)
commit d0bfb29fe5b34c58a190e084614fe489771bf53b
Author: Christoph Reiter <reiter christoph gmail com>
Date: Fri Apr 20 10:09:31 2018 +0200
Add overrides for Gio.ListStore.sort and Gio.ListStore.insert_sorted. Fixes #130
Those functions use CompareDataFunc which works with pointers and doesn't know
anything about GObjects.
Add overrides which wrap the passed in sort function and convert the pointers
to proper Python wrappers.
gi/_compat.py | 2 ++
gi/gimodule.c | 27 ++++++++++++++++++++++++
gi/overrides/Gio.py | 20 ++++++++++++++++++
tests/test_overrides_gio.py | 51 +++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 98 insertions(+), 2 deletions(-)
---
diff --git a/gi/_compat.py b/gi/_compat.py
index b4cc46d8..00f5fbb3 100644
--- a/gi/_compat.py
+++ b/gi/_compat.py
@@ -30,6 +30,7 @@ if sys.version_info[0] == 2:
reload = eval("reload")
xrange = eval("xrange")
+ cmp = eval("cmp")
exec("def reraise(tp, value, tb):\n raise tp, value, tb")
else:
@@ -49,6 +50,7 @@ else:
from importlib import reload
reload
xrange = range
+ cmp = lambda a, b: (a > b) - (a < b)
def reraise(tp, value, tb):
raise tp(value).with_traceback(tb)
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 441831cc..a3984dad 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -2240,7 +2240,34 @@ _wrap_pyig_pyos_getsig (PyObject *self, PyObject *args)
return PyLong_FromVoidPtr ((void *)(PyOS_getsig (sig_num)));
}
+static PyObject *
+_wrap_pygobject_new_full (PyObject *self, PyObject *args)
+{
+ PyObject *ptr_value, *long_value;
+ PyObject *steal;
+ GObject *obj;
+
+ if (!PyArg_ParseTuple (args, "OO", &ptr_value, &steal))
+ return NULL;
+
+ long_value = PyNumber_Long (ptr_value);
+ if (!long_value) {
+ PyErr_SetString (PyExc_TypeError, "first argument must be an integer");
+ return NULL;
+ }
+ obj = PyLong_AsVoidPtr (long_value);
+ Py_DECREF (long_value);
+
+ if (!G_IS_OBJECT (obj)) {
+ PyErr_SetString (PyExc_TypeError, "pointer is not a GObject");
+ return NULL;
+ }
+
+ return pygobject_new_full (obj, PyObject_IsTrue (steal), NULL);
+}
+
static PyMethodDef _gi_functions[] = {
+ { "pygobject_new_full", (PyCFunction) _wrap_pygobject_new_full, METH_VARARGS },
{ "enum_add", (PyCFunction) _wrap_pyg_enum_add, METH_VARARGS | METH_KEYWORDS },
{ "enum_register_new_gtype_and_add", (PyCFunction) _wrap_pyg_enum_register_new_gtype_and_add,
METH_VARARGS | METH_KEYWORDS },
{ "flags_add", (PyCFunction) _wrap_pyg_flags_add, METH_VARARGS | METH_KEYWORDS },
diff --git a/gi/overrides/Gio.py b/gi/overrides/Gio.py
index 75a128e3..f3c26b8d 100644
--- a/gi/overrides/Gio.py
+++ b/gi/overrides/Gio.py
@@ -24,6 +24,7 @@ from .._ossighelper import wakeup_on_signal, register_sigint_fallback
from ..overrides import override, deprecated_init
from ..module import get_introspection_module
from .._compat import xrange
+from gi._gi import pygobject_new_full
from gi import PyGIWarning
from gi.repository import GLib
@@ -324,8 +325,27 @@ ListModel = override(ListModel)
__all__.append('ListModel')
+def _wrap_list_store_sort_func(func):
+
+ def wrap(a, b, *user_data):
+ a = pygobject_new_full(a, False)
+ b = pygobject_new_full(b, False)
+ return func(a, b, *user_data)
+
+ return wrap
+
+
class ListStore(Gio.ListStore):
+ def sort(self, compare_func, *user_data):
+ compare_func = _wrap_list_store_sort_func(compare_func)
+ return super(ListStore, self).sort(compare_func, *user_data)
+
+ def insert_sorted(self, item, compare_func, *user_data):
+ compare_func = _wrap_list_store_sort_func(compare_func)
+ return super(ListStore, self).insert_sorted(
+ item, compare_func, *user_data)
+
def __delitem__(self, key):
if isinstance(key, slice):
start, stop, step = key.indices(len(self))
diff --git a/tests/test_overrides_gio.py b/tests/test_overrides_gio.py
index 123653cd..8434c2b0 100644
--- a/tests/test_overrides_gio.py
+++ b/tests/test_overrides_gio.py
@@ -5,13 +5,14 @@ import random
import pytest
from gi.repository import Gio, GObject
+from gi._compat import cmp
class Item(GObject.Object):
_id = 0
- def __init__(self):
- super(Item, self).__init__()
+ def __init__(self, **kwargs):
+ super(Item, self).__init__(**kwargs)
Item._id += 1
self._id = self._id
@@ -19,6 +20,52 @@ class Item(GObject.Object):
return str(self._id)
+class NamedItem(Item):
+
+ name = GObject.Property(type=str, default='')
+
+ def __repr__(self):
+ return self.props.name
+
+
+def test_list_store_sort():
+ store = Gio.ListStore()
+ items = [NamedItem(name=n) for n in "cabx"]
+ sorted_items = sorted(items, key=lambda i: i.props.name)
+
+ user_data = [object(), object()]
+
+ def sort_func(a, b, *args):
+ assert list(args) == user_data
+ assert isinstance(a, NamedItem)
+ assert isinstance(b, NamedItem)
+ return cmp(a.props.name, b.props.name)
+
+ store[:] = items
+ assert store[:] != sorted_items
+ store.sort(sort_func, *user_data)
+ assert store[:] == sorted_items
+
+
+def test_list_store_insert_sorted():
+ store = Gio.ListStore()
+ items = [NamedItem(name=n) for n in "cabx"]
+ sorted_items = sorted(items, key=lambda i: i.props.name)
+
+ user_data = [object(), object()]
+
+ def sort_func(a, b, *args):
+ assert list(args) == user_data
+ assert isinstance(a, NamedItem)
+ assert isinstance(b, NamedItem)
+ return cmp(a.props.name, b.props.name)
+
+ for item in items:
+ index = store.insert_sorted(item, sort_func, *user_data)
+ assert isinstance(index, int)
+ assert store[:] == sorted_items
+
+
def test_list_model_len():
model = Gio.ListStore.new(Item)
assert len(model) == 0
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]