[pygobject/gparam-deprecation: 3/3] Port to g_object_new_with_properties()



commit 28962d865f5f4f8e0cf5ba56d1660c06c65e9cff
Author: Christoph Reiter <reiter christoph gmail com>
Date:   Fri Oct 4 16:12:19 2019 +0200

    Port to g_object_new_with_properties()
    
    g_object_newv() and GParameter are deprecated now.
    
    Replace all GParameter usage with a separate GValue and char* array
    and add a compatibility function for g_object_new_with_properties()
    that also works with older glib and converts things back to GParameter.

 gi/gimodule.c         | 48 +++++++++++++++++++++++++++++++------
 gi/gimodule.h         | 11 +++++++--
 gi/pygobject-object.c | 65 +++++++++++++++++++++++++++++----------------------
 3 files changed, 87 insertions(+), 37 deletions(-)
---
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 4cba06e2..cf3c5ea2 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -1005,19 +1005,53 @@ pygobject_init_wrapper_get(void)
     return (PyObject *) g_private_get(&pygobject_construction_wrapper);
 }
 
+/**
+ * Like g_object_new_with_properties() but also works with older glib versions.
+ */
+GObject *
+pygobject_object_new_with_properties(GType object_type,
+                                     guint n_properties,
+                                     const char *names[],
+                                     const GValue values[])
+{
+    GObject *obj;
+
+#if GLIB_CHECK_VERSION(2, 54, 0)
+    obj = g_object_new_with_properties(object_type, n_properties, names, values);
+#else
+    {
+        GParameter *parameters;
+        uint i;
+
+        parameters = g_new(GParameter, n_properties);
+        for (i = 0; i < n_properties; i++) {
+            parameters[i].name = names[i];
+            parameters[i].value = values[i];
+        }
+        obj = g_object_newv(object_type, n_properties, parameters);
+        g_free(parameters);
+    }
+#endif
+
+    return obj;
+}
+
 int
-pygobject_constructv(PyGObject  *self,
-                     guint       n_parameters,
-                     GParameter *parameters)
+pygobject_constructv (PyGObject   *self,
+                      guint n_properties,
+                      const char *names[],
+                      const GValue values[])
 {
     GObject *obj;
 
     g_assert (self->obj == NULL);
     pygobject_init_wrapper_set((PyObject *) self);
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-    obj = g_object_newv(pyg_type_from_object((PyObject *) self),
-                        n_parameters, parameters);
-G_GNUC_END_IGNORE_DEPRECATIONS
+
+    obj = pygobject_object_new_with_properties(pyg_type_from_object((PyObject *) self),
+                                               n_properties,
+                                               names,
+                                               values);
+
     if (g_object_is_floating (obj))
         self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
     pygobject_sink (obj);
diff --git a/gi/gimodule.h b/gi/gimodule.h
index 7917ef6a..b9274bc4 100644
--- a/gi/gimodule.h
+++ b/gi/gimodule.h
@@ -4,7 +4,14 @@
 #include "pygobject-internal.h"
 
 int           pygobject_constructv (PyGObject   *self,
-                                    guint        n_parameters,
-                                    GParameter  *parameters);
+                                    guint n_properties,
+                                    const char *names[],
+                                    const GValue values[]);
+
+GObject *
+pygobject_object_new_with_properties(GType object_type,
+                                     guint n_properties,
+                                     const char *names[],
+                                     const GValue values[]);
 
 #endif /*_PYGOBJECT_GIMODULE_H_*/
diff --git a/gi/pygobject-object.c b/gi/pygobject-object.c
index 8e1437bd..d411afbd 100644
--- a/gi/pygobject-object.c
+++ b/gi/pygobject-object.c
@@ -1258,20 +1258,25 @@ pygobject_free(PyObject *op)
 
 static gboolean
 pygobject_prepare_construct_properties(GObjectClass *class, PyObject *kwargs,
-                                       guint *n_params, GParameter **params)
+                                       guint *n_properties, const char **names[], const GValue **values)
 {
-    *n_params = 0;
-    *params = NULL;
+    *n_properties = 0;
+    *names = NULL;
+    *values = NULL;
 
     if (kwargs) {
         Py_ssize_t pos = 0;
         PyObject *key;
         PyObject *value;
+        Py_ssize_t len;
 
-        *params = g_new0(GParameter, PyDict_Size(kwargs));
+        len = PyDict_Size(kwargs);
+        *names = g_new(const char*, len);
+        *values = g_new0(GValue, len);
         while (PyDict_Next(kwargs, &pos, &key, &value)) {
             GParamSpec *pspec;
-            GParameter *param = &(*params)[*n_params];
+            GValue *gvalue = &(*values)[*n_properties];
+
             const gchar *key_str = PYGLIB_PyUnicode_AsString(key);
 
             pspec = g_object_class_find_property(class, key_str);
@@ -1281,16 +1286,16 @@ pygobject_prepare_construct_properties(GObjectClass *class, PyObject *kwargs,
                              G_OBJECT_CLASS_NAME(class), key_str);
                 return FALSE;
             }
-            g_value_init(&param->value, G_PARAM_SPEC_VALUE_TYPE(pspec));
-            if (pyg_param_gvalue_from_pyobject(&param->value, value, pspec) < 0) {
+            g_value_init(gvalue, G_PARAM_SPEC_VALUE_TYPE(pspec));
+            if (pyg_param_gvalue_from_pyobject(gvalue, value, pspec) < 0) {
                 PyErr_Format(PyExc_TypeError,
                              "could not convert value for property `%s' from %s to %s",
                              key_str, Py_TYPE(value)->tp_name,
                              g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)));
                 return FALSE;
             }
-            param->name = g_strdup(key_str);
-            ++(*n_params);
+            (*names)[*n_properties] = g_strdup(key_str);
+            ++(*n_properties);
         }
     }
     return TRUE;
@@ -1302,8 +1307,9 @@ static int
 pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
     GType object_type;
-    guint n_params = 0, i;
-    GParameter *params = NULL;
+    guint n_properties = 0, i;
+    const GValue *values = NULL;
+    const char **names = NULL;
     GObjectClass *class;
 
     /* Only do GObject creation and property setting if the GObject hasn't
@@ -1337,18 +1343,20 @@ pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs)
        return -1;
     }
 
-    if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
+    if (!pygobject_prepare_construct_properties (class, kwargs, &n_properties, &names, &values))
         goto cleanup;
 
-    if (pygobject_constructv(self, n_params, params))
-       PyErr_SetString(PyExc_RuntimeError, "could not create object");
+    if (pygobject_constructv(self, n_properties, names, values))
+        PyErr_SetString(PyExc_RuntimeError, "could not create object");
 
  cleanup:
-    for (i = 0; i < n_params; i++) {
-       g_free((gchar *) params[i].name);
-       g_value_unset(&params[i].value);
+    for (i = 0; i < n_properties; i++) {
+        g_free(names[i]);
+        g_value_unset(&values[i]);
     }
-    g_free(params);
+    g_free(names);
+    g_free(values);
+
     g_type_class_unref(class);
     
     return (self->obj) ? 0 : -1;
@@ -2495,8 +2503,9 @@ pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
     GType type;
     GObject *obj = NULL;
     GObjectClass *class;
-    guint n_params = 0, i;
-    GParameter *params = NULL;
+    guint n_properties = 0, i;
+    const GValue *values = NULL;
+    const char **names = NULL;
 
     if (!PyArg_ParseTuple (args, "O:gobject.new", &pytype)) {
        return NULL;
@@ -2517,22 +2526,22 @@ pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
        return NULL;
     }
 
-    if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
+    if (!pygobject_prepare_construct_properties (class, kwargs, &n_properties, &names, &values))
         goto cleanup;
 
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-    obj = g_object_newv(type, n_params, params);
-G_GNUC_END_IGNORE_DEPRECATIONS
+    obj = pygobject_object_new_with_properties(type, n_properties, names, values);
 
     if (!obj)
        PyErr_SetString (PyExc_RuntimeError, "could not create object");
 
  cleanup:
-    for (i = 0; i < n_params; i++) {
-       g_free((gchar *) params[i].name);
-       g_value_unset(&params[i].value);
+    for (i = 0; i < n_properties; i++) {
+        g_free(names[i]);
+        g_value_unset(&values[i]);
     }
-    g_free(params);
+    g_free(names);
+    g_free(values);
+
     g_type_class_unref(class);
 
     if (obj) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]