diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:41:54 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:41:58 +0900 |
commit | 4bfc3de521c8d93613e5153028da35406609a64f (patch) | |
tree | 98175ed0ab42bc56bec3d45d69364a988a00de1f /gi | |
parent | 5a89ec21697bd9e08c9102b2a7b6c60b4652e66c (diff) | |
download | pygobject2-4bfc3de521c8d93613e5153028da35406609a64f.tar.gz pygobject2-4bfc3de521c8d93613e5153028da35406609a64f.tar.bz2 pygobject2-4bfc3de521c8d93613e5153028da35406609a64f.zip |
Imported Upstream version 3.13.2
Change-Id: Icce9be2c1bf0568fc95f75ff0a714c017e6171ec
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi')
51 files changed, 1058 insertions, 686 deletions
diff --git a/gi/Makefile.am b/gi/Makefile.am index b00d30a..6fb1c5d 100644 --- a/gi/Makefile.am +++ b/gi/Makefile.am @@ -71,6 +71,7 @@ _gi_la_SOURCES = \ pygi-info.h \ pygi-foreign.c \ pygi-foreign.h \ + pygi-foreign-api.h \ pygi-struct.c \ pygi-struct.h \ pygi-source.c \ @@ -139,12 +140,14 @@ _gi_cairo_la_SOURCES = \ pygi-foreign-cairo.c _gi_cairo_la_CFLAGS = \ $(GI_CFLAGS) \ + $(CAIRO_CFLAGS) \ $(PYCAIRO_CFLAGS) _gi_cairo_la_CPPFLAGS = \ $(extension_cppflags) _gi_cairo_la_LIBADD = \ $(extension_libadd) \ $(GI_LIBS) \ + $(CAIRO_LIBS) \ $(PYCAIRO_LIBS) _gi_cairo_la_LDFLAGS = \ $(extension_ldflags) \ diff --git a/gi/Makefile.in b/gi/Makefile.in index 82ee5e7..256b41a 100644 --- a/gi/Makefile.in +++ b/gi/Makefile.in @@ -155,7 +155,8 @@ _gi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(_gi_la_CFLAGS) $(CFLAGS) \ $(_gi_la_LDFLAGS) $(LDFLAGS) -o $@ _gi_cairo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) am__gi_cairo_la_OBJECTS = _gi_cairo_la-pygi-foreign-cairo.lo _gi_cairo_la_OBJECTS = $(am__gi_cairo_la_OBJECTS) _gi_cairo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -492,6 +493,7 @@ _gi_la_SOURCES = \ pygi-info.h \ pygi-foreign.c \ pygi-foreign.h \ + pygi-foreign-api.h \ pygi-struct.c \ pygi-struct.h \ pygi-source.c \ @@ -561,6 +563,7 @@ _gi_cairo_la_SOURCES = \ _gi_cairo_la_CFLAGS = \ $(GI_CFLAGS) \ + $(CAIRO_CFLAGS) \ $(PYCAIRO_CFLAGS) _gi_cairo_la_CPPFLAGS = \ @@ -569,6 +572,7 @@ _gi_cairo_la_CPPFLAGS = \ _gi_cairo_la_LIBADD = \ $(extension_libadd) \ $(GI_LIBS) \ + $(CAIRO_LIBS) \ $(PYCAIRO_LIBS) _gi_cairo_la_LDFLAGS = \ diff --git a/gi/__init__.py b/gi/__init__.py index 7c1a279..df6843c 100644 --- a/gi/__init__.py +++ b/gi/__init__.py @@ -26,6 +26,7 @@ __path__ = extend_path(__path__, __name__) import sys import os +import importlib # we can't have pygobject 2 loaded at the same time we load the internal _gobject if 'gobject' in sys.modules: @@ -33,6 +34,7 @@ if 'gobject' in sys.modules: 'modules like "gobject". Please change all occurrences ' 'of "import gobject" to "from gi.repository import GObject".') +from . import _gi from ._gi import _gobject from ._gi import _API from ._gi import Repository @@ -87,3 +89,29 @@ def require_version(namespace, version): def get_required_version(namespace): return _versions.get(namespace, None) + + +def require_foreign(namespace, symbol=None): + """Ensure the given foreign marshaling module is available and loaded. + + :param str namespace: + Introspection namespace of the foreign module (e.g. "cairo") + :param symbol: + Optional symbol typename to ensure a converter exists. + :type symbol: str or None + :raises: ImportError + + :Example: + + .. code-block:: python + + import gi + import cairo + gi.require_foreign('cairo') + + """ + try: + _gi.require_foreign(namespace, symbol) + except Exception as e: + raise ImportError(str(e)) + importlib.import_module('gi.repository', namespace) diff --git a/gi/_error.py b/gi/_error.py new file mode 100644 index 0000000..6b684ce --- /dev/null +++ b/gi/_error.py @@ -0,0 +1,54 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab +# +# Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org> +# +# _error.py: GError Python implementation +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# USA + + +# NOTE: This file should not have any dependencies on introspection libs +# like gi.repository.GLib because it would cause a circular dependency. +# Developers wanting to use the GError class in their applications should +# use gi.repository.GLib.GError + + +class GError(RuntimeError): + def __init__(self, message='unknown error', domain='pygi-error', code=0): + super(GError, self).__init__(message) + self.message = message + self.domain = domain + self.code = code + + def __str__(self): + return "%s: %s (%d)" % (self.domain, self.message, self.code) + + def __repr__(self): + return "%s.%s('%s', '%s', %d)" % (GError.__module__, GError.__name__, + self.message, self.domain, self.code) + + def copy(self): + return GError(self.message, self.domain, self.code) + + def matches(self, domain, code): + """Placeholder that will be monkey patched in GLib overrides.""" + raise NotImplementedError + + @staticmethod + def new_literal(domain, message, code): + """Placeholder that will be monkey patched in GLib overrides.""" + raise NotImplementedError diff --git a/gi/_option.py b/gi/_option.py index 422c53f..2d30abf 100644 --- a/gi/_option.py +++ b/gi/_option.py @@ -41,6 +41,7 @@ else: _bytes = str from gi._gi import _glib +from gi._error import GError GLib = get_introspection_module('GLib') OPTION_CONTEXT_ERROR_QUARK = GLib.quark_to_string(GLib.option_error_quark()) @@ -202,7 +203,7 @@ class OptionGroup(optparse.OptionGroup): opt.process(option_name, option_value, self.values, parser) except OptionValueError: error = sys.exc_info()[1] - gerror = _glib.GError(str(error)) + gerror = GError(str(error)) gerror.domain = OPTION_CONTEXT_ERROR_QUARK gerror.code = GLib.OptionError.BAD_VALUE gerror.message = str(error) @@ -347,7 +348,7 @@ class OptionParser(optparse.OptionParser): try: options, args = optparse.OptionParser.parse_args( self, args, values) - except _glib.GError: + except GError: error = sys.exc_info()[1] if error.domain != OPTION_CONTEXT_ERROR_QUARK: raise diff --git a/gi/gimodule.c b/gi/gimodule.c index 25fc3d6..44a8fbd 100644 --- a/gi/gimodule.c +++ b/gi/gimodule.c @@ -27,6 +27,8 @@ #include "pygi-private.h" #include "pygi.h" #include "pyglib.h" +#include "pygi-error.h" +#include "pygi-foreign.h" #include <pyglib-python-compat.h> @@ -494,7 +496,7 @@ _wrap_pyg_variant_new_tuple (PyObject *self, PyObject *args) return NULL; } - values[i] = (GVariant *) ( (PyGPointer *) value)->pointer; + values[i] = pyg_pointer_get (value, GVariant); } variant = g_variant_new_tuple (values, PyTuple_Size (py_values)); @@ -584,7 +586,7 @@ pyg_channel_read(PyObject* self, PyObject *args, PyObject *kwargs) status = g_io_channel_read_chars (iochannel, buf, buf_size, &single_read, &error); Py_END_ALLOW_THREADS; - if (pyglib_error_check(&error)) + if (pygi_error_check (&error)) goto failure; total_read += single_read; @@ -615,15 +617,12 @@ static PyMethodDef _gi_functions[] = { { "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 }, { NULL, NULL, 0 } }; static struct PyGI_API CAPI = { - 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, + pygi_register_foreign_struct, }; PYGLIB_MODULE_START(_gi, "_gi") @@ -664,12 +663,14 @@ PYGLIB_MODULE_START(_gi, "_gi") PyModule_AddObject (module, "_gobject", _gobject_module); PyModule_AddStringConstant(module, "__package__", "gi._gi"); + 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_argument_init(); + _pygi_argument_init (); /* Use RuntimeWarning as the base class of PyGIDeprecationWarning * for unstable (odd minor version) and use DeprecationWarning for diff --git a/gi/glibmodule.c b/gi/glibmodule.c index e859158..297805a 100644 --- a/gi/glibmodule.c +++ b/gi/glibmodule.c @@ -31,8 +31,6 @@ #include "pygoptiongroup.h" #include "pygspawn.h" -PyObject *PyGError = NULL; - /* ---------------- glib module functions -------------------- */ static PyMethodDef _glib_functions[] = { @@ -48,27 +46,10 @@ static PyMethodDef _glib_functions[] = { { NULL, NULL, 0 } }; -static void -pyglib_register_error(PyObject *d) -{ - PyObject *dict; - dict = PyDict_New(); - /* This is a hack to work around the deprecation warning of - * BaseException.message in Python 2.6+. - * GError has also an "message" attribute. - */ - PyDict_SetItemString(dict, "message", Py_None); - PyGError = PyErr_NewException("gi._glib.GError", PyExc_RuntimeError, dict); - Py_DECREF(dict); - - PyDict_SetItemString(d, "GError", PyGError); -} - PYGLIB_MODULE_START(_glib, "_glib") { PyObject *d = PyModule_GetDict(module); - pyglib_register_error(d); pyglib_spawn_register_types(d); pyglib_option_context_register_types(d); pyglib_option_group_register_types(d); diff --git a/gi/gobjectmodule.c b/gi/gobjectmodule.c index a20d93a..458884b 100644 --- a/gi/gobjectmodule.c +++ b/gi/gobjectmodule.c @@ -37,6 +37,7 @@ #include "pygoptiongroup.h" #include "pygi-value.h" +#include "pygi-error.h" static GHashTable *log_handlers = NULL; static gboolean log_handlers_disabled = FALSE; @@ -1834,55 +1835,6 @@ pyg_flags_add_constants(PyObject *module, GType flags_type, } /** - * pyg_error_check: - * @error: a pointer to the GError. - * - * Checks to see if the GError has been set. If the error has been - * set, then the gobject.GError Python exception will be raised, and - * the GError cleared. - * - * Returns: True if an error was set. - * - * Deprecated: Since 2.16, use pyglib_error_check instead. - */ -gboolean -pyg_error_check(GError **error) -{ -#if 0 - if (PyErr_Warn(PyExc_DeprecationWarning, - "pyg_error_check is deprecated, use " - "pyglib_error_check instead")) - return NULL; -#endif - return pyglib_error_check(error); -} - -/** - * pyg_gerror_exception_check: - * @error: a standard GLib GError ** output parameter - * - * Checks to see if a GError exception has been raised, and if so - * translates the python exception to a standard GLib GError. If the - * raised exception is not a GError then PyErr_Print() is called. - * - * Returns: 0 if no exception has been raised, -1 if it is a - * valid gobject.GError, -2 otherwise. - * - * Deprecated: Since 2.16, use pyglib_gerror_exception_check instead. - */ -gboolean -pyg_gerror_exception_check(GError **error) -{ -#if 0 - if (PyErr_Warn(PyExc_DeprecationWarning, - "pyg_gerror_exception_check is deprecated, use " - "pyglib_gerror_exception_check instead")) - return NULL; -#endif - return pyglib_gerror_exception_check(error); -} - -/** * 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 @@ -2055,7 +2007,7 @@ struct _PyGObject_Functions pygobject_api_functions = { pyg_constant_strip_prefix, - pyg_error_check, + pygi_error_check, _pyg_set_thread_block_funcs, (PyGThreadBlockFunc)0, /* block_threads */ @@ -2098,7 +2050,7 @@ struct _PyGObject_Functions pygobject_api_functions = { NULL, /* previously type_register_custom */ - pyg_gerror_exception_check, + pygi_gerror_exception_check, pyg_option_group_new, pyg_type_from_object_strict, diff --git a/gi/overrides/GIMarshallingTests.py b/gi/overrides/GIMarshallingTests.py index cc967b4..b675adf 100644 --- a/gi/overrides/GIMarshallingTests.py +++ b/gi/overrides/GIMarshallingTests.py @@ -53,13 +53,13 @@ class OverridesObject(GIMarshallingTests.OverridesObject): def __init__(self, long_): GIMarshallingTests.OverridesObject.__init__(self) # FIXME: doesn't work yet - #self.long_ = long_ + # self.long_ = long_ @classmethod def new(cls, long_): self = GIMarshallingTests.OverridesObject.new() # FIXME: doesn't work yet - #self.long_ = long_ + # self.long_ = long_ return self def method(self): diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py index 0e8f694..214d507 100644 --- a/gi/overrides/GLib.py +++ b/gi/overrides/GLib.py @@ -40,7 +40,9 @@ __all__.append('option') # Types and functions still needed from static bindings from gi._gi import _glib -GError = _glib.GError +from gi._error import GError + +Error = GError OptionContext = _glib.OptionContext OptionGroup = _glib.OptionGroup Pid = _glib.Pid @@ -52,7 +54,30 @@ def threads_init(): 'See: https://wiki.gnome.org/PyGObject/Threading', PyGIDeprecationWarning, stacklevel=2) -__all__ += ['GError', 'OptionContext', 'OptionGroup', 'Pid', + +def gerror_matches(self, domain, code): + # Handle cases where self.domain was set to an integer for compatibility + # with the introspected GLib.Error. + if isinstance(self.domain, str): + self_domain_quark = GLib.quark_from_string(self.domain) + else: + self_domain_quark = self.domain + return (self_domain_quark, self.code) == (domain, code) + + +def gerror_new_literal(domain, message, code): + domain_quark = GLib.quark_to_string(domain) + return GError(message, domain_quark, code) + + +# Monkey patch methods that rely on GLib introspection to be loaded at runtime. +Error.__name__ = 'Error' +Error.__module__ = 'GLib' +Error.matches = gerror_matches +Error.new_literal = staticmethod(gerror_new_literal) + + +__all__ += ['GError', 'Error', 'OptionContext', 'OptionGroup', 'Pid', 'spawn_async', 'threads_init'] diff --git a/gi/overrides/Gio.py b/gi/overrides/Gio.py index 5a5dd2f..e646821 100644 --- a/gi/overrides/Gio.py +++ b/gi/overrides/Gio.py @@ -82,14 +82,14 @@ class Settings(Gio.Settings): def __getitem__(self, key): # get_value() aborts the program on an unknown key - if not key in self: + if key not in self: raise KeyError('unknown key: %r' % (key,)) return self.get_value(key).unpack() def __setitem__(self, key, value): # set_value() aborts the program on an unknown key - if not key in self: + if key not in self: raise KeyError('unknown key: %r' % (key,)) # determine type string of this key diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py index df55c2d..561bdf0 100644 --- a/gi/overrides/Gtk.py +++ b/gi/overrides/Gtk.py @@ -86,6 +86,17 @@ class Widget(Gtk.Widget): target_list = Gtk.TargetList.new(_construct_target_list(target_list)) super(Widget, self).drag_source_set_target_list(target_list) + def style_get_property(self, property_name, value=None): + if value is None: + prop = self.find_style_property(property_name) + if prop is None: + raise ValueError('Class "%s" does not contain style property "%s"' % + (self, property_name)) + value = GObject.Value(prop.value_type) + + Gtk.Widget.style_get_property(self, property_name, value) + return value.get_value() + Widget = override(Widget) __all__.append('Widget') @@ -110,6 +121,27 @@ class Container(Gtk.Container, Widget): get_focus_chain = strip_boolean_result(Gtk.Container.get_focus_chain) + def child_get_property(self, child, property_name, value=None): + if value is None: + prop = self.find_child_property(property_name) + if prop is None: + raise ValueError('Class "%s" does not contain child property "%s"' % + (self, property_name)) + value = GObject.Value(prop.value_type) + + Gtk.Container.child_get_property(self, child, property_name, value) + return value.get_value() + + def child_get(self, child, *prop_names): + """Returns a list of child property values for the given names.""" + return [self.child_get_property(child, name) for name in prop_names] + + def child_set(self, child, **kwargs): + """Set a child properties on the given child to key/value pairs.""" + for name, value in kwargs.items(): + name = name.replace('_', '-') + self.child_set_property(child, name, value) + Container = override(Container) __all__.append('Container') @@ -1122,13 +1154,13 @@ class TreePath(Gtk.TreePath): return self.to_string() def __lt__(self, other): - return not other is None and self.compare(other) < 0 + return other is not None and self.compare(other) < 0 def __le__(self, other): - return not other is None and self.compare(other) <= 0 + return other is not None and self.compare(other) <= 0 def __eq__(self, other): - return not other is None and self.compare(other) == 0 + return other is not None and self.compare(other) == 0 def __ne__(self, other): return other is None or self.compare(other) != 0 diff --git a/gi/pygboxed.c b/gi/pygboxed.c index 35716a2..9faa652 100644 --- a/gi/pygboxed.c +++ b/gi/pygboxed.c @@ -27,6 +27,7 @@ #include "pygboxed.h" #include "pygi.h" +#include "pygi-type.h" GQuark pygboxed_type_key; GQuark pygboxed_marshal_key; @@ -36,9 +37,9 @@ PYGLIB_DEFINE_TYPE("gobject.GBoxed", PyGBoxed_Type, PyGBoxed); static void pyg_boxed_dealloc(PyGBoxed *self) { - if (self->free_on_dealloc && self->boxed) { + if (self->free_on_dealloc && pyg_boxed_get_ptr (self)) { PyGILState_STATE state = pyglib_gil_state_ensure(); - g_boxed_free(self->gtype, self->boxed); + g_boxed_free (self->gtype, pyg_boxed_get_ptr (self)); pyglib_gil_state_release(state); } @@ -50,9 +51,9 @@ pyg_boxed_richcompare(PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other) && PyObject_IsInstance(self, (PyObject*)&PyGBoxed_Type)) - return _pyglib_generic_ptr_richcompare(((PyGBoxed*)self)->boxed, - ((PyGBoxed*)other)->boxed, - op); + return _pyglib_generic_ptr_richcompare (pyg_boxed_get_ptr (self), + pyg_boxed_get_ptr (other), + op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -63,7 +64,7 @@ pyg_boxed_richcompare(PyObject *self, PyObject *other, int op) static long pyg_boxed_hash(PyGBoxed *self) { - return (long)self->boxed; + return (long)pyg_boxed_get_ptr (self); } static PyObject * @@ -72,7 +73,7 @@ pyg_boxed_repr(PyGBoxed *self) gchar buf[128]; g_snprintf(buf, sizeof(buf), "<%s at 0x%lx>", g_type_name(self->gtype), - (long)self->boxed); + (long)pyg_boxed_get_ptr (self)); return PYGLIB_PyUnicode_FromString(buf); } @@ -84,7 +85,7 @@ pyg_boxed_init(PyGBoxed *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTuple(args, ":GBoxed.__init__")) return -1; - self->boxed = NULL; + pyg_boxed_set_ptr (self, NULL); self->gtype = 0; self->free_on_dealloc = FALSE; @@ -103,7 +104,7 @@ pyg_boxed_free(PyObject *op) static PyObject * pyg_boxed_copy(PyGBoxed *self) { - return pyg_boxed_new (self->gtype, self->boxed, TRUE, TRUE); + return pyg_boxed_new (self->gtype, pyg_boxed_get_ptr (self), TRUE, TRUE); } @@ -205,7 +206,7 @@ pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed, if (copy_boxed) boxed = g_boxed_copy(boxed_type, boxed); - self->boxed = boxed; + pyg_boxed_set_ptr (self, boxed); self->gtype = boxed_type; self->free_on_dealloc = own_ref; diff --git a/gi/pygenum.c b/gi/pygenum.c index 1b9b50e..053518f 100644 --- a/gi/pygenum.c +++ b/gi/pygenum.c @@ -26,6 +26,7 @@ #include <pyglib.h> #include "pygobject-private.h" #include "pygi.h" +#include "pygi-type.h" #include "pygenum.h" diff --git a/gi/pygflags.c b/gi/pygflags.c index c14bf7d..a7df8ce 100644 --- a/gi/pygflags.c +++ b/gi/pygflags.c @@ -28,6 +28,7 @@ #include "pygflags.h" #include "pygi.h" +#include "pygi-type.h" GQuark pygflags_class_key; diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index 4094c3d..15be78c 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -33,7 +33,7 @@ #include "pygi-basictype.h" #include "pygi-object.h" #include "pygi-struct-marshal.h" - +#include "pygi-error.h" static gboolean gi_argument_to_gssize (GIArgument *arg_in, @@ -1029,16 +1029,16 @@ array_success: * Further re-factoring is needed to fix this leak. * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405 */ - _pygi_marshal_from_py_interface_struct (object, - &arg, - NULL, /*arg_name*/ - info, /*interface_info*/ - g_type, - py_type, - transfer, - FALSE, /*copy_reference*/ - g_struct_info_is_foreign (info), - g_type_info_is_pointer (type_info)); + pygi_arg_struct_from_py_marshal (object, + &arg, + NULL, /*arg_name*/ + info, /*interface_info*/ + g_type, + py_type, + transfer, + FALSE, /*copy_reference*/ + g_struct_info_is_foreign (info), + g_type_info_is_pointer (type_info)); Py_DECREF (py_type); break; @@ -1372,13 +1372,13 @@ _pygi_argument_to_object (GIArgument *arg, py_type = _pygi_type_get_from_g_type (g_type); } - object = _pygi_marshal_to_py_interface_struct (arg, - info, /*interface_info*/ - g_type, - py_type, - transfer, - FALSE, /*is_allocated*/ - g_struct_info_is_foreign (info)); + object = pygi_arg_struct_to_py_marshal (arg, + info, /*interface_info*/ + g_type, + py_type, + transfer, + FALSE, /*is_allocated*/ + g_struct_info_is_foreign (info)); Py_XDECREF (py_type); break; @@ -1558,12 +1558,12 @@ _pygi_argument_to_object (GIArgument *arg, GError *error = (GError *) arg->v_pointer; if (error != NULL && transfer == GI_TRANSFER_NOTHING) { /* If we have not been transferred the ownership we must copy - * the error, because pyglib_error_check() is going to free it. + * the error, because pygi_error_check() is going to free it. */ error = g_error_copy (error); } - if (pyglib_error_check (&error)) { + if (pygi_error_check (&error)) { PyObject *err_type; PyObject *err_value; PyObject *err_trace; diff --git a/gi/pygi-array.c b/gi/pygi-array.c index c17ace0..fceffc6 100644 --- a/gi/pygi-array.c +++ b/gi/pygi-array.c @@ -454,7 +454,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, * allocated in _pygi_marshal_from_py_array(), so we must * not try to deallocate it as a slice and thus * short-circuit cleanup_func. */ - if (cleanup_func == _pygi_marshal_cleanup_from_py_interface_struct_gvalue) { + if (cleanup_func == pygi_arg_gvalue_from_py_cleanup) { g_value_unset ((GValue*) item); continue; } diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c index c52858b..b46cdcc 100644 --- a/gi/pygi-boxed.c +++ b/gi/pygi-boxed.c @@ -32,10 +32,10 @@ _boxed_dealloc (PyGIBoxed *self) if ( ( (PyGBoxed *) self)->free_on_dealloc) { if (self->slice_allocated) { - g_slice_free1 (self->size, ( (PyGBoxed *) self)->boxed); + g_slice_free1 (self->size, pyg_boxed_get_ptr (self)); } else { g_type = pyg_type_from_object ( (PyObject *) self); - g_boxed_free (g_type, ( (PyGBoxed *) self)->boxed); + g_boxed_free (g_type, pyg_boxed_get_ptr (self)); } } @@ -158,8 +158,8 @@ _pygi_boxed_new (PyTypeObject *type, } ( (PyGBoxed *) self)->gtype = pyg_type_from_object ( (PyObject *) type); - ( (PyGBoxed *) self)->boxed = boxed; ( (PyGBoxed *) self)->free_on_dealloc = free_on_dealloc; + pyg_boxed_set_ptr (self, boxed); if (allocated_slice > 0) { self->size = allocated_slice; self->slice_allocated = TRUE; diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c index c8da66f..24bb1a4 100644 --- a/gi/pygi-cache.c +++ b/gi/pygi-cache.c @@ -695,7 +695,7 @@ _setup_invoker (GICallableInfo *callable_info, &error)) { return TRUE; } - if (!pyglib_error_check (&error)) { + if (!pygi_error_check (&error)) { PyErr_Format (PyExc_RuntimeError, "unknown error creating invoker for %s", g_base_info_get_name ((GIBaseInfo *)callable_info)); @@ -707,7 +707,7 @@ _setup_invoker (GICallableInfo *callable_info, (GIFunctionInfo *)callable_info, invoker, &error)) { - if (!pyglib_error_check (&error)) { + if (!pygi_error_check (&error)) { PyErr_Format (PyExc_RuntimeError, "unknown error creating invoker for %s", g_base_info_get_name ((GIBaseInfo *)callable_info)); diff --git a/gi/pygi-error.c b/gi/pygi-error.c index 349bb7e..2e9150f 100644 --- a/gi/pygi-error.c +++ b/gi/pygi-error.c @@ -1,6 +1,8 @@ /* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com> * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org> * @@ -23,6 +25,194 @@ #include "pygi-error.h" +static PyObject *PyGError = NULL; +static PyObject *exception_table = NULL; + +/** + * pygi_error_marshal: + * @error: a pointer to the GError. + * + * Checks to see if @error has been set. If @error has been set, then a + * GLib.GError Python exception object is returned (but not raised). + * + * Returns: a GLib.GError Python exception object, or NULL. + */ +PyObject * +pygi_error_marshal (GError **error) +{ + PyGILState_STATE state; + PyObject *exc_type; + PyObject *exc_instance; + const char *domain = NULL; + + g_return_val_if_fail(error != NULL, NULL); + + if (*error == NULL) + return NULL; + + state = pyglib_gil_state_ensure(); + + exc_type = PyGError; + if (exception_table != NULL) + { + PyObject *item; + item = PyDict_GetItem(exception_table, PYGLIB_PyLong_FromLong((*error)->domain)); + if (item != NULL) + exc_type = item; + } + + if ((*error)->domain) { + domain = g_quark_to_string ((*error)->domain); + } + + exc_instance = PyObject_CallFunction (exc_type, "ssi", + (*error)->message, + domain, + (*error)->code); + + pyglib_gil_state_release(state); + + return exc_instance; +} + +/** + * pygi_error_check: + * @error: a pointer to the GError. + * + * Checks to see if the GError has been set. If the error has been + * set, then the glib.GError Python exception will be raised, and + * the GError cleared. + * + * Returns: True if an error was set. + */ +gboolean +pygi_error_check (GError **error) +{ + PyGILState_STATE state; + PyObject *exc_instance; + + g_return_val_if_fail(error != NULL, FALSE); + if (*error == NULL) + return FALSE; + + state = pyglib_gil_state_ensure(); + + exc_instance = pygi_error_marshal (error); + PyErr_SetObject(PyGError, exc_instance); + Py_DECREF(exc_instance); + g_clear_error(error); + + pyglib_gil_state_release(state); + + return TRUE; +} + +/** + * pygi_gerror_exception_check: + * @error: a standard GLib GError ** output parameter + * + * Checks to see if a GError exception has been raised, and if so + * translates the python exception to a standard GLib GError. If the + * raised exception is not a GError then PyErr_Print() is called. + * + * Returns: 0 if no exception has been raised, -1 if it is a + * valid glib.GError, -2 otherwise. + */ +gboolean +pygi_gerror_exception_check (GError **error) +{ + PyObject *type, *value, *traceback; + PyObject *py_message, *py_domain, *py_code; + const char *bad_gerror_message; + + PyErr_Fetch(&type, &value, &traceback); + if (type == NULL) + return 0; + PyErr_NormalizeException(&type, &value, &traceback); + if (value == NULL) { + PyErr_Restore(type, value, traceback); + PyErr_Print(); + return -2; + } + if (!value || + !PyErr_GivenExceptionMatches(type, + (PyObject *) PyGError)) { + PyErr_Restore(type, value, traceback); + PyErr_Print(); + return -2; + } + Py_DECREF(type); + Py_XDECREF(traceback); + + py_message = PyObject_GetAttrString(value, "message"); + if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) { + bad_gerror_message = "GLib.Error instances must have a 'message' string attribute"; + Py_XDECREF(py_message); + goto bad_gerror; + } + + py_domain = PyObject_GetAttrString(value, "domain"); + if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) { + bad_gerror_message = "GLib.Error instances must have a 'domain' string attribute"; + Py_DECREF(py_message); + Py_XDECREF(py_domain); + goto bad_gerror; + } + + py_code = PyObject_GetAttrString(value, "code"); + if (!py_code || !PYGLIB_PyLong_Check(py_code)) { + bad_gerror_message = "GLib.Error instances must have a 'code' int attribute"; + Py_DECREF(py_message); + Py_DECREF(py_domain); + Py_XDECREF(py_code); + goto bad_gerror; + } + + g_set_error(error, g_quark_from_string(PYGLIB_PyUnicode_AsString(py_domain)), + PYGLIB_PyLong_AsLong(py_code), "%s", PYGLIB_PyUnicode_AsString(py_message)); + + Py_DECREF(py_message); + Py_DECREF(py_code); + Py_DECREF(py_domain); + return -1; + +bad_gerror: + Py_DECREF(value); + g_set_error(error, g_quark_from_static_string("pygi"), 0, "%s", bad_gerror_message); + PyErr_SetString(PyExc_ValueError, bad_gerror_message); + PyErr_Print(); + return -2; +} + +/** + * pygi_register_exception_for_domain: + * @name: name of the exception + * @error_domain: error domain + * + * Registers a new GLib.Error exception subclass called #name for + * a specific #domain. This exception will be raised when a GError + * of the same domain is passed in to pygi_error_check(). + * + * Returns: the new exception + */ +PyObject * +pygi_register_exception_for_domain (gchar *name, + gint error_domain) +{ + PyObject *exception; + + exception = PyErr_NewException(name, PyGError, NULL); + + if (exception_table == NULL) + exception_table = PyDict_New(); + + PyDict_SetItem(exception_table, + PYGLIB_PyLong_FromLong(error_domain), + exception); + + return exception; +} + static gboolean _pygi_marshal_from_py_gerror (PyGIInvokeState *state, PyGICallableCache *callable_cache, @@ -45,7 +235,7 @@ _pygi_marshal_to_py_gerror (PyGIInvokeState *state, GError *error = arg->v_pointer; PyObject *py_obj = NULL; - py_obj = pyglib_error_marshal(&error); + py_obj = pygi_error_marshal (&error); if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) { g_error_free (error); @@ -107,3 +297,16 @@ pygi_arg_gerror_new_from_info (GITypeInfo *type_info, return NULL; } } + +void +pygi_error_register_types (PyObject *module) +{ + PyObject *error_module = PyImport_ImportModule ("gi._error"); + if (!error_module) { + return; + } + + /* Stash a reference to the Python implemented gi._error.GError. */ + PyGError = PyObject_GetAttrString (error_module, "GError"); +} + diff --git a/gi/pygi-error.h b/gi/pygi-error.h index fdeb32f..72d2be0 100644 --- a/gi/pygi-error.h +++ b/gi/pygi-error.h @@ -1,6 +1,8 @@ /* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org> * * This library is free software; you can redistribute it and/or @@ -25,10 +27,21 @@ G_BEGIN_DECLS -PyGIArgCache *pygi_arg_gerror_new_from_info (GITypeInfo *type_info, - GIArgInfo *arg_info, /* may be null */ - GITransfer transfer, - PyGIDirection direction); +gboolean pygi_error_check (GError **error); + +PyObject* pygi_error_marshal (GError **error); + +gboolean pygi_gerror_exception_check (GError **error); + +PyObject* pygi_register_exception_for_domain (gchar *name, + gint error_domain); + +PyGIArgCache* pygi_arg_gerror_new_from_info (GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be null */ + GITransfer transfer, + PyGIDirection direction); + +void pygi_error_register_types (PyObject *module); G_END_DECLS diff --git a/gi/pygi-foreign-api.h b/gi/pygi-foreign-api.h new file mode 100644 index 0000000..9367518 --- /dev/null +++ b/gi/pygi-foreign-api.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org> + * + * 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/>. + */ + +#ifndef __PYGI_FOREIGN_API_H__ +#define __PYGI_FOREIGN_API_H__ + +#include <girepository.h> +#include <pygobject.h> + +typedef PyObject * (*PyGIArgOverrideToGIArgumentFunc) (PyObject *value, + GIInterfaceInfo *interface_info, + GITransfer transfer, + GIArgument *arg); +typedef PyObject * (*PyGIArgOverrideFromGIArgumentFunc) (GIInterfaceInfo *interface_info, + GITransfer transfer, + gpointer data); +typedef PyObject * (*PyGIArgOverrideReleaseFunc) (GITypeInfo *type_info, + gpointer struct_); + + +struct PyGI_API { + void (*register_foreign_struct) (const char* namespace_, + const char* name, + PyGIArgOverrideToGIArgumentFunc to_func, + PyGIArgOverrideFromGIArgumentFunc from_func, + PyGIArgOverrideReleaseFunc release_func); +}; + + +#ifndef _INSIDE_PYGOBJECT_ + +static struct PyGI_API *PyGI_API = NULL; + +static int +_pygi_import (void) +{ + if (PyGI_API != NULL) { + return 1; + } + PyGI_API = (struct PyGI_API*) PyCapsule_Import("gi._API", FALSE); + if (PyGI_API == NULL) { + return -1; + } + + return 0; +} + + +static inline PyObject * +pygi_register_foreign_struct (const char* namespace_, + const char* name, + PyGIArgOverrideToGIArgumentFunc to_func, + PyGIArgOverrideFromGIArgumentFunc from_func, + PyGIArgOverrideReleaseFunc release_func) +{ + if (_pygi_import() < 0) { + return NULL; + } + PyGI_API->register_foreign_struct(namespace_, + name, + to_func, + from_func, + release_func); + Py_RETURN_NONE; +} + +#endif /* _INSIDE_PYGOBJECT_ */ + +#endif /* __PYGI_FOREIGN_API_H__ */ diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c index 8261a07..5937759 100644 --- a/gi/pygi-foreign-cairo.c +++ b/gi/pygi-foreign-cairo.c @@ -31,11 +31,19 @@ static Pycairo_CAPI_t *Pycairo_CAPI; #include <pycairo/py3cairo.h> #endif +#include <cairo-gobject.h> -#include "pygi-foreign.h" - +/* Limit includes from PyGI to APIs which do not have link dependencies + * (pygobject.h and pygi-foreign-api.h) since _gi_cairo is built as a separate + * shared library that interacts with PyGI through a PyCapsule API at runtime. + */ +#include <pygi-foreign-api.h> #include <pyglib-python-compat.h> +/* + * cairo_t marshaling + */ + static PyObject * cairo_context_to_arg (PyObject *value, GIInterfaceInfo *interface_info, @@ -68,6 +76,7 @@ cairo_context_from_arg (GIInterfaceInfo *interface_info, return PycairoContext_FromContext (context, &PycairoContext_Type, NULL); } + static PyObject * cairo_context_release (GIBaseInfo *base_info, gpointer struct_) @@ -76,6 +85,36 @@ cairo_context_release (GIBaseInfo *base_info, Py_RETURN_NONE; } +static int +cairo_context_to_gvalue (GValue *value, PyObject *obj) +{ + cairo_t *cr = PycairoContext_GET (obj); + if (!cr) { + return -1; + } + + /* PycairoContext_GET returns a borrowed reference, use set_boxed + * to add new ref to the context which will be managed by the GValue. */ + g_value_set_boxed (value, cr); + return 0; +} + +static PyObject * +cairo_context_from_gvalue (const GValue *value) +{ + /* PycairoContext_FromContext steals a ref, so we dup it out of the GValue. */ + cairo_t *cr = g_value_dup_boxed (value); + if (!cr) { + return NULL; + } + + return PycairoContext_FromContext (cr, &PycairoContext_Type, NULL); +} + + +/* + * cairo_surface_t marshaling + */ static PyObject * cairo_surface_to_arg (PyObject *value, @@ -118,6 +157,36 @@ cairo_surface_release (GIBaseInfo *base_info, Py_RETURN_NONE; } +static int +cairo_surface_to_gvalue (GValue *value, PyObject *obj) +{ + cairo_surface_t *surface = ((PycairoSurface*) obj)->surface; + if (!surface) { + return -1; + } + + /* surface is a borrowed reference, use set_boxed + * to add new ref to the context which will be managed by the GValue. */ + g_value_set_boxed (value, surface); + return 0; +} + +static PyObject * +cairo_surface_from_gvalue (const GValue *value) +{ + /* PycairoSurface_FromSurface steals a ref, so we dup it out of the GValue. */ + cairo_surface_t *surface = g_value_dup_boxed (value); + if (!surface) { + return NULL; + } + + return PycairoSurface_FromSurface (surface, NULL); +} + + +/* + * cairo_path_t marshaling + */ static PyObject * cairo_path_to_arg (PyObject *value, @@ -162,6 +231,39 @@ cairo_path_release (GIBaseInfo *base_info, Py_RETURN_NONE; } + +/* + * cairo_font_face_t marshaling + */ + +static int +cairo_font_face_to_gvalue (GValue *value, PyObject *obj) +{ + cairo_font_face_t *font_face = ((PycairoFontFace*) obj)->font_face; + if (!font_face) { + return -1; + } + + g_value_set_boxed (value, font_face); + return 0; +} + +static PyObject * +cairo_font_face_from_gvalue (const GValue *value) +{ + cairo_font_face_t *font_face = g_value_dup_boxed (value); + if (!font_face) { + return NULL; + } + + return PycairoFontFace_FromFontFace (font_face); +} + + +/* + * cairo_font_options_t marshaling + */ + static PyObject * cairo_font_options_to_arg (PyObject *value, GIInterfaceInfo *interface_info, @@ -203,6 +305,69 @@ cairo_font_options_release (GIBaseInfo *base_info, Py_RETURN_NONE; } + +/* + * scaled_font_t marshaling + */ + +static int +cairo_scaled_font_to_gvalue (GValue *value, PyObject *obj) +{ + cairo_scaled_font_t *scaled_font = ((PycairoScaledFont*) obj)->scaled_font; + if (!scaled_font) { + return -1; + } + + /* scaled_font is a borrowed reference, use set_boxed + * to add new ref to the context which will be managed by the GValue. */ + g_value_set_boxed (value, scaled_font); + return 0; +} + +static PyObject * +cairo_scaled_font_from_gvalue (const GValue *value) +{ + /* PycairoScaledFont_FromScaledFont steals a ref, so we dup it out of the GValue. */ + cairo_scaled_font_t *scaled_font = g_value_dup_boxed (value); + if (!scaled_font) { + return NULL; + } + + return PycairoScaledFont_FromScaledFont (scaled_font); +} + + +/* + * cairo_pattern_t marshaling + */ + +static int +cairo_pattern_to_gvalue (GValue *value, PyObject *obj) +{ + cairo_pattern_t *pattern = ((PycairoPattern*) obj)->pattern; + if (!pattern) { + return -1; + } + + /* pattern is a borrowed reference, use set_boxed + * to add new ref to the context which will be managed by the GValue. */ + g_value_set_boxed (value, pattern); + return 0; +} + +static PyObject * +cairo_pattern_from_gvalue (const GValue *value) +{ + /* PycairoPattern_FromPattern steals a ref, so we dup it out of the GValue. */ + cairo_pattern_t *pattern = g_value_dup_boxed (value); + if (!pattern) { + return NULL; + } + + return PycairoPattern_FromPattern (pattern, NULL); +} + + static PyMethodDef _gi_cairo_functions[] = { {0,} }; PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo") { @@ -215,6 +380,8 @@ PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo") if (Pycairo_CAPI == NULL) return PYGLIB_MODULE_ERROR_RETURN; + pygobject_init (3, 13, 2); + pygi_register_foreign_struct ("cairo", "Context", cairo_context_to_arg, @@ -238,5 +405,26 @@ PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo") cairo_font_options_to_arg, cairo_font_options_from_arg, cairo_font_options_release); + + pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_CONTEXT, + cairo_context_from_gvalue, + cairo_context_to_gvalue); + + pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_SURFACE, + cairo_surface_from_gvalue, + cairo_surface_to_gvalue); + + pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_FONT_FACE, + cairo_font_face_from_gvalue, + cairo_font_face_to_gvalue); + + pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_SCALED_FONT, + cairo_scaled_font_from_gvalue, + cairo_scaled_font_to_gvalue); + + pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_PATTERN, + cairo_pattern_from_gvalue, + cairo_pattern_to_gvalue); + } PYGLIB_MODULE_END; diff --git a/gi/pygi-foreign.c b/gi/pygi-foreign.c index f3c1a34..82392be 100644 --- a/gi/pygi-foreign.c +++ b/gi/pygi-foreign.c @@ -63,24 +63,24 @@ do_lookup (const gchar *namespace, const gchar *name) return NULL; } +static PyObject * +pygi_struct_foreign_load_module (const char *namespace) +{ + gchar *module_name = g_strconcat ("gi._gi_", namespace, NULL); + PyObject *module = PyImport_ImportModule (module_name); + g_free (module_name); + return module; +} + static PyGIForeignStruct * -pygi_struct_foreign_lookup (GIBaseInfo *base_info) +pygi_struct_foreign_lookup_by_name (const char *namespace, const char *name) { PyGIForeignStruct *result; - const gchar *namespace = g_base_info_get_namespace (base_info); - const gchar *name = g_base_info_get_name (base_info); - - if (foreign_structs == NULL) { - init_foreign_structs (); - } result = do_lookup (namespace, name); if (result == NULL) { - gchar *module_name = g_strconcat ("gi._gi_", namespace, NULL); - PyObject *module = PyImport_ImportModule (module_name); - - g_free (module_name); + PyObject *module = pygi_struct_foreign_load_module (namespace); if (module == NULL) PyErr_Clear (); @@ -92,7 +92,7 @@ pygi_struct_foreign_lookup (GIBaseInfo *base_info) if (result == NULL) { PyErr_Format (PyExc_TypeError, - "Couldn't find conversion for foreign struct '%s.%s'", + "Couldn't find foreign struct converter for '%s.%s'", namespace, name); } @@ -100,6 +100,15 @@ pygi_struct_foreign_lookup (GIBaseInfo *base_info) return result; } +static PyGIForeignStruct * +pygi_struct_foreign_lookup (GIBaseInfo *base_info) +{ + const gchar *namespace = g_base_info_get_namespace (base_info); + const gchar *name = g_base_info_get_name (base_info); + + return pygi_struct_foreign_lookup_by_name (namespace, name); +} + PyObject * pygi_struct_foreign_convert_to_g_argument (PyObject *value, GIInterfaceInfo *interface_info, @@ -151,11 +160,11 @@ pygi_struct_foreign_release (GIBaseInfo *base_info, } void -pygi_register_foreign_struct_real (const char* namespace_, - const char* name, - PyGIArgOverrideToGIArgumentFunc to_func, - PyGIArgOverrideFromGIArgumentFunc from_func, - PyGIArgOverrideReleaseFunc release_func) +pygi_register_foreign_struct (const char* namespace_, + const char* name, + PyGIArgOverrideToGIArgumentFunc to_func, + PyGIArgOverrideFromGIArgumentFunc from_func, + PyGIArgOverrideReleaseFunc release_func) { PyGIForeignStruct *new_struct = g_slice_new (PyGIForeignStruct); new_struct->namespace = namespace_; @@ -166,3 +175,42 @@ pygi_register_foreign_struct_real (const char* namespace_, g_ptr_array_add (foreign_structs, new_struct); } + +PyObject * +pygi_require_foreign (PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "namespace", "symbol", NULL }; + const char *namespace = NULL; + const char *symbol = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, + "s|z:require_foreign", + kwlist, &namespace, &symbol)) { + return NULL; + } + + if (symbol) { + PyGIForeignStruct *foreign; + foreign = pygi_struct_foreign_lookup_by_name (namespace, symbol); + if (foreign == NULL) { + return NULL; + } + } else { + PyObject *module = pygi_struct_foreign_load_module (namespace); + if (module) { + Py_DECREF (module); + } else { + return NULL; + } + } + + Py_RETURN_NONE; +} + +void +pygi_foreign_init (void) +{ + if (foreign_structs == NULL) { + init_foreign_structs (); + } +} diff --git a/gi/pygi-foreign.h b/gi/pygi-foreign.h index 478d759..afa4768 100644 --- a/gi/pygi-foreign.h +++ b/gi/pygi-foreign.h @@ -26,9 +26,7 @@ #define __PYGI_FOREIGN_H__ #include <Python.h> -#include <girepository.h> - -#include "pygi.h" +#include "pygi-foreign-api.h" PyObject *pygi_struct_foreign_convert_to_g_argument (PyObject *value, GIInterfaceInfo *interface_info, @@ -40,10 +38,16 @@ PyObject *pygi_struct_foreign_convert_from_g_argument (GIInterfaceInfo *interfac PyObject *pygi_struct_foreign_release (GITypeInfo *type_info, gpointer struct_); -void pygi_register_foreign_struct_real (const char* namespace_, - const char* name, - PyGIArgOverrideToGIArgumentFunc to_func, - PyGIArgOverrideFromGIArgumentFunc from_func, - PyGIArgOverrideReleaseFunc release_func); +void pygi_register_foreign_struct (const char* namespace_, + const char* name, + PyGIArgOverrideToGIArgumentFunc to_func, + PyGIArgOverrideFromGIArgumentFunc from_func, + PyGIArgOverrideReleaseFunc release_func); + +PyObject *pygi_require_foreign (PyObject *self, + PyObject *args, + PyObject *kwargs); + +void pygi_foreign_init (void); #endif /* __PYGI_FOREIGN_H__ */ diff --git a/gi/pygi-info.c b/gi/pygi-info.c index 065d470..43ee711 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -754,6 +754,15 @@ _wrap_g_callable_info_get_return_attribute (PyGIBaseInfo *self, PyObject *py_nam } } +static PyObject * +_wrap_g_callable_info_can_throw_gerror (PyGIBaseInfo *self) +{ + if (g_callable_info_can_throw_gerror (self->info)) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + static PyMethodDef _PyGICallableInfo_methods[] = { { "invoke", (PyCFunction) _wrap_g_callable_info_invoke, METH_VARARGS | METH_KEYWORDS }, { "get_arguments", (PyCFunction) _wrap_g_callable_info_get_arguments, METH_NOARGS }, @@ -762,11 +771,12 @@ static PyMethodDef _PyGICallableInfo_methods[] = { { "may_return_null", (PyCFunction) _wrap_g_callable_info_may_return_null, METH_NOARGS }, { "skip_return", (PyCFunction) _wrap_g_callable_info_skip_return, METH_NOARGS }, { "get_return_attribute", (PyCFunction) _wrap_g_callable_info_get_return_attribute, METH_O }, + { "can_throw_gerror", (PyCFunction) _wrap_g_callable_info_can_throw_gerror, METH_NOARGS }, { NULL, NULL, 0 } }; /* CallbackInfo */ -PYGLIB_DEFINE_TYPE ("gi.CallbackInfo", PyGICallbackInfo_Type, PyGIBaseInfo); +PYGLIB_DEFINE_TYPE ("gi.CallbackInfo", PyGICallbackInfo_Type, PyGICallableInfo); static PyMethodDef _PyGICallbackInfo_methods[] = { { NULL, NULL, 0 } @@ -2185,7 +2195,7 @@ _pygi_info_register_types (PyObject *m) _PyGI_REGISTER_TYPE (m, PyGIUnresolvedInfo_Type, UnresolvedInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGICallbackInfo_Type, CallbackInfo, - PyGIBaseInfo_Type); + PyGICallableInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIRegisteredTypeInfo_Type, RegisteredTypeInfo, PyGIBaseInfo_Type); _PyGI_REGISTER_TYPE (m, PyGIStructInfo_Type, StructInfo, diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c index 4af2e72..eebf959 100644 --- a/gi/pygi-invoke.c +++ b/gi/pygi-invoke.c @@ -23,6 +23,7 @@ #include <pyglib.h> #include "pygi-invoke.h" #include "pygi-marshal-cleanup.h" +#include "pygi-error.h" static inline gboolean _invoke_callable (PyGIInvokeState *state, @@ -46,7 +47,7 @@ _invoke_callable (PyGIInvokeState *state, * state->error allowing for easy checking here. */ if (state->error != NULL) { - if (pyglib_error_check (&(state->error))) { + if (pygi_error_check (&(state->error))) { /* even though we errored out, the call itself was successful, so we assume the call processed all of the parameters */ pygi_marshal_cleanup_args_from_py_marshal_success (state, cache); @@ -308,7 +309,7 @@ _invoke_state_init_from_callable_cache (GIBaseInfo *info, state->function_ptr = g_vfunc_info_get_address ((GIVFuncInfo *)info, state->implementor_gtype, &error); - if (pyglib_error_check (&error)) { + if (pygi_error_check (&error)) { return FALSE; } } diff --git a/gi/pygi-property.c b/gi/pygi-property.c index 6f80506..f7cb032 100644 --- a/gi/pygi-property.c +++ b/gi/pygi-property.c @@ -105,7 +105,7 @@ g_value_get_or_dup_boxed (const GValue *value, GITransfer transfer) } PyObject * -pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec) +pygi_get_property_value (PyGObject *instance, GParamSpec *pspec) { GIPropertyInfo *property_info = NULL; GValue value = { 0, }; @@ -271,9 +271,9 @@ out: } gint -pygi_set_property_value_real (PyGObject *instance, - GParamSpec *pspec, - PyObject *py_value) +pygi_set_property_value (PyGObject *instance, + GParamSpec *pspec, + PyObject *py_value) { GIPropertyInfo *property_info = NULL; GITypeInfo *type_info = NULL; diff --git a/gi/pygi-property.h b/gi/pygi-property.h index 875d21e..5678bc3 100644 --- a/gi/pygi-property.h +++ b/gi/pygi-property.h @@ -27,13 +27,15 @@ #include <Python.h> #include <girepository.h> -#include "pygi.h" +#include "pygobject.h" -PyObject *pygi_get_property_value_real (PyGObject *instance, - GParamSpec *pspec); +PyObject * +pygi_get_property_value (PyGObject *instance, + GParamSpec *pspec); -gint pygi_set_property_value_real (PyGObject *instance, - GParamSpec *pspec, - PyObject *py_value); +gint +pygi_set_property_value (PyGObject *instance, + GParamSpec *pspec, + PyObject *py_value); #endif /* __PYGI_PROPERTY_H__ */ diff --git a/gi/pygi-signal-closure.c b/gi/pygi-signal-closure.c index c5f51af..079669c 100644 --- a/gi/pygi-signal-closure.c +++ b/gi/pygi-signal-closure.c @@ -171,12 +171,12 @@ pygi_signal_closure_marshal(GClosure *closure, } GClosure * -pygi_signal_closure_new_real (PyGObject *instance, - GType g_type, - const gchar *signal_name, - PyObject *callback, - PyObject *extra_args, - PyObject *swap_data) +pygi_signal_closure_new (PyGObject *instance, + GType g_type, + const gchar *signal_name, + PyObject *callback, + PyObject *extra_args, + PyObject *swap_data) { GClosure *closure = NULL; PyGISignalClosure *pygi_closure = NULL; diff --git a/gi/pygi-signal-closure.h b/gi/pygi-signal-closure.h index ffdd29c..5cc191b 100644 --- a/gi/pygi-signal-closure.h +++ b/gi/pygi-signal-closure.h @@ -24,7 +24,7 @@ #ifndef __PYGI_SIGNAL_CLOSURE_H__ #define __PYGI_SIGNAL_CLOSURE_H__ -#include "pygi.h" +#include "pygobject.h" G_BEGIN_DECLS @@ -35,12 +35,13 @@ typedef struct _PyGISignalClosure GISignalInfo *signal_info; } PyGISignalClosure; -GClosure * pygi_signal_closure_new_real (PyGObject *instance, - GType g_type, - const gchar *sig_name, - PyObject *callback, - PyObject *extra_args, - PyObject *swap_data); +GClosure * +pygi_signal_closure_new (PyGObject *instance, + GType g_type, + const gchar *sig_name, + PyObject *callback, + PyObject *extra_args, + PyObject *swap_data); G_END_DECLS diff --git a/gi/pygi-struct-marshal.c b/gi/pygi-struct-marshal.c index 7346eae..9abaaae 100644 --- a/gi/pygi-struct-marshal.c +++ b/gi/pygi-struct-marshal.c @@ -84,7 +84,7 @@ _is_union_member (GIInterfaceInfo *interface_info, PyObject *py_arg) { * GValue from Python */ -/* _pygi_marshal_from_py_gvalue: +/* pygi_arg_gvalue_from_py_marshal: * py_arg: (in): * arg: (out): * transfer: @@ -92,10 +92,10 @@ _is_union_member (GIInterfaceInfo *interface_info, PyObject *py_arg) { * when it is already holding a GValue vs. copying the value. */ gboolean -_pygi_marshal_from_py_gvalue (PyObject *py_arg, - GIArgument *arg, - GITransfer transfer, - gboolean copy_reference) { +pygi_arg_gvalue_from_py_marshal (PyObject *py_arg, + GIArgument *arg, + GITransfer transfer, + gboolean copy_reference) { GValue *value; GType object_type; @@ -130,11 +130,11 @@ _pygi_marshal_from_py_gvalue (PyObject *py_arg, } void -_pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *py_arg, - gpointer data, - gboolean was_processed) +pygi_arg_gvalue_from_py_cleanup (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *py_arg, + gpointer data, + gboolean was_processed) { /* Note py_arg can be NULL for hash table which is a bug. */ if (was_processed && py_arg != NULL) { @@ -151,13 +151,13 @@ _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state, } } -/* _pygi_marshal_from_py_gclosure: +/* pygi_arg_gclosure_from_py_marshal: * py_arg: (in): * arg: (out): */ gboolean -_pygi_marshal_from_py_gclosure(PyObject *py_arg, - GIArgument *arg) +pygi_arg_gclosure_from_py_marshal (PyObject *py_arg, + GIArgument *arg) { GClosure *closure; GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE); @@ -183,21 +183,21 @@ _pygi_marshal_from_py_gclosure(PyObject *py_arg, return TRUE; } -/* _pygi_marshal_from_py_interface_struct: +/* pygi_arg_struct_from_py_marshal: * * Dispatcher to various sub marshalers */ gboolean -_pygi_marshal_from_py_interface_struct (PyObject *py_arg, - GIArgument *arg, - const gchar *arg_name, - GIBaseInfo *interface_info, - GType g_type, - PyObject *py_type, - GITransfer transfer, - gboolean copy_reference, - gboolean is_foreign, - gboolean is_pointer) +pygi_arg_struct_from_py_marshal (PyObject *py_arg, + GIArgument *arg, + const gchar *arg_name, + GIBaseInfo *interface_info, + GType g_type, + PyObject *py_type, + GITransfer transfer, + gboolean copy_reference, + gboolean is_foreign, + gboolean is_pointer) { gboolean is_union = FALSE; @@ -211,12 +211,12 @@ _pygi_marshal_from_py_interface_struct (PyObject *py_arg, */ if (g_type_is_a (g_type, G_TYPE_CLOSURE)) { - return _pygi_marshal_from_py_gclosure (py_arg, arg); + return pygi_arg_gclosure_from_py_marshal (py_arg, arg); } else if (g_type_is_a (g_type, G_TYPE_VALUE)) { - return _pygi_marshal_from_py_gvalue(py_arg, - arg, - transfer, - copy_reference); + return pygi_arg_gvalue_from_py_marshal(py_arg, + arg, + transfer, + copy_reference); } else if (is_foreign) { PyObject *success; success = pygi_struct_foreign_convert_to_g_argument (py_arg, @@ -292,25 +292,25 @@ type_error: } static gboolean -_pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - PyObject *py_arg, - GIArgument *arg, - gpointer *cleanup_data) +arg_struct_from_py_marshal_adapter (PyGIInvokeState *state, + PyGICallableCache *callable_cache, + PyGIArgCache *arg_cache, + PyObject *py_arg, + GIArgument *arg, + gpointer *cleanup_data) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; - gboolean res = _pygi_marshal_from_py_interface_struct (py_arg, - arg, - arg_cache->arg_name, - iface_cache->interface_info, - iface_cache->g_type, - iface_cache->py_type, - arg_cache->transfer, - TRUE, /*copy_reference*/ - iface_cache->is_foreign, - arg_cache->is_pointer); + gboolean res = pygi_arg_struct_from_py_marshal (py_arg, + arg, + arg_cache->arg_name, + iface_cache->interface_info, + iface_cache->g_type, + iface_cache->py_type, + arg_cache->transfer, + TRUE, /*copy_reference*/ + iface_cache->is_foreign, + arg_cache->is_pointer); /* Assume struct marshaling is always a pointer and assign cleanup_data * here rather than passing it further down the chain. @@ -320,27 +320,28 @@ _pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state, } static void -_pygi_marshal_cleanup_from_py_interface_struct_foreign (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *py_arg, - gpointer data, - gboolean was_processed) +arg_foreign_from_py_cleanup (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *py_arg, + gpointer data, + gboolean was_processed) { - if (state->failed && was_processed) + if (state->failed && was_processed) { pygi_struct_foreign_release ( ( (PyGIInterfaceCache *)arg_cache)->interface_info, data); + } } PyObject * -_pygi_marshal_to_py_interface_struct (GIArgument *arg, - GIInterfaceInfo *interface_info, - GType g_type, - PyObject *py_type, - GITransfer transfer, - gboolean is_allocated, - gboolean is_foreign) +pygi_arg_struct_to_py_marshal (GIArgument *arg, + GIInterfaceInfo *interface_info, + GType g_type, + PyObject *py_type, + GITransfer transfer, + gboolean is_allocated, + gboolean is_foreign) { PyObject *py_obj = NULL; @@ -400,89 +401,107 @@ _pygi_marshal_to_py_interface_struct (GIArgument *arg, } static PyObject * -_pygi_marshal_to_py_interface_struct_cache_adapter (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - GIArgument *arg) +arg_struct_to_py_marshal_adapter (PyGIInvokeState *state, + PyGICallableCache *callable_cache, + PyGIArgCache *arg_cache, + GIArgument *arg) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; - return _pygi_marshal_to_py_interface_struct (arg, - iface_cache->interface_info, - iface_cache->g_type, - iface_cache->py_type, - arg_cache->transfer, - arg_cache->is_caller_allocates, - iface_cache->is_foreign); + return pygi_arg_struct_to_py_marshal (arg, + iface_cache->interface_info, + iface_cache->g_type, + iface_cache->py_type, + arg_cache->transfer, + arg_cache->is_caller_allocates, + iface_cache->is_foreign); } static void -_pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *dummy, - gpointer data, - gboolean was_processed) +arg_foreign_to_py_cleanup (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *dummy, + gpointer data, + gboolean was_processed) { - if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING) + if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING) { pygi_struct_foreign_release ( ( (PyGIInterfaceCache *)arg_cache)->interface_info, data); + } } +static gboolean +arg_type_class_from_py_marshal (PyGIInvokeState *state, + PyGICallableCache *callable_cache, + PyGIArgCache *arg_cache, + PyObject *py_arg, + GIArgument *arg, + gpointer *cleanup_data) +{ + GType gtype = pyg_type_from_object (py_arg); + + if (G_TYPE_IS_CLASSED (gtype)) { + arg->v_pointer = g_type_class_ref (gtype); + *cleanup_data = arg->v_pointer; + return TRUE; + } else { + PyErr_Format (PyExc_TypeError, + "Unable to retrieve a GObject type class from \"%s\".", + Py_TYPE(py_arg)->tp_name); + return FALSE; + } +} static void -_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache, - GIInterfaceInfo *iface_info, - GITransfer transfer) +arg_type_class_from_py_cleanup (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *py_arg, + gpointer data, + gboolean was_processed) { - PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; - iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info); - arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter; - - if (iface_cache->g_type == G_TYPE_VALUE) - arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue; - else if (iface_cache->is_foreign) - arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign; + if (was_processed) { + g_type_class_unref (data); + } } static void -_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache, - GIInterfaceInfo *iface_info, - GITransfer transfer) +arg_struct_from_py_setup (PyGIArgCache *arg_cache, + GIInterfaceInfo *iface_info, + GITransfer transfer) { PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info); - arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter; - if (iface_cache->is_foreign) - arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign; -} + if (g_struct_info_is_gtype_struct ((GIStructInfo*)iface_info)) { + arg_cache->from_py_marshaller = arg_type_class_from_py_marshal; + /* Since we always add a ref in the marshalling, only unref the + * GTypeClass when we don't transfer ownership. */ + if (transfer == GI_TRANSFER_NOTHING) { + arg_cache->from_py_cleanup = arg_type_class_from_py_cleanup; + } -static gboolean -pygi_arg_struct_setup_from_info (PyGIArgCache *arg_cache, - GITypeInfo *type_info, - GIArgInfo *arg_info, - GITransfer transfer, - PyGIDirection direction, - GIInterfaceInfo *iface_info) -{ - /* NOTE: usage of pygi_arg_interface_new_from_info already calls - * pygi_arg_interface_setup so no need to do it here. - */ + } else { + arg_cache->from_py_marshaller = arg_struct_from_py_marshal_adapter; - if (direction & PYGI_DIRECTION_FROM_PYTHON) { - _arg_cache_from_py_interface_struct_setup (arg_cache, - iface_info, - transfer); + if (iface_cache->g_type == G_TYPE_VALUE) + arg_cache->from_py_cleanup = pygi_arg_gvalue_from_py_cleanup; + else if (iface_cache->is_foreign) + arg_cache->from_py_cleanup = arg_foreign_from_py_cleanup; } +} - if (direction & PYGI_DIRECTION_TO_PYTHON) { - _arg_cache_to_py_interface_struct_setup (arg_cache, - iface_info, - transfer); - } +static void +arg_struct_to_py_setup (PyGIArgCache *arg_cache, + GIInterfaceInfo *iface_info, + GITransfer transfer) +{ + PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache; + iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info); + arg_cache->to_py_marshaller = arg_struct_to_py_marshal_adapter; - return TRUE; + if (iface_cache->is_foreign) + arg_cache->to_py_cleanup = arg_foreign_to_py_cleanup; } PyGIArgCache * @@ -492,7 +511,6 @@ pygi_arg_struct_new_from_info (GITypeInfo *type_info, PyGIDirection direction, GIInterfaceInfo *iface_info) { - gboolean res = FALSE; PyGIArgCache *cache = NULL; cache = pygi_arg_interface_new_from_info (type_info, @@ -503,16 +521,13 @@ pygi_arg_struct_new_from_info (GITypeInfo *type_info, if (cache == NULL) return NULL; - res = pygi_arg_struct_setup_from_info (cache, - type_info, - arg_info, - transfer, - direction, - iface_info); - if (res) { - return cache; - } else { - pygi_arg_cache_free (cache); - return NULL; + if (direction & PYGI_DIRECTION_FROM_PYTHON) { + arg_struct_from_py_setup (cache, iface_info, transfer); } + + if (direction & PYGI_DIRECTION_TO_PYTHON) { + arg_struct_to_py_setup (cache, iface_info, transfer); + } + + return cache; } diff --git a/gi/pygi-struct-marshal.h b/gi/pygi-struct-marshal.h index 66e3ecf..6a7f92d 100644 --- a/gi/pygi-struct-marshal.h +++ b/gi/pygi-struct-marshal.h @@ -33,40 +33,40 @@ PyGIArgCache *pygi_arg_struct_new_from_info (GITypeInfo *type_info, GIInterfaceInfo *iface_info); -gboolean _pygi_marshal_from_py_gvalue (PyObject *py_arg, /*in*/ - GIArgument *arg, /*out*/ - GITransfer transfer, - gboolean is_allocated); +gboolean pygi_arg_gvalue_from_py_marshal (PyObject *py_arg, /*in*/ + GIArgument *arg, /*out*/ + GITransfer transfer, + gboolean is_allocated); -gboolean _pygi_marshal_from_py_gclosure(PyObject *py_arg, /*in*/ - GIArgument *arg); /*out*/ +gboolean pygi_arg_gclosure_from_py_marshal (PyObject *py_arg, /*in*/ + GIArgument *arg); /*out*/ -gboolean _pygi_marshal_from_py_interface_struct (PyObject *py_arg, - GIArgument *arg, - const gchar *arg_name, - GIBaseInfo *interface_info, - GType g_type, - PyObject *py_type, - GITransfer transfer, - gboolean is_allocated, - gboolean is_foreign, - gboolean is_pointer); +gboolean pygi_arg_struct_from_py_marshal (PyObject *py_arg, + GIArgument *arg, + const gchar *arg_name, + GIBaseInfo *interface_info, + GType g_type, + PyObject *py_type, + GITransfer transfer, + gboolean is_allocated, + gboolean is_foreign, + gboolean is_pointer); -PyObject *_pygi_marshal_to_py_interface_struct (GIArgument *arg, - GIInterfaceInfo *interface_info, - GType g_type, - PyObject *py_type, - GITransfer transfer, - gboolean is_allocated, - gboolean is_foreign); +PyObject *pygi_arg_struct_to_py_marshal (GIArgument *arg, + GIInterfaceInfo *interface_info, + GType g_type, + PyObject *py_type, + GITransfer transfer, + gboolean is_allocated, + gboolean is_foreign); /* Needed for hack in pygi-arg-garray.c */ -void _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *py_arg, - gpointer data, - gboolean was_processed); +void pygi_arg_gvalue_from_py_cleanup (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *py_arg, + gpointer data, + gboolean was_processed); G_END_DECLS diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c index b1db8a4..692068b 100644 --- a/gi/pygi-struct.c +++ b/gi/pygi-struct.c @@ -60,9 +60,9 @@ _struct_dealloc (PyGIStruct *self) GIBaseInfo *info = _struct_get_info ( (PyObject *) self ); if (info != NULL && g_struct_info_is_foreign ( (GIStructInfo *) info)) { - pygi_struct_foreign_release (info, ( (PyGPointer *) self)->pointer); + pygi_struct_foreign_release (info, pyg_pointer_get_ptr (self)); } else if (self->free_on_dealloc) { - g_free ( ( (PyGPointer *) self)->pointer); + g_free (pyg_pointer_get_ptr (self)); } if (info != NULL) { @@ -152,8 +152,8 @@ _pygi_struct_new (PyTypeObject *type, g_type = pyg_type_from_object ( (PyObject *) type); + pyg_pointer_set_ptr (self, pointer); ( (PyGPointer *) self)->gtype = g_type; - ( (PyGPointer *) self)->pointer = pointer; self->free_on_dealloc = free_on_dealloc; return (PyObject *) self; diff --git a/gi/pygi-type.c b/gi/pygi-type.c index b8d4c65..924e0b8 100644 --- a/gi/pygi-type.c +++ b/gi/pygi-type.c @@ -50,7 +50,7 @@ _pygi_type_import_by_name (const char *namespace_, } PyObject * -pygi_type_import_by_g_type_real (GType g_type) +pygi_type_import_by_g_type (GType g_type) { GIRepository *repository; GIBaseInfo *info; @@ -89,7 +89,7 @@ _pygi_type_get_from_g_type (GType g_type) py_type = PyObject_GetAttrString (py_g_type, "pytype"); if (py_type == Py_None) { - py_type = pygi_type_import_by_g_type_real (g_type); + py_type = pygi_type_import_by_g_type (g_type); } Py_DECREF (py_g_type); diff --git a/gi/pygi-type.h b/gi/pygi-type.h index 822a441..85f7551 100644 --- a/gi/pygi-type.h +++ b/gi/pygi-type.h @@ -21,12 +21,13 @@ #define __PYGI_TYPE_H__ #include <Python.h> +#include <girepository.h> G_BEGIN_DECLS /* Public */ -PyObject *pygi_type_import_by_g_type_real (GType g_type); +PyObject *pygi_type_import_by_g_type (GType g_type); /* Private */ diff --git a/gi/pygi-value.c b/gi/pygi-value.c index 8235116..f54f8e1 100644 --- a/gi/pygi-value.c +++ b/gi/pygi-value.c @@ -555,7 +555,7 @@ pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj) * GObject.ParamSpec */ if (G_IS_PARAM_SPEC (pygobject_get (obj))) g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj))); - else if (PyGParamSpec_Check(obj)) + else if (pyg_param_spec_check (obj)) g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL)); else { PyErr_SetString(PyExc_TypeError, "Expected ParamSpec"); @@ -78,112 +78,5 @@ typedef struct { PyGICallableCache *cache; } PyGICCallback; -typedef PyObject * (*PyGIArgOverrideToGIArgumentFunc) (PyObject *value, - GIInterfaceInfo *interface_info, - GITransfer transfer, - GIArgument *arg); -typedef PyObject * (*PyGIArgOverrideFromGIArgumentFunc) (GIInterfaceInfo *interface_info, - GITransfer transfer, - gpointer data); -typedef PyObject * (*PyGIArgOverrideReleaseFunc) (GITypeInfo *type_info, - gpointer struct_); - -struct PyGI_API { - PyObject* (*type_import_by_g_type) (GType g_type); - PyObject* (*get_property_value) (PyGObject *instance, - GParamSpec *pspec); - gint (*set_property_value) (PyGObject *instance, - GParamSpec *pspec, - PyObject *value); - GClosure * (*signal_closure_new) (PyGObject *instance, - GType g_type, - const gchar *sig_name, - PyObject *callback, - PyObject *extra_args, - PyObject *swap_data); - void (*register_foreign_struct) (const char* namespace_, - const char* name, - PyGIArgOverrideToGIArgumentFunc to_func, - PyGIArgOverrideFromGIArgumentFunc from_func, - PyGIArgOverrideReleaseFunc release_func); -}; - -static struct PyGI_API *PyGI_API = NULL; - -static int -_pygi_import (void) -{ - if (PyGI_API != NULL) { - return 1; - } - PyGI_API = (struct PyGI_API*) PyCapsule_Import("gi._API", FALSE); - if (PyGI_API == NULL) { - return -1; - } - - return 0; -} - -static inline PyObject * -pygi_type_import_by_g_type (GType g_type) -{ - if (_pygi_import() < 0) { - return NULL; - } - return PyGI_API->type_import_by_g_type(g_type); -} - -static inline PyObject * -pygi_get_property_value (PyGObject *instance, - GParamSpec *pspec) -{ - if (_pygi_import() < 0) { - return NULL; - } - return PyGI_API->get_property_value(instance, pspec); -} - -static inline gint -pygi_set_property_value (PyGObject *instance, - GParamSpec *pspec, - PyObject *value) -{ - if (_pygi_import() < 0) { - return -1; - } - return PyGI_API->set_property_value(instance, pspec, value); -} - -static inline GClosure * -pygi_signal_closure_new (PyGObject *instance, - GType g_type, - const gchar *sig_name, - PyObject *callback, - PyObject *extra_args, - PyObject *swap_data) -{ - if (_pygi_import() < 0) { - return NULL; - } - return PyGI_API->signal_closure_new(instance, g_type, sig_name, callback, extra_args, swap_data); -} - -static inline PyObject * -pygi_register_foreign_struct (const char* namespace_, - const char* name, - PyGIArgOverrideToGIArgumentFunc to_func, - PyGIArgOverrideFromGIArgumentFunc from_func, - PyGIArgOverrideReleaseFunc release_func) -{ - if (_pygi_import() < 0) { - return NULL; - } - PyGI_API->register_foreign_struct(namespace_, - name, - to_func, - from_func, - release_func); - Py_RETURN_NONE; -} #endif /* __PYGI_H__ */ diff --git a/gi/pyglib-private.h b/gi/pyglib-private.h index 3569c6b..78dd489 100644 --- a/gi/pyglib-private.h +++ b/gi/pyglib-private.h @@ -31,7 +31,6 @@ G_BEGIN_DECLS gboolean _pyglib_handler_marshal(gpointer user_data); void _pyglib_destroy_notify(gpointer user_data); -extern PyObject *PyGError; extern PyObject *pyglib__glib_module_create (void); G_END_DECLS diff --git a/gi/pyglib.c b/gi/pyglib.c index 6c52f31..8db9b17 100644 --- a/gi/pyglib.c +++ b/gi/pyglib.c @@ -28,205 +28,6 @@ #include "pygoptioncontext.h" #include "pygoptiongroup.h" -static PyObject *exception_table = NULL; - -/** - * pyglib_error_marshal: - * @error: a pointer to the GError. - * - * Checks to see if @error has been set. If @error has been set, then a - * GLib.GError Python exception object is returned (but not raised). - * - * Returns: a GLib.GError Python exception object, or NULL. - */ -PyObject * -pyglib_error_marshal (GError **error) -{ - PyGILState_STATE state; - PyObject *exc_type; - PyObject *exc_instance; - PyObject *d; - - g_return_val_if_fail(error != NULL, NULL); - - if (*error == NULL) - return NULL; - - state = pyglib_gil_state_ensure(); - - exc_type = PyGError; - if (exception_table != NULL) - { - PyObject *item; - item = PyDict_GetItem(exception_table, PYGLIB_PyLong_FromLong((*error)->domain)); - if (item != NULL) - exc_type = item; - } - - exc_instance = PyObject_CallFunction(exc_type, "z", (*error)->message); - - if ((*error)->domain) { - PyObject_SetAttrString(exc_instance, "domain", - d=PYGLIB_PyUnicode_FromString(g_quark_to_string((*error)->domain))); - Py_DECREF(d); - } - else - PyObject_SetAttrString(exc_instance, "domain", Py_None); - - PyObject_SetAttrString(exc_instance, "code", - d=PYGLIB_PyLong_FromLong((*error)->code)); - Py_DECREF(d); - - if ((*error)->message) { - PyObject_SetAttrString(exc_instance, "message", - d=PYGLIB_PyUnicode_FromString((*error)->message)); - Py_DECREF(d); - } else { - PyObject_SetAttrString(exc_instance, "message", Py_None); - } - - pyglib_gil_state_release(state); - - return exc_instance; -} - -/** - * pyglib_error_check: - * @error: a pointer to the GError. - * - * Checks to see if the GError has been set. If the error has been - * set, then the glib.GError Python exception will be raised, and - * the GError cleared. - * - * Returns: True if an error was set. - */ -gboolean -pyglib_error_check(GError **error) -{ - PyGILState_STATE state; - PyObject *exc_instance; - - g_return_val_if_fail(error != NULL, FALSE); - if (*error == NULL) - return FALSE; - - state = pyglib_gil_state_ensure(); - - exc_instance = pyglib_error_marshal (error); - PyErr_SetObject(PyGError, exc_instance); - Py_DECREF(exc_instance); - g_clear_error(error); - - pyglib_gil_state_release(state); - - return TRUE; -} - -/** - * pyglib_gerror_exception_check: - * @error: a standard GLib GError ** output parameter - * - * Checks to see if a GError exception has been raised, and if so - * translates the python exception to a standard GLib GError. If the - * raised exception is not a GError then PyErr_Print() is called. - * - * Returns: 0 if no exception has been raised, -1 if it is a - * valid glib.GError, -2 otherwise. - */ -gboolean -pyglib_gerror_exception_check(GError **error) -{ - PyObject *type, *value, *traceback; - PyObject *py_message, *py_domain, *py_code; - const char *bad_gerror_message; - - PyErr_Fetch(&type, &value, &traceback); - if (type == NULL) - return 0; - PyErr_NormalizeException(&type, &value, &traceback); - if (value == NULL) { - PyErr_Restore(type, value, traceback); - PyErr_Print(); - return -2; - } - if (!value || - !PyErr_GivenExceptionMatches(type, - (PyObject *) PyGError)) { - PyErr_Restore(type, value, traceback); - PyErr_Print(); - return -2; - } - Py_DECREF(type); - Py_XDECREF(traceback); - - py_message = PyObject_GetAttrString(value, "message"); - if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) { - bad_gerror_message = "gi._glib.GError instances must have a 'message' string attribute"; - Py_XDECREF(py_message); - goto bad_gerror; - } - - py_domain = PyObject_GetAttrString(value, "domain"); - if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) { - bad_gerror_message = "gi._glib.GError instances must have a 'domain' string attribute"; - Py_DECREF(py_message); - Py_XDECREF(py_domain); - goto bad_gerror; - } - - py_code = PyObject_GetAttrString(value, "code"); - if (!py_code || !PYGLIB_PyLong_Check(py_code)) { - bad_gerror_message = "gi._glib.GError instances must have a 'code' int attribute"; - Py_DECREF(py_message); - Py_DECREF(py_domain); - Py_XDECREF(py_code); - goto bad_gerror; - } - - g_set_error(error, g_quark_from_string(PYGLIB_PyUnicode_AsString(py_domain)), - PYGLIB_PyLong_AsLong(py_code), "%s", PYGLIB_PyUnicode_AsString(py_message)); - - Py_DECREF(py_message); - Py_DECREF(py_code); - Py_DECREF(py_domain); - return -1; - -bad_gerror: - Py_DECREF(value); - g_set_error(error, g_quark_from_static_string("pyglib"), 0, "%s", bad_gerror_message); - PyErr_SetString(PyExc_ValueError, bad_gerror_message); - PyErr_Print(); - return -2; -} - -/** - * pyglib_register_exception_for_domain: - * @name: name of the exception - * @error_domain: error domain - * - * Registers a new glib.GError exception subclass called #name for - * a specific #domain. This exception will be raised when a GError - * of the same domain is passed in to pyglib_error_check(). - * - * Returns: the new exception - */ -PyObject * -pyglib_register_exception_for_domain(gchar *name, - gint error_domain) -{ - PyObject *exception; - - exception = PyErr_NewException(name, PyGError, NULL); - - if (exception_table == NULL) - exception_table = PyDict_New(); - - PyDict_SetItem(exception_table, - PYGLIB_PyLong_FromLong(error_domain), - exception); - - return exception; -} /** * pyg_option_group_transfer_group: diff --git a/gi/pyglib.h b/gi/pyglib.h index 544bada..00228dd 100644 --- a/gi/pyglib.h +++ b/gi/pyglib.h @@ -37,11 +37,6 @@ typedef void (*PyGLibThreadBlockFunc) (void); # define pyglib_gil_state_release PyGILState_Release #endif -gboolean pyglib_error_check(GError **error); -PyObject *pyglib_error_marshal (GError **error); -gboolean pyglib_gerror_exception_check(GError **error); -PyObject *pyglib_register_exception_for_domain(gchar *name, - gint error_domain); GOptionGroup * pyglib_option_group_transfer_group(PyObject *self); /* Private: for gobject <-> glib interaction only. */ diff --git a/gi/pygobject-private.h b/gi/pygobject-private.h index be565d6..b6242cd 100644 --- a/gi/pygobject-private.h +++ b/gi/pygobject-private.h @@ -53,7 +53,6 @@ extern GQuark pygobject_custom_key; void pygobject_data_free (PyGObjectData *data); void pyg_destroy_notify (gpointer user_data); gboolean pyg_handler_marshal (gpointer user_data); -gboolean pyg_error_check (GError **error); int pygobject_constructv (PyGObject *self, guint n_parameters, GParameter *parameters); @@ -62,8 +61,6 @@ PyObject *pyg_integer_richcompare(PyObject *v, PyObject *w, int op); -gboolean pyg_gerror_exception_check(GError **error); - void pygobject_ref_float(PyGObject *self); void pygobject_ref_sink(PyGObject *self); diff --git a/gi/pygobject.c b/gi/pygobject.c index 04fd6a5..1a011e1 100644 --- a/gi/pygobject.c +++ b/gi/pygobject.c @@ -29,6 +29,9 @@ #include "pygi.h" #include "pygi-value.h" +#include "pygi-type.h" +#include "pygi-property.h" +#include "pygi-signal-closure.h" static void pygobject_dealloc(PyGObject *self); static int pygobject_traverse(PyGObject *self, visitproc visit, void *arg); diff --git a/gi/pygobject.h b/gi/pygobject.h index 76b8b11..85359a5 100644 --- a/gi/pygobject.h +++ b/gi/pygobject.h @@ -57,6 +57,8 @@ typedef struct { } PyGBoxed; #define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed) +#define pyg_boxed_get_ptr(v) (((PyGBoxed *)(v))->boxed) +#define pyg_boxed_set_ptr(v,p) (((PyGBoxed *)(v))->boxed = (gpointer)p) #define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode) typedef struct { @@ -66,6 +68,8 @@ typedef struct { } PyGPointer; #define pyg_pointer_get(v,t) ((t *)((PyGPointer *)(v))->pointer) +#define pyg_pointer_get_ptr(v) (((PyGPointer *)(v))->pointer) +#define pyg_pointer_set_ptr(v,p) (((PyGPointer *)(v))->pointer = (gpointer)p) #define pyg_pointer_check(v,typecode) (PyObject_TypeCheck(v, &PyGPointer_Type) && ((PyGPointer *)(v))->gtype == typecode) typedef void (*PyGFatalExceptionFunc) (void); @@ -76,8 +80,13 @@ typedef struct { GParamSpec *pspec; } PyGParamSpec; -#define PyGParamSpec_Get(v) (((PyGParamSpec *)v)->pspec) -#define PyGParamSpec_Check(v) (PyObject_TypeCheck(v, &PyGParamSpec_Type)) +#define pyg_param_spec_get(v) (((PyGParamSpec *)v)->pspec) +#define pyg_param_spec_set(v,p) (((PyGParamSpec *)v)->pspec = (GParamSpec*)p) +#define pyg_param_spec_check(v) (PyObject_TypeCheck(v, &PyGParamSpec_Type)) + +/* Deprecated in favor of lower case with underscore macros above. */ +#define PyGParamSpec_Get pyg_param_spec_get +#define PyGParamSpec_Check pyg_param_spec_check typedef int (*PyGClassInitFunc) (gpointer gclass, PyTypeObject *pyclass); typedef PyTypeObject * (*PyGTypeRegistrationFunction) (const gchar *name, diff --git a/gi/pygoptioncontext.c b/gi/pygoptioncontext.c index f6bb223..ab439f0 100644 --- a/gi/pygoptioncontext.c +++ b/gi/pygoptioncontext.c @@ -25,6 +25,7 @@ #include <pyglib.h> #include "pyglib-private.h" #include "pygoptioncontext.h" +#include "pygi-error.h" PYGLIB_DEFINE_TYPE("gi._glib.OptionContext", PyGOptionContext_Type, PyGOptionContext) @@ -138,7 +139,7 @@ pyg_option_context_parse(PyGOptionContext *self, { g_strfreev(argv_content); g_strfreev(original); - pyglib_error_check(&error); + pygi_error_check(&error); return NULL; } diff --git a/gi/pygoptiongroup.c b/gi/pygoptiongroup.c index 613232f..4c1664d 100644 --- a/gi/pygoptiongroup.c +++ b/gi/pygoptiongroup.c @@ -25,6 +25,7 @@ #include <pyglib.h> #include "pyglib-private.h" #include "pygoptiongroup.h" +#include "pygi-error.h" PYGLIB_DEFINE_TYPE("gi._glib.OptionGroup", PyGOptionGroup_Type, PyGOptionGroup) @@ -148,7 +149,7 @@ arg_func(const gchar *option_name, Py_DECREF(ret); no_error = TRUE; } else - no_error = pyglib_gerror_exception_check(error) != -1; + no_error = pygi_gerror_exception_check(error) != -1; pyglib_gil_state_release(state); return no_error; diff --git a/gi/pygparamspec.c b/gi/pygparamspec.c index 9e6c467..ff53243 100644 --- a/gi/pygparamspec.c +++ b/gi/pygparamspec.c @@ -34,9 +34,9 @@ static PyObject* pyg_param_spec_richcompare(PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other) && Py_TYPE(self) == &PyGParamSpec_Type) - return _pyglib_generic_ptr_richcompare(((PyGParamSpec*)self)->pspec, - ((PyGParamSpec*)other)->pspec, - op); + return _pyglib_generic_ptr_richcompare (pyg_param_spec_get (self), + pyg_param_spec_get (other), + op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -46,7 +46,7 @@ pyg_param_spec_richcompare(PyObject *self, PyObject *other, int op) static long pyg_param_spec_hash(PyGParamSpec *self) { - return (long)self->pspec; + return (long)pyg_param_spec_get (self); } static PyObject * @@ -55,15 +55,15 @@ pyg_param_spec_repr(PyGParamSpec *self) char buf[80]; g_snprintf(buf, sizeof(buf), "<%s '%s'>", - G_PARAM_SPEC_TYPE_NAME(self->pspec), - g_param_spec_get_name(self->pspec)); + G_PARAM_SPEC_TYPE_NAME (pyg_param_spec_get (self)), + g_param_spec_get_name (pyg_param_spec_get (self))); return PYGLIB_PyUnicode_FromString(buf); } static void pyg_param_spec_dealloc(PyGParamSpec *self) { - g_param_spec_unref(self->pspec); + g_param_spec_unref (pyg_param_spec_get (self)); PyObject_DEL(self); } @@ -112,8 +112,8 @@ pyg_param_spec_getattr(PyGParamSpec *self, const gchar *attr) { GParamSpec *pspec; - pspec = self->pspec; - + pspec = pyg_param_spec_get (self); + /* common attributes */ if (!strcmp(attr, "__gtype__")) { return pyg_type_wrapper_new(G_PARAM_SPEC_TYPE(pspec)); @@ -281,7 +281,7 @@ pyg_param_spec_getattr(PyGParamSpec *self, const gchar *attr) static PyObject * pyg_param_spec_dir(PyGParamSpec *self, PyObject *dummy) { - GParamSpec *pspec = self->pspec; + GParamSpec *pspec = pyg_param_spec_get (self); if (G_IS_PARAM_SPEC_CHAR(pspec)) { return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__", @@ -393,7 +393,7 @@ pyg_param_spec_new(GParamSpec *pspec) if (self == NULL) return NULL; - self->pspec = g_param_spec_ref(pspec); + pyg_param_spec_set (self, g_param_spec_ref (pspec)); return (PyObject *)self; } diff --git a/gi/pygpointer.c b/gi/pygpointer.c index 2729695..d728a40 100644 --- a/gi/pygpointer.c +++ b/gi/pygpointer.c @@ -27,6 +27,7 @@ #include "pygpointer.h" #include "pygi.h" +#include "pygi-type.h" GQuark pygpointer_class_key; @@ -43,9 +44,9 @@ static PyObject* pyg_pointer_richcompare(PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other)) - return _pyglib_generic_ptr_richcompare(((PyGPointer*)self)->pointer, - ((PyGPointer*)other)->pointer, - op); + return _pyglib_generic_ptr_richcompare (pyg_pointer_get_ptr (self), + pyg_pointer_get_ptr (other), + op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -55,7 +56,7 @@ pyg_pointer_richcompare(PyObject *self, PyObject *other, int op) static long pyg_pointer_hash(PyGPointer *self) { - return (long)self->pointer; + return (long)pyg_pointer_get_ptr (self); } static PyObject * @@ -64,7 +65,7 @@ pyg_pointer_repr(PyGPointer *self) gchar buf[128]; g_snprintf(buf, sizeof(buf), "<%s at 0x%lx>", g_type_name(self->gtype), - (long)self->pointer); + (long)pyg_pointer_get_ptr (self)); return PYGLIB_PyUnicode_FromString(buf); } @@ -76,7 +77,7 @@ pyg_pointer_init(PyGPointer *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTuple(args, ":GPointer.__init__")) return -1; - self->pointer = NULL; + pyg_pointer_set_ptr (self, NULL); self->gtype = 0; g_snprintf(buf, sizeof(buf), "%s can not be constructed", @@ -174,7 +175,7 @@ pyg_pointer_new(GType pointer_type, gpointer pointer) if (self == NULL) return NULL; - self->pointer = pointer; + pyg_pointer_set_ptr (self, pointer); self->gtype = pointer_type; return (PyObject *)self; diff --git a/gi/pygspawn.c b/gi/pygspawn.c index 8f3ff51..3851ad9 100644 --- a/gi/pygspawn.c +++ b/gi/pygspawn.c @@ -26,6 +26,7 @@ #include "pyglib-private.h" #include "pygspawn.h" +#include "pygi-error.h" struct _PyGChildSetupData { PyObject *func; @@ -214,7 +215,7 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs) Py_XDECREF(callback_data->data); g_slice_free(struct _PyGChildSetupData, callback_data); } - pyglib_error_check(&error); + pygi_error_check(&error); return NULL; } g_free(argv); diff --git a/gi/pygtype.c b/gi/pygtype.c index 131a271..985e969 100644 --- a/gi/pygtype.c +++ b/gi/pygtype.c @@ -28,6 +28,7 @@ #include "pygparamspec.h" #include "pygtype.h" +#include "pygi-type.h" #include "pygi-value.h" /* -------------- __gtype__ objects ---------------------------- */ @@ -621,6 +622,7 @@ pyg_type_lookup(GType type) /* recursively lookup types */ while (ptype) { + pygi_type_import_by_g_type (ptype); if ((tm = g_type_get_qdata(ptype, pyg_type_marshal_key)) != NULL) break; ptype = g_type_parent(ptype); @@ -888,7 +890,8 @@ pyg_signal_class_closure_marshal(GClosure *closure, && item->ob_refcnt != 1) { PyGBoxed* boxed_item = (PyGBoxed*)item; if (!boxed_item->free_on_dealloc) { - boxed_item->boxed = g_boxed_copy(boxed_item->gtype, boxed_item->boxed); + gpointer boxed_ptr = pyg_boxed_get_ptr (boxed_item); + pyg_boxed_set_ptr (boxed_item, g_boxed_copy (boxed_item->gtype, boxed_ptr)); boxed_item->free_on_dealloc = TRUE; } } diff --git a/gi/types.py b/gi/types.py index e6e3903..aa5bcb4 100644 --- a/gi/types.py +++ b/gi/types.py @@ -55,6 +55,17 @@ class MetaClassHelper(object): for method_info in cls.__info__.get_methods(): setattr(cls, method_info.__name__, method_info) + def _setup_class_methods(cls): + info = cls.__info__ + class_struct = info.get_class_struct() + if class_struct is None: + return + for method_info in class_struct.get_methods(): + name = method_info.__name__ + # Don't mask regular methods or base class methods with TypeClass methods. + if not hasattr(cls, name): + setattr(cls, name, classmethod(method_info)) + def _setup_fields(cls): for field_info in cls.__info__.get_fields(): name = field_info.get_name().replace('-', '_') @@ -182,7 +193,7 @@ class _GObjectMetaBase(type): cls._type_register(cls.__dict__) def _type_register(cls, namespace): - ## don't register the class if already registered + # don't register the class if already registered if '__gtype__' in namespace: return @@ -211,6 +222,8 @@ class GObjectMeta(_GObjectMetaBase, MetaClassHelper): if is_python_defined: cls._setup_vfuncs() elif is_gi_defined: + if isinstance(cls.__info__, ObjectInfo): + cls._setup_class_methods() cls._setup_methods() cls._setup_constants() cls._setup_native_vfuncs() |