diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:35:07 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:35:08 +0900 |
commit | df82aa0a770d4b3e52e96eb5c60b528ddcdb2343 (patch) | |
tree | bbf6d1c2270fe7057773ff1c2cf578ff40f704da /gi | |
parent | 095413828bd9b33e57b352f9ca80473172611202 (diff) | |
download | pygobject2-df82aa0a770d4b3e52e96eb5c60b528ddcdb2343.tar.gz pygobject2-df82aa0a770d4b3e52e96eb5c60b528ddcdb2343.tar.bz2 pygobject2-df82aa0a770d4b3e52e96eb5c60b528ddcdb2343.zip |
Imported Upstream version 2.26.0upstream/2.26.0
Change-Id: I616aeca320e366d54dd6e188c260b64639305c49
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi')
34 files changed, 1734 insertions, 842 deletions
diff --git a/gi/Makefile.am b/gi/Makefile.am index c651c97..2fbb4ac 100644 --- a/gi/Makefile.am +++ b/gi/Makefile.am @@ -7,7 +7,7 @@ SUBDIRS = \ repository \ overrides -INCLUDES = -I$(top_srcdir)/gobject +INCLUDES = -I$(top_srcdir)/gobject -I$(top_srcdir)/glib pygidir = $(pkgpyexecdir)/gi pygi_PYTHON = \ @@ -22,7 +22,7 @@ _gi_la_CFLAGS = \ _gi_la_LDFLAGS = \ -module \ -avoid-version \ - -export-symbols-regex init_gi + -export-symbols-regex "init_gi|PyInit__gi" _gi_la_LIBADD = \ $(GI_LIBS) _gi_la_SOURCES = \ @@ -34,6 +34,8 @@ _gi_la_SOURCES = \ pygi-invoke.h \ pygi-foreign.c \ pygi-foreign.h \ + pygi-foreign-gvariant.c \ + pygi-foreign-gvariant.h \ pygi-struct.c \ pygi-struct.h \ pygi-argument.c \ @@ -48,6 +50,8 @@ _gi_la_SOURCES = \ pygi-callbacks.h \ pygi.h \ pygi-private.h \ + pygi-property.c \ + pygi-property.h \ pygobject-external.h \ gimodule.c @@ -58,24 +62,28 @@ _gi_cairo_la_CFLAGS = \ _gi_cairo_la_LDFLAGS = \ -module \ -avoid-version \ - -export-symbols-regex init_gi_cairo + -export-symbols-regex "init_gi_cairo|PyInit__gi_cairo" _gi_cairo_la_LIBADD = \ $(GI_LIBS) \ $(PYCAIRO_LIBS) _gi_cairo_la_SOURCES = pygi-foreign-cairo.c -pygi_LTLIBRARIES = _gi.la _gi_cairo.la + +pygi_LTLIBRARIES = _gi.la + +if ENABLE_CAIRO +pygi_LTLIBRARIES += _gi_cairo.la +endif + # This is to ensure we have a symlink to the .so in the # build directory, which the Python interpreter can load # directly without having to know how to parse .la files. -_gi.so: _gi.la - rm -f $@ && $(LN_S) .libs/$@ $@ -_gi_cairo.so: _gi_cairo.la - rm -f $@ && $(LN_S) .libs/$@ $@ +.la.so: + test -L $@ || $(LN_S) .libs/$@ $@ -all-local: _gi.so _gi_cairo.so -check-local: _gi.so _gi_cairo.so +all-local: $(LTLIBRARIES:.la=.so) +check-local: $(LTLIBRARIES:.la=.so) clean-local: - rm -f _gi.so _gi_cairo.so + rm -f $(LTLIBRARIES:.la=.so) diff --git a/gi/Makefile.in b/gi/Makefile.in index 6fb0b9a..1aecd0a 100644 --- a/gi/Makefile.in +++ b/gi/Makefile.in @@ -33,6 +33,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@ENABLE_CAIRO_TRUE@am__append_1 = _gi_cairo.la subdir = gi DIST_COMMON = $(pygi_PYTHON) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in @@ -75,9 +76,10 @@ am__DEPENDENCIES_1 = _gi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__gi_la_OBJECTS = _gi_la-pygi-repository.lo _gi_la-pygi-info.lo \ _gi_la-pygi-invoke.lo _gi_la-pygi-foreign.lo \ - _gi_la-pygi-struct.lo _gi_la-pygi-argument.lo \ - _gi_la-pygi-type.lo _gi_la-pygi-boxed.lo \ - _gi_la-pygi-closure.lo _gi_la-pygi-callbacks.lo \ + _gi_la-pygi-foreign-gvariant.lo _gi_la-pygi-struct.lo \ + _gi_la-pygi-argument.lo _gi_la-pygi-type.lo \ + _gi_la-pygi-boxed.lo _gi_la-pygi-closure.lo \ + _gi_la-pygi-callbacks.lo _gi_la-pygi-property.lo \ _gi_la-gimodule.lo _gi_la_OBJECTS = $(am__gi_la_OBJECTS) AM_V_lt = $(am__v_lt_$(V)) @@ -93,6 +95,7 @@ _gi_cairo_la_OBJECTS = $(am__gi_cairo_la_OBJECTS) _gi_cairo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(_gi_cairo_la_CFLAGS) \ $(CFLAGS) $(_gi_cairo_la_LDFLAGS) $(LDFLAGS) -o $@ +@ENABLE_CAIRO_TRUE@am__gi_cairo_la_rpath = -rpath $(pygidir) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -199,6 +202,7 @@ GIOUNIX_LIBS = @GIOUNIX_LIBS@ GIO_CFLAGS = @GIO_CFLAGS@ GIO_LIBS = @GIO_LIBS@ GI_CFLAGS = @GI_CFLAGS@ +GI_DATADIR = @GI_DATADIR@ GI_LIBS = @GI_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ @@ -323,7 +327,7 @@ SUBDIRS = \ repository \ overrides -INCLUDES = -I$(top_srcdir)/gobject +INCLUDES = -I$(top_srcdir)/gobject -I$(top_srcdir)/glib pygidir = $(pkgpyexecdir)/gi pygi_PYTHON = \ types.py \ @@ -338,7 +342,7 @@ _gi_la_CFLAGS = \ _gi_la_LDFLAGS = \ -module \ -avoid-version \ - -export-symbols-regex init_gi + -export-symbols-regex "init_gi|PyInit__gi" _gi_la_LIBADD = \ $(GI_LIBS) @@ -352,6 +356,8 @@ _gi_la_SOURCES = \ pygi-invoke.h \ pygi-foreign.c \ pygi-foreign.h \ + pygi-foreign-gvariant.c \ + pygi-foreign-gvariant.h \ pygi-struct.c \ pygi-struct.h \ pygi-argument.c \ @@ -366,6 +372,8 @@ _gi_la_SOURCES = \ pygi-callbacks.h \ pygi.h \ pygi-private.h \ + pygi-property.c \ + pygi-property.h \ pygobject-external.h \ gimodule.c @@ -377,18 +385,18 @@ _gi_cairo_la_CFLAGS = \ _gi_cairo_la_LDFLAGS = \ -module \ -avoid-version \ - -export-symbols-regex init_gi_cairo + -export-symbols-regex "init_gi_cairo|PyInit__gi_cairo" _gi_cairo_la_LIBADD = \ $(GI_LIBS) \ $(PYCAIRO_LIBS) _gi_cairo_la_SOURCES = pygi-foreign-cairo.c -pygi_LTLIBRARIES = _gi.la _gi_cairo.la +pygi_LTLIBRARIES = _gi.la $(am__append_1) all: all-recursive .SUFFIXES: -.SUFFIXES: .c .lo .o .obj +.SUFFIXES: .c .la .lo .o .obj .so $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -453,7 +461,7 @@ clean-pygiLTLIBRARIES: _gi.la: $(_gi_la_OBJECTS) $(_gi_la_DEPENDENCIES) $(AM_V_CCLD)$(_gi_la_LINK) -rpath $(pygidir) $(_gi_la_OBJECTS) $(_gi_la_LIBADD) $(LIBS) _gi_cairo.la: $(_gi_cairo_la_OBJECTS) $(_gi_cairo_la_DEPENDENCIES) - $(AM_V_CCLD)$(_gi_cairo_la_LINK) -rpath $(pygidir) $(_gi_cairo_la_OBJECTS) $(_gi_cairo_la_LIBADD) $(LIBS) + $(AM_V_CCLD)$(_gi_cairo_la_LINK) $(am__gi_cairo_la_rpath) $(_gi_cairo_la_OBJECTS) $(_gi_cairo_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -467,9 +475,11 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-boxed.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-callbacks.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-closure.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-foreign-gvariant.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-foreign.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-info.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-invoke.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-property.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-repository.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-struct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-type.Plo@am__quote@ @@ -530,6 +540,14 @@ _gi_la-pygi-foreign.lo: pygi-foreign.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-foreign.lo `test -f 'pygi-foreign.c' || echo '$(srcdir)/'`pygi-foreign.c +_gi_la-pygi-foreign-gvariant.lo: pygi-foreign-gvariant.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-foreign-gvariant.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-foreign-gvariant.Tpo -c -o _gi_la-pygi-foreign-gvariant.lo `test -f 'pygi-foreign-gvariant.c' || echo '$(srcdir)/'`pygi-foreign-gvariant.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-foreign-gvariant.Tpo $(DEPDIR)/_gi_la-pygi-foreign-gvariant.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygi-foreign-gvariant.c' object='_gi_la-pygi-foreign-gvariant.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-foreign-gvariant.lo `test -f 'pygi-foreign-gvariant.c' || echo '$(srcdir)/'`pygi-foreign-gvariant.c + _gi_la-pygi-struct.lo: pygi-struct.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-struct.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-struct.Tpo -c -o _gi_la-pygi-struct.lo `test -f 'pygi-struct.c' || echo '$(srcdir)/'`pygi-struct.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-struct.Tpo $(DEPDIR)/_gi_la-pygi-struct.Plo @@ -578,6 +596,14 @@ _gi_la-pygi-callbacks.lo: pygi-callbacks.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-callbacks.lo `test -f 'pygi-callbacks.c' || echo '$(srcdir)/'`pygi-callbacks.c +_gi_la-pygi-property.lo: pygi-property.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-property.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-property.Tpo -c -o _gi_la-pygi-property.lo `test -f 'pygi-property.c' || echo '$(srcdir)/'`pygi-property.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-property.Tpo $(DEPDIR)/_gi_la-pygi-property.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pygi-property.c' object='_gi_la-pygi-property.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-property.lo `test -f 'pygi-property.c' || echo '$(srcdir)/'`pygi-property.c + _gi_la-gimodule.lo: gimodule.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-gimodule.lo -MD -MP -MF $(DEPDIR)/_gi_la-gimodule.Tpo -c -o _gi_la-gimodule.lo `test -f 'gimodule.c' || echo '$(srcdir)/'`gimodule.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-gimodule.Tpo $(DEPDIR)/_gi_la-gimodule.Plo @@ -960,15 +986,13 @@ uninstall-am: uninstall-pygiLTLIBRARIES uninstall-pygiPYTHON # This is to ensure we have a symlink to the .so in the # build directory, which the Python interpreter can load # directly without having to know how to parse .la files. -_gi.so: _gi.la - rm -f $@ && $(LN_S) .libs/$@ $@ -_gi_cairo.so: _gi_cairo.la - rm -f $@ && $(LN_S) .libs/$@ $@ +.la.so: + test -L $@ || $(LN_S) .libs/$@ $@ -all-local: _gi.so _gi_cairo.so -check-local: _gi.so _gi_cairo.so +all-local: $(LTLIBRARIES:.la=.so) +check-local: $(LTLIBRARIES:.la=.so) clean-local: - rm -f _gi.so _gi_cairo.so + rm -f $(LTLIBRARIES:.la=.so) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/gi/gimodule.c b/gi/gimodule.c index df0db7a..89caf4e 100644 --- a/gi/gimodule.c +++ b/gi/gimodule.c @@ -25,6 +25,7 @@ #include "pygi.h" #include <pygobject.h> +#include <pyglib-python-compat.h> static PyObject * _wrap_pyg_enum_add (PyObject *self, @@ -195,12 +196,17 @@ _wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args) field_info = g_struct_info_get_field (struct_info, i); if (strcmp (g_base_info_get_name ( (GIBaseInfo*) field_info), - g_base_info_get_name ( (GIBaseInfo*) vfunc_info)) != 0) + g_base_info_get_name ( (GIBaseInfo*) vfunc_info)) != 0) { + g_base_info_unref (field_info); continue; + } type_info = g_field_info_get_type (field_info); - if (g_type_info_get_tag (type_info) != GI_TYPE_TAG_INTERFACE) + if (g_type_info_get_tag (type_info) != GI_TYPE_TAG_INTERFACE) { + g_base_info_unref (type_info); + g_base_info_unref (field_info); continue; + } interface_info = g_type_info_get_interface (type_info); g_assert (g_base_info_get_type (interface_info) == GI_INFO_TYPE_CALLBACK); @@ -229,32 +235,85 @@ _wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyMethodDef _pygi_functions[] = { +static PyObject * +_wrap_pyg_variant_new_tuple (PyObject *self, PyObject *args) +{ + PyObject *py_values; + GVariant **values = NULL; + GVariant *variant = NULL; + PyObject *py_variant = NULL; + PyObject *py_type; + gssize i; + + if (!PyArg_ParseTuple (args, "O!:variant_new_tuple", + &PyTuple_Type, &py_values)) { + return NULL; + } + + 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 %d is not a GLib.Variant", i); + return NULL; + } + + values[i] = (GVariant *) ( (PyGPointer *) value)->pointer; + } + + 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_variant_type_from_string (PyObject *self, PyObject *args) +{ + char *type_string; + PyObject *py_type; + PyObject *py_variant = NULL; + + if (!PyArg_ParseTuple (args, "s:variant_type_from_string", + &type_string)) { + return NULL; + } + + py_type = _pygi_type_import_by_name ("GLib", "VariantType"); + + py_variant = _pygi_struct_new ( (PyTypeObject *) py_type, type_string, FALSE); + + return py_variant; +} + +static PyMethodDef _gi_functions[] = { { "enum_add", (PyCFunction) _wrap_pyg_enum_add, METH_VARARGS | METH_KEYWORDS }, { "flags_add", (PyCFunction) _wrap_pyg_flags_add, METH_VARARGS | METH_KEYWORDS }, { "set_object_has_new_constructor", (PyCFunction) _wrap_pyg_set_object_has_new_constructor, METH_VARARGS | METH_KEYWORDS }, { "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 }, { 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_register_foreign_struct_real, }; -PyMODINIT_FUNC -init_gi (void) +PYGLIB_MODULE_START(_gi, "_gi") { - PyObject *m; PyObject *api; - m = Py_InitModule ("_gi", _pygi_functions); - if (m == NULL) { - return; - } - if (pygobject_init (-1, -1, -1) == NULL) { return; } @@ -263,16 +322,16 @@ init_gi (void) return; } - _pygi_repository_register_types (m); - _pygi_info_register_types (m); - _pygi_struct_register_types (m); - _pygi_boxed_register_types (m); + _pygi_repository_register_types (module); + _pygi_info_register_types (module); + _pygi_struct_register_types (module); + _pygi_boxed_register_types (module); _pygi_argument_init(); api = PyCObject_FromVoidPtr ( (void *) &CAPI, NULL); if (api == NULL) { return; } - PyModule_AddObject (m, "_API", api); + PyModule_AddObject (module, "_API", api); } - +PYGLIB_MODULE_END diff --git a/gi/importer.py b/gi/importer.py index 6076692..1cb9b92 100644 --- a/gi/importer.py +++ b/gi/importer.py @@ -27,7 +27,7 @@ import sys import gobject from ._gi import Repository, RepositoryError -from .module import DynamicModule, DynamicGObjectModule, ModuleProxy +from .module import DynamicModule, DynamicGObjectModule repository = Repository.get_default() @@ -48,10 +48,10 @@ class DynamicImporter(object): path, namespace = fullname.rsplit('.', 1) if path != self.path: return - try: - repository.require(namespace) - except RepositoryError, e: - logging.exception(e) + + if not repository.enumerate_versions(namespace): + logging.error('Could not find any typelib for %s', namespace) + return None else: return self @@ -69,18 +69,10 @@ class DynamicImporter(object): dynamic_module = DynamicModule(namespace) modules[namespace] = dynamic_module - overrides_modules = __import__('gi.overrides', fromlist=[namespace]) - overrides_module = getattr(overrides_modules, namespace, None) - - if overrides_module is not None: - module = ModuleProxy(fullname, namespace, dynamic_module, overrides_module) - else: - module = dynamic_module - - module.__file__ = '<%s>' % fullname - module.__loader__ = self + dynamic_module.__file__ = '<%s>' % fullname + dynamic_module.__loader__ = self - sys.modules[fullname] = module + sys.modules[fullname] = dynamic_module - return module + return dynamic_module diff --git a/gi/module.py b/gi/module.py index e149986..819fcc6 100644 --- a/gi/module.py +++ b/gi/module.py @@ -64,6 +64,7 @@ def get_parent_for_object(object_info): module = __import__('gi.repository.%s' % namespace, fromlist=[name]) return getattr(module, name) + def get_interfaces_for_object(object_info): interfaces = [] for interface_info in object_info.get_interfaces(): @@ -75,17 +76,24 @@ def get_interfaces_for_object(object_info): return interfaces -class DynamicModule(object): +class IntrospectionModule(object): - def __init__(self, namespace): + def __init__(self, namespace, version=None): + repository.require(namespace, version) self._namespace = namespace + self.version = version self.__name__ = 'gi.repository.' + namespace + repository.require(self._namespace, self.version) + + if self.version is None: + self.version = repository.get_version(self._namespace) + def __getattr__(self, name): info = repository.find_by_name(self._namespace, name) if not info: raise AttributeError("%r object has no attribute %r" % ( - self.__class__.__name__, name)) + self.__name__, name)) if isinstance(info, EnumInfo): g_type = info.get_g_type() @@ -133,7 +141,7 @@ class DynamicModule(object): elif g_type.is_a(gobject.TYPE_POINTER) or g_type == gobject.TYPE_NONE: bases = (Struct,) else: - raise TypeError, "unable to create a wrapper for %s.%s" % (info.get_namespace(), info.get_name()) + raise TypeError("unable to create a wrapper for %s.%s" % (info.get_namespace(), info.get_name())) metaclass = StructMeta else: raise NotImplementedError(info) @@ -162,10 +170,10 @@ class DynamicModule(object): def __repr__(self): path = repository.get_typelib_path(self._namespace) - return "<DynamicModule %r from %r>" % (self._namespace, path) + return "<IntrospectionModule %r from %r>" % (self._namespace, path) -class DynamicGObjectModule(DynamicModule): +class DynamicGObjectModule(IntrospectionModule): """Wrapper for the GObject module This class allows us to access both the static PyGObject module and the GI GObject module @@ -182,12 +190,11 @@ class DynamicGObjectModule(DynamicModule): """ def __init__(self): - self._namespace = 'GObject' - self._module = gobject + IntrospectionModule.__init__(self, namespace='GObject') def __getattr__(self, name): # first see if this attr is in the gobject module - attr = getattr(self._module, name, None) + attr = getattr(gobject, name, None) # if not in module assume request for an attr exported through GI if attr is None: @@ -195,23 +202,34 @@ class DynamicGObjectModule(DynamicModule): return attr -class ModuleProxy(object): - - def __init__(self, name, namespace, dynamic_module, overrides_module): - self.__name__ = name +class DynamicModule(object): + def __init__(self, namespace): self._namespace = namespace - self._dynamic_module = dynamic_module - self._overrides_module = overrides_module + self.introspection_module = None + self._version = None + self._overrides_module = None + + def require_version(self, version): + if self.introspection_module is not None and \ + self.introspection_module.version != version: + raise RuntimeError('Module has been already loaded ') + self._version = version + + def _import(self): + self.introspection_module = IntrospectionModule(self._namespace, + self._version) + + overrides_modules = __import__('gi.overrides', fromlist=[self._namespace]) + self._overrides_module = getattr(overrides_modules, self._namespace, None) def __getattr__(self, name): - override_exports = getattr(self._overrides_module, '__all__', ()) - if (name in override_exports): - attribute = getattr(self._overrides_module, name, None) - else: - attribute = getattr(self._dynamic_module, name) - return attribute + if self.introspection_module is None: + self._import() - def __str__(self): - return "<ModuleProxy %r>" % self.__name__ + if self._overrides_module is not None: + override_exports = getattr(self._overrides_module, '__all__', ()) + if name in override_exports: + return getattr(self._overrides_module, name, None) + return getattr(self.introspection_module, name) diff --git a/gi/overrides/GIMarshallingTests.py b/gi/overrides/GIMarshallingTests.py index 768efd7..ee01495 100644 --- a/gi/overrides/GIMarshallingTests.py +++ b/gi/overrides/GIMarshallingTests.py @@ -21,7 +21,7 @@ from ..types import override from ..importer import modules -GIMarshallingTests = modules['GIMarshallingTests'] +GIMarshallingTests = modules['GIMarshallingTests'].introspection_module __all__ = [] diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py new file mode 100644 index 0000000..78d8c35 --- /dev/null +++ b/gi/overrides/GLib.py @@ -0,0 +1,165 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab +# +# Copyright (C) 2010 Tomeu Vizoso <tomeu.vizoso@collabora.co.uk> +# +# 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 + +from ..importer import modules +from .._gi import variant_new_tuple, variant_type_from_string + +GLib = modules['GLib'].introspection_module + +__all__ = [] + +class _VariantCreator(object): + + _LEAF_CONSTRUCTORS = { + 'b': GLib.Variant.new_boolean, + 'y': GLib.Variant.new_byte, + 'n': GLib.Variant.new_int16, + 'q': GLib.Variant.new_uint16, + 'i': GLib.Variant.new_int32, + 'u': GLib.Variant.new_uint32, + 'x': GLib.Variant.new_int64, + 't': GLib.Variant.new_uint64, + 'h': GLib.Variant.new_handle, + 'd': GLib.Variant.new_double, + 's': GLib.Variant.new_string, + 'o': GLib.Variant.new_object_path, + 'g': GLib.Variant.new_signature, + 'v': GLib.Variant.new_variant, + } + + def __init__(self, format_string, args): + self._format_string = format_string + self._args = args + + def create(self): + if self._format_string_is_leaf(): + return self._new_variant_leaf() + + format_char = self._pop_format_char() + arg = self._pop_arg() + + if format_char == 'm': + raise NotImplementedError() + else: + builder = GLib.VariantBuilder() + if format_char == '(': + builder.init(variant_type_from_string('r')) + elif format_char == '{': + builder.init(variant_type_from_string('{?*}')) + else: + raise NotImplementedError() + format_char = self._pop_format_char() + while format_char not in [')', '}']: + builder.add_value(Variant(format_char, arg)) + format_char = self._pop_format_char() + if self._args: + arg = self._pop_arg() + return builder.end() + + def _format_string_is_leaf(self): + format_char = self._format_string[0] + return not format_char in ['m', '(', '{'] + + def _format_string_is_nnp(self): + format_char = self._format_string[0] + return format_char in ['a', 's', 'o', 'g', '^', '@', '*', '?', 'r', + 'v', '&'] + + def _new_variant_leaf(self): + if self._format_string_is_nnp(): + return self._new_variant_nnp() + + format_char = self._pop_format_char() + arg = self._pop_arg() + + return _VariantCreator._LEAF_CONSTRUCTORS[format_char](arg) + + def _new_variant_nnp(self): + format_char = self._pop_format_char() + arg = self._pop_arg() + + if format_char == '&': + format_char = self._pop_format_char() + + if format_char == 'a': + builder = GLib.VariantBuilder() + builder.init(variant_type_from_string('a*')) + + element_format_string = self._pop_leaf_format_string() + + if isinstance(arg, dict): + for element in arg.items(): + value = Variant(element_format_string, *element) + builder.add_value(value) + else: + for element in arg: + value = Variant(element_format_string, element) + builder.add_value(value) + return builder.end() + elif format_char == '^': + raise NotImplementedError() + elif format_char == '@': + raise NotImplementedError() + elif format_char == '*': + raise NotImplementedError() + elif format_char == 'r': + raise NotImplementedError() + elif format_char == '?': + raise NotImplementedError() + else: + return _VariantCreator._LEAF_CONSTRUCTORS[format_char](arg) + + def _pop_format_char(self): + format_char = self._format_string[0] + self._format_string = self._format_string[1:] + return format_char + + def _pop_leaf_format_string(self): + # FIXME: This will break when the leaf is inside a tuple or dict entry + format_string = self._format_string + self._format_string = '' + return format_string + + def _pop_arg(self): + arg = self._args[0] + self._args = self._args[1:] + return arg + +class Variant(GLib.Variant): + def __new__(cls, format_string, *args): + creator = _VariantCreator(format_string, args) + return creator.create() + + def __repr__(self): + return '<GLib.Variant(%s)>' % getattr(self, 'print')(True) + +@classmethod +def new_tuple(cls, *elements): + return variant_new_tuple(elements) + +def get_string(self): + value, length = GLib.Variant.get_string(self) + return value + +setattr(Variant, 'new_tuple', new_tuple) +setattr(Variant, 'get_string', get_string) + +__all__.append('Variant') + diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py index 4eaff08..23a9d8e 100644 --- a/gi/overrides/Gdk.py +++ b/gi/overrides/Gdk.py @@ -22,7 +22,7 @@ from ..types import override from ..importer import modules -Gdk = modules['Gdk'] +Gdk = modules['Gdk'].introspection_module __all__ = [] @@ -43,6 +43,25 @@ class Color(Gdk.Color): Color = override(Color) __all__.append('Color') +if Gdk.version == '2.0': + class Rectangle(Gdk.Rectangle): + + def __init__(self, x, y, width, height): + Gdk.Rectangle.__init__(self) + self.x = x + self.y = y + self.width = width + self.height = height + + def __new__(cls, *args, **kwargs): + return Gdk.Rectangle.__new__(cls) + + def __repr__(self): + return '<Gdk.Rectangle(x=%d, y=%d, width=%d, height=%d)>' % (self.x, self.y, self.height, self.width) + + Rectangle = override(Rectangle) + __all__.append('Rectangle') + class Drawable(Gdk.Drawable): def cairo_create(self): return Gdk.cairo_create(self) @@ -50,6 +69,54 @@ class Drawable(Gdk.Drawable): Drawable = override(Drawable) __all__.append('Drawable') +class Event(Gdk.Event): + _UNION_MEMBERS = { + Gdk.EventType.DELETE: 'any', + Gdk.EventType.DESTROY: 'any', + Gdk.EventType.EXPOSE: 'expose', + Gdk.EventType.MOTION_NOTIFY: 'motion', + Gdk.EventType.BUTTON_PRESS: 'button', + #Gdk.EventType.2BUTTON_PRESS: 'button', + #Gdk.EventType.3BUTTON_PRESS: 'button', + Gdk.EventType.BUTTON_RELEASE: 'button', + Gdk.EventType.KEY_PRESS: 'key', + Gdk.EventType.KEY_RELEASE: 'key', + Gdk.EventType.ENTER_NOTIFY: 'crossing', + Gdk.EventType.LEAVE_NOTIFY: 'crossing', + Gdk.EventType.FOCUS_CHANGE: 'focus_change', + Gdk.EventType.CONFIGURE: 'configure', + Gdk.EventType.MAP: 'any', + Gdk.EventType.UNMAP: 'any', + Gdk.EventType.PROPERTY_NOTIFY: 'property', + Gdk.EventType.SELECTION_CLEAR: 'selection', + Gdk.EventType.SELECTION_REQUEST: 'selection', + Gdk.EventType.SELECTION_NOTIFY: 'selection', + Gdk.EventType.PROXIMITY_IN: 'proximity', + Gdk.EventType.PROXIMITY_OUT: 'proximity', + Gdk.EventType.DRAG_ENTER: 'dnd', + Gdk.EventType.DRAG_LEAVE: 'dnd', + Gdk.EventType.DRAG_MOTION: 'dnd', + Gdk.EventType.DRAG_STATUS: 'dnd', + Gdk.EventType.DROP_START: 'dnd', + Gdk.EventType.DROP_FINISHED: 'dnd', + Gdk.EventType.CLIENT_EVENT: 'client', + Gdk.EventType.VISIBILITY_NOTIFY: 'visibility', + Gdk.EventType.NO_EXPOSE: 'no_expose' + } + + def __new__(cls, *args, **kwargs): + return Gdk.Event.__new__(cls) + + def __getattr__(self, name): + real_event = getattr(self, '_UNION_MEMBERS').get(self.type) + if real_event: + return getattr(getattr(self, real_event), name) + else: + return getattr(self, name) + +Event = override(Event) +__all__.append('Event') + import sys diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py index 38a90b3..1f6901c 100644 --- a/gi/overrides/Gtk.py +++ b/gi/overrides/Gtk.py @@ -19,13 +19,21 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA +import sys import gobject from gi.repository import Gdk from gi.repository import GObject from ..types import override from ..importer import modules -Gtk = modules['Gtk'] +if sys.version_info >= (3, 0): + _basestring = str + _callable = lambda c: hasattr(c, '__call__') +else: + _basestring = basestring + _callable = callable + +Gtk = modules['Gtk'].introspection_module __all__ = [] class ActionGroup(Gtk.ActionGroup): @@ -184,7 +192,7 @@ __all__.append('ActionGroup') class UIManager(Gtk.UIManager): def add_ui_from_string(self, buffer): - if not isinstance(buffer, basestring): + if not isinstance(buffer, _basestring): raise TypeError('buffer must be a string') length = len(buffer) @@ -207,7 +215,7 @@ class Builder(Gtk.Builder): if handler is None: raise AttributeError('Handler %s not found' % handler_name) - if not callable(handler): + if not _callable(handler): raise TypeError('Handler %s is not a method or function' % handler_name) after = flags or GObject.ConnectFlags.AFTER @@ -226,7 +234,7 @@ class Builder(Gtk.Builder): obj_or_map); def add_from_string(self, buffer): - if not isinstance(buffer, basestring): + if not isinstance(buffer, _basestring): raise TypeError('buffer must be a string') length = len(buffer) @@ -234,7 +242,7 @@ class Builder(Gtk.Builder): return Gtk.Builder.add_from_string(self, buffer, length) def add_objects_from_string(self, buffer, object_ids): - if not isinstance(buffer, basestring): + if not isinstance(buffer, _basestring): raise TypeError('buffer must be a string') length = len(buffer) @@ -256,8 +264,14 @@ class Dialog(Gtk.Dialog): self.set_modal(True) if flags & Gtk.DialogFlags.DESTROY_WITH_PARENT: self.set_destroy_with_parent(True) - if flags & Gtk.DialogFlags.NO_SEPARATOR: - self.set_has_separator(False) + + # NO_SEPARATOR has been removed from Gtk 3 + try: + if flags & Gtk.DialogFlags.NO_SEPARATOR: + self.set_has_separator(False) + except AttributeError: + pass + if buttons: self.add_buttons(*buttons) @@ -324,14 +338,14 @@ class TextBuffer(Gtk.TextBuffer): return tag def insert(self, iter, text): - if not isinstance(text , basestring): + if not isinstance(text , _basestring): raise TypeError('text must be a string, not %s' % type(text)) length = len(text) Gtk.TextBuffer.insert(self, iter, text, length) def insert_at_cursor(self, text): - if not isinstance(text , basestring): + if not isinstance(text , _basestring): raise TypeError('text must be a string, not %s' % type(text)) length = len(text) @@ -382,7 +396,7 @@ class TreeStore(Gtk.TreeStore, TreeModel): if len(row) != n_columns: raise ValueError('row sequence has the incorrect number of elements') - for i in xrange(n_columns): + for i in range(n_columns): if row[i] is not None: self.set_value(treeiter, i, row[i]) @@ -399,12 +413,25 @@ class TreeViewColumn(Gtk.TreeViewColumn): if cell_renderer: self.pack_start(cell_renderer, True) - for (name, value) in attributes.iteritems(): + for (name, value) in attributes.items(): self.add_attribute(cell_renderer, name, value) TreeViewColumn = override(TreeViewColumn) __all__.append('TreeViewColumn') +class Button(Gtk.Button): + def __init__(self, label=None, stock=None, use_underline=False): + if stock: + label = stock + use_stock = True + use_underline = True + else: + use_stock = False + Gtk.Button.__init__(self, label=label, use_stock=use_stock, + use_underline=use_underline) +Button = override(Button) +__all__.append('Button') + import sys initialized, argv = Gtk.init_check(sys.argv) diff --git a/gi/overrides/Makefile.am b/gi/overrides/Makefile.am index 62f6457..b36c7a5 100644 --- a/gi/overrides/Makefile.am +++ b/gi/overrides/Makefile.am @@ -4,6 +4,7 @@ pkgpyexecdir = $(pyexecdir)/gtk-2.0/gi pygioverridesdir = $(pkgpyexecdir)/overrides pygioverrides_PYTHON = \ + GLib.py \ Gtk.py \ Gdk.py \ GIMarshallingTests.py \ diff --git a/gi/overrides/Makefile.in b/gi/overrides/Makefile.in index b0a8c01..630735c 100644 --- a/gi/overrides/Makefile.in +++ b/gi/overrides/Makefile.in @@ -115,6 +115,7 @@ GIOUNIX_LIBS = @GIOUNIX_LIBS@ GIO_CFLAGS = @GIO_CFLAGS@ GIO_LIBS = @GIO_LIBS@ GI_CFLAGS = @GI_CFLAGS@ +GI_DATADIR = @GI_DATADIR@ GI_LIBS = @GI_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ @@ -237,6 +238,7 @@ top_srcdir = @top_srcdir@ PLATFORM_VERSION = 2.0 pygioverridesdir = $(pkgpyexecdir)/overrides pygioverrides_PYTHON = \ + GLib.py \ Gtk.py \ Gdk.py \ GIMarshallingTests.py \ diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index 9ace5d2..e3dd8c3 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -3,7 +3,7 @@ * * Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org> * - * pygi-argument.c: GArgument - PyObject conversion functions. + * pygi-argument.c: GIArgument - PyObject conversion functions. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ #include <datetime.h> #include <pygobject.h> - +#include <pyglib-python-compat.h> static void _pygi_g_type_tag_py_bounds (GITypeTag type_tag, @@ -37,29 +37,29 @@ _pygi_g_type_tag_py_bounds (GITypeTag type_tag, { switch (type_tag) { case GI_TYPE_TAG_INT8: - *lower = PyInt_FromLong (-128); - *upper = PyInt_FromLong (127); + *lower = PYGLIB_PyLong_FromLong (-128); + *upper = PYGLIB_PyLong_FromLong (127); break; case GI_TYPE_TAG_UINT8: - *upper = PyInt_FromLong (255); - *lower = PyInt_FromLong (0); + *upper = PYGLIB_PyLong_FromLong (255); + *lower = PYGLIB_PyLong_FromLong (0); break; case GI_TYPE_TAG_INT16: - *lower = PyInt_FromLong (-32768); - *upper = PyInt_FromLong (32767); + *lower = PYGLIB_PyLong_FromLong (-32768); + *upper = PYGLIB_PyLong_FromLong (32767); break; case GI_TYPE_TAG_UINT16: - *upper = PyInt_FromLong (65535); - *lower = PyInt_FromLong (0); + *upper = PYGLIB_PyLong_FromLong (65535); + *lower = PYGLIB_PyLong_FromLong (0); break; case GI_TYPE_TAG_INT32: - *lower = PyInt_FromLong (G_MININT32); - *upper = PyInt_FromLong (G_MAXINT32); + *lower = PYGLIB_PyLong_FromLong (G_MININT32); + *upper = PYGLIB_PyLong_FromLong (G_MAXINT32); break; case GI_TYPE_TAG_UINT32: /* Note: On 32-bit archs, this number doesn't fit in a long. */ *upper = PyLong_FromLongLong (G_MAXUINT32); - *lower = PyInt_FromLong (0); + *lower = PYGLIB_PyLong_FromLong (0); break; case GI_TYPE_TAG_INT64: /* Note: On 32-bit archs, these numbers don't fit in a long. */ @@ -68,7 +68,7 @@ _pygi_g_type_tag_py_bounds (GITypeTag type_tag, break; case GI_TYPE_TAG_UINT64: *upper = PyLong_FromUnsignedLongLong (G_MAXUINT64); - *lower = PyInt_FromLong (0); + *lower = PYGLIB_PyLong_FromLong (0); break; case GI_TYPE_TAG_FLOAT: *upper = PyFloat_FromDouble (G_MAXFLOAT); @@ -161,6 +161,101 @@ _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, } gint +_pygi_g_type_interface_check_object (GIBaseInfo *info, + PyObject *object) +{ + gint retval = 1; + GIInfoType info_type; + + info_type = g_base_info_get_type (info); + switch (info_type) { + case GI_INFO_TYPE_CALLBACK: + if (!PyCallable_Check (object)) { + PyErr_Format (PyExc_TypeError, "Must be callable, not %s", + object->ob_type->tp_name); + retval = 0; + } + break; + case GI_INFO_TYPE_ENUM: + retval = 0; + if (PyNumber_Check (object)) { + PyObject *number = PYGLIB_PyNumber_Long (object); + if (number == NULL) + PyErr_Clear(); + else { + glong value = PYGLIB_PyLong_AsLong (number); + int i; + for (i = 0; i < g_enum_info_get_n_values (info); i++) { + GIValueInfo *value_info = g_enum_info_get_value (info, i); + glong enum_value = g_value_info_get_value (value_info); + if (value == enum_value) { + retval = 1; + break; + } + } + } + } + if (retval < 1) + retval = _pygi_g_registered_type_info_check_object ( + (GIRegisteredTypeInfo *) info, TRUE, object); + break; + case GI_INFO_TYPE_FLAGS: + if (PyNumber_Check (object)) { + /* Accept 0 as a valid flag value */ + PyObject *number = PYGLIB_PyNumber_Long (object); + if (number == NULL) + PyErr_Clear(); + else { + long value = PYGLIB_PyLong_AsLong (number); + if (value == 0) + break; + else if (value == -1) + PyErr_Clear(); + } + } + retval = _pygi_g_registered_type_info_check_object ( + (GIRegisteredTypeInfo *) info, TRUE, object); + break; + case GI_INFO_TYPE_STRUCT: + { + GType type; + + /* Handle special cases. */ + type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); + if (g_type_is_a (type, G_TYPE_VALUE)) { + GType object_type; + object_type = pyg_type_from_object ( (PyObject *) object->ob_type); + if (object_type == G_TYPE_INVALID) { + PyErr_Format (PyExc_TypeError, "Must be of a known GType, not %s", + object->ob_type->tp_name); + retval = 0; + } + break; + } else if (g_type_is_a (type, G_TYPE_CLOSURE)) { + if (!PyCallable_Check (object)) { + PyErr_Format (PyExc_TypeError, "Must be callable, not %s", + object->ob_type->tp_name); + retval = 0; + } + break; + } + + /* Fallback. */ + } + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_INTERFACE: + case GI_INFO_TYPE_OBJECT: + case GI_INFO_TYPE_UNION: + retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object); + break; + default: + g_assert_not_reached(); + } + + return retval; +} + +gint _pygi_g_type_info_check_object (GITypeInfo *type_info, PyObject *object, gboolean allow_none) @@ -204,7 +299,7 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info, if (type_tag == GI_TYPE_TAG_FLOAT || type_tag == GI_TYPE_TAG_DOUBLE) { number = PyNumber_Float (object); } else { - number = PyNumber_Int (object); + number = PYGLIB_PyNumber_Long (object); } _pygi_g_type_tag_py_bounds (type_tag, &lower, &upper); @@ -215,8 +310,8 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info, } /* Check bounds */ - if (PyObject_Compare (lower, number) > 0 - || PyObject_Compare (upper, number) < 0) { + if (PyObject_RichCompareBool (lower, number, Py_GT) + || PyObject_RichCompareBool (upper, number, Py_LT)) { PyObject *lower_str; PyObject *upper_str; @@ -232,10 +327,30 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info, goto check_number_error_release; } +#if PY_VERSION_HEX < 0x03000000 PyErr_Format (PyExc_ValueError, "Must range from %s to %s", PyString_AS_STRING (lower_str), PyString_AS_STRING (upper_str)); +#else + { + PyObject *lower_pybytes_obj = PyUnicode_AsUTF8String (lower_str); + if (!lower_pybytes_obj) + goto utf8_fail; + + PyObject *upper_pybytes_obj = PyUnicode_AsUTF8String (upper_str); + if (!upper_pybytes_obj) { + Py_DECREF(lower_pybytes_obj); + goto utf8_fail; + } + PyErr_Format (PyExc_ValueError, "Must range from %s to %s", + PyBytes_AsString (lower_pybytes_obj), + PyBytes_AsString (upper_pybytes_obj)); + Py_DECREF (lower_pybytes_obj); + Py_DECREF (upper_pybytes_obj); + } +utf8_fail: +#endif retval = 0; check_number_error_release: @@ -251,15 +366,7 @@ check_number_release: } case GI_TYPE_TAG_GTYPE: { - gint is_instance; - - is_instance = PyObject_IsInstance (object, (PyObject *) &PyGTypeWrapper_Type); - if (is_instance < 0) { - retval = -1; - break; - } - - if (!is_instance && (!PyType_Check (object) || pyg_type_from_object (object) == 0)) { + if (pyg_type_from_object (object) == 0) { PyErr_Format (PyExc_TypeError, "Must be gobject.GType, not %s", object->ob_type->tp_name); retval = 0; @@ -268,7 +375,7 @@ check_number_release: } case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: - if (!PyString_Check (object)) { + if (!PYGLIB_PyUnicode_Check (object)) { PyErr_Format (PyExc_TypeError, "Must be string, not %s", object->ob_type->tp_name); retval = 0; @@ -334,77 +441,11 @@ check_number_release: case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; - GIInfoType info_type; info = g_type_info_get_interface (type_info); g_assert (info != NULL); - info_type = g_base_info_get_type (info); - - switch (info_type) { - case GI_INFO_TYPE_CALLBACK: - if (!PyCallable_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be callable, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - case GI_INFO_TYPE_ENUM: - retval = _pygi_g_registered_type_info_check_object ( - (GIRegisteredTypeInfo *) info, TRUE, object); - break; - case GI_INFO_TYPE_FLAGS: - if (PyNumber_Check (object)) { - /* Accept 0 as a valid flag value */ - PyObject *number = PyNumber_Int (object); - if (number == NULL) - PyErr_Clear(); - else { - long value = PyInt_AsLong (number); - if (value == 0) - break; - else if (value == -1) - PyErr_Clear(); - } - } - retval = _pygi_g_registered_type_info_check_object ( - (GIRegisteredTypeInfo *) info, TRUE, object); - break; - case GI_INFO_TYPE_STRUCT: - { - GType type; - - /* Handle special cases. */ - type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); - if (g_type_is_a (type, G_TYPE_VALUE)) { - GType object_type; - object_type = pyg_type_from_object ( (PyObject *) object->ob_type); - if (object_type == G_TYPE_INVALID) { - PyErr_Format (PyExc_TypeError, "Must be of a known GType, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - } else if (g_type_is_a (type, G_TYPE_CLOSURE)) { - if (!PyCallable_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be callable, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - } - - /* Fallback. */ - } - case GI_INFO_TYPE_BOXED: - case GI_INFO_TYPE_INTERFACE: - case GI_INFO_TYPE_OBJECT: - case GI_INFO_TYPE_UNION: - retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object); - break; - default: - g_assert_not_reached(); - } + retval = _pygi_g_type_interface_check_object(info, object); g_base_info_unref (info); break; @@ -466,7 +507,8 @@ check_number_release: GITypeInfo *value_type_info; Py_ssize_t i; - if (!PyMapping_Check (object)) { + keys = PyMapping_Keys (object); + if (keys == NULL) { PyErr_Format (PyExc_TypeError, "Must be mapping, not %s", object->ob_type->tp_name); retval = 0; @@ -475,12 +517,7 @@ check_number_release: length = PyMapping_Length (object); if (length < 0) { - retval = -1; - break; - } - - keys = PyMapping_Keys (object); - if (keys == NULL) { + Py_DECREF (keys); retval = -1; break; } @@ -540,8 +577,8 @@ check_number_release: } GArray * -_pygi_argument_to_array (GArgument *arg, - GArgument *args[], +_pygi_argument_to_array (GIArgument *arg, + GIArgument *args[], GITypeInfo *type_info, gboolean is_method) { @@ -572,12 +609,6 @@ _pygi_argument_to_array (GArgument *arg, length_arg_pos = g_type_info_get_array_length (type_info); g_assert (length_arg_pos >= 0); - if (is_method) { - length_arg_pos--; - } - - g_assert (length_arg_pos >= 0); - /* FIXME: Take into account the type of the argument. */ length = args[length_arg_pos]->v_int; } @@ -593,15 +624,15 @@ _pygi_argument_to_array (GArgument *arg, return g_array; } -GArgument +GIArgument _pygi_argument_from_object (PyObject *object, GITypeInfo *type_info, GITransfer transfer) { - GArgument arg; + GIArgument arg; GITypeTag type_tag; - memset(&arg, 0, sizeof(GArgument)); + memset(&arg, 0, sizeof(GIArgument)); type_tag = g_type_info_get_tag (type_info); switch (type_tag) { @@ -622,12 +653,12 @@ _pygi_argument_from_object (PyObject *object, { PyObject *int_; - int_ = PyNumber_Int (object); + int_ = PYGLIB_PyNumber_Long (object); if (int_ == NULL) { break; } - arg.v_long = PyInt_AsLong (int_); + arg.v_long = PYGLIB_PyLong_AsLong (int_); Py_DECREF (int_); @@ -639,16 +670,18 @@ _pygi_argument_from_object (PyObject *object, PyObject *number; guint64 value; - number = PyNumber_Int (object); + number = PYGLIB_PyNumber_Long (object); if (number == NULL) { break; } +#if PY_VERSION_HEX < 0x03000000 if (PyInt_Check (number)) { value = PyInt_AS_LONG (number); - } else { + } else +#endif + if (PyLong_Check (number)) value = PyLong_AsUnsignedLongLong (number); - } arg.v_uint64 = value; @@ -661,16 +694,18 @@ _pygi_argument_from_object (PyObject *object, PyObject *number; gint64 value; - number = PyNumber_Int (object); + number = PYGLIB_PyNumber_Long (object); if (number == NULL) { break; } +#if PY_VERSION_HEX < 0x03000000 if (PyInt_Check (number)) { value = PyInt_AS_LONG (number); - } else { + } else +#endif + if (PyLong_Check (number)) value = PyLong_AsLongLong (number); - } arg.v_int64 = value; @@ -714,30 +749,53 @@ _pygi_argument_from_object (PyObject *object, } case GI_TYPE_TAG_UTF8: { - const gchar *string; + gchar *string; if (object == Py_None) { arg.v_string = NULL; break; } +#if PY_VERSION_HEX < 0x03000000 + string = g_strdup(PyString_AsString (object)); +#else + { + PyObject *pybytes_obj = PyUnicode_AsUTF8String (object); + if (!pybytes_obj) + break; - string = PyString_AsString (object); + string = g_strdup(PyBytes_AsString (pybytes_obj)); + Py_DECREF (pybytes_obj); + } +#endif + arg.v_string = string; - /* Don't need to check for errors, since g_strdup is NULL-proof. */ - arg.v_string = g_strdup (string); break; } case GI_TYPE_TAG_FILENAME: { GError *error = NULL; - const gchar *string; + gchar *string; + +#if PY_VERSION_HEX < 0x03000000 + string = g_strdup(PyString_AsString (object)); +#else + { + PyObject *pybytes_obj = PyUnicode_AsUTF8String (object); + if (!pybytes_obj) + break; + + string = g_strdup(PyBytes_AsString (pybytes_obj)); + Py_DECREF (pybytes_obj); + } +#endif - string = PyString_AsString (object); if (string == NULL) { break; } arg.v_string = g_filename_from_utf8 (string, -1, NULL, NULL, &error); + g_free(string); + if (arg.v_string == NULL) { PyErr_SetString (PyExc_Exception, error->message); /* TODO: Convert the error to an exception. */ @@ -781,7 +839,7 @@ _pygi_argument_from_object (PyObject *object, for (i = 0; i < length; i++) { PyObject *py_item; - GArgument item; + GIArgument item; py_item = PySequence_GetItem (object, i); if (py_item == NULL) { @@ -801,7 +859,7 @@ _pygi_argument_from_object (PyObject *object, array_item_error: /* Free everything we have converted so far. */ - _pygi_argument_release ( (GArgument *) &array, type_info, + _pygi_argument_release ( (GIArgument *) &array, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); array = NULL; @@ -900,12 +958,12 @@ array_item_error: { PyObject *int_; - int_ = PyNumber_Int (object); + int_ = PYGLIB_PyNumber_Long (object); if (int_ == NULL) { break; } - arg.v_long = PyInt_AsLong (int_); + arg.v_long = PYGLIB_PyLong_AsLong (int_); Py_DECREF (int_); @@ -956,7 +1014,7 @@ array_item_error: for (i = length - 1; i >= 0; i--) { PyObject *py_item; - GArgument item; + GIArgument item; py_item = PySequence_GetItem (object, i); if (py_item == NULL) { @@ -981,7 +1039,7 @@ array_item_error: list_item_error: /* Free everything we have converted so far. */ - _pygi_argument_release ( (GArgument *) &list, type_info, + _pygi_argument_release ( (GIArgument *) &list, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); list = NULL; @@ -1061,8 +1119,8 @@ list_item_error: for (i = 0; i < length; i++) { PyObject *py_key; PyObject *py_value; - GArgument key; - GArgument value; + GIArgument key; + GIArgument value; py_key = PyList_GET_ITEM (keys, i); py_value = PyList_GET_ITEM (values, i); @@ -1083,7 +1141,7 @@ list_item_error: hash_table_item_error: /* Free everything we have converted so far. */ - _pygi_argument_release ( (GArgument *) &hash_table, type_info, + _pygi_argument_release ( (GIArgument *) &hash_table, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); hash_table = NULL; @@ -1110,7 +1168,7 @@ hash_table_release: } PyObject * -_pygi_argument_to_object (GArgument *arg, +_pygi_argument_to_object (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer) { @@ -1135,27 +1193,27 @@ _pygi_argument_to_object (GArgument *arg, } case GI_TYPE_TAG_INT8: { - object = PyInt_FromLong (arg->v_int8); + object = PYGLIB_PyLong_FromLong (arg->v_int8); break; } case GI_TYPE_TAG_UINT8: { - object = PyInt_FromLong (arg->v_uint8); + object = PYGLIB_PyLong_FromLong (arg->v_uint8); break; } case GI_TYPE_TAG_INT16: { - object = PyInt_FromLong (arg->v_int16); + object = PYGLIB_PyLong_FromLong (arg->v_int16); break; } case GI_TYPE_TAG_UINT16: { - object = PyInt_FromLong (arg->v_uint16); + object = PYGLIB_PyLong_FromLong (arg->v_uint16); break; } case GI_TYPE_TAG_INT32: { - object = PyInt_FromLong (arg->v_int32); + object = PYGLIB_PyLong_FromLong (arg->v_int32); break; } case GI_TYPE_TAG_UINT32: @@ -1195,7 +1253,7 @@ _pygi_argument_to_object (GArgument *arg, break; } - object = PyString_FromString (arg->v_string); + object = PYGLIB_PyUnicode_FromString (arg->v_string); break; case GI_TYPE_TAG_FILENAME: { @@ -1215,7 +1273,7 @@ _pygi_argument_to_object (GArgument *arg, break; } - object = PyString_FromString (string); + object = PYGLIB_PyUnicode_FromString (string); g_free (string); @@ -1249,7 +1307,7 @@ _pygi_argument_to_object (GArgument *arg, item_size = g_array_get_element_size (array); for (i = 0; i < array->len; i++) { - GArgument item; + GIArgument item; PyObject *py_item; gboolean is_struct = FALSE; @@ -1266,9 +1324,9 @@ _pygi_argument_to_object (GArgument *arg, } if (is_struct) { - item.v_pointer = &_g_array_index (array, GArgument, i); + item.v_pointer = &_g_array_index (array, GIArgument, i); } else { - memcpy (&item, &_g_array_index (array, GArgument, i), item_size); + memcpy (&item, &_g_array_index (array, GIArgument, i), item_size); } py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer); @@ -1355,15 +1413,12 @@ _pygi_argument_to_object (GArgument *arg, break; } - if (transfer != GI_TRANSFER_NOTHING) - g_warning ("Transfer mode should be set to None for " - "struct types as there is no way to free " - "them safely. Ignoring transfer mode " - "to prevent a potential invalid free. " - "This may cause a leak in your application."); - + /* Only structs created in invoke can be safely marked + * GI_TRANSFER_EVERYTHING. Trust that invoke has + * filtered correctly + */ object = _pygi_struct_new ( (PyTypeObject *) py_type, arg->v_pointer, - FALSE); + transfer == GI_TRANSFER_EVERYTHING); Py_DECREF (py_type); } else { @@ -1446,7 +1501,7 @@ _pygi_argument_to_object (GArgument *arg, item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; for (i = 0; list != NULL; list = g_slist_next (list), i++) { - GArgument item; + GIArgument item; PyObject *py_item; item.v_pointer = list->data; @@ -1470,8 +1525,8 @@ _pygi_argument_to_object (GArgument *arg, GITypeInfo *value_type_info; GITransfer item_transfer; GHashTableIter hash_table_iter; - GArgument key; - GArgument value; + GIArgument key; + GIArgument value; if (arg->v_pointer == NULL) { object = Py_None; @@ -1486,9 +1541,11 @@ _pygi_argument_to_object (GArgument *arg, key_type_info = g_type_info_get_param_type (type_info, 0); g_assert (key_type_info != NULL); + g_assert (g_type_info_get_tag (key_type_info) != GI_TYPE_TAG_VOID); value_type_info = g_type_info_get_param_type (type_info, 1); g_assert (value_type_info != NULL); + g_assert (g_type_info_get_tag (value_type_info) != GI_TYPE_TAG_VOID); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; @@ -1533,12 +1590,13 @@ _pygi_argument_to_object (GArgument *arg, } void -_pygi_argument_release (GArgument *arg, +_pygi_argument_release (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer, GIDirection direction) { GITypeTag type_tag; + gboolean is_out = (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT); type_tag = g_type_info_get_tag (type_info); @@ -1590,8 +1648,8 @@ _pygi_argument_release (GArgument *arg, /* Free the items */ for (i = 0; i < array->len; i++) { - GArgument *item; - item = &_g_array_index (array, GArgument, i); + GIArgument *item; + item = &_g_array_index (array, GIArgument, i); _pygi_argument_release (item, item_type_info, item_transfer, direction); } @@ -1649,7 +1707,7 @@ _pygi_argument_release (GArgument *arg, } } else if (g_struct_info_is_foreign ( (GIStructInfo*) info)) { if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) { - pygi_struct_foreign_release_g_argument (transfer, type_info, arg); + pygi_struct_foreign_release (info, arg->v_pointer); } } else if (g_type_is_a (type, G_TYPE_BOXED)) { } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) { @@ -1666,7 +1724,7 @@ _pygi_argument_release (GArgument *arg, if (arg->v_pointer == NULL) { return; } - if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) { + if (is_out && transfer == GI_TRANSFER_EVERYTHING) { g_object_unref (arg->v_pointer); } break; @@ -1701,7 +1759,7 @@ _pygi_argument_release (GArgument *arg, /* Free the items */ for (item = list; item != NULL; item = g_slist_next (item)) { - _pygi_argument_release ( (GArgument *) &item->data, item_type_info, + _pygi_argument_release ( (GIArgument *) &item->data, item_type_info, item_transfer, direction); } @@ -1754,9 +1812,9 @@ _pygi_argument_release (GArgument *arg, g_hash_table_iter_init (&hash_table_iter, hash_table); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { - _pygi_argument_release ( (GArgument *) &key, key_type_info, + _pygi_argument_release ( (GIArgument *) &key, key_type_info, item_transfer, direction); - _pygi_argument_release ( (GArgument *) &value, value_type_info, + _pygi_argument_release ( (GIArgument *) &value, value_type_info, item_transfer, direction); } diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h index 821737a..d932e8f 100644 --- a/gi/pygi-argument.h +++ b/gi/pygi-argument.h @@ -30,6 +30,8 @@ G_BEGIN_DECLS /* Private */ +gint _pygi_g_type_interface_check_object (GIBaseInfo *info, + PyObject *object); gint _pygi_g_type_info_check_object (GITypeInfo *type_info, PyObject *object, @@ -40,21 +42,21 @@ gint _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, PyObject *object); -GArray* _pygi_argument_to_array (GArgument *arg, - GArgument *args[], +GArray* _pygi_argument_to_array (GIArgument *arg, + GIArgument *args[], GITypeInfo *type_info, gboolean is_method); -GArgument _pygi_argument_from_object (PyObject *object, +GIArgument _pygi_argument_from_object (PyObject *object, GITypeInfo *type_info, GITransfer transfer); -PyObject* _pygi_argument_to_object (GArgument *arg, +PyObject* _pygi_argument_to_object (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer); -void _pygi_argument_release (GArgument *arg, +void _pygi_argument_release (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer, GIDirection direction); diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c index 4903834..2fd446c 100644 --- a/gi/pygi-boxed.c +++ b/gi/pygi-boxed.c @@ -25,6 +25,7 @@ #include <pygobject.h> #include <girepository.h> +#include <pyglib-python-compat.h> static void _boxed_dealloc (PyGIBoxed *self) @@ -44,7 +45,38 @@ _boxed_dealloc (PyGIBoxed *self) } } - ( (PyGObject *) self)->ob_type->tp_free ( (PyObject *) self); + Py_TYPE( (PyGObject *) self)->tp_free ( (PyObject *) self); +} + +void * +_pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out) +{ + gsize size; + + /* FIXME: Remove when bgo#622711 is fixed */ + if (g_registered_type_info_get_g_type (info) == G_TYPE_VALUE) { + size = sizeof (GValue); + } else { + switch (g_base_info_get_type (info)) { + case GI_INFO_TYPE_UNION: + size = g_union_info_get_size ( (GIUnionInfo *) info); + break; + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_STRUCT: + size = g_struct_info_get_size ( (GIStructInfo *) info); + break; + default: + PyErr_Format (PyExc_TypeError, + "info should be Boxed or Union, not '%d'", + g_base_info_get_type (info)); + return NULL; + } + } + + if( size_out != NULL) + *size_out = size; + + return g_slice_alloc0 (size); } static PyObject * @@ -55,7 +87,7 @@ _boxed_new (PyTypeObject *type, static char *kwlist[] = { NULL }; GIBaseInfo *info; - gsize size; + gsize size = 0; gpointer boxed; PyGIBoxed *self = NULL; @@ -71,22 +103,7 @@ _boxed_new (PyTypeObject *type, return NULL; } - switch (g_base_info_get_type (info)) { - case GI_INFO_TYPE_UNION: - size = g_union_info_get_size ( (GIUnionInfo *) info); - break; - case GI_INFO_TYPE_BOXED: - case GI_INFO_TYPE_STRUCT: - size = g_struct_info_get_size ( (GIStructInfo *) info); - break; - default: - PyErr_Format (PyExc_TypeError, - "info should be Boxed or Union, not '%d'", - g_base_info_get_type (info)); - return NULL; - } - - boxed = g_slice_alloc0 (size); + boxed = _pygi_boxed_alloc (info, &size); if (boxed == NULL) { PyErr_NoMemory(); goto out; @@ -116,41 +133,7 @@ _boxed_init (PyObject *self, return 0; } - -PyTypeObject PyGIBoxed_Type = { - PyObject_HEAD_INIT (NULL) - 0, - "gi.Boxed", /* tp_name */ - sizeof (PyGIBoxed), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) _boxed_dealloc, /* tp_dealloc */ - (printfunc) NULL, /* tp_print */ - (getattrfunc) NULL, /* tp_getattr */ - (setattrfunc) NULL, /* tp_setattr */ - (cmpfunc) NULL, /* tp_compare */ - (reprfunc) NULL, /* tp_repr */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - (hashfunc) NULL, /* tp_hash */ - (ternaryfunc) NULL, /* tp_call */ - (reprfunc) NULL, /* tp_str */ - (getattrofunc) NULL, /* tp_getattro */ - (setattrofunc) NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - NULL, /* tp_doc */ - (traverseproc) NULL, /* tp_traverse */ - (inquiry) NULL, /* tp_clear */ - (richcmpfunc) NULL, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc) NULL, /* tp_iter */ - (iternextfunc) NULL, /* tp_iternext */ - NULL, /* tp_methods */ - NULL, /* tp_members */ - NULL, /* tp_getset */ - (PyTypeObject *) NULL, /* tp_base */ -}; +PYGLIB_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed); PyObject * _pygi_boxed_new (PyTypeObject *type, @@ -185,10 +168,13 @@ _pygi_boxed_new (PyTypeObject *type, void _pygi_boxed_register_types (PyObject *m) { - PyGIBoxed_Type.ob_type = &PyType_Type; + Py_TYPE(&PyGIBoxed_Type) = &PyType_Type; PyGIBoxed_Type.tp_base = &PyGBoxed_Type; PyGIBoxed_Type.tp_new = (newfunc) _boxed_new; PyGIBoxed_Type.tp_init = (initproc) _boxed_init; + PyGIBoxed_Type.tp_dealloc = (destructor) _boxed_dealloc; + PyGIBoxed_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); + if (PyType_Ready (&PyGIBoxed_Type)) return; if (PyModule_AddObject (m, "Boxed", (PyObject *) &PyGIBoxed_Type)) diff --git a/gi/pygi-boxed.h b/gi/pygi-boxed.h index 4f84060..a84ec4e 100644 --- a/gi/pygi-boxed.h +++ b/gi/pygi-boxed.h @@ -28,10 +28,12 @@ G_BEGIN_DECLS extern PyTypeObject PyGIBoxed_Type; -PyObject * -_pygi_boxed_new (PyTypeObject *type, - gpointer boxed, - gboolean free_on_dealloc); +PyObject * _pygi_boxed_new (PyTypeObject *type, + gpointer boxed, + gboolean free_on_dealloc); + +void * _pygi_boxed_alloc (GIBaseInfo *info, + gsize *size); void _pygi_boxed_register_types (PyObject *m); diff --git a/gi/pygi-callbacks.c b/gi/pygi-callbacks.c index 6fdc1ce..bae4001 100644 --- a/gi/pygi-callbacks.c +++ b/gi/pygi-callbacks.c @@ -95,7 +95,8 @@ _pygi_scan_for_callbacks (GIFunctionInfo *function_info, interface_type = g_base_info_get_type (interface_info); if (interface_type == GI_INFO_TYPE_CALLBACK && ! (strcmp (g_base_info_get_namespace ( (GIBaseInfo*) interface_info), "GLib") == 0 && - strcmp (g_base_info_get_name ( (GIBaseInfo*) interface_info), "DestroyNotify") == 0)) { + (strcmp (g_base_info_get_name ( (GIBaseInfo*) interface_info), "DestroyNotify") == 0 || + (strcmp (g_base_info_get_name ( (GIBaseInfo*) interface_info), "FreeFunc") == 0)))) { if (*callback_index != G_MAXUINT8) { PyErr_Format (PyExc_TypeError, "Function %s.%s has multiple callbacks, not supported", g_base_info_get_namespace ( (GIBaseInfo*) function_info), @@ -108,11 +109,8 @@ _pygi_scan_for_callbacks (GIFunctionInfo *function_info, g_base_info_unref (interface_info); } destroy = g_arg_info_get_destroy (arg_info); - if (is_method) - --destroy; + closure = g_arg_info_get_closure (arg_info); - if (is_method) - --closure; direction = g_arg_info_get_direction (arg_info); if (destroy > 0 && destroy < n_args) { @@ -200,7 +198,8 @@ _pygi_create_callback (GIBaseInfo *function_info, if (!found_py_function || (py_function == Py_None || !PyCallable_Check (py_function))) { - PyErr_Format (PyExc_TypeError, "Error invoking %s.%s: Invalid callback given for argument %s", + PyErr_Format (PyExc_TypeError, "Error invoking %s.%s: Unexpected value " + "for argument '%s'", g_base_info_get_namespace ( (GIBaseInfo*) function_info), g_base_info_get_name ( (GIBaseInfo*) function_info), g_base_info_get_name ( (GIBaseInfo*) callback_arg)); diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c index b26d5b1..1e2ce05 100644 --- a/gi/pygi-closure.c +++ b/gi/pygi-closure.c @@ -28,7 +28,7 @@ static GSList* async_free_list; -static GArgument * +static GIArgument * _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) { gint num_args, i; @@ -36,10 +36,10 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) GITypeInfo *arg_type; GITypeTag tag; GIDirection direction; - GArgument *g_args; + GIArgument *g_args; num_args = g_callable_info_get_n_args (callable_info); - g_args = g_new0 (GArgument, num_args); + g_args = g_new0 (GIArgument, num_args); for (i = 0; i < num_args; i++) { arg_info = g_callable_info_get_arg (callable_info, i); @@ -130,13 +130,13 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) static gboolean _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, void *user_data, PyObject **py_args, - GArgument **out_args) + GIArgument **out_args) { int n_args = g_callable_info_get_n_args (callable_info); int n_in_args = 0; int n_out_args = 0; int i; - GArgument *g_args = NULL; + GIArgument *g_args = NULL; *py_args = NULL; *py_args = PyTuple_New (n_args); @@ -144,7 +144,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, goto error; *out_args = NULL; - *out_args = g_new0 (GArgument, n_args); + *out_args = g_new0 (GIArgument, n_args); g_args = _pygi_closure_convert_ffi_arguments (callable_info, args); for (i = 0; i < n_args; i++) { @@ -156,7 +156,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, GITypeTag arg_tag = g_type_info_get_tag (arg_type); GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); PyObject *value; - GArgument *arg; + GIArgument *arg; if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID && g_type_info_is_pointer (arg_type)) { @@ -170,9 +170,9 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, } } else { if (direction == GI_DIRECTION_IN) - arg = (GArgument*) &g_args[i]; + arg = (GIArgument*) &g_args[i]; else - arg = (GArgument*) g_args[i].v_pointer; + arg = (GIArgument*) g_args[i].v_pointer; value = _pygi_argument_to_object (arg, arg_type, transfer); if (value == NULL) { @@ -214,7 +214,7 @@ error: static void _pygi_closure_set_out_arguments (GICallableInfo *callable_info, - PyObject *py_retval, GArgument *out_args, + PyObject *py_retval, GIArgument *out_args, void *resp) { int n_args, i, i_py_retval, i_out_args; @@ -225,15 +225,15 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info, return_type_info = g_callable_info_get_return_type (callable_info); return_type_tag = g_type_info_get_tag (return_type_info); if (return_type_tag != GI_TYPE_TAG_VOID) { - GArgument arg; + GIArgument arg; GITransfer transfer = g_callable_info_get_caller_owns (callable_info); if (PyTuple_Check (py_retval)) { PyObject *item = PyTuple_GET_ITEM (py_retval, 0); arg = _pygi_argument_from_object (item, return_type_info, transfer); - * ( (GArgument*) resp) = arg; + * ( (GIArgument*) resp) = arg; } else { arg = _pygi_argument_from_object (py_retval, return_type_info, transfer); - * ( (GArgument*) resp) = arg; + * ( (GIArgument*) resp) = arg; } i_py_retval++; } @@ -248,14 +248,14 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info, if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); - GArgument arg; + GIArgument arg; if (PyTuple_Check (py_retval)) { PyObject *item = PyTuple_GET_ITEM (py_retval, i_py_retval); arg = _pygi_argument_from_object (item, type_info, transfer); - * ( (GArgument*) out_args[i_out_args].v_pointer) = arg; + * ( (GIArgument*) out_args[i_out_args].v_pointer) = arg; } else if (i_py_retval == 0) { arg = _pygi_argument_from_object (py_retval, type_info, transfer); - * ( (GArgument*) out_args[i_out_args].v_pointer) = arg; + * ( (GIArgument*) out_args[i_out_args].v_pointer) = arg; } else g_assert_not_reached(); @@ -280,7 +280,7 @@ _pygi_closure_handle (ffi_cif *cif, GITypeInfo *return_type; PyObject *retval; PyObject *py_args; - GArgument *out_args = NULL; + GIArgument *out_args = NULL; /* Lock the GIL as we are coming into this code without the lock and we may be executing python code */ diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c index 08d50ad..095f6cb 100644 --- a/gi/pygi-foreign-cairo.c +++ b/gi/pygi-foreign-cairo.c @@ -22,16 +22,24 @@ */ #include <cairo.h> + +#if PY_VERSION_HEX < 0x03000000 #include <pycairo.h> +#else +#include <pycairo/py3cairo.h> +#endif + Pycairo_CAPI_t *Pycairo_CAPI; #include "pygi-foreign.h" +#include <pyglib-python-compat.h> + PyObject * cairo_context_to_arg (PyObject *value, GITypeInfo *type_info, GITransfer transfer, - GArgument *arg) + GIArgument *arg) { cairo_t *cr; @@ -47,7 +55,7 @@ cairo_context_to_arg (PyObject *value, } PyObject * -cairo_context_from_arg (GITypeInfo *type_info, GArgument *arg) +cairo_context_from_arg (GITypeInfo *type_info, GIArgument *arg) { cairo_t *context = (cairo_t*) arg; @@ -57,10 +65,10 @@ cairo_context_from_arg (GITypeInfo *type_info, GArgument *arg) } PyObject * -cairo_context_release_arg (GITransfer transfer, GITypeInfo *type_info, - GArgument *arg) +cairo_context_release (GIBaseInfo *base_info, + gpointer struct_) { - cairo_destroy ( (cairo_t*) arg->v_pointer); + cairo_destroy ( (cairo_t*) struct_); Py_RETURN_NONE; } @@ -69,7 +77,7 @@ PyObject * cairo_surface_to_arg (PyObject *value, GITypeInfo *type_info, GITransfer transfer, - GArgument *arg) + GIArgument *arg) { cairo_surface_t *surface; @@ -86,7 +94,7 @@ cairo_surface_to_arg (PyObject *value, } PyObject * -cairo_surface_from_arg (GITypeInfo *type_info, GArgument *arg) +cairo_surface_from_arg (GITypeInfo *type_info, GIArgument *arg) { cairo_surface_t *surface = (cairo_surface_t*) arg; @@ -96,36 +104,31 @@ cairo_surface_from_arg (GITypeInfo *type_info, GArgument *arg) } PyObject * -cairo_surface_release_arg (GITransfer transfer, GITypeInfo *type_info, - GArgument *arg) +cairo_surface_release (GIBaseInfo *base_info, + gpointer struct_) { - cairo_surface_destroy ( (cairo_surface_t*) arg->v_pointer); + cairo_surface_destroy ( (cairo_surface_t*) struct_); Py_RETURN_NONE; } -PyMODINIT_FUNC -init_gi_cairo (void) -{ - PyObject *m; - - m = Py_InitModule ("_gi_cairo", NULL); - if (m == NULL) { - return; - } +static PyMethodDef _gi_cairo_functions[] = {}; +PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo") +{ Pycairo_IMPORT; if (Pycairo_CAPI == NULL) - return; + return 0; pygi_register_foreign_struct ("cairo", "Context", cairo_context_to_arg, cairo_context_from_arg, - cairo_context_release_arg); + cairo_context_release); pygi_register_foreign_struct ("cairo", "Surface", cairo_surface_to_arg, cairo_surface_from_arg, - cairo_surface_release_arg); + cairo_surface_release); } +PYGLIB_MODULE_END; diff --git a/gi/pygi-foreign-gvariant.c b/gi/pygi-foreign-gvariant.c new file mode 100644 index 0000000..ac16395 --- /dev/null +++ b/gi/pygi-foreign-gvariant.c @@ -0,0 +1,63 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* + * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "pygobject.h" + +#include "pygi-private.h" +#include "pygi-foreign-gvariant.h" + +PyObject * +g_variant_to_arg (PyObject *value, + GITypeInfo *type_info, + GITransfer transfer, + GIArgument *arg) +{ + g_assert (transfer == GI_TRANSFER_NOTHING); + + /* TODO check that value is a PyGPointer */ + + arg->v_pointer = (GVariant *) ( (PyGPointer *) value)->pointer; + Py_RETURN_NONE; +} + +PyObject * +g_variant_from_arg (GITypeInfo *type_info, + GIArgument *arg) +{ + GVariant *variant = (GVariant *) arg; + GITypeInfo *interface_info = g_type_info_get_interface (type_info); + PyObject *type = _pygi_type_import_by_gi_info (interface_info); + + g_variant_ref_sink (variant); + + return _pygi_struct_new ( (PyTypeObject *) type, variant, FALSE); +} + +PyObject * +g_variant_release_foreign (GIBaseInfo *base_info, + gpointer struct_) +{ + g_variant_unref ( (GVariant *) struct_); + Py_RETURN_NONE; +} + diff --git a/gi/pygi-foreign-gvariant.h b/gi/pygi-foreign-gvariant.h new file mode 100644 index 0000000..6de8c57 --- /dev/null +++ b/gi/pygi-foreign-gvariant.h @@ -0,0 +1,41 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* + * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __PYGI_FOREIGN_G_VARIANT_H__ +#define __PYGI_FOREIGN_G_VARIANT_H__ + +#include "pygi-foreign.h" + +PyObject *g_variant_to_arg(PyObject *value, + GITypeInfo *type_info, + GITransfer transfer, + GIArgument *arg); + +PyObject *g_variant_from_arg(GITypeInfo *type_info, + GIArgument *arg); + +PyObject *g_variant_release_foreign (GIBaseInfo *base_info, + gpointer struct_); + +#endif /* __PYGI_FOREIGN_G_VARIANT_H__ */ + diff --git a/gi/pygi-foreign.c b/gi/pygi-foreign.c index 13a0f77..f80b43c 100644 --- a/gi/pygi-foreign.c +++ b/gi/pygi-foreign.c @@ -23,6 +23,7 @@ */ #include "pygi-foreign.h" +#include "pygi-foreign-gvariant.h" #include <config.h> #include <girepository.h> @@ -30,62 +31,87 @@ typedef struct { const char *namespace; const char *name; - PyGIArgOverrideToGArgumentFunc to_func; - PyGIArgOverrideFromGArgumentFunc from_func; - PyGIArgOverrideReleaseGArgumentFunc release_func; + PyGIArgOverrideToGIArgumentFunc to_func; + PyGIArgOverrideFromGIArgumentFunc from_func; + PyGIArgOverrideReleaseFunc release_func; } PyGIForeignStruct; static GPtrArray *foreign_structs = NULL; +void +init_foreign_structs () +{ + foreign_structs = g_ptr_array_new (); + + pygi_register_foreign_struct ("GLib", + "Variant", + g_variant_to_arg, + g_variant_from_arg, + g_variant_release_foreign); +} + static PyGIForeignStruct * -pygi_struct_foreign_lookup (GITypeInfo *type_info) +do_lookup (const gchar *namespace, const gchar *name) { gint i; - PyObject *module; - gchar *module_name; - GIBaseInfo *base_info; - const gchar *namespace; - const gchar *name; - - base_info = g_type_info_get_interface (type_info); - if (base_info == NULL) { - PyErr_Format (PyExc_ValueError, "Couldn't resolve the type of this foreign struct"); - return NULL; + for (i = 0; i < foreign_structs->len; i++) { + PyGIForeignStruct *foreign_struct = \ + g_ptr_array_index (foreign_structs, i); + + if ( (strcmp (namespace, foreign_struct->namespace) == 0) && + (strcmp (name, foreign_struct->name) == 0)) { + return foreign_struct; + } + } + return NULL; +} + +static PyGIForeignStruct * +pygi_struct_foreign_lookup (GIBaseInfo *base_info) +{ + 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 (); } - namespace = g_base_info_get_namespace (base_info); - name = g_base_info_get_name (base_info); + result = do_lookup (namespace, name); - module_name = g_strconcat ("gi._gi_", g_base_info_get_namespace (base_info), NULL); - module = PyImport_ImportModule (module_name); - g_free (module_name); + if (result == NULL) { + gchar *module_name = g_strconcat ("gi._gi_", namespace, NULL); + PyObject *module = PyImport_ImportModule (module_name); - if (foreign_structs != NULL) { - for (i = 0; i < foreign_structs->len; i++) { - PyGIForeignStruct *foreign_struct = \ - g_ptr_array_index (foreign_structs, i); + g_free (module_name); - if ( (strcmp (namespace, foreign_struct->namespace) == 0) && - (strcmp (name, foreign_struct->name) == 0)) { - g_base_info_unref (base_info); - return foreign_struct; - } + if (module == NULL) + PyErr_Clear (); + else { + Py_DECREF (module); + result = do_lookup (namespace, name); } } - g_base_info_unref (base_info); + if (result == NULL) { + PyErr_Format (PyExc_TypeError, + "Couldn't find conversion for foreign struct '%s.%s'", + namespace, + name); + } - PyErr_Format (PyExc_TypeError, "Couldn't find conversion for foreign struct '%s.%s'", namespace, name); - return NULL; + return result; } PyObject * -pygi_struct_foreign_convert_to_g_argument (PyObject *value, +pygi_struct_foreign_convert_to_g_argument (PyObject *value, GITypeInfo *type_info, GITransfer transfer, - GArgument *arg) + GIArgument *arg) { - PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info); + GIBaseInfo *base_info = g_type_info_get_interface (type_info); + PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info); + g_base_info_unref (base_info); if (foreign_struct == NULL) return NULL; @@ -98,9 +124,12 @@ pygi_struct_foreign_convert_to_g_argument (PyObject *value, PyObject * pygi_struct_foreign_convert_from_g_argument (GITypeInfo *type_info, - GArgument *arg) + GIArgument *arg) { - PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info); + GIBaseInfo *base_info = g_type_info_get_interface (type_info); + PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info); + g_base_info_unref (base_info); + if (foreign_struct == NULL) return NULL; @@ -109,11 +138,10 @@ pygi_struct_foreign_convert_from_g_argument (GITypeInfo *type_info, } PyObject * -pygi_struct_foreign_release_g_argument (GITransfer transfer, - GITypeInfo *type_info, - GArgument *arg) +pygi_struct_foreign_release (GIBaseInfo *base_info, + gpointer struct_) { - PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info); + PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info); if (foreign_struct == NULL) return NULL; @@ -121,7 +149,7 @@ pygi_struct_foreign_release_g_argument (GITransfer transfer, if (!foreign_struct->release_func) Py_RETURN_NONE; - if (!foreign_struct->release_func (transfer, type_info, arg)) + if (!foreign_struct->release_func (base_info, struct_)) return NULL; Py_RETURN_NONE; @@ -130,9 +158,9 @@ pygi_struct_foreign_release_g_argument (GITransfer transfer, void pygi_register_foreign_struct_real (const char* namespace_, const char* name, - PyGIArgOverrideToGArgumentFunc to_func, - PyGIArgOverrideFromGArgumentFunc from_func, - PyGIArgOverrideReleaseGArgumentFunc release_func) + PyGIArgOverrideToGIArgumentFunc to_func, + PyGIArgOverrideFromGIArgumentFunc from_func, + PyGIArgOverrideReleaseFunc release_func) { PyGIForeignStruct *new_struct = g_slice_new0 (PyGIForeignStruct); new_struct->namespace = namespace_; @@ -141,8 +169,5 @@ pygi_register_foreign_struct_real (const char* namespace_, new_struct->from_func = from_func; new_struct->release_func = release_func; - if (foreign_structs == NULL) - foreign_structs = g_ptr_array_new (); - g_ptr_array_add (foreign_structs, new_struct); } diff --git a/gi/pygi-foreign.h b/gi/pygi-foreign.h index 9a35bd8..b57f892 100644 --- a/gi/pygi-foreign.h +++ b/gi/pygi-foreign.h @@ -33,17 +33,16 @@ PyObject *pygi_struct_foreign_convert_to_g_argument (PyObject *value, GITypeInfo *type_info, GITransfer transfer, - GArgument *arg); + GIArgument *arg); PyObject *pygi_struct_foreign_convert_from_g_argument (GITypeInfo *type_info, - GArgument *arg); -PyObject *pygi_struct_foreign_release_g_argument (GITransfer transfer, - GITypeInfo *type_info, - GArgument *arg); + GIArgument *arg); +PyObject *pygi_struct_foreign_release (GITypeInfo *type_info, + gpointer struct_); void pygi_register_foreign_struct_real (const char* namespace_, const char* name, - PyGIArgOverrideToGArgumentFunc to_func, - PyGIArgOverrideFromGArgumentFunc from_func, - PyGIArgOverrideReleaseGArgumentFunc release_func); + PyGIArgOverrideToGIArgumentFunc to_func, + PyGIArgOverrideFromGIArgumentFunc from_func, + PyGIArgOverrideReleaseFunc release_func); #endif /* __PYGI_FOREIGN_H__ */ diff --git a/gi/pygi-info.c b/gi/pygi-info.c index 7888ada..feeccf7 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -24,44 +24,7 @@ #include "pygi-private.h" #include <pygobject.h> - -#define _PyGI_DEFINE_INFO_TYPE(name, cname, base) \ -static PyMethodDef _Py##cname##_methods[]; \ -PyTypeObject Py##cname##_Type = { \ - PyObject_HEAD_INIT(NULL) \ - 0, \ - "gi." name, /* tp_name */ \ - sizeof(PyGIBaseInfo), /* tp_basicsize */ \ - 0, /* tp_itemsize */ \ - (destructor)NULL, /* tp_dealloc */ \ - (printfunc)NULL, /* tp_print */ \ - (getattrfunc)NULL, /* tp_getattr */ \ - (setattrfunc)NULL, /* tp_setattr */ \ - (cmpfunc)NULL, /* tp_compare */ \ - (reprfunc)NULL, /* tp_repr */ \ - NULL, /* tp_as_number */ \ - NULL, /* tp_as_sequence */ \ - NULL, /* tp_as_mapping */ \ - (hashfunc)NULL, /* tp_hash */ \ - (ternaryfunc)NULL, /* tp_call */ \ - (reprfunc)NULL, /* tp_str */ \ - (getattrofunc)NULL, /* tp_getattro */ \ - (setattrofunc)NULL, /* tp_setattro */ \ - NULL, /* tp_as_buffer */ \ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ \ - NULL, /* tp_doc */ \ - (traverseproc)NULL, /* tp_traverse */ \ - (inquiry)NULL, /* tp_clear */ \ - (richcmpfunc)NULL, /* tp_richcompare */ \ - offsetof(PyGIBaseInfo, inst_weakreflist), /* tp_weaklistoffset */ \ - (getiterfunc)NULL, /* tp_iter */ \ - (iternextfunc)NULL, /* tp_iternext */ \ - _Py##cname##_methods, /* tp_methods */ \ - NULL, /* tp_members */ \ - NULL, /* tp_getset */ \ - &base /* tp_base */ \ -} - +#include <pyglib-python-compat.h> /* BaseInfo */ @@ -74,7 +37,7 @@ _base_info_dealloc (PyGIBaseInfo *self) g_base_info_unref (self->info); - self->ob_type->tp_free ( (PyObject *) self); + Py_TYPE( (PyObject *) self)->tp_free ( (PyObject *) self); } static int @@ -88,55 +51,26 @@ _base_info_traverse (PyGIBaseInfo *self, static PyObject * _base_info_repr (PyGIBaseInfo *self) { - return PyString_FromFormat ("<%s object (%s) at 0x%p>", - self->ob_type->tp_name, g_base_info_get_name (self->info), (void *) self); + return PYGLIB_PyUnicode_FromFormat ("<%s object (%s) at 0x%p>", + Py_TYPE( (PyObject *) self)->tp_name, + g_base_info_get_name (self->info), + (void *) self); } static PyMethodDef _PyGIBaseInfo_methods[]; -PyTypeObject PyGIBaseInfo_Type = { - PyObject_HEAD_INIT (NULL) - 0, - "gi.BaseInfo", /* tp_name */ - sizeof (PyGIBaseInfo), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) _base_info_dealloc, /* tp_dealloc */ - (printfunc) NULL, /* tp_print */ - (getattrfunc) NULL, /* tp_getattr */ - (setattrfunc) NULL, /* tp_setattr */ - (cmpfunc) NULL, /* tp_compare */ - (reprfunc) _base_info_repr, /* tp_repr */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - (hashfunc) NULL, /* tp_hash */ - (ternaryfunc) NULL, /* tp_call */ - (reprfunc) NULL, /* tp_str */ - (getattrofunc) NULL, /* tp_getattro */ - (setattrofunc) NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /* tp_flags */ - NULL, /* tp_doc */ - (traverseproc) _base_info_traverse, /* tp_traverse */ - (inquiry) NULL, /* tp_clear */ - (richcmpfunc) NULL, /* tp_richcompare */ - offsetof (PyGIBaseInfo, inst_weakreflist), /* tp_weaklistoffset */ - (getiterfunc) NULL, /* tp_iter */ - (iternextfunc) NULL, /* tp_iternext */ - _PyGIBaseInfo_methods, /* tp_methods */ -}; +PYGLIB_DEFINE_TYPE("gi.BaseInfo", PyGIBaseInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_base_info_get_name (PyGIBaseInfo *self) { - return PyString_FromString (g_base_info_get_name (self->info)); + return PYGLIB_PyUnicode_FromString (g_base_info_get_name (self->info)); } static PyObject * _wrap_g_base_info_get_namespace (PyGIBaseInfo *self) { - return PyString_FromString (g_base_info_get_namespace (self->info)); + return PYGLIB_PyUnicode_FromString (g_base_info_get_namespace (self->info)); } static PyObject * @@ -255,7 +189,7 @@ _pygi_object_get_gi_info (PyObject *object, } if (!PyObject_TypeCheck (py_info, type)) { PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s, not %s", - type->tp_name, py_info->ob_type->tp_name); + type->tp_name, Py_TYPE(&py_info)->tp_name); goto out; } @@ -270,7 +204,7 @@ out: /* CallableInfo */ -_PyGI_DEFINE_INFO_TYPE ("CallableInfo", GICallableInfo, PyGIBaseInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.CallableInfo", PyGICallableInfo_Type, PyGIBaseInfo); static PyMethodDef _PyGICallableInfo_methods[] = { { NULL, NULL, 0 } @@ -278,7 +212,7 @@ static PyMethodDef _PyGICallableInfo_methods[] = { /* FunctionInfo */ -_PyGI_DEFINE_INFO_TYPE ("FunctionInfo", GIFunctionInfo, PyGICallableInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.FunctionInfo", PyGIFunctionInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_function_info_is_constructor (PyGIBaseInfo *self) @@ -467,7 +401,7 @@ static PyMethodDef _PyGIFunctionInfo_methods[] = { /* RegisteredTypeInfo */ -_PyGI_DEFINE_INFO_TYPE ("RegisteredTypeInfo", GIRegisteredTypeInfo, PyGIBaseInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.RegisteredTypeInfo", PyGIRegisteredTypeInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_registered_type_info_get_g_type (PyGIBaseInfo *self) @@ -486,7 +420,7 @@ static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = { /* GIStructInfo */ -_PyGI_DEFINE_INFO_TYPE ("StructInfo", GIStructInfo, PyGIRegisteredTypeInfo_Type); +PYGLIB_DEFINE_TYPE ("StructInfo", PyGIStructInfo_Type, PyGIBaseInfo); static PyObject * _get_fields (PyGIBaseInfo *self, GIInfoType info_type) @@ -832,7 +766,7 @@ pygi_g_struct_info_is_simple (GIStructInfo *struct_info) /* EnumInfo */ -_PyGI_DEFINE_INFO_TYPE ("EnumInfo", GIEnumInfo, PyGIRegisteredTypeInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.EnumInfo", PyGIEnumInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_enum_info_get_values (PyGIBaseInfo *self) @@ -877,7 +811,7 @@ static PyMethodDef _PyGIEnumInfo_methods[] = { /* ObjectInfo */ -_PyGI_DEFINE_INFO_TYPE ("ObjectInfo", GIObjectInfo, PyGIRegisteredTypeInfo_Type); +PYGLIB_DEFINE_TYPE ("ObjectInfo", PyGIObjectInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_object_info_get_parent (PyGIBaseInfo *self) @@ -970,7 +904,7 @@ static PyMethodDef _PyGIObjectInfo_methods[] = { /* GIInterfaceInfo */ -_PyGI_DEFINE_INFO_TYPE ("InterfaceInfo", GIInterfaceInfo, PyGIRegisteredTypeInfo_Type); +PYGLIB_DEFINE_TYPE ("InterfaceInfo", PyGIInterfaceInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_interface_info_get_methods (PyGIBaseInfo *self) @@ -1028,13 +962,13 @@ static PyMethodDef _PyGIInterfaceInfo_methods[] = { }; /* GIConstantInfo */ -_PyGI_DEFINE_INFO_TYPE ("ConstantInfo", GIConstantInfo, PyGIBaseInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.ConstantInfo", PyGIConstantInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_constant_info_get_value (PyGIBaseInfo *self) { GITypeInfo *type_info; - GArgument value; + GIArgument value; PyObject *py_value; if (g_constant_info_get_value ( (GIConstantInfo *) self->info, &value) < 0) { @@ -1057,7 +991,7 @@ static PyMethodDef _PyGIConstantInfo_methods[] = { }; /* GIValueInfo */ -_PyGI_DEFINE_INFO_TYPE ("ValueInfo", GIValueInfo, PyGIBaseInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.ValueInfo", PyGIValueInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_value_info_get_value (PyGIBaseInfo *self) @@ -1066,7 +1000,7 @@ _wrap_g_value_info_get_value (PyGIBaseInfo *self) value = g_value_info_get_value ( (GIValueInfo *) self->info); - return PyInt_FromLong (value); + return PYGLIB_PyLong_FromLong (value); } @@ -1077,7 +1011,7 @@ static PyMethodDef _PyGIValueInfo_methods[] = { /* GIFieldInfo */ -_PyGI_DEFINE_INFO_TYPE ("FieldInfo", GIFieldInfo, PyGIBaseInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.FieldInfo", PyGIFieldInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_field_info_get_value (PyGIBaseInfo *self, @@ -1088,10 +1022,10 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self, GIInfoType container_info_type; gpointer pointer; GITypeInfo *field_type_info; - GArgument value; + GIArgument value; PyObject *py_value = NULL; - memset(&value, 0, sizeof(GArgument)); + memset(&value, 0, sizeof(GIArgument)); if (!PyArg_ParseTuple (args, "O:FieldInfo.get_value", &instance)) { return NULL; @@ -1197,7 +1131,7 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self, GIInfoType container_info_type; gpointer pointer; GITypeInfo *field_type_info; - GArgument value; + GIArgument value; PyObject *retval = NULL; if (!PyArg_ParseTuple (args, "OO:FieldInfo.set_value", &instance, &py_value)) { @@ -1333,14 +1267,14 @@ static PyMethodDef _PyGIFieldInfo_methods[] = { /* GIUnresolvedInfo */ -_PyGI_DEFINE_INFO_TYPE ("UnresolvedInfo", GIUnresolvedInfo, PyGIBaseInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.UnresolvedInfo", PyGIUnresolvedInfo_Type, PyGIBaseInfo); static PyMethodDef _PyGIUnresolvedInfo_methods[] = { { NULL, NULL, 0 } }; /* GIVFuncInfo */ -_PyGI_DEFINE_INFO_TYPE ("VFuncInfo", GIVFuncInfo, PyGIBaseInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.VFuncInfo", PyGIVFuncInfo_Type, PyGIBaseInfo); static PyMethodDef _PyGIVFuncInfo_methods[] = { { NULL, NULL, 0 } @@ -1348,7 +1282,7 @@ static PyMethodDef _PyGIVFuncInfo_methods[] = { /* GIUnionInfo */ -_PyGI_DEFINE_INFO_TYPE ("UnionInfo", GIUnionInfo, PyGIRegisteredTypeInfo_Type); +PYGLIB_DEFINE_TYPE ("gi.UnionInfo", PyGIUnionInfo_Type, PyGIBaseInfo); static PyObject * _wrap_g_union_info_get_fields (PyGIBaseInfo *self) @@ -1458,27 +1392,61 @@ _pygi_g_base_info_get_fullname (GIBaseInfo *info) void _pygi_info_register_types (PyObject *m) { -#define _PyGI_REGISTER_TYPE(m, type, name) \ - type.ob_type = &PyType_Type; \ +#define _PyGI_REGISTER_TYPE(m, type, cname, base) \ + Py_TYPE(&type) = &PyType_Type; \ + type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); \ + type.tp_weaklistoffset = offsetof(PyGIBaseInfo, inst_weakreflist); \ + type.tp_methods = _PyGI##cname##_methods; \ + type.tp_base = &base; \ if (PyType_Ready(&type)) \ return; \ - if (PyModule_AddObject(m, name, (PyObject *)&type)) \ + if (PyModule_AddObject(m, #cname, (PyObject *)&type)) \ return - _PyGI_REGISTER_TYPE (m, PyGIBaseInfo_Type, "BaseInfo"); - _PyGI_REGISTER_TYPE (m, PyGIUnresolvedInfo_Type, "UnresolvedInfo"); - _PyGI_REGISTER_TYPE (m, PyGICallableInfo_Type, "CallableInfo"); - _PyGI_REGISTER_TYPE (m, PyGIFunctionInfo_Type, "FunctionInfo"); - _PyGI_REGISTER_TYPE (m, PyGIRegisteredTypeInfo_Type, "RegisteredTypeInfo"); - _PyGI_REGISTER_TYPE (m, PyGIStructInfo_Type, "StructInfo"); - _PyGI_REGISTER_TYPE (m, PyGIEnumInfo_Type, "EnumInfo"); - _PyGI_REGISTER_TYPE (m, PyGIObjectInfo_Type, "ObjectInfo"); - _PyGI_REGISTER_TYPE (m, PyGIInterfaceInfo_Type, "InterfaceInfo"); - _PyGI_REGISTER_TYPE (m, PyGIConstantInfo_Type, "ConstantInfo"); - _PyGI_REGISTER_TYPE (m, PyGIValueInfo_Type, "ValueInfo"); - _PyGI_REGISTER_TYPE (m, PyGIFieldInfo_Type, "FieldInfo"); - _PyGI_REGISTER_TYPE (m, PyGIVFuncInfo_Type, "VFuncInfo"); - _PyGI_REGISTER_TYPE (m, PyGIUnionInfo_Type, "UnionInfo"); + Py_TYPE(&PyGIBaseInfo_Type) = &PyType_Type; + + PyGIBaseInfo_Type.tp_dealloc = (destructor) _base_info_dealloc; + PyGIBaseInfo_Type.tp_repr = (reprfunc) _base_info_repr; + PyGIBaseInfo_Type.tp_flags = (Py_TPFLAGS_DEFAULT | + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC); + PyGIBaseInfo_Type.tp_traverse = (traverseproc) _base_info_traverse; + PyGIBaseInfo_Type.tp_weaklistoffset = offsetof(PyGIBaseInfo, inst_weakreflist); + PyGIBaseInfo_Type.tp_methods = _PyGIBaseInfo_methods; + + if (PyType_Ready(&PyGIBaseInfo_Type)) + return; + + if (PyModule_AddObject(m, "BaseInfo", (PyObject *)&PyGIBaseInfo_Type)) + return; + + _PyGI_REGISTER_TYPE (m, PyGIUnresolvedInfo_Type, UnresolvedInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGICallableInfo_Type, CallableInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIFunctionInfo_Type, FunctionInfo, + PyGICallableInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIRegisteredTypeInfo_Type, RegisteredTypeInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIStructInfo_Type, StructInfo, + PyGIRegisteredTypeInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIEnumInfo_Type, EnumInfo, + PyGIRegisteredTypeInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIObjectInfo_Type, ObjectInfo, + PyGIRegisteredTypeInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIInterfaceInfo_Type, InterfaceInfo, + PyGIRegisteredTypeInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIConstantInfo_Type, ConstantInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIValueInfo_Type, ValueInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIFieldInfo_Type, FieldInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIVFuncInfo_Type, VFuncInfo, + PyGIBaseInfo_Type); + _PyGI_REGISTER_TYPE (m, PyGIUnionInfo_Type, UnionInfo, + PyGIRegisteredTypeInfo_Type); + #undef _PyGI_REGISTER_TYPE } diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c index a470003..64b3f31 100644 --- a/gi/pygi-invoke.c +++ b/gi/pygi-invoke.c @@ -49,14 +49,14 @@ struct invocation_state GITypeInfo *return_type_info; GITypeTag return_type_tag; - GArgument **args; + GIArgument **args; gboolean *args_is_auxiliary; - GArgument *in_args; - GArgument *out_args; - GArgument *out_values; - GArgument *backup_args; - GArgument return_arg; + GIArgument *in_args; + GIArgument *out_args; + GIArgument *out_values; + GIArgument *backup_args; + GIArgument return_arg; PyObject *return_value; }; @@ -154,18 +154,14 @@ _prepare_invocation_state (struct invocation_state *state, if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { state->n_in_args += 1; - if (transfer == GI_TRANSFER_CONTAINER) { - state->n_backup_args += 1; - } + } + if (direction == GI_DIRECTION_INOUT) { + state->n_backup_args += 1; } if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { state->n_out_args += 1; } - if (direction == GI_DIRECTION_INOUT && transfer == GI_TRANSFER_NOTHING) { - state->n_backup_args += 1; - } - switch (arg_type_tag) { case GI_TYPE_TAG_ARRAY: { @@ -173,13 +169,16 @@ _prepare_invocation_state (struct invocation_state *state, length_arg_pos = g_type_info_get_array_length (state->arg_type_infos[i]); - if (state->is_method) - length_arg_pos--; // length_arg_pos refers to C args - if (length_arg_pos < 0) { break; } + /* For array lengths, we're going to delete the length argument; + * so remove the extra backup we just added above */ + if (direction == GI_DIRECTION_INOUT) { + state->n_backup_args -= 1; + } + g_assert (length_arg_pos < state->n_args); state->args_is_auxiliary[length_arg_pos] = TRUE; @@ -208,9 +207,6 @@ _prepare_invocation_state (struct invocation_state *state, gint length_arg_pos; length_arg_pos = g_type_info_get_array_length (state->return_type_info); - if (state->is_method) - length_arg_pos--; // length_arg_pos refers to C args - if (length_arg_pos >= 0) { g_assert (length_arg_pos < state->n_args); state->args_is_auxiliary[length_arg_pos] = TRUE; @@ -285,10 +281,10 @@ _prepare_invocation_state (struct invocation_state *state, } state->args = g_slice_alloc0 (sizeof (gpointer) * state->n_args); - state->in_args = g_slice_alloc0 (sizeof (GArgument) * state->n_in_args); - state->out_args = g_slice_alloc0 (sizeof (GArgument) * state->n_out_args); - state->out_values = g_slice_alloc0 (sizeof (GArgument) * state->n_out_args); - state->backup_args = g_slice_alloc0 (sizeof (GArgument) * state->n_backup_args); + state->in_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_in_args); + state->out_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_out_args); + state->out_values = g_slice_alloc0 (sizeof (GIArgument) * state->n_out_args); + state->backup_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_backup_args); /* Bind args so we can use an unique index. */ { @@ -344,19 +340,15 @@ _prepare_invocation_state (struct invocation_state *state, } if (is_caller_allocates) { - gsize size; - /* if caller allocates only use one level of indirection */ state->out_args[out_args_pos].v_pointer = NULL; state->args[i] = &state->out_args[out_args_pos]; - - /* FIXME: Remove when bgo#622711 is fixed */ - if (g_registered_type_info_get_g_type (info) == G_TYPE_VALUE) - size = sizeof (GValue); - else - size = g_struct_info_get_size ( (GIStructInfo *) info); - - state->args[i]->v_pointer = g_malloc0 (size); + if (g_type_is_a (g_registered_type_info_get_g_type (info), G_TYPE_BOXED)) + state->args[i]->v_pointer = _pygi_boxed_alloc (info, NULL); + else { + gssize size = g_struct_info_get_size ( (GIStructInfo *) info); + state->args[i]->v_pointer = g_malloc0 (size); + } } else { state->out_args[out_args_pos].v_pointer = &state->out_values[out_args_pos]; state->out_values[out_args_pos].v_pointer = NULL; @@ -387,6 +379,7 @@ _prepare_invocation_state (struct invocation_state *state, GIBaseInfo *container_info; GIInfoType container_info_type; PyObject *py_arg; + gint check_val; container_info = g_base_info_get_container (function_info); container_info_type = g_base_info_get_type (container_info); @@ -394,6 +387,19 @@ _prepare_invocation_state (struct invocation_state *state, g_assert (py_args_pos < state->n_py_args); py_arg = PyTuple_GET_ITEM (py_args, py_args_pos); + /* In python 2 python takes care of checking the type + * of the self instance. In python 3 it does not + * so we have to check it here + */ + check_val = _pygi_g_type_interface_check_object(container_info, + py_arg); + if (check_val < 0) { + return FALSE; + } else if (!check_val) { + _PyGI_ERROR_PREFIX ("instance: "); + return FALSE; + } + switch (container_info_type) { case GI_INFO_TYPE_UNION: case GI_INFO_TYPE_STRUCT: @@ -487,61 +493,11 @@ _prepare_invocation_state (struct invocation_state *state, return FALSE; } - if (direction == GI_DIRECTION_INOUT && transfer == GI_TRANSFER_NOTHING) { + if (direction == GI_DIRECTION_INOUT) { /* We need to keep a copy of the argument to be able to release it later. */ g_assert (backup_args_pos < state->n_backup_args); state->backup_args[backup_args_pos] = *state->args[i]; backup_args_pos += 1; - } else if (transfer == GI_TRANSFER_CONTAINER) { - /* We need to keep a copy of the items to be able to release them later. */ - switch (arg_type_tag) { - case GI_TYPE_TAG_ARRAY: - { - GArray *array; - gsize item_size; - GArray *new_array; - - array = state->args[i]->v_pointer; - - item_size = g_array_get_element_size (array); - - new_array = g_array_sized_new (FALSE, FALSE, item_size, array->len); - g_array_append_vals (new_array, array->data, array->len); - - g_assert (backup_args_pos < state->n_backup_args); - state->backup_args[backup_args_pos].v_pointer = new_array; - - break; - } - case GI_TYPE_TAG_GLIST: - g_assert (backup_args_pos < state->n_backup_args); - state->backup_args[backup_args_pos].v_pointer = g_list_copy (state->args[i]->v_pointer); - break; - case GI_TYPE_TAG_GSLIST: - g_assert (backup_args_pos < state->n_backup_args); - state->backup_args[backup_args_pos].v_pointer = g_slist_copy (state->args[i]->v_pointer); - break; - case GI_TYPE_TAG_GHASH: - { - GHashTable *hash_table; - GList *keys; - GList *values; - - hash_table = state->args[i]->v_pointer; - - keys = g_hash_table_get_keys (hash_table); - values = g_hash_table_get_values (hash_table); - - g_assert (backup_args_pos < state->n_backup_args); - state->backup_args[backup_args_pos].v_pointer = g_list_concat (keys, values); - - break; - } - default: - g_warn_if_reached(); - } - - backup_args_pos += 1; } if (arg_type_tag == GI_TYPE_TAG_ARRAY) { @@ -551,8 +507,6 @@ _prepare_invocation_state (struct invocation_state *state, array = state->args[i]->v_pointer; length_arg_pos = g_type_info_get_array_length (state->arg_type_infos[i]); - if (state->is_method) - length_arg_pos--; // length_arg_pos refers to C args if (length_arg_pos >= 0) { int len = 0; /* Set the auxiliary argument holding the length. */ @@ -639,6 +593,11 @@ _process_invocation_state (struct invocation_state *state, GIInfoType info_type; GITransfer transfer; + if (state->return_arg.v_pointer == NULL) { + PyErr_SetString (PyExc_TypeError, "constructor returned NULL"); + return FALSE; + } + g_assert (state->n_py_args > 0); py_type = (PyTypeObject *) PyTuple_GET_ITEM (py_args, 0); @@ -651,10 +610,6 @@ _process_invocation_state (struct invocation_state *state, switch (info_type) { case GI_INFO_TYPE_UNION: - /* TODO */ - PyErr_SetString (PyExc_NotImplementedError, "creating unions is not supported yet"); - g_base_info_unref (info); - return FALSE; case GI_INFO_TYPE_STRUCT: { GType type; @@ -662,24 +617,22 @@ _process_invocation_state (struct invocation_state *state, type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); if (g_type_is_a (type, G_TYPE_BOXED)) { - if (state->return_arg.v_pointer == NULL) { - PyErr_SetString (PyExc_TypeError, "constructor returned NULL"); - break; - } g_warn_if_fail (transfer == GI_TRANSFER_EVERYTHING); state->return_value = _pygi_boxed_new (py_type, state->return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING); + } else if (type == G_TYPE_NONE && g_struct_info_is_foreign (info)) { + state->return_value = + pygi_struct_foreign_convert_from_g_argument ( + state->return_type_info, state->return_arg.v_pointer); } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) { - if (state->return_arg.v_pointer == NULL) { - PyErr_SetString (PyExc_TypeError, "constructor returned NULL"); - break; - } - if (transfer != GI_TRANSFER_NOTHING) - g_warning ("Transfer mode should be set to None for " + g_warning ("Return argument in %s returns a struct " + "with a transfer mode of \"full\" " + "Transfer mode should be set to None for " "struct types as there is no way to free " "them safely. Ignoring transfer mode " "to prevent a potential invalid free. " - "This may cause a leak in your application."); + "This may cause a leak in your application.", + g_base_info_get_name ( (GIBaseInfo *) function_info) ); state->return_value = _pygi_struct_new (py_type, state->return_arg.v_pointer, FALSE); } else { @@ -740,10 +693,8 @@ _process_invocation_state (struct invocation_state *state, /* Convert output arguments and release arguments. */ { - gsize backup_args_pos; gsize return_values_pos; - backup_args_pos = 0; return_values_pos = 0; if (state->n_return_values > 1) { @@ -795,6 +746,36 @@ _process_invocation_state (struct invocation_state *state, /* Convert the argument. */ PyObject *obj; + /* If we created it, deallocate when it goes out of scope + * otherwise it is unsafe to deallocate random structures + * we are given + */ + if (type_tag == GI_TYPE_TAG_INTERFACE) { + GIBaseInfo *info; + GIInfoType info_type; + + info = g_type_info_get_interface (state->arg_type_infos[i]); + g_assert (info != NULL); + info_type = g_base_info_get_type (info); + + if ( (info_type == GI_INFO_TYPE_STRUCT) && + !g_struct_info_is_foreign((GIStructInfo *) info) ) { + if (g_arg_info_is_caller_allocates (state->arg_infos[i])) { + transfer = GI_TRANSFER_EVERYTHING; + } else if (transfer == GI_TRANSFER_EVERYTHING) { + transfer = GI_TRANSFER_NOTHING; + g_warning ("Out argument %ld in %s returns a struct " + "with a transfer mode of \"full\". " + "Transfer mode should be set to \"none\" for " + "struct type returns as there is no way to free " + "them safely. Ignoring transfer mode " + "to prevent a potential invalid free. " + "This may cause a leak in your application.", + i, g_base_info_get_name ( (GIBaseInfo *) function_info) ); + } + } + } + obj = _pygi_argument_to_object (state->args[i], state->arg_type_infos[i], transfer); if (obj == NULL) { /* TODO: release arguments. */ @@ -814,83 +795,9 @@ _process_invocation_state (struct invocation_state *state, return_values_pos += 1; } - /* Release the argument. */ - - if ( (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) - && transfer == GI_TRANSFER_CONTAINER) { - /* Release the items we kept in another container. */ - switch (type_tag) { - case GI_TYPE_TAG_ARRAY: - case GI_TYPE_TAG_GLIST: - case GI_TYPE_TAG_GSLIST: - g_assert (backup_args_pos < state->n_backup_args); - _pygi_argument_release (&state->backup_args[backup_args_pos], state->arg_type_infos[i], - transfer, GI_DIRECTION_IN); - break; - case GI_TYPE_TAG_GHASH: - { - GITypeInfo *key_type_info; - GITypeInfo *value_type_info; - GList *item; - gsize length; - gsize j; - - key_type_info = g_type_info_get_param_type (state->arg_type_infos[i], 0); - value_type_info = g_type_info_get_param_type (state->arg_type_infos[i], 1); - - g_assert (backup_args_pos < state->n_backup_args); - item = state->backup_args[backup_args_pos].v_pointer; - - length = g_list_length (item) / 2; - - for (j = 0; j < length; j++, item = g_list_next (item)) { - _pygi_argument_release ( (GArgument *) &item->data, key_type_info, - GI_TRANSFER_NOTHING, GI_DIRECTION_IN); - } - - for (j = 0; j < length; j++, item = g_list_next (item)) { - _pygi_argument_release ( (GArgument *) &item->data, value_type_info, - GI_TRANSFER_NOTHING, GI_DIRECTION_IN); - } - - g_list_free (state->backup_args[backup_args_pos].v_pointer); - - break; - } - default: - g_warn_if_reached(); - } - - if (direction == GI_DIRECTION_INOUT) { - /* Release the output argument. */ - _pygi_argument_release (state->args[i], state->arg_type_infos[i], GI_TRANSFER_CONTAINER, - GI_DIRECTION_OUT); - } - - backup_args_pos += 1; - } else if (direction == GI_DIRECTION_INOUT) { - if (transfer == GI_TRANSFER_NOTHING) { - g_assert (backup_args_pos < state->n_backup_args); - _pygi_argument_release (&state->backup_args[backup_args_pos], state->arg_type_infos[i], - GI_TRANSFER_NOTHING, GI_DIRECTION_IN); - backup_args_pos += 1; - } - - _pygi_argument_release (state->args[i], state->arg_type_infos[i], transfer, - GI_DIRECTION_OUT); - } else { - _pygi_argument_release (state->args[i], state->arg_type_infos[i], transfer, direction); - } - - if (type_tag == GI_TYPE_TAG_ARRAY - && (direction != GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)) { - /* We created a #GArray and it has not been released above, so free it. */ - state->args[i]->v_pointer = g_array_free (state->args[i]->v_pointer, FALSE); - } } g_assert (state->n_return_values <= 1 || return_values_pos == state->n_return_values); - g_assert (backup_args_pos == state->n_backup_args); } return TRUE; @@ -900,6 +807,7 @@ static void _free_invocation_state (struct invocation_state *state) { gsize i; + gsize backup_args_pos; if (state->return_type_info != NULL) { g_base_info_unref ( (GIBaseInfo *) state->return_type_info); @@ -910,29 +818,42 @@ _free_invocation_state (struct invocation_state *state) _pygi_invoke_closure_free (state->closure); } + /* release all arguments. */ + backup_args_pos = 0; for (i = 0; i < state->n_args; i++) { - /* check for caller-allocated values we need to free */ - if (g_arg_info_is_caller_allocates (state->arg_infos[i])) { - GIBaseInfo *info; - GIInfoType info_type; + if (state->args_is_auxiliary[i]) { + /* Auxiliary arguments are not released. */ + continue; + } - info = g_type_info_get_interface (state->arg_type_infos[i]); - g_assert (info != NULL); - info_type = g_base_info_get_type (info); + if (state->args != NULL + && state->args[i] != NULL + && state->arg_infos[i] != NULL + && state->arg_type_infos[i] != NULL) { + GIDirection direction; + GITypeTag type_tag; + GITransfer transfer; - /* caller-allocates applies only to structs right now - * the GI scanner is overzealous when marking parameters - * as caller-allocates, so we only free if this was a struct - */ - if (info_type == GI_INFO_TYPE_STRUCT) { - /* special case GValues so we make sure to unset them */ - if (g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info) == G_TYPE_VALUE) { - g_value_unset ( (GValue *) state->args[i]); - } + direction = g_arg_info_get_direction (state->arg_infos[i]); + transfer = g_arg_info_get_ownership_transfer (state->arg_infos[i]); + + type_tag = g_type_info_get_tag (state->arg_type_infos[i]); + + /* Release the argument. */ + if (direction == GI_DIRECTION_INOUT) { + _pygi_argument_release (&state->backup_args[backup_args_pos], state->arg_type_infos[i], + transfer, GI_DIRECTION_IN); + backup_args_pos += 1; + } + _pygi_argument_release (state->args[i], state->arg_type_infos[i], transfer, direction); - g_free (state->args[i]); + if (type_tag == GI_TYPE_TAG_ARRAY + && (direction != GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)) { + /* We created a #GArray and it has not been released above, so free it. */ + state->args[i]->v_pointer = g_array_free (state->args[i]->v_pointer, FALSE); } + } if (state->arg_type_infos[i] != NULL) @@ -940,37 +861,30 @@ _free_invocation_state (struct invocation_state *state) if (state->arg_infos[i] != NULL) g_base_info_unref ( (GIBaseInfo *) state->arg_infos[i]); } + g_assert (backup_args_pos == state->n_backup_args); - if (state->arg_infos != NULL) { - g_slice_free1 (sizeof (gpointer) * state->n_args, state->arg_infos); - } - - if (state->arg_type_infos != NULL) { - g_slice_free1 (sizeof (gpointer) * state->n_args, state->arg_type_infos); - } + g_slice_free1 (sizeof (gpointer) * state->n_args, state->arg_infos); + g_slice_free1 (sizeof (gpointer) * state->n_args, state->arg_type_infos); + g_slice_free1 (sizeof (gboolean) * state->n_args, state->args_is_auxiliary); if (state->args != NULL) { g_slice_free1 (sizeof (gpointer) * state->n_args, state->args); } - if (state->args_is_auxiliary != NULL) { - g_slice_free1 (sizeof (gboolean) * state->n_args, state->args_is_auxiliary); - } - if (state->in_args != NULL) { - g_slice_free1 (sizeof (GArgument) * state->n_in_args, state->in_args); + g_slice_free1 (sizeof (GIArgument) * state->n_in_args, state->in_args); } if (state->out_args != NULL) { - g_slice_free1 (sizeof (GArgument) * state->n_out_args, state->out_args); + g_slice_free1 (sizeof (GIArgument) * state->n_out_args, state->out_args); } if (state->out_values != NULL) { - g_slice_free1 (sizeof (GArgument) * state->n_out_args, state->out_values); + g_slice_free1 (sizeof (GIArgument) * state->n_out_args, state->out_values); } if (state->backup_args != NULL) { - g_slice_free1 (sizeof (GArgument) * state->n_backup_args, state->backup_args); + g_slice_free1 (sizeof (GIArgument) * state->n_backup_args, state->backup_args); } if (PyErr_Occurred()) { @@ -1001,6 +915,7 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self, PyObject *py_args) return NULL; } + _free_invocation_state (&state); return state.return_value; } diff --git a/gi/pygi-private.h b/gi/pygi-private.h index 0ff5df7..3a14bc3 100644 --- a/gi/pygi-private.h +++ b/gi/pygi-private.h @@ -28,8 +28,30 @@ #include "pygi-closure.h" #include "pygi-callbacks.h" #include "pygi-invoke.h" +#include "pygi-property.h" G_BEGIN_DECLS +#if PY_VERSION_HEX >= 0x03000000 + +#define _PyGI_ERROR_PREFIX(format, ...) G_STMT_START { \ + PyObject *py_error_prefix; \ + py_error_prefix = PyUnicode_FromFormat(format, ## __VA_ARGS__); \ + if (py_error_prefix != NULL) { \ + PyObject *py_error_type, *py_error_value, *py_error_traceback; \ + PyErr_Fetch(&py_error_type, &py_error_value, &py_error_traceback); \ + if (PyUnicode_Check(py_error_value)) { \ + PyObject *new; \ + new = PyUnicode_Concat(py_error_prefix, py_error_value); \ + Py_DECREF(py_error_value); \ + if (new != NULL) { \ + py_error_value = new; \ + } \ + } \ + PyErr_Restore(py_error_type, py_error_value, py_error_traceback); \ + } \ +} G_STMT_END + +#else #define _PyGI_ERROR_PREFIX(format, ...) G_STMT_START { \ PyObject *py_error_prefix; \ @@ -47,6 +69,8 @@ G_BEGIN_DECLS } \ } G_STMT_END +#endif + /* Redefine g_array_index because we want it to return the i-th element, casted * to the type t, of the array a, and not the i-th element of the array a * casted to the type t. */ diff --git a/gi/pygi-property.c b/gi/pygi-property.c new file mode 100644 index 0000000..7b6a508 --- /dev/null +++ b/gi/pygi-property.c @@ -0,0 +1,345 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* + * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "pygi-private.h" + +#include <girepository.h> + +/* Copied from glib */ +static void +canonicalize_key (gchar *key) +{ + gchar *p; + + for (p = key; *p != 0; p++) + { + gchar c = *p; + + if (c != '-' && + (c < '0' || c > '9') && + (c < 'A' || c > 'Z') && + (c < 'a' || c > 'z')) + *p = '-'; + } +} + +static GIPropertyInfo * +_pygi_lookup_property_from_g_type (GType g_type, const gchar *attr_name) +{ + GIRepository *repository; + GIBaseInfo *info; + gssize n_infos; + gssize i; + GType parent; + + repository = g_irepository_get_default(); + info = g_irepository_find_by_gtype (repository, g_type); + if (info == NULL) { + return NULL; + } + + n_infos = g_object_info_get_n_properties ( (GIObjectInfo *) info); + for (i = 0; i < n_infos; i++) { + GIPropertyInfo *property_info; + + property_info = g_object_info_get_property ( (GIObjectInfo *) info, i); + g_assert (info != NULL); + + if (strcmp (attr_name, g_base_info_get_name (property_info)) == 0) { + g_base_info_unref (info); + return property_info; + } + + g_base_info_unref (property_info); + } + + g_base_info_unref (info); + + parent = g_type_parent (g_type); + if (parent > 0) + return _pygi_lookup_property_from_g_type (parent, attr_name); + + return NULL; +} + +PyObject * +pygi_get_property_value_real (PyGObject *instance, + const gchar *attr_name) +{ + GType g_type; + GIPropertyInfo *property_info = NULL; + char *property_name = g_strdup (attr_name); + GParamSpec *pspec = NULL; + GValue value = { 0, }; + GIArgument arg = { 0, }; + PyObject *py_value = NULL; + GITypeInfo *type_info = NULL; + GITransfer transfer; + + canonicalize_key (property_name); + + g_type = pyg_type_from_object ((PyObject *)instance); + property_info = _pygi_lookup_property_from_g_type (g_type, property_name); + + if (property_info == NULL) + goto out; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (instance->obj), + attr_name); + if (pspec == NULL) + goto out; + + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + g_object_get_property (instance->obj, attr_name, &value); + + type_info = g_property_info_get_type (property_info); + transfer = g_property_info_get_ownership_transfer (property_info); + + GITypeTag type_tag = g_type_info_get_tag (type_info); + switch (type_tag) { + case GI_TYPE_TAG_BOOLEAN: + arg.v_boolean = g_value_get_boolean (&value); + break; + case GI_TYPE_TAG_INT8: + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_INT32: + case GI_TYPE_TAG_INT64: + arg.v_int = g_value_get_int (&value); + break; + case GI_TYPE_TAG_UINT8: + case GI_TYPE_TAG_UINT16: + case GI_TYPE_TAG_UINT32: + case GI_TYPE_TAG_UINT64: + arg.v_uint = g_value_get_uint (&value); + break; + case GI_TYPE_TAG_FLOAT: + arg.v_float = g_value_get_float (&value); + break; + case GI_TYPE_TAG_DOUBLE: + arg.v_double = g_value_get_double (&value); + break; + case GI_TYPE_TAG_GTYPE: + arg.v_size = g_value_get_uint (&value); + break; + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + arg.v_string = g_value_dup_string (&value); + break; + case GI_TYPE_TAG_INTERFACE: + { + GIBaseInfo *info; + GIInfoType info_type; + GType type; + + info = g_type_info_get_interface (type_info); + type = g_registered_type_info_get_g_type (info); + info_type = g_base_info_get_type (info); + + switch (info_type) { + case GI_INFO_TYPE_ENUM: + arg.v_int32 = g_value_get_enum (&value); + break; + case GI_INFO_TYPE_INTERFACE: + case GI_INFO_TYPE_OBJECT: + arg.v_pointer = g_value_get_object (&value); + break; + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_STRUCT: + case GI_INFO_TYPE_UNION: + + if (g_type_is_a (type, G_TYPE_BOXED)) { + arg.v_pointer = g_value_get_boxed (&value); + } else if (g_type_is_a (type, G_TYPE_POINTER)) { + arg.v_pointer = g_value_get_pointer (&value); + } else { + PyErr_Format (PyExc_NotImplementedError, + "Retrieving properties of type '%s' is not implemented", + g_type_name (type)); + } + break; + default: + PyErr_Format (PyExc_NotImplementedError, + "Retrieving properties of type '%s' is not implemented", + g_type_name (type)); + goto out; + } + break; + } + case GI_TYPE_TAG_GHASH: + arg.v_pointer = g_value_get_boxed (&value); + break; + case GI_TYPE_TAG_GLIST: + arg.v_pointer = g_value_get_pointer (&value); + break; + default: + PyErr_Format (PyExc_NotImplementedError, + "Retrieving properties of type %s is not implemented", + g_type_tag_to_string (g_type_info_get_tag (type_info))); + goto out; + } + + py_value = _pygi_argument_to_object (&arg, type_info, transfer); + +out: + g_free (property_name); + if (property_info != NULL) + g_base_info_unref (property_info); + if (type_info != NULL) + g_base_info_unref (type_info); + + return py_value; +} + +gint +pygi_set_property_value_real (PyGObject *instance, + const gchar *attr_name, + PyObject *py_value) +{ + GType g_type; + GIPropertyInfo *property_info = NULL; + char *property_name = g_strdup (attr_name); + GITypeInfo *type_info = NULL; + GITypeTag type_tag; + GITransfer transfer; + GValue value = { 0, }; + GIArgument arg = { 0, }; + GParamSpec *pspec = NULL; + gint ret_value = -1; + + canonicalize_key (property_name); + + g_type = pyg_type_from_object ((PyObject *)instance); + property_info = _pygi_lookup_property_from_g_type (g_type, property_name); + + if (property_info == NULL) + goto out; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (instance->obj), + attr_name); + if (pspec == NULL) + goto out; + + if (! (pspec->flags & G_PARAM_WRITABLE)) + goto out; + + type_info = g_property_info_get_type (property_info); + transfer = g_property_info_get_ownership_transfer (property_info); + arg = _pygi_argument_from_object (py_value, type_info, transfer); + + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + // FIXME: Lots of types still unhandled + type_tag = g_type_info_get_tag (type_info); + switch (type_tag) { + case GI_TYPE_TAG_INTERFACE: + { + GIBaseInfo *info; + GIInfoType info_type; + GType type; + + info = g_type_info_get_interface (type_info); + type = g_registered_type_info_get_g_type (info); + info_type = g_base_info_get_type (info); + + switch (info_type) { + case GI_INFO_TYPE_ENUM: + g_value_set_enum (&value, arg.v_int32); + break; + case GI_INFO_TYPE_INTERFACE: + case GI_INFO_TYPE_OBJECT: + g_value_set_object (&value, arg.v_pointer); + break; + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_STRUCT: + case GI_INFO_TYPE_UNION: + if (g_type_is_a (type, G_TYPE_BOXED)) { + g_value_set_boxed (&value, arg.v_pointer); + } else { + PyErr_Format (PyExc_NotImplementedError, + "Setting properties of type '%s' is not implemented", + g_type_name (type)); + } + break; + default: + PyErr_Format (PyExc_NotImplementedError, + "Setting properties of type '%s' is not implemented", + g_type_name (type)); + goto out; + } + break; + } + case GI_TYPE_TAG_BOOLEAN: + g_value_set_boolean (&value, arg.v_boolean); + break; + case GI_TYPE_TAG_INT8: + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_INT32: + case GI_TYPE_TAG_INT64: + g_value_set_int (&value, arg.v_int); + break; + case GI_TYPE_TAG_UINT8: + case GI_TYPE_TAG_UINT16: + case GI_TYPE_TAG_UINT32: + case GI_TYPE_TAG_UINT64: + g_value_set_uint (&value, arg.v_uint); + break; + case GI_TYPE_TAG_FLOAT: + g_value_set_float (&value, arg.v_float); + break; + case GI_TYPE_TAG_DOUBLE: + g_value_set_double (&value, arg.v_double); + break; + case GI_TYPE_TAG_GTYPE: + g_value_set_uint (&value, arg.v_size); + break; + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + g_value_set_string (&value, arg.v_string); + break; + case GI_TYPE_TAG_GHASH: + g_value_set_boxed (&value, arg.v_pointer); + break; + case GI_TYPE_TAG_GLIST: + g_value_set_pointer (&value, arg.v_pointer); + break; + default: + PyErr_Format (PyExc_NotImplementedError, + "Setting properties of type %s is not implemented", + g_type_tag_to_string (g_type_info_get_tag (type_info))); + goto out; + } + + g_object_set_property (instance->obj, attr_name, &value); + + ret_value = 0; + +out: + g_free (property_name); + if (property_info != NULL) + g_base_info_unref (property_info); + if (type_info != NULL) + g_base_info_unref (type_info); + + return ret_value; +} + diff --git a/gi/pygi-property.h b/gi/pygi-property.h new file mode 100644 index 0000000..31d0e42 --- /dev/null +++ b/gi/pygi-property.h @@ -0,0 +1,39 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* + * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __PYGI_PROPERTY_H__ +#define __PYGI_PROPERTY_H__ + +#include <Python.h> +#include <girepository.h> + +#include "pygi.h" + +PyObject *pygi_get_property_value_real (PyGObject *instance, + const gchar *attr_name); + +gint pygi_set_property_value_real (PyGObject *instance, + const gchar *attr_name, + PyObject *py_value); + +#endif /* __PYGI_PROPERTY_H__ */ diff --git a/gi/pygi-repository.c b/gi/pygi-repository.c index 783b4aa..9b22eae 100644 --- a/gi/pygi-repository.c +++ b/gi/pygi-repository.c @@ -23,41 +23,42 @@ #include "pygi-private.h" +#include <pyglib-python-compat.h> + PyObject *PyGIRepositoryError; static PyMethodDef _PyGIRepository_methods[]; -PyTypeObject PyGIRepository_Type = { - PyObject_HEAD_INIT (NULL) - 0, - "gi.Repository", /* tp_name */ - sizeof (PyGIRepository), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) NULL, /* tp_dealloc */ - (printfunc) NULL, /* tp_print */ - (getattrfunc) NULL, /* tp_getattr */ - (setattrfunc) NULL, /* tp_setattr */ - (cmpfunc) NULL, /* tp_compare */ - (reprfunc) NULL, /* tp_repr */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - (hashfunc) NULL, /* tp_hash */ - (ternaryfunc) NULL, /* tp_call */ - (reprfunc) NULL, /* tp_str */ - (getattrofunc) NULL, /* tp_getattro */ - (setattrofunc) NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - NULL, /* tp_doc */ - (traverseproc) NULL, /* tp_traverse */ - (inquiry) NULL, /* tp_clear */ - (richcmpfunc) NULL, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc) NULL, /* tp_iter */ - (iternextfunc) NULL, /* tp_iternext */ - _PyGIRepository_methods, /* tp_methods */ -}; +PYGLIB_DEFINE_TYPE("gi.Repository", PyGIRepository_Type, PyGIRepository); + +static PyObject * +_wrap_g_irepository_enumerate_versions (PyGIRepository *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "namespace", NULL }; + const char *namespace_; + GList *versions, *item; + PyObject *ret = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.enumerate_versions", + kwlist, &namespace_)) { + return NULL; + } + + versions = g_irepository_enumerate_versions (self->repository, namespace_); + ret = PyList_New(0); + for (item = versions; item; item = item->next) { + char *version = item->data; + PyObject *py_version = PYGLIB_PyUnicode_FromString (version); + PyList_Append(ret, py_version); + Py_DECREF(py_version); + g_free (version); + } + g_list_free(versions); + + return ret; +} static PyObject * _wrap_g_irepository_get_default (PyObject *self) @@ -91,7 +92,7 @@ _wrap_g_irepository_require (PyGIRepository *self, GTypelib *typelib; GError *error; - if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|sO:Repository.require", + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|zO:Repository.require", kwlist, &namespace_, &version, &lazy)) { return NULL; } @@ -207,25 +208,55 @@ _wrap_g_irepository_get_typelib_path (PyGIRepository *self, return NULL; } - return PyString_FromString (typelib_path); + return PYGLIB_PyBytes_FromString (typelib_path); +} + +static PyObject * +_wrap_g_irepository_get_version (PyGIRepository *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "namespace", NULL }; + const char *namespace_; + const gchar *version; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, + "s:Repository.get_version", kwlist, &namespace_)) { + return NULL; + } + + version = g_irepository_get_version (self->repository, namespace_); + if (version == NULL) { + PyErr_Format (PyExc_RuntimeError, "Namespace '%s' not loaded", namespace_); + return NULL; + } + + return PYGLIB_PyUnicode_FromString (version); } static PyMethodDef _PyGIRepository_methods[] = { + { "enumerate_versions", (PyCFunction) _wrap_g_irepository_enumerate_versions, METH_VARARGS | METH_KEYWORDS }, { "get_default", (PyCFunction) _wrap_g_irepository_get_default, METH_STATIC | METH_NOARGS }, { "require", (PyCFunction) _wrap_g_irepository_require, METH_VARARGS | METH_KEYWORDS }, { "get_infos", (PyCFunction) _wrap_g_irepository_get_infos, METH_VARARGS | METH_KEYWORDS }, { "find_by_name", (PyCFunction) _wrap_g_irepository_find_by_name, METH_VARARGS | METH_KEYWORDS }, { "get_typelib_path", (PyCFunction) _wrap_g_irepository_get_typelib_path, METH_VARARGS | METH_KEYWORDS }, + { "get_version", (PyCFunction) _wrap_g_irepository_get_version, METH_VARARGS | METH_KEYWORDS }, { NULL, NULL, 0 } }; void _pygi_repository_register_types (PyObject *m) { - PyGIRepository_Type.ob_type = &PyType_Type; + Py_TYPE(&PyGIRepository_Type) = &PyType_Type; + + PyGIRepository_Type.tp_flags = Py_TPFLAGS_DEFAULT; + PyGIRepository_Type.tp_methods = _PyGIRepository_methods; + if (PyType_Ready (&PyGIRepository_Type)) { return; } + if (PyModule_AddObject (m, "Repository", (PyObject *) &PyGIRepository_Type)) { return; } diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c index 2f1ce42..c2e1f4d 100644 --- a/gi/pygi-struct.c +++ b/gi/pygi-struct.c @@ -25,19 +25,28 @@ #include <pygobject.h> #include <girepository.h> +#include <pyglib-python-compat.h> static void _struct_dealloc (PyGIStruct *self) { + GIBaseInfo *info = _pygi_object_get_gi_info ( + (PyObject *) self, + &PyGIStructInfo_Type); + PyObject_GC_UnTrack ( (PyObject *) self); PyObject_ClearWeakRefs ( (PyObject *) self); - if (self->free_on_dealloc) { + if (info != NULL && g_struct_info_is_foreign ( (GIStructInfo *) info)) { + pygi_struct_foreign_release (info, ( (PyGPointer *) self)->pointer); + } else if (self->free_on_dealloc) { g_free ( ( (PyGPointer *) self)->pointer); } - ( (PyGPointer *) self)->ob_type->tp_free ( (PyObject *) self); + g_base_info_unref (info); + + Py_TYPE( (PyGPointer *) self )->tp_free ( (PyObject *) self); } static PyObject * @@ -48,7 +57,6 @@ _struct_new (PyTypeObject *type, static char *kwlist[] = { NULL }; GIBaseInfo *info; - gboolean is_simple; gsize size; gpointer pointer; PyObject *self = NULL; @@ -92,41 +100,7 @@ _struct_init (PyObject *self, return 0; } - -PyTypeObject PyGIStruct_Type = { - PyObject_HEAD_INIT (NULL) - 0, - "gi.Struct", /* tp_name */ - sizeof (PyGIStruct), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) _struct_dealloc, /* tp_dealloc */ - (printfunc) NULL, /* tp_print */ - (getattrfunc) NULL, /* tp_getattr */ - (setattrfunc) NULL, /* tp_setattr */ - (cmpfunc) NULL, /* tp_compare */ - (reprfunc) NULL, /* tp_repr */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - (hashfunc) NULL, /* tp_hash */ - (ternaryfunc) NULL, /* tp_call */ - (reprfunc) NULL, /* tp_str */ - (getattrofunc) NULL, /* tp_getattro */ - (setattrofunc) NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - NULL, /* tp_doc */ - (traverseproc) NULL, /* tp_traverse */ - (inquiry) NULL, /* tp_clear */ - (richcmpfunc) NULL, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc) NULL, /* tp_iter */ - (iternextfunc) NULL, /* tp_iternext */ - NULL, /* tp_methods */ - NULL, /* tp_members */ - NULL, /* tp_getset */ - (PyTypeObject *) NULL, /* tp_base */ -}; +PYGLIB_DEFINE_TYPE("gi.Struct", PyGIStruct_Type, PyGIStruct); PyObject * _pygi_struct_new (PyTypeObject *type, @@ -158,10 +132,13 @@ _pygi_struct_new (PyTypeObject *type, void _pygi_struct_register_types (PyObject *m) { - PyGIStruct_Type.ob_type = &PyType_Type; + Py_TYPE(&PyGIStruct_Type) = &PyType_Type; PyGIStruct_Type.tp_base = &PyGPointer_Type; PyGIStruct_Type.tp_new = (newfunc) _struct_new; PyGIStruct_Type.tp_init = (initproc) _struct_init; + PyGIStruct_Type.tp_dealloc = (destructor) _struct_dealloc; + PyGIStruct_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); + if (PyType_Ready (&PyGIStruct_Type)) return; if (PyModule_AddObject (m, "Struct", (PyObject *) &PyGIStruct_Type)) diff --git a/gi/pygi-type.c b/gi/pygi-type.c index bd9804e..129ea98 100644 --- a/gi/pygi-type.c +++ b/gi/pygi-type.c @@ -25,17 +25,13 @@ PyObject * -_pygi_type_import_by_gi_info (GIBaseInfo *info) +_pygi_type_import_by_name (const char *namespace_, + const char *name) { - const gchar *namespace_; - const gchar *name; gchar *module_name; PyObject *py_module; PyObject *py_object; - namespace_ = g_base_info_get_namespace (info); - name = g_base_info_get_name (info); - module_name = g_strconcat ("gi.repository.", namespace_, NULL); py_module = PyImport_ImportModule (module_name); @@ -74,6 +70,13 @@ pygi_type_import_by_g_type_real (GType g_type) } PyObject * +_pygi_type_import_by_gi_info (GIBaseInfo *info) +{ + return _pygi_type_import_by_name (g_base_info_get_namespace (info), + g_base_info_get_name (info)); +} + +PyObject * _pygi_type_get_from_g_type (GType g_type) { PyObject *py_g_type; diff --git a/gi/pygi-type.h b/gi/pygi-type.h index 16d5bdc..bb43d19 100644 --- a/gi/pygi-type.h +++ b/gi/pygi-type.h @@ -33,6 +33,8 @@ PyObject *pygi_type_import_by_g_type_real (GType g_type); /* Private */ +PyObject *_pygi_type_import_by_name (const char *namespace_, const char *name); + PyObject *_pygi_type_import_by_gi_info (GIBaseInfo *info); PyObject *_pygi_type_get_from_g_type (GType g_type); @@ -22,6 +22,7 @@ #ifndef __PYGI_H__ #define __PYGI_H__ +#define NO_IMPORT_PYGOBJECT #include <config.h> #include <pygobject.h> @@ -51,23 +52,27 @@ typedef struct { gsize size; } PyGIBoxed; -typedef PyObject * (*PyGIArgOverrideToGArgumentFunc) (PyObject *value, +typedef PyObject * (*PyGIArgOverrideToGIArgumentFunc) (PyObject *value, GITypeInfo *type_info, GITransfer transfer, - GArgument *arg); -typedef PyObject * (*PyGIArgOverrideFromGArgumentFunc) (GITypeInfo *type_info, - GArgument *arg); -typedef PyObject * (*PyGIArgOverrideReleaseGArgumentFunc) (GITransfer transfer, - GITypeInfo *type_info, - GArgument *arg); + GIArgument *arg); +typedef PyObject * (*PyGIArgOverrideFromGIArgumentFunc) (GITypeInfo *type_info, + GIArgument *arg); +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, + const gchar *attr_name); + gint (*set_property_value) (PyGObject *instance, + const gchar *attr_name, + PyObject *value); void (*register_foreign_struct) (const char* namespace_, const char* name, - PyGIArgOverrideToGArgumentFunc to_func, - PyGIArgOverrideFromGArgumentFunc from_func, - PyGIArgOverrideReleaseGArgumentFunc release_func); + PyGIArgOverrideToGIArgumentFunc to_func, + PyGIArgOverrideFromGIArgumentFunc from_func, + PyGIArgOverrideReleaseFunc release_func); }; static struct PyGI_API *PyGI_API = NULL; @@ -97,11 +102,32 @@ pygi_type_import_by_g_type (GType g_type) } static inline PyObject * +pygi_get_property_value (PyGObject *instance, + const gchar *attr_name) +{ + if (_pygi_import() < 0) { + return NULL; + } + return PyGI_API->get_property_value(instance, attr_name); +} + +static inline gint +pygi_set_property_value (PyGObject *instance, + const gchar *attr_name, + PyObject *value) +{ + if (_pygi_import() < 0) { + return -1; + } + return PyGI_API->set_property_value(instance, attr_name, value); +} + +static inline PyObject * pygi_register_foreign_struct (const char* namespace_, const char* name, - PyGIArgOverrideToGArgumentFunc to_func, - PyGIArgOverrideFromGArgumentFunc from_func, - PyGIArgOverrideReleaseGArgumentFunc release_func) + PyGIArgOverrideToGIArgumentFunc to_func, + PyGIArgOverrideFromGIArgumentFunc from_func, + PyGIArgOverrideReleaseFunc release_func) { if (_pygi_import() < 0) { return NULL; @@ -122,6 +148,21 @@ pygi_type_import_by_g_type (GType g_type) return NULL; } +static inline PyObject * +pygi_get_property_value (PyGObject *instance, + const gchar *attr_name) +{ + return -1; +} + +static inline gint +pygi_set_property_value (PyGObject *instance, + const gchar *attr_name, + PyObject *value) +{ + return -1; +} + #endif /* ENABLE_INTROSPECTION */ #endif /* __PYGI_H__ */ diff --git a/gi/repository/Makefile.in b/gi/repository/Makefile.in index 3252c9d..7b36c15 100644 --- a/gi/repository/Makefile.in +++ b/gi/repository/Makefile.in @@ -115,6 +115,7 @@ GIOUNIX_LIBS = @GIOUNIX_LIBS@ GIO_CFLAGS = @GIO_CFLAGS@ GIO_LIBS = @GIO_LIBS@ GI_CFLAGS = @GI_CFLAGS@ +GI_DATADIR = @GI_DATADIR@ GI_LIBS = @GI_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ diff --git a/gi/types.py b/gi/types.py index 8ac9cab..0a8768c 100644 --- a/gi/types.py +++ b/gi/types.py @@ -50,7 +50,7 @@ def Constructor(info): def constructor(cls, *args): cls_name = info.get_container().get_name() if cls.__name__ != cls_name: - raise TypeError, '%s constructor cannot be used to create instances of a subclass' % cls_name + raise TypeError('%s constructor cannot be used to create instances of a subclass' % cls_name) return info.invoke(cls, *args) constructor.__info__ = info @@ -105,10 +105,14 @@ class MetaClassHelper(object): 'the method do_%s()' % (base.__info__.get_namespace(), base.__info__.get_name(), vfunc_info.get_name())) - elif vfunc is not None and not \ - is_function_in_classes(vfunc.im_func, cls.__bases__): - hook_up_vfunc_implementation(vfunc_info, cls.__gtype__, - vfunc) + elif vfunc is not None: + function = vfunc + if sys.version_info < (3, 0): + function = vfunc.im_func + + if not is_function_in_classes(function, cls.__bases__): + hook_up_vfunc_implementation(vfunc_info, cls.__gtype__, + vfunc) def is_function_in_classes(function, classes): for klass in classes: @@ -161,6 +165,7 @@ class StructMeta(type, MetaClassHelper): def override(type_): g_type = type_.__info__.get_g_type() + assert g_type != gobject.TYPE_NONE if g_type != gobject.TYPE_INVALID: g_type.pytype = type_ return type_ |