Imported Upstream version 3.3.1
[platform/upstream/pygobject2.git] / gi / gimodule.c
index e14b4f6..6ccd87f 100644 (file)
  * USA
  */
 
-#include <Python.h>
-#include <glib-object.h>
-
-#include "config.h"
-#include "pyglib.h"
-#include "pyginterface.h"
-#include "pygi-repository.h"
-#include "pyglib.h"
-#include "pygtype.h"
-#include "pygenum.h"
-#include "pygboxed.h"
-#include "pygflags.h"
-#include "pygi-error.h"
-#include "pygi-foreign.h"
-#include "pygi-resulttuple.h"
-#include "pygi-source.h"
-#include "pygi-ccallback.h"
-#include "pygi-closure.h"
-#include "pygi-type.h"
-#include "pygi-boxed.h"
-#include "pygi-info.h"
-#include "pygi-struct.h"
-#include "pygobject-object.h"
-#include "pygoptioncontext.h"
-#include "pygoptiongroup.h"
-#include "pygspawn.h"
-#include "gobjectmodule.h"
-#include "pygparamspec.h"
-#include "pygpointer.h"
+#include "pygi-private.h"
+#include "pygi.h"
 
+#include <pygobject.h>
 #include <pyglib-python-compat.h>
 
-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,
-                       PyObject * (add_func) (PyObject *, const char *,
-                                              const char *, GType))
-{
-    PyObject *new_type;
-    GIRepository *repository;
-    GIBaseInfo *info;
-    const gchar *type_name;
-
-    repository = g_irepository_get_default ();
-    info = g_irepository_find_by_gtype (repository, g_type);
-    if (info != NULL) {
-        type_name = g_base_info_get_name (info);
-        new_type = add_func (NULL, type_name, NULL, g_type);
-        g_base_info_unref (info);
-    } else {
-        type_name = g_type_name (g_type);
-        new_type = add_func (NULL, type_name, NULL, g_type);
-    }
-
-    return new_type;
-}
-
-
 static PyObject *
 _wrap_pyg_enum_add (PyObject *self,
                     PyObject *args,
@@ -107,7 +47,7 @@ _wrap_pyg_enum_add (PyObject *self,
         return NULL;
     }
 
-    return flags_enum_from_gtype (g_type, pyg_enum_add);
+    return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type);
 }
 
 static PyObject *
@@ -121,9 +61,7 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
     gint n_values;
     GEnumValue *g_enum_values;
     int i;
-    const gchar *namespace;
     const gchar *type_name;
-    gchar *full_name;
     GType g_type;
 
     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
@@ -140,10 +78,6 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
 
     info = (GIEnumInfo *)py_info->info;
     n_values = g_enum_info_get_n_values (info);
-
-    /* The new memory is zero filled which fulfills the registration
-     * function requirement that the last item is zeroed out as a terminator.
-     */
     g_enum_values = g_new0 (GEnumValue, n_values + 1);
 
     for (i = 0; i < n_values; i++) {
@@ -170,40 +104,15 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
         g_base_info_unref ((GIBaseInfo *) value_info);
     }
 
-    /* Obfuscate the full_name by prefixing it with "Py" to avoid conflicts
-     * with real GTypes. See: https://bugzilla.gnome.org/show_bug.cgi?id=692515
-     */
-    namespace = g_base_info_get_namespace ((GIBaseInfo *) info);
-    type_name = g_base_info_get_name ((GIBaseInfo *) info);
-    full_name = g_strconcat ("Py", namespace, type_name, NULL);
-
-    /* If enum registration fails, free all the memory allocated
-     * for the values array. This needs to leak when successful
-     * as GObject keeps a reference to the data as specified in the docs.
-     */
-    g_type = g_enum_register_static (full_name, g_enum_values);
-    if (g_type == G_TYPE_INVALID) {
-        for (i = 0; i < n_values; i++) {
-            GEnumValue *enum_value = &g_enum_values[i];
-
-            /* Only free value_name if it is different from value_nick to avoid
-             * a double free. The pointer might have been is re-used in the case
-             * c_identifier was NULL in the above loop.
-             */
-            if (enum_value->value_name != enum_value->value_nick)
-                g_free ((gchar *) enum_value->value_name);
-            g_free ((gchar *) enum_value->value_nick);
-        }
+    g_enum_values[n_values].value = 0;
+    g_enum_values[n_values].value_nick = NULL;
+    g_enum_values[n_values].value_name = NULL;
 
-        PyErr_Format (PyExc_RuntimeError, "Unable to register enum '%s'", full_name);
-
-        g_free (g_enum_values);
-        g_free (full_name);
-        return NULL;
-    }
+    type_name = g_base_info_get_name ((GIBaseInfo *) info);
+    type_name = g_strdup (type_name);
+    g_type = g_enum_register_static (type_name, g_enum_values);
 
-    g_free (full_name);
-    return pyg_enum_add (NULL, type_name, NULL, g_type);
+    return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type);
 }
 
 static PyObject *
@@ -226,7 +135,7 @@ _wrap_pyg_flags_add (PyObject *self,
         return NULL;
     }
 
-    return flags_enum_from_gtype (g_type, pyg_flags_add);
+    return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type);
 }
 
 static PyObject *
@@ -240,9 +149,7 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
     gint n_values;
     GFlagsValue *g_flags_values;
     int i;
-    const gchar *namespace;
     const gchar *type_name;
-    gchar *full_name;
     GType g_type;
 
     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
@@ -259,10 +166,6 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
 
     info = (GIEnumInfo *)py_info->info;
     n_values = g_enum_info_get_n_values (info);
-
-    /* The new memory is zero filled which fulfills the registration
-     * function requirement that the last item is zeroed out as a terminator.
-     */
     g_flags_values = g_new0 (GFlagsValue, n_values + 1);
 
     for (i = 0; i < n_values; i++) {
@@ -289,46 +192,21 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
         g_base_info_unref ((GIBaseInfo *) value_info);
     }
 
-    /* Obfuscate the full_name by prefixing it with "Py" to avoid conflicts
-     * with real GTypes. See: https://bugzilla.gnome.org/show_bug.cgi?id=692515
-     */
-    namespace = g_base_info_get_namespace ((GIBaseInfo *) info);
-    type_name = g_base_info_get_name ((GIBaseInfo *) info);
-    full_name = g_strconcat ("Py", namespace, type_name, NULL);
-
-    /* If enum registration fails, free all the memory allocated
-     * for the values array. This needs to leak when successful
-     * as GObject keeps a reference to the data as specified in the docs.
-     */
-    g_type = g_flags_register_static (full_name, g_flags_values);
-    if (g_type == G_TYPE_INVALID) {
-        for (i = 0; i < n_values; i++) {
-            GFlagsValue *flags_value = &g_flags_values[i];
-
-            /* Only free value_name if it is different from value_nick to avoid
-             * a double free. The pointer might have been is re-used in the case
-             * c_identifier was NULL in the above loop.
-             */
-            if (flags_value->value_name != flags_value->value_nick)
-                g_free ((gchar *) flags_value->value_name);
-            g_free ((gchar *) flags_value->value_nick);
-        }
+    g_flags_values[n_values].value = 0;
+    g_flags_values[n_values].value_nick = NULL;
+    g_flags_values[n_values].value_name = NULL;
 
-        PyErr_Format (PyExc_RuntimeError, "Unable to register flags '%s'", full_name);
-
-        g_free (g_flags_values);
-        g_free (full_name);
-        return NULL;
-    }
+    type_name = g_base_info_get_name ((GIBaseInfo *) info);
+    type_name = g_strdup (type_name);
+    g_type = g_flags_register_static (type_name, g_flags_values);
 
-    g_free (full_name);
-    return pyg_flags_add (NULL, type_name, NULL, g_type);
+    return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type);
 }
 
 static void
 initialize_interface (GTypeInterface *iface, PyTypeObject *pytype)
 {
-    /* pygobject prints a warning if interface_init is NULL */
+    // pygobject prints a warning if interface_init is NULL
 }
 
 static PyObject *
@@ -522,105 +400,59 @@ _wrap_pyg_has_vfunc_implementation (PyObject *self, PyObject *args)
 #endif
 
 static PyObject *
-_wrap_pyg_variant_type_from_string (PyObject *self, PyObject *args)
+_wrap_pyg_variant_new_tuple (PyObject *self, PyObject *args)
 {
-    char *type_string;
-    PyObject *py_type;
+    PyObject *py_values;
+    GVariant **values = NULL;
+    GVariant *variant = NULL;
     PyObject *py_variant = NULL;
+    PyObject *py_type;
+    gssize i;
 
-    if (!PyArg_ParseTuple (args, "s:variant_type_from_string",
-                           &type_string)) {
+    if (!PyArg_ParseTuple (args, "O!:variant_new_tuple",
+                           &PyTuple_Type, &py_values)) {
         return NULL;
     }
 
-    py_type = _pygi_type_import_by_name ("GLib", "VariantType");
+    py_type = _pygi_type_import_by_name ("GLib", "Variant");
+
+    values = g_newa (GVariant*, PyTuple_Size (py_values));
+
+    for (i = 0; i < PyTuple_Size (py_values); i++) {
+        PyObject *value = PyTuple_GET_ITEM (py_values, i);
+
+        if (!PyObject_IsInstance (value, py_type)) {
+            PyErr_Format (PyExc_TypeError, "argument %" G_GSSIZE_FORMAT " is not a GLib.Variant", i);
+            return NULL;
+        }
+
+        values[i] = (GVariant *) ( (PyGPointer *) value)->pointer;
+    }
 
-    /* Pass the string directly and force a boxed copy. This works because
-     * GVariantType is just a char pointer. */
-    py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string,
-                                   TRUE, /* copy_boxed */
-                                   0);   /* slice_allocated */
+    variant = g_variant_new_tuple (values, PyTuple_Size (py_values));
+
+    py_variant = _pygi_struct_new ( (PyTypeObject *) py_type, variant, FALSE);
 
     return py_variant;
 }
 
 static PyObject *
-_wrap_pyg_source_new (PyObject *self, PyObject *args)
+_wrap_pyg_variant_type_from_string (PyObject *self, PyObject *args)
 {
-    return pyg_source_new ();
-}
-
-#define CHUNK_SIZE 8192
+    char *type_string;
+    PyObject *py_type;
+    PyObject *py_variant = NULL;
 
-static PyObject*
-pyg_channel_read(PyObject* self, PyObject *args, PyObject *kwargs)
-{
-    int max_count = -1;
-    PyObject *py_iochannel, *ret_obj = NULL;
-    gsize total_read = 0;
-    GError* error = NULL;
-    GIOStatus status = G_IO_STATUS_NORMAL;
-    GIOChannel *iochannel = NULL;
-
-    if (!PyArg_ParseTuple (args, "Oi:pyg_channel_read", &py_iochannel, &max_count)) {
-        return NULL;
-    }
-    if (!pyg_boxed_check (py_iochannel, G_TYPE_IO_CHANNEL)) {
-        PyErr_SetString(PyExc_TypeError, "first argument is not a GLib.IOChannel");
+    if (!PyArg_ParseTuple (args, "s:variant_type_from_string",
+                           &type_string)) {
         return NULL;
     }
-       
-    if (max_count == 0)
-        return PYGLIB_PyBytes_FromString("");
-
-    iochannel = pyg_boxed_get (py_iochannel, GIOChannel);
-
-    while (status == G_IO_STATUS_NORMAL
-          && (max_count == -1 || total_read < (gsize)max_count)) {
-       gsize single_read;
-       char* buf;
-       gsize buf_size;
-       
-       if (max_count == -1) 
-           buf_size = CHUNK_SIZE;
-       else {
-           buf_size = max_count - total_read;
-           if (buf_size > CHUNK_SIZE)
-               buf_size = CHUNK_SIZE;
-        }
-       
-       if ( ret_obj == NULL ) {
-           ret_obj = PYGLIB_PyBytes_FromStringAndSize((char *)NULL, buf_size);
-           if (ret_obj == NULL)
-               goto failure;
-       }
-       else if (buf_size + total_read > (gsize)PYGLIB_PyBytes_Size(ret_obj)) {
-           if (PYGLIB_PyBytes_Resize(&ret_obj, buf_size + total_read) == -1)
-               goto failure;
-       }
-       
-        buf = PYGLIB_PyBytes_AsString(ret_obj) + total_read;
-
-        Py_BEGIN_ALLOW_THREADS;
-        status = g_io_channel_read_chars (iochannel, buf, buf_size, &single_read, &error);
-        Py_END_ALLOW_THREADS;
-
-        if (pygi_error_check (&error))
-           goto failure;
-       
-       total_read += single_read;
-    }
-       
-    if ( total_read != (gsize)PYGLIB_PyBytes_Size(ret_obj) ) {
-       if (PYGLIB_PyBytes_Resize(&ret_obj, total_read) == -1)
-           goto failure;
-    }
 
-    return ret_obj;
+    py_type = _pygi_type_import_by_name ("GLib", "VariantType");
+
+    py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE);
 
-  failure:
-    Py_XDECREF(ret_obj);
-    return NULL;
+    return py_variant;
 }
 
 static PyMethodDef _gi_functions[] = {
@@ -631,112 +463,37 @@ static PyMethodDef _gi_functions[] = {
 
     { "register_interface_info", (PyCFunction) _wrap_pyg_register_interface_info, METH_VARARGS },
     { "hook_up_vfunc_implementation", (PyCFunction) _wrap_pyg_hook_up_vfunc_implementation, METH_VARARGS },
+    { "variant_new_tuple", (PyCFunction) _wrap_pyg_variant_new_tuple, METH_VARARGS },
     { "variant_type_from_string", (PyCFunction) _wrap_pyg_variant_type_from_string, METH_VARARGS },
-    { "source_new", (PyCFunction) _wrap_pyg_source_new, METH_NOARGS },
-    { "source_set_callback", (PyCFunction) pyg_source_set_callback, METH_VARARGS },
-    { "io_channel_read", (PyCFunction) pyg_channel_read, METH_VARARGS },
-    { "require_foreign", (PyCFunction) pygi_require_foreign, METH_VARARGS | METH_KEYWORDS },
-    { "spawn_async",
-      (PyCFunction)pyglib_spawn_async, METH_VARARGS|METH_KEYWORDS,
-      "spawn_async(argv, envp=None, working_directory=None,\n"
-      "            flags=0, child_setup=None, user_data=None,\n"
-      "            standard_input=None, standard_output=None,\n"
-      "            standard_error=None) -> (pid, stdin, stdout, stderr)\n"
-      "\n"
-      "Execute a child program asynchronously within a glib.MainLoop()\n"
-      "See the reference manual for a complete reference.\n" },
-    { "type_name", pyg_type_name, METH_VARARGS },
-    { "type_from_name", pyg_type_from_name, METH_VARARGS },
-    { "type_is_a", pyg_type_is_a, METH_VARARGS },
-    { "type_register", _wrap_pyg_type_register, METH_VARARGS },
-    { "signal_new", pyg_signal_new, METH_VARARGS },
-    { "list_properties",
-      pyg_object_class_list_properties, METH_VARARGS },
-    { "new",
-      (PyCFunction)pyg_object_new, METH_VARARGS|METH_KEYWORDS },
-    { "signal_accumulator_true_handled",
-      (PyCFunction)pyg_signal_accumulator_true_handled, METH_VARARGS },
-    { "add_emission_hook",
-      (PyCFunction)pyg_add_emission_hook, METH_VARARGS },
-    { "_install_metaclass",
-      (PyCFunction)pyg__install_metaclass, METH_O },
-    { "_gvalue_get",
-      (PyCFunction)pyg__gvalue_get, METH_O },
-    { "_gvalue_set",
-      (PyCFunction)pyg__gvalue_set, METH_VARARGS },
     { NULL, NULL, 0 }
 };
 
 static struct PyGI_API CAPI = {
-  pygi_register_foreign_struct,
+  pygi_type_import_by_g_type_real,
+  pygi_get_property_value_real,
+  pygi_set_property_value_real,
+  pygi_signal_closure_new_real,
+  pygi_register_foreign_struct_real,
 };
 
 PYGLIB_MODULE_START(_gi, "_gi")
 {
     PyObject *api;
-    PyObject *module_dict = PyModule_GetDict (module);
 
-    /* Always enable Python threads since we cannot predict which GI repositories
-     * might accept Python callbacks run within non-Python threads or might trigger
-     * toggle ref notifications.
-     * See: https://bugzilla.gnome.org/show_bug.cgi?id=709223
-     */
-    PyEval_InitThreads ();
+    if (pygobject_init (-1, -1, -1) == NULL) {
+        return PYGLIB_MODULE_ERROR_RETURN;
+    }
 
-    PyModule_AddStringConstant(module, "__package__", "gi._gi");
+    if (_pygobject_import() < 0) {
+        return PYGLIB_MODULE_ERROR_RETURN;
+    }
 
-    pygi_foreign_init ();
-    pygi_error_register_types (module);
     _pygi_repository_register_types (module);
     _pygi_info_register_types (module);
     _pygi_struct_register_types (module);
     _pygi_boxed_register_types (module);
     _pygi_ccallback_register_types (module);
-    pygi_resulttuple_register_types (module);
-
-    pyglib_spawn_register_types (module_dict);
-    pyglib_option_context_register_types (module_dict);
-    pyglib_option_group_register_types (module_dict);
-
-    pygobject_register_api (module_dict);
-    pygobject_register_constants (module);
-    pygobject_register_features (module_dict);
-    pygobject_register_version_tuples (module_dict);
-    pygobject_register_warnings (module_dict);
-    pygobject_type_register_types (module_dict);
-    pygobject_object_register_types (module_dict);
-    pygobject_interface_register_types (module_dict);
-    pygobject_paramspec_register_types (module_dict);
-    pygobject_boxed_register_types (module_dict);
-    pygobject_pointer_register_types (module_dict);
-    pygobject_enum_register_types (module_dict);
-    pygobject_flags_register_types (module_dict);
-
-    PyGIWarning = PyErr_NewException ("gi.PyGIWarning", PyExc_Warning, NULL);
-
-    /* Use RuntimeWarning as the base class of PyGIDeprecationWarning
-     * for unstable (odd minor version) and use DeprecationWarning for
-     * stable (even minor version). This is so PyGObject deprecations
-     * behave the same as regular Python deprecations in stable releases.
-     */
-#if PYGOBJECT_MINOR_VERSION % 2
-    PyGIDeprecationWarning = PyErr_NewException("gi.PyGIDeprecationWarning",
-                                                PyExc_RuntimeWarning, NULL);
-#else
-    PyGIDeprecationWarning = PyErr_NewException("gi.PyGIDeprecationWarning",
-                                                PyExc_DeprecationWarning, NULL);
-#endif
-
-    /* Place holder object used to fill in "from Python" argument lists
-     * for values not supplied by the caller but support a GI default.
-     */
-    _PyGIDefaultArgPlaceholder = PyObject_New(PyObject, &PyType_Type);
-
-    Py_INCREF (PyGIWarning);
-    PyModule_AddObject (module, "PyGIWarning", PyGIWarning);
-
-    Py_INCREF(PyGIDeprecationWarning);
-    PyModule_AddObject(module, "PyGIDeprecationWarning", PyGIDeprecationWarning);
+    _pygi_argument_init();
 
     api = PYGLIB_CPointer_WrapPointer ( (void *) &CAPI, "gi._API");
     if (api == NULL) {