#include "pyginterface.h"
#include "pygparamspec.h"
-#include "pygi-external.h"
+#include "pygi.h"
static void pygobject_dealloc(PyGObject *self);
GQuark pygobject_wrapper_key;
GQuark pygobject_has_updated_constructor_key;
GQuark pygobject_instance_data_key;
+GQuark pygobject_ref_sunk_key;
/* -------------- class <-> wrapper manipulation --------------- */
void
pygobject_sink(GObject *obj)
{
+ gboolean sunk = FALSE;
+
+ /* We use a gobject data key to avoid running the sink funcs more than once. */
+ if (g_object_get_qdata (obj, pygobject_ref_sunk_key))
+ return;
+
if (sink_funcs) {
gint i;
if (g_type_is_a(G_OBJECT_TYPE(obj),
g_array_index(sink_funcs, SinkFunc, i).type)) {
g_array_index(sink_funcs, SinkFunc, i).sinkfunc(obj);
- return;
+
+ sunk = TRUE;
+ break;
}
}
}
- if (G_IS_INITIALLY_UNOWNED(obj) && !g_object_is_floating(obj)) {
- /* GtkWindow and GtkInvisible does not return a ref to caller of
- * g_object_new.
- */
- g_object_ref(obj);
- } else if (g_object_is_floating(obj)) {
+
+ if (!sunk && G_IS_INITIALLY_UNOWNED (obj))
g_object_ref_sink(obj);
- }
+
+ g_object_set_qdata (obj, pygobject_ref_sunk_key, GINT_TO_POINTER (1));
}
/**
name = g_strdup(g_param_spec_get_name(props[i]));
/* hyphens cannot belong in identifiers */
g_strdelimit(name, "-", '_');
- prop_str = _PyUnicode_FromString(name);
+ prop_str = PYGLIB_PyUnicode_FromString(name);
PyList_SetItem(props_list, i, prop_str);
g_free(name);
GValue value = { 0, };
PyObject *ret;
- attr_name = _PyUnicode_AsString(attr);
+ attr_name = PYGLIB_PyUnicode_AsString(attr);
if (!attr_name) {
PyErr_Clear();
return PyObject_GenericGetAttr((PyObject *)self, attr);
return build_parameter_list(class);
}
+ if (self->pygobject != NULL) {
+ ret = pygi_get_property_value (self->pygobject, attr_name);
+ if (ret != NULL)
+ return ret;
+ }
+
pspec = g_object_class_find_property(class, attr_name);
g_type_class_unref(class);
GParamSpec *pspec;
char *attr_name;
GObject *obj;
+ int ret = -1;
if (pvalue == NULL) {
PyErr_SetString(PyExc_TypeError, "properties cannot be "
return -1;
}
- attr_name = _PyUnicode_AsString(attr);
+ attr_name = PYGLIB_PyUnicode_AsString(attr);
if (!attr_name) {
PyErr_Clear();
return PyObject_GenericSetAttr((PyObject *)self, attr, pvalue);
return -1;
}
+ ret = pygi_set_property_value (self->pygobject, attr_name, pvalue);
+ if (ret == 0)
+ return 0;
+ else if (ret == -1)
+ if (PyErr_Occurred())
+ return -1;
+
obj = self->pygobject->obj;
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), attr_name);
if (!pspec) {
*/
s = strrchr(type->tp_name, '.');
if (s != NULL) {
- mod_name = _PyUnicode_FromStringAndSize(type->tp_name, (int)(s - type->tp_name));
+ mod_name = PYGLIB_PyUnicode_FromStringAndSize(type->tp_name, (int)(s - type->tp_name));
PyDict_SetItemString(type->tp_dict, "__module__", mod_name);
Py_DECREF(mod_name);
}
pygobject_inherit_slots(PyTypeObject *type, PyObject *bases, gboolean check_for_present)
{
static int slot_offsets[] = { offsetof(PyTypeObject, tp_richcompare),
- offsetof(PyTypeObject, tp_compare),
- offsetof(PyTypeObject, tp_hash),
- offsetof(PyTypeObject, tp_iter),
- offsetof(PyTypeObject, tp_repr),
- offsetof(PyTypeObject, tp_str),
- offsetof(PyTypeObject, tp_print) };
+#if PY_VERSION_HEX < 0x03000000
+ offsetof(PyTypeObject, tp_compare),
+#endif
+ offsetof(PyTypeObject, tp_richcompare),
+ offsetof(PyTypeObject, tp_hash),
+ offsetof(PyTypeObject, tp_iter),
+ offsetof(PyTypeObject, tp_repr),
+ offsetof(PyTypeObject, tp_str),
+ offsetof(PyTypeObject, tp_print) };
int i;
/* Happens when registering gobject.GObject itself, at least. */
return pygobject_new_full(obj, TRUE, NULL);
}
+PyObject *
+pygobject_new_sunk(GObject *obj)
+{
+ g_object_set_qdata (obj, pygobject_ref_sunk_key, GINT_TO_POINTER (1));
+ return pygobject_new_full(obj, TRUE, NULL);
+}
+
static void
pygobject_unwatch_closure(gpointer data, GClosure *closure)
{
static void
pygobject_dealloc(PyGObject *self)
{
- PyObject_ClearWeakRefs((PyObject *)self);
+ /* Untrack must be done first. This is because followup calls such as
+ * ClearWeakRefs could call into Python and cause new allocations to
+ * happen, which could in turn could trigger the garbage collector,
+ * which would then get confused as it is tracking this half-deallocated
+ * object. */
PyObject_GC_UnTrack((PyObject *)self);
+
+ PyObject_ClearWeakRefs((PyObject *)self);
/* this forces inst_data->type to be updated, which could prove
* important if a new wrapper has to be created and it is of a
* unregistered type */
PyObject_GC_Del(self);
}
-static int
-pygobject_compare(PyGObject *self, PyGObject *v)
+static PyObject*
+pygobject_richcompare(PyObject *self, PyObject *other, int op)
{
- if (self->obj == v->obj) return 0;
- if (self->obj > v->obj) return -1;
- return 1;
+ int isinst;
+
+ isinst = PyObject_IsInstance(self, (PyObject*)&PyGObject_Type);
+ if (isinst == -1)
+ return NULL;
+ if (!isinst) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ isinst = PyObject_IsInstance(other, (PyObject*)&PyGObject_Type);
+ if (isinst == -1)
+ return NULL;
+ if (!isinst) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ return _pyglib_generic_ptr_richcompare(((PyGObject*)self)->obj,
+ ((PyGObject*)other)->obj,
+ op);
}
static long
(long)self,
self->obj ? G_OBJECT_TYPE_NAME(self->obj) : "uninitialized",
(long)self->obj);
- return _PyUnicode_FromString(buf);
+ return PYGLIB_PyUnicode_FromString(buf);
}
PyObject_GC_Del(op);
}
+gboolean
+pygobject_prepare_construct_properties(GObjectClass *class, PyObject *kwargs,
+ guint *n_params, GParameter **params)
+{
+ *n_params = 0;
+ *params = NULL;
+
+ if (kwargs) {
+ Py_ssize_t pos = 0;
+ PyObject *key;
+ PyObject *value;
+
+ *params = g_new0(GParameter, PyDict_Size(kwargs));
+ while (PyDict_Next(kwargs, &pos, &key, &value)) {
+ GParamSpec *pspec;
+ GParameter *param = &(*params)[*n_params];
+ const gchar *key_str = PYGLIB_PyUnicode_AsString(key);
+
+ pspec = g_object_class_find_property(class, key_str);
+ if (!pspec) {
+ PyErr_Format(PyExc_TypeError,
+ "gobject `%s' doesn't support property `%s'",
+ G_OBJECT_CLASS_NAME(class), key_str);
+ return FALSE;
+ }
+ g_value_init(¶m->value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+ if (pyg_param_gvalue_from_pyobject(¶m->value, value, pspec) < 0) {
+ PyErr_Format(PyExc_TypeError,
+ "could not convert value for property `%s' from %s to %s",
+ key_str, Py_TYPE(value)->tp_name,
+ g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)));
+ return FALSE;
+ }
+ param->name = g_strdup(key_str);
+ ++(*n_params);
+ }
+ }
+ return TRUE;
+}
/* ---------------- PyGObject methods ----------------- */
return -1;
}
- if (kwargs) {
- Py_ssize_t pos = 0;
- PyObject *key;
- PyObject *value;
-
- params = g_new0(GParameter, PyDict_Size(kwargs));
- while (PyDict_Next (kwargs, &pos, &key, &value)) {
- GParamSpec *pspec;
- gchar *key_str = _PyUnicode_AsString(key);
-
- pspec = g_object_class_find_property (class, key_str);
- if (!pspec) {
- PyErr_Format(PyExc_TypeError,
- "object of type `%s' doesn't support property `%s'",
- g_type_name(object_type), key_str);
- goto cleanup;
- }
- g_value_init(¶ms[n_params].value,
- G_PARAM_SPEC_VALUE_TYPE(pspec));
- if (pyg_value_from_pyobject(¶ms[n_params].value, value)) {
- PyErr_Format(PyExc_TypeError,
- "could not convert value for property `%s'",
- key_str);
- goto cleanup;
- }
- params[n_params].name = g_strdup(key_str);
- n_params++;
- }
- }
+ if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, ¶ms))
+ goto cleanup;
+
if (pygobject_constructv(self, n_params, params))
PyErr_SetString(PyExc_RuntimeError, "could not create object");
GValue value = { 0 };
PyObject *item;
- if (!_PyUnicode_Check(py_property)) {
+ if (!PYGLIB_PyUnicode_Check(py_property)) {
PyErr_SetString(PyExc_TypeError,
"Expected string argument for property.");
return NULL;
}
- property_name = _PyUnicode_AsString(py_property);
+ property_name = PYGLIB_PyUnicode_AsString(py_property);
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
property_name);
pos = 0;
while (kwargs && PyDict_Next (kwargs, &pos, &key, &value)) {
- gchar *key_str = _PyUnicode_AsString(key);
+ gchar *key_str = PYGLIB_PyUnicode_AsString(key);
GParamSpec *pspec;
pspec = g_object_class_find_property(class, key_str);
if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj),
&sigid, &detail, TRUE)) {
PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
name);
return NULL;
}
extra_args = PySequence_GetSlice(args, 2, len);
if (extra_args == NULL)
return NULL;
- closure = pyg_closure_new(callback, extra_args, NULL);
+
+ closure = pygi_signal_closure_new(self, name, callback, extra_args, NULL);
+ if (closure == NULL)
+ closure = pyg_closure_new(callback, extra_args, NULL);
+
pygobject_watch_closure((PyObject *)self, closure);
handlerid = g_signal_connect_closure_by_id(self->obj, sigid, detail,
closure, FALSE);
if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj),
&sigid, &detail, TRUE)) {
PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
name);
return NULL;
}
extra_args = PySequence_GetSlice(args, 2, len);
if (extra_args == NULL)
return NULL;
- closure = pyg_closure_new(callback, extra_args, NULL);
+
+ closure = pygi_signal_closure_new(self, name, callback, extra_args, NULL);
+ if (closure == NULL)
+ closure = pyg_closure_new(callback, extra_args, NULL);
+
pygobject_watch_closure((PyObject *)self, closure);
handlerid = g_signal_connect_closure_by_id(self->obj, sigid, detail,
closure, TRUE);
if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj),
&sigid, &detail, TRUE)) {
PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
name);
return NULL;
}
extra_args = PySequence_GetSlice(args, 3, len);
if (extra_args == NULL)
return NULL;
- closure = pyg_closure_new(callback, extra_args, object);
+
+ closure = pygi_signal_closure_new(self, name, callback, extra_args, object);
+ if (closure == NULL)
+ closure = pyg_closure_new(callback, extra_args, object);
+
pygobject_watch_closure((PyObject *)self, closure);
handlerid = g_signal_connect_closure_by_id(self->obj, sigid, detail,
closure, FALSE);
if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj),
&sigid, &detail, TRUE)) {
PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
name);
return NULL;
}
extra_args = PySequence_GetSlice(args, 3, len);
if (extra_args == NULL)
return NULL;
- closure = pyg_closure_new(callback, extra_args, object);
+
+ closure = pygi_signal_closure_new(self, name, callback, extra_args, object);
+ if (closure == NULL)
+ closure = pyg_closure_new(callback, extra_args, object);
+
pygobject_watch_closure((PyObject *)self, closure);
handlerid = g_signal_connect_closure_by_id(self->obj, sigid, detail,
closure, TRUE);
if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj),
&signal_id, &detail, TRUE)) {
PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
name);
return NULL;
}
if (!g_signal_parse_name(signal, G_OBJECT_TYPE(self->obj),
&signal_id, &detail, TRUE)) {
PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)),
signal);
return NULL;
}
closure = gclosure_from_pyfunc(self, pyfunc);
if (!closure) {
PyErr_Format(PyExc_TypeError, "nothing connected to %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc)));
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc)));
return NULL;
}
0, 0,
closure,
NULL, NULL);
- return _PyLong_FromLong(retval);
+ return PYGLIB_PyLong_FromLong(retval);
}
static PyObject *
closure = gclosure_from_pyfunc(self, pyfunc);
if (!closure) {
PyErr_Format(PyExc_TypeError, "nothing connected to %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc)));
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc)));
return NULL;
}
0, 0,
closure,
NULL, NULL);
- return _PyLong_FromLong(retval);
+ return PYGLIB_PyLong_FromLong(retval);
}
static PyObject *
closure = gclosure_from_pyfunc(self, pyfunc);
if (!closure) {
PyErr_Format(PyExc_TypeError, "nothing connected to %s",
- _PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc)));
+ PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc)));
return NULL;
}
0, 0,
closure,
NULL, NULL);
- return _PyLong_FromLong(retval);
+ return PYGLIB_PyLong_FromLong(retval);
}
static PyMethodDef pygobject_methods[] = {
{ "get_property", (PyCFunction)pygobject_get_property, METH_VARARGS },
{ "get_properties", (PyCFunction)pygobject_get_properties, METH_VARARGS },
{ "set_property", (PyCFunction)pygobject_set_property, METH_VARARGS },
- { "set_properties", (PyCFunction)pygobject_set_properties, METH_KEYWORDS },
+ { "set_properties", (PyCFunction)pygobject_set_properties, METH_VARARGS|METH_KEYWORDS },
{ "freeze_notify", (PyCFunction)pygobject_freeze_notify, METH_VARARGS },
{ "notify", (PyCFunction)pygobject_notify, METH_VARARGS },
{ "thaw_notify", (PyCFunction)pygobject_thaw_notify, METH_VARARGS },
static PyObject *
pygobject_get_refcount(PyGObject *self, void *closure)
{
- return _PyLong_FromLong(self->obj->ref_count);
+ return PYGLIB_PyLong_FromLong(self->obj->ref_count);
}
static int
pygobject_has_updated_constructor_key =
g_quark_from_static_string("PyGObject::has-updated-constructor");
pygobject_instance_data_key = g_quark_from_static_string("PyGObject::instance-data");
+ pygobject_ref_sunk_key = g_quark_from_static_string("PyGObject::ref-sunk");
/* GObject */
if (!PY_TYPE_OBJECT)
pyobject_copy,
pyobject_free);
PyGObject_Type.tp_dealloc = (destructor)pygobject_dealloc;
- PyGObject_Type.tp_compare = (cmpfunc)pygobject_compare;
+ PyGObject_Type.tp_richcompare = pygobject_richcompare;
PyGObject_Type.tp_repr = (reprfunc)pygobject_repr;
PyGObject_Type.tp_hash = (hashfunc)pygobject_hash;
PyGObject_Type.tp_setattro = (setattrofunc)pygobject_setattro;
descr = PyObject_New(PyObject, &PyGPropsDescr_Type);
PyDict_SetItemString(PyGObject_Type.tp_dict, "props", descr);
PyDict_SetItemString(PyGObject_Type.tp_dict, "__module__",
- o=_PyUnicode_FromString("gobject._gobject"));
+ o=PYGLIB_PyUnicode_FromString("gobject._gobject"));
Py_DECREF(o);
/* GPropsIter */