summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Reiter <reiter.christoph@gmail.com>2018-03-21 19:30:26 +0100
committerChristoph Reiter <reiter.christoph@gmail.com>2018-03-21 21:38:37 +0100
commit2ad711b25064e106ab80a9358c932e51e9c871e2 (patch)
tree8d04048b8ab0e994949d11d815c4b20cc967502e
parent84448a33ee741eeeba1121b4d67963dcd95de813 (diff)
downloadpygobject-2ad711b25064e106ab80a9358c932e51e9c871e2.tar.gz
Remove gobjectmodule
This finishes what was started in b2529624b3925adbef2671025e08cbf747f162e8 and moves the remaining code mostly into gimodule. While this makes the large file even larger, it's a good starting point for more cleanups.
-rw-r--r--gi/Makefile.am2
-rw-r--r--gi/gimodule.c1721
-rw-r--r--gi/gimodule.h10
-rw-r--r--gi/gobjectmodule.c1897
-rw-r--r--gi/gobjectmodule.h27
-rw-r--r--gi/pygboxed.h2
-rw-r--r--gi/pygi-util.c42
-rw-r--r--gi/pygi-util.h1
-rw-r--r--gi/pygi-value.c34
-rw-r--r--gi/pygi-value.h3
-rw-r--r--gi/pygobject-object.c59
-rw-r--r--gi/pygobject-object.h1
12 files changed, 1863 insertions, 1936 deletions
diff --git a/gi/Makefile.am b/gi/Makefile.am
index 38410755..38209410 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -34,8 +34,6 @@ pygidir = $(pyexecdir)/gi
pygi_LTLIBRARIES = _gi.la
_gi_la_SOURCES = \
- gobjectmodule.c \
- gobjectmodule.h \
pygboxed.c \
pygboxed.h \
pygenum.c \
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 4bcb5fb9..136f74dd 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -47,9 +47,13 @@
#include "pygoptioncontext.h"
#include "pygoptiongroup.h"
#include "pygspawn.h"
-#include "gobjectmodule.h"
#include "pygparamspec.h"
#include "pygpointer.h"
+#include "pygobject-internal.h"
+#include "pygi-value.h"
+#include "pygi-property.h"
+#include "pygi-util.h"
+#include "gimodule.h"
#include <pyglib-python-compat.h>
@@ -57,10 +61,6 @@ PyObject *PyGIWarning;
PyObject *PyGIDeprecationWarning;
PyObject *_PyGIDefaultArgPlaceholder;
-
-/* Defined by PYGLIB_MODULE_START */
-extern PyObject *pyglib__gobject_module_create (void);
-
/* Returns a new flag/enum type or %NULL */
static PyObject *
flags_enum_from_gtype (GType g_type,
@@ -86,6 +86,1319 @@ flags_enum_from_gtype (GType g_type,
return new_type;
}
+static void pyg_flags_add_constants(PyObject *module, GType flags_type,
+ const gchar *strip_prefix);
+
+/**
+ * pyg_enum_add_constants:
+ * @module: a Python module
+ * @enum_type: the GType of the enumeration.
+ * @strip_prefix: the prefix to strip from the constant names.
+ *
+ * Adds constants to the given Python module for each value name of
+ * the enumeration. A prefix will be stripped from each enum name.
+ */
+static void
+pyg_enum_add_constants(PyObject *module, GType enum_type,
+ const gchar *strip_prefix)
+{
+ GEnumClass *eclass;
+ guint i;
+
+ if (!G_TYPE_IS_ENUM(enum_type)) {
+ if (G_TYPE_IS_FLAGS(enum_type)) /* See bug #136204 */
+ pyg_flags_add_constants(module, enum_type, strip_prefix);
+ else
+ g_warning("`%s' is not an enum type", g_type_name(enum_type));
+ return;
+ }
+ g_return_if_fail (strip_prefix != NULL);
+
+ eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
+
+ for (i = 0; i < eclass->n_values; i++) {
+ const gchar *name = eclass->values[i].value_name;
+ gint value = eclass->values[i].value;
+
+ PyModule_AddIntConstant(module,
+ (char*) pyg_constant_strip_prefix(name, strip_prefix),
+ (long) value);
+ }
+
+ g_type_class_unref(eclass);
+}
+
+/**
+ * pyg_flags_add_constants:
+ * @module: a Python module
+ * @flags_type: the GType of the flags type.
+ * @strip_prefix: the prefix to strip from the constant names.
+ *
+ * Adds constants to the given Python module for each value name of
+ * the flags set. A prefix will be stripped from each flag name.
+ */
+static void
+pyg_flags_add_constants(PyObject *module, GType flags_type,
+ const gchar *strip_prefix)
+{
+ GFlagsClass *fclass;
+ guint i;
+
+ if (!G_TYPE_IS_FLAGS(flags_type)) {
+ if (G_TYPE_IS_ENUM(flags_type)) /* See bug #136204 */
+ pyg_enum_add_constants(module, flags_type, strip_prefix);
+ else
+ g_warning("`%s' is not an flags type", g_type_name(flags_type));
+ return;
+ }
+ g_return_if_fail (strip_prefix != NULL);
+
+ fclass = G_FLAGS_CLASS(g_type_class_ref(flags_type));
+
+ for (i = 0; i < fclass->n_values; i++) {
+ const gchar *name = fclass->values[i].value_name;
+ guint value = fclass->values[i].value;
+
+ PyModule_AddIntConstant(module,
+ (char*) pyg_constant_strip_prefix(name, strip_prefix),
+ (long) value);
+ }
+
+ g_type_class_unref(fclass);
+}
+
+/**
+ * pyg_set_thread_block_funcs:
+ * Deprecated, only available for ABI compatibility.
+ */
+static void
+_pyg_set_thread_block_funcs (PyGThreadBlockFunc block_threads_func,
+ PyGThreadBlockFunc unblock_threads_func)
+{
+ PyGILState_STATE state = PyGILState_Ensure ();
+ PyErr_Warn (PyExc_DeprecationWarning,
+ "Using pyg_set_thread_block_funcs is not longer needed. "
+ "PyGObject always uses Py_BLOCK/UNBLOCK_THREADS.");
+ PyGILState_Release (state);
+}
+
+static GParamSpec *
+create_property (const gchar *prop_name,
+ GType prop_type,
+ const gchar *nick,
+ const gchar *blurb,
+ PyObject *args,
+ GParamFlags flags)
+{
+ GParamSpec *pspec = NULL;
+
+ switch (G_TYPE_FUNDAMENTAL(prop_type)) {
+ case G_TYPE_CHAR:
+ {
+ gchar minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_char (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_UCHAR:
+ {
+ gchar minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_uchar (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_BOOLEAN:
+ {
+ gboolean default_value;
+
+ if (!PyArg_ParseTuple(args, "i", &default_value))
+ return NULL;
+ pspec = g_param_spec_boolean (prop_name, nick, blurb,
+ default_value, flags);
+ }
+ break;
+ case G_TYPE_INT:
+ {
+ gint minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "iii", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_int (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_UINT:
+ {
+ guint minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "III", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_uint (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_LONG:
+ {
+ glong minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "lll", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_long (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_ULONG:
+ {
+ gulong minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "kkk", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_ulong (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_INT64:
+ {
+ gint64 minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "LLL", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_int64 (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_UINT64:
+ {
+ guint64 minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "KKK", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_uint64 (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_ENUM:
+ {
+ gint default_value;
+ PyObject *pydefault;
+
+ if (!PyArg_ParseTuple(args, "O", &pydefault))
+ return NULL;
+
+ if (pyg_enum_get_value(prop_type, pydefault,
+ (gint *)&default_value))
+ return NULL;
+
+ pspec = g_param_spec_enum (prop_name, nick, blurb,
+ prop_type, default_value, flags);
+ }
+ break;
+ case G_TYPE_FLAGS:
+ {
+ guint default_value;
+ PyObject *pydefault;
+
+ if (!PyArg_ParseTuple(args, "O", &pydefault))
+ return NULL;
+
+ if (pyg_flags_get_value(prop_type, pydefault,
+ &default_value))
+ return NULL;
+
+ pspec = g_param_spec_flags (prop_name, nick, blurb,
+ prop_type, default_value, flags);
+ }
+ break;
+ case G_TYPE_FLOAT:
+ {
+ gfloat minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "fff", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_float (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_DOUBLE:
+ {
+ gdouble minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "ddd", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_double (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_STRING:
+ {
+ const gchar *default_value;
+
+ if (!PyArg_ParseTuple(args, "z", &default_value))
+ return NULL;
+ pspec = g_param_spec_string (prop_name, nick, blurb,
+ default_value, flags);
+ }
+ break;
+ case G_TYPE_PARAM:
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ pspec = g_param_spec_param (prop_name, nick, blurb, prop_type, flags);
+ break;
+ case G_TYPE_BOXED:
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ pspec = g_param_spec_boxed (prop_name, nick, blurb, prop_type, flags);
+ break;
+ case G_TYPE_POINTER:
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (prop_type == G_TYPE_GTYPE)
+ pspec = g_param_spec_gtype (prop_name, nick, blurb, G_TYPE_NONE, flags);
+ else
+ pspec = g_param_spec_pointer (prop_name, nick, blurb, flags);
+ break;
+ case G_TYPE_OBJECT:
+ case G_TYPE_INTERFACE:
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ pspec = g_param_spec_object (prop_name, nick, blurb, prop_type, flags);
+ break;
+ case G_TYPE_VARIANT:
+ {
+ PyObject *pydefault;
+ GVariant *default_value = NULL;
+
+ if (!PyArg_ParseTuple(args, "O", &pydefault))
+ return NULL;
+ if (pydefault != Py_None)
+ default_value = pyg_boxed_get (pydefault, GVariant);
+ pspec = g_param_spec_variant (prop_name, nick, blurb, G_VARIANT_TYPE_ANY, default_value, flags);
+ }
+ break;
+ default:
+ /* unhandled pspec type ... */
+ break;
+ }
+
+ if (!pspec) {
+ char buf[128];
+
+ g_snprintf(buf, sizeof(buf), "could not create param spec for type %s",
+ g_type_name(prop_type));
+ PyErr_SetString(PyExc_TypeError, buf);
+ return NULL;
+ }
+
+ return pspec;
+}
+
+static GParamSpec *
+pyg_param_spec_from_object (PyObject *tuple)
+{
+ gint val_length;
+ const gchar *prop_name;
+ GType prop_type;
+ const gchar *nick, *blurb;
+ PyObject *slice, *item, *py_prop_type;
+ GParamSpec *pspec;
+
+ val_length = PyTuple_Size(tuple);
+ if (val_length < 4) {
+ PyErr_SetString(PyExc_TypeError,
+ "paramspec tuples must be at least 4 elements long");
+ return NULL;
+ }
+
+ slice = PySequence_GetSlice(tuple, 0, 4);
+ if (!slice) {
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(slice, "sOzz", &prop_name, &py_prop_type, &nick, &blurb)) {
+ Py_DECREF(slice);
+ return NULL;
+ }
+
+ Py_DECREF(slice);
+
+ prop_type = pyg_type_from_object(py_prop_type);
+ if (!prop_type) {
+ return NULL;
+ }
+
+ item = PyTuple_GetItem(tuple, val_length-1);
+ if (!PYGLIB_PyLong_Check(item)) {
+ PyErr_SetString(PyExc_TypeError,
+ "last element in tuple must be an int");
+ return NULL;
+ }
+
+ /* slice is the extra items in the tuple */
+ slice = PySequence_GetSlice(tuple, 4, val_length-1);
+ pspec = create_property(prop_name, prop_type,
+ nick, blurb, slice,
+ PYGLIB_PyLong_AsLong(item));
+
+ return pspec;
+}
+
+/**
+ * pyg_parse_constructor_args: helper function for PyGObject constructors
+ * @obj_type: GType of the GObject, for parameter introspection
+ * @arg_names: %NULL-terminated array of constructor argument names
+ * @prop_names: %NULL-terminated array of property names, with direct
+ * correspondence to @arg_names
+ * @params: GParameter array where parameters will be placed; length
+ * of this array must be at least equal to the number of
+ * arguments/properties
+ * @nparams: output parameter to contain actual number of arguments found
+ * @py_args: array of PyObject* containing the actual constructor arguments
+ *
+ * Parses an array of PyObject's and creates a GParameter array
+ *
+ * Return value: %TRUE if all is successful, otherwise %FALSE and
+ * python exception set.
+ **/
+static gboolean
+pyg_parse_constructor_args(GType obj_type,
+ char **arg_names,
+ char **prop_names,
+ GParameter *params,
+ guint *nparams,
+ PyObject **py_args)
+{
+ guint arg_i, param_i;
+ GObjectClass *oclass;
+
+ oclass = g_type_class_ref(obj_type);
+ g_return_val_if_fail(oclass, FALSE);
+
+ for (param_i = arg_i = 0; arg_names[arg_i]; ++arg_i) {
+ GParamSpec *spec;
+ if (!py_args[arg_i])
+ continue;
+ spec = g_object_class_find_property(oclass, prop_names[arg_i]);
+ params[param_i].name = prop_names[arg_i];
+ g_value_init(&params[param_i].value, spec->value_type);
+ if (pyg_value_from_pyobject(&params[param_i].value, py_args[arg_i]) == -1) {
+ guint i;
+ PyErr_Format(PyExc_TypeError, "could not convert parameter '%s' of type '%s'",
+ arg_names[arg_i], g_type_name(spec->value_type));
+ g_type_class_unref(oclass);
+ for (i = 0; i < param_i; ++i)
+ g_value_unset(&params[i].value);
+ return FALSE;
+ }
+ ++param_i;
+ }
+ g_type_class_unref(oclass);
+ *nparams = param_i;
+ return TRUE;
+}
+
+/* Only for backwards compatibility */
+static int
+pygobject_enable_threads(void)
+{
+ return 0;
+}
+
+static int
+pygobject_gil_state_ensure (void)
+{
+ return PyGILState_Ensure ();
+}
+
+static void
+pygobject_gil_state_release (int flag)
+{
+ PyGILState_Release(flag);
+}
+
+static void
+pyg_register_class_init(GType gtype, PyGClassInitFunc class_init)
+{
+ GSList *list;
+
+ list = g_type_get_qdata(gtype, pygobject_class_init_key);
+ list = g_slist_prepend(list, class_init);
+ g_type_set_qdata(gtype, pygobject_class_init_key, list);
+}
+
+static gboolean
+add_properties (GObjectClass *klass, PyObject *properties)
+{
+ gboolean ret = TRUE;
+ Py_ssize_t pos = 0;
+ PyObject *key, *value;
+
+ while (PyDict_Next(properties, &pos, &key, &value)) {
+ const gchar *prop_name;
+ GType prop_type;
+ const gchar *nick, *blurb;
+ GParamFlags flags;
+ gint val_length;
+ PyObject *slice, *item, *py_prop_type;
+ GParamSpec *pspec;
+
+ /* values are of format (type,nick,blurb, type_specific_args, flags) */
+
+ if (!PYGLIB_PyUnicode_Check(key)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gproperties__ keys must be strings");
+ ret = FALSE;
+ break;
+ }
+ prop_name = PYGLIB_PyUnicode_AsString (key);
+
+ if (!PyTuple_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gproperties__ values must be tuples");
+ ret = FALSE;
+ break;
+ }
+ val_length = PyTuple_Size(value);
+ if (val_length < 4) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gproperties__ values must be at least 4 elements long");
+ ret = FALSE;
+ break;
+ }
+
+ slice = PySequence_GetSlice(value, 0, 3);
+ if (!slice) {
+ ret = FALSE;
+ break;
+ }
+ if (!PyArg_ParseTuple(slice, "Ozz", &py_prop_type, &nick, &blurb)) {
+ Py_DECREF(slice);
+ ret = FALSE;
+ break;
+ }
+ Py_DECREF(slice);
+ prop_type = pyg_type_from_object(py_prop_type);
+ if (!prop_type) {
+ ret = FALSE;
+ break;
+ }
+ item = PyTuple_GetItem(value, val_length-1);
+ if (!PYGLIB_PyLong_Check(item)) {
+ PyErr_SetString(PyExc_TypeError,
+ "last element in __gproperties__ value tuple must be an int");
+ ret = FALSE;
+ break;
+ }
+ flags = PYGLIB_PyLong_AsLong(item);
+
+ /* slice is the extra items in the tuple */
+ slice = PySequence_GetSlice(value, 3, val_length-1);
+ pspec = create_property(prop_name, prop_type, nick, blurb,
+ slice, flags);
+ Py_DECREF(slice);
+
+ if (pspec) {
+ g_object_class_install_property(klass, 1, pspec);
+ } else {
+ PyObject *type, *pvalue, *traceback;
+ ret = FALSE;
+ PyErr_Fetch(&type, &pvalue, &traceback);
+ if (PYGLIB_PyUnicode_Check(pvalue)) {
+ char msg[256];
+ g_snprintf(msg, 256,
+ "%s (while registering property '%s' for GType '%s')",
+ PYGLIB_PyUnicode_AsString(pvalue),
+ prop_name, G_OBJECT_CLASS_NAME(klass));
+ Py_DECREF(pvalue);
+ value = PYGLIB_PyUnicode_FromString(msg);
+ }
+ PyErr_Restore(type, pvalue, traceback);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static gboolean
+override_signal(GType instance_type, const gchar *signal_name)
+{
+ guint signal_id;
+
+ signal_id = g_signal_lookup(signal_name, instance_type);
+ if (!signal_id) {
+ gchar buf[128];
+
+ g_snprintf(buf, sizeof(buf), "could not look up %s", signal_name);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return FALSE;
+ }
+ g_signal_override_class_closure(signal_id, instance_type,
+ pyg_signal_class_closure_get());
+ return TRUE;
+}
+
+typedef struct _PyGSignalAccumulatorData {
+ PyObject *callable;
+ PyObject *user_data;
+} PyGSignalAccumulatorData;
+
+
+static gboolean
+_pyg_signal_accumulator(GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer _data)
+{
+ PyObject *py_ihint, *py_return_accu, *py_handler_return, *py_detail;
+ PyObject *py_retval;
+ gboolean retval = FALSE;
+ PyGSignalAccumulatorData *data = _data;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+ if (ihint->detail)
+ py_detail = PYGLIB_PyUnicode_FromString(g_quark_to_string(ihint->detail));
+ else {
+ Py_INCREF(Py_None);
+ py_detail = Py_None;
+ }
+
+ py_ihint = Py_BuildValue("lNi", (long int) ihint->signal_id,
+ py_detail, ihint->run_type);
+ py_handler_return = pyg_value_as_pyobject(handler_return, TRUE);
+ py_return_accu = pyg_value_as_pyobject(return_accu, FALSE);
+ if (data->user_data)
+ py_retval = PyObject_CallFunction(data->callable, "NNNO", py_ihint,
+ py_return_accu, py_handler_return,
+ data->user_data);
+ else
+ py_retval = PyObject_CallFunction(data->callable, "NNN", py_ihint,
+ py_return_accu, py_handler_return);
+ if (!py_retval)
+ PyErr_Print();
+ else {
+ if (!PyTuple_Check(py_retval) || PyTuple_Size(py_retval) != 2) {
+ PyErr_SetString(PyExc_TypeError, "accumulator function must return"
+ " a (bool, object) tuple");
+ PyErr_Print();
+ } else {
+ retval = PyObject_IsTrue(PyTuple_GET_ITEM(py_retval, 0));
+ if (pyg_value_from_pyobject(return_accu, PyTuple_GET_ITEM(py_retval, 1))) {
+ PyErr_Print();
+ }
+ }
+ Py_DECREF(py_retval);
+ }
+ PyGILState_Release(state);
+ return retval;
+}
+
+static gboolean
+create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple)
+{
+ GSignalFlags signal_flags;
+ PyObject *py_return_type, *py_param_types;
+ GType return_type;
+ guint n_params, i;
+ GType *param_types;
+ guint signal_id;
+ GSignalAccumulator accumulator = NULL;
+ PyGSignalAccumulatorData *accum_data = NULL;
+ PyObject *py_accum = NULL, *py_accum_data = NULL;
+
+ if (!PyArg_ParseTuple(tuple, "iOO|OO", &signal_flags, &py_return_type,
+ &py_param_types, &py_accum, &py_accum_data))
+ {
+ gchar buf[128];
+
+ PyErr_Clear();
+ g_snprintf(buf, sizeof(buf),
+ "value for __gsignals__['%s'] not in correct format", signal_name);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return FALSE;
+ }
+
+ if (py_accum && py_accum != Py_None && !PyCallable_Check(py_accum))
+ {
+ gchar buf[128];
+
+ g_snprintf(buf, sizeof(buf),
+ "accumulator for __gsignals__['%s'] must be callable", signal_name);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return FALSE;
+ }
+
+ return_type = pyg_type_from_object(py_return_type);
+ if (!return_type)
+ return FALSE;
+ if (!PySequence_Check(py_param_types)) {
+ gchar buf[128];
+
+ g_snprintf(buf, sizeof(buf),
+ "third element of __gsignals__['%s'] tuple must be a sequence", signal_name);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return FALSE;
+ }
+ n_params = PySequence_Length(py_param_types);
+ param_types = g_new(GType, n_params);
+ for (i = 0; i < n_params; i++) {
+ PyObject *item = PySequence_GetItem(py_param_types, i);
+
+ param_types[i] = pyg_type_from_object(item);
+ if (param_types[i] == 0) {
+ Py_DECREF(item);
+ g_free(param_types);
+ return FALSE;
+ }
+ Py_DECREF(item);
+ }
+
+ if (py_accum != NULL && py_accum != Py_None) {
+ accum_data = g_new(PyGSignalAccumulatorData, 1);
+ accum_data->callable = py_accum;
+ Py_INCREF(py_accum);
+ accum_data->user_data = py_accum_data;
+ Py_XINCREF(py_accum_data);
+ accumulator = _pyg_signal_accumulator;
+ }
+
+ signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
+ pyg_signal_class_closure_get(),
+ accumulator, accum_data,
+ gi_cclosure_marshal_generic,
+ return_type, n_params, param_types);
+ g_free(param_types);
+
+ if (signal_id == 0) {
+ gchar buf[128];
+
+ g_snprintf(buf, sizeof(buf), "could not create signal for %s",
+ signal_name);
+ PyErr_SetString(PyExc_RuntimeError, buf);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+static PyObject *
+add_signals (GObjectClass *klass, PyObject *signals)
+{
+ gboolean ret = TRUE;
+ Py_ssize_t pos = 0;
+ PyObject *key, *value, *overridden_signals = NULL;
+ GType instance_type = G_OBJECT_CLASS_TYPE (klass);
+
+ overridden_signals = PyDict_New();
+ while (PyDict_Next(signals, &pos, &key, &value)) {
+ const gchar *signal_name;
+ gchar *signal_name_canon, *c;
+
+ if (!PYGLIB_PyUnicode_Check(key)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gsignals__ keys must be strings");
+ ret = FALSE;
+ break;
+ }
+ signal_name = PYGLIB_PyUnicode_AsString (key);
+
+ if (value == Py_None ||
+ (PYGLIB_PyUnicode_Check(value) &&
+ !strcmp(PYGLIB_PyUnicode_AsString(value), "override")))
+ {
+ /* canonicalize signal name, replacing '-' with '_' */
+ signal_name_canon = g_strdup(signal_name);
+ for (c = signal_name_canon; *c; ++c)
+ if (*c == '-')
+ *c = '_';
+ if (PyDict_SetItemString(overridden_signals,
+ signal_name_canon, key)) {
+ g_free(signal_name_canon);
+ ret = FALSE;
+ break;
+ }
+ g_free(signal_name_canon);
+
+ ret = override_signal(instance_type, signal_name);
+ } else {
+ ret = create_signal(instance_type, signal_name, value);
+ }
+
+ if (!ret)
+ break;
+ }
+ if (ret)
+ return overridden_signals;
+ else {
+ Py_XDECREF(overridden_signals);
+ return NULL;
+ }
+}
+
+static void
+pyg_object_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ PyObject *object_wrapper, *retval;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+
+ object_wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
+
+ if (object_wrapper)
+ Py_INCREF (object_wrapper);
+ else
+ object_wrapper = pygobject_new(object);
+
+ if (object_wrapper == NULL) {
+ PyGILState_Release(state);
+ return;
+ }
+
+ retval = pygi_call_do_get_property (object_wrapper, pspec);
+ if (retval && pyg_value_from_pyobject (value, retval) < 0) {
+ PyErr_Print();
+ }
+ Py_DECREF(object_wrapper);
+ Py_XDECREF(retval);
+
+ PyGILState_Release(state);
+}
+
+static void
+pyg_object_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ PyObject *object_wrapper, *retval;
+ PyObject *py_pspec, *py_value;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+
+ object_wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
+
+ if (object_wrapper)
+ Py_INCREF (object_wrapper);
+ else
+ object_wrapper = pygobject_new(object);
+
+ if (object_wrapper == NULL) {
+ PyGILState_Release(state);
+ return;
+ }
+
+ py_pspec = pyg_param_spec_new(pspec);
+ py_value = pyg_value_as_pyobject (value, TRUE);
+
+ retval = PyObject_CallMethod(object_wrapper, "do_set_property",
+ "OO", py_pspec, py_value);
+ if (retval) {
+ Py_DECREF(retval);
+ } else {
+ PyErr_Print();
+ }
+
+ Py_DECREF(object_wrapper);
+ Py_DECREF(py_pspec);
+ Py_DECREF(py_value);
+
+ PyGILState_Release(state);
+}
+
+static void
+pyg_object_class_init(GObjectClass *class, PyObject *py_class)
+{
+ PyObject *gproperties, *gsignals, *overridden_signals;
+ PyObject *class_dict = ((PyTypeObject*) py_class)->tp_dict;
+
+ class->set_property = pyg_object_set_property;
+ class->get_property = pyg_object_get_property;
+
+ /* install signals */
+ /* we look this up in the instance dictionary, so we don't
+ * accidentally get a parent type's __gsignals__ attribute. */
+ gsignals = PyDict_GetItemString(class_dict, "__gsignals__");
+ if (gsignals) {
+ if (!PyDict_Check(gsignals)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gsignals__ attribute not a dict!");
+ return;
+ }
+ if (!(overridden_signals = add_signals(class, gsignals))) {
+ return;
+ }
+ if (PyDict_SetItemString(class_dict, "__gsignals__",
+ overridden_signals)) {
+ return;
+ }
+ Py_DECREF(overridden_signals);
+
+ PyDict_DelItemString(class_dict, "__gsignals__");
+ } else {
+ PyErr_Clear();
+ }
+
+ /* install properties */
+ /* we look this up in the instance dictionary, so we don't
+ * accidentally get a parent type's __gproperties__ attribute. */
+ gproperties = PyDict_GetItemString(class_dict, "__gproperties__");
+ if (gproperties) {
+ if (!PyDict_Check(gproperties)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gproperties__ attribute not a dict!");
+ return;
+ }
+ if (!add_properties(class, gproperties)) {
+ return;
+ }
+ PyDict_DelItemString(class_dict, "__gproperties__");
+ /* Borrowed reference. Py_DECREF(gproperties); */
+ } else {
+ PyErr_Clear();
+ }
+}
+
+static GPrivate pygobject_construction_wrapper;
+
+static inline void
+pygobject_init_wrapper_set(PyObject *wrapper)
+{
+ g_private_set(&pygobject_construction_wrapper, wrapper);
+}
+
+static inline PyObject *
+pygobject_init_wrapper_get(void)
+{
+ return (PyObject *) g_private_get(&pygobject_construction_wrapper);
+}
+
+int
+pygobject_constructv(PyGObject *self,
+ guint n_parameters,
+ GParameter *parameters)
+{
+ 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
+ if (g_object_is_floating (obj))
+ self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
+ pygobject_sink (obj);
+
+ pygobject_init_wrapper_set(NULL);
+ self->obj = obj;
+ pygobject_register_wrapper((PyObject *) self);
+
+ return 0;
+}
+
+static void
+pygobject__g_instance_init(GTypeInstance *instance,
+ gpointer g_class)
+{
+ GObject *object = (GObject *) instance;
+ PyObject *wrapper, *args, *kwargs;
+
+ wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
+ if (wrapper == NULL) {
+ wrapper = pygobject_init_wrapper_get();
+ if (wrapper && ((PyGObject *) wrapper)->obj == NULL) {
+ ((PyGObject *) wrapper)->obj = object;
+ pygobject_register_wrapper(wrapper);
+ }
+ }
+ pygobject_init_wrapper_set(NULL);
+ if (wrapper == NULL) {
+ /* this looks like a python object created through
+ * g_object_new -> we have no python wrapper, so create it
+ * now */
+ PyGILState_STATE state;
+ state = PyGILState_Ensure();
+ wrapper = pygobject_new_full(object,
+ /*steal=*/ FALSE,
+ g_class);
+
+ /* float the wrapper ref here because we are going to orphan it
+ * so we don't destroy the wrapper. The next call to pygobject_new_full
+ * will take the ref */
+ pygobject_ref_float ((PyGObject *) wrapper);
+ args = PyTuple_New(0);
+ kwargs = PyDict_New();
+ if (Py_TYPE(wrapper)->tp_init(wrapper, args, kwargs))
+ PyErr_Print();
+
+ Py_DECREF(args);
+ Py_DECREF(kwargs);
+ PyGILState_Release(state);
+ }
+}
+
+/* This implementation is bad, see bug 566571 for an example why.
+ * Instead of scanning explicitly declared bases for interfaces, we
+ * should automatically initialize all implemented interfaces to
+ * prevent bugs like that one. However, this will lead to
+ * performance degradation as each virtual method in derived classes
+ * will round-trip through do_*() stuff, *even* if it is not
+ * overriden. We need to teach codegen to retain parent method
+ * instead of setting virtual to *_proxy_do_*() if corresponding
+ * do_*() is not overriden. Ok, that was a messy explanation.
+ */
+static void
+pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
+ PyObject *bases,
+ GType *parent_interfaces, guint n_parent_interfaces)
+{
+ int i;
+
+ if (!bases) {
+ g_warning("type has no bases");
+ return;
+ }
+
+ for (i = 0; i < PyTuple_GET_SIZE(bases); ++i) {
+ PyObject *base = PyTuple_GET_ITEM(bases, i);
+ GType itype;
+ const GInterfaceInfo *iinfo;
+ GInterfaceInfo iinfo_copy;
+
+ /* 'base' can also be a PyClassObject, see bug #566571. */
+ if (!PyType_Check(base))
+ continue;
+
+ if (!PyType_IsSubtype((PyTypeObject*) base, &PyGInterface_Type))
+ continue;
+
+ itype = pyg_type_from_object(base);
+
+ /* Happens for _implementations_ of an interface. */
+ if (!G_TYPE_IS_INTERFACE(itype))
+ continue;
+
+ iinfo = pyg_lookup_interface_info(itype);
+ if (!iinfo) {
+ gchar *error;
+ error = g_strdup_printf("Interface type %s "
+ "has no Python implementation support",
+ ((PyTypeObject *) base)->tp_name);
+ PyErr_Warn(PyExc_RuntimeWarning, error);
+ g_free(error);
+ continue;
+ }
+
+ iinfo_copy = *iinfo;
+ iinfo_copy.interface_data = class;
+ g_type_add_interface_static(instance_type, itype, &iinfo_copy);
+ }
+}
+
+static int
+pyg_run_class_init(GType gtype, gpointer gclass, PyTypeObject *pyclass)
+{
+ GSList *list;
+ PyGClassInitFunc class_init;
+ GType parent_type;
+ int rv;
+
+ parent_type = g_type_parent(gtype);
+ if (parent_type) {
+ rv = pyg_run_class_init(parent_type, gclass, pyclass);
+ if (rv)
+ return rv;
+ }
+
+ list = g_type_get_qdata(gtype, pygobject_class_init_key);
+ for (; list; list = list->next) {
+ class_init = list->data;
+ rv = class_init(gclass, pyclass);
+ if (rv)
+ return rv;
+ }
+
+ return 0;
+}
+
+static char *
+get_type_name_for_class(PyTypeObject *class)
+{
+ gint i, name_serial;
+ char name_serial_str[16];
+ PyObject *module;
+ char *type_name = NULL;
+
+ /* make name for new GType */
+ name_serial = 1;
+ /* give up after 1000 tries, just in case.. */
+ while (name_serial < 1000)
+ {
+ g_free(type_name);
+ g_snprintf(name_serial_str, 16, "-v%i", name_serial);
+ module = PyObject_GetAttrString((PyObject *)class, "__module__");
+ if (module && PYGLIB_PyUnicode_Check(module)) {
+ type_name = g_strconcat(PYGLIB_PyUnicode_AsString(module), ".",
+ class->tp_name,
+ name_serial > 1 ? name_serial_str : NULL,
+ NULL);
+ Py_DECREF(module);
+ } else {
+ if (module)
+ Py_DECREF(module);
+ else
+ PyErr_Clear();
+ type_name = g_strconcat(class->tp_name,
+ name_serial > 1 ? name_serial_str : NULL,
+ NULL);
+ }
+ /* convert '.' in type name to '+', which isn't banned (grumble) */
+ for (i = 0; type_name[i] != '\0'; i++)
+ if (type_name[i] == '.')
+ type_name[i] = '+';
+ if (g_type_from_name(type_name) == 0)
+ break; /* we now have a unique name */
+ ++name_serial;
+ }
+
+ return type_name;
+}
+
+static int
+pyg_type_register(PyTypeObject *class, const char *type_name)
+{
+ PyObject *gtype;
+ GType parent_type, instance_type;
+ GType *parent_interfaces;
+ guint n_parent_interfaces;
+ GTypeQuery query;
+ gpointer gclass;
+ GTypeInfo type_info = {
+ 0, /* class_size */
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+
+ (GClassInitFunc) pyg_object_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+
+ 0, /* instance_size */
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pygobject__g_instance_init
+ };
+ gchar *new_type_name;
+
+ /* find the GType of the parent */
+ parent_type = pyg_type_from_object((PyObject *)class);
+ if (!parent_type)
+ return -1;
+
+ parent_interfaces = g_type_interfaces(parent_type, &n_parent_interfaces);
+
+ if (type_name)
+ /* care is taken below not to free this */
+ new_type_name = (gchar *) type_name;
+ else
+ new_type_name = get_type_name_for_class(class);
+
+ /* set class_data that will be passed to the class_init function. */
+ type_info.class_data = class;
+
+ /* fill in missing values of GTypeInfo struct */
+ g_type_query(parent_type, &query);
+ type_info.class_size = query.class_size;
+ type_info.instance_size = query.instance_size;
+
+ /* create new typecode */
+ instance_type = g_type_register_static(parent_type, new_type_name,
+ &type_info, 0);
+ if (instance_type == 0) {
+ PyErr_Format(PyExc_RuntimeError,
+ "could not create new GType: %s (subclass of %s)",
+ new_type_name,
+ g_type_name(parent_type));
+
+ if (type_name == NULL)
+ g_free(new_type_name);
+
+ return -1;
+ }
+
+ if (type_name == NULL)
+ g_free(new_type_name);
+
+ /* store pointer to the class with the GType */
+ Py_INCREF(class);
+ g_type_set_qdata(instance_type, g_quark_from_string("PyGObject::class"),
+ class);
+
+ /* Mark this GType as a custom python type */
+ g_type_set_qdata(instance_type, pygobject_custom_key,
+ GINT_TO_POINTER (1));
+
+ /* set new value of __gtype__ on class */
+ gtype = pyg_type_wrapper_new(instance_type);
+ PyObject_SetAttrString((PyObject *)class, "__gtype__", gtype);
+ Py_DECREF(gtype);
+
+ /* if no __doc__, set it to the auto doc descriptor */
+ if (PyDict_GetItemString(class->tp_dict, "__doc__") == NULL) {
+ PyDict_SetItemString(class->tp_dict, "__doc__",
+ pyg_object_descr_doc_get());
+ }
+
+ /*
+ * Note, all interfaces need to be registered before the first
+ * g_type_class_ref(), see bug #686149.
+ *
+ * See also comment above pyg_type_add_interfaces().
+ */
+ pyg_type_add_interfaces(class, instance_type, class->tp_bases,
+ parent_interfaces, n_parent_interfaces);
+
+
+ gclass = g_type_class_ref(instance_type);
+ if (PyErr_Occurred() != NULL) {
+ g_type_class_unref(gclass);
+ g_free(parent_interfaces);
+ return -1;
+ }
+
+ if (pyg_run_class_init(instance_type, gclass, class)) {
+ g_type_class_unref(gclass);
+ g_free(parent_interfaces);
+ return -1;
+ }
+ g_type_class_unref(gclass);
+ g_free(parent_interfaces);
+
+ if (PyErr_Occurred() != NULL)
+ return -1;
+ return 0;
+}
+
+static PyObject *
+_wrap_pyg_type_register(PyObject *self, PyObject *args)
+{
+ PyTypeObject *class;
+ char *type_name = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!|z:gobject.type_register",
+ &PyType_Type, &class, &type_name))
+ return NULL;
+ if (!PyType_IsSubtype(class, &PyGObject_Type)) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument must be a GObject subclass");
+ return NULL;
+ }
+
+ /* Check if type already registered */
+ if (pyg_type_from_object((PyObject *) class) ==
+ pyg_type_from_object((PyObject *) class->tp_base))
+ {
+ if (pyg_type_register(class, type_name))
+ return NULL;
+ }
+
+ Py_INCREF(class);
+ return (PyObject *) class;
+}
+
+static GHashTable *log_handlers = NULL;
+static gboolean log_handlers_disabled = FALSE;
+
+static void
+remove_handler(gpointer domain,
+ gpointer handler,
+ gpointer unused)
+{
+ g_log_remove_handler(domain, GPOINTER_TO_UINT(handler));
+}
+
+static void
+_log_func(const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ if (G_LIKELY(Py_IsInitialized()))
+ {
+ PyGILState_STATE state;
+ PyObject* warning = user_data;
+
+ state = PyGILState_Ensure();
+ PyErr_Warn(warning, (char *) message);
+ PyGILState_Release(state);
+ } else
+ g_log_default_handler(log_domain, log_level, message, user_data);
+}
+
+static void
+add_warning_redirection(const char *domain,
+ PyObject *warning)
+{
+ g_return_if_fail(domain != NULL);
+ g_return_if_fail(warning != NULL);
+
+ if (!log_handlers_disabled)
+ {
+ guint handler;
+ gpointer old_handler;
+
+ if (!log_handlers)
+ log_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+ if ((old_handler = g_hash_table_lookup(log_handlers, domain)))
+ g_log_remove_handler(domain, GPOINTER_TO_UINT(old_handler));
+
+ handler = g_log_set_handler(domain, G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING,
+ _log_func, warning);
+ g_hash_table_insert(log_handlers, g_strdup(domain), GUINT_TO_POINTER(handler));
+ }
+}
+
+static void
+disable_warning_redirections(void)
+{
+ log_handlers_disabled = TRUE;
+
+ if (log_handlers)
+ {
+ g_hash_table_foreach(log_handlers, remove_handler, NULL);
+ g_hash_table_destroy(log_handlers);
+ log_handlers = NULL;
+ }
+}
+
+static void
+pygobject_register_warnings(PyObject *d)
+{
+ PyObject *warning;
+
+ warning = PyErr_NewException("gobject.Warning", PyExc_Warning, NULL);
+ PyDict_SetItemString(d, "Warning", warning);
+ add_warning_redirection("GLib", warning);
+ add_warning_redirection("GLib-GObject", warning);
+ add_warning_redirection("GThread", warning);
+}
static PyObject *
_wrap_pyg_enum_add (PyObject *self,
@@ -619,6 +1932,267 @@ pyg_channel_read(PyObject* self, PyObject *args, PyObject *kwargs)
return NULL;
}
+static gboolean
+marshal_emission_hook(GSignalInvocationHint *ihint,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer user_data)
+{
+ PyGILState_STATE state;
+ gboolean retval = FALSE;
+ PyObject *func, *args;
+ PyObject *retobj;
+ PyObject *params;
+ guint i;
+
+ state = PyGILState_Ensure();
+
+ /* construct Python tuple for the parameter values */
+ params = PyTuple_New(n_param_values);
+
+ for (i = 0; i < n_param_values; i++) {
+ PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
+
+ /* error condition */
+ if (!item) {
+ goto out;
+ }
+ PyTuple_SetItem(params, i, item);
+ }
+
+ args = (PyObject *)user_data;
+ func = PyTuple_GetItem(args, 0);
+ args = PySequence_Concat(params, PyTuple_GetItem(args, 1));
+ Py_DECREF(params);
+
+ /* params passed to function may have extra arguments */
+
+ retobj = PyObject_CallObject(func, args);
+ Py_DECREF(args);
+ if (retobj == NULL) {
+ PyErr_Print();
+ }
+
+ retval = (retobj == Py_True ? TRUE : FALSE);
+ Py_XDECREF(retobj);
+out:
+ PyGILState_Release(state);
+ return retval;
+}
+
+/**
+ * pyg_destroy_notify:
+ * @user_data: a PyObject pointer.
+ *
+ * A function that can be used as a GDestroyNotify callback that will
+ * call Py_DECREF on the data.
+ */
+static void
+pyg_destroy_notify(gpointer user_data)
+{
+ PyObject *obj = (PyObject *)user_data;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+ Py_DECREF(obj);
+ PyGILState_Release(state);
+}
+
+static PyObject *
+pyg_add_emission_hook(PyGObject *self, PyObject *args)
+{
+ PyObject *first, *callback, *extra_args, *data, *repr;
+ gchar *name;
+ gulong hook_id;
+ guint sigid;
+ Py_ssize_t len;
+ GQuark detail = 0;
+ GType gtype;
+ PyObject *pygtype;
+
+ len = PyTuple_Size(args);
+ if (len < 3) {
+ PyErr_SetString(PyExc_TypeError,
+ "gobject.add_emission_hook requires at least 3 arguments");
+ return NULL;
+ }
+ first = PySequence_GetSlice(args, 0, 3);
+ if (!PyArg_ParseTuple(first, "OsO:add_emission_hook",
+ &pygtype, &name, &callback)) {
+ Py_DECREF(first);
+ return NULL;
+ }
+ Py_DECREF(first);
+
+ if ((gtype = pyg_type_from_object(pygtype)) == 0) {
+ return NULL;
+ }
+ if (!PyCallable_Check(callback)) {
+ PyErr_SetString(PyExc_TypeError, "third argument must be callable");
+ return NULL;
+ }
+
+ if (!g_signal_parse_name(name, gtype, &sigid, &detail, TRUE)) {
+ repr = PyObject_Repr((PyObject*)self);
+ PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
+ PYGLIB_PyUnicode_AsString(repr),
+ name);
+ Py_DECREF(repr);
+ return NULL;
+ }
+ extra_args = PySequence_GetSlice(args, 3, len);
+ if (extra_args == NULL)
+ return NULL;
+
+ data = Py_BuildValue("(ON)", callback, extra_args);
+ if (data == NULL)
+ return NULL;
+
+ hook_id = g_signal_add_emission_hook(sigid, detail,
+ marshal_emission_hook,
+ data,
+ (GDestroyNotify)pyg_destroy_notify);
+
+ return PyLong_FromUnsignedLong(hook_id);
+}
+
+static PyObject *
+pyg_signal_new(PyObject *self, PyObject *args)
+{
+ gchar *signal_name;
+ PyObject *py_type;
+ GSignalFlags signal_flags;
+ GType return_type;
+ PyObject *py_return_type, *py_param_types;
+
+ GType instance_type = 0;
+ Py_ssize_t n_params, i;
+ GType *param_types;
+
+ guint signal_id;
+
+ if (!PyArg_ParseTuple(args, "sOiOO:gobject.signal_new", &signal_name,
+ &py_type, &signal_flags, &py_return_type,
+ &py_param_types))
+ return NULL;
+
+ instance_type = pyg_type_from_object(py_type);
+ if (!instance_type)
+ return NULL;
+ if (!(G_TYPE_IS_INSTANTIATABLE(instance_type) || G_TYPE_IS_INTERFACE(instance_type))) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument 2 must be an object type or interface type");
+ return NULL;
+ }
+
+ return_type = pyg_type_from_object(py_return_type);
+ if (!return_type)
+ return NULL;
+
+ if (!PySequence_Check(py_param_types)) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument 5 must be a sequence of GType codes");
+ return NULL;
+ }
+ n_params = PySequence_Length(py_param_types);
+ param_types = g_new(GType, n_params);
+ for (i = 0; i < n_params; i++) {
+ PyObject *item = PySequence_GetItem(py_param_types, i);
+
+ param_types[i] = pyg_type_from_object(item);
+ if (param_types[i] == 0) {
+ PyErr_Clear();
+ Py_DECREF(item);
+ PyErr_SetString(PyExc_TypeError,
+ "argument 5 must be a sequence of GType codes");
+ g_free(param_types);
+ return NULL;
+ }
+ Py_DECREF(item);
+ }
+
+ signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
+ pyg_signal_class_closure_get(),
+ (GSignalAccumulator)0, NULL,
+ (GSignalCMarshaller)0,
+ return_type, n_params, param_types);
+ g_free(param_types);
+ if (signal_id != 0)
+ return PYGLIB_PyLong_FromLong(signal_id);
+ PyErr_SetString(PyExc_RuntimeError, "could not create signal");
+ return NULL;
+}
+
+static PyObject *
+pyg_object_class_list_properties (PyObject *self, PyObject *args)
+{
+ GParamSpec **specs;
+ PyObject *py_itype, *list;
+ GType itype;
+ GObjectClass *class = NULL;
+ gpointer iface = NULL;
+ guint nprops;
+ guint i;
+
+ if (!PyArg_ParseTuple(args, "O:gobject.list_properties",
+ &py_itype))
+ return NULL;
+ if ((itype = pyg_type_from_object(py_itype)) == 0)
+ return NULL;
+
+ if (G_TYPE_IS_INTERFACE(itype)) {
+ iface = g_type_default_interface_ref(itype);
+ if (!iface) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "could not get a reference to interface type");
+ return NULL;
+ }
+ specs = g_object_interface_list_properties(iface, &nprops);
+ } else if (g_type_is_a(itype, G_TYPE_OBJECT)) {
+ class = g_type_class_ref(itype);
+ if (!class) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "could not get a reference to type class");
+ return NULL;
+ }
+ specs = g_object_class_list_properties(class, &nprops);
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "type must be derived from GObject or an interface");
+ return NULL;
+ }
+
+ list = PyTuple_New(nprops);
+ if (list == NULL) {
+ g_free(specs);
+ g_type_class_unref(class);
+ return NULL;
+ }
+ for (i = 0; i < nprops; i++) {
+ PyTuple_SetItem(list, i, pyg_param_spec_new(specs[i]));
+ }
+ g_free(specs);
+ if (class)
+ g_type_class_unref(class);
+ else
+ g_type_default_interface_unref(iface);
+
+ return list;
+}
+
+static PyObject *
+pyg__install_metaclass(PyObject *dummy, PyTypeObject *metaclass)
+{
+ Py_INCREF(metaclass);
+ PyGObject_MetaType = metaclass;
+ Py_INCREF(metaclass);
+
+ Py_TYPE(&PyGObject_Type) = metaclass;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
static PyMethodDef _gi_functions[] = {
{ "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 },
@@ -662,6 +2236,143 @@ static struct PyGI_API CAPI = {
pygi_register_foreign_struct,
};
+struct _PyGObject_Functions pygobject_api_functions = {
+ pygobject_register_class,
+ pygobject_register_wrapper,
+ pygobject_lookup_class,
+ pygobject_new,
+
+ pyg_closure_new,
+ pygobject_watch_closure,
+ pyg_destroy_notify,
+
+ pyg_type_from_object,
+ pyg_type_wrapper_new,
+ pyg_enum_get_value,
+ pyg_flags_get_value,
+ pyg_register_gtype_custom,
+ pyg_value_from_pyobject,
+ pyg_value_as_pyobject,
+
+ pyg_register_interface,
+
+ &PyGBoxed_Type,
+ pyg_register_boxed,
+ pyg_boxed_new,
+
+ &PyGPointer_Type,
+ pyg_register_pointer,
+ pyg_pointer_new,
+
+ pyg_enum_add_constants,
+ pyg_flags_add_constants,
+
+ pyg_constant_strip_prefix,
+
+ pygi_error_check,
+
+ _pyg_set_thread_block_funcs,
+ (PyGThreadBlockFunc)0, /* block_threads */
+ (PyGThreadBlockFunc)0, /* unblock_threads */
+
+ &PyGParamSpec_Type,
+ pyg_param_spec_new,
+ pyg_param_spec_from_object,
+
+ pyg_pyobj_to_unichar_conv,
+ pyg_parse_constructor_args,
+ pyg_param_gvalue_as_pyobject,
+ pyg_param_gvalue_from_pyobject,
+
+ &PyGEnum_Type,
+ pyg_enum_add,
+ pyg_enum_from_gtype,
+
+ &PyGFlags_Type,
+ pyg_flags_add,
+ pyg_flags_from_gtype,
+
+ TRUE, /* threads_enabled */
+
+ pygobject_enable_threads,
+ pygobject_gil_state_ensure,
+ pygobject_gil_state_release,
+ pyg_register_class_init,
+ pyg_register_interface_info,
+
+ pyg_closure_set_exception_handler,
+
+ add_warning_redirection,
+ disable_warning_redirections,
+
+ NULL, /* previously type_register_custom */
+
+ pygi_gerror_exception_check,
+
+ pyg_option_group_new,
+ pyg_type_from_object_strict,
+
+ pygobject_new_full,
+ &PyGObject_Type,
+
+ pyg_value_from_pyobject_with_error
+};
+
+static void
+pygobject_register_api(PyObject *d)
+{
+ PyObject *api;
+
+ api = PYGLIB_CPointer_WrapPointer(&pygobject_api_functions, "gobject._PyGObject_API");
+ PyDict_SetItemString(d, "_PyGObject_API", api);
+ Py_DECREF(api);
+}
+
+/* some constants */
+static void
+pygobject_register_constants(PyObject *m)
+{
+ /* PyFloat_ return a new ref, and add object takes the ref */
+ PyModule_AddObject(m, "G_MINFLOAT", PyFloat_FromDouble(G_MINFLOAT));
+ PyModule_AddObject(m, "G_MAXFLOAT", PyFloat_FromDouble(G_MAXFLOAT));
+ PyModule_AddObject(m, "G_MINDOUBLE", PyFloat_FromDouble(G_MINDOUBLE));
+ PyModule_AddObject(m, "G_MAXDOUBLE", PyFloat_FromDouble(G_MAXDOUBLE));
+ PyModule_AddIntConstant(m, "G_MINSHORT", G_MINSHORT);
+ PyModule_AddIntConstant(m, "G_MAXSHORT", G_MAXSHORT);
+ PyModule_AddIntConstant(m, "G_MAXUSHORT", G_MAXUSHORT);
+ PyModule_AddIntConstant(m, "G_MININT", G_MININT);
+ PyModule_AddIntConstant(m, "G_MAXINT", G_MAXINT);
+ PyModule_AddObject(m, "G_MAXUINT", PyLong_FromUnsignedLong(G_MAXUINT));
+ PyModule_AddObject(m, "G_MINLONG", PyLong_FromLong(G_MINLONG));
+ PyModule_AddObject(m, "G_MAXLONG", PyLong_FromLong(G_MAXLONG));
+ PyModule_AddObject(m, "G_MAXULONG", PyLong_FromUnsignedLong(G_MAXULONG));
+ PyModule_AddObject(m, "G_MAXSIZE", PyLong_FromSize_t(G_MAXSIZE));
+ PyModule_AddObject(m, "G_MAXSSIZE", PyLong_FromSsize_t(G_MAXSSIZE));
+ PyModule_AddObject(m, "G_MINSSIZE", PyLong_FromSsize_t(G_MINSSIZE));
+ PyModule_AddObject(m, "G_MINOFFSET", PyLong_FromLongLong(G_MINOFFSET));
+ PyModule_AddObject(m, "G_MAXOFFSET", PyLong_FromLongLong(G_MAXOFFSET));
+
+ PyModule_AddIntConstant(m, "SIGNAL_RUN_FIRST", G_SIGNAL_RUN_FIRST);
+ PyModule_AddIntConstant(m, "PARAM_READWRITE", G_PARAM_READWRITE);
+
+ /* The rest of the types are set in __init__.py */
+ PyModule_AddObject(m, "TYPE_INVALID", pyg_type_wrapper_new(G_TYPE_INVALID));
+ PyModule_AddObject(m, "TYPE_GSTRING", pyg_type_wrapper_new(G_TYPE_GSTRING));
+}
+
+static void
+pygobject_register_version_tuples(PyObject *d)
+{
+ PyObject *tuple;
+
+ /* pygobject version */
+ tuple = Py_BuildValue ("(iii)",
+ PYGOBJECT_MAJOR_VERSION,
+ PYGOBJECT_MINOR_VERSION,
+ PYGOBJECT_MICRO_VERSION);
+ PyDict_SetItemString(d, "pygobject_version", tuple);
+}
+
PYGLIB_MODULE_START(_gi, "_gi")
{
PyObject *api;
diff --git a/gi/gimodule.h b/gi/gimodule.h
new file mode 100644
index 00000000..7917ef6a
--- /dev/null
+++ b/gi/gimodule.h
@@ -0,0 +1,10 @@
+#ifndef _PYGOBJECT_GIMODULE_H_
+#define _PYGOBJECT_GIMODULE_H_
+
+#include "pygobject-internal.h"
+
+int pygobject_constructv (PyGObject *self,
+ guint n_parameters,
+ GParameter *parameters);
+
+#endif /*_PYGOBJECT_GIMODULE_H_*/
diff --git a/gi/gobjectmodule.c b/gi/gobjectmodule.c
deleted file mode 100644
index 5d89dcb7..00000000
--- a/gi/gobjectmodule.c
+++ /dev/null
@@ -1,1897 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pygtk- Python bindings for the GTK toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- *
- * gobjectmodule.c: wrapper for the gobject library.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include <Python.h>
-#include <gobject/gvaluecollector.h>
-#include <girepository.h>
-#include <pyglib.h>
-#include <pythread.h>
-#include "gobjectmodule.h"
-#include "pygboxed.h"
-#include "pygenum.h"
-#include "pygflags.h"
-#include "pyginterface.h"
-#include "pygparamspec.h"
-#include "pygpointer.h"
-#include "pygtype.h"
-#include "pygoptiongroup.h"
-#include "pygobject-object.h"
-
-#include "pygi-value.h"
-#include "pygi-error.h"
-#include "pygi-property.h"
-
-static GHashTable *log_handlers = NULL;
-static gboolean log_handlers_disabled = FALSE;
-
-static void pyg_flags_add_constants(PyObject *module, GType flags_type,
- const gchar *strip_prefix);
-
-static int pyg_type_register(PyTypeObject *class, const char *type_name);
-
-/* -------------- GDK threading hooks ---------------------------- */
-
-/**
- * pyg_set_thread_block_funcs:
- * Deprecated, only available for ABI compatibility.
- */
-static void
-_pyg_set_thread_block_funcs (PyGThreadBlockFunc block_threads_func,
- PyGThreadBlockFunc unblock_threads_func)
-{
- PyGILState_STATE state = PyGILState_Ensure ();
- PyErr_Warn (PyExc_DeprecationWarning,
- "Using pyg_set_thread_block_funcs is not longer needed. "
- "PyGObject always uses Py_BLOCK/UNBLOCK_THREADS.");
- PyGILState_Release (state);
-}
-
-/**
- * pyg_destroy_notify:
- * @user_data: a PyObject pointer.
- *
- * A function that can be used as a GDestroyNotify callback that will
- * call Py_DECREF on the data.
- */
-static void
-pyg_destroy_notify(gpointer user_data)
-{
- PyObject *obj = (PyObject *)user_data;
- PyGILState_STATE state;
-
- state = PyGILState_Ensure();
- Py_DECREF(obj);
- PyGILState_Release(state);
-}
-
-
-/* ---------------- gobject module functions -------------------- */
-
-static void
-pyg_object_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- PyObject *object_wrapper, *retval;
- PyObject *py_pspec, *py_value;
- PyGILState_STATE state;
-
- state = PyGILState_Ensure();
-
- object_wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
-
- if (object_wrapper)
- Py_INCREF (object_wrapper);
- else
- object_wrapper = pygobject_new(object);
-
- if (object_wrapper == NULL) {
- PyGILState_Release(state);
- return;
- }
-
- py_pspec = pyg_param_spec_new(pspec);
- py_value = pyg_value_as_pyobject (value, TRUE);
-
- retval = PyObject_CallMethod(object_wrapper, "do_set_property",
- "OO", py_pspec, py_value);
- if (retval) {
- Py_DECREF(retval);
- } else {
- PyErr_Print();
- }
-
- Py_DECREF(object_wrapper);
- Py_DECREF(py_pspec);
- Py_DECREF(py_value);
-
- PyGILState_Release(state);
-}
-
-static void
-pyg_object_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- PyObject *object_wrapper, *retval;
- PyGILState_STATE state;
-
- state = PyGILState_Ensure();
-
- object_wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
-
- if (object_wrapper)
- Py_INCREF (object_wrapper);
- else
- object_wrapper = pygobject_new(object);
-
- if (object_wrapper == NULL) {
- PyGILState_Release(state);
- return;
- }
-
- retval = pygi_call_do_get_property (object_wrapper, pspec);
- if (retval && pyg_value_from_pyobject (value, retval) < 0) {
- PyErr_Print();
- }
- Py_DECREF(object_wrapper);
- Py_XDECREF(retval);
-
- PyGILState_Release(state);
-}
-
-typedef struct _PyGSignalAccumulatorData {
- PyObject *callable;
- PyObject *user_data;
-} PyGSignalAccumulatorData;
-
-static gboolean
-_pyg_signal_accumulator(GSignalInvocationHint *ihint,
- GValue *return_accu,
- const GValue *handler_return,
- gpointer _data)
-{
- PyObject *py_ihint, *py_return_accu, *py_handler_return, *py_detail;
- PyObject *py_retval;
- gboolean retval = FALSE;
- PyGSignalAccumulatorData *data = _data;
- PyGILState_STATE state;
-
- state = PyGILState_Ensure();
- if (ihint->detail)
- py_detail = PYGLIB_PyUnicode_FromString(g_quark_to_string(ihint->detail));
- else {
- Py_INCREF(Py_None);
- py_detail = Py_None;
- }
-
- py_ihint = Py_BuildValue("lNi", (long int) ihint->signal_id,
- py_detail, ihint->run_type);
- py_handler_return = pyg_value_as_pyobject(handler_return, TRUE);
- py_return_accu = pyg_value_as_pyobject(return_accu, FALSE);
- if (data->user_data)
- py_retval = PyObject_CallFunction(data->callable, "NNNO", py_ihint,
- py_return_accu, py_handler_return,
- data->user_data);
- else
- py_retval = PyObject_CallFunction(data->callable, "NNN", py_ihint,
- py_return_accu, py_handler_return);
- if (!py_retval)
- PyErr_Print();
- else {
- if (!PyTuple_Check(py_retval) || PyTuple_Size(py_retval) != 2) {
- PyErr_SetString(PyExc_TypeError, "accumulator function must return"
- " a (bool, object) tuple");
- PyErr_Print();
- } else {
- retval = PyObject_IsTrue(PyTuple_GET_ITEM(py_retval, 0));
- if (pyg_value_from_pyobject(return_accu, PyTuple_GET_ITEM(py_retval, 1))) {
- PyErr_Print();
- }
- }
- Py_DECREF(py_retval);
- }
- PyGILState_Release(state);
- return retval;
-}
-
-static gboolean
-create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple)
-{
- GSignalFlags signal_flags;
- PyObject *py_return_type, *py_param_types;
- GType return_type;
- guint n_params, i;
- GType *param_types;
- guint signal_id;
- GSignalAccumulator accumulator = NULL;
- PyGSignalAccumulatorData *accum_data = NULL;
- PyObject *py_accum = NULL, *py_accum_data = NULL;
-
- if (!PyArg_ParseTuple(tuple, "iOO|OO", &signal_flags, &py_return_type,
- &py_param_types, &py_accum, &py_accum_data))
- {
- gchar buf[128];
-
- PyErr_Clear();
- g_snprintf(buf, sizeof(buf),
- "value for __gsignals__['%s'] not in correct format", signal_name);
- PyErr_SetString(PyExc_TypeError, buf);
- return FALSE;
- }
-
- if (py_accum && py_accum != Py_None && !PyCallable_Check(py_accum))
- {
- gchar buf[128];
-
- g_snprintf(buf, sizeof(buf),
- "accumulator for __gsignals__['%s'] must be callable", signal_name);
- PyErr_SetString(PyExc_TypeError, buf);
- return FALSE;
- }
-
- return_type = pyg_type_from_object(py_return_type);
- if (!return_type)
- return FALSE;
- if (!PySequence_Check(py_param_types)) {
- gchar buf[128];
-
- g_snprintf(buf, sizeof(buf),
- "third element of __gsignals__['%s'] tuple must be a sequence", signal_name);
- PyErr_SetString(PyExc_TypeError, buf);
- return FALSE;
- }
- n_params = PySequence_Length(py_param_types);
- param_types = g_new(GType, n_params);
- for (i = 0; i < n_params; i++) {
- PyObject *item = PySequence_GetItem(py_param_types, i);
-
- param_types[i] = pyg_type_from_object(item);
- if (param_types[i] == 0) {
- Py_DECREF(item);
- g_free(param_types);
- return FALSE;
- }
- Py_DECREF(item);
- }
-
- if (py_accum != NULL && py_accum != Py_None) {
- accum_data = g_new(PyGSignalAccumulatorData, 1);
- accum_data->callable = py_accum;
- Py_INCREF(py_accum);
- accum_data->user_data = py_accum_data;
- Py_XINCREF(py_accum_data);
- accumulator = _pyg_signal_accumulator;
- }
-
- signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
- pyg_signal_class_closure_get(),
- accumulator, accum_data,
- gi_cclosure_marshal_generic,
- return_type, n_params, param_types);
- g_free(param_types);
-
- if (signal_id == 0) {
- gchar buf[128];
-
- g_snprintf(buf, sizeof(buf), "could not create signal for %s",
- signal_name);
- PyErr_SetString(PyExc_RuntimeError, buf);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-override_signal(GType instance_type, const gchar *signal_name)
-{
- guint signal_id;
-
- signal_id = g_signal_lookup(signal_name, instance_type);
- if (!signal_id) {
- gchar buf[128];
-
- g_snprintf(buf, sizeof(buf), "could not look up %s", signal_name);
- PyErr_SetString(PyExc_TypeError, buf);
- return FALSE;
- }
- g_signal_override_class_closure(signal_id, instance_type,
- pyg_signal_class_closure_get());
- return TRUE;
-}
-
-static PyObject *
-add_signals (GObjectClass *klass, PyObject *signals)
-{
- gboolean ret = TRUE;
- Py_ssize_t pos = 0;
- PyObject *key, *value, *overridden_signals = NULL;
- GType instance_type = G_OBJECT_CLASS_TYPE (klass);
-
- overridden_signals = PyDict_New();
- while (PyDict_Next(signals, &pos, &key, &value)) {
- const gchar *signal_name;
- gchar *signal_name_canon, *c;
-
- if (!PYGLIB_PyUnicode_Check(key)) {
- PyErr_SetString(PyExc_TypeError,
- "__gsignals__ keys must be strings");
- ret = FALSE;
- break;
- }
- signal_name = PYGLIB_PyUnicode_AsString (key);
-
- if (value == Py_None ||
- (PYGLIB_PyUnicode_Check(value) &&
- !strcmp(PYGLIB_PyUnicode_AsString(value), "override")))
- {
- /* canonicalize signal name, replacing '-' with '_' */
- signal_name_canon = g_strdup(signal_name);
- for (c = signal_name_canon; *c; ++c)
- if (*c == '-')
- *c = '_';
- if (PyDict_SetItemString(overridden_signals,
- signal_name_canon, key)) {
- g_free(signal_name_canon);
- ret = FALSE;
- break;
- }
- g_free(signal_name_canon);
-
- ret = override_signal(instance_type, signal_name);
- } else {
- ret = create_signal(instance_type, signal_name, value);
- }
-
- if (!ret)
- break;
- }
- if (ret)
- return overridden_signals;
- else {
- Py_XDECREF(overridden_signals);
- return NULL;
- }
-}
-
-static GParamSpec *
-create_property (const gchar *prop_name,
- GType prop_type,
- const gchar *nick,
- const gchar *blurb,
- PyObject *args,
- GParamFlags flags)
-{
- GParamSpec *pspec = NULL;
-
- switch (G_TYPE_FUNDAMENTAL(prop_type)) {
- case G_TYPE_CHAR:
- {
- gchar minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_char (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_UCHAR:
- {
- gchar minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_uchar (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_BOOLEAN:
- {
- gboolean default_value;
-
- if (!PyArg_ParseTuple(args, "i", &default_value))
- return NULL;
- pspec = g_param_spec_boolean (prop_name, nick, blurb,
- default_value, flags);
- }
- break;
- case G_TYPE_INT:
- {
- gint minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "iii", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_int (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_UINT:
- {
- guint minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "III", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_uint (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_LONG:
- {
- glong minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "lll", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_long (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_ULONG:
- {
- gulong minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "kkk", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_ulong (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_INT64:
- {
- gint64 minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "LLL", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_int64 (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_UINT64:
- {
- guint64 minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "KKK", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_uint64 (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_ENUM:
- {
- gint default_value;
- PyObject *pydefault;
-
- if (!PyArg_ParseTuple(args, "O", &pydefault))
- return NULL;
-
- if (pyg_enum_get_value(prop_type, pydefault,
- (gint *)&default_value))
- return NULL;
-
- pspec = g_param_spec_enum (prop_name, nick, blurb,
- prop_type, default_value, flags);
- }
- break;
- case G_TYPE_FLAGS:
- {
- guint default_value;
- PyObject *pydefault;
-
- if (!PyArg_ParseTuple(args, "O", &pydefault))
- return NULL;
-
- if (pyg_flags_get_value(prop_type, pydefault,
- &default_value))
- return NULL;
-
- pspec = g_param_spec_flags (prop_name, nick, blurb,
- prop_type, default_value, flags);
- }
- break;
- case G_TYPE_FLOAT:
- {
- gfloat minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "fff", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_float (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_DOUBLE:
- {
- gdouble minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "ddd", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_double (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_STRING:
- {
- const gchar *default_value;
-
- if (!PyArg_ParseTuple(args, "z", &default_value))
- return NULL;
- pspec = g_param_spec_string (prop_name, nick, blurb,
- default_value, flags);
- }
- break;
- case G_TYPE_PARAM:
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- pspec = g_param_spec_param (prop_name, nick, blurb, prop_type, flags);
- break;
- case G_TYPE_BOXED:
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- pspec = g_param_spec_boxed (prop_name, nick, blurb, prop_type, flags);
- break;
- case G_TYPE_POINTER:
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- if (prop_type == G_TYPE_GTYPE)
- pspec = g_param_spec_gtype (prop_name, nick, blurb, G_TYPE_NONE, flags);
- else
- pspec = g_param_spec_pointer (prop_name, nick, blurb, flags);
- break;
- case G_TYPE_OBJECT:
- case G_TYPE_INTERFACE:
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- pspec = g_param_spec_object (prop_name, nick, blurb, prop_type, flags);
- break;
- case G_TYPE_VARIANT:
- {
- PyObject *pydefault;
- GVariant *default_value = NULL;
-
- if (!PyArg_ParseTuple(args, "O", &pydefault))
- return NULL;
- if (pydefault != Py_None)
- default_value = pyg_boxed_get (pydefault, GVariant);
- pspec = g_param_spec_variant (prop_name, nick, blurb, G_VARIANT_TYPE_ANY, default_value, flags);
- }
- break;
- default:
- /* unhandled pspec type ... */
- break;
- }
-
- if (!pspec) {
- char buf[128];
-
- g_snprintf(buf, sizeof(buf), "could not create param spec for type %s",
- g_type_name(prop_type));
- PyErr_SetString(PyExc_TypeError, buf);
- return NULL;
- }
-
- return pspec;
-}
-
-static GParamSpec *
-pyg_param_spec_from_object (PyObject *tuple)
-{
- gint val_length;
- const gchar *prop_name;
- GType prop_type;
- const gchar *nick, *blurb;
- PyObject *slice, *item, *py_prop_type;
- GParamSpec *pspec;
-
- val_length = PyTuple_Size(tuple);
- if (val_length < 4) {
- PyErr_SetString(PyExc_TypeError,
- "paramspec tuples must be at least 4 elements long");
- return NULL;
- }
-
- slice = PySequence_GetSlice(tuple, 0, 4);
- if (!slice) {
- return NULL;
- }
-
- if (!PyArg_ParseTuple(slice, "sOzz", &prop_name, &py_prop_type, &nick, &blurb)) {
- Py_DECREF(slice);
- return NULL;
- }
-
- Py_DECREF(slice);
-
- prop_type = pyg_type_from_object(py_prop_type);
- if (!prop_type) {
- return NULL;
- }
-
- item = PyTuple_GetItem(tuple, val_length-1);
- if (!PYGLIB_PyLong_Check(item)) {
- PyErr_SetString(PyExc_TypeError,
- "last element in tuple must be an int");
- return NULL;
- }
-
- /* slice is the extra items in the tuple */
- slice = PySequence_GetSlice(tuple, 4, val_length-1);
- pspec = create_property(prop_name, prop_type,
- nick, blurb, slice,
- PYGLIB_PyLong_AsLong(item));
-
- return pspec;
-}
-
-static gboolean
-add_properties (GObjectClass *klass, PyObject *properties)
-{
- gboolean ret = TRUE;
- Py_ssize_t pos = 0;
- PyObject *key, *value;
-
- while (PyDict_Next(properties, &pos, &key, &value)) {
- const gchar *prop_name;
- GType prop_type;
- const gchar *nick, *blurb;
- GParamFlags flags;
- gint val_length;
- PyObject *slice, *item, *py_prop_type;
- GParamSpec *pspec;
-
- /* values are of format (type,nick,blurb, type_specific_args, flags) */
-
- if (!PYGLIB_PyUnicode_Check(key)) {
- PyErr_SetString(PyExc_TypeError,
- "__gproperties__ keys must be strings");
- ret = FALSE;
- break;
- }
- prop_name = PYGLIB_PyUnicode_AsString (key);
-
- if (!PyTuple_Check(value)) {
- PyErr_SetString(PyExc_TypeError,
- "__gproperties__ values must be tuples");
- ret = FALSE;
- break;
- }
- val_length = PyTuple_Size(value);
- if (val_length < 4) {
- PyErr_SetString(PyExc_TypeError,
- "__gproperties__ values must be at least 4 elements long");
- ret = FALSE;
- break;
- }
-
- slice = PySequence_GetSlice(value, 0, 3);
- if (!slice) {
- ret = FALSE;
- break;
- }
- if (!PyArg_ParseTuple(slice, "Ozz", &py_prop_type, &nick, &blurb)) {
- Py_DECREF(slice);
- ret = FALSE;
- break;
- }
- Py_DECREF(slice);
- prop_type = pyg_type_from_object(py_prop_type);
- if (!prop_type) {
- ret = FALSE;
- break;
- }
- item = PyTuple_GetItem(value, val_length-1);
- if (!PYGLIB_PyLong_Check(item)) {
- PyErr_SetString(PyExc_TypeError,
- "last element in __gproperties__ value tuple must be an int");
- ret = FALSE;
- break;
- }
- flags = PYGLIB_PyLong_AsLong(item);
-
- /* slice is the extra items in the tuple */
- slice = PySequence_GetSlice(value, 3, val_length-1);
- pspec = create_property(prop_name, prop_type, nick, blurb,
- slice, flags);
- Py_DECREF(slice);
-
- if (pspec) {
- g_object_class_install_property(klass, 1, pspec);
- } else {
- PyObject *type, *pvalue, *traceback;
- ret = FALSE;
- PyErr_Fetch(&type, &pvalue, &traceback);
- if (PYGLIB_PyUnicode_Check(pvalue)) {
- char msg[256];
- g_snprintf(msg, 256,
- "%s (while registering property '%s' for GType '%s')",
- PYGLIB_PyUnicode_AsString(pvalue),
- prop_name, G_OBJECT_CLASS_NAME(klass));
- Py_DECREF(pvalue);
- value = PYGLIB_PyUnicode_FromString(msg);
- }
- PyErr_Restore(type, pvalue, traceback);
- break;
- }
- }
-
- return ret;
-}
-
-static void
-pyg_object_class_init(GObjectClass *class, PyObject *py_class)
-{
- PyObject *gproperties, *gsignals, *overridden_signals;
- PyObject *class_dict = ((PyTypeObject*) py_class)->tp_dict;
-
- class->set_property = pyg_object_set_property;
- class->get_property = pyg_object_get_property;
-
- /* install signals */
- /* we look this up in the instance dictionary, so we don't
- * accidentally get a parent type's __gsignals__ attribute. */
- gsignals = PyDict_GetItemString(class_dict, "__gsignals__");
- if (gsignals) {
- if (!PyDict_Check(gsignals)) {
- PyErr_SetString(PyExc_TypeError,
- "__gsignals__ attribute not a dict!");
- return;
- }
- if (!(overridden_signals = add_signals(class, gsignals))) {
- return;
- }
- if (PyDict_SetItemString(class_dict, "__gsignals__",
- overridden_signals)) {
- return;
- }
- Py_DECREF(overridden_signals);
-
- PyDict_DelItemString(class_dict, "__gsignals__");
- } else {
- PyErr_Clear();
- }
-
- /* install properties */
- /* we look this up in the instance dictionary, so we don't
- * accidentally get a parent type's __gproperties__ attribute. */
- gproperties = PyDict_GetItemString(class_dict, "__gproperties__");
- if (gproperties) {
- if (!PyDict_Check(gproperties)) {
- PyErr_SetString(PyExc_TypeError,
- "__gproperties__ attribute not a dict!");
- return;
- }
- if (!add_properties(class, gproperties)) {
- return;
- }
- PyDict_DelItemString(class_dict, "__gproperties__");
- /* Borrowed reference. Py_DECREF(gproperties); */
- } else {
- PyErr_Clear();
- }
-}
-
-static void
-pyg_register_class_init(GType gtype, PyGClassInitFunc class_init)
-{
- GSList *list;
-
- list = g_type_get_qdata(gtype, pygobject_class_init_key);
- list = g_slist_prepend(list, class_init);
- g_type_set_qdata(gtype, pygobject_class_init_key, list);
-}
-
-static int
-pyg_run_class_init(GType gtype, gpointer gclass, PyTypeObject *pyclass)
-{
- GSList *list;
- PyGClassInitFunc class_init;
- GType parent_type;
- int rv;
-
- parent_type = g_type_parent(gtype);
- if (parent_type) {
- rv = pyg_run_class_init(parent_type, gclass, pyclass);
- if (rv)
- return rv;
- }
-
- list = g_type_get_qdata(gtype, pygobject_class_init_key);
- for (; list; list = list->next) {
- class_init = list->data;
- rv = class_init(gclass, pyclass);
- if (rv)
- return rv;
- }
-
- return 0;
-}
-
-PyObject *
-_wrap_pyg_type_register(PyObject *self, PyObject *args)
-{
- PyTypeObject *class;
- char *type_name = NULL;
-
- if (!PyArg_ParseTuple(args, "O!|z:gobject.type_register",
- &PyType_Type, &class, &type_name))
- return NULL;
- if (!PyType_IsSubtype(class, &PyGObject_Type)) {
- PyErr_SetString(PyExc_TypeError,
- "argument must be a GObject subclass");
- return NULL;
- }
-
- /* Check if type already registered */
- if (pyg_type_from_object((PyObject *) class) ==
- pyg_type_from_object((PyObject *) class->tp_base))
- {
- if (pyg_type_register(class, type_name))
- return NULL;
- }
-
- Py_INCREF(class);
- return (PyObject *) class;
-}
-
-static char *
-get_type_name_for_class(PyTypeObject *class)
-{
- gint i, name_serial;
- char name_serial_str[16];
- PyObject *module;
- char *type_name = NULL;
-
- /* make name for new GType */
- name_serial = 1;
- /* give up after 1000 tries, just in case.. */
- while (name_serial < 1000)
- {
- g_free(type_name);
- g_snprintf(name_serial_str, 16, "-v%i", name_serial);
- module = PyObject_GetAttrString((PyObject *)class, "__module__");
- if (module && PYGLIB_PyUnicode_Check(module)) {
- type_name = g_strconcat(PYGLIB_PyUnicode_AsString(module), ".",
- class->tp_name,
- name_serial > 1 ? name_serial_str : NULL,
- NULL);
- Py_DECREF(module);
- } else {
- if (module)
- Py_DECREF(module);
- else
- PyErr_Clear();
- type_name = g_strconcat(class->tp_name,
- name_serial > 1 ? name_serial_str : NULL,
- NULL);
- }
- /* convert '.' in type name to '+', which isn't banned (grumble) */
- for (i = 0; type_name[i] != '\0'; i++)
- if (type_name[i] == '.')
- type_name[i] = '+';
- if (g_type_from_name(type_name) == 0)
- break; /* we now have a unique name */
- ++name_serial;
- }
-
- return type_name;
-}
-
-
-static GPrivate pygobject_construction_wrapper;
-
-static inline void
-pygobject_init_wrapper_set(PyObject *wrapper)
-{
- g_private_set(&pygobject_construction_wrapper, wrapper);
-}
-
-static inline PyObject *
-pygobject_init_wrapper_get(void)
-{
- return (PyObject *) g_private_get(&pygobject_construction_wrapper);
-}
-
-int
-pygobject_constructv(PyGObject *self,
- guint n_parameters,
- GParameter *parameters)
-{
- 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
- if (g_object_is_floating (obj))
- self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
- pygobject_sink (obj);
-
- pygobject_init_wrapper_set(NULL);
- self->obj = obj;
- pygobject_register_wrapper((PyObject *) self);
-
- return 0;
-}
-
-static void
-pygobject__g_instance_init(GTypeInstance *instance,
- gpointer g_class)
-{
- GObject *object = (GObject *) instance;
- PyObject *wrapper, *args, *kwargs;
-
- wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
- if (wrapper == NULL) {
- wrapper = pygobject_init_wrapper_get();
- if (wrapper && ((PyGObject *) wrapper)->obj == NULL) {
- ((PyGObject *) wrapper)->obj = object;
- pygobject_register_wrapper(wrapper);
- }
- }
- pygobject_init_wrapper_set(NULL);
- if (wrapper == NULL) {
- /* this looks like a python object created through
- * g_object_new -> we have no python wrapper, so create it
- * now */
- PyGILState_STATE state;
- state = PyGILState_Ensure();
- wrapper = pygobject_new_full(object,
- /*steal=*/ FALSE,
- g_class);
-
- /* float the wrapper ref here because we are going to orphan it
- * so we don't destroy the wrapper. The next call to pygobject_new_full
- * will take the ref */
- pygobject_ref_float ((PyGObject *) wrapper);
- args = PyTuple_New(0);
- kwargs = PyDict_New();
- if (Py_TYPE(wrapper)->tp_init(wrapper, args, kwargs))
- PyErr_Print();
-
- Py_DECREF(args);
- Py_DECREF(kwargs);
- PyGILState_Release(state);
- }
-}
-
-
-/* This implementation is bad, see bug 566571 for an example why.
- * Instead of scanning explicitly declared bases for interfaces, we
- * should automatically initialize all implemented interfaces to
- * prevent bugs like that one. However, this will lead to
- * performance degradation as each virtual method in derived classes
- * will round-trip through do_*() stuff, *even* if it is not
- * overriden. We need to teach codegen to retain parent method
- * instead of setting virtual to *_proxy_do_*() if corresponding
- * do_*() is not overriden. Ok, that was a messy explanation.
- */
-static void
-pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
- PyObject *bases,
- GType *parent_interfaces, guint n_parent_interfaces)
-{
- int i;
-
- if (!bases) {
- g_warning("type has no bases");
- return;
- }
-
- for (i = 0; i < PyTuple_GET_SIZE(bases); ++i) {
- PyObject *base = PyTuple_GET_ITEM(bases, i);
- GType itype;
- const GInterfaceInfo *iinfo;
- GInterfaceInfo iinfo_copy;
-
- /* 'base' can also be a PyClassObject, see bug #566571. */
- if (!PyType_Check(base))
- continue;
-
- if (!PyType_IsSubtype((PyTypeObject*) base, &PyGInterface_Type))
- continue;
-
- itype = pyg_type_from_object(base);
-
- /* Happens for _implementations_ of an interface. */
- if (!G_TYPE_IS_INTERFACE(itype))
- continue;
-
- iinfo = pyg_lookup_interface_info(itype);
- if (!iinfo) {
- gchar *error;
- error = g_strdup_printf("Interface type %s "
- "has no Python implementation support",
- ((PyTypeObject *) base)->tp_name);
- PyErr_Warn(PyExc_RuntimeWarning, error);
- g_free(error);
- continue;
- }
-
- iinfo_copy = *iinfo;
- iinfo_copy.interface_data = class;
- g_type_add_interface_static(instance_type, itype, &iinfo_copy);
- }
-}
-
-static int
-pyg_type_register(PyTypeObject *class, const char *type_name)
-{
- PyObject *gtype;
- GType parent_type, instance_type;
- GType *parent_interfaces;
- guint n_parent_interfaces;
- GTypeQuery query;
- gpointer gclass;
- GTypeInfo type_info = {
- 0, /* class_size */
-
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
-
- (GClassInitFunc) pyg_object_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
-
- 0, /* instance_size */
- 0, /* n_preallocs */
- (GInstanceInitFunc) pygobject__g_instance_init
- };
- gchar *new_type_name;
-
- /* find the GType of the parent */
- parent_type = pyg_type_from_object((PyObject *)class);
- if (!parent_type)
- return -1;
-
- parent_interfaces = g_type_interfaces(parent_type, &n_parent_interfaces);
-
- if (type_name)
- /* care is taken below not to free this */
- new_type_name = (gchar *) type_name;
- else
- new_type_name = get_type_name_for_class(class);
-
- /* set class_data that will be passed to the class_init function. */
- type_info.class_data = class;
-
- /* fill in missing values of GTypeInfo struct */
- g_type_query(parent_type, &query);
- type_info.class_size = query.class_size;
- type_info.instance_size = query.instance_size;
-
- /* create new typecode */
- instance_type = g_type_register_static(parent_type, new_type_name,
- &type_info, 0);
- if (instance_type == 0) {
- PyErr_Format(PyExc_RuntimeError,
- "could not create new GType: %s (subclass of %s)",
- new_type_name,
- g_type_name(parent_type));
-
- if (type_name == NULL)
- g_free(new_type_name);
-
- return -1;
- }
-
- if (type_name == NULL)
- g_free(new_type_name);
-
- /* store pointer to the class with the GType */
- Py_INCREF(class);
- g_type_set_qdata(instance_type, g_quark_from_string("PyGObject::class"),
- class);
-
- /* Mark this GType as a custom python type */
- g_type_set_qdata(instance_type, pygobject_custom_key,
- GINT_TO_POINTER (1));
-
- /* set new value of __gtype__ on class */
- gtype = pyg_type_wrapper_new(instance_type);
- PyObject_SetAttrString((PyObject *)class, "__gtype__", gtype);
- Py_DECREF(gtype);
-
- /* if no __doc__, set it to the auto doc descriptor */
- if (PyDict_GetItemString(class->tp_dict, "__doc__") == NULL) {
- PyDict_SetItemString(class->tp_dict, "__doc__",
- pyg_object_descr_doc_get());
- }
-
- /*
- * Note, all interfaces need to be registered before the first
- * g_type_class_ref(), see bug #686149.
- *
- * See also comment above pyg_type_add_interfaces().
- */
- pyg_type_add_interfaces(class, instance_type, class->tp_bases,
- parent_interfaces, n_parent_interfaces);
-
-
- gclass = g_type_class_ref(instance_type);
- if (PyErr_Occurred() != NULL) {
- g_type_class_unref(gclass);
- g_free(parent_interfaces);
- return -1;
- }
-
- if (pyg_run_class_init(instance_type, gclass, class)) {
- g_type_class_unref(gclass);
- g_free(parent_interfaces);
- return -1;
- }
- g_type_class_unref(gclass);
- g_free(parent_interfaces);
-
- if (PyErr_Occurred() != NULL)
- return -1;
- return 0;
-}
-
-PyObject *
-pyg_signal_new(PyObject *self, PyObject *args)
-{
- gchar *signal_name;
- PyObject *py_type;
- GSignalFlags signal_flags;
- GType return_type;
- PyObject *py_return_type, *py_param_types;
-
- GType instance_type = 0;
- Py_ssize_t n_params, i;
- GType *param_types;
-
- guint signal_id;
-
- if (!PyArg_ParseTuple(args, "sOiOO:gobject.signal_new", &signal_name,
- &py_type, &signal_flags, &py_return_type,
- &py_param_types))
- return NULL;
-
- instance_type = pyg_type_from_object(py_type);
- if (!instance_type)
- return NULL;
- if (!(G_TYPE_IS_INSTANTIATABLE(instance_type) || G_TYPE_IS_INTERFACE(instance_type))) {
- PyErr_SetString(PyExc_TypeError,
- "argument 2 must be an object type or interface type");
- return NULL;
- }
-
- return_type = pyg_type_from_object(py_return_type);
- if (!return_type)
- return NULL;
-
- if (!PySequence_Check(py_param_types)) {
- PyErr_SetString(PyExc_TypeError,
- "argument 5 must be a sequence of GType codes");
- return NULL;
- }
- n_params = PySequence_Length(py_param_types);
- param_types = g_new(GType, n_params);
- for (i = 0; i < n_params; i++) {
- PyObject *item = PySequence_GetItem(py_param_types, i);
-
- param_types[i] = pyg_type_from_object(item);
- if (param_types[i] == 0) {
- PyErr_Clear();
- Py_DECREF(item);
- PyErr_SetString(PyExc_TypeError,
- "argument 5 must be a sequence of GType codes");
- g_free(param_types);
- return NULL;
- }
- Py_DECREF(item);
- }
-
- signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
- pyg_signal_class_closure_get(),
- (GSignalAccumulator)0, NULL,
- (GSignalCMarshaller)0,
- return_type, n_params, param_types);
- g_free(param_types);
- if (signal_id != 0)
- return PYGLIB_PyLong_FromLong(signal_id);
- PyErr_SetString(PyExc_RuntimeError, "could not create signal");
- return NULL;
-}
-
-PyObject *
-pyg_object_class_list_properties (PyObject *self, PyObject *args)
-{
- GParamSpec **specs;
- PyObject *py_itype, *list;
- GType itype;
- GObjectClass *class = NULL;
- gpointer iface = NULL;
- guint nprops;
- guint i;
-
- if (!PyArg_ParseTuple(args, "O:gobject.list_properties",
- &py_itype))
- return NULL;
- if ((itype = pyg_type_from_object(py_itype)) == 0)
- return NULL;
-
- if (G_TYPE_IS_INTERFACE(itype)) {
- iface = g_type_default_interface_ref(itype);
- if (!iface) {
- PyErr_SetString(PyExc_RuntimeError,
- "could not get a reference to interface type");
- return NULL;
- }
- specs = g_object_interface_list_properties(iface, &nprops);
- } else if (g_type_is_a(itype, G_TYPE_OBJECT)) {
- class = g_type_class_ref(itype);
- if (!class) {
- PyErr_SetString(PyExc_RuntimeError,
- "could not get a reference to type class");
- return NULL;
- }
- specs = g_object_class_list_properties(class, &nprops);
- } else {
- PyErr_SetString(PyExc_TypeError,
- "type must be derived from GObject or an interface");
- return NULL;
- }
-
- list = PyTuple_New(nprops);
- if (list == NULL) {
- g_free(specs);
- g_type_class_unref(class);
- return NULL;
- }
- for (i = 0; i < nprops; i++) {
- PyTuple_SetItem(list, i, pyg_param_spec_new(specs[i]));
- }
- g_free(specs);
- if (class)
- g_type_class_unref(class);
- else
- g_type_default_interface_unref(iface);
-
- return list;
-}
-
-PyObject *
-pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
-{
- PyObject *pytype;
- GType type;
- GObject *obj = NULL;
- GObjectClass *class;
- guint n_params = 0, i;
- GParameter *params = NULL;
-
- if (!PyArg_ParseTuple (args, "O:gobject.new", &pytype)) {
- return NULL;
- }
-
- if ((type = pyg_type_from_object (pytype)) == 0)
- return NULL;
-
- if (G_TYPE_IS_ABSTRACT(type)) {
- PyErr_Format(PyExc_TypeError, "cannot create instance of abstract "
- "(non-instantiable) type `%s'", g_type_name(type));
- return NULL;
- }
-
- if ((class = g_type_class_ref (type)) == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "could not get a reference to type class");
- return NULL;
- }
-
- if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
- goto cleanup;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- obj = g_object_newv(type, n_params, params);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- 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);
- }
- g_free(params);
- g_type_class_unref(class);
-
- if (obj) {
- pygobject_sink (obj);
- self = (PyGObject *) pygobject_new((GObject *)obj);
- g_object_unref(obj);
- } else
- self = NULL;
-
- return (PyObject *) self;
-}
-
-static int
-pygobject_gil_state_ensure (void)
-{
- return PyGILState_Ensure ();
-}
-
-static void
-pygobject_gil_state_release (int flag)
-{
- PyGILState_Release(flag);
-}
-
-/* Only for backwards compatibility */
-static int
-pygobject_enable_threads(void)
-{
- return 0;
-}
-
-static gboolean
-marshal_emission_hook(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue *param_values,
- gpointer user_data)
-{
- PyGILState_STATE state;
- gboolean retval = FALSE;
- PyObject *func, *args;
- PyObject *retobj;
- PyObject *params;
- guint i;
-
- state = PyGILState_Ensure();
-
- /* construct Python tuple for the parameter values */
- params = PyTuple_New(n_param_values);
-
- for (i = 0; i < n_param_values; i++) {
- PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
-
- /* error condition */
- if (!item) {
- goto out;
- }
- PyTuple_SetItem(params, i, item);
- }
-
- args = (PyObject *)user_data;
- func = PyTuple_GetItem(args, 0);
- args = PySequence_Concat(params, PyTuple_GetItem(args, 1));
- Py_DECREF(params);
-
- /* params passed to function may have extra arguments */
-
- retobj = PyObject_CallObject(func, args);
- Py_DECREF(args);
- if (retobj == NULL) {
- PyErr_Print();
- }
-
- retval = (retobj == Py_True ? TRUE : FALSE);
- Py_XDECREF(retobj);
-out:
- PyGILState_Release(state);
- return retval;
-}
-
-PyObject *
-pyg_add_emission_hook(PyGObject *self, PyObject *args)
-{
- PyObject *first, *callback, *extra_args, *data, *repr;
- gchar *name;
- gulong hook_id;
- guint sigid;
- Py_ssize_t len;
- GQuark detail = 0;
- GType gtype;
- PyObject *pygtype;
-
- len = PyTuple_Size(args);
- if (len < 3) {
- PyErr_SetString(PyExc_TypeError,
- "gobject.add_emission_hook requires at least 3 arguments");
- return NULL;
- }
- first = PySequence_GetSlice(args, 0, 3);
- if (!PyArg_ParseTuple(first, "OsO:add_emission_hook",
- &pygtype, &name, &callback)) {
- Py_DECREF(first);
- return NULL;
- }
- Py_DECREF(first);
-
- if ((gtype = pyg_type_from_object(pygtype)) == 0) {
- return NULL;
- }
- if (!PyCallable_Check(callback)) {
- PyErr_SetString(PyExc_TypeError, "third argument must be callable");
- return NULL;
- }
-
- if (!g_signal_parse_name(name, gtype, &sigid, &detail, TRUE)) {
- repr = PyObject_Repr((PyObject*)self);
- PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- PYGLIB_PyUnicode_AsString(repr),
- name);
- Py_DECREF(repr);
- return NULL;
- }
- extra_args = PySequence_GetSlice(args, 3, len);
- if (extra_args == NULL)
- return NULL;
-
- data = Py_BuildValue("(ON)", callback, extra_args);
- if (data == NULL)
- return NULL;
-
- hook_id = g_signal_add_emission_hook(sigid, detail,
- marshal_emission_hook,
- data,
- (GDestroyNotify)pyg_destroy_notify);
-
- return PyLong_FromUnsignedLong(hook_id);
-}
-
-PyObject *
-pyg__install_metaclass(PyObject *dummy, PyTypeObject *metaclass)
-{
- Py_INCREF(metaclass);
- PyGObject_MetaType = metaclass;
- Py_INCREF(metaclass);
-
- Py_TYPE(&PyGObject_Type) = metaclass;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-PyObject *
-pyg__gvalue_get(PyObject *module, PyObject *pygvalue)
-{
- if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
- PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
- return NULL;
- }
-
- return pyg_value_as_pyobject (pyg_boxed_get(pygvalue, GValue),
- /*copy_boxed=*/ TRUE);
-}
-
-PyObject *
-pyg__gvalue_set(PyObject *module, PyObject *args)
-{
- PyObject *pygvalue;
- PyObject *pyobject;
-
- if (!PyArg_ParseTuple (args, "OO:_gi._gvalue_set",
- &pygvalue, &pyobject))
- return NULL;
-
- if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
- PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
- return NULL;
- }
-
- if (pyg_value_from_pyobject_with_error (pyg_boxed_get (pygvalue, GValue),
- pyobject) == -1)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-
-/* ----------------- Constant extraction ------------------------ */
-
-/**
- * pyg_constant_strip_prefix:
- * @name: the constant name.
- * @strip_prefix: the prefix to strip.
- *
- * Advances the pointer @name by strlen(@strip_prefix) characters. If
- * the resulting name does not start with a letter or underscore, the
- * @name pointer will be rewound. This is to ensure that the
- * resulting name is a valid identifier. Hence the returned string is
- * a pointer into the string @name.
- *
- * Returns: the stripped constant name.
- */
-const gchar *
-pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix)
-{
- size_t prefix_len;
- guint i;
-
- prefix_len = strlen(strip_prefix);
-
- /* Check so name starts with strip_prefix, if it doesn't:
- * return the rest of the part which doesn't match
- */
- for (i = 0; i < prefix_len; i++) {
- if (name[i] != strip_prefix[i] && name[i] != '_') {
- return &name[i];
- }
- }
-
- /* strip off prefix from value name, while keeping it a valid
- * identifier */
- for (i = prefix_len + 1; i > 0; i--) {
- if (g_ascii_isalpha(name[i - 1]) || name[i - 1] == '_') {
- return &name[i - 1];
- }
- }
- return name;
-}
-
-/**
- * pyg_enum_add_constants:
- * @module: a Python module
- * @enum_type: the GType of the enumeration.
- * @strip_prefix: the prefix to strip from the constant names.
- *
- * Adds constants to the given Python module for each value name of
- * the enumeration. A prefix will be stripped from each enum name.
- */
-static void
-pyg_enum_add_constants(PyObject *module, GType enum_type,
- const gchar *strip_prefix)
-{
- GEnumClass *eclass;
- guint i;
-
- if (!G_TYPE_IS_ENUM(enum_type)) {
- if (G_TYPE_IS_FLAGS(enum_type)) /* See bug #136204 */
- pyg_flags_add_constants(module, enum_type, strip_prefix);
- else
- g_warning("`%s' is not an enum type", g_type_name(enum_type));
- return;
- }
- g_return_if_fail (strip_prefix != NULL);
-
- eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
-
- for (i = 0; i < eclass->n_values; i++) {
- const gchar *name = eclass->values[i].value_name;
- gint value = eclass->values[i].value;
-
- PyModule_AddIntConstant(module,
- (char*) pyg_constant_strip_prefix(name, strip_prefix),
- (long) value);
- }
-
- g_type_class_unref(eclass);
-}
-
-/**
- * pyg_flags_add_constants:
- * @module: a Python module
- * @flags_type: the GType of the flags type.
- * @strip_prefix: the prefix to strip from the constant names.
- *
- * Adds constants to the given Python module for each value name of
- * the flags set. A prefix will be stripped from each flag name.
- */
-static void
-pyg_flags_add_constants(PyObject *module, GType flags_type,
- const gchar *strip_prefix)
-{
- GFlagsClass *fclass;
- guint i;
-
- if (!G_TYPE_IS_FLAGS(flags_type)) {
- if (G_TYPE_IS_ENUM(flags_type)) /* See bug #136204 */
- pyg_enum_add_constants(module, flags_type, strip_prefix);
- else
- g_warning("`%s' is not an flags type", g_type_name(flags_type));
- return;
- }
- g_return_if_fail (strip_prefix != NULL);
-
- fclass = G_FLAGS_CLASS(g_type_class_ref(flags_type));
-
- for (i = 0; i < fclass->n_values; i++) {
- const gchar *name = fclass->values[i].value_name;
- guint value = fclass->values[i].value;
-
- PyModule_AddIntConstant(module,
- (char*) pyg_constant_strip_prefix(name, strip_prefix),
- (long) value);
- }
-
- g_type_class_unref(fclass);
-}
-
-/**
- * pyg_parse_constructor_args: helper function for PyGObject constructors
- * @obj_type: GType of the GObject, for parameter introspection
- * @arg_names: %NULL-terminated array of constructor argument names
- * @prop_names: %NULL-terminated array of property names, with direct
- * correspondence to @arg_names
- * @params: GParameter array where parameters will be placed; length
- * of this array must be at least equal to the number of
- * arguments/properties
- * @nparams: output parameter to contain actual number of arguments found
- * @py_args: array of PyObject* containing the actual constructor arguments
- *
- * Parses an array of PyObject's and creates a GParameter array
- *
- * Return value: %TRUE if all is successful, otherwise %FALSE and
- * python exception set.
- **/
-static gboolean
-pyg_parse_constructor_args(GType obj_type,
- char **arg_names,
- char **prop_names,
- GParameter *params,
- guint *nparams,
- PyObject **py_args)
-{
- guint arg_i, param_i;
- GObjectClass *oclass;
-
- oclass = g_type_class_ref(obj_type);
- g_return_val_if_fail(oclass, FALSE);
-
- for (param_i = arg_i = 0; arg_names[arg_i]; ++arg_i) {
- GParamSpec *spec;
- if (!py_args[arg_i])
- continue;
- spec = g_object_class_find_property(oclass, prop_names[arg_i]);
- params[param_i].name = prop_names[arg_i];
- g_value_init(&params[param_i].value, spec->value_type);
- if (pyg_value_from_pyobject(&params[param_i].value, py_args[arg_i]) == -1) {
- guint i;
- PyErr_Format(PyExc_TypeError, "could not convert parameter '%s' of type '%s'",
- arg_names[arg_i], g_type_name(spec->value_type));
- g_type_class_unref(oclass);
- for (i = 0; i < param_i; ++i)
- g_value_unset(&params[i].value);
- return FALSE;
- }
- ++param_i;
- }
- g_type_class_unref(oclass);
- *nparams = param_i;
- return TRUE;
-}
-
-static void
-_log_func(const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer user_data)
-{
- if (G_LIKELY(Py_IsInitialized()))
- {
- PyGILState_STATE state;
- PyObject* warning = user_data;
-
- state = PyGILState_Ensure();
- PyErr_Warn(warning, (char *) message);
- PyGILState_Release(state);
- } else
- g_log_default_handler(log_domain, log_level, message, user_data);
-}
-
-static void
-add_warning_redirection(const char *domain,
- PyObject *warning)
-{
- g_return_if_fail(domain != NULL);
- g_return_if_fail(warning != NULL);
-
- if (!log_handlers_disabled)
- {
- guint handler;
- gpointer old_handler;
-
- if (!log_handlers)
- log_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
- if ((old_handler = g_hash_table_lookup(log_handlers, domain)))
- g_log_remove_handler(domain, GPOINTER_TO_UINT(old_handler));
-
- handler = g_log_set_handler(domain, G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING,
- _log_func, warning);
- g_hash_table_insert(log_handlers, g_strdup(domain), GUINT_TO_POINTER(handler));
- }
-}
-
-static void
-remove_handler(gpointer domain,
- gpointer handler,
- gpointer unused)
-{
- g_log_remove_handler(domain, GPOINTER_TO_UINT(handler));
-}
-
-static void
-disable_warning_redirections(void)
-{
- log_handlers_disabled = TRUE;
-
- if (log_handlers)
- {
- g_hash_table_foreach(log_handlers, remove_handler, NULL);
- g_hash_table_destroy(log_handlers);
- log_handlers = NULL;
- }
-}
-
-/* ----------------- gobject module initialisation -------------- */
-
-struct _PyGObject_Functions pygobject_api_functions = {
- pygobject_register_class,
- pygobject_register_wrapper,
- pygobject_lookup_class,
- pygobject_new,
-
- pyg_closure_new,
- pygobject_watch_closure,
- pyg_destroy_notify,
-
- pyg_type_from_object,
- pyg_type_wrapper_new,
- pyg_enum_get_value,
- pyg_flags_get_value,
- pyg_register_gtype_custom,
- pyg_value_from_pyobject,
- pyg_value_as_pyobject,
-
- pyg_register_interface,
-
- &PyGBoxed_Type,
- pyg_register_boxed,
- pyg_boxed_new,
-
- &PyGPointer_Type,
- pyg_register_pointer,
- pyg_pointer_new,
-
- pyg_enum_add_constants,
- pyg_flags_add_constants,
-
- pyg_constant_strip_prefix,
-
- pygi_error_check,
-
- _pyg_set_thread_block_funcs,
- (PyGThreadBlockFunc)0, /* block_threads */
- (PyGThreadBlockFunc)0, /* unblock_threads */
-
- &PyGParamSpec_Type,
- pyg_param_spec_new,
- pyg_param_spec_from_object,
-
- pyg_pyobj_to_unichar_conv,
- pyg_parse_constructor_args,
- pyg_param_gvalue_as_pyobject,
- pyg_param_gvalue_from_pyobject,
-
- &PyGEnum_Type,
- pyg_enum_add,
- pyg_enum_from_gtype,
-
- &PyGFlags_Type,
- pyg_flags_add,
- pyg_flags_from_gtype,
-
- TRUE, /* threads_enabled */
-
- pygobject_enable_threads,
- pygobject_gil_state_ensure,
- pygobject_gil_state_release,
- pyg_register_class_init,
- pyg_register_interface_info,
-
- pyg_closure_set_exception_handler,
-
- add_warning_redirection,
- disable_warning_redirections,
-
- NULL, /* previously type_register_custom */
-
- pygi_gerror_exception_check,
-
- pyg_option_group_new,
- pyg_type_from_object_strict,
-
- pygobject_new_full,
- &PyGObject_Type,
-
- pyg_value_from_pyobject_with_error
-};
-
-/* for addon libraries ... */
-void
-pygobject_register_api(PyObject *d)
-{
- PyObject *api;
-
- api = PYGLIB_CPointer_WrapPointer(&pygobject_api_functions, "gobject._PyGObject_API");
- PyDict_SetItemString(d, "_PyGObject_API", api);
- Py_DECREF(api);
-}
-
-/* some constants */
-void
-pygobject_register_constants(PyObject *m)
-{
- /* PyFloat_ return a new ref, and add object takes the ref */
- PyModule_AddObject(m, "G_MINFLOAT", PyFloat_FromDouble(G_MINFLOAT));
- PyModule_AddObject(m, "G_MAXFLOAT", PyFloat_FromDouble(G_MAXFLOAT));
- PyModule_AddObject(m, "G_MINDOUBLE", PyFloat_FromDouble(G_MINDOUBLE));
- PyModule_AddObject(m, "G_MAXDOUBLE", PyFloat_FromDouble(G_MAXDOUBLE));
- PyModule_AddIntConstant(m, "G_MINSHORT", G_MINSHORT);
- PyModule_AddIntConstant(m, "G_MAXSHORT", G_MAXSHORT);
- PyModule_AddIntConstant(m, "G_MAXUSHORT", G_MAXUSHORT);
- PyModule_AddIntConstant(m, "G_MININT", G_MININT);
- PyModule_AddIntConstant(m, "G_MAXINT", G_MAXINT);
- PyModule_AddObject(m, "G_MAXUINT", PyLong_FromUnsignedLong(G_MAXUINT));
- PyModule_AddObject(m, "G_MINLONG", PyLong_FromLong(G_MINLONG));
- PyModule_AddObject(m, "G_MAXLONG", PyLong_FromLong(G_MAXLONG));
- PyModule_AddObject(m, "G_MAXULONG", PyLong_FromUnsignedLong(G_MAXULONG));
- PyModule_AddObject(m, "G_MAXSIZE", PyLong_FromSize_t(G_MAXSIZE));
- PyModule_AddObject(m, "G_MAXSSIZE", PyLong_FromSsize_t(G_MAXSSIZE));
- PyModule_AddObject(m, "G_MINSSIZE", PyLong_FromSsize_t(G_MINSSIZE));
- PyModule_AddObject(m, "G_MINOFFSET", PyLong_FromLongLong(G_MINOFFSET));
- PyModule_AddObject(m, "G_MAXOFFSET", PyLong_FromLongLong(G_MAXOFFSET));
-
- PyModule_AddIntConstant(m, "SIGNAL_RUN_FIRST", G_SIGNAL_RUN_FIRST);
- PyModule_AddIntConstant(m, "PARAM_READWRITE", G_PARAM_READWRITE);
-
- /* The rest of the types are set in __init__.py */
- PyModule_AddObject(m, "TYPE_INVALID", pyg_type_wrapper_new(G_TYPE_INVALID));
- PyModule_AddObject(m, "TYPE_GSTRING", pyg_type_wrapper_new(G_TYPE_GSTRING));
-}
-
-void
-pygobject_register_version_tuples(PyObject *d)
-{
- PyObject *tuple;
-
- /* pygobject version */
- tuple = Py_BuildValue ("(iii)",
- PYGOBJECT_MAJOR_VERSION,
- PYGOBJECT_MINOR_VERSION,
- PYGOBJECT_MICRO_VERSION);
- PyDict_SetItemString(d, "pygobject_version", tuple);
-}
-
-void
-pygobject_register_warnings(PyObject *d)
-{
- PyObject *warning;
-
- warning = PyErr_NewException("gobject.Warning", PyExc_Warning, NULL);
- PyDict_SetItemString(d, "Warning", warning);
- add_warning_redirection("GLib", warning);
- add_warning_redirection("GLib-GObject", warning);
- add_warning_redirection("GThread", warning);
-}
diff --git a/gi/gobjectmodule.h b/gi/gobjectmodule.h
deleted file mode 100644
index 5cc927a1..00000000
--- a/gi/gobjectmodule.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _PYGOBJECT_GOBJECTMODULE_H_
-#define _PYGOBJECT_GOBJECTMODULE_H_
-
-
-#include "pygobject-internal.h"
-
-int pygobject_constructv (PyGObject *self,
- guint n_parameters,
- GParameter *parameters);
-
-void pygobject_register_api (PyObject *d);
-void pygobject_register_constants (PyObject *m);
-void pygobject_register_version_tuples (PyObject *d);
-void pygobject_register_warnings (PyObject *d);
-
-PyObject * _wrap_pyg_type_register (PyObject *self, PyObject *args);
-PyObject * pyg_signal_new (PyObject *self, PyObject *args);
-PyObject * pyg_object_class_list_properties (PyObject *self, PyObject *args);
-PyObject * pyg_object_new (PyGObject *self, PyObject *args,
- PyObject *kwargs);
-PyObject * pyg_add_emission_hook (PyGObject *self, PyObject *args);
-PyObject * pyg__install_metaclass (PyObject *dummy,
- PyTypeObject *metaclass);
-PyObject * pyg__gvalue_get (PyObject *module, PyObject *pygvalue);
-PyObject * pyg__gvalue_set (PyObject *module, PyObject *args);
-
-#endif /*_PYGOBJECT_GOBJECTMODULE_H_*/
diff --git a/gi/pygboxed.h b/gi/pygboxed.h
index 93b3de65..6db26e82 100644
--- a/gi/pygboxed.h
+++ b/gi/pygboxed.h
@@ -29,8 +29,6 @@ void pyg_register_boxed (PyObject *dict, const gchar *class_name,
PyObject * pyg_boxed_new (GType boxed_type, gpointer boxed,
gboolean copy_boxed, gboolean own_ref);
-const gchar * pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix);
-
void pygobject_boxed_register_types(PyObject *d);
#endif /* __PYGOBJECT_BOXED_H__ */
diff --git a/gi/pygi-util.c b/gi/pygi-util.c
index 1d9201e6..c06806b5 100644
--- a/gi/pygi-util.c
+++ b/gi/pygi-util.c
@@ -2,8 +2,6 @@
* pygtk- Python bindings for the GTK toolkit.
* Copyright (C) 1998-2003 James Henstridge
*
- * gobjectmodule.c: wrapper for the gobject library.
- *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -40,3 +38,43 @@ pyg_integer_richcompare(PyObject *v, PyObject *w, int op)
Py_INCREF(result);
return result;
}
+
+/**
+ * pyg_constant_strip_prefix:
+ * @name: the constant name.
+ * @strip_prefix: the prefix to strip.
+ *
+ * Advances the pointer @name by strlen(@strip_prefix) characters. If
+ * the resulting name does not start with a letter or underscore, the
+ * @name pointer will be rewound. This is to ensure that the
+ * resulting name is a valid identifier. Hence the returned string is
+ * a pointer into the string @name.
+ *
+ * Returns: the stripped constant name.
+ */
+const gchar *
+pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix)
+{
+ size_t prefix_len;
+ guint i;
+
+ prefix_len = strlen(strip_prefix);
+
+ /* Check so name starts with strip_prefix, if it doesn't:
+ * return the rest of the part which doesn't match
+ */
+ for (i = 0; i < prefix_len; i++) {
+ if (name[i] != strip_prefix[i] && name[i] != '_') {
+ return &name[i];
+ }
+ }
+
+ /* strip off prefix from value name, while keeping it a valid
+ * identifier */
+ for (i = prefix_len + 1; i > 0; i--) {
+ if (g_ascii_isalpha(name[i - 1]) || name[i - 1] == '_') {
+ return &name[i - 1];
+ }
+ }
+ return name;
+}
diff --git a/gi/pygi-util.h b/gi/pygi-util.h
index c7bc1d58..9da3f6b1 100644
--- a/gi/pygi-util.h
+++ b/gi/pygi-util.h
@@ -9,6 +9,7 @@
G_BEGIN_DECLS
PyObject * pyg_integer_richcompare(PyObject *v, PyObject *w, int op);
+const gchar * pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix);
#if PY_VERSION_HEX >= 0x03000000
diff --git a/gi/pygi-value.c b/gi/pygi-value.c
index 814bb024..2a40aaa2 100644
--- a/gi/pygi-value.c
+++ b/gi/pygi-value.c
@@ -999,3 +999,37 @@ error:
g_free (argv);
return -1;
}
+
+PyObject *
+pyg__gvalue_get(PyObject *module, PyObject *pygvalue)
+{
+ if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
+ PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
+ return NULL;
+ }
+
+ return pyg_value_as_pyobject (pyg_boxed_get(pygvalue, GValue),
+ /*copy_boxed=*/ TRUE);
+}
+
+PyObject *
+pyg__gvalue_set(PyObject *module, PyObject *args)
+{
+ PyObject *pygvalue;
+ PyObject *pyobject;
+
+ if (!PyArg_ParseTuple (args, "OO:_gi._gvalue_set",
+ &pygvalue, &pyobject))
+ return NULL;
+
+ if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
+ PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
+ return NULL;
+ }
+
+ if (pyg_value_from_pyobject_with_error (pyg_boxed_get (pygvalue, GValue),
+ pyobject) == -1)
+ return NULL;
+
+ Py_RETURN_NONE;
+}
diff --git a/gi/pygi-value.h b/gi/pygi-value.h
index 5b2eac19..43709a30 100644
--- a/gi/pygi-value.h
+++ b/gi/pygi-value.h
@@ -45,6 +45,9 @@ PyObject *pygi_value_to_py_structured_type (const GValue *value,
GType fundamental,
gboolean copy_boxed);
+PyObject *pyg__gvalue_get(PyObject *module, PyObject *pygvalue);
+PyObject *pyg__gvalue_set(PyObject *module, PyObject *args);
+
G_END_DECLS
#endif /* __PYGI_VALUE_H__ */
diff --git a/gi/pygobject-object.c b/gi/pygobject-object.c
index 2b25c07c..f99a331d 100644
--- a/gi/pygobject-object.c
+++ b/gi/pygobject-object.c
@@ -26,7 +26,7 @@
#include "pygparamspec.h"
#include "pygtype.h"
#include "pygboxed.h"
-#include "gobjectmodule.h"
+#include "gimodule.h"
#include "pygi-value.h"
#include "pygi-type.h"
@@ -2434,3 +2434,60 @@ pygobject_object_register_types(PyObject *d)
return;
PyDict_SetItemString(d, "GObjectWeakRef", (PyObject *) &PyGObjectWeakRef_Type);
}
+
+PyObject *
+pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyObject *pytype;
+ GType type;
+ GObject *obj = NULL;
+ GObjectClass *class;
+ guint n_params = 0, i;
+ GParameter *params = NULL;
+
+ if (!PyArg_ParseTuple (args, "O:gobject.new", &pytype)) {
+ return NULL;
+ }
+
+ if ((type = pyg_type_from_object (pytype)) == 0)
+ return NULL;
+
+ if (G_TYPE_IS_ABSTRACT(type)) {
+ PyErr_Format(PyExc_TypeError, "cannot create instance of abstract "
+ "(non-instantiable) type `%s'", g_type_name(type));
+ return NULL;
+ }
+
+ if ((class = g_type_class_ref (type)) == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "could not get a reference to type class");
+ return NULL;
+ }
+
+ if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
+ goto cleanup;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ obj = g_object_newv(type, n_params, params);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ 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);
+ }
+ g_free(params);
+ g_type_class_unref(class);
+
+ if (obj) {
+ pygobject_sink (obj);
+ self = (PyGObject *) pygobject_new((GObject *)obj);
+ g_object_unref(obj);
+ } else
+ self = NULL;
+
+ return (PyObject *) self;
+}
diff --git a/gi/pygobject-object.h b/gi/pygobject-object.h
index fb39a259..70315289 100644
--- a/gi/pygobject-object.h
+++ b/gi/pygobject-object.h
@@ -50,6 +50,7 @@ void pygobject_watch_closure (PyObject *self, GClosure *closure);
void pygobject_object_register_types(PyObject *d);
void pygobject_ref_float(PyGObject *self);
void pygobject_ref_sink(PyGObject *self);
+PyObject * pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs);
GClosure * gclosure_from_pyfunc(PyGObject *object, PyObject *func);