Index: codegen/codegen.py
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/codegen/codegen.py,v
retrieving revision 1.91
diff -u -p -d -r1.91 codegen.py
--- codegen/codegen.py	15 Mar 2005 20:40:38 -0000	1.91
+++ codegen/codegen.py	28 May 2005 22:13:12 -0000
@@ -739,7 +739,6 @@ class GObjectWrapper(Wrapper):
         print >> out, "static int"
         print >> out, '_wrap_%s(PyGObject *self, PyObject *args,'\
               ' PyObject *kwargs)\n{' % constructor.c_name
-        print >> out, "    GType obj_type = pyg_type_from_object((PyObject *) self);"
 
         def py_str_list_to_c(arg):
             if arg:
@@ -757,6 +756,7 @@ class GObjectWrapper(Wrapper):
             prop_names = py_str_list_to_c([param.pname for param in
                                           mandatory_arguments + optional_arguments])
 
+            print >> out, "    GType obj_type = pyg_type_from_object((PyObject *) self);"
             print >> out, "    GParameter params[%i];" % len(constructor.params)
             print >> out, "    PyObject *parsed_args[%i] = {NULL, };" % len(constructor.params)
             print >> out, "    char *arg_names[] = %s;" % arg_names
@@ -785,7 +785,7 @@ class GObjectWrapper(Wrapper):
             print >> out, "    if (!pyg_parse_constructor_args(obj_type, arg_names, prop_names,"
             print >> out, "                                    params, &nparams, parsed_args))"
             print >> out, "        return -1;"
-            print >> out, "    self->obj = g_object_newv(obj_type, nparams, params);"
+            print >> out, "    pygobject_constructv(self, nparams, params);"
             print >> out, "    for (i = 0; i < nparams; ++i)"
             print >> out, "        g_value_unset(&params[i].value);"
         else:
@@ -799,7 +799,7 @@ class GObjectWrapper(Wrapper):
             print >> out, '    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":%s.__init__", kwlist))' % classname
             print >> out, "        return -1;"
             print >> out
-            print >> out, "    self->obj = g_object_newv(obj_type, 0, NULL);"
+            print >> out, "    pygobject_constructv(self, 0, NULL);"
 
         print >> out, \
               '    if (!self->obj) {\n' \
@@ -811,7 +811,6 @@ class GObjectWrapper(Wrapper):
             print >> out, "    g_object_ref(self->obj);\n"
 
         print >> out, \
-              '    pygobject_register_wrapper((PyObject *)self);\n' \
               '    return 0;\n' \
               '}\n\n' % { 'typename': classname }
         return "_wrap_%s" % constructor.c_name
Index: gobject/gobjectmodule.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobject/gobjectmodule.c,v
retrieving revision 1.172
diff -u -p -d -r1.172 gobjectmodule.c
--- gobject/gobjectmodule.c	28 May 2005 21:47:14 -0000	1.172
+++ gobject/gobjectmodule.c	28 May 2005 22:13:16 -0000
@@ -26,6 +26,8 @@
 
 #include "pygobject-private.h"
 #include "pythread.h"
+#include <gobject/gvaluecollector.h>
+
 
 static PyObject *gerror_exc = NULL;
 static gboolean use_gil_state_api = FALSE;
@@ -40,6 +42,7 @@ GQuark pygboxed_marshal_key;
 GQuark pygenum_class_key;
 GQuark pygflags_class_key;
 GQuark pygpointer_class_key;
+static GQuark pyg_in_constructor_key;
 
 static void pyg_flags_add_constants(PyObject *module, GType flags_type,
 				    const gchar *strip_prefix);
@@ -413,11 +416,199 @@ pyg_object_get_property (GObject *object
     pyg_gil_state_release(state);
 }
 
+
+static GObject*
+pyg_object_constructor(GType                   this_type,
+                       GType                   leaf_type,
+                       guint                   n_construct_properties,
+                       GObjectConstructParam  *construct_properties,
+                       GData                 **datalist)
+{
+    GType parent_type = g_type_parent(this_type);
+    GObjectClass *parent_class = g_type_class_peek(parent_type);
+    GObject *object;
+    PyObject *wrapper;
+    gboolean in_constructor;
+
+      /* Check if we are being called by an outer
+       * pyg_object_constructor that happens to be chaining to a
+       * parent that is another python gobject */
+    in_constructor = (datalist && g_datalist_id_get_data(datalist, pyg_in_constructor_key));
+    g_datalist_id_set_data(datalist, pyg_in_constructor_key, GINT_TO_POINTER(1));
+
+    if (parent_class->constructor_full)
+        object = parent_class->constructor_full(parent_type, leaf_type, 0, NULL, datalist);
+    else
+        object = parent_class->constructor(leaf_type, 0, NULL);
+
+      /* If we were already inside another pygobject constructor,
+       * don't do anything else, since the outer constructor will take
+       * care of everything. */
+    if (in_constructor)
+        return object;
+
+    if (datalist)
+        wrapper = (PyObject *) g_datalist_id_get_data(datalist, pygobject_wrapper_key);
+    else
+        wrapper = NULL;
+
+    if (wrapper) {
+          /* A wrapper already exists; we just need to associate the
+           * wrapper and set the construction properties */
+        ((PyGObject*)wrapper)->obj = object;
+          /* we don't sink() here because we have to sink() in
+           * pygobject_construct (compatibility reasons) */
+        pygobject_register_wrapper_full(wrapper, FALSE);
+          /* Now set construction properties */
+        if (n_construct_properties) {
+            int i;
+            g_object_freeze_notify(object);
+            for (i = 0; i < n_construct_properties; ++i)
+                g_object_set_property(object,
+                                      construct_properties[i].pspec->name,
+                                      construct_properties[i].value);
+            g_object_thaw_notify(object);
+        }
+    } else {
+        PyObject *args, *kwargs;
+        PyTypeObject *typeobject = pygobject_lookup_class(leaf_type);
+        guint i;
+
+        if (!typeobject)
+            g_error("No Python type, type %s is improperly registered", 
+                    g_type_name(leaf_type));
+        if (n_construct_properties > 0) {
+            kwargs = PyDict_New();
+            for (i = 0; i < n_construct_properties; i++) {
+                PyObject *valobj = pyg_param_gvalue_as_pyobject(construct_properties[i].value, 
+                                                                FALSE,
+                                                                construct_properties[i].pspec);
+                if (!valobj || PyDict_SetItemString(kwargs,
+                                                    construct_properties[i].pspec->name,
+                                                    valobj) != 0)
+                    g_warning("could not add property %s to construct properties",
+                              construct_properties[i].pspec->name);
+                Py_XDECREF(valobj);
+            }
+        } else {
+            kwargs = NULL;
+        }
+        args = (PyObject *) PyTuple_New(0);
+          /* Create a PyGObject to be owned by C code */
+        wrapper = pygobject_new_full(object, FALSE);
+        ((PyGObject*)wrapper)->obj = object;
+        wrapper->ob_type->tp_init(wrapper, args, kwargs);
+        Py_DECREF(args);
+        Py_XDECREF(kwargs);
+    }
+    return object;
+}
+
+int
+pygobject_constructv(PyGObject  *self,
+                     guint       n_parameters,
+                     GParameter *parameters)
+{
+    if (self->obj == NULL)
+    {
+        GData *datalist;
+
+        g_datalist_init(&datalist);
+        g_datalist_id_set_data(&datalist, pygobject_wrapper_key, self);
+        self->obj = g_object_newv_with_data(pyg_type_from_object((PyObject *)self),
+                                            n_parameters, parameters,
+                                            &datalist);
+        g_datalist_clear(&datalist);
+          /* wrapper may or not be already registered, depending on
+           * whether this is a gobject subclass in python; but in any
+           * case, the object is not yet sink()ed. */
+        pygobject_register_wrapper_full((PyObject *)self, TRUE);
+    } else {
+          /* we are being called from a pygobject constructor; we set
+           * construction properties here instead of in the PyGObject
+           * constructor because python __init__ may have modified
+           * them. */
+        if (n_parameters) {
+            int i;
+            g_object_freeze_notify(self->obj);
+            for (i = 0; i < n_parameters; ++i)
+                g_object_set_property(self->obj, parameters[i].name,
+                                      &parameters[i].value);
+            g_object_thaw_notify(self->obj);
+        }
+    }
+    return 0;
+}
+
+int
+pygobject_construct(PyGObject *self, const char *first_property_name, ...)
+{
+    va_list var_args;
+    GObjectClass *class;
+    GParameter *params;
+    const gchar *name;
+    guint n_params = 0, n_alloced_params = 16;
+    GType object_type = pyg_type_from_object((PyObject *)self);
+    int retval;
+
+    if (!first_property_name)
+        return pygobject_constructv(self, 0, NULL);
+
+    va_start(var_args, first_property_name);
+    class = g_type_class_ref(object_type);
+
+    params = g_new(GParameter, n_alloced_params);
+    name = first_property_name;
+    while (name)
+    {
+        gchar *error = NULL;
+        GParamSpec *pspec = g_object_class_find_property(class, name);
+
+        if (!pspec)
+	{
+            g_warning("%s: object class `%s' has no property named `%s'", 
+                      G_STRFUNC, 
+                      g_type_name(object_type), 
+                      name);
+            break;
+	}
+        if (n_params >= n_alloced_params)
+	{
+            n_alloced_params += 16;
+            params = g_renew(GParameter, params, n_alloced_params);
+	}
+        params[n_params].name = name;
+        params[n_params].value.g_type = 0;
+        g_value_init(&params[n_params].value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+        G_VALUE_COLLECT(&params[n_params].value, var_args, 0, &error);
+        if (error)
+	{
+            g_warning("%s: %s", G_STRFUNC, error);
+            g_free(error);
+            g_value_unset(&params[n_params].value);
+            break;
+	}
+        n_params++;
+        name = va_arg(var_args, gchar*);
+    }
+
+    retval = pygobject_constructv(self, n_params, params);
+
+    while (n_params--)
+        g_value_unset(&params[n_params].value);
+    g_free(params);
+    va_end(var_args);
+    g_type_class_unref(class);
+    return retval;
+}
+
 static void
 pyg_object_class_init(GObjectClass *class, PyObject *py_class)
 {
     class->set_property = pyg_object_set_property;
     class->get_property = pyg_object_get_property;
+    class->constructor = NULL;
+    class->constructor_full = pyg_object_constructor;
 }
 
 static gboolean
@@ -2454,7 +2645,9 @@ struct _PyGObject_Functions pygobject_ap
   pyg_register_class_init,
   pyg_register_interface_info,
 
-  pyg_closure_set_exception_handler
+  pyg_closure_set_exception_handler,
+  pygobject_constructv,
+  pygobject_construct,
 };
 
 #define REGISTER_TYPE(d, type, name) \
@@ -2494,6 +2687,7 @@ initgobject(void)
     pyginterface_type_key    = g_quark_from_static_string("PyGInterface::type");
     pyginterface_info_key    = g_quark_from_static_string("PyGInterface::info");
     pygpointer_class_key     = g_quark_from_static_string("PyGPointer::class");
+    pyg_in_constructor_key   = g_quark_from_static_string("PyGObject::in-constructor");
 
     PY_TYPE_OBJECT = g_boxed_type_register_static("PyObject",
 						  pyobject_copy,
Index: gobject/pygobject-private.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobject/pygobject-private.h,v
retrieving revision 1.33
diff -u -p -d -r1.33 pygobject-private.h
--- gobject/pygobject-private.h	28 May 2005 15:42:06 -0000	1.33
+++ gobject/pygobject-private.h	28 May 2005 22:13:16 -0000
@@ -99,12 +99,22 @@ void          pygobject_register_class  
 					  GType gtype, PyTypeObject *type,
 					  PyObject *bases);
 void          pygobject_register_wrapper (PyObject *self);
+void          pygobject_register_wrapper_full(PyObject *self, gboolean sink);
+
 PyObject *    pygobject_new              (GObject *obj);
+PyObject *    pygobject_new_full         (GObject *obj, gboolean sink);
 PyTypeObject *pygobject_lookup_class     (GType gtype);
 void          pygobject_watch_closure    (PyObject *self, GClosure *closure);
 void          pygobject_register_sinkfunc(GType type,
 					  void (* sinkfunc)(GObject *object));
 int           pyg_type_register          (PyTypeObject *class);
+
+int           pygobject_constructv       (PyGObject  *self,
+                                          guint       n_parameters,
+                                          GParameter *parameters);
+int           pygobject_construct        (PyGObject  *self,
+                                          const char *first_property_name,
+                                          ...);
 
 /* from pygboxed.c */
 extern PyTypeObject PyGBoxed_Type;
Index: gobject/pygobject.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobject/pygobject.c,v
retrieving revision 1.43
diff -u -p -d -r1.43 pygobject.c
--- gobject/pygobject.c	28 May 2005 15:26:59 -0000	1.43
+++ gobject/pygobject.c	28 May 2005 22:13:16 -0000
@@ -137,7 +137,7 @@ pygobject_register_class(PyObject *dict,
 }
 
 /**
- * pygobject_register_wrapper:
+ * pygobject_register_wrapper_full:
  * @self: the wrapper instance
  *
  * In the constructor of PyGTK wrappers, this function should be
@@ -147,16 +147,23 @@ pygobject_register_class(PyObject *dict,
  * floating references on the GObject.
  */
 void
-pygobject_register_wrapper(PyObject *self)
+pygobject_register_wrapper_full(PyObject *self, gboolean sink)
 {
     GObject *obj = ((PyGObject *)self)->obj;
 
-    sink_object(obj);
+    if (sink)
+        sink_object(obj);
     Py_INCREF(self);
     g_object_set_qdata_full(obj, pygobject_wrapper_key, self,
 			    pyg_destroy_notify);
 }
 
+void
+pygobject_register_wrapper(PyObject *self)
+{
+    pygobject_register_wrapper_full(self, TRUE);
+}
+
 /**
  * pygobject_new_with_interfaces
  * @gtype: the GType of the GObject subclass.
@@ -313,8 +320,9 @@ pygobject_lookup_class(GType gtype)
 }
 
 /**
- * pygobject_new:
+ * pygobject_new_full:
  * @obj: a GObject instance.
+ * @sink: whether to sink() the GObject (otherwise it is merely ref'ed)
  *
  * This function gets a reference to a wrapper for the given GObject
  * instance.  If a wrapper has already been created, a new reference
@@ -324,7 +332,7 @@ pygobject_lookup_class(GType gtype)
  * Returns: a reference to the wrapper for the GObject.
  */
 PyObject *
-pygobject_new(GObject *obj)
+pygobject_new_full(GObject *obj, gboolean sink)
 {
     PyGObject *self;
 
@@ -347,11 +355,10 @@ pygobject_new(GObject *obj)
 	self = PyObject_GC_New(PyGObject, tp);
 	if (self == NULL)
 	    return NULL;
-        pyg_begin_allow_threads;
-	self->obj = g_object_ref(obj);
-	pyg_end_allow_threads;
-	sink_object(self->obj);
-
+        if (sink) {
+            self->obj = g_object_ref(obj);
+            sink_object(self->obj);
+        }
 	self->inst_dict = NULL;
 	self->weakreflist = NULL;
 	self->closures = NULL;
@@ -366,6 +373,12 @@ pygobject_new(GObject *obj)
     return (PyObject *)self;
 }
 
+PyObject *
+pygobject_new(GObject *obj)
+{
+    return pygobject_new_full(obj, TRUE);
+}
+
 static void
 pygobject_unwatch_closure(gpointer data, GClosure *closure)
 {
@@ -599,11 +612,8 @@ pygobject_init(PyGObject *self, PyObject
 	}
     }
 
-    self->obj = g_object_newv(object_type, n_params, params);
-    if (self->obj)
-	pygobject_register_wrapper((PyObject *)self);
-    else
-	PyErr_SetString (PyExc_RuntimeError, "could not create object");
+    if (pygobject_constructv(self, n_params, params))
+	PyErr_SetString(PyExc_RuntimeError, "could not create object");
 	   
  cleanup:
     for (i = 0; i < n_params; i++) {
Index: gobject/pygobject.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobject/pygobject.h,v
retrieving revision 1.51
diff -u -p -d -r1.51 pygobject.h
--- gobject/pygobject.h	17 May 2005 17:47:10 -0000	1.51
+++ gobject/pygobject.h	28 May 2005 22:13:16 -0000
@@ -163,6 +163,12 @@ struct _PyGObject_Functions {
     void      (*register_class_init) (GType gtype, PyGClassInitFunc class_init);
     void      (*register_interface_info) (GType gtype, const GInterfaceInfo *info);
     void      (*closure_set_exception_handler) (GClosure *closure, PyClosureExceptionHandler handler);
+    int       (*object_constructv) (PyGObject  *self,
+                                    guint       n_parameters,
+                                    GParameter *parameters);
+    int       (*pygobject_construct) (PyGObject  *self,
+                                      const char *first_property_name,
+                                      ...);
 };
 
 #ifndef _INSIDE_PYGOBJECT_
@@ -217,6 +223,8 @@ struct _PyGObject_Functions *_PyGObject_
 #define pyg_enable_threads          (_PyGObject_API->enable_threads)
 #define pyg_register_class_init     (_PyGObject_API->register_class_init)
 #define pyg_register_interface_info (_PyGObject_API->register_interface_info)
+#define pygobject_construct         (_PyGObject_API->object_construct)
+#define pygobject_constructv        (_PyGObject_API->object_constructv)
 
 #define pyg_block_threads()   G_STMT_START {   \
     if (_PyGObject_API->block_threads != NULL) \
