Index: bonobo/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-python/gnome-python/bonobo/Makefile.am,v
retrieving revision 1.16
diff -u -r1.16 Makefile.am
--- bonobo/Makefile.am	25 Feb 2003 14:29:50 -0000	1.16
+++ bonobo/Makefile.am	7 Apr 2003 23:49:16 -0000
@@ -46,7 +46,7 @@
 _bonobomodule_la_CFLAGS = $(BONOBO_CFLAGS)
 _bonobomodule_la_LDFLAGS = -module -avoid-version -export-symbols-regex init_bonobo
 _bonobomodule_la_LIBADD = $(BONOBO_LIBS)
-_bonobomodule_la_SOURCES = bonobomodule.c bonobo-arg.c
+_bonobomodule_la_SOURCES = bonobomodule.c bonobo-arg.c bonobo-unknown.c
 nodist__bonobomodule_la_SOURCES = bonobo.c
 CLEANFILES += bonobo.c
 EXTRA_DIST += bonobo.override
Index: bonobo/bonobo-unknown.c
===================================================================
RCS file: bonobo/bonobo-unknown.c
diff -N bonobo/bonobo-unknown.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-unknown.c	7 Apr 2003 23:49:17 -0000
@@ -0,0 +1,326 @@
+/* -*- mode: C; c-basic-offset: 4 -*- */
+ 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Python.h>
+#include <pyorbit.h>
+#include <pygobject.h>
+#define BONOBO_PRIVATE
+#include <bonobo/bonobo-object.h>
+
+
+static PyTypeObject *_PyPortableServer_Servant_Type;
+#define PyPortableServer_Servant_Type (*_PyPortableServer_Servant_Type)
+extern PyTypeObject PyBonobo_Unknown_Type;
+extern PyTypeObject PyBonoboObject_Type;
+
+
+typedef struct _PyBonobo_Unknown PyBonobo_Unknown;
+
+typedef struct {
+    int     ref_count;		/* Bonobo::Object ref_count */
+    GSList *objs;		/* list of PyBonobo_Unknown */
+} AggregateObject;
+
+
+struct _PyBonobo_Unknown {
+    PyObject_HEAD
+    PyObject        *servant;
+    AggregateObject *ao;	/* if bonobo_object != NULL, this is
+				 * no longer used */
+    BonoboObject    *bonobo_object;
+};
+
+
+static void
+pybonobo_unknown_dealloc(PyBonobo_Unknown *self)
+{
+    GSList *l;
+
+    Py_XDECREF(self->servant);
+    for (l = self->ao->objs; l; l = l->next)
+    {
+	PyBonobo_Unknown *other = l->data;
+	if (other != self) {
+	    Py_DECREF(other);
+	}
+    }
+    self->ao->objs = g_slist_remove(self->ao->objs, self);
+    if (self->ao->objs == NULL)
+	g_free(self->ao);
+}
+
+
+static int
+pybonobo_unknown_init(PyBonobo_Unknown *self, PyObject *args)
+{
+    if (!PyArg_ParseTuple(args, "O!:bonobo.Unknown.__init__",
+			  &PyPortableServer_Servant_Type,
+			  &self->servant))
+        return -1;
+
+    Py_INCREF(self->servant);
+    PyObject_SetAttrString(self->servant, "_delegate", (PyObject *) self);
+    self->ao = g_new0(AggregateObject, 1);
+    self->ao->ref_count = 1;
+    self->bonobo_object = NULL;
+    self->ao->objs = g_slist_prepend(self->ao->objs, self);
+    return 0;
+}
+
+
+static PyObject *
+pybonobo_unknown_queryInterface(PyBonobo_Unknown *self, PyObject *args)
+{
+    Bonobo_Unknown  match_obj = CORBA_OBJECT_NIL;
+    char           *repo_id;
+    GSList         *l;
+    PyObject       *retval;
+
+    if (!PyArg_ParseTuple(args, "s:bonobo.Unknown.queryInterface", &repo_id))
+        return NULL;
+
+    if (self->bonobo_object)
+	match_obj = bonobo_object_query_interface(self->bonobo_object,
+						  repo_id, NULL);
+    else {
+	for (l = self->ao->objs; l; l = l->next)
+	{
+	    PyBonobo_Unknown *other = l->data;
+	    PyObject         *this;
+	    CORBA_Object      objref;
+	    CORBA_char       *type_id;
+	    gboolean          match;
+
+	    this = PyObject_CallMethod(other->servant, "_this", NULL);
+	    g_assert(PyObject_TypeCheck(this, &PyCORBA_Object_Type));
+	    objref = ((PyCORBA_Object *) this)->objref;
+	    type_id = ORBit_small_get_type_id(objref, NULL);
+	    match = (strcmp(repo_id, type_id) == 0);
+	    CORBA_free(type_id);
+	    Py_DECREF(this);
+	    if (match) {
+		match_obj = CORBA_Object_duplicate(objref, NULL);
+		break;
+	    }
+	}
+    }
+    if (match_obj == CORBA_OBJECT_NIL) {
+	Py_INCREF(Py_None);
+	return Py_None;
+    }
+    retval = pycorba_object_new(match_obj);
+    CORBA_Object_release(match_obj, NULL);
+    return retval;
+}
+
+
+static void
+_bonobo_object_destroyed(gpointer data)
+{
+    PyObject *obj = data;
+    Py_DECREF(obj);
+}
+
+
+static void
+pybonobo_unknown_aggregate(PyBonobo_Unknown *self, PyBonobo_Unknown *other)
+{
+    self->ao->objs = g_slist_append(self->ao->objs, other->ao->objs);
+    g_slist_free(other->ao->objs);
+    g_free(other->ao);
+    other->ao = self->ao;
+}
+
+
+void
+pybonobo_unknown_aggregate_with_bonobo_object(PyObject     *obj,
+					      BonoboObject *bonobo_object)
+{
+    GSList           *l;
+    PyBonobo_Unknown *self = (PyBonobo_Unknown *) obj;
+
+    for (l = self->ao->objs; l; l = l->next)
+    {
+	PyBonobo_Unknown *unknown = l->data;
+	PyObject         *pyobjref;
+	CORBA_Object      objref;
+	
+	g_assert(unknown->bonobo_object == NULL);
+	unknown->bonobo_object = bonobo_object;
+	pyobjref = PyObject_CallMethod(unknown->servant, "_this", NULL);
+	g_assert(PyObject_TypeCheck(pyobjref, &PyCORBA_Object_Type));
+	objref = ((PyCORBA_Object *) pyobjref)->objref;
+	Py_INCREF(unknown);
+	bonobo_object_add_foreign_interface(bonobo_object, objref,
+					    _bonobo_object_destroyed,
+					    unknown);
+	Py_DECREF(pyobjref);
+    }
+}
+
+
+static PyObject *
+pybonobo_unknown_add_interface(PyBonobo_Unknown *self, PyObject *args)
+{
+    PyObject *other;
+
+    if (!PyArg_ParseTuple(args, "O:bonobo.Unknown.add_interface", &other))
+        return NULL;
+
+    if (PyObject_TypeCheck(other, &PyBonobo_Unknown_Type)) {
+	PyBonobo_Unknown *other_unknown = (PyBonobo_Unknown *) other;
+	if (self->bonobo_object)
+	    pybonobo_unknown_aggregate_with_bonobo_object
+		((PyObject *) other_unknown, self->bonobo_object);
+	else if (other_unknown->bonobo_object)
+	    pybonobo_unknown_aggregate_with_bonobo_object
+		((PyObject *) self, other_unknown->bonobo_object);
+	else
+	    pybonobo_unknown_aggregate(self, other_unknown);
+    } else if (PyObject_TypeCheck(other, &PyBonoboObject_Type))
+    {
+	BonoboObject *bonobo_object;
+
+	bonobo_object = BONOBO_OBJECT(((PyGObject *) other)->obj);
+	if (self->bonobo_object)
+	    bonobo_object_add_interface(self->bonobo_object, bonobo_object);
+	else
+	    pybonobo_unknown_aggregate_with_bonobo_object
+		((PyObject *) self, bonobo_object);
+    } else {
+	PyErr_SetString (PyExc_TypeError, "argument must be either "
+			 "bonobo.Object or bonobo.Unknown");
+	return NULL;
+    }
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+
+static PyObject *
+pybonobo_unknown_ref(PyBonobo_Unknown *self)
+{
+    if (self->bonobo_object)
+	bonobo_object_ref(self->bonobo_object);
+    else
+	++self->ao->ref_count;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+
+static PyObject *
+pybonobo_unknown_unref(PyBonobo_Unknown *self)
+{
+    if (self->bonobo_object)
+	bonobo_object_unref(self->bonobo_object);
+    else
+	--self->ao->ref_count;
+    if (self->ao->ref_count == 0)
+    {
+	GSList *l;
+
+	for (l = self->ao->objs; l; l = l->next)
+	{
+	    PyBonobo_Unknown *unknown = l->data;
+	    Py_XDECREF(unknown->servant);
+	    unknown->servant = NULL;
+	}
+    }
+    if (self->ao->ref_count < 0)
+	g_warning("self->ao->ref_count == %i", self->ao->ref_count);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+
+static PyMethodDef pybonobo_unknown_methods[] = {
+    { "queryInterface", (PyCFunction)pybonobo_unknown_queryInterface, METH_VARARGS },
+    { "add_interface", (PyCFunction)pybonobo_unknown_add_interface, METH_VARARGS },
+    { "ref", (PyCFunction)pybonobo_unknown_ref, METH_NOARGS },
+    { "unref", (PyCFunction)pybonobo_unknown_unref, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+
+PyTypeObject PyBonobo_Unknown_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                  /* ob_size */
+    "Unknown",           		/* tp_name */
+    sizeof(PyBonobo_Unknown),   	/* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    /* methods */
+    (destructor)pybonobo_unknown_dealloc, /* tp_dealloc */
+    (printfunc)0,                       /* tp_print */
+    (getattrfunc)0,                     /* tp_getattr */
+    (setattrfunc)0,                     /* tp_setattr */
+    (cmpfunc)0,                         /* tp_compare */
+    (reprfunc)0,     			/* tp_repr */
+    0,                                  /* tp_as_number */
+    0,                                  /* tp_as_sequence */
+    0,                                  /* tp_as_mapping */
+    (hashfunc)0,                        /* tp_hash */
+    (ternaryfunc)0,                     /* tp_call */
+    (reprfunc)0,                        /* tp_str */
+    (getattrofunc)0,                    /* tp_getattro */
+    (setattrofunc)0,                    /* tp_setattro */
+    0,                                  /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */
+    NULL, 				/* Documentation string */
+    (traverseproc)0,                    /* tp_traverse */
+    (inquiry)0,                         /* tp_clear */
+    (richcmpfunc)0,                     /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    (getiterfunc)0,                     /* tp_iter */
+    (iternextfunc)0,                    /* tp_iternext */
+    pybonobo_unknown_methods,           /* tp_methods */
+    0,            			/* tp_members */
+    0,                                  /* tp_getset */
+    (PyTypeObject *)0,                  /* tp_base */
+    (PyObject *)0,                      /* tp_dict */
+    (descrgetfunc)0,                    /* tp_descr_get */
+    0,                                  /* tp_descr_set */
+    0,                                  /* tp_dictoffset */
+    (initproc)pybonobo_unknown_init,    /* tp_init */
+    0,                                  /* tp_alloc */
+    (newfunc)0,      			/* tp_new */
+    0,                                  /* tp_free */
+    (inquiry)0,                         /* tp_is_gc */
+    (PyObject *)0,                      /* tp_bases */
+};
+
+
+void pybonobo_unknown_register_classes(PyObject *dict)
+{
+    PyObject *module;
+
+    /* (copy-paste from ORBitmodule.c) */
+#define INIT_TYPE(tp) G_STMT_START{ \
+    if (!tp.ob_type)  tp.ob_type  = &PyType_Type; \
+    if (!tp.tp_alloc) tp.tp_alloc = PyType_GenericAlloc; \
+    if (!tp.tp_new)   tp.tp_new   = PyType_GenericNew; \
+    if (PyType_Ready(&tp) < 0) \
+        return; }G_STMT_END
+
+    INIT_TYPE(PyBonobo_Unknown_Type);
+
+#undef INIT_TYPE
+
+    if ((module = PyImport_ImportModule("PortableServer")) != NULL) {
+        PyObject *moddict = PyModule_GetDict(module);
+
+        _PyPortableServer_Servant_Type =
+	    (PyTypeObject *) PyDict_GetItemString(moddict, "Servant");
+    } else {
+        Py_FatalError("could not import ORBit");
+        return;
+    }
+
+    PyDict_SetItemString(dict, "Unknown", (PyObject *) &PyBonobo_Unknown_Type);
+
+}
+
Index: bonobo/bonobo.override
===================================================================
RCS file: /cvs/gnome/gnome-python/gnome-python/bonobo/bonobo.override,v
retrieving revision 1.14
diff -u -r1.14 bonobo.override
--- bonobo/bonobo.override	26 Jan 2003 19:37:44 -0000	1.14
+++ bonobo/bonobo.override	7 Apr 2003 23:49:17 -0000
@@ -9,6 +9,11 @@
 #include <libbonobo.h>
 #include <bonobo/bonobo-persist-client.h>
 #include <bonobo/bonobo-item-handler.h>
+
+extern PyTypeObject PyBonobo_Unknown_Type;
+void pybonobo_unknown_aggregate_with_bonobo_object(PyObject     *obj,
+						   BonoboObject *bonobo_object);
+
 %%
 modulename bonobo
 %%
@@ -240,4 +245,32 @@
     pygobject_register_wrapper ((PyObject *)self);
     
     return 0;
+}
+
+%%
+override bonobo_object_add_interface kwargs
+static PyObject *
+_wrap_bonobo_object_add_interface(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "newobj", NULL };
+    PyObject *newobj;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:BonoboObject.add_interface",
+				     kwlist, &newobj))
+        return NULL;
+
+    if (PyObject_TypeCheck(newobj, &PyBonoboObject_Type))
+	bonobo_object_add_interface(BONOBO_OBJECT(self->obj),
+				    BONOBO_OBJECT(((PyGObject *)newobj)->obj));
+    else if (PyObject_TypeCheck(newobj, &PyBonobo_Unknown_Type))
+	pybonobo_unknown_aggregate_with_bonobo_object
+	    (newobj, BONOBO_OBJECT(self->obj));
+    else {
+	PyErr_SetString (PyExc_TypeError, "argument must be either "
+			 "bonobo.Object or bonobo.Unknown");
+	return NULL;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
 }
Index: bonobo/bonobomodule.c
===================================================================
RCS file: /cvs/gnome/gnome-python/gnome-python/bonobo/bonobomodule.c,v
retrieving revision 1.5
diff -u -r1.5 bonobomodule.c
--- bonobo/bonobomodule.c	11 Jan 2003 23:32:38 -0000	1.5
+++ bonobo/bonobomodule.c	7 Apr 2003 23:49:17 -0000
@@ -10,6 +10,8 @@
 
 void _pybonobo_register_boxed_types(PyObject *moddict);
 void pybonobo_register_classes(PyObject *d);
+void pybonobo_unknown_register_classes(PyObject *d);
+
 extern PyMethodDef pybonobo_functions[];
 
 DL_EXPORT(void)
@@ -53,6 +55,7 @@
 
     _pybonobo_register_boxed_types(d);
     pybonobo_register_classes(d);
+    pybonobo_unknown_register_classes(d);
 
     /* add anything else to the module dictionary (such as constants) */
 
Index: examples/bonobo/unknown.py
===================================================================
RCS file: examples/bonobo/unknown.py
diff -N examples/bonobo/unknown.py
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ examples/bonobo/unknown.py	7 Apr 2003 23:49:17 -0000
@@ -0,0 +1,26 @@
+#! /usr/bin/env python
+
+import pygtk
+pygtk.require("2.0")
+
+import bonobo
+import Bonobo
+import Bonobo__POA
+import CORBA, sys
+
+orb = CORBA.ORB_init(sys.argv)
+bonobo.activate()
+    
+class PersistStream(bonobo.Unknown):
+    def __init__(self):
+	servant = Bonobo__POA.PersistStream()
+	self._this = servant._this()
+	bonobo.Unknown.__init__(self, servant)
+
+
+ps = PersistStream()
+psref = ps._this
+
+print psref.queryInterface("IDL:Bonobo/PersistStream:1.0")
+psref.unref()
+
