summaryrefslogtreecommitdiff
path: root/gi
diff options
context:
space:
mode:
Diffstat (limited to 'gi')
-rw-r--r--gi/Makefile.am133
-rw-r--r--gi/Makefile.in1154
-rw-r--r--gi/__init__.py113
-rw-r--r--gi/_constants.py47
-rw-r--r--gi/_error.py55
-rw-r--r--gi/_glib/Makefile.am91
-rw-r--r--gi/_glib/Makefile.in915
-rw-r--r--gi/_glib/__init__.py25
-rw-r--r--gi/_glib/glibmodule.c103
-rw-r--r--gi/_glib/pyglib-private.h49
-rw-r--r--gi/_glib/pyglib-python-compat.h220
-rw-r--r--gi/_glib/pyglib.c475
-rw-r--r--gi/_glib/pyglib.h77
-rw-r--r--gi/_gobject/Makefile.am87
-rw-r--r--gi/_gobject/Makefile.in923
-rw-r--r--gi/_gobject/__init__.py60
-rw-r--r--gi/_gobject/constants.py49
-rw-r--r--gi/_gobject/gobjectmodule.c2220
-rw-r--r--gi/_gobject/pygflags.h27
-rw-r--r--gi/_gobject/pygobject-private.h204
-rw-r--r--gi/_gobject/pygparamspec.c404
-rw-r--r--gi/_gobject/pygtype.c1927
-rw-r--r--gi/_gobject/pygtype.h28
-rw-r--r--gi/_gtktemplate.py307
-rw-r--r--gi/_option.py (renamed from gi/_glib/option.py)113
-rw-r--r--gi/_ossighelper.py239
-rw-r--r--gi/_propertyhelper.py (renamed from gi/_gobject/propertyhelper.py)157
-rw-r--r--gi/_signalhelper.py (renamed from gi/_gobject/signalhelper.py)153
-rw-r--r--gi/docstring.py181
-rw-r--r--gi/gimodule.c2211
-rw-r--r--gi/gimodule.h17
-rw-r--r--gi/importer.py133
-rw-r--r--gi/meson.build91
-rw-r--r--gi/module.py223
-rw-r--r--gi/overrides/GIMarshallingTests.py6
-rw-r--r--gi/overrides/GLib.py569
-rw-r--r--gi/overrides/GObject.py525
-rw-r--r--gi/overrides/Gdk.py547
-rw-r--r--gi/overrides/GdkPixbuf.py53
-rw-r--r--gi/overrides/Gio.py321
-rw-r--r--gi/overrides/Gtk.py1535
-rw-r--r--gi/overrides/Makefile.am23
-rw-r--r--gi/overrides/Makefile.in582
-rw-r--r--gi/overrides/Pango.py22
-rw-r--r--gi/overrides/__init__.py357
-rw-r--r--gi/overrides/keysyms.py1494
-rw-r--r--gi/overrides/meson.build15
-rw-r--r--gi/pygboxed.c (renamed from gi/_gobject/pygboxed.c)162
-rw-r--r--gi/pygboxed.h (renamed from gi/_gobject/pygboxed.h)15
-rw-r--r--gi/pygenum.c (renamed from gi/_gobject/pygenum.c)147
-rw-r--r--gi/pygenum.h47
-rw-r--r--gi/pygflags.c (renamed from gi/_gobject/pygflags.c)155
-rw-r--r--gi/pygflags.h46
-rw-r--r--gi/pygi-argument.c1087
-rw-r--r--gi/pygi-argument.h41
-rw-r--r--gi/pygi-array.c978
-rw-r--r--gi/pygi-array.h43
-rw-r--r--gi/pygi-basictype.c1338
-rw-r--r--gi/pygi-basictype.h89
-rw-r--r--gi/pygi-boxed.c168
-rw-r--r--gi/pygi-boxed.h23
-rw-r--r--gi/pygi-cache.c1867
-rw-r--r--gi/pygi-cache.h255
-rw-r--r--gi/pygi-ccallback.c52
-rw-r--r--gi/pygi-ccallback.h17
-rw-r--r--gi/pygi-closure.c1074
-rw-r--r--gi/pygi-closure.h20
-rw-r--r--gi/pygi-enum-marshal.c407
-rw-r--r--gi/pygi-enum-marshal.h42
-rw-r--r--gi/pygi-error.c374
-rw-r--r--gi/pygi-error.h50
-rw-r--r--gi/pygi-foreign-api.h85
-rw-r--r--gi/pygi-foreign-cairo.c549
-rw-r--r--gi/pygi-foreign.c114
-rw-r--r--gi/pygi-foreign.h23
-rw-r--r--gi/pygi-hashtable.c420
-rw-r--r--gi/pygi-hashtable.h36
-rw-r--r--gi/pygi-info.c1686
-rw-r--r--gi/pygi-info.h28
-rw-r--r--gi/pygi-invoke-state-struct.h64
-rw-r--r--gi/pygi-invoke.c685
-rw-r--r--gi/pygi-invoke.h16
-rw-r--r--gi/pygi-list.c500
-rw-r--r--gi/pygi-list.h39
-rw-r--r--gi/pygi-marshal-cleanup.c523
-rw-r--r--gi/pygi-marshal-cleanup.h65
-rw-r--r--gi/pygi-marshal-from-py.c1870
-rw-r--r--gi/pygi-marshal-from-py.h151
-rw-r--r--gi/pygi-marshal-to-py.c891
-rw-r--r--gi/pygi-marshal-to-py.h104
-rw-r--r--gi/pygi-object.c381
-rw-r--r--gi/pygi-object.h52
-rw-r--r--gi/pygi-private.h87
-rw-r--r--gi/pygi-property.c251
-rw-r--r--gi/pygi-property.h21
-rw-r--r--gi/pygi-repository.c144
-rw-r--r--gi/pygi-repository.h12
-rw-r--r--gi/pygi-resulttuple.c368
-rw-r--r--gi/pygi-resulttuple.h (renamed from gi/_gobject/pygenum.h)27
-rw-r--r--gi/pygi-signal-closure.c107
-rw-r--r--gi/pygi-signal-closure.h17
-rw-r--r--gi/pygi-source.c139
-rw-r--r--gi/pygi-source.h4
-rw-r--r--gi/pygi-struct-marshal.c646
-rw-r--r--gi/pygi-struct-marshal.h69
-rw-r--r--gi/pygi-struct.c177
-rw-r--r--gi/pygi-struct.h23
-rw-r--r--gi/pygi-type.c1367
-rw-r--r--gi/pygi-type.h52
-rw-r--r--gi/pygi-util.c126
-rw-r--r--gi/pygi-util.h56
-rw-r--r--gi/pygi-value.c933
-rw-r--r--gi/pygi-value.h52
-rw-r--r--gi/pygi.h190
-rw-r--r--gi/pyginterface.c (renamed from gi/_gobject/pyginterface.c)70
-rw-r--r--gi/pyginterface.h (renamed from gi/_gobject/pyginterface.h)6
-rw-r--r--gi/pygobject-external.h75
-rw-r--r--gi/pygobject-internal.h7
-rw-r--r--gi/pygobject-object.c (renamed from gi/_gobject/pygobject.c)729
-rw-r--r--gi/pygobject-object.h52
-rw-r--r--gi/pygobject.h (renamed from gi/_gobject/pygobject.h)42
-rw-r--r--gi/pygoptioncontext.c (renamed from gi/_glib/pygoptioncontext.c)88
-rw-r--r--gi/pygoptioncontext.h (renamed from gi/_glib/pygoptioncontext.h)6
-rw-r--r--gi/pygoptiongroup.c (renamed from gi/_glib/pygoptiongroup.c)55
-rw-r--r--gi/pygoptiongroup.h (renamed from gi/_glib/pygoptiongroup.h)9
-rw-r--r--gi/pygparamspec.c423
-rw-r--r--gi/pygparamspec.h (renamed from gi/_gobject/pygparamspec.h)8
-rw-r--r--gi/pygpointer.c (renamed from gi/_gobject/pygpointer.c)71
-rw-r--r--gi/pygpointer.h (renamed from gi/_gobject/pygpointer.h)16
-rw-r--r--gi/pygspawn.c (renamed from gi/_glib/pygspawn.c)92
-rw-r--r--gi/pygspawn.h (renamed from gi/_glib/pygspawn.h)6
-rw-r--r--gi/pygtkcompat.py1
-rw-r--r--gi/repository/Makefile.am16
-rw-r--r--gi/repository/Makefile.in574
-rw-r--r--gi/repository/__init__.py2
-rw-r--r--gi/repository/meson.build5
-rw-r--r--gi/types.py158
137 files changed, 21069 insertions, 22349 deletions
diff --git a/gi/Makefile.am b/gi/Makefile.am
deleted file mode 100644
index fc11ff8..0000000
--- a/gi/Makefile.am
+++ /dev/null
@@ -1,133 +0,0 @@
-SUBDIRS = \
- repository \
- overrides \
- _glib \
- _gobject
-
-extension_cppflags = \
- $(PYTHON_INCLUDES) \
- -DPY_SSIZE_T_CLEAN
-
-extension_ldflags = \
- -module \
- -avoid-version \
- -shrext $(PYTHON_SO)
-
-if OS_WIN32
-# Windows requires Python modules to be explicitly linked to libpython.
-# Extension modules are shared libaries (.dll), but need to be
-# called .pyd for Python to load it as an extension module.
-extension_libadd = \
- $(PYTHON_LIBS)
-
-extension_ldflags += \
- -no-undefined
-endif
-
-pygidir = $(pyexecdir)/gi
-
-pygi_PYTHON = \
- __init__.py \
- types.py \
- module.py \
- importer.py \
- pygtkcompat.py \
- docstring.py
-
-pygi_LTLIBRARIES = _gi.la
-
-_gi_la_SOURCES = \
- pygi-repository.c \
- pygi-repository.h \
- pygi-info.c \
- pygi-info.h \
- pygi-foreign.c \
- pygi-foreign.h \
- pygi-struct.c \
- pygi-struct.h \
- pygi-source.c \
- pygi-source.h \
- pygi-argument.c \
- pygi-argument.h \
- pygi-type.c \
- pygi-type.h \
- pygi-boxed.c \
- pygi-boxed.h \
- pygi-closure.c \
- pygi-closure.h \
- pygi-ccallback.c \
- pygi-ccallback.h \
- pygi.h \
- pygi-private.h \
- pygi-property.c \
- pygi-property.h \
- pygi-signal-closure.c \
- pygi-signal-closure.h \
- pygobject-external.h \
- gimodule.c \
- pygi-invoke.c \
- pygi-invoke.h \
- pygi-invoke-state-struct.h \
- pygi-cache.h \
- pygi-cache.c \
- pygi-marshal-from-py.c \
- pygi-marshal-from-py.h \
- pygi-marshal-to-py.c \
- pygi-marshal-to-py.h \
- pygi-marshal-cleanup.c \
- pygi-marshal-cleanup.h
-_gi_la_CFLAGS = \
- $(GI_CFLAGS)
-_gi_la_CPPFLAGS = \
- $(extension_cppflags) \
- -I$(top_srcdir)/gi/_glib \
- -I$(top_srcdir)/gi/_gobject
-_gi_la_LIBADD = \
- $(extension_libadd) \
- $(GI_LIBS) \
- $(top_builddir)/gi/_glib/libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-_gi_la_LDFLAGS = \
- $(extension_ldflags) \
- -export-symbols-regex "init_gi|PyInit__gi"
-
-if ENABLE_CAIRO
-pygi_LTLIBRARIES += _gi_cairo.la
-endif
-
-_gi_cairo_la_SOURCES = \
- pygi-foreign-cairo.c
-_gi_cairo_la_CFLAGS = \
- $(GI_CFLAGS) \
- $(PYCAIRO_CFLAGS)
-_gi_cairo_la_CPPFLAGS = \
- $(extension_cppflags) \
- -I$(top_srcdir)/gi/_glib \
- -I$(top_srcdir)/gi/_gobject
-_gi_cairo_la_LIBADD = \
- $(extension_libadd) \
- $(GI_LIBS) \
- $(PYCAIRO_LIBS)
-_gi_cairo_la_LDFLAGS = \
- $(extension_ldflags) \
- -export-symbols-regex "init_gi_cairo|PyInit__gi_cairo"
-
-
-# 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.
-%$(PYTHON_SO): %.la
- $(LN_S) -f .libs/$@ $@
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pygi_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-all-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-
-check-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-clean-local:
- rm -f $(LTLIBRARIES:.la=$(PYTHON_SO))
diff --git a/gi/Makefile.in b/gi/Makefile.in
deleted file mode 100644
index abc8c4e..0000000
--- a/gi/Makefile.in
+++ /dev/null
@@ -1,1154 +0,0 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-@OS_WIN32_TRUE@am__append_1 = \
-@OS_WIN32_TRUE@ -no-undefined
-
-@ENABLE_CAIRO_TRUE@am__append_2 = _gi_cairo.la
-subdir = gi
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(top_srcdir)/depcomp $(pygi_PYTHON) $(top_srcdir)/py-compile
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
- $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-am__installdirs = "$(DESTDIR)$(pygidir)" "$(DESTDIR)$(pygidir)"
-LTLIBRARIES = $(pygi_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-@OS_WIN32_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
-_gi_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
- $(top_builddir)/gi/_glib/libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-am__gi_la_OBJECTS = _gi_la-pygi-repository.lo _gi_la-pygi-info.lo \
- _gi_la-pygi-foreign.lo _gi_la-pygi-struct.lo \
- _gi_la-pygi-source.lo _gi_la-pygi-argument.lo \
- _gi_la-pygi-type.lo _gi_la-pygi-boxed.lo \
- _gi_la-pygi-closure.lo _gi_la-pygi-ccallback.lo \
- _gi_la-pygi-property.lo _gi_la-pygi-signal-closure.lo \
- _gi_la-gimodule.lo _gi_la-pygi-invoke.lo _gi_la-pygi-cache.lo \
- _gi_la-pygi-marshal-from-py.lo _gi_la-pygi-marshal-to-py.lo \
- _gi_la-pygi-marshal-cleanup.lo
-_gi_la_OBJECTS = $(am__gi_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 =
-_gi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(_gi_la_CFLAGS) $(CFLAGS) \
- $(_gi_la_LDFLAGS) $(LDFLAGS) -o $@
-_gi_cairo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-am__gi_cairo_la_OBJECTS = _gi_cairo_la-pygi-foreign-cairo.lo
-_gi_cairo_la_OBJECTS = $(am__gi_cairo_la_OBJECTS)
-_gi_cairo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(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)
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
- $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-SOURCES = $(_gi_la_SOURCES) $(_gi_cairo_la_SOURCES)
-DIST_SOURCES = $(_gi_la_SOURCES) $(_gi_cairo_la_SOURCES)
-RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
- ctags-recursive dvi-recursive html-recursive info-recursive \
- install-data-recursive install-dvi-recursive \
- install-exec-recursive install-html-recursive \
- install-info-recursive install-pdf-recursive \
- install-ps-recursive install-recursive installcheck-recursive \
- installdirs-recursive pdf-recursive ps-recursive \
- tags-recursive uninstall-recursive
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile)
-am__pep3147_tweak = \
- sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|'
-py_compile = $(top_srcdir)/py-compile
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
- distclean-recursive maintainer-clean-recursive
-am__recursive_targets = \
- $(RECURSIVE_TARGETS) \
- $(RECURSIVE_CLEAN_TARGETS) \
- $(am__extra_recursive_targets)
-AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
- distdir
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates. Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
- BEGIN { nonempty = 0; } \
- { items[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique. This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
- list='$(am__tagged_files)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DIST_SUBDIRS = $(SUBDIRS)
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-am__relativize = \
- dir0=`pwd`; \
- sed_first='s,^\([^/]*\)/.*$$,\1,'; \
- sed_rest='s,^[^/]*/*,,'; \
- sed_last='s,^.*/\([^/]*\)$$,\1,'; \
- sed_butlast='s,/*[^/]*$$,,'; \
- while test -n "$$dir1"; do \
- first=`echo "$$dir1" | sed -e "$$sed_first"`; \
- if test "$$first" != "."; then \
- if test "$$first" = ".."; then \
- dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
- dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
- else \
- first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
- if test "$$first2" = "$$first"; then \
- dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
- else \
- dir2="../$$dir2"; \
- fi; \
- dir0="$$dir0"/"$$first"; \
- fi; \
- fi; \
- dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
- done; \
- reldir="$$dir2"
-ACLOCAL = @ACLOCAL@
-ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CAIRO_CFLAGS = @CAIRO_CFLAGS@
-CAIRO_LIBS = @CAIRO_LIBS@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
-CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
-CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DATADIR = @DATADIR@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FFI_CFLAGS = @FFI_CFLAGS@
-FFI_LIBS = @FFI_LIBS@
-FGREP = @FGREP@
-GENHTML = @GENHTML@
-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_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
-GLIB_LIBS = @GLIB_LIBS@
-GLIB_MKENUMS = @GLIB_MKENUMS@
-GOBJECT_QUERY = @GOBJECT_QUERY@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
-INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBFFI_PC = @LIBFFI_PC@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLATFORM = @PLATFORM@
-PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@
-PYCAIRO_LIBS = @PYCAIRO_LIBS@
-PYGOBJECT_MAJOR_VERSION = @PYGOBJECT_MAJOR_VERSION@
-PYGOBJECT_MICRO_VERSION = @PYGOBJECT_MICRO_VERSION@
-PYGOBJECT_MINOR_VERSION = @PYGOBJECT_MINOR_VERSION@
-PYTHON = @PYTHON@
-PYTHON_BASENAME = @PYTHON_BASENAME@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_INCLUDES = @PYTHON_INCLUDES@
-PYTHON_LIBS = @PYTHON_LIBS@
-PYTHON_LIB_LOC = @PYTHON_LIB_LOC@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_SO = @PYTHON_SO@
-PYTHON_VERSION = @PYTHON_VERSION@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-THREADING_CFLAGS = @THREADING_CFLAGS@
-VERSION = @VERSION@
-WARN_CFLAGS = @WARN_CFLAGS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-SUBDIRS = \
- repository \
- overrides \
- _glib \
- _gobject
-
-extension_cppflags = \
- $(PYTHON_INCLUDES) \
- -DPY_SSIZE_T_CLEAN
-
-extension_ldflags = -module -avoid-version -shrext $(PYTHON_SO) \
- $(am__append_1)
-
-# Windows requires Python modules to be explicitly linked to libpython.
-# Extension modules are shared libaries (.dll), but need to be
-# called .pyd for Python to load it as an extension module.
-@OS_WIN32_TRUE@extension_libadd = \
-@OS_WIN32_TRUE@ $(PYTHON_LIBS)
-
-pygidir = $(pyexecdir)/gi
-pygi_PYTHON = \
- __init__.py \
- types.py \
- module.py \
- importer.py \
- pygtkcompat.py \
- docstring.py
-
-pygi_LTLIBRARIES = _gi.la $(am__append_2)
-_gi_la_SOURCES = \
- pygi-repository.c \
- pygi-repository.h \
- pygi-info.c \
- pygi-info.h \
- pygi-foreign.c \
- pygi-foreign.h \
- pygi-struct.c \
- pygi-struct.h \
- pygi-source.c \
- pygi-source.h \
- pygi-argument.c \
- pygi-argument.h \
- pygi-type.c \
- pygi-type.h \
- pygi-boxed.c \
- pygi-boxed.h \
- pygi-closure.c \
- pygi-closure.h \
- pygi-ccallback.c \
- pygi-ccallback.h \
- pygi.h \
- pygi-private.h \
- pygi-property.c \
- pygi-property.h \
- pygi-signal-closure.c \
- pygi-signal-closure.h \
- pygobject-external.h \
- gimodule.c \
- pygi-invoke.c \
- pygi-invoke.h \
- pygi-invoke-state-struct.h \
- pygi-cache.h \
- pygi-cache.c \
- pygi-marshal-from-py.c \
- pygi-marshal-from-py.h \
- pygi-marshal-to-py.c \
- pygi-marshal-to-py.h \
- pygi-marshal-cleanup.c \
- pygi-marshal-cleanup.h
-
-_gi_la_CFLAGS = \
- $(GI_CFLAGS)
-
-_gi_la_CPPFLAGS = \
- $(extension_cppflags) \
- -I$(top_srcdir)/gi/_glib \
- -I$(top_srcdir)/gi/_gobject
-
-_gi_la_LIBADD = \
- $(extension_libadd) \
- $(GI_LIBS) \
- $(top_builddir)/gi/_glib/libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-
-_gi_la_LDFLAGS = \
- $(extension_ldflags) \
- -export-symbols-regex "init_gi|PyInit__gi"
-
-_gi_cairo_la_SOURCES = \
- pygi-foreign-cairo.c
-
-_gi_cairo_la_CFLAGS = \
- $(GI_CFLAGS) \
- $(PYCAIRO_CFLAGS)
-
-_gi_cairo_la_CPPFLAGS = \
- $(extension_cppflags) \
- -I$(top_srcdir)/gi/_glib \
- -I$(top_srcdir)/gi/_gobject
-
-_gi_cairo_la_LIBADD = \
- $(extension_libadd) \
- $(GI_LIBS) \
- $(PYCAIRO_LIBS)
-
-_gi_cairo_la_LDFLAGS = \
- $(extension_ldflags) \
- -export-symbols-regex "init_gi_cairo|PyInit__gi_cairo"
-
-all: all-recursive
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign gi/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign gi/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-install-pygiLTLIBRARIES: $(pygi_LTLIBRARIES)
- @$(NORMAL_INSTALL)
- @list='$(pygi_LTLIBRARIES)'; test -n "$(pygidir)" || list=; \
- list2=; for p in $$list; do \
- if test -f $$p; then \
- list2="$$list2 $$p"; \
- else :; fi; \
- done; \
- test -z "$$list2" || { \
- echo " $(MKDIR_P) '$(DESTDIR)$(pygidir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pygidir)" || exit 1; \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pygidir)'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pygidir)"; \
- }
-
-uninstall-pygiLTLIBRARIES:
- @$(NORMAL_UNINSTALL)
- @list='$(pygi_LTLIBRARIES)'; test -n "$(pygidir)" || list=; \
- for p in $$list; do \
- $(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pygidir)/$$f'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pygidir)/$$f"; \
- done
-
-clean-pygiLTLIBRARIES:
- -test -z "$(pygi_LTLIBRARIES)" || rm -f $(pygi_LTLIBRARIES)
- @list='$(pygi_LTLIBRARIES)'; \
- locs=`for p in $$list; do echo $$p; done | \
- sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
- sort -u`; \
- test -z "$$locs" || { \
- echo rm -f $${locs}; \
- rm -f $${locs}; \
- }
-
-_gi.la: $(_gi_la_OBJECTS) $(_gi_la_DEPENDENCIES) $(EXTRA__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) $(EXTRA__gi_cairo_la_DEPENDENCIES)
- $(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)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_cairo_la-pygi-foreign-cairo.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-gimodule.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-argument.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-boxed.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-cache.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-ccallback.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.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-marshal-cleanup.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-marshal-from-py.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-marshal-to-py.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-signal-closure.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gi_la-pygi-source.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@
-
-.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-_gi_la-pygi-repository.lo: pygi-repository.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-repository.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-repository.Tpo -c -o _gi_la-pygi-repository.lo `test -f 'pygi-repository.c' || echo '$(srcdir)/'`pygi-repository.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-repository.Tpo $(DEPDIR)/_gi_la-pygi-repository.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-repository.c' object='_gi_la-pygi-repository.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-repository.lo `test -f 'pygi-repository.c' || echo '$(srcdir)/'`pygi-repository.c
-
-_gi_la-pygi-info.lo: pygi-info.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-info.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-info.Tpo -c -o _gi_la-pygi-info.lo `test -f 'pygi-info.c' || echo '$(srcdir)/'`pygi-info.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-info.Tpo $(DEPDIR)/_gi_la-pygi-info.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-info.c' object='_gi_la-pygi-info.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-info.lo `test -f 'pygi-info.c' || echo '$(srcdir)/'`pygi-info.c
-
-_gi_la-pygi-foreign.lo: pygi-foreign.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-foreign.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-foreign.Tpo -c -o _gi_la-pygi-foreign.lo `test -f 'pygi-foreign.c' || echo '$(srcdir)/'`pygi-foreign.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-foreign.Tpo $(DEPDIR)/_gi_la-pygi-foreign.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-foreign.c' object='_gi_la-pygi-foreign.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_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-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) $(_gi_la_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
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-struct.c' object='_gi_la-pygi-struct.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-struct.lo `test -f 'pygi-struct.c' || echo '$(srcdir)/'`pygi-struct.c
-
-_gi_la-pygi-source.lo: pygi-source.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-source.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-source.Tpo -c -o _gi_la-pygi-source.lo `test -f 'pygi-source.c' || echo '$(srcdir)/'`pygi-source.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-source.Tpo $(DEPDIR)/_gi_la-pygi-source.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-source.c' object='_gi_la-pygi-source.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-source.lo `test -f 'pygi-source.c' || echo '$(srcdir)/'`pygi-source.c
-
-_gi_la-pygi-argument.lo: pygi-argument.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-argument.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-argument.Tpo -c -o _gi_la-pygi-argument.lo `test -f 'pygi-argument.c' || echo '$(srcdir)/'`pygi-argument.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-argument.Tpo $(DEPDIR)/_gi_la-pygi-argument.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-argument.c' object='_gi_la-pygi-argument.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-argument.lo `test -f 'pygi-argument.c' || echo '$(srcdir)/'`pygi-argument.c
-
-_gi_la-pygi-type.lo: pygi-type.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-type.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-type.Tpo -c -o _gi_la-pygi-type.lo `test -f 'pygi-type.c' || echo '$(srcdir)/'`pygi-type.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-type.Tpo $(DEPDIR)/_gi_la-pygi-type.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-type.c' object='_gi_la-pygi-type.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-type.lo `test -f 'pygi-type.c' || echo '$(srcdir)/'`pygi-type.c
-
-_gi_la-pygi-boxed.lo: pygi-boxed.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-boxed.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-boxed.Tpo -c -o _gi_la-pygi-boxed.lo `test -f 'pygi-boxed.c' || echo '$(srcdir)/'`pygi-boxed.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-boxed.Tpo $(DEPDIR)/_gi_la-pygi-boxed.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-boxed.c' object='_gi_la-pygi-boxed.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-boxed.lo `test -f 'pygi-boxed.c' || echo '$(srcdir)/'`pygi-boxed.c
-
-_gi_la-pygi-closure.lo: pygi-closure.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-closure.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-closure.Tpo -c -o _gi_la-pygi-closure.lo `test -f 'pygi-closure.c' || echo '$(srcdir)/'`pygi-closure.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-closure.Tpo $(DEPDIR)/_gi_la-pygi-closure.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-closure.c' object='_gi_la-pygi-closure.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-closure.lo `test -f 'pygi-closure.c' || echo '$(srcdir)/'`pygi-closure.c
-
-_gi_la-pygi-ccallback.lo: pygi-ccallback.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-ccallback.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-ccallback.Tpo -c -o _gi_la-pygi-ccallback.lo `test -f 'pygi-ccallback.c' || echo '$(srcdir)/'`pygi-ccallback.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-ccallback.Tpo $(DEPDIR)/_gi_la-pygi-ccallback.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-ccallback.c' object='_gi_la-pygi-ccallback.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-ccallback.lo `test -f 'pygi-ccallback.c' || echo '$(srcdir)/'`pygi-ccallback.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) $(_gi_la_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
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)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@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_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-pygi-signal-closure.lo: pygi-signal-closure.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-signal-closure.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-signal-closure.Tpo -c -o _gi_la-pygi-signal-closure.lo `test -f 'pygi-signal-closure.c' || echo '$(srcdir)/'`pygi-signal-closure.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-signal-closure.Tpo $(DEPDIR)/_gi_la-pygi-signal-closure.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-signal-closure.c' object='_gi_la-pygi-signal-closure.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-signal-closure.lo `test -f 'pygi-signal-closure.c' || echo '$(srcdir)/'`pygi-signal-closure.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) $(_gi_la_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
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gimodule.c' object='_gi_la-gimodule.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-gimodule.lo `test -f 'gimodule.c' || echo '$(srcdir)/'`gimodule.c
-
-_gi_la-pygi-invoke.lo: pygi-invoke.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-invoke.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-invoke.Tpo -c -o _gi_la-pygi-invoke.lo `test -f 'pygi-invoke.c' || echo '$(srcdir)/'`pygi-invoke.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-invoke.Tpo $(DEPDIR)/_gi_la-pygi-invoke.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-invoke.c' object='_gi_la-pygi-invoke.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-invoke.lo `test -f 'pygi-invoke.c' || echo '$(srcdir)/'`pygi-invoke.c
-
-_gi_la-pygi-cache.lo: pygi-cache.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-cache.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-cache.Tpo -c -o _gi_la-pygi-cache.lo `test -f 'pygi-cache.c' || echo '$(srcdir)/'`pygi-cache.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-cache.Tpo $(DEPDIR)/_gi_la-pygi-cache.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-cache.c' object='_gi_la-pygi-cache.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-cache.lo `test -f 'pygi-cache.c' || echo '$(srcdir)/'`pygi-cache.c
-
-_gi_la-pygi-marshal-from-py.lo: pygi-marshal-from-py.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-marshal-from-py.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-marshal-from-py.Tpo -c -o _gi_la-pygi-marshal-from-py.lo `test -f 'pygi-marshal-from-py.c' || echo '$(srcdir)/'`pygi-marshal-from-py.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-marshal-from-py.Tpo $(DEPDIR)/_gi_la-pygi-marshal-from-py.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-marshal-from-py.c' object='_gi_la-pygi-marshal-from-py.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-marshal-from-py.lo `test -f 'pygi-marshal-from-py.c' || echo '$(srcdir)/'`pygi-marshal-from-py.c
-
-_gi_la-pygi-marshal-to-py.lo: pygi-marshal-to-py.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-marshal-to-py.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-marshal-to-py.Tpo -c -o _gi_la-pygi-marshal-to-py.lo `test -f 'pygi-marshal-to-py.c' || echo '$(srcdir)/'`pygi-marshal-to-py.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-marshal-to-py.Tpo $(DEPDIR)/_gi_la-pygi-marshal-to-py.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-marshal-to-py.c' object='_gi_la-pygi-marshal-to-py.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-marshal-to-py.lo `test -f 'pygi-marshal-to-py.c' || echo '$(srcdir)/'`pygi-marshal-to-py.c
-
-_gi_la-pygi-marshal-cleanup.lo: pygi-marshal-cleanup.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -MT _gi_la-pygi-marshal-cleanup.lo -MD -MP -MF $(DEPDIR)/_gi_la-pygi-marshal-cleanup.Tpo -c -o _gi_la-pygi-marshal-cleanup.lo `test -f 'pygi-marshal-cleanup.c' || echo '$(srcdir)/'`pygi-marshal-cleanup.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_la-pygi-marshal-cleanup.Tpo $(DEPDIR)/_gi_la-pygi-marshal-cleanup.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-marshal-cleanup.c' object='_gi_la-pygi-marshal-cleanup.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_la_CPPFLAGS) $(CPPFLAGS) $(_gi_la_CFLAGS) $(CFLAGS) -c -o _gi_la-pygi-marshal-cleanup.lo `test -f 'pygi-marshal-cleanup.c' || echo '$(srcdir)/'`pygi-marshal-cleanup.c
-
-_gi_cairo_la-pygi-foreign-cairo.lo: pygi-foreign-cairo.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_cairo_la_CPPFLAGS) $(CPPFLAGS) $(_gi_cairo_la_CFLAGS) $(CFLAGS) -MT _gi_cairo_la-pygi-foreign-cairo.lo -MD -MP -MF $(DEPDIR)/_gi_cairo_la-pygi-foreign-cairo.Tpo -c -o _gi_cairo_la-pygi-foreign-cairo.lo `test -f 'pygi-foreign-cairo.c' || echo '$(srcdir)/'`pygi-foreign-cairo.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gi_cairo_la-pygi-foreign-cairo.Tpo $(DEPDIR)/_gi_cairo_la-pygi-foreign-cairo.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygi-foreign-cairo.c' object='_gi_cairo_la-pygi-foreign-cairo.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_gi_cairo_la_CPPFLAGS) $(CPPFLAGS) $(_gi_cairo_la_CFLAGS) $(CFLAGS) -c -o _gi_cairo_la-pygi-foreign-cairo.lo `test -f 'pygi-foreign-cairo.c' || echo '$(srcdir)/'`pygi-foreign-cairo.c
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-pygiPYTHON: $(pygi_PYTHON)
- @$(NORMAL_INSTALL)
- @list='$(pygi_PYTHON)'; dlist=; list2=; test -n "$(pygidir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(pygidir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pygidir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \
- if test -f $$b$$p; then \
- $(am__strip_dir) \
- dlist="$$dlist $$f"; \
- list2="$$list2 $$b$$p"; \
- else :; fi; \
- done; \
- for file in $$list2; do echo $$file; done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pygidir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(pygidir)" || exit $$?; \
- done || exit $$?; \
- if test -n "$$dlist"; then \
- $(am__py_compile) --destdir "$(DESTDIR)" \
- --basedir "$(pygidir)" $$dlist; \
- else :; fi
-
-uninstall-pygiPYTHON:
- @$(NORMAL_UNINSTALL)
- @list='$(pygi_PYTHON)'; test -n "$(pygidir)" || list=; \
- py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$py_files" || exit 0; \
- dir='$(DESTDIR)$(pygidir)'; \
- pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \
- pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \
- py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \
- echo "$$py_files_pep3147";\
- pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \
- pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \
- st=0; \
- for files in \
- "$$py_files" \
- "$$pyc_files" \
- "$$pyo_files" \
- "$$pyc_files_pep3147" \
- "$$pyo_files_pep3147" \
- ; do \
- $(am__uninstall_files_from_dir) || st=$$?; \
- done; \
- exit $$st
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run 'make' without going through this Makefile.
-# To change the values of 'make' variables: instead of editing Makefiles,
-# (1) if the variable is set in 'config.status', edit 'config.status'
-# (which will cause the Makefiles to be regenerated when you run 'make');
-# (2) otherwise, pass the desired values on the 'make' command line.
-$(am__recursive_targets):
- @fail=; \
- if $(am__make_keepgoing); then \
- failcom='fail=yes'; \
- else \
- failcom='exit 1'; \
- fi; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- for subdir in $$list; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- dot_seen=yes; \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done; \
- if test "$$dot_seen" = "no"; then \
- $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
- fi; test -z "$$fail"
-
-ID: $(am__tagged_files)
- $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-recursive
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- set x; \
- here=`pwd`; \
- if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
- include_option=--etags-include; \
- empty_fix=.; \
- else \
- include_option=--include; \
- empty_fix=; \
- fi; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test ! -f $$subdir/TAGS || \
- set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
- fi; \
- done; \
- $(am__define_uniq_tagged_files); \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: ctags-recursive
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-recursive
-
-cscopelist-am: $(am__tagged_files)
- list='$(am__tagged_files)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- $(am__make_dryrun) \
- || test -d "$(distdir)/$$subdir" \
- || $(MKDIR_P) "$(distdir)/$$subdir" \
- || exit 1; \
- dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
- $(am__relativize); \
- new_distdir=$$reldir; \
- dir1=$$subdir; dir2="$(top_distdir)"; \
- $(am__relativize); \
- new_top_distdir=$$reldir; \
- echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
- echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
- ($(am__cd) $$subdir && \
- $(MAKE) $(AM_MAKEFLAGS) \
- top_distdir="$$new_top_distdir" \
- distdir="$$new_distdir" \
- am__remove_distdir=: \
- am__skip_length_check=: \
- am__skip_mode_fix=: \
- distdir) \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) check-local
-check: check-recursive
-all-am: Makefile $(LTLIBRARIES) all-local
-installdirs: installdirs-recursive
-installdirs-am:
- for dir in "$(DESTDIR)$(pygidir)" "$(DESTDIR)$(pygidir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-recursive
-
-clean-am: clean-generic clean-libtool clean-local \
- clean-pygiLTLIBRARIES mostlyclean-am
-
-distclean: distclean-recursive
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info: info-recursive
-
-info-am:
-
-install-data-am: install-pygiLTLIBRARIES install-pygiPYTHON
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-recursive
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am: uninstall-pygiLTLIBRARIES uninstall-pygiPYTHON
-
-.MAKE: $(am__recursive_targets) check-am install-am install-strip
-
-.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \
- check check-am check-local clean clean-generic clean-libtool \
- clean-local clean-pygiLTLIBRARIES cscopelist-am ctags ctags-am \
- distclean distclean-compile distclean-generic \
- distclean-libtool distclean-tags distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-pdf install-pdf-am \
- install-ps install-ps-am install-pygiLTLIBRARIES \
- install-pygiPYTHON install-strip installcheck installcheck-am \
- installdirs installdirs-am maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags tags-am uninstall 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.
-%$(PYTHON_SO): %.la
- $(LN_S) -f .libs/$@ $@
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pygi_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-all-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-
-check-local: $(LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-clean-local:
- rm -f $(LTLIBRARIES:.la=$(PYTHON_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.
-.NOEXPORT:
diff --git a/gi/__init__.py b/gi/__init__.py
index 0645d44..3454790 100644
--- a/gi/__init__.py
+++ b/gi/__init__.py
@@ -18,32 +18,63 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-from __future__ import absolute_import
-
# support overrides in different directories than our gi module
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
+import sys
+import os
+import importlib
+import types
+
+_static_binding_error = ('When using gi.repository you must not import static '
+ 'modules like "gobject". Please change all occurrences '
+ 'of "import gobject" to "from gi.repository import GObject". '
+ 'See: https://bugzilla.gnome.org/show_bug.cgi?id=709183')
+
+# we can't have pygobject 2 loaded at the same time we load the internal _gobject
+if 'gobject' in sys.modules:
+ raise ImportError(_static_binding_error)
+
+
+from . import _gi
from ._gi import _API
from ._gi import Repository
from ._gi import PyGIDeprecationWarning
-
-# Force loading the GObject typelib so we have available the wrappers for
-# base classes such as GInitiallyUnowned
-import gi._gobject
-gi # pyflakes
+from ._gi import PyGIWarning
_API = _API # pyflakes
PyGIDeprecationWarning = PyGIDeprecationWarning
-
-import os
+PyGIWarning = PyGIWarning
_versions = {}
_overridesdir = os.path.join(os.path.dirname(__file__), 'overrides')
-version_info = gi._gobject.pygobject_version[:]
+# Needed for compatibility with "pygobject.h"/pygobject_init()
+_gobject = types.ModuleType("gi._gobject")
+sys.modules[_gobject.__name__] = _gobject
+_gobject._PyGObject_API = _gi._PyGObject_API
+_gobject.pygobject_version = _gi.pygobject_version
+
+version_info = _gi.pygobject_version[:]
__version__ = "{0}.{1}.{2}".format(*version_info)
+_gi.register_foreign()
+
+
+class _DummyStaticModule(types.ModuleType):
+ __path__ = None
+
+ def __getattr__(self, name):
+ raise AttributeError(_static_binding_error)
+
+
+sys.modules['glib'] = _DummyStaticModule('glib', _static_binding_error)
+sys.modules['gobject'] = _DummyStaticModule('gobject', _static_binding_error)
+sys.modules['gio'] = _DummyStaticModule('gio', _static_binding_error)
+sys.modules['gtk'] = _DummyStaticModule('gtk', _static_binding_error)
+sys.modules['gtk.gdk'] = _DummyStaticModule('gtk.gdk', _static_binding_error)
+
def check_version(version):
if isinstance(version, str):
@@ -59,8 +90,27 @@ def check_version(version):
def require_version(namespace, version):
+ """ Ensures the correct versions are loaded when importing `gi` modules.
+
+ :param namespace: The name of module to require.
+ :type namespace: str
+ :param version: The version of module to require.
+ :type version: str
+ :raises ValueError: If module/version is already loaded, already required, or unavailable.
+
+ :Example:
+
+ .. code-block:: python
+
+ import gi
+ gi.require_version('Gtk', '3.0')
+
+ """
repository = Repository.get_default()
+ if not isinstance(version, str):
+ raise ValueError('Namespace version needs to be a string.')
+
if namespace in repository.get_loaded_namespaces():
loaded_version = repository.get_version(namespace)
if loaded_version != version:
@@ -82,5 +132,48 @@ def require_version(namespace, version):
_versions[namespace] = version
+def require_versions(requires):
+ """ Utility function for consolidating multiple `gi.require_version()` calls.
+
+ :param requires: The names and versions of modules to require.
+ :type requires: dict
+
+ :Example:
+
+ .. code-block:: python
+
+ import gi
+ gi.require_versions({'Gtk': '3.0', 'GLib': '2.0', 'Gio': '2.0'})
+ """
+ for module_name, module_version in requires.items():
+ require_version(module_name, module_version)
+
+
def get_required_version(namespace):
return _versions.get(namespace, None)
+
+
+def require_foreign(namespace, symbol=None):
+ """Ensure the given foreign marshaling module is available and loaded.
+
+ :param str namespace:
+ Introspection namespace of the foreign module (e.g. "cairo")
+ :param symbol:
+ Optional symbol typename to ensure a converter exists.
+ :type symbol: str or None
+ :raises: ImportError
+
+ :Example:
+
+ .. code-block:: python
+
+ import gi
+ import cairo
+ gi.require_foreign('cairo')
+
+ """
+ try:
+ _gi.require_foreign(namespace, symbol)
+ except Exception as e:
+ raise ImportError(str(e))
+ importlib.import_module('gi.repository', namespace)
diff --git a/gi/_constants.py b/gi/_constants.py
new file mode 100644
index 0000000..6fca96b
--- /dev/null
+++ b/gi/_constants.py
@@ -0,0 +1,47 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# pygobject - Python bindings for the GObject library
+# Copyright (C) 2006-2007 Johan Dahlin
+#
+# gi/_constants.py: GObject type constants
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+from . import _gi
+
+TYPE_INVALID = _gi.TYPE_INVALID
+TYPE_NONE = _gi.GType.from_name('void')
+TYPE_INTERFACE = _gi.GType.from_name('GInterface')
+TYPE_CHAR = _gi.GType.from_name('gchar')
+TYPE_UCHAR = _gi.GType.from_name('guchar')
+TYPE_BOOLEAN = _gi.GType.from_name('gboolean')
+TYPE_INT = _gi.GType.from_name('gint')
+TYPE_UINT = _gi.GType.from_name('guint')
+TYPE_LONG = _gi.GType.from_name('glong')
+TYPE_ULONG = _gi.GType.from_name('gulong')
+TYPE_INT64 = _gi.GType.from_name('gint64')
+TYPE_UINT64 = _gi.GType.from_name('guint64')
+TYPE_ENUM = _gi.GType.from_name('GEnum')
+TYPE_FLAGS = _gi.GType.from_name('GFlags')
+TYPE_FLOAT = _gi.GType.from_name('gfloat')
+TYPE_DOUBLE = _gi.GType.from_name('gdouble')
+TYPE_STRING = _gi.GType.from_name('gchararray')
+TYPE_POINTER = _gi.GType.from_name('gpointer')
+TYPE_BOXED = _gi.GType.from_name('GBoxed')
+TYPE_PARAM = _gi.GType.from_name('GParam')
+TYPE_OBJECT = _gi.GType.from_name('GObject')
+TYPE_PYOBJECT = _gi.GType.from_name('PyObject')
+TYPE_GTYPE = _gi.GType.from_name('GType')
+TYPE_STRV = _gi.GType.from_name('GStrv')
+TYPE_VARIANT = _gi.GType.from_name('GVariant')
+TYPE_UNICHAR = TYPE_UINT
diff --git a/gi/_error.py b/gi/_error.py
new file mode 100644
index 0000000..6440ef7
--- /dev/null
+++ b/gi/_error.py
@@ -0,0 +1,55 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# vim: tabstop=4 shiftwidth=4 expandtab
+#
+# Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+#
+# _error.py: GError Python implementation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+# USA
+
+
+# NOTE: This file should not have any dependencies on introspection libs
+# like gi.repository.GLib because it would cause a circular dependency.
+# Developers wanting to use the GError class in their applications should
+# use gi.repository.GLib.GError
+
+
+class GError(RuntimeError):
+ def __init__(self, message='unknown error', domain='pygi-error', code=0):
+ super(GError, self).__init__(message)
+ self.message = message
+ self.domain = domain
+ self.code = code
+
+ def __str__(self):
+ return "%s: %s (%d)" % (self.domain, self.message, self.code)
+
+ def __repr__(self):
+ return "%s.%s('%s', '%s', %d)" % (
+ GError.__module__.rsplit(".", 1)[-1], GError.__name__,
+ self.message, self.domain, self.code)
+
+ def copy(self):
+ return GError(self.message, self.domain, self.code)
+
+ def matches(self, domain, code):
+ """Placeholder that will be monkey patched in GLib overrides."""
+ raise NotImplementedError
+
+ @staticmethod
+ def new_literal(domain, message, code):
+ """Placeholder that will be monkey patched in GLib overrides."""
+ raise NotImplementedError
diff --git a/gi/_glib/Makefile.am b/gi/_glib/Makefile.am
deleted file mode 100644
index 774b7e1..0000000
--- a/gi/_glib/Makefile.am
+++ /dev/null
@@ -1,91 +0,0 @@
-AUTOMAKE_OPTIONS = 1.7
-
-extension_cppflags = \
- $(PYTHON_INCLUDES) \
- -DPY_SSIZE_T_CLEAN
-
-extension_ldflags = \
- -module \
- -avoid-version \
- -shrext $(PYTHON_SO)
-
-if OS_WIN32
-# Windows requires Python modules to be explicitly linked to libpython.
-# Extension modules are shared libaries (.dll), but need to be
-# called .pyd for Python to load it as an extension module.
-extension_libadd = \
- $(PYTHON_LIBS)
-
-extension_ldflags += \
- -no-undefined
-endif
-
-
-pyglibdir = $(pyexecdir)/gi/_glib
-
-pyglib_PYTHON = \
- __init__.py \
- option.py
-
-lib_LTLIBRARIES = libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_SOURCES = \
- pyglib.c \
- pyglib.h \
- pyglib-private.h \
- pyglib-python-compat.h
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CPPFLAGS = \
- $(extension_cppflags)
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CFLAGS = \
- $(GLIB_CFLAGS)
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_LIBADD = \
- $(extension_libadd) \
- $(FFI_LIBS) \
- $(GLIB_LIBS)
-
-if OS_WIN32
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_LDFLAGS = \
- -no-undefined
-endif
-
-pyglib_LTLIBRARIES = _glib.la
-
-_glib_la_SOURCES = \
- glibmodule.c \
- pygoptioncontext.c \
- pygoptioncontext.h \
- pygoptiongroup.c \
- pygoptiongroup.h \
- pygspawn.c \
- pygspawn.h
-_glib_la_CFLAGS = \
- $(GLIB_CFLAGS)
-_glib_la_CPPFLAGS = \
- $(extension_cppflags)
-_glib_la_LIBADD = \
- $(extension_libadd) \
- $(GLIB_LIBS) \
- libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-_glib_la_LDFLAGS = \
- $(extension_ldflags) \
- -export-symbols-regex "_glib|PyInit__glib"
-
-if PLATFORM_WIN32
-_glib_la_CFLAGS += -DPLATFORM_WIN32
-endif
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pyglib_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-
-all: $(pyglib_LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-check-local: $(pyglib_LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-clean-local:
- rm -f $(pyglib_LTLIBRARIES:.la=$(PYTHON_SO))
-%$(PYTHON_SO): %.la
- $(LN_S) -f .libs/$@ $@
diff --git a/gi/_glib/Makefile.in b/gi/_glib/Makefile.in
deleted file mode 100644
index b08e8f1..0000000
--- a/gi/_glib/Makefile.in
+++ /dev/null
@@ -1,915 +0,0 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-@OS_WIN32_TRUE@am__append_1 = \
-@OS_WIN32_TRUE@ -no-undefined
-
-@PLATFORM_WIN32_TRUE@am__append_2 = -DPLATFORM_WIN32
-subdir = gi/_glib
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(top_srcdir)/depcomp $(pyglib_PYTHON) \
- $(top_srcdir)/py-compile
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
- $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pyglibdir)" \
- "$(DESTDIR)$(pyglibdir)"
-LTLIBRARIES = $(lib_LTLIBRARIES) $(pyglib_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-@OS_WIN32_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
-_glib_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
- libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-am__glib_la_OBJECTS = _glib_la-glibmodule.lo \
- _glib_la-pygoptioncontext.lo _glib_la-pygoptiongroup.lo \
- _glib_la-pygspawn.lo
-_glib_la_OBJECTS = $(am__glib_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 =
-_glib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(_glib_la_CFLAGS) \
- $(CFLAGS) $(_glib_la_LDFLAGS) $(LDFLAGS) -o $@
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_DEPENDENCIES = \
- $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
-am_libpyglib_gi_2_0_@PYTHON_BASENAME@_la_OBJECTS = \
- libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.lo
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_OBJECTS = \
- $(am_libpyglib_gi_2_0_@PYTHON_BASENAME@_la_OBJECTS)
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_LINK = $(LIBTOOL) $(AM_V_lt) \
- --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
- $(CCLD) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CFLAGS) \
- $(CFLAGS) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_LDFLAGS) \
- $(LDFLAGS) -o $@
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
- $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-SOURCES = $(_glib_la_SOURCES) \
- $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_SOURCES)
-DIST_SOURCES = $(_glib_la_SOURCES) \
- $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_SOURCES)
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile)
-am__pep3147_tweak = \
- sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|'
-py_compile = $(top_srcdir)/py-compile
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates. Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
- BEGIN { nonempty = 0; } \
- { items[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique. This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
- list='$(am__tagged_files)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CAIRO_CFLAGS = @CAIRO_CFLAGS@
-CAIRO_LIBS = @CAIRO_LIBS@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
-CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
-CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DATADIR = @DATADIR@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FFI_CFLAGS = @FFI_CFLAGS@
-FFI_LIBS = @FFI_LIBS@
-FGREP = @FGREP@
-GENHTML = @GENHTML@
-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_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
-GLIB_LIBS = @GLIB_LIBS@
-GLIB_MKENUMS = @GLIB_MKENUMS@
-GOBJECT_QUERY = @GOBJECT_QUERY@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
-INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBFFI_PC = @LIBFFI_PC@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLATFORM = @PLATFORM@
-PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@
-PYCAIRO_LIBS = @PYCAIRO_LIBS@
-PYGOBJECT_MAJOR_VERSION = @PYGOBJECT_MAJOR_VERSION@
-PYGOBJECT_MICRO_VERSION = @PYGOBJECT_MICRO_VERSION@
-PYGOBJECT_MINOR_VERSION = @PYGOBJECT_MINOR_VERSION@
-PYTHON = @PYTHON@
-PYTHON_BASENAME = @PYTHON_BASENAME@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_INCLUDES = @PYTHON_INCLUDES@
-PYTHON_LIBS = @PYTHON_LIBS@
-PYTHON_LIB_LOC = @PYTHON_LIB_LOC@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_SO = @PYTHON_SO@
-PYTHON_VERSION = @PYTHON_VERSION@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-THREADING_CFLAGS = @THREADING_CFLAGS@
-VERSION = @VERSION@
-WARN_CFLAGS = @WARN_CFLAGS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-AUTOMAKE_OPTIONS = 1.7
-extension_cppflags = \
- $(PYTHON_INCLUDES) \
- -DPY_SSIZE_T_CLEAN
-
-extension_ldflags = -module -avoid-version -shrext $(PYTHON_SO) \
- $(am__append_1)
-
-# Windows requires Python modules to be explicitly linked to libpython.
-# Extension modules are shared libaries (.dll), but need to be
-# called .pyd for Python to load it as an extension module.
-@OS_WIN32_TRUE@extension_libadd = \
-@OS_WIN32_TRUE@ $(PYTHON_LIBS)
-
-pyglibdir = $(pyexecdir)/gi/_glib
-pyglib_PYTHON = \
- __init__.py \
- option.py
-
-lib_LTLIBRARIES = libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_SOURCES = \
- pyglib.c \
- pyglib.h \
- pyglib-private.h \
- pyglib-python-compat.h
-
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CPPFLAGS = \
- $(extension_cppflags)
-
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CFLAGS = \
- $(GLIB_CFLAGS)
-
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la_LIBADD = \
- $(extension_libadd) \
- $(FFI_LIBS) \
- $(GLIB_LIBS)
-
-@OS_WIN32_TRUE@libpyglib_gi_2_0_@PYTHON_BASENAME@_la_LDFLAGS = \
-@OS_WIN32_TRUE@ -no-undefined
-
-pyglib_LTLIBRARIES = _glib.la
-_glib_la_SOURCES = \
- glibmodule.c \
- pygoptioncontext.c \
- pygoptioncontext.h \
- pygoptiongroup.c \
- pygoptiongroup.h \
- pygspawn.c \
- pygspawn.h
-
-_glib_la_CFLAGS = $(GLIB_CFLAGS) $(am__append_2)
-_glib_la_CPPFLAGS = \
- $(extension_cppflags)
-
-_glib_la_LIBADD = \
- $(extension_libadd) \
- $(GLIB_LIBS) \
- libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-
-_glib_la_LDFLAGS = \
- $(extension_ldflags) \
- -export-symbols-regex "_glib|PyInit__glib"
-
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign gi/_glib/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign gi/_glib/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-install-libLTLIBRARIES: $(lib_LTLIBRARIES)
- @$(NORMAL_INSTALL)
- @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
- list2=; for p in $$list; do \
- if test -f $$p; then \
- list2="$$list2 $$p"; \
- else :; fi; \
- done; \
- test -z "$$list2" || { \
- echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
- }
-
-uninstall-libLTLIBRARIES:
- @$(NORMAL_UNINSTALL)
- @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
- for p in $$list; do \
- $(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
- done
-
-clean-libLTLIBRARIES:
- -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
- @list='$(lib_LTLIBRARIES)'; \
- locs=`for p in $$list; do echo $$p; done | \
- sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
- sort -u`; \
- test -z "$$locs" || { \
- echo rm -f $${locs}; \
- rm -f $${locs}; \
- }
-
-install-pyglibLTLIBRARIES: $(pyglib_LTLIBRARIES)
- @$(NORMAL_INSTALL)
- @list='$(pyglib_LTLIBRARIES)'; test -n "$(pyglibdir)" || list=; \
- list2=; for p in $$list; do \
- if test -f $$p; then \
- list2="$$list2 $$p"; \
- else :; fi; \
- done; \
- test -z "$$list2" || { \
- echo " $(MKDIR_P) '$(DESTDIR)$(pyglibdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pyglibdir)" || exit 1; \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pyglibdir)'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pyglibdir)"; \
- }
-
-uninstall-pyglibLTLIBRARIES:
- @$(NORMAL_UNINSTALL)
- @list='$(pyglib_LTLIBRARIES)'; test -n "$(pyglibdir)" || list=; \
- for p in $$list; do \
- $(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pyglibdir)/$$f'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pyglibdir)/$$f"; \
- done
-
-clean-pyglibLTLIBRARIES:
- -test -z "$(pyglib_LTLIBRARIES)" || rm -f $(pyglib_LTLIBRARIES)
- @list='$(pyglib_LTLIBRARIES)'; \
- locs=`for p in $$list; do echo $$p; done | \
- sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
- sort -u`; \
- test -z "$$locs" || { \
- echo rm -f $${locs}; \
- rm -f $${locs}; \
- }
-
-_glib.la: $(_glib_la_OBJECTS) $(_glib_la_DEPENDENCIES) $(EXTRA__glib_la_DEPENDENCIES)
- $(AM_V_CCLD)$(_glib_la_LINK) -rpath $(pyglibdir) $(_glib_la_OBJECTS) $(_glib_la_LIBADD) $(LIBS)
-
-libpyglib-gi-2.0-@PYTHON_BASENAME@.la: $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_OBJECTS) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_DEPENDENCIES) $(EXTRA_libpyglib_gi_2_0_@PYTHON_BASENAME@_la_DEPENDENCIES)
- $(AM_V_CCLD)$(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_LINK) -rpath $(libdir) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_OBJECTS) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-glibmodule.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygoptioncontext.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygoptiongroup.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_glib_la-pygspawn.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.Plo@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-_glib_la-glibmodule.lo: glibmodule.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_glib_la_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-glibmodule.lo -MD -MP -MF $(DEPDIR)/_glib_la-glibmodule.Tpo -c -o _glib_la-glibmodule.lo `test -f 'glibmodule.c' || echo '$(srcdir)/'`glibmodule.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_glib_la-glibmodule.Tpo $(DEPDIR)/_glib_la-glibmodule.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='glibmodule.c' object='_glib_la-glibmodule.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_glib_la_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-glibmodule.lo `test -f 'glibmodule.c' || echo '$(srcdir)/'`glibmodule.c
-
-_glib_la-pygoptioncontext.lo: pygoptioncontext.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_glib_la_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygoptioncontext.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygoptioncontext.Tpo -c -o _glib_la-pygoptioncontext.lo `test -f 'pygoptioncontext.c' || echo '$(srcdir)/'`pygoptioncontext.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_glib_la-pygoptioncontext.Tpo $(DEPDIR)/_glib_la-pygoptioncontext.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygoptioncontext.c' object='_glib_la-pygoptioncontext.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_glib_la_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygoptioncontext.lo `test -f 'pygoptioncontext.c' || echo '$(srcdir)/'`pygoptioncontext.c
-
-_glib_la-pygoptiongroup.lo: pygoptiongroup.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_glib_la_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygoptiongroup.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygoptiongroup.Tpo -c -o _glib_la-pygoptiongroup.lo `test -f 'pygoptiongroup.c' || echo '$(srcdir)/'`pygoptiongroup.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_glib_la-pygoptiongroup.Tpo $(DEPDIR)/_glib_la-pygoptiongroup.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygoptiongroup.c' object='_glib_la-pygoptiongroup.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_glib_la_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygoptiongroup.lo `test -f 'pygoptiongroup.c' || echo '$(srcdir)/'`pygoptiongroup.c
-
-_glib_la-pygspawn.lo: pygspawn.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_glib_la_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -MT _glib_la-pygspawn.lo -MD -MP -MF $(DEPDIR)/_glib_la-pygspawn.Tpo -c -o _glib_la-pygspawn.lo `test -f 'pygspawn.c' || echo '$(srcdir)/'`pygspawn.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_glib_la-pygspawn.Tpo $(DEPDIR)/_glib_la-pygspawn.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygspawn.c' object='_glib_la-pygspawn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(_glib_la_CPPFLAGS) $(CPPFLAGS) $(_glib_la_CFLAGS) $(CFLAGS) -c -o _glib_la-pygspawn.lo `test -f 'pygspawn.c' || echo '$(srcdir)/'`pygspawn.c
-
-libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.lo: pyglib.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CPPFLAGS) $(CPPFLAGS) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CFLAGS) $(CFLAGS) -MT libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.lo -MD -MP -MF $(DEPDIR)/libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.Tpo -c -o libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.lo `test -f 'pyglib.c' || echo '$(srcdir)/'`pyglib.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.Tpo $(DEPDIR)/libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pyglib.c' object='libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CPPFLAGS) $(CPPFLAGS) $(libpyglib_gi_2_0_@PYTHON_BASENAME@_la_CFLAGS) $(CFLAGS) -c -o libpyglib_gi_2_0_@PYTHON_BASENAME@_la-pyglib.lo `test -f 'pyglib.c' || echo '$(srcdir)/'`pyglib.c
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-pyglibPYTHON: $(pyglib_PYTHON)
- @$(NORMAL_INSTALL)
- @list='$(pyglib_PYTHON)'; dlist=; list2=; test -n "$(pyglibdir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(pyglibdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pyglibdir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \
- if test -f $$b$$p; then \
- $(am__strip_dir) \
- dlist="$$dlist $$f"; \
- list2="$$list2 $$b$$p"; \
- else :; fi; \
- done; \
- for file in $$list2; do echo $$file; done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pyglibdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(pyglibdir)" || exit $$?; \
- done || exit $$?; \
- if test -n "$$dlist"; then \
- $(am__py_compile) --destdir "$(DESTDIR)" \
- --basedir "$(pyglibdir)" $$dlist; \
- else :; fi
-
-uninstall-pyglibPYTHON:
- @$(NORMAL_UNINSTALL)
- @list='$(pyglib_PYTHON)'; test -n "$(pyglibdir)" || list=; \
- py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$py_files" || exit 0; \
- dir='$(DESTDIR)$(pyglibdir)'; \
- pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \
- pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \
- py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \
- echo "$$py_files_pep3147";\
- pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \
- pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \
- st=0; \
- for files in \
- "$$py_files" \
- "$$pyc_files" \
- "$$pyo_files" \
- "$$pyc_files_pep3147" \
- "$$pyo_files_pep3147" \
- ; do \
- $(am__uninstall_files_from_dir) || st=$$?; \
- done; \
- exit $$st
-
-ID: $(am__tagged_files)
- $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- set x; \
- here=`pwd`; \
- $(am__define_uniq_tagged_files); \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
- list='$(am__tagged_files)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) check-local
-check: check-am
-all-am: Makefile $(LTLIBRARIES)
-installdirs:
- for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pyglibdir)" "$(DESTDIR)$(pyglibdir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
- clean-pyglibLTLIBRARIES mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-pyglibLTLIBRARIES install-pyglibPYTHON
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am: install-libLTLIBRARIES
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-libLTLIBRARIES uninstall-pyglibLTLIBRARIES \
- uninstall-pyglibPYTHON
-
-.MAKE: check-am install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \
- clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
- clean-pyglibLTLIBRARIES cscopelist-am ctags ctags-am distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am \
- install-libLTLIBRARIES install-man install-pdf install-pdf-am \
- install-ps install-ps-am install-pyglibLTLIBRARIES \
- install-pyglibPYTHON install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \
- uninstall-pyglibLTLIBRARIES uninstall-pyglibPYTHON
-
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pyglib_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-all: $(pyglib_LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-check-local: $(pyglib_LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-clean-local:
- rm -f $(pyglib_LTLIBRARIES:.la=$(PYTHON_SO))
-%$(PYTHON_SO): %.la
- $(LN_S) -f .libs/$@ $@
-
-# 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.
-.NOEXPORT:
diff --git a/gi/_glib/__init__.py b/gi/_glib/__init__.py
deleted file mode 100644
index 0b9df9a..0000000
--- a/gi/_glib/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-# pygobject - Python bindings for the GObject library
-# Copyright (C) 2006-2012 Johan Dahlin
-#
-# glib/__init__.py: initialisation file for glib module
-#
-# 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 Street, Fifth Floor, Boston, MA 02110-1301
-# USA
-
-from . import _glib
-
-# Internal API
-_PyGLib_API = _glib._PyGLib_API
diff --git a/gi/_glib/glibmodule.c b/gi/_glib/glibmodule.c
deleted file mode 100644
index d08d4fb..0000000
--- a/gi/_glib/glibmodule.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- Mode: C; c-set-style: python; c-basic-offset: 4 -*-
- * pyglib - Python bindings for GLib toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- * 2004-2008 Johan Dahlin
- *
- * glibmodule.c: wrapper for the glib library.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <Python.h>
-#include <glib.h>
-#include "pyglib.h"
-#include "pyglib-private.h"
-#include "pygoptioncontext.h"
-#include "pygoptiongroup.h"
-#include "pygspawn.h"
-
-/* ---------------- glib module functions -------------------- */
-
-static PyMethodDef _glib_functions[] = {
- { "spawn_async",
- (PyCFunction)pyglib_spawn_async, METH_VARARGS|METH_KEYWORDS,
- "spawn_async(argv, envp=None, working_directory=None,\n"
- " flags=0, child_setup=None, user_data=None,\n"
- " standard_input=None, standard_output=None,\n"
- " standard_error=None) -> (pid, stdin, stdout, stderr)\n"
- "Execute a child program asynchronously within a glib.MainLoop()\n"
- "See the reference manual for a complete reference." },
- { NULL, NULL, 0 }
-};
-
-/* ----------------- glib module initialisation -------------- */
-
-static struct _PyGLib_Functions pyglib_api = {
- FALSE, /* threads_enabled */
- NULL, /* gerror_exception */
- NULL, /* block_threads */
- NULL, /* unblock_threads */
- NULL, /* pyg_main_context_new */
- pyg_option_context_new,
- pyg_option_group_new,
-};
-
-static void
-pyglib_register_api(PyObject *d)
-{
- PyObject *o;
-
- /* for addon libraries ... */
- PyDict_SetItemString(d, "_PyGLib_API",
- o=PYGLIB_CPointer_WrapPointer(&pyglib_api,"gi._glib._PyGLib_API"));
- Py_DECREF(o);
-
- pyglib_init_internal(o);
-}
-
-static void
-pyglib_register_error(PyObject *d)
-{
- PyObject *dict;
- PyObject *gerror_class;
- dict = PyDict_New();
- /* This is a hack to work around the deprecation warning of
- * BaseException.message in Python 2.6+.
- * GError has also an "message" attribute.
- */
- PyDict_SetItemString(dict, "message", Py_None);
- gerror_class = PyErr_NewException("gi._glib.GError", PyExc_RuntimeError, dict);
- Py_DECREF(dict);
-
- PyDict_SetItemString(d, "GError", gerror_class);
- pyglib_api.gerror_exception = gerror_class;
-}
-
-PYGLIB_MODULE_START(_glib, "_glib")
-{
- PyObject *d = PyModule_GetDict(module);
-
- pyglib_register_api(d);
- pyglib_register_error(d);
- pyglib_spawn_register_types(d);
- pyglib_option_context_register_types(d);
- pyglib_option_group_register_types(d);
-}
-PYGLIB_MODULE_END
diff --git a/gi/_glib/pyglib-private.h b/gi/_glib/pyglib-private.h
deleted file mode 100644
index 183184f..0000000
--- a/gi/_glib/pyglib-private.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pyglib - Python bindings for GLib toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- * 2004-2008 Johan Dahlin
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGLIB_PRIVATE_H__
-#define __PYGLIB_PRIVATE_H__
-
-#include <Python.h>
-#include <glib.h>
-
-#include <pyglib-python-compat.h>
-
-G_BEGIN_DECLS
-
-struct _PyGLib_Functions {
- gboolean threads_enabled;
- PyObject *gerror_exception;
- PyGLibThreadBlockFunc block_threads;
- PyGLibThreadBlockFunc unblock_threads;
- PyObject* (*main_context_new)(GMainContext *context);
- PyObject* (*option_context_new)(GOptionContext *context);
- PyObject* (*option_group_new)(GOptionGroup *group);
-};
-
-gboolean _pyglib_handler_marshal(gpointer user_data);
-void _pyglib_destroy_notify(gpointer user_data);
-
-G_END_DECLS
-
-#endif /* __PYGLIB_PRIVATE_H__ */
-
-
diff --git a/gi/_glib/pyglib-python-compat.h b/gi/_glib/pyglib-python-compat.h
deleted file mode 100644
index 7b4c595..0000000
--- a/gi/_glib/pyglib-python-compat.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pyglib - Python bindings for GLib toolkit.
- * Copyright (C) 2008 Johan Dahlin
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGLIB_PYTHON_COMPAT_H__
-#define __PYGLIB_PYTHON_COMPAT_H__
-
-# define PYGLIB_CPointer_Check PyCapsule_CheckExact
-# define PYGLIB_CPointer_WrapPointer(ptr, typename) \
- PyCapsule_New(ptr, typename, NULL)
-# define PYGLIB_CPointer_GetPointer(obj, typename) \
- PyCapsule_GetPointer(obj, typename)
-# define PYGLIB_CPointer_Import(module, symbol) \
- PyCapsule_Import(##module##.##symbol##, FALSE)
-
-#if PY_VERSION_HEX < 0x03000000
-
-#define PYGLIB_INIT_FUNCTION(modname, fullpkgname, functions) \
-static int _pyglib_init_##modname(PyObject *module); \
-void init##modname(void) \
-{ \
- PyObject *module = Py_InitModule(fullpkgname, functions); \
- _pyglib_init_##modname(module); \
-} \
-static int _pyglib_init_##modname(PyObject *module)
-
-#else
-
-#define PYGLIB_INIT_FUNCTION(modname, fullpkgname, functions) \
-static struct PyModuleDef _##modname##module = { \
- PyModuleDef_HEAD_INIT, \
- fullpkgname, \
- NULL, \
- -1, \
- functions, \
- NULL, \
- NULL, \
- NULL, \
- NULL \
-}; \
-static int _pyglib_init_##modname(PyObject *module); \
-PyObject *PyInit_##modname(void) \
-{ \
- PyObject *module = PyModule_Create(&_##modname##module); \
- if (module == NULL) \
- return NULL; \
- if (_pyglib_init_##modname(module) != 0 ) {\
- Py_DECREF(module); \
- return NULL; \
- } \
- return module; \
-} \
-static int _pyglib_init_##modname(PyObject *module)
-
-#endif
-
-/* Compilation on Python 2.x */
-#if PY_VERSION_HEX < 0x03000000
-#define PYGLIB_MODULE_ERROR_RETURN
-
-#define RO READONLY
-
-#define PYGLIB_PyBaseString_Check(ob) (PyString_Check(ob) || PyUnicode_Check(ob))
-
-#define PYGLIB_PyUnicode_Check PyString_Check
-#define PYGLIB_PyUnicode_AsString PyString_AsString
-#define PYGLIB_PyUnicode_AsStringAndSize PyString_AsStringAndSize
-#define PYGLIB_PyUnicode_FromString PyString_FromString
-#define PYGLIB_PyUnicode_FromStringAndSize PyString_FromStringAndSize
-#define PYGLIB_PyUnicode_FromFormat PyString_FromFormat
-#define PYGLIB_PyUnicode_AS_STRING PyString_AS_STRING
-#define PYGLIB_PyUnicode_GET_SIZE PyString_GET_SIZE
-#define PYGLIB_PyUnicode_Type PyString_Type
-#define PYGLIB_PyUnicode_InternFromString PyString_InternFromString
-#define PYGLIB_PyUnicode_InternInPlace PyString_InternInPlace
-
-#define PYGLIB_PyBytes_FromString PyString_FromString
-#define PYGLIB_PyBytes_FromStringAndSize PyString_FromStringAndSize
-#define PYGLIB_PyBytes_Resize _PyString_Resize
-#define PYGLIB_PyBytes_AsString PyString_AsString
-#define PYGLIB_PyBytes_Size PyString_Size
-#define PYGLIB_PyBytes_Check PyString_Check
-
-#define PYGLIB_PyLong_Check PyInt_Check
-#define PYGLIB_PyLong_FromLong PyInt_FromLong
-#define PYGLIB_PyLong_FromSsize_t PyInt_FromSsize_t
-#define PYGLIB_PyLong_FromSize_t PyInt_FromSize_t
-#define PYGLIB_PyLong_AsLong PyInt_AsLong
-#define PYGLIB_PyLongObject PyIntObject
-#define PYGLIB_PyLong_Type PyInt_Type
-#define PYGLIB_PyLong_AS_LONG PyInt_AS_LONG
-#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
-
-/* Python 2.7 lacks a PyInt_FromUnsignedLong function; use signed longs, and
- * rely on PyInt_AsUnsignedLong() to interpret them correctly */
-#define PYGLIB_PyLong_FromUnsignedLong PyInt_FromLong
-#define PYGLIB_PyLong_AsUnsignedLong(o) PyInt_AsUnsignedLongMask((PyObject*)(o))
-
-#define PYGLIB_PyNumber_Long PyNumber_Int
-
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(base, size) \
- PyObject_HEAD_INIT(base) \
- size,
-#endif
-
-#define PYGLIB_MODULE_START(symbol, modname) \
-DL_EXPORT(void) init##symbol(void); \
-DL_EXPORT(void) init##symbol(void) \
-{ \
- PyObject *module; \
- module = Py_InitModule(modname, symbol##_functions);
-#define PYGLIB_MODULE_END }
-#define PYGLIB_DEFINE_TYPE(typename, symbol, csymbol) \
-PyTypeObject symbol = { \
- PyObject_HEAD_INIT(NULL) \
- 0, \
- typename, \
- sizeof(csymbol), \
- 0, \
-};
-#define PYGLIB_REGISTER_TYPE(d, type, name) \
- if (!type.tp_alloc) \
- type.tp_alloc = PyType_GenericAlloc; \
- if (!type.tp_new) \
- type.tp_new = PyType_GenericNew; \
- if (PyType_Ready(&type)) \
- return; \
- PyDict_SetItemString(d, name, (PyObject *)&type);
-
-#else
-
-#define PYGLIB_MODULE_ERROR_RETURN 0
-
-#define PYGLIB_MODULE_START(symbol, modname) \
- static struct PyModuleDef _##symbol##module = { \
- PyModuleDef_HEAD_INIT, \
- modname, \
- NULL, \
- -1, \
- symbol##_functions, \
- NULL, \
- NULL, \
- NULL, \
- NULL \
-}; \
-PyMODINIT_FUNC PyInit_##symbol(void); \
-PyMODINIT_FUNC PyInit_##symbol(void) \
-{ \
- PyObject *module; \
- module = PyModule_Create(&_##symbol##module);
-#define PYGLIB_MODULE_END return module; }
-#define PYGLIB_DEFINE_TYPE(typename, symbol, csymbol) \
-PyTypeObject symbol = { \
- PyVarObject_HEAD_INIT(NULL, 0) \
- typename, \
- sizeof(csymbol) \
-};
-#define PYGLIB_REGISTER_TYPE(d, type, name) \
- if (!type.tp_alloc) \
- type.tp_alloc = PyType_GenericAlloc; \
- if (!type.tp_new) \
- type.tp_new = PyType_GenericNew; \
- if (PyType_Ready(&type)) \
- return; \
- PyDict_SetItemString(d, name, (PyObject *)&type);
-
-#define PYGLIB_PyBaseString_Check PyUnicode_Check
-
-#define PYGLIB_PyUnicode_Check PyUnicode_Check
-#define PYGLIB_PyUnicode_AsString _PyUnicode_AsString
-#define PYGLIB_PyUnicode_AsStringAndSize(obj, buf, size) \
- (((*(buf) = _PyUnicode_AsStringAndSize(obj, size)) != NULL) ? 0 : -1)
-#define PYGLIB_PyUnicode_FromString PyUnicode_FromString
-#define PYGLIB_PyUnicode_FromStringAndSize PyUnicode_FromStringAndSize
-#define PYGLIB_PyUnicode_FromFormat PyUnicode_FromFormat
-#define PYGLIB_PyUnicode_GET_SIZE PyUnicode_GET_SIZE
-#define PYGLIB_PyUnicode_Resize PyUnicode_Resize
-#define PYGLIB_PyUnicode_Type PyUnicode_Type
-#define PYGLIB_PyUnicode_InternFromString PyUnicode_InternFromString
-#define PYGLIB_PyUnicode_InternInPlace PyUnicode_InternInPlace
-
-#define PYGLIB_PyLong_Check PyLong_Check
-#define PYGLIB_PyLong_FromLong PyLong_FromLong
-#define PYGLIB_PyLong_AsLong PyLong_AsLong
-#define PYGLIB_PyLong_AS_LONG(o) PyLong_AS_LONG((PyObject*)(o))
-#define PYGLIB_PyLongObject PyLongObject
-#define PYGLIB_PyLong_Type PyLong_Type
-
-#define PYGLIB_PyLong_FromUnsignedLong PyLong_FromUnsignedLong
-#define PYGLIB_PyLong_AsUnsignedLong(o) PyLong_AsUnsignedLongMask((PyObject*)(o))
-
-#define PYGLIB_PyBytes_FromString PyBytes_FromString
-#define PYGLIB_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
-#define PYGLIB_PyBytes_Resize(o, len) _PyBytes_Resize(o, len)
-#define PYGLIB_PyBytes_AsString PyBytes_AsString
-#define PYGLIB_PyBytes_Size PyBytes_Size
-#define PYGLIB_PyBytes_Check PyBytes_Check
-
-#define PYGLIB_PyNumber_Long PyNumber_Long
-
-#endif
-
-#endif /* __PYGLIB_PYTHON_COMPAT_H__ */
diff --git a/gi/_glib/pyglib.c b/gi/_glib/pyglib.c
deleted file mode 100644
index 9753a52..0000000
--- a/gi/_glib/pyglib.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/* -*- Mode: C; c-set-style: python; c-basic-offset: 4 -*-
- * pyglib - Python bindings for GLib toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- * 2004-2008 Johan Dahlin
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <Python.h>
-#include <pythread.h>
-#include "pyglib.h"
-#include "pyglib-private.h"
-#include "pygoptioncontext.h"
-#include "pygoptiongroup.h"
-
-static struct _PyGLib_Functions *_PyGLib_API;
-static PyObject *exception_table = NULL;
-
-void
-pyglib_init(void)
-{
- PyObject *glib, *cobject;
-
- glib = PyImport_ImportModule("gi._glib");
- if (!glib) {
- if (PyErr_Occurred()) {
- PyObject *type, *value, *traceback;
- PyObject *py_orig_exc;
- PyErr_Fetch(&type, &value, &traceback);
- py_orig_exc = PyObject_Repr(value);
- Py_XDECREF(type);
- Py_XDECREF(value);
- Py_XDECREF(traceback);
- PyErr_Format(PyExc_ImportError,
- "could not import gi._glib (error was: %s)",
- PYGLIB_PyUnicode_AsString(py_orig_exc));
- Py_DECREF(py_orig_exc);
- } else {
- PyErr_SetString(PyExc_ImportError,
- "could not import gi._glib (no error given)");
- }
- return;
- }
-
- cobject = PyObject_GetAttrString(glib, "_PyGLib_API");
- if (cobject && PYGLIB_CPointer_Check(cobject))
- _PyGLib_API = (struct _PyGLib_Functions *) PYGLIB_CPointer_GetPointer(cobject, "gi._glib._PyGLib_API");
- else {
- PyErr_SetString(PyExc_ImportError,
- "could not import gi._glib (could not find _PyGLib_API object)");
- Py_DECREF(glib);
- return;
- }
-}
-
-void
-pyglib_init_internal(PyObject *api)
-{
- _PyGLib_API = (struct _PyGLib_Functions *) PYGLIB_CPointer_GetPointer(api, "gi._glib._PyGLib_API");
-}
-
-/**
- * pyglib_error_marshal:
- * @error: a pointer to the GError.
- *
- * Checks to see if @error has been set. If @error has been set, then a
- * GLib.GError Python exception object is returned (but not raised).
- *
- * Returns: a GLib.GError Python exception object, or NULL.
- */
-PyObject *
-pyglib_error_marshal (GError **error)
-{
- PyGILState_STATE state;
- PyObject *exc_type;
- PyObject *exc_instance;
- PyObject *d;
-
- g_return_val_if_fail(error != NULL, NULL);
-
- if (*error == NULL)
- return NULL;
-
- state = pyglib_gil_state_ensure();
-
- exc_type = _PyGLib_API->gerror_exception;
- if (exception_table != NULL)
- {
- PyObject *item;
- item = PyDict_GetItem(exception_table, PYGLIB_PyLong_FromLong((*error)->domain));
- if (item != NULL)
- exc_type = item;
- }
-
- exc_instance = PyObject_CallFunction(exc_type, "z", (*error)->message);
-
- if ((*error)->domain) {
- PyObject_SetAttrString(exc_instance, "domain",
- d=PYGLIB_PyUnicode_FromString(g_quark_to_string((*error)->domain)));
- Py_DECREF(d);
- }
- else
- PyObject_SetAttrString(exc_instance, "domain", Py_None);
-
- PyObject_SetAttrString(exc_instance, "code",
- d=PYGLIB_PyLong_FromLong((*error)->code));
- Py_DECREF(d);
-
- if ((*error)->message) {
- PyObject_SetAttrString(exc_instance, "message",
- d=PYGLIB_PyUnicode_FromString((*error)->message));
- Py_DECREF(d);
- } else {
- PyObject_SetAttrString(exc_instance, "message", Py_None);
- }
-
- pyglib_gil_state_release(state);
-
- return exc_instance;
-}
-
-/**
- * pyglib_error_check:
- * @error: a pointer to the GError.
- *
- * Checks to see if the GError has been set. If the error has been
- * set, then the glib.GError Python exception will be raised, and
- * the GError cleared.
- *
- * Returns: True if an error was set.
- */
-gboolean
-pyglib_error_check(GError **error)
-{
- PyGILState_STATE state;
- PyObject *exc_instance;
-
- g_return_val_if_fail(error != NULL, FALSE);
- if (*error == NULL)
- return FALSE;
-
- state = pyglib_gil_state_ensure();
-
- exc_instance = pyglib_error_marshal (error);
- PyErr_SetObject(_PyGLib_API->gerror_exception, exc_instance);
- Py_DECREF(exc_instance);
- g_clear_error(error);
-
- pyglib_gil_state_release(state);
-
- return TRUE;
-}
-
-/**
- * pyglib_gerror_exception_check:
- * @error: a standard GLib GError ** output parameter
- *
- * Checks to see if a GError exception has been raised, and if so
- * translates the python exception to a standard GLib GError. If the
- * raised exception is not a GError then PyErr_Print() is called.
- *
- * Returns: 0 if no exception has been raised, -1 if it is a
- * valid glib.GError, -2 otherwise.
- */
-gboolean
-pyglib_gerror_exception_check(GError **error)
-{
- PyObject *type, *value, *traceback;
- PyObject *py_message, *py_domain, *py_code;
- const char *bad_gerror_message;
-
- PyErr_Fetch(&type, &value, &traceback);
- if (type == NULL)
- return 0;
- PyErr_NormalizeException(&type, &value, &traceback);
- if (value == NULL) {
- PyErr_Restore(type, value, traceback);
- PyErr_Print();
- return -2;
- }
- if (!value ||
- !PyErr_GivenExceptionMatches(type,
- (PyObject *) _PyGLib_API->gerror_exception)) {
- PyErr_Restore(type, value, traceback);
- PyErr_Print();
- return -2;
- }
- Py_DECREF(type);
- Py_XDECREF(traceback);
-
- py_message = PyObject_GetAttrString(value, "message");
- if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) {
- bad_gerror_message = "gi._glib.GError instances must have a 'message' string attribute";
- Py_XDECREF(py_message);
- goto bad_gerror;
- }
-
- py_domain = PyObject_GetAttrString(value, "domain");
- if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) {
- bad_gerror_message = "gi._glib.GError instances must have a 'domain' string attribute";
- Py_DECREF(py_message);
- Py_XDECREF(py_domain);
- goto bad_gerror;
- }
-
- py_code = PyObject_GetAttrString(value, "code");
- if (!py_code || !PYGLIB_PyLong_Check(py_code)) {
- bad_gerror_message = "gi._glib.GError instances must have a 'code' int attribute";
- Py_DECREF(py_message);
- Py_DECREF(py_domain);
- Py_XDECREF(py_code);
- goto bad_gerror;
- }
-
- g_set_error(error, g_quark_from_string(PYGLIB_PyUnicode_AsString(py_domain)),
- PYGLIB_PyLong_AsLong(py_code), "%s", PYGLIB_PyUnicode_AsString(py_message));
-
- Py_DECREF(py_message);
- Py_DECREF(py_code);
- Py_DECREF(py_domain);
- return -1;
-
-bad_gerror:
- Py_DECREF(value);
- g_set_error(error, g_quark_from_static_string("pyglib"), 0, "%s", bad_gerror_message);
- PyErr_SetString(PyExc_ValueError, bad_gerror_message);
- PyErr_Print();
- return -2;
-}
-
-/**
- * pyglib_register_exception_for_domain:
- * @name: name of the exception
- * @error_domain: error domain
- *
- * Registers a new glib.GError exception subclass called #name for
- * a specific #domain. This exception will be raised when a GError
- * of the same domain is passed in to pyglib_error_check().
- *
- * Returns: the new exception
- */
-PyObject *
-pyglib_register_exception_for_domain(gchar *name,
- gint error_domain)
-{
- PyObject *exception;
-
- exception = PyErr_NewException(name, _PyGLib_API->gerror_exception, NULL);
-
- if (exception_table == NULL)
- exception_table = PyDict_New();
-
- PyDict_SetItem(exception_table,
- PYGLIB_PyLong_FromLong(error_domain),
- exception);
-
- return exception;
-}
-
-/**
- * pyg_option_group_transfer_group:
- * @group: a GOptionGroup wrapper
- *
- * This is used to transfer the GOptionGroup to a GOptionContext. After this
- * is called, the calle must handle the release of the GOptionGroup.
- *
- * When #NULL is returned, the GOptionGroup was already transfered.
- *
- * Returns: Either #NULL or the wrapped GOptionGroup.
- */
-GOptionGroup *
-pyglib_option_group_transfer_group(PyObject *obj)
-{
- PyGOptionGroup *self = (PyGOptionGroup*)obj;
-
- if (self->is_in_context)
- return NULL;
-
- self->is_in_context = TRUE;
-
- /* Here we increase the reference count of the PyGOptionGroup, because now
- * the GOptionContext holds an reference to us (it is the userdata passed
- * to g_option_group_new().
- *
- * The GOptionGroup is freed with the GOptionContext.
- *
- * We set it here because if we would do this in the init method we would
- * hold two references and the PyGOptionGroup would never be freed.
- */
- Py_INCREF(self);
-
- return self->group;
-}
-
-/**
- * pyglib_option_group_new:
- * @group: a GOptionGroup
- *
- * The returned GOptionGroup can't be used to set any hooks, translation domains
- * or add entries. It's only intend is, to use for GOptionContext.add_group().
- *
- * Returns: the GOptionGroup wrapper.
- */
-PyObject *
-pyglib_option_group_new (GOptionGroup *group)
-{
- return _PyGLib_API->option_group_new(group);
-}
-
-/**
- * pyglib_option_context_new:
- * @context: a GOptionContext
- *
- * Returns: A new GOptionContext wrapper.
- */
-PyObject *
-pyglib_option_context_new (GOptionContext *context)
-{
- return _PyGLib_API->option_context_new(context);
-}
-
-
-/****** Private *****/
-
-/**
- * _pyglib_destroy_notify:
- * @user_data: a PyObject pointer.
- *
- * A function that can be used as a GDestroyNotify callback that will
- * call Py_DECREF on the data.
- */
-void
-_pyglib_destroy_notify(gpointer user_data)
-{
- PyObject *obj = (PyObject *)user_data;
- PyGILState_STATE state;
-
- g_return_if_fail (_PyGLib_API != NULL);
-
- state = pyglib_gil_state_ensure();
- Py_DECREF(obj);
- pyglib_gil_state_release(state);
-}
-
-gboolean
-_pyglib_handler_marshal(gpointer user_data)
-{
- PyObject *tuple, *ret;
- gboolean res;
- PyGILState_STATE state;
-
- g_return_val_if_fail(user_data != NULL, FALSE);
-
- state = pyglib_gil_state_ensure();
-
- tuple = (PyObject *)user_data;
- ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0),
- PyTuple_GetItem(tuple, 1));
- if (!ret) {
- PyErr_Print();
- res = FALSE;
- } else {
- res = PyObject_IsTrue(ret);
- Py_DECREF(ret);
- }
-
- pyglib_gil_state_release(state);
-
- return res;
-}
-
-PyObject*
-_pyglib_generic_ptr_richcompare(void* a, void *b, int op)
-{
- PyObject *res;
-
- switch (op) {
-
- case Py_EQ:
- res = (a == b) ? Py_True : Py_False;
- break;
-
- case Py_NE:
- res = (a != b) ? Py_True : Py_False;
- break;
-
- case Py_LT:
- res = (a < b) ? Py_True : Py_False;
- break;
-
- case Py_LE:
- res = (a <= b) ? Py_True : Py_False;
- break;
-
- case Py_GT:
- res = (a > b) ? Py_True : Py_False;
- break;
-
- case Py_GE:
- res = (a >= b) ? Py_True : Py_False;
- break;
-
- default:
- res = Py_NotImplemented;
- break;
- }
-
- Py_INCREF(res);
- return res;
-}
-
-PyObject*
-_pyglib_generic_long_richcompare(long a, long b, int op)
-{
- PyObject *res;
-
- switch (op) {
-
- case Py_EQ:
- res = (a == b) ? Py_True : Py_False;
- Py_INCREF(res);
- break;
-
- case Py_NE:
- res = (a != b) ? Py_True : Py_False;
- Py_INCREF(res);
- break;
-
-
- case Py_LT:
- res = (a < b) ? Py_True : Py_False;
- Py_INCREF(res);
- break;
-
- case Py_LE:
- res = (a <= b) ? Py_True : Py_False;
- Py_INCREF(res);
- break;
-
- case Py_GT:
- res = (a > b) ? Py_True : Py_False;
- Py_INCREF(res);
- break;
-
- case Py_GE:
- res = (a >= b) ? Py_True : Py_False;
- Py_INCREF(res);
- break;
-
- default:
- res = Py_NotImplemented;
- Py_INCREF(res);
- break;
- }
-
- return res;
-}
-
diff --git a/gi/_glib/pyglib.h b/gi/_glib/pyglib.h
deleted file mode 100644
index 1c62f1d..0000000
--- a/gi/_glib/pyglib.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pyglib - Python bindings for GLib toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- * 2004-2008 Johan Dahlin
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGLIB_H__
-#define __PYGLIB_H__
-
-#include <Python.h>
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef void (*PyGLibThreadsEnabledFunc) (void);
-typedef void (*PyGLibThreadBlockFunc) (void);
-
-void pyglib_init(void);
-void pyglib_init_internal(PyObject *api);
-
-#ifdef DISABLE_THREADING
-# define pyglib_gil_state_ensure() PyGILState_LOCKED
-# define pyglib_gil_state_release(state) state
-#else
-# define pyglib_gil_state_ensure PyGILState_Ensure
-# define pyglib_gil_state_release PyGILState_Release
-#endif
-
-/* Deprecated, only available for API compatibility. */
-#define pyg_set_thread_block_funcs(a, b)
-#define pyglib_block_threads()
-#define pyglib_unblock_threads()
-
-gboolean pyglib_error_check(GError **error);
-PyObject *pyglib_error_marshal (GError **error);
-gboolean pyglib_gerror_exception_check(GError **error);
-PyObject *pyglib_register_exception_for_domain(gchar *name,
- gint error_domain);
-PyObject * pyglib_option_context_new(GOptionContext *context);
-PyObject * pyglib_option_group_new(GOptionGroup *group);
-GOptionGroup * pyglib_option_group_transfer_group(PyObject *self);
-
-/* Private: for gobject <-> glib interaction only. */
-PyObject* _pyglib_generic_ptr_richcompare(void* a, void *b, int op);
-PyObject* _pyglib_generic_long_richcompare(long a, long b, int op);
-
-
-#define PYGLIB_REGISTER_TYPE(d, type, name) \
- if (!type.tp_alloc) \
- type.tp_alloc = PyType_GenericAlloc; \
- if (!type.tp_new) \
- type.tp_new = PyType_GenericNew; \
- if (PyType_Ready(&type)) \
- return; \
- PyDict_SetItemString(d, name, (PyObject *)&type);
-
-
-G_END_DECLS
-
-#endif /* __PYGLIB_H__ */
-
diff --git a/gi/_gobject/Makefile.am b/gi/_gobject/Makefile.am
deleted file mode 100644
index 5059ea7..0000000
--- a/gi/_gobject/Makefile.am
+++ /dev/null
@@ -1,87 +0,0 @@
-AUTOMAKE_OPTIONS = 1.7
-PLATFORM_VERSION = 3.0
-
-pkgincludedir = $(includedir)/pygobject-$(PLATFORM_VERSION)
-pkginclude_HEADERS = pygobject.h
-
-extension_cppflags = \
- $(PYTHON_INCLUDES) \
- -DPY_SSIZE_T_CLEAN
-
-extension_ldflags = \
- -module \
- -avoid-version \
- -shrext $(PYTHON_SO)
-
-if OS_WIN32
-# Windows requires Python modules to be explicitly linked to libpython.
-# Extension modules are shared libaries (.dll), but need to be
-# called .pyd for Python to load it as an extension module.
-extension_libadd = \
- $(PYTHON_LIBS)
-
-extension_ldflags += \
- -no-undefined
-endif
-
-pygobjectdir = $(pyexecdir)/gi/_gobject
-
-pygobject_PYTHON = \
- __init__.py \
- constants.py \
- propertyhelper.py \
- signalhelper.py
-
-pygobject_LTLIBRARIES = _gobject.la
-
-_gobject_la_SOURCES = \
- gobjectmodule.c \
- pygboxed.c \
- pygboxed.h \
- pygenum.c \
- pygenum.h \
- pygflags.c \
- pygflags.h \
- pyginterface.c \
- pyginterface.h \
- pygobject.c \
- pygobject.h \
- pygobject-private.h \
- pygparamspec.c \
- pygparamspec.h \
- pygpointer.c \
- pygpointer.h \
- pygtype.c \
- pygtype.h
-_gobject_la_CFLAGS = \
- $(extension_cppflags) \
- -I$(top_srcdir)/gi/_glib \
- -I$(top_srcdir)/gi \
- $(GLIB_CFLAGS) \
- $(GI_CFLAGS)
-_gi_la_CPPFLAGS = \
- $(extension_cppflags)
-_gobject_la_LIBADD = \
- $(extension_libadd) \
- $(GLIB_LIBS) \
- $(GI_LIBS) \
- $(top_builddir)/gi/_glib/libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-_gobject_la_LDFLAGS = \
- $(extension_ldflags) \
- -export-symbols-regex "_gobject|PyInit__gobject"
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pygobject_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-
-all: $(pygobject_LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-check-local: $(pygobject_LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-clean-local:
- rm -f $(pygobject_LTLIBRARIES:.la=$(PYTHON_SO))
-%$(PYTHON_SO): %.la
- $(LN_S) -f .libs/$@ $@
diff --git a/gi/_gobject/Makefile.in b/gi/_gobject/Makefile.in
deleted file mode 100644
index b057108..0000000
--- a/gi/_gobject/Makefile.in
+++ /dev/null
@@ -1,923 +0,0 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-@OS_WIN32_TRUE@am__append_1 = \
-@OS_WIN32_TRUE@ -no-undefined
-
-subdir = gi/_gobject
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(top_srcdir)/depcomp $(pygobject_PYTHON) \
- $(top_srcdir)/py-compile $(pkginclude_HEADERS)
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
- $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-am__installdirs = "$(DESTDIR)$(pygobjectdir)" \
- "$(DESTDIR)$(pygobjectdir)" "$(DESTDIR)$(pkgincludedir)"
-LTLIBRARIES = $(pygobject_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-@OS_WIN32_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
-_gobject_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) \
- $(top_builddir)/gi/_glib/libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-am__gobject_la_OBJECTS = _gobject_la-gobjectmodule.lo \
- _gobject_la-pygboxed.lo _gobject_la-pygenum.lo \
- _gobject_la-pygflags.lo _gobject_la-pyginterface.lo \
- _gobject_la-pygobject.lo _gobject_la-pygparamspec.lo \
- _gobject_la-pygpointer.lo _gobject_la-pygtype.lo
-_gobject_la_OBJECTS = $(am__gobject_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 =
-_gobject_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(_gobject_la_CFLAGS) \
- $(CFLAGS) $(_gobject_la_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
- $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-SOURCES = $(_gobject_la_SOURCES)
-DIST_SOURCES = $(_gobject_la_SOURCES)
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile)
-am__pep3147_tweak = \
- sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|'
-py_compile = $(top_srcdir)/py-compile
-HEADERS = $(pkginclude_HEADERS)
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates. Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
- BEGIN { nonempty = 0; } \
- { items[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique. This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
- list='$(am__tagged_files)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-pkgincludedir = $(includedir)/pygobject-$(PLATFORM_VERSION)
-ACLOCAL = @ACLOCAL@
-ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CAIRO_CFLAGS = @CAIRO_CFLAGS@
-CAIRO_LIBS = @CAIRO_LIBS@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
-CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
-CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DATADIR = @DATADIR@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FFI_CFLAGS = @FFI_CFLAGS@
-FFI_LIBS = @FFI_LIBS@
-FGREP = @FGREP@
-GENHTML = @GENHTML@
-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_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
-GLIB_LIBS = @GLIB_LIBS@
-GLIB_MKENUMS = @GLIB_MKENUMS@
-GOBJECT_QUERY = @GOBJECT_QUERY@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
-INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBFFI_PC = @LIBFFI_PC@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLATFORM = @PLATFORM@
-PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@
-PYCAIRO_LIBS = @PYCAIRO_LIBS@
-PYGOBJECT_MAJOR_VERSION = @PYGOBJECT_MAJOR_VERSION@
-PYGOBJECT_MICRO_VERSION = @PYGOBJECT_MICRO_VERSION@
-PYGOBJECT_MINOR_VERSION = @PYGOBJECT_MINOR_VERSION@
-PYTHON = @PYTHON@
-PYTHON_BASENAME = @PYTHON_BASENAME@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_INCLUDES = @PYTHON_INCLUDES@
-PYTHON_LIBS = @PYTHON_LIBS@
-PYTHON_LIB_LOC = @PYTHON_LIB_LOC@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_SO = @PYTHON_SO@
-PYTHON_VERSION = @PYTHON_VERSION@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-THREADING_CFLAGS = @THREADING_CFLAGS@
-VERSION = @VERSION@
-WARN_CFLAGS = @WARN_CFLAGS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-AUTOMAKE_OPTIONS = 1.7
-PLATFORM_VERSION = 3.0
-pkginclude_HEADERS = pygobject.h
-extension_cppflags = \
- $(PYTHON_INCLUDES) \
- -DPY_SSIZE_T_CLEAN
-
-extension_ldflags = -module -avoid-version -shrext $(PYTHON_SO) \
- $(am__append_1)
-
-# Windows requires Python modules to be explicitly linked to libpython.
-# Extension modules are shared libaries (.dll), but need to be
-# called .pyd for Python to load it as an extension module.
-@OS_WIN32_TRUE@extension_libadd = \
-@OS_WIN32_TRUE@ $(PYTHON_LIBS)
-
-pygobjectdir = $(pyexecdir)/gi/_gobject
-pygobject_PYTHON = \
- __init__.py \
- constants.py \
- propertyhelper.py \
- signalhelper.py
-
-pygobject_LTLIBRARIES = _gobject.la
-_gobject_la_SOURCES = \
- gobjectmodule.c \
- pygboxed.c \
- pygboxed.h \
- pygenum.c \
- pygenum.h \
- pygflags.c \
- pygflags.h \
- pyginterface.c \
- pyginterface.h \
- pygobject.c \
- pygobject.h \
- pygobject-private.h \
- pygparamspec.c \
- pygparamspec.h \
- pygpointer.c \
- pygpointer.h \
- pygtype.c \
- pygtype.h
-
-_gobject_la_CFLAGS = \
- $(extension_cppflags) \
- -I$(top_srcdir)/gi/_glib \
- -I$(top_srcdir)/gi \
- $(GLIB_CFLAGS) \
- $(GI_CFLAGS)
-
-_gi_la_CPPFLAGS = \
- $(extension_cppflags)
-
-_gobject_la_LIBADD = \
- $(extension_libadd) \
- $(GLIB_LIBS) \
- $(GI_LIBS) \
- $(top_builddir)/gi/_glib/libpyglib-gi-2.0-@PYTHON_BASENAME@.la
-
-_gobject_la_LDFLAGS = \
- $(extension_ldflags) \
- -export-symbols-regex "_gobject|PyInit__gobject"
-
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign gi/_gobject/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign gi/_gobject/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-install-pygobjectLTLIBRARIES: $(pygobject_LTLIBRARIES)
- @$(NORMAL_INSTALL)
- @list='$(pygobject_LTLIBRARIES)'; test -n "$(pygobjectdir)" || list=; \
- list2=; for p in $$list; do \
- if test -f $$p; then \
- list2="$$list2 $$p"; \
- else :; fi; \
- done; \
- test -z "$$list2" || { \
- echo " $(MKDIR_P) '$(DESTDIR)$(pygobjectdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pygobjectdir)" || exit 1; \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pygobjectdir)'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pygobjectdir)"; \
- }
-
-uninstall-pygobjectLTLIBRARIES:
- @$(NORMAL_UNINSTALL)
- @list='$(pygobject_LTLIBRARIES)'; test -n "$(pygobjectdir)" || list=; \
- for p in $$list; do \
- $(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pygobjectdir)/$$f'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pygobjectdir)/$$f"; \
- done
-
-clean-pygobjectLTLIBRARIES:
- -test -z "$(pygobject_LTLIBRARIES)" || rm -f $(pygobject_LTLIBRARIES)
- @list='$(pygobject_LTLIBRARIES)'; \
- locs=`for p in $$list; do echo $$p; done | \
- sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
- sort -u`; \
- test -z "$$locs" || { \
- echo rm -f $${locs}; \
- rm -f $${locs}; \
- }
-
-_gobject.la: $(_gobject_la_OBJECTS) $(_gobject_la_DEPENDENCIES) $(EXTRA__gobject_la_DEPENDENCIES)
- $(AM_V_CCLD)$(_gobject_la_LINK) -rpath $(pygobjectdir) $(_gobject_la_OBJECTS) $(_gobject_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-gobjectmodule.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-pygboxed.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-pygenum.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-pygflags.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-pyginterface.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-pygobject.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-pygparamspec.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-pygpointer.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/_gobject_la-pygtype.Plo@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-_gobject_la-gobjectmodule.lo: gobjectmodule.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-gobjectmodule.lo -MD -MP -MF $(DEPDIR)/_gobject_la-gobjectmodule.Tpo -c -o _gobject_la-gobjectmodule.lo `test -f 'gobjectmodule.c' || echo '$(srcdir)/'`gobjectmodule.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-gobjectmodule.Tpo $(DEPDIR)/_gobject_la-gobjectmodule.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gobjectmodule.c' object='_gobject_la-gobjectmodule.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-gobjectmodule.lo `test -f 'gobjectmodule.c' || echo '$(srcdir)/'`gobjectmodule.c
-
-_gobject_la-pygboxed.lo: pygboxed.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-pygboxed.lo -MD -MP -MF $(DEPDIR)/_gobject_la-pygboxed.Tpo -c -o _gobject_la-pygboxed.lo `test -f 'pygboxed.c' || echo '$(srcdir)/'`pygboxed.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-pygboxed.Tpo $(DEPDIR)/_gobject_la-pygboxed.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygboxed.c' object='_gobject_la-pygboxed.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-pygboxed.lo `test -f 'pygboxed.c' || echo '$(srcdir)/'`pygboxed.c
-
-_gobject_la-pygenum.lo: pygenum.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-pygenum.lo -MD -MP -MF $(DEPDIR)/_gobject_la-pygenum.Tpo -c -o _gobject_la-pygenum.lo `test -f 'pygenum.c' || echo '$(srcdir)/'`pygenum.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-pygenum.Tpo $(DEPDIR)/_gobject_la-pygenum.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygenum.c' object='_gobject_la-pygenum.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-pygenum.lo `test -f 'pygenum.c' || echo '$(srcdir)/'`pygenum.c
-
-_gobject_la-pygflags.lo: pygflags.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-pygflags.lo -MD -MP -MF $(DEPDIR)/_gobject_la-pygflags.Tpo -c -o _gobject_la-pygflags.lo `test -f 'pygflags.c' || echo '$(srcdir)/'`pygflags.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-pygflags.Tpo $(DEPDIR)/_gobject_la-pygflags.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygflags.c' object='_gobject_la-pygflags.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-pygflags.lo `test -f 'pygflags.c' || echo '$(srcdir)/'`pygflags.c
-
-_gobject_la-pyginterface.lo: pyginterface.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-pyginterface.lo -MD -MP -MF $(DEPDIR)/_gobject_la-pyginterface.Tpo -c -o _gobject_la-pyginterface.lo `test -f 'pyginterface.c' || echo '$(srcdir)/'`pyginterface.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-pyginterface.Tpo $(DEPDIR)/_gobject_la-pyginterface.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pyginterface.c' object='_gobject_la-pyginterface.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-pyginterface.lo `test -f 'pyginterface.c' || echo '$(srcdir)/'`pyginterface.c
-
-_gobject_la-pygobject.lo: pygobject.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-pygobject.lo -MD -MP -MF $(DEPDIR)/_gobject_la-pygobject.Tpo -c -o _gobject_la-pygobject.lo `test -f 'pygobject.c' || echo '$(srcdir)/'`pygobject.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-pygobject.Tpo $(DEPDIR)/_gobject_la-pygobject.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygobject.c' object='_gobject_la-pygobject.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-pygobject.lo `test -f 'pygobject.c' || echo '$(srcdir)/'`pygobject.c
-
-_gobject_la-pygparamspec.lo: pygparamspec.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-pygparamspec.lo -MD -MP -MF $(DEPDIR)/_gobject_la-pygparamspec.Tpo -c -o _gobject_la-pygparamspec.lo `test -f 'pygparamspec.c' || echo '$(srcdir)/'`pygparamspec.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-pygparamspec.Tpo $(DEPDIR)/_gobject_la-pygparamspec.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygparamspec.c' object='_gobject_la-pygparamspec.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-pygparamspec.lo `test -f 'pygparamspec.c' || echo '$(srcdir)/'`pygparamspec.c
-
-_gobject_la-pygpointer.lo: pygpointer.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-pygpointer.lo -MD -MP -MF $(DEPDIR)/_gobject_la-pygpointer.Tpo -c -o _gobject_la-pygpointer.lo `test -f 'pygpointer.c' || echo '$(srcdir)/'`pygpointer.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-pygpointer.Tpo $(DEPDIR)/_gobject_la-pygpointer.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygpointer.c' object='_gobject_la-pygpointer.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-pygpointer.lo `test -f 'pygpointer.c' || echo '$(srcdir)/'`pygpointer.c
-
-_gobject_la-pygtype.lo: pygtype.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) $(_gobject_la_CFLAGS) $(CFLAGS) -MT _gobject_la-pygtype.lo -MD -MP -MF $(DEPDIR)/_gobject_la-pygtype.Tpo -c -o _gobject_la-pygtype.lo `test -f 'pygtype.c' || echo '$(srcdir)/'`pygtype.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/_gobject_la-pygtype.Tpo $(DEPDIR)/_gobject_la-pygtype.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pygtype.c' object='_gobject_la-pygtype.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_gobject_la_CFLAGS) $(CFLAGS) -c -o _gobject_la-pygtype.lo `test -f 'pygtype.c' || echo '$(srcdir)/'`pygtype.c
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-pygobjectPYTHON: $(pygobject_PYTHON)
- @$(NORMAL_INSTALL)
- @list='$(pygobject_PYTHON)'; dlist=; list2=; test -n "$(pygobjectdir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(pygobjectdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pygobjectdir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \
- if test -f $$b$$p; then \
- $(am__strip_dir) \
- dlist="$$dlist $$f"; \
- list2="$$list2 $$b$$p"; \
- else :; fi; \
- done; \
- for file in $$list2; do echo $$file; done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pygobjectdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(pygobjectdir)" || exit $$?; \
- done || exit $$?; \
- if test -n "$$dlist"; then \
- $(am__py_compile) --destdir "$(DESTDIR)" \
- --basedir "$(pygobjectdir)" $$dlist; \
- else :; fi
-
-uninstall-pygobjectPYTHON:
- @$(NORMAL_UNINSTALL)
- @list='$(pygobject_PYTHON)'; test -n "$(pygobjectdir)" || list=; \
- py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$py_files" || exit 0; \
- dir='$(DESTDIR)$(pygobjectdir)'; \
- pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \
- pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \
- py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \
- echo "$$py_files_pep3147";\
- pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \
- pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \
- st=0; \
- for files in \
- "$$py_files" \
- "$$pyc_files" \
- "$$pyo_files" \
- "$$pyc_files_pep3147" \
- "$$pyo_files_pep3147" \
- ; do \
- $(am__uninstall_files_from_dir) || st=$$?; \
- done; \
- exit $$st
-install-pkgincludeHEADERS: $(pkginclude_HEADERS)
- @$(NORMAL_INSTALL)
- @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; \
- done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
- $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
- done
-
-uninstall-pkgincludeHEADERS:
- @$(NORMAL_UNINSTALL)
- @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
- files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
-
-ID: $(am__tagged_files)
- $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- set x; \
- here=`pwd`; \
- $(am__define_uniq_tagged_files); \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
- list='$(am__tagged_files)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) check-local
-check: check-am
-all-am: Makefile $(LTLIBRARIES) $(HEADERS)
-installdirs:
- for dir in "$(DESTDIR)$(pygobjectdir)" "$(DESTDIR)$(pygobjectdir)" "$(DESTDIR)$(pkgincludedir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool clean-local \
- clean-pygobjectLTLIBRARIES mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-pkgincludeHEADERS \
- install-pygobjectLTLIBRARIES install-pygobjectPYTHON
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-pkgincludeHEADERS \
- uninstall-pygobjectLTLIBRARIES uninstall-pygobjectPYTHON
-
-.MAKE: check-am install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \
- clean-generic clean-libtool clean-local \
- clean-pygobjectLTLIBRARIES cscopelist-am ctags ctags-am \
- distclean distclean-compile distclean-generic \
- distclean-libtool distclean-tags distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-pdf install-pdf-am \
- install-pkgincludeHEADERS install-ps install-ps-am \
- install-pygobjectLTLIBRARIES install-pygobjectPYTHON \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
- pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
- uninstall-pkgincludeHEADERS uninstall-pygobjectLTLIBRARIES \
- uninstall-pygobjectPYTHON
-
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pygobject_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-all: $(pygobject_LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-check-local: $(pygobject_LTLIBRARIES:.la=$(PYTHON_SO)) build_pylinks
-clean-local:
- rm -f $(pygobject_LTLIBRARIES:.la=$(PYTHON_SO))
-%$(PYTHON_SO): %.la
- $(LN_S) -f .libs/$@ $@
-
-# 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.
-.NOEXPORT:
diff --git a/gi/_gobject/__init__.py b/gi/_gobject/__init__.py
deleted file mode 100644
index d3ea0e0..0000000
--- a/gi/_gobject/__init__.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-# pygobject - Python bindings for the GObject library
-# Copyright (C) 2006-2012 Johan Dahlin
-#
-# gobject/__init__.py: initialisation file for gobject module
-#
-# 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 Street, Fifth Floor, Boston, MA 02110-1301
-# USA
-
-# this can go when things are a little further along
-
-import sys
-
-# we can't have pygobject 2 loaded at the same time we load the internal _gobject
-if 'gobject' in sys.modules:
- raise ImportError('When using gi.repository you must not import static modules like "gobject". Please change all occurrences of "import gobject" to "from gi.repository import GObject".')
-
-from . import _gobject
-from . import propertyhelper
-from . import signalhelper
-
-GObject = _gobject.GObject
-GType = _gobject.GType
-_PyGObject_API = _gobject._PyGObject_API
-pygobject_version = _gobject.pygobject_version
-
-
-class GObjectMeta(type):
- "Metaclass for automatically registering GObject classes"
- def __init__(cls, name, bases, dict_):
- type.__init__(cls, name, bases, dict_)
- propertyhelper.install_properties(cls)
- signalhelper.install_signals(cls)
- cls._type_register(cls.__dict__)
-
- def _type_register(cls, namespace):
- ## don't register the class if already registered
- if '__gtype__' in namespace:
- return
-
- # Do not register a new GType for the overrides, as this would sort of
- # defeat the purpose of overrides...
- if cls.__module__.startswith('gi.overrides.'):
- return
-
- _gobject.type_register(cls, namespace.get('__gtype_name__'))
-
-_gobject._install_metaclass(GObjectMeta)
diff --git a/gi/_gobject/constants.py b/gi/_gobject/constants.py
deleted file mode 100644
index 9565a66..0000000
--- a/gi/_gobject/constants.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- Mode: Python; py-indent-offset: 4 -*-
-# pygobject - Python bindings for the GObject library
-# Copyright (C) 2006-2007 Johan Dahlin
-#
-# gobject/constants.py: GObject type constants
-#
-# 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 Street, Fifth Floor, Boston, MA 02110-1301
-# USA
-
-from . import _gobject
-
-TYPE_INVALID = _gobject.TYPE_INVALID
-TYPE_NONE = _gobject.type_from_name('void')
-TYPE_INTERFACE = _gobject.type_from_name('GInterface')
-TYPE_CHAR = _gobject.type_from_name('gchar')
-TYPE_UCHAR = _gobject.type_from_name('guchar')
-TYPE_BOOLEAN = _gobject.type_from_name('gboolean')
-TYPE_INT = _gobject.type_from_name('gint')
-TYPE_UINT = _gobject.type_from_name('guint')
-TYPE_LONG = _gobject.type_from_name('glong')
-TYPE_ULONG = _gobject.type_from_name('gulong')
-TYPE_INT64 = _gobject.type_from_name('gint64')
-TYPE_UINT64 = _gobject.type_from_name('guint64')
-TYPE_ENUM = _gobject.type_from_name('GEnum')
-TYPE_FLAGS = _gobject.type_from_name('GFlags')
-TYPE_FLOAT = _gobject.type_from_name('gfloat')
-TYPE_DOUBLE = _gobject.type_from_name('gdouble')
-TYPE_STRING = _gobject.type_from_name('gchararray')
-TYPE_POINTER = _gobject.type_from_name('gpointer')
-TYPE_BOXED = _gobject.type_from_name('GBoxed')
-TYPE_PARAM = _gobject.type_from_name('GParam')
-TYPE_OBJECT = _gobject.type_from_name('GObject')
-TYPE_PYOBJECT = _gobject.type_from_name('PyObject')
-TYPE_GTYPE = _gobject.type_from_name('GType')
-TYPE_STRV = _gobject.type_from_name('GStrv')
-TYPE_VARIANT = _gobject.type_from_name('GVariant')
-TYPE_UNICHAR = TYPE_UINT
diff --git a/gi/_gobject/gobjectmodule.c b/gi/_gobject/gobjectmodule.c
deleted file mode 100644
index ac37904..0000000
--- a/gi/_gobject/gobjectmodule.c
+++ /dev/null
@@ -1,2220 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pygtk- Python bindings for the GTK toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- *
- * gobjectmodule.c: wrapper for the gobject library.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <gobject/gvaluecollector.h>
-#include <girepository.h>
-#include <pyglib.h>
-#include <pythread.h>
-#include "pygobject-private.h"
-#include "pygboxed.h"
-#include "pygenum.h"
-#include "pygflags.h"
-#include "pyginterface.h"
-#include "pygparamspec.h"
-#include "pygpointer.h"
-#include "pygtype.h"
-
-static GHashTable *log_handlers = NULL;
-static gboolean log_handlers_disabled = FALSE;
-
-static void pyg_flags_add_constants(PyObject *module, GType flags_type,
- const gchar *strip_prefix);
-
-
-/* -------------- GDK threading hooks ---------------------------- */
-
-/**
- * pyg_set_thread_block_funcs:
- * Deprecated, only available for ABI compatibility.
- */
-static void
-_pyg_set_thread_block_funcs (PyGThreadBlockFunc block_threads_func,
- PyGThreadBlockFunc unblock_threads_func)
-{
- PyGILState_STATE state = pyglib_gil_state_ensure ();
- PyErr_Warn (PyExc_DeprecationWarning,
- "Using pyg_set_thread_block_funcs is not longer needed. "
- "PyGObject always uses Py_BLOCK/UNBLOCK_THREADS.");
- pyglib_gil_state_release (state);
-}
-
-/**
- * pyg_destroy_notify:
- * @user_data: a PyObject pointer.
- *
- * A function that can be used as a GDestroyNotify callback that will
- * call Py_DECREF on the data.
- */
-void
-pyg_destroy_notify(gpointer user_data)
-{
- PyObject *obj = (PyObject *)user_data;
- PyGILState_STATE state;
-
- state = pyglib_gil_state_ensure();
- Py_DECREF(obj);
- pyglib_gil_state_release(state);
-}
-
-
-/* ---------------- gobject module functions -------------------- */
-
-static PyObject *
-pyg_type_name (PyObject *self, PyObject *args)
-{
- PyObject *gtype;
- GType type;
- const gchar *name;
-
-#if 0
- if (PyErr_Warn(PyExc_DeprecationWarning,
- "gobject.type_name is deprecated; "
- "use GType.name instead"))
- return NULL;
-#endif
-
- if (!PyArg_ParseTuple(args, "O:gobject.type_name", &gtype))
- return NULL;
- if ((type = pyg_type_from_object(gtype)) == 0)
- return NULL;
- name = g_type_name(type);
- if (name)
- return PYGLIB_PyUnicode_FromString(name);
- PyErr_SetString(PyExc_RuntimeError, "unknown typecode");
- return NULL;
-}
-
-static PyObject *
-pyg_type_from_name (PyObject *self, PyObject *args)
-{
- const gchar *name;
- GType type;
- PyObject *repr = NULL;
-#if 0
- if (PyErr_Warn(PyExc_DeprecationWarning,
- "gobject.type_from_name is deprecated; "
- "use GType.from_name instead"))
- return NULL;
-#endif
- if (!PyArg_ParseTuple(args, "s:gobject.type_from_name", &name))
- return NULL;
- type = g_type_from_name(name);
- if (type != 0)
- return pyg_type_wrapper_new(type);
- repr = PyObject_Repr((PyObject*)self);
- PyErr_Format(PyExc_RuntimeError, "%s: unknown type name: %s",
- PYGLIB_PyUnicode_AsString(repr),
- name);
- Py_DECREF(repr);
- return NULL;
-}
-
-static PyObject *
-pyg_type_is_a (PyObject *self, PyObject *args)
-{
- PyObject *gtype, *gparent;
- GType type, parent;
-#if 0
- if (PyErr_Warn(PyExc_DeprecationWarning,
- "gobject.type_is_a is deprecated; "
- "use GType.is_a instead"))
- return NULL;
-#endif
- if (!PyArg_ParseTuple(args, "OO:gobject.type_is_a", &gtype, &gparent))
- return NULL;
- if ((type = pyg_type_from_object(gtype)) == 0)
- return NULL;
- if ((parent = pyg_type_from_object(gparent)) == 0)
- return NULL;
- return PyBool_FromLong(g_type_is_a(type, parent));
-}
-
-static void
-pyg_object_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- PyObject *object_wrapper, *retval;
- PyObject *py_pspec, *py_value;
- PyGILState_STATE state;
-
- state = pyglib_gil_state_ensure();
-
- object_wrapper = pygobject_new(object);
-
- if (object_wrapper == NULL) {
- pyglib_gil_state_release(state);
- return;
- }
-
- py_pspec = pyg_param_spec_new(pspec);
- py_value = pyg_value_as_pyobject (value, TRUE);
-
- retval = PyObject_CallMethod(object_wrapper, "do_set_property",
- "OO", py_pspec, py_value);
- if (retval) {
- Py_DECREF(retval);
- } else {
- PyErr_Print();
- }
-
- Py_DECREF(object_wrapper);
- Py_DECREF(py_pspec);
- Py_DECREF(py_value);
-
- pyglib_gil_state_release(state);
-}
-
-static void
-pyg_object_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- PyObject *object_wrapper, *retval;
- PyObject *py_pspec;
- PyGILState_STATE state;
-
- state = pyglib_gil_state_ensure();
-
- object_wrapper = pygobject_new(object);
-
- if (object_wrapper == NULL) {
- pyglib_gil_state_release(state);
- return;
- }
-
- py_pspec = pyg_param_spec_new(pspec);
- retval = PyObject_CallMethod(object_wrapper, "do_get_property",
- "O", py_pspec);
- if (retval == NULL || pyg_value_from_pyobject(value, retval) < 0) {
- PyErr_Print();
- }
- Py_DECREF(object_wrapper);
- Py_DECREF(py_pspec);
- Py_XDECREF(retval);
-
- pyglib_gil_state_release(state);
-}
-
-typedef struct _PyGSignalAccumulatorData {
- PyObject *callable;
- PyObject *user_data;
-} PyGSignalAccumulatorData;
-
-static gboolean
-_pyg_signal_accumulator(GSignalInvocationHint *ihint,
- GValue *return_accu,
- const GValue *handler_return,
- gpointer _data)
-{
- PyObject *py_ihint, *py_return_accu, *py_handler_return, *py_detail;
- PyObject *py_retval;
- gboolean retval = FALSE;
- PyGSignalAccumulatorData *data = _data;
- PyGILState_STATE state;
-
- state = pyglib_gil_state_ensure();
- if (ihint->detail)
- py_detail = PYGLIB_PyUnicode_FromString(g_quark_to_string(ihint->detail));
- else {
- Py_INCREF(Py_None);
- py_detail = Py_None;
- }
-
- py_ihint = Py_BuildValue("lNi", (long int) ihint->signal_id,
- py_detail, ihint->run_type);
- py_handler_return = pyg_value_as_pyobject(handler_return, TRUE);
- py_return_accu = pyg_value_as_pyobject(return_accu, FALSE);
- if (data->user_data)
- py_retval = PyObject_CallFunction(data->callable, "NNNO", py_ihint,
- py_return_accu, py_handler_return,
- data->user_data);
- else
- py_retval = PyObject_CallFunction(data->callable, "NNN", py_ihint,
- py_return_accu, py_handler_return);
- if (!py_retval)
- PyErr_Print();
- else {
- if (!PyTuple_Check(py_retval) || PyTuple_Size(py_retval) != 2) {
- PyErr_SetString(PyExc_TypeError, "accumulator function must return"
- " a (bool, object) tuple");
- PyErr_Print();
- } else {
- retval = PyObject_IsTrue(PyTuple_GET_ITEM(py_retval, 0));
- if (pyg_value_from_pyobject(return_accu, PyTuple_GET_ITEM(py_retval, 1))) {
- PyErr_Print();
- }
- }
- Py_DECREF(py_retval);
- }
- pyglib_gil_state_release(state);
- return retval;
-}
-
-static gboolean
-create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple)
-{
- GSignalFlags signal_flags;
- PyObject *py_return_type, *py_param_types;
- GType return_type;
- guint n_params, i;
- GType *param_types;
- guint signal_id;
- GSignalAccumulator accumulator = NULL;
- PyGSignalAccumulatorData *accum_data = NULL;
- PyObject *py_accum = NULL, *py_accum_data = NULL;
-
- if (!PyArg_ParseTuple(tuple, "iOO|OO", &signal_flags, &py_return_type,
- &py_param_types, &py_accum, &py_accum_data))
- {
- gchar buf[128];
-
- PyErr_Clear();
- g_snprintf(buf, sizeof(buf),
- "value for __gsignals__['%s'] not in correct format", signal_name);
- PyErr_SetString(PyExc_TypeError, buf);
- return FALSE;
- }
-
- if (py_accum && py_accum != Py_None && !PyCallable_Check(py_accum))
- {
- gchar buf[128];
-
- g_snprintf(buf, sizeof(buf),
- "accumulator for __gsignals__['%s'] must be callable", signal_name);
- PyErr_SetString(PyExc_TypeError, buf);
- return FALSE;
- }
-
- return_type = pyg_type_from_object(py_return_type);
- if (!return_type)
- return FALSE;
- if (!PySequence_Check(py_param_types)) {
- gchar buf[128];
-
- g_snprintf(buf, sizeof(buf),
- "third element of __gsignals__['%s'] tuple must be a sequence", signal_name);
- PyErr_SetString(PyExc_TypeError, buf);
- return FALSE;
- }
- n_params = PySequence_Length(py_param_types);
- param_types = g_new(GType, n_params);
- for (i = 0; i < n_params; i++) {
- PyObject *item = PySequence_GetItem(py_param_types, i);
-
- param_types[i] = pyg_type_from_object(item);
- if (param_types[i] == 0) {
- Py_DECREF(item);
- g_free(param_types);
- return FALSE;
- }
- Py_DECREF(item);
- }
-
- if (py_accum != NULL && py_accum != Py_None) {
- accum_data = g_new(PyGSignalAccumulatorData, 1);
- accum_data->callable = py_accum;
- Py_INCREF(py_accum);
- accum_data->user_data = py_accum_data;
- Py_XINCREF(py_accum_data);
- accumulator = _pyg_signal_accumulator;
- }
-
- signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
- pyg_signal_class_closure_get(),
- accumulator, accum_data,
- gi_cclosure_marshal_generic,
- return_type, n_params, param_types);
- g_free(param_types);
-
- if (signal_id == 0) {
- gchar buf[128];
-
- g_snprintf(buf, sizeof(buf), "could not create signal for %s",
- signal_name);
- PyErr_SetString(PyExc_RuntimeError, buf);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-override_signal(GType instance_type, const gchar *signal_name)
-{
- guint signal_id;
-
- signal_id = g_signal_lookup(signal_name, instance_type);
- if (!signal_id) {
- gchar buf[128];
-
- g_snprintf(buf, sizeof(buf), "could not look up %s", signal_name);
- PyErr_SetString(PyExc_TypeError, buf);
- return FALSE;
- }
- g_signal_override_class_closure(signal_id, instance_type,
- pyg_signal_class_closure_get());
- return TRUE;
-}
-
-static PyObject *
-add_signals (GObjectClass *klass, PyObject *signals)
-{
- gboolean ret = TRUE;
- Py_ssize_t pos = 0;
- PyObject *key, *value, *overridden_signals = NULL;
- GType instance_type = G_OBJECT_CLASS_TYPE (klass);
-
- overridden_signals = PyDict_New();
- while (PyDict_Next(signals, &pos, &key, &value)) {
- const gchar *signal_name;
- gchar *signal_name_canon, *c;
-
- if (!PYGLIB_PyUnicode_Check(key)) {
- PyErr_SetString(PyExc_TypeError,
- "__gsignals__ keys must be strings");
- ret = FALSE;
- break;
- }
- signal_name = PYGLIB_PyUnicode_AsString (key);
-
- if (value == Py_None ||
- (PYGLIB_PyUnicode_Check(value) &&
- !strcmp(PYGLIB_PyUnicode_AsString(value), "override")))
- {
- /* canonicalize signal name, replacing '-' with '_' */
- signal_name_canon = g_strdup(signal_name);
- for (c = signal_name_canon; *c; ++c)
- if (*c == '-')
- *c = '_';
- if (PyDict_SetItemString(overridden_signals,
- signal_name_canon, key)) {
- g_free(signal_name_canon);
- ret = FALSE;
- break;
- }
- g_free(signal_name_canon);
-
- ret = override_signal(instance_type, signal_name);
- } else {
- ret = create_signal(instance_type, signal_name, value);
- }
-
- if (!ret)
- break;
- }
- if (ret)
- return overridden_signals;
- else {
- Py_XDECREF(overridden_signals);
- return NULL;
- }
-}
-
-static GParamSpec *
-create_property (const gchar *prop_name,
- GType prop_type,
- const gchar *nick,
- const gchar *blurb,
- PyObject *args,
- GParamFlags flags)
-{
- GParamSpec *pspec = NULL;
-
- switch (G_TYPE_FUNDAMENTAL(prop_type)) {
- case G_TYPE_CHAR:
- {
- gchar minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_char (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_UCHAR:
- {
- gchar minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_uchar (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_BOOLEAN:
- {
- gboolean default_value;
-
- if (!PyArg_ParseTuple(args, "i", &default_value))
- return NULL;
- pspec = g_param_spec_boolean (prop_name, nick, blurb,
- default_value, flags);
- }
- break;
- case G_TYPE_INT:
- {
- gint minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "iii", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_int (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_UINT:
- {
- guint minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "III", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_uint (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_LONG:
- {
- glong minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "lll", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_long (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_ULONG:
- {
- gulong minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "kkk", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_ulong (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_INT64:
- {
- gint64 minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "LLL", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_int64 (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_UINT64:
- {
- guint64 minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "KKK", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_uint64 (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_ENUM:
- {
- gint default_value;
- PyObject *pydefault;
-
- if (!PyArg_ParseTuple(args, "O", &pydefault))
- return NULL;
-
- if (pyg_enum_get_value(prop_type, pydefault,
- (gint *)&default_value))
- return NULL;
-
- pspec = g_param_spec_enum (prop_name, nick, blurb,
- prop_type, default_value, flags);
- }
- break;
- case G_TYPE_FLAGS:
- {
- guint default_value;
- PyObject *pydefault;
-
- if (!PyArg_ParseTuple(args, "O", &pydefault))
- return NULL;
-
- if (pyg_flags_get_value(prop_type, pydefault,
- &default_value))
- return NULL;
-
- pspec = g_param_spec_flags (prop_name, nick, blurb,
- prop_type, default_value, flags);
- }
- break;
- case G_TYPE_FLOAT:
- {
- gfloat minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "fff", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_float (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_DOUBLE:
- {
- gdouble minimum, maximum, default_value;
-
- if (!PyArg_ParseTuple(args, "ddd", &minimum, &maximum,
- &default_value))
- return NULL;
- pspec = g_param_spec_double (prop_name, nick, blurb, minimum,
- maximum, default_value, flags);
- }
- break;
- case G_TYPE_STRING:
- {
- const gchar *default_value;
-
- if (!PyArg_ParseTuple(args, "z", &default_value))
- return NULL;
- pspec = g_param_spec_string (prop_name, nick, blurb,
- default_value, flags);
- }
- break;
- case G_TYPE_PARAM:
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- pspec = g_param_spec_param (prop_name, nick, blurb, prop_type, flags);
- break;
- case G_TYPE_BOXED:
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- pspec = g_param_spec_boxed (prop_name, nick, blurb, prop_type, flags);
- break;
- case G_TYPE_POINTER:
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- if (prop_type == G_TYPE_GTYPE)
- pspec = g_param_spec_gtype (prop_name, nick, blurb, G_TYPE_NONE, flags);
- else
- pspec = g_param_spec_pointer (prop_name, nick, blurb, flags);
- break;
- case G_TYPE_OBJECT:
- case G_TYPE_INTERFACE:
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- pspec = g_param_spec_object (prop_name, nick, blurb, prop_type, flags);
- break;
- case G_TYPE_VARIANT:
- {
- PyObject *pydefault;
- GVariant *default_value = NULL;
-
- if (!PyArg_ParseTuple(args, "O", &pydefault))
- return NULL;
- if (pydefault != Py_None)
- default_value = pyg_boxed_get (pydefault, GVariant);
- pspec = g_param_spec_variant (prop_name, nick, blurb, G_VARIANT_TYPE_ANY, default_value, flags);
- }
- break;
- default:
- /* unhandled pspec type ... */
- break;
- }
-
- if (!pspec) {
- char buf[128];
-
- g_snprintf(buf, sizeof(buf), "could not create param spec for type %s",
- g_type_name(prop_type));
- PyErr_SetString(PyExc_TypeError, buf);
- return NULL;
- }
-
- return pspec;
-}
-
-static GParamSpec *
-pyg_param_spec_from_object (PyObject *tuple)
-{
- gint val_length;
- const gchar *prop_name;
- GType prop_type;
- const gchar *nick, *blurb;
- PyObject *slice, *item, *py_prop_type;
- GParamSpec *pspec;
-
- val_length = PyTuple_Size(tuple);
- if (val_length < 4) {
- PyErr_SetString(PyExc_TypeError,
- "paramspec tuples must be at least 4 elements long");
- return NULL;
- }
-
- slice = PySequence_GetSlice(tuple, 0, 4);
- if (!slice) {
- return NULL;
- }
-
- if (!PyArg_ParseTuple(slice, "sOzz", &prop_name, &py_prop_type, &nick, &blurb)) {
- Py_DECREF(slice);
- return NULL;
- }
-
- Py_DECREF(slice);
-
- prop_type = pyg_type_from_object(py_prop_type);
- if (!prop_type) {
- return NULL;
- }
-
- item = PyTuple_GetItem(tuple, val_length-1);
- if (!PYGLIB_PyLong_Check(item)) {
- PyErr_SetString(PyExc_TypeError,
- "last element in tuple must be an int");
- return NULL;
- }
-
- /* slice is the extra items in the tuple */
- slice = PySequence_GetSlice(tuple, 4, val_length-1);
- pspec = create_property(prop_name, prop_type,
- nick, blurb, slice,
- PYGLIB_PyLong_AsLong(item));
-
- return pspec;
-}
-
-static gboolean
-add_properties (GObjectClass *klass, PyObject *properties)
-{
- gboolean ret = TRUE;
- Py_ssize_t pos = 0;
- PyObject *key, *value;
-
- while (PyDict_Next(properties, &pos, &key, &value)) {
- const gchar *prop_name;
- GType prop_type;
- const gchar *nick, *blurb;
- GParamFlags flags;
- gint val_length;
- PyObject *slice, *item, *py_prop_type;
- GParamSpec *pspec;
-
- /* values are of format (type,nick,blurb, type_specific_args, flags) */
-
- if (!PYGLIB_PyUnicode_Check(key)) {
- PyErr_SetString(PyExc_TypeError,
- "__gproperties__ keys must be strings");
- ret = FALSE;
- break;
- }
- prop_name = PYGLIB_PyUnicode_AsString (key);
-
- if (!PyTuple_Check(value)) {
- PyErr_SetString(PyExc_TypeError,
- "__gproperties__ values must be tuples");
- ret = FALSE;
- break;
- }
- val_length = PyTuple_Size(value);
- if (val_length < 4) {
- PyErr_SetString(PyExc_TypeError,
- "__gproperties__ values must be at least 4 elements long");
- ret = FALSE;
- break;
- }
-
- slice = PySequence_GetSlice(value, 0, 3);
- if (!slice) {
- ret = FALSE;
- break;
- }
- if (!PyArg_ParseTuple(slice, "Ozz", &py_prop_type, &nick, &blurb)) {
- Py_DECREF(slice);
- ret = FALSE;
- break;
- }
- Py_DECREF(slice);
- prop_type = pyg_type_from_object(py_prop_type);
- if (!prop_type) {
- ret = FALSE;
- break;
- }
- item = PyTuple_GetItem(value, val_length-1);
- if (!PYGLIB_PyLong_Check(item)) {
- PyErr_SetString(PyExc_TypeError,
- "last element in __gproperties__ value tuple must be an int");
- ret = FALSE;
- break;
- }
- flags = PYGLIB_PyLong_AsLong(item);
-
- /* slice is the extra items in the tuple */
- slice = PySequence_GetSlice(value, 3, val_length-1);
- pspec = create_property(prop_name, prop_type, nick, blurb,
- slice, flags);
- Py_DECREF(slice);
-
- if (pspec) {
- g_object_class_install_property(klass, 1, pspec);
- } else {
- PyObject *type, *value, *traceback;
- ret = FALSE;
- PyErr_Fetch(&type, &value, &traceback);
- if (PYGLIB_PyUnicode_Check(value)) {
- char msg[256];
- g_snprintf(msg, 256,
- "%s (while registering property '%s' for GType '%s')",
- PYGLIB_PyUnicode_AsString(value),
- prop_name, G_OBJECT_CLASS_NAME(klass));
- Py_DECREF(value);
- value = PYGLIB_PyUnicode_FromString(msg);
- }
- PyErr_Restore(type, value, traceback);
- break;
- }
- }
-
- return ret;
-}
-
-static void
-pyg_object_class_init(GObjectClass *class, PyObject *py_class)
-{
- PyObject *gproperties, *gsignals, *overridden_signals;
- PyObject *class_dict = ((PyTypeObject*) py_class)->tp_dict;
-
- class->set_property = pyg_object_set_property;
- class->get_property = pyg_object_get_property;
-
- /* install signals */
- /* we look this up in the instance dictionary, so we don't
- * accidentally get a parent type's __gsignals__ attribute. */
- gsignals = PyDict_GetItemString(class_dict, "__gsignals__");
- if (gsignals) {
- if (!PyDict_Check(gsignals)) {
- PyErr_SetString(PyExc_TypeError,
- "__gsignals__ attribute not a dict!");
- return;
- }
- if (!(overridden_signals = add_signals(class, gsignals))) {
- return;
- }
- if (PyDict_SetItemString(class_dict, "__gsignals__",
- overridden_signals)) {
- return;
- }
- Py_DECREF(overridden_signals);
-
- PyDict_DelItemString(class_dict, "__gsignals__");
- } else {
- PyErr_Clear();
- }
-
- /* install properties */
- /* we look this up in the instance dictionary, so we don't
- * accidentally get a parent type's __gproperties__ attribute. */
- gproperties = PyDict_GetItemString(class_dict, "__gproperties__");
- if (gproperties) {
- if (!PyDict_Check(gproperties)) {
- PyErr_SetString(PyExc_TypeError,
- "__gproperties__ attribute not a dict!");
- return;
- }
- if (!add_properties(class, gproperties)) {
- return;
- }
- PyDict_DelItemString(class_dict, "__gproperties__");
- /* Borrowed reference. Py_DECREF(gproperties); */
- } else {
- PyErr_Clear();
- }
-}
-
-static void
-pyg_register_class_init(GType gtype, PyGClassInitFunc class_init)
-{
- GSList *list;
-
- list = g_type_get_qdata(gtype, pygobject_class_init_key);
- list = g_slist_prepend(list, class_init);
- g_type_set_qdata(gtype, pygobject_class_init_key, list);
-}
-
-static int
-pyg_run_class_init(GType gtype, gpointer gclass, PyTypeObject *pyclass)
-{
- GSList *list;
- PyGClassInitFunc class_init;
- GType parent_type;
- int rv;
-
- parent_type = g_type_parent(gtype);
- if (parent_type) {
- rv = pyg_run_class_init(parent_type, gclass, pyclass);
- if (rv)
- return rv;
- }
-
- list = g_type_get_qdata(gtype, pygobject_class_init_key);
- for (; list; list = list->next) {
- class_init = list->data;
- rv = class_init(gclass, pyclass);
- if (rv)
- return rv;
- }
-
- return 0;
-}
-
-static PyObject *
-_wrap_pyg_type_register(PyObject *self, PyObject *args)
-{
- PyTypeObject *class;
- char *type_name = NULL;
-
- if (!PyArg_ParseTuple(args, "O!|z:gobject.type_register",
- &PyType_Type, &class, &type_name))
- return NULL;
- if (!PyType_IsSubtype(class, &PyGObject_Type)) {
- PyErr_SetString(PyExc_TypeError,
- "argument must be a GObject subclass");
- return NULL;
- }
-
- /* Check if type already registered */
- if (pyg_type_from_object((PyObject *) class) ==
- pyg_type_from_object((PyObject *) class->tp_base))
- {
- if (pyg_type_register(class, type_name))
- return NULL;
- }
-
- Py_INCREF(class);
- return (PyObject *) class;
-}
-
-static char *
-get_type_name_for_class(PyTypeObject *class)
-{
- gint i, name_serial;
- char name_serial_str[16];
- PyObject *module;
- char *type_name = NULL;
-
- /* make name for new GType */
- name_serial = 1;
- /* give up after 1000 tries, just in case.. */
- while (name_serial < 1000)
- {
- g_free(type_name);
- snprintf(name_serial_str, 16, "-v%i", name_serial);
- module = PyObject_GetAttrString((PyObject *)class, "__module__");
- if (module && PYGLIB_PyUnicode_Check(module)) {
- type_name = g_strconcat(PYGLIB_PyUnicode_AsString(module), ".",
- class->tp_name,
- name_serial > 1 ? name_serial_str : NULL,
- NULL);
- Py_DECREF(module);
- } else {
- if (module)
- Py_DECREF(module);
- else
- PyErr_Clear();
- type_name = g_strconcat(class->tp_name,
- name_serial > 1 ? name_serial_str : NULL,
- NULL);
- }
- /* convert '.' in type name to '+', which isn't banned (grumble) */
- for (i = 0; type_name[i] != '\0'; i++)
- if (type_name[i] == '.')
- type_name[i] = '+';
- if (g_type_from_name(type_name) == 0)
- break; /* we now have a unique name */
- ++name_serial;
- }
-
- return type_name;
-}
-
-
-static GPrivate pygobject_construction_wrapper;
-
-static inline void
-pygobject_init_wrapper_set(PyObject *wrapper)
-{
- g_private_set(&pygobject_construction_wrapper, wrapper);
-}
-
-static inline PyObject *
-pygobject_init_wrapper_get(void)
-{
- return (PyObject *) g_private_get(&pygobject_construction_wrapper);
-}
-
-int
-pygobject_constructv(PyGObject *self,
- guint n_parameters,
- GParameter *parameters)
-{
- if (self->obj == NULL) {
- GObject *obj;
- pygobject_init_wrapper_set((PyObject *) self);
- obj = g_object_newv(pyg_type_from_object((PyObject *) self),
- n_parameters, parameters);
-
- if (g_object_is_floating (obj))
- self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
- pygobject_sink (obj);
-
- pygobject_init_wrapper_set(NULL);
- if (self->obj == NULL) {
- self->obj = obj;
- pygobject_register_wrapper((PyObject *) self);
- }
- } else {
- int i;
- for (i = 0; i < n_parameters; ++i)
- g_object_set_property(self->obj,
- parameters[i].name,
- &parameters[i].value);
- }
- return 0;
-}
-
-static void
-pygobject__g_instance_init(GTypeInstance *instance,
- gpointer g_class)
-{
- GObject *object = (GObject *) instance;
- PyObject *wrapper, *args, *kwargs;
-
- wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
- if (wrapper == NULL) {
- wrapper = pygobject_init_wrapper_get();
- if (wrapper && ((PyGObject *) wrapper)->obj == NULL) {
- ((PyGObject *) wrapper)->obj = object;
- pygobject_register_wrapper(wrapper);
- }
- }
- pygobject_init_wrapper_set(NULL);
- if (wrapper == NULL) {
- /* this looks like a python object created through
- * g_object_new -> we have no python wrapper, so create it
- * now */
- PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
- wrapper = pygobject_new_full(object,
- /*steal=*/ FALSE,
- g_class);
-
- /* float the wrapper ref here because we are going to orphan it
- * so we don't destroy the wrapper. The next call to pygobject_new_full
- * will take the ref */
- pygobject_ref_float ((PyGObject *) wrapper);
- args = PyTuple_New(0);
- kwargs = PyDict_New();
- if (Py_TYPE(wrapper)->tp_init(wrapper, args, kwargs))
- PyErr_Print();
-
- Py_DECREF(args);
- Py_DECREF(kwargs);
- pyglib_gil_state_release(state);
- }
-}
-
-
-/* This implementation is bad, see bug 566571 for an example why.
- * Instead of scanning explicitly declared bases for interfaces, we
- * should automatically initialize all implemented interfaces to
- * prevent bugs like that one. However, this will lead to
- * performance degradation as each virtual method in derived classes
- * will round-trip through do_*() stuff, *even* if it is not
- * overriden. We need to teach codegen to retain parent method
- * instead of setting virtual to *_proxy_do_*() if corresponding
- * do_*() is not overriden. Ok, that was a messy explanation.
- */
-static void
-pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
- PyObject *bases,
- GType *parent_interfaces, guint n_parent_interfaces)
-{
- int i;
-
- if (!bases) {
- g_warning("type has no bases");
- return;
- }
-
- for (i = 0; i < PyTuple_GET_SIZE(bases); ++i) {
- PyObject *base = PyTuple_GET_ITEM(bases, i);
- GType itype;
- const GInterfaceInfo *iinfo;
- GInterfaceInfo iinfo_copy;
-
- /* 'base' can also be a PyClassObject, see bug #566571. */
- if (!PyType_Check(base))
- continue;
-
- if (!PyType_IsSubtype((PyTypeObject*) base, &PyGInterface_Type))
- continue;
-
- itype = pyg_type_from_object(base);
-
- /* Happens for _implementations_ of an interface. */
- if (!G_TYPE_IS_INTERFACE(itype))
- continue;
-
- iinfo = pyg_lookup_interface_info(itype);
- if (!iinfo) {
- gchar *error;
- error = g_strdup_printf("Interface type %s "
- "has no Python implementation support",
- ((PyTypeObject *) base)->tp_name);
- PyErr_Warn(PyExc_RuntimeWarning, error);
- g_free(error);
- continue;
- }
-
- iinfo_copy = *iinfo;
- iinfo_copy.interface_data = class;
- g_type_add_interface_static(instance_type, itype, &iinfo_copy);
- }
-}
-
-int
-pyg_type_register(PyTypeObject *class, const char *type_name)
-{
- PyObject *gtype;
- GType parent_type, instance_type;
- GType *parent_interfaces;
- guint n_parent_interfaces;
- GTypeQuery query;
- gpointer gclass;
- GTypeInfo type_info = {
- 0, /* class_size */
-
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
-
- (GClassInitFunc) pyg_object_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
-
- 0, /* instance_size */
- 0, /* n_preallocs */
- (GInstanceInitFunc) pygobject__g_instance_init
- };
- gchar *new_type_name;
-
- /* find the GType of the parent */
- parent_type = pyg_type_from_object((PyObject *)class);
- if (!parent_type)
- return -1;
-
- parent_interfaces = g_type_interfaces(parent_type, &n_parent_interfaces);
-
- if (type_name)
- /* care is taken below not to free this */
- new_type_name = (gchar *) type_name;
- else
- new_type_name = get_type_name_for_class(class);
-
- /* set class_data that will be passed to the class_init function. */
- type_info.class_data = class;
-
- /* fill in missing values of GTypeInfo struct */
- g_type_query(parent_type, &query);
- type_info.class_size = query.class_size;
- type_info.instance_size = query.instance_size;
-
- /* create new typecode */
- instance_type = g_type_register_static(parent_type, new_type_name,
- &type_info, 0);
- if (instance_type == 0) {
- PyErr_Format(PyExc_RuntimeError,
- "could not create new GType: %s (subclass of %s)",
- new_type_name,
- g_type_name(parent_type));
-
- if (type_name == NULL)
- g_free(new_type_name);
-
- return -1;
- }
-
- if (type_name == NULL)
- g_free(new_type_name);
-
- /* store pointer to the class with the GType */
- Py_INCREF(class);
- g_type_set_qdata(instance_type, g_quark_from_string("PyGObject::class"),
- class);
-
- /* Mark this GType as a custom python type */
- g_type_set_qdata(instance_type, pygobject_custom_key,
- GINT_TO_POINTER (1));
-
- /* set new value of __gtype__ on class */
- gtype = pyg_type_wrapper_new(instance_type);
- PyObject_SetAttrString((PyObject *)class, "__gtype__", gtype);
- Py_DECREF(gtype);
-
- /* if no __doc__, set it to the auto doc descriptor */
- if (PyDict_GetItemString(class->tp_dict, "__doc__") == NULL) {
- PyDict_SetItemString(class->tp_dict, "__doc__",
- pyg_object_descr_doc_get());
- }
-
- /*
- * Note, all interfaces need to be registered before the first
- * g_type_class_ref(), see bug #686149.
- *
- * See also comment above pyg_type_add_interfaces().
- */
- pyg_type_add_interfaces(class, instance_type, class->tp_bases,
- parent_interfaces, n_parent_interfaces);
-
-
- gclass = g_type_class_ref(instance_type);
- if (PyErr_Occurred() != NULL) {
- g_type_class_unref(gclass);
- g_free(parent_interfaces);
- return -1;
- }
-
- if (pyg_run_class_init(instance_type, gclass, class)) {
- g_type_class_unref(gclass);
- g_free(parent_interfaces);
- return -1;
- }
- g_type_class_unref(gclass);
- g_free(parent_interfaces);
-
- if (PyErr_Occurred() != NULL)
- return -1;
- return 0;
-}
-
-static PyObject *
-pyg_signal_new(PyObject *self, PyObject *args)
-{
- gchar *signal_name;
- PyObject *py_type;
- GSignalFlags signal_flags;
- GType return_type;
- PyObject *py_return_type, *py_param_types;
-
- GType instance_type = 0;
- Py_ssize_t n_params, i;
- GType *param_types;
-
- guint signal_id;
-
- if (!PyArg_ParseTuple(args, "sOiOO:gobject.signal_new", &signal_name,
- &py_type, &signal_flags, &py_return_type,
- &py_param_types))
- return NULL;
-
- instance_type = pyg_type_from_object(py_type);
- if (!instance_type)
- return NULL;
- if (!(G_TYPE_IS_INSTANTIATABLE(instance_type) || G_TYPE_IS_INTERFACE(instance_type))) {
- PyErr_SetString(PyExc_TypeError,
- "argument 2 must be an object type or interface type");
- return NULL;
- }
-
- return_type = pyg_type_from_object(py_return_type);
- if (!return_type)
- return NULL;
-
- if (!PySequence_Check(py_param_types)) {
- PyErr_SetString(PyExc_TypeError,
- "argument 5 must be a sequence of GType codes");
- return NULL;
- }
- n_params = PySequence_Length(py_param_types);
- param_types = g_new(GType, n_params);
- for (i = 0; i < n_params; i++) {
- PyObject *item = PySequence_GetItem(py_param_types, i);
-
- param_types[i] = pyg_type_from_object(item);
- if (param_types[i] == 0) {
- PyErr_Clear();
- Py_DECREF(item);
- PyErr_SetString(PyExc_TypeError,
- "argument 5 must be a sequence of GType codes");
- g_free(param_types);
- return NULL;
- }
- Py_DECREF(item);
- }
-
- signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
- pyg_signal_class_closure_get(),
- (GSignalAccumulator)0, NULL,
- (GSignalCMarshaller)0,
- return_type, n_params, param_types);
- g_free(param_types);
- if (signal_id != 0)
- return PYGLIB_PyLong_FromLong(signal_id);
- PyErr_SetString(PyExc_RuntimeError, "could not create signal");
- return NULL;
-}
-
-static PyObject *
-pyg_signal_query (PyObject *self, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist1[] = { "name", "type", NULL };
- static char *kwlist2[] = { "signal_id", NULL };
- PyObject *py_query, *params_list, *py_itype;
- GObjectClass *class = NULL;
- GType itype;
- gchar *signal_name;
- guint i;
- GSignalQuery query;
- guint id;
- gpointer iface = NULL;
-
- if (PyArg_ParseTupleAndKeywords(args, kwargs, "sO:gobject.signal_query",
- kwlist1, &signal_name, &py_itype)) {
- if ((itype = pyg_type_from_object(py_itype)) == 0)
- return NULL;
-
- if (G_TYPE_IS_INSTANTIATABLE(itype)) {
- class = g_type_class_ref(itype);
- if (!class) {
- PyErr_SetString(PyExc_RuntimeError,
- "could not get a reference to type class");
- return NULL;
- }
- } else if (!G_TYPE_IS_INTERFACE(itype)) {
- PyErr_SetString(PyExc_TypeError,
- "type must be instantiable or an interface");
- return NULL;
- } else {
- iface = g_type_default_interface_ref(itype);
- }
- id = g_signal_lookup(signal_name, itype);
- } else {
- PyErr_Clear();
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "i:gobject.signal_query",
- kwlist2, &id)) {
- PyErr_Clear();
- PyErr_SetString(PyExc_TypeError,
- "Usage: one of:\n"
- " gobject.signal_query(name, type)\n"
- " gobject.signal_query(signal_id)");
-
- return NULL;
- }
- }
-
- g_signal_query(id, &query);
-
- if (query.signal_id == 0) {
- Py_INCREF(Py_None);
- py_query = Py_None;
- goto done;
- }
- py_query = PyTuple_New(6);
- if (py_query == NULL) {
- goto done;
- }
- params_list = PyTuple_New(query.n_params);
- if (params_list == NULL) {
- Py_DECREF(py_query);
- py_query = NULL;
- goto done;
- }
-
- PyTuple_SET_ITEM(py_query, 0, PYGLIB_PyLong_FromLong(query.signal_id));
- PyTuple_SET_ITEM(py_query, 1, PYGLIB_PyUnicode_FromString(query.signal_name));
- PyTuple_SET_ITEM(py_query, 2, pyg_type_wrapper_new(query.itype));
- PyTuple_SET_ITEM(py_query, 3, PYGLIB_PyLong_FromLong(query.signal_flags));
- PyTuple_SET_ITEM(py_query, 4, pyg_type_wrapper_new(query.return_type));
- for (i = 0; i < query.n_params; i++) {
- PyTuple_SET_ITEM(params_list, i,
- pyg_type_wrapper_new(query.param_types[i]));
- }
- PyTuple_SET_ITEM(py_query, 5, params_list);
-
- done:
- if (class)
- g_type_class_unref(class);
- if (iface)
- g_type_default_interface_unref(iface);
-
- return py_query;
-}
-
-static PyObject *
-pyg_object_class_list_properties (PyObject *self, PyObject *args)
-{
- GParamSpec **specs;
- PyObject *py_itype, *list;
- GType itype;
- GObjectClass *class = NULL;
- gpointer iface = NULL;
- guint nprops;
- guint i;
-
- if (!PyArg_ParseTuple(args, "O:gobject.list_properties",
- &py_itype))
- return NULL;
- if ((itype = pyg_type_from_object(py_itype)) == 0)
- return NULL;
-
- if (G_TYPE_IS_INTERFACE(itype)) {
- iface = g_type_default_interface_ref(itype);
- if (!iface) {
- PyErr_SetString(PyExc_RuntimeError,
- "could not get a reference to interface type");
- return NULL;
- }
- specs = g_object_interface_list_properties(iface, &nprops);
- } else if (g_type_is_a(itype, G_TYPE_OBJECT)) {
- class = g_type_class_ref(itype);
- if (!class) {
- PyErr_SetString(PyExc_RuntimeError,
- "could not get a reference to type class");
- return NULL;
- }
- specs = g_object_class_list_properties(class, &nprops);
- } else {
- PyErr_SetString(PyExc_TypeError,
- "type must be derived from GObject or an interface");
- return NULL;
- }
-
- list = PyTuple_New(nprops);
- if (list == NULL) {
- g_free(specs);
- g_type_class_unref(class);
- return NULL;
- }
- for (i = 0; i < nprops; i++) {
- PyTuple_SetItem(list, i, pyg_param_spec_new(specs[i]));
- }
- g_free(specs);
- if (class)
- g_type_class_unref(class);
- else
- g_type_default_interface_unref(iface);
-
- return list;
-}
-
-static PyObject *
-pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
-{
- PyObject *pytype;
- GType type;
- GObject *obj = NULL;
- GObjectClass *class;
- guint n_params = 0, i;
- GParameter *params = NULL;
-
- if (!PyArg_ParseTuple (args, "O:gobject.new", &pytype)) {
- return NULL;
- }
-
- if ((type = pyg_type_from_object (pytype)) == 0)
- return NULL;
-
- if (G_TYPE_IS_ABSTRACT(type)) {
- PyErr_Format(PyExc_TypeError, "cannot create instance of abstract "
- "(non-instantiable) type `%s'", g_type_name(type));
- return NULL;
- }
-
- if ((class = g_type_class_ref (type)) == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "could not get a reference to type class");
- return NULL;
- }
-
- if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
- goto cleanup;
-
- obj = g_object_newv(type, n_params, params);
- if (!obj)
- PyErr_SetString (PyExc_RuntimeError, "could not create object");
-
- cleanup:
- for (i = 0; i < n_params; i++) {
- g_free((gchar *) params[i].name);
- g_value_unset(&params[i].value);
- }
- g_free(params);
- g_type_class_unref(class);
-
- if (obj) {
- pygobject_sink (obj);
- self = (PyGObject *) pygobject_new((GObject *)obj);
- g_object_unref(obj);
- } else
- self = NULL;
-
- return (PyObject *) self;
-}
-
-gboolean
-pyg_handler_marshal(gpointer user_data)
-{
- PyObject *tuple, *ret;
- gboolean res;
- PyGILState_STATE state;
-
- g_return_val_if_fail(user_data != NULL, FALSE);
-
- state = pyglib_gil_state_ensure();
-
- tuple = (PyObject *)user_data;
- ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0),
- PyTuple_GetItem(tuple, 1));
- if (!ret) {
- PyErr_Print();
- res = FALSE;
- } else {
- res = PyObject_IsTrue(ret);
- Py_DECREF(ret);
- }
-
- pyglib_gil_state_release(state);
-
- return res;
-}
-
-static int
-pygobject_gil_state_ensure (void)
-{
- return pyglib_gil_state_ensure ();
-}
-
-static void
-pygobject_gil_state_release (int flag)
-{
- pyglib_gil_state_release(flag);
-}
-
-/* Only for backwards compatibility */
-static int
-pygobject_enable_threads(void)
-{
- return 0;
-}
-
-static PyObject *
-pyg_signal_accumulator_true_handled(PyObject *unused, PyObject *args)
-{
- PyErr_SetString(PyExc_TypeError,
- "signal_accumulator_true_handled can only"
- " be used as accumulator argument when registering signals");
- return NULL;
-}
-
-static gboolean
-marshal_emission_hook(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue *param_values,
- gpointer user_data)
-{
- PyGILState_STATE state;
- gboolean retval = FALSE;
- PyObject *func, *args;
- PyObject *retobj;
- PyObject *params;
- guint i;
-
- state = pyglib_gil_state_ensure();
-
- /* construct Python tuple for the parameter values */
- params = PyTuple_New(n_param_values);
-
- for (i = 0; i < n_param_values; i++) {
- PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
-
- /* error condition */
- if (!item) {
- goto out;
- }
- PyTuple_SetItem(params, i, item);
- }
-
- args = (PyObject *)user_data;
- func = PyTuple_GetItem(args, 0);
- args = PySequence_Concat(params, PyTuple_GetItem(args, 1));
- Py_DECREF(params);
-
- /* params passed to function may have extra arguments */
-
- retobj = PyObject_CallObject(func, args);
- Py_DECREF(args);
- if (retobj == NULL) {
- PyErr_Print();
- }
-
- retval = (retobj == Py_True ? TRUE : FALSE);
- Py_XDECREF(retobj);
-out:
- pyglib_gil_state_release(state);
- return retval;
-}
-
-static PyObject *
-pyg_add_emission_hook(PyGObject *self, PyObject *args)
-{
- PyObject *first, *callback, *extra_args, *data, *repr;
- gchar *name;
- gulong hook_id;
- guint sigid;
- Py_ssize_t len;
- GQuark detail = 0;
- GType gtype;
- PyObject *pygtype;
-
- len = PyTuple_Size(args);
- if (len < 3) {
- PyErr_SetString(PyExc_TypeError,
- "gobject.add_emission_hook requires at least 3 arguments");
- return NULL;
- }
- first = PySequence_GetSlice(args, 0, 3);
- if (!PyArg_ParseTuple(first, "OsO:add_emission_hook",
- &pygtype, &name, &callback)) {
- Py_DECREF(first);
- return NULL;
- }
- Py_DECREF(first);
-
- if ((gtype = pyg_type_from_object(pygtype)) == 0) {
- return NULL;
- }
- if (!PyCallable_Check(callback)) {
- PyErr_SetString(PyExc_TypeError, "third argument must be callable");
- return NULL;
- }
-
- if (!g_signal_parse_name(name, gtype, &sigid, &detail, TRUE)) {
- repr = PyObject_Repr((PyObject*)self);
- PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- PYGLIB_PyUnicode_AsString(repr),
- name);
- Py_DECREF(repr);
- return NULL;
- }
- extra_args = PySequence_GetSlice(args, 3, len);
- if (extra_args == NULL)
- return NULL;
-
- data = Py_BuildValue("(ON)", callback, extra_args);
- if (data == NULL)
- return NULL;
-
- hook_id = g_signal_add_emission_hook(sigid, detail,
- marshal_emission_hook,
- data,
- (GDestroyNotify)pyg_destroy_notify);
-
- return PyLong_FromUnsignedLong(hook_id);
-}
-
-static PyObject *
-pyg__install_metaclass(PyObject *dummy, PyTypeObject *metaclass)
-{
- Py_INCREF(metaclass);
- PyGObject_MetaType = metaclass;
- Py_INCREF(metaclass);
-
- Py_TYPE(&PyGObject_Type) = metaclass;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-pyg__gvalue_get(PyObject *module, PyObject *pygvalue)
-{
- if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
- PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
- return NULL;
- }
-
- return pyg_value_as_pyobject (pyg_boxed_get(pygvalue, GValue),
- /*copy_boxed=*/ TRUE);
-}
-
-static PyObject *
-pyg__gvalue_set(PyObject *module, PyObject *args)
-{
- PyObject *pygvalue;
- PyObject *pyobject;
-
- if (!PyArg_ParseTuple (args, "OO:_gobject._gvalue_set",
- &pygvalue, &pyobject))
- return NULL;
-
- if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
- PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
- return NULL;
- }
-
- if (pyg_value_from_pyobject_with_error (pyg_boxed_get (pygvalue, GValue),
- pyobject) == -1)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-static PyMethodDef _gobject_functions[] = {
- { "type_name", pyg_type_name, METH_VARARGS },
- { "type_from_name", pyg_type_from_name, METH_VARARGS },
- { "type_is_a", pyg_type_is_a, METH_VARARGS },
- { "type_register", _wrap_pyg_type_register, METH_VARARGS },
- { "signal_new", pyg_signal_new, METH_VARARGS },
- { "signal_query",
- (PyCFunction)pyg_signal_query, METH_VARARGS|METH_KEYWORDS },
- { "list_properties",
- pyg_object_class_list_properties, METH_VARARGS },
- { "new",
- (PyCFunction)pyg_object_new, METH_VARARGS|METH_KEYWORDS },
- { "signal_accumulator_true_handled",
- (PyCFunction)pyg_signal_accumulator_true_handled, METH_VARARGS },
- { "add_emission_hook",
- (PyCFunction)pyg_add_emission_hook, METH_VARARGS },
- { "_install_metaclass",
- (PyCFunction)pyg__install_metaclass, METH_O },
- { "_gvalue_get",
- (PyCFunction)pyg__gvalue_get, METH_O },
- { "_gvalue_set",
- (PyCFunction)pyg__gvalue_set, METH_VARARGS },
-
- { NULL, NULL, 0 }
-};
-
-
-/* ----------------- Constant extraction ------------------------ */
-
-/**
- * pyg_constant_strip_prefix:
- * @name: the constant name.
- * @strip_prefix: the prefix to strip.
- *
- * Advances the pointer @name by strlen(@strip_prefix) characters. If
- * the resulting name does not start with a letter or underscore, the
- * @name pointer will be rewound. This is to ensure that the
- * resulting name is a valid identifier. Hence the returned string is
- * a pointer into the string @name.
- *
- * Returns: the stripped constant name.
- */
-const gchar *
-pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix)
-{
- gint prefix_len;
- guint i;
-
- prefix_len = strlen(strip_prefix);
-
- /* Check so name starts with strip_prefix, if it doesn't:
- * return the rest of the part which doesn't match
- */
- for (i = 0; i < prefix_len; i++) {
- if (name[i] != strip_prefix[i] && name[i] != '_') {
- return &name[i];
- }
- }
-
- /* strip off prefix from value name, while keeping it a valid
- * identifier */
- for (i = prefix_len; i >= 0; i--) {
- if (g_ascii_isalpha(name[i]) || name[i] == '_') {
- return &name[i];
- }
- }
- return name;
-}
-
-/**
- * pyg_enum_add_constants:
- * @module: a Python module
- * @enum_type: the GType of the enumeration.
- * @strip_prefix: the prefix to strip from the constant names.
- *
- * Adds constants to the given Python module for each value name of
- * the enumeration. A prefix will be stripped from each enum name.
- */
-static void
-pyg_enum_add_constants(PyObject *module, GType enum_type,
- const gchar *strip_prefix)
-{
- GEnumClass *eclass;
- guint i;
-
- if (!G_TYPE_IS_ENUM(enum_type)) {
- if (G_TYPE_IS_FLAGS(enum_type)) /* See bug #136204 */
- pyg_flags_add_constants(module, enum_type, strip_prefix);
- else
- g_warning("`%s' is not an enum type", g_type_name(enum_type));
- return;
- }
- g_return_if_fail (strip_prefix != NULL);
-
- eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
-
- for (i = 0; i < eclass->n_values; i++) {
- const gchar *name = eclass->values[i].value_name;
- gint value = eclass->values[i].value;
-
- PyModule_AddIntConstant(module,
- (char*) pyg_constant_strip_prefix(name, strip_prefix),
- (long) value);
- }
-
- g_type_class_unref(eclass);
-}
-
-/**
- * pyg_flags_add_constants:
- * @module: a Python module
- * @flags_type: the GType of the flags type.
- * @strip_prefix: the prefix to strip from the constant names.
- *
- * Adds constants to the given Python module for each value name of
- * the flags set. A prefix will be stripped from each flag name.
- */
-static void
-pyg_flags_add_constants(PyObject *module, GType flags_type,
- const gchar *strip_prefix)
-{
- GFlagsClass *fclass;
- guint i;
-
- if (!G_TYPE_IS_FLAGS(flags_type)) {
- if (G_TYPE_IS_ENUM(flags_type)) /* See bug #136204 */
- pyg_enum_add_constants(module, flags_type, strip_prefix);
- else
- g_warning("`%s' is not an flags type", g_type_name(flags_type));
- return;
- }
- g_return_if_fail (strip_prefix != NULL);
-
- fclass = G_FLAGS_CLASS(g_type_class_ref(flags_type));
-
- for (i = 0; i < fclass->n_values; i++) {
- const gchar *name = fclass->values[i].value_name;
- guint value = fclass->values[i].value;
-
- PyModule_AddIntConstant(module,
- (char*) pyg_constant_strip_prefix(name, strip_prefix),
- (long) value);
- }
-
- g_type_class_unref(fclass);
-}
-
-/**
- * pyg_error_check:
- * @error: a pointer to the GError.
- *
- * Checks to see if the GError has been set. If the error has been
- * set, then the gobject.GError Python exception will be raised, and
- * the GError cleared.
- *
- * Returns: True if an error was set.
- *
- * Deprecated: Since 2.16, use pyglib_error_check instead.
- */
-gboolean
-pyg_error_check(GError **error)
-{
-#if 0
- if (PyErr_Warn(PyExc_DeprecationWarning,
- "pyg_error_check is deprecated, use "
- "pyglib_error_check instead"))
- return NULL;
-#endif
- return pyglib_error_check(error);
-}
-
-/**
- * pyg_gerror_exception_check:
- * @error: a standard GLib GError ** output parameter
- *
- * Checks to see if a GError exception has been raised, and if so
- * translates the python exception to a standard GLib GError. If the
- * raised exception is not a GError then PyErr_Print() is called.
- *
- * Returns: 0 if no exception has been raised, -1 if it is a
- * valid gobject.GError, -2 otherwise.
- *
- * Deprecated: Since 2.16, use pyglib_gerror_exception_check instead.
- */
-gboolean
-pyg_gerror_exception_check(GError **error)
-{
-#if 0
- if (PyErr_Warn(PyExc_DeprecationWarning,
- "pyg_gerror_exception_check is deprecated, use "
- "pyglib_gerror_exception_check instead"))
- return NULL;
-#endif
- return pyglib_gerror_exception_check(error);
-}
-
-/**
- * pyg_parse_constructor_args: helper function for PyGObject constructors
- * @obj_type: GType of the GObject, for parameter introspection
- * @arg_names: %NULL-terminated array of constructor argument names
- * @prop_names: %NULL-terminated array of property names, with direct
- * correspondence to @arg_names
- * @params: GParameter array where parameters will be placed; length
- * of this array must be at least equal to the number of
- * arguments/properties
- * @nparams: output parameter to contain actual number of arguments found
- * @py_args: array of PyObject* containing the actual constructor arguments
- *
- * Parses an array of PyObject's and creates a GParameter array
- *
- * Return value: %TRUE if all is successful, otherwise %FALSE and
- * python exception set.
- **/
-static gboolean
-pyg_parse_constructor_args(GType obj_type,
- char **arg_names,
- char **prop_names,
- GParameter *params,
- guint *nparams,
- PyObject **py_args)
-{
- guint arg_i, param_i;
- GObjectClass *oclass;
-
- oclass = g_type_class_ref(obj_type);
- g_return_val_if_fail(oclass, FALSE);
-
- for (param_i = arg_i = 0; arg_names[arg_i]; ++arg_i) {
- GParamSpec *spec;
- if (!py_args[arg_i])
- continue;
- spec = g_object_class_find_property(oclass, prop_names[arg_i]);
- params[param_i].name = prop_names[arg_i];
- g_value_init(&params[param_i].value, spec->value_type);
- if (pyg_value_from_pyobject(&params[param_i].value, py_args[arg_i]) == -1) {
- int i;
- PyErr_Format(PyExc_TypeError, "could not convert parameter '%s' of type '%s'",
- arg_names[arg_i], g_type_name(spec->value_type));
- g_type_class_unref(oclass);
- for (i = 0; i < param_i; ++i)
- g_value_unset(&params[i].value);
- return FALSE;
- }
- ++param_i;
- }
- g_type_class_unref(oclass);
- *nparams = param_i;
- return TRUE;
-}
-
-PyObject *
-pyg_integer_richcompare(PyObject *v, PyObject *w, int op)
-{
- PyObject *result;
- gboolean t;
-
- switch (op) {
- case Py_EQ: t = PYGLIB_PyLong_AS_LONG(v) == PYGLIB_PyLong_AS_LONG(w); break;
- case Py_NE: t = PYGLIB_PyLong_AS_LONG(v) != PYGLIB_PyLong_AS_LONG(w); break;
- case Py_LE: t = PYGLIB_PyLong_AS_LONG(v) <= PYGLIB_PyLong_AS_LONG(w); break;
- case Py_GE: t = PYGLIB_PyLong_AS_LONG(v) >= PYGLIB_PyLong_AS_LONG(w); break;
- case Py_LT: t = PYGLIB_PyLong_AS_LONG(v) < PYGLIB_PyLong_AS_LONG(w); break;
- case Py_GT: t = PYGLIB_PyLong_AS_LONG(v) > PYGLIB_PyLong_AS_LONG(w); break;
- default: g_assert_not_reached();
- }
-
- result = t ? Py_True : Py_False;
- Py_INCREF(result);
- return result;
-}
-
-static void
-_log_func(const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer user_data)
-{
- if (G_LIKELY(Py_IsInitialized()))
- {
- PyGILState_STATE state;
- PyObject* warning = user_data;
-
- state = pyglib_gil_state_ensure();
- PyErr_Warn(warning, (char *) message);
- pyglib_gil_state_release(state);
- } else
- g_log_default_handler(log_domain, log_level, message, user_data);
-}
-
-static void
-add_warning_redirection(const char *domain,
- PyObject *warning)
-{
- g_return_if_fail(domain != NULL);
- g_return_if_fail(warning != NULL);
-
- if (!log_handlers_disabled)
- {
- guint handler;
- gpointer old_handler;
-
- if (!log_handlers)
- log_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
- if ((old_handler = g_hash_table_lookup(log_handlers, domain)))
- g_log_remove_handler(domain, GPOINTER_TO_UINT(old_handler));
-
- handler = g_log_set_handler(domain, G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING,
- _log_func, warning);
- g_hash_table_insert(log_handlers, g_strdup(domain), GUINT_TO_POINTER(handler));
- }
-}
-
-static void
-remove_handler(gpointer domain,
- gpointer handler,
- gpointer unused)
-{
- g_log_remove_handler(domain, GPOINTER_TO_UINT(handler));
-}
-
-static void
-disable_warning_redirections(void)
-{
- log_handlers_disabled = TRUE;
-
- if (log_handlers)
- {
- g_hash_table_foreach(log_handlers, remove_handler, NULL);
- g_hash_table_destroy(log_handlers);
- log_handlers = NULL;
- }
-}
-
-/* ----------------- gobject module initialisation -------------- */
-
-struct _PyGObject_Functions pygobject_api_functions = {
- pygobject_register_class,
- pygobject_register_wrapper,
- pygobject_lookup_class,
- pygobject_new,
-
- pyg_closure_new,
- pygobject_watch_closure,
- pyg_destroy_notify,
-
- pyg_type_from_object,
- pyg_type_wrapper_new,
- pyg_enum_get_value,
- pyg_flags_get_value,
- pyg_register_gtype_custom,
- pyg_value_from_pyobject,
- pyg_value_as_pyobject,
-
- pyg_register_interface,
-
- &PyGBoxed_Type,
- pyg_register_boxed,
- pyg_boxed_new,
-
- &PyGPointer_Type,
- pyg_register_pointer,
- pyg_pointer_new,
-
- pyg_enum_add_constants,
- pyg_flags_add_constants,
-
- pyg_constant_strip_prefix,
-
- pyg_error_check,
-
- _pyg_set_thread_block_funcs,
- (PyGThreadBlockFunc)0, /* block_threads */
- (PyGThreadBlockFunc)0, /* unblock_threads */
-
- &PyGParamSpec_Type,
- pyg_param_spec_new,
- pyg_param_spec_from_object,
-
- pyg_pyobj_to_unichar_conv,
- pyg_parse_constructor_args,
- pyg_param_gvalue_as_pyobject,
- pyg_param_gvalue_from_pyobject,
-
- &PyGEnum_Type,
- pyg_enum_add,
- pyg_enum_from_gtype,
-
- &PyGFlags_Type,
- pyg_flags_add,
- pyg_flags_from_gtype,
-
- /* threads_enabled */
-#ifdef DISABLE_THREADING
- FALSE,
-#else
- TRUE,
-#endif
-
- pygobject_enable_threads,
- pygobject_gil_state_ensure,
- pygobject_gil_state_release,
- pyg_register_class_init,
- pyg_register_interface_info,
-
- pyg_closure_set_exception_handler,
-
- add_warning_redirection,
- disable_warning_redirections,
-
- NULL, /* previously type_register_custom */
-
- pyg_gerror_exception_check,
-
- pyglib_option_group_new,
- pyg_type_from_object_strict,
-
- pygobject_new_full,
- &PyGObject_Type,
-
- pyg_value_from_pyobject_with_error
-};
-
-/* for addon libraries ... */
-static void
-pygobject_register_api(PyObject *d)
-{
- PyObject *api;
-
- api = PYGLIB_CPointer_WrapPointer(&pygobject_api_functions, "gobject._PyGObject_API");
- PyDict_SetItemString(d, "_PyGObject_API", api);
- Py_DECREF(api);
-}
-
-/* some constants */
-static void
-pygobject_register_constants(PyObject *m)
-{
- /* PyFloat_ return a new ref, and add object takes the ref */
- PyModule_AddObject(m, "G_MINFLOAT", PyFloat_FromDouble(G_MINFLOAT));
- PyModule_AddObject(m, "G_MAXFLOAT", PyFloat_FromDouble(G_MAXFLOAT));
- PyModule_AddObject(m, "G_MINDOUBLE", PyFloat_FromDouble(G_MINDOUBLE));
- PyModule_AddObject(m, "G_MAXDOUBLE", PyFloat_FromDouble(G_MAXDOUBLE));
- PyModule_AddIntConstant(m, "G_MINSHORT", G_MINSHORT);
- PyModule_AddIntConstant(m, "G_MAXSHORT", G_MAXSHORT);
- PyModule_AddIntConstant(m, "G_MAXUSHORT", G_MAXUSHORT);
- PyModule_AddIntConstant(m, "G_MININT", G_MININT);
- PyModule_AddIntConstant(m, "G_MAXINT", G_MAXINT);
- PyModule_AddObject(m, "G_MAXUINT", PyLong_FromUnsignedLong(G_MAXUINT));
- PyModule_AddObject(m, "G_MINLONG", PyLong_FromLong(G_MINLONG));
- PyModule_AddObject(m, "G_MAXLONG", PyLong_FromLong(G_MAXLONG));
- PyModule_AddObject(m, "G_MAXULONG", PyLong_FromUnsignedLong(G_MAXULONG));
- PyModule_AddObject(m, "G_MAXSIZE", PyLong_FromSize_t(G_MAXSIZE));
- PyModule_AddObject(m, "G_MAXSSIZE", PyLong_FromSsize_t(G_MAXSSIZE));
- PyModule_AddObject(m, "G_MINSSIZE", PyLong_FromSsize_t(G_MINSSIZE));
- PyModule_AddObject(m, "G_MINOFFSET", PyLong_FromLongLong(G_MINOFFSET));
- PyModule_AddObject(m, "G_MAXOFFSET", PyLong_FromLongLong(G_MAXOFFSET));
-
- PyModule_AddIntConstant(m, "SIGNAL_RUN_FIRST", G_SIGNAL_RUN_FIRST);
- PyModule_AddIntConstant(m, "PARAM_READWRITE", G_PARAM_READWRITE);
-
- /* The rest of the types are set in __init__.py */
- PyModule_AddObject(m, "TYPE_INVALID", pyg_type_wrapper_new(G_TYPE_INVALID));
- PyModule_AddObject(m, "TYPE_GSTRING", pyg_type_wrapper_new(G_TYPE_GSTRING));
-}
-
-/* features */
-static void
-pygobject_register_features(PyObject *d)
-{
- PyObject *features;
-
- features = PyDict_New();
- PyDict_SetItemString(features, "generic-c-marshaller", Py_True);
- PyDict_SetItemString(d, "features", features);
- Py_DECREF(features);
-}
-
-static void
-pygobject_register_version_tuples(PyObject *d)
-{
- PyObject *tuple;
-
- /* pygobject version */
- tuple = Py_BuildValue ("(iii)",
- PYGOBJECT_MAJOR_VERSION,
- PYGOBJECT_MINOR_VERSION,
- PYGOBJECT_MICRO_VERSION);
- PyDict_SetItemString(d, "pygobject_version", tuple);
-}
-
-static void
-pygobject_register_warnings(PyObject *d)
-{
- PyObject *warning;
-
- warning = PyErr_NewException("gobject.Warning", PyExc_Warning, NULL);
- PyDict_SetItemString(d, "Warning", warning);
- add_warning_redirection("GLib", warning);
- add_warning_redirection("GLib-GObject", warning);
- add_warning_redirection("GThread", warning);
-}
-
-
-PYGLIB_MODULE_START(_gobject, "_gobject")
-{
- PyObject *d;
-
- pyglib_init();
-
- d = PyModule_GetDict(module);
- pygobject_register_api(d);
- pygobject_register_constants(module);
- pygobject_register_features(d);
- pygobject_register_version_tuples(d);
- pygobject_register_warnings(d);
- pygobject_type_register_types(d);
- pygobject_object_register_types(d);
- pygobject_interface_register_types(d);
- pygobject_paramspec_register_types(d);
- pygobject_boxed_register_types(d);
- pygobject_pointer_register_types(d);
- pygobject_enum_register_types(d);
- pygobject_flags_register_types(d);
-}
-PYGLIB_MODULE_END
diff --git a/gi/_gobject/pygflags.h b/gi/_gobject/pygflags.h
deleted file mode 100644
index e93265c..0000000
--- a/gi/_gobject/pygflags.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pygtk- Python bindings for the GTK toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- * 2004-2008 Johan Dahlin
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGOBJECT_FLAGS_H__
-#define __PYGOBJECT_FLAGS_H__
-
-void pygobject_flags_register_types(PyObject *d);
-
-#endif /* __PYGOBJECT_FLAGS_H__ */
diff --git a/gi/_gobject/pygobject-private.h b/gi/_gobject/pygobject-private.h
deleted file mode 100644
index 294b0f6..0000000
--- a/gi/_gobject/pygobject-private.h
+++ /dev/null
@@ -1,204 +0,0 @@
-#ifndef _PYGOBJECT_PRIVATE_H_
-#define _PYGOBJECT_PRIVATE_H_
-
-#ifdef _PYGOBJECT_H_
-# error "include pygobject.h or pygobject-private.h, but not both"
-#endif
-
-#define _INSIDE_PYGOBJECT_
-#include "pygobject.h"
-
-#include "pyglib-python-compat.h"
-
-#define PYGOBJECT_REGISTER_GTYPE(d, type, name, gtype) \
- { \
- PyObject *o; \
- PYGLIB_REGISTER_TYPE(d, type, name); \
- PyDict_SetItemString(type.tp_dict, "__gtype__", \
- o=pyg_type_wrapper_new(gtype)); \
- Py_DECREF(o); \
-}
-
-/* from gobjectmodule.c */
-extern struct _PyGObject_Functions pygobject_api_functions;
-
-
-#ifndef Py_CLEAR /* since Python 2.4 */
-# define Py_CLEAR(op) \
- do { \
- if (op) { \
- PyObject *tmp = (PyObject *)(op); \
- (op) = NULL; \
- Py_DECREF(tmp); \
- } \
- } while (0)
-#endif
-
-extern GType PY_TYPE_OBJECT;
-
-extern GQuark pygboxed_type_key;
-extern GQuark pygboxed_marshal_key;
-extern GQuark pygenum_class_key;
-extern GQuark pygflags_class_key;
-extern GQuark pyginterface_type_key;
-extern GQuark pyginterface_info_key;
-extern GQuark pygobject_class_init_key;
-extern GQuark pygobject_class_key;
-extern GQuark pygobject_wrapper_key;
-extern GQuark pygpointer_class_key;
-extern GQuark pygobject_has_updated_constructor_key;
-extern GQuark pygobject_instance_data_key;
-extern GQuark pygobject_custom_key;
-
-void pygobject_data_free (PyGObjectData *data);
-void pyg_destroy_notify (gpointer user_data);
-gboolean pyg_handler_marshal (gpointer user_data);
-gboolean pyg_error_check (GError **error);
-int pygobject_constructv (PyGObject *self,
- guint n_parameters,
- GParameter *parameters);
-
-PyObject *pyg_integer_richcompare(PyObject *v,
- PyObject *w,
- int op);
-
-gboolean pyg_gerror_exception_check(GError **error);
-
-void pygobject_ref_float(PyGObject *self);
-void pygobject_ref_sink(PyGObject *self);
-
-/* from pygtype.h */
-extern PyTypeObject PyGTypeWrapper_Type;
-
-PyObject *pyg_type_wrapper_new (GType type);
-GType pyg_type_from_object_strict (PyObject *obj, gboolean strict);
-GType pyg_type_from_object (PyObject *obj);
-
-gint pyg_enum_get_value (GType enum_type, PyObject *obj, gint *val);
-gint pyg_flags_get_value (GType flag_type, PyObject *obj, guint *val);
-int pyg_pyobj_to_unichar_conv (PyObject* py_obj, void* ptr);
-
-typedef PyObject *(* fromvaluefunc)(const GValue *value);
-typedef int (*tovaluefunc)(GValue *value, PyObject *obj);
-
-void pyg_register_gtype_custom(GType gtype,
- fromvaluefunc from_func,
- tovaluefunc to_func);
-int pyg_value_from_pyobject(GValue *value, PyObject *obj);
-int pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj);
-PyObject *pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed);
-int pyg_param_gvalue_from_pyobject(GValue* value,
- PyObject* py_obj,
- const GParamSpec* pspec);
-PyObject *pyg_param_gvalue_as_pyobject(const GValue* gvalue,
- gboolean copy_boxed,
- const GParamSpec* pspec);
-
-GClosure *pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data);
-void pyg_closure_set_exception_handler(GClosure *closure,
- PyClosureExceptionHandler handler);
-GClosure *pyg_signal_class_closure_get(void);
-GClosure *gclosure_from_pyfunc(PyGObject *object, PyObject *func);
-
-PyObject *pyg_object_descr_doc_get(void);
-void pygobject_object_register_types(PyObject *d);
-
-extern PyTypeObject *PyGObject_MetaType;
-
-/* from pygobject.h */
-extern PyTypeObject PyGObject_Type;
-extern PyTypeObject PyGProps_Type;
-extern PyTypeObject PyGPropsDescr_Type;
-extern PyTypeObject PyGPropsIter_Type;
-
- /* Data that belongs to the GObject instance, not the Python wrapper */
-struct _PyGObjectData {
- PyTypeObject *type; /* wrapper type for this instance */
- GSList *closures;
-};
-
-void pygobject_register_class (PyObject *dict,
- const gchar *type_name,
- GType gtype, PyTypeObject *type,
- PyObject *bases);
-void pygobject_register_wrapper (PyObject *self);
-PyObject * pygobject_new (GObject *obj);
-PyObject * pygobject_new_full (GObject *obj, gboolean steal, gpointer g_class);
-void pygobject_sink (GObject *obj);
-PyTypeObject *pygobject_lookup_class (GType gtype);
-void pygobject_watch_closure (PyObject *self, GClosure *closure);
-int pyg_type_register (PyTypeObject *class,
- const gchar *type_name);
-
-/* from pygboxed.c */
-extern PyTypeObject PyGBoxed_Type;
-
-void pyg_register_boxed (PyObject *dict, const gchar *class_name,
- GType boxed_type, PyTypeObject *type);
-PyObject * pyg_boxed_new (GType boxed_type, gpointer boxed,
- gboolean copy_boxed, gboolean own_ref);
-
-extern PyTypeObject PyGPointer_Type;
-
-void pyg_register_pointer (PyObject *dict, const gchar *class_name,
- GType pointer_type, PyTypeObject *type);
-PyObject * pyg_pointer_new (GType pointer_type, gpointer pointer);
-
-const gchar * pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix);
-
-/* pygflags */
-typedef struct {
- PYGLIB_PyLongObject parent;
- int zero_pad; /* must always be 0 */
- GType gtype;
-} PyGFlags;
-
-extern PyTypeObject PyGFlags_Type;
-
-#define PyGFlags_Check(x) (PyObject_IsInstance((PyObject *)x, (PyObject *)&PyGFlags_Type) && g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_FLAGS))
-
-extern PyObject * pyg_flags_add (PyObject * module,
- const char * type_name,
- const char * strip_prefix,
- GType gtype);
-extern PyObject * pyg_flags_from_gtype (GType gtype,
- guint value);
-
-/* pygenum */
-#define PyGEnum_Check(x) (PyObject_IsInstance((PyObject *)x, (PyObject *)&PyGEnum_Type) && g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_ENUM))
-
-typedef struct {
- PYGLIB_PyLongObject parent;
- int zero_pad; /* must always be 0 */
- GType gtype;
-} PyGEnum;
-
-extern PyTypeObject PyGEnum_Type;
-
-extern PyObject * pyg_enum_add (PyObject * module,
- const char * type_name,
- const char * strip_prefix,
- GType gtype);
-extern PyObject * pyg_enum_from_gtype (GType gtype,
- int value);
-
-/* pygtype.c */
-extern gboolean pyg_gtype_is_custom (GType gtype);
-
-/* pygobject.c */
-extern PyTypeObject PyGObjectWeakRef_Type;
-
-static inline PyGObjectData *
-pyg_object_peek_inst_data(GObject *obj)
-{
- return ((PyGObjectData *)
- g_object_get_qdata(obj, pygobject_instance_data_key));
-}
-
-gboolean pygobject_prepare_construct_properties (GObjectClass *class,
- PyObject *kwargs,
- guint *n_params,
- GParameter **params);
-
-
-#endif
diff --git a/gi/_gobject/pygparamspec.c b/gi/_gobject/pygparamspec.c
deleted file mode 100644
index 94f1dbb..0000000
--- a/gi/_gobject/pygparamspec.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pygtk- Python bindings for the GTK toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- * Copyright (C) 2004 Johan Dahlin
- *
- * pygenum.c: GEnum and GFlag wrappers
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <pyglib.h>
-
-#include "pygobject-private.h"
-#include "pygparamspec.h"
-
-PYGLIB_DEFINE_TYPE("gobject.GParamSpec", PyGParamSpec_Type, PyGParamSpec);
-
-static PyObject*
-pyg_param_spec_richcompare(PyObject *self, PyObject *other, int op)
-{
- if (Py_TYPE(self) == Py_TYPE(other) && Py_TYPE(self) == &PyGParamSpec_Type)
- return _pyglib_generic_ptr_richcompare(((PyGParamSpec*)self)->pspec,
- ((PyGParamSpec*)other)->pspec,
- op);
- else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static long
-pyg_param_spec_hash(PyGParamSpec *self)
-{
- return (long)self->pspec;
-}
-
-static PyObject *
-pyg_param_spec_repr(PyGParamSpec *self)
-{
- char buf[80];
-
- g_snprintf(buf, sizeof(buf), "<%s '%s'>",
- G_PARAM_SPEC_TYPE_NAME(self->pspec),
- g_param_spec_get_name(self->pspec));
- return PYGLIB_PyUnicode_FromString(buf);
-}
-
-static void
-pyg_param_spec_dealloc(PyGParamSpec *self)
-{
- g_param_spec_unref(self->pspec);
- PyObject_DEL(self);
-}
-
-
-static PyObject *
-pygenum_from_pspec(GParamSpec *pspec)
-{
- PyObject *pyclass;
- GParamSpecEnum *enum_pspec;
- GType enum_type;
-
- enum_pspec = G_PARAM_SPEC_ENUM(pspec);
- enum_type = G_ENUM_CLASS_TYPE(enum_pspec->enum_class);
- pyclass = (PyObject*)g_type_get_qdata(enum_type, pygenum_class_key);
- if (pyclass == NULL) {
- pyclass = pyg_enum_add(NULL, g_type_name(enum_type), NULL, enum_type);
- if (pyclass == NULL)
- pyclass = Py_None;
- }
-
- Py_INCREF(pyclass);
- return pyclass;
-}
-
-static PyObject *
-pygflags_from_pspec(GParamSpec *pspec)
-{
- PyObject *pyclass;
- GParamSpecFlags *flag_pspec;
- GType flag_type;
-
- flag_pspec = G_PARAM_SPEC_FLAGS(pspec);
- flag_type = G_FLAGS_CLASS_TYPE(flag_pspec->flags_class);
- pyclass = (PyObject*)g_type_get_qdata(flag_type, pygflags_class_key);
- if (pyclass == NULL) {
- pyclass = pyg_flags_add(NULL, g_type_name(flag_type), NULL, flag_type);
- if (pyclass == NULL)
- pyclass = Py_None;
- }
- Py_INCREF(pyclass);
- return pyclass;
-}
-
-static PyObject *
-pyg_param_spec_getattr(PyGParamSpec *self, const gchar *attr)
-{
- GParamSpec *pspec;
-
- pspec = self->pspec;
-
- /* common attributes */
- if (!strcmp(attr, "__gtype__")) {
- return pyg_type_wrapper_new(G_PARAM_SPEC_TYPE(pspec));
- } else if (!strcmp(attr, "name")) {
- return Py_BuildValue("s", g_param_spec_get_name(pspec));
- } else if (!strcmp(attr, "nick")) {
- return Py_BuildValue("s", g_param_spec_get_nick(pspec));
- } else if (!strcmp(attr, "blurb") || !strcmp(attr, "__doc__")) {
- return Py_BuildValue("s", g_param_spec_get_blurb(pspec));
- } else if (!strcmp(attr, "flags")) {
- return PYGLIB_PyLong_FromLong(pspec->flags);
- } else if (!strcmp(attr, "value_type")) {
- return pyg_type_wrapper_new(pspec->value_type);
- } else if (!strcmp(attr, "owner_type")) {
- return pyg_type_wrapper_new(pspec->owner_type);
- }
-
- if (G_IS_PARAM_SPEC_CHAR(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value", "flags",
- "maximum", "minimum", "name", "nick",
- "owner_type", "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PYGLIB_PyUnicode_FromFormat(
- "%c", G_PARAM_SPEC_CHAR(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PYGLIB_PyLong_FromLong(G_PARAM_SPEC_CHAR(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PYGLIB_PyLong_FromLong(G_PARAM_SPEC_CHAR(pspec)->maximum);
- }
- } else if (G_IS_PARAM_SPEC_UCHAR(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "maximum", "minimum",
- "name", "nick", "owner_type",
- "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PYGLIB_PyUnicode_FromFormat(
- "%c", G_PARAM_SPEC_UCHAR(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PYGLIB_PyLong_FromLong(G_PARAM_SPEC_UCHAR(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PYGLIB_PyLong_FromLong(G_PARAM_SPEC_UCHAR(pspec)->maximum);
- }
- } else if (G_IS_PARAM_SPEC_BOOLEAN(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "name", "nick", "owner_type",
- "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PyBool_FromLong(G_PARAM_SPEC_BOOLEAN(pspec)->default_value);
- }
- } else if (G_IS_PARAM_SPEC_INT(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "maximum", "minimum", "name",
- "nick", "owner_type", "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PYGLIB_PyLong_FromLong(G_PARAM_SPEC_INT(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PYGLIB_PyLong_FromLong(G_PARAM_SPEC_INT(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PYGLIB_PyLong_FromLong(G_PARAM_SPEC_INT(pspec)->maximum);
- }
- } else if (G_IS_PARAM_SPEC_UINT(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "maximum", "minimum",
- "name", "nick", "owner_type",
- "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PyLong_FromUnsignedLong(G_PARAM_SPEC_UINT(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PyLong_FromUnsignedLong(G_PARAM_SPEC_UINT(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PyLong_FromUnsignedLong(G_PARAM_SPEC_UINT(pspec)->maximum);
- }
- } else if (G_IS_PARAM_SPEC_LONG(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "maximum", "minimum", "name",
- "nick", "owner_type", "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PyLong_FromLong(G_PARAM_SPEC_LONG(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PyLong_FromLong(G_PARAM_SPEC_LONG(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PyLong_FromLong(G_PARAM_SPEC_LONG(pspec)->maximum);
- }
- } else if (G_IS_PARAM_SPEC_ULONG(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "maximum", "minimum", "name",
- "nick", "owner_type", "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PyLong_FromUnsignedLong(G_PARAM_SPEC_ULONG(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PyLong_FromUnsignedLong(G_PARAM_SPEC_ULONG(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PyLong_FromUnsignedLong(G_PARAM_SPEC_ULONG(pspec)->maximum);
- }
- } else if (G_IS_PARAM_SPEC_INT64(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "maximum", "minimum", "name",
- "nick", "owner_type", "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PyLong_FromLongLong(G_PARAM_SPEC_INT64(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PyLong_FromLongLong(G_PARAM_SPEC_INT64(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PyLong_FromLongLong(G_PARAM_SPEC_INT64(pspec)->maximum);
- }
- } else if (G_IS_PARAM_SPEC_UINT64(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "maximum", "minimum",
- "name", "nick", "owner_type",
- "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PyLong_FromUnsignedLongLong(G_PARAM_SPEC_UINT64(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PyLong_FromUnsignedLongLong(G_PARAM_SPEC_UINT64(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PyLong_FromUnsignedLongLong(G_PARAM_SPEC_UINT64(pspec)->maximum);
- }
- } else if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[sssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "name", "nick", "owner_type",
- "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PYGLIB_PyUnicode_FromFormat(
- "%c", G_PARAM_SPEC_UNICHAR(pspec)->default_value);
- }
- } else if (G_IS_PARAM_SPEC_ENUM(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[ssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value", "enum_class",
- "flags", "name", "nick", "owner_type",
- "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return pyg_enum_from_gtype(
- pspec->value_type, G_PARAM_SPEC_ENUM(pspec)->default_value);
- } else if (!strcmp(attr, "enum_class")) {
- return pygenum_from_pspec(pspec);
- }
- } else if (G_IS_PARAM_SPEC_FLAGS(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[ssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value",
- "flags", "flags_class", "name", "nick",
- "owner_type", "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return pyg_flags_from_gtype(
- pspec->value_type, G_PARAM_SPEC_FLAGS(pspec)->default_value);
- } else if (!strcmp(attr, "flags_class")) {
- return pygflags_from_pspec(pspec);
- }
- } else if (G_IS_PARAM_SPEC_FLOAT(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[ssssssssssss]", "__doc__", "__gtype__",
- "blurb", "epsilon",
- "flags", "maximum", "minimum", "name", "nick", "owner_type",
- "value_type",
- "default_value");
- } else if (!strcmp(attr, "default_value")) {
- return PyFloat_FromDouble(G_PARAM_SPEC_FLOAT(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PyFloat_FromDouble(G_PARAM_SPEC_FLOAT(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PyFloat_FromDouble(G_PARAM_SPEC_FLOAT(pspec)->maximum);
- } else if (!strcmp(attr, "epsilon")) {
- return PyFloat_FromDouble(G_PARAM_SPEC_FLOAT(pspec)->epsilon);
- }
- } else if (G_IS_PARAM_SPEC_DOUBLE(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[ssssssssssss]", "__doc__", "__gtype__",
- "blurb", "default_value", "epsilon",
- "flags", "maximum", "minimum", "name", "nick",
- "owner_type", "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return PyFloat_FromDouble(
- G_PARAM_SPEC_DOUBLE(pspec)->default_value);
- } else if (!strcmp(attr, "minimum")) {
- return PyFloat_FromDouble(G_PARAM_SPEC_DOUBLE(pspec)->minimum);
- } else if (!strcmp(attr, "maximum")) {
- return PyFloat_FromDouble(G_PARAM_SPEC_DOUBLE(pspec)->maximum);
- } else if (!strcmp(attr, "epsilon")) {
- return PyFloat_FromDouble(G_PARAM_SPEC_DOUBLE(pspec)->epsilon);
- }
- } else if (G_IS_PARAM_SPEC_STRING(pspec)) {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[ssssssssssssss]", "__doc__", "__gtype__",
- "blurb", "cset_first", "cset_nth", "default_value",
- "ensure_non_null", "flags", "name", "nick",
- "null_fold_if_empty", "owner_type", "substitutor",
- "value_type");
- } else if (!strcmp(attr, "default_value")) {
- return Py_BuildValue(
- "s", G_PARAM_SPEC_STRING(pspec)->default_value);
- } else if (!strcmp(attr, "cset_first")) {
- return Py_BuildValue(
- "s", G_PARAM_SPEC_STRING(pspec)->cset_first);
- } else if (!strcmp(attr, "cset_nth")) {
- return Py_BuildValue(
- "s", G_PARAM_SPEC_STRING(pspec)->cset_nth);
- } else if (!strcmp(attr, "substitutor")) {
- return Py_BuildValue(
- "c", G_PARAM_SPEC_STRING(pspec)->substitutor);
- } else if (!strcmp(attr, "null_fold_if_empty")) {
- return PyBool_FromLong(
- G_PARAM_SPEC_STRING(pspec)->null_fold_if_empty);
- } else if (!strcmp(attr, "ensure_non_null")) {
- return PyBool_FromLong(
- G_PARAM_SPEC_STRING(pspec)->ensure_non_null);
- }
- } else {
- if (!strcmp(attr, "__members__")) {
- return Py_BuildValue("[ssssssss]", "__doc__", "__gtype__", "blurb",
- "flags", "name", "nick",
- "owner_type", "value_type");
-
- /* This is actually not what's exported by GObjects paramspecs,
- * But we exported this in earlier versions, so it's better to keep it here
- * compatibility. But don't add it in __members__, to "hide" it.
- */
- } else if (!strcmp(attr, "default_value")) {
- /* XXX: Raise deprecation warning */
- Py_INCREF(Py_None);
- return Py_None;
- }
- }
-
- PyErr_SetString(PyExc_AttributeError, attr);
- return NULL;
-}
-
-/**
- * pyg_param_spec_new:
- * @pspec: a GParamSpec.
- *
- * Creates a wrapper for a GParamSpec.
- *
- * Returns: the GParamSpec wrapper.
- */
-PyObject *
-pyg_param_spec_new(GParamSpec *pspec)
-{
- PyGParamSpec *self;
-
- self = (PyGParamSpec *)PyObject_NEW(PyGParamSpec,
- &PyGParamSpec_Type);
- if (self == NULL)
- return NULL;
-
- self->pspec = g_param_spec_ref(pspec);
- return (PyObject *)self;
-}
-
-void
-pygobject_paramspec_register_types(PyObject *d)
-{
- Py_TYPE(&PyGParamSpec_Type) = &PyType_Type;
- PyGParamSpec_Type.tp_dealloc = (destructor)pyg_param_spec_dealloc;
- PyGParamSpec_Type.tp_getattr = (getattrfunc)pyg_param_spec_getattr;
- PyGParamSpec_Type.tp_richcompare = pyg_param_spec_richcompare;
- PyGParamSpec_Type.tp_flags = Py_TPFLAGS_DEFAULT;
- PyGParamSpec_Type.tp_repr = (reprfunc)pyg_param_spec_repr;
- PyGParamSpec_Type.tp_hash = (hashfunc)pyg_param_spec_hash;
-
-
- if (PyType_Ready(&PyGParamSpec_Type))
- return;
- PyDict_SetItemString(d, "GParamSpec", (PyObject *)&PyGParamSpec_Type);
-}
diff --git a/gi/_gobject/pygtype.c b/gi/_gobject/pygtype.c
deleted file mode 100644
index 9dc1153..0000000
--- a/gi/_gobject/pygtype.c
+++ /dev/null
@@ -1,1927 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pygtk- Python bindings for the GTK toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- *
- * pygtype.c: glue code to wrap the GType code.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <pyglib.h>
-
-#include "pygobject-private.h"
-#include "pygparamspec.h"
-#include "pygtype.h"
-
-/* -------------- __gtype__ objects ---------------------------- */
-
-typedef struct {
- PyObject_HEAD
- GType type;
-} PyGTypeWrapper;
-
-PYGLIB_DEFINE_TYPE("gobject.GType", PyGTypeWrapper_Type, PyGTypeWrapper);
-
-static PyObject*
-pyg_type_wrapper_richcompare(PyObject *self, PyObject *other, int op)
-{
- if (Py_TYPE(self) == Py_TYPE(other) && Py_TYPE(self) == &PyGTypeWrapper_Type)
- return _pyglib_generic_long_richcompare(((PyGTypeWrapper*)self)->type,
- ((PyGTypeWrapper*)other)->type,
- op);
- else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static long
-pyg_type_wrapper_hash(PyGTypeWrapper *self)
-{
- return (long)self->type;
-}
-
-static PyObject *
-pyg_type_wrapper_repr(PyGTypeWrapper *self)
-{
- char buf[80];
- const gchar *name = g_type_name(self->type);
-
- g_snprintf(buf, sizeof(buf), "<GType %s (%lu)>",
- name?name:"invalid", (unsigned long int) self->type);
- return PYGLIB_PyUnicode_FromString(buf);
-}
-
-static void
-pyg_type_wrapper_dealloc(PyGTypeWrapper *self)
-{
- PyObject_DEL(self);
-}
-
-static GQuark
-_pyg_type_key(GType type) {
- GQuark key;
-
- if (g_type_is_a(type, G_TYPE_INTERFACE)) {
- key = pyginterface_type_key;
- } else if (g_type_is_a(type, G_TYPE_ENUM)) {
- key = pygenum_class_key;
- } else if (g_type_is_a(type, G_TYPE_FLAGS)) {
- key = pygflags_class_key;
- } else if (g_type_is_a(type, G_TYPE_POINTER)) {
- key = pygpointer_class_key;
- } else if (g_type_is_a(type, G_TYPE_BOXED)) {
- key = pygboxed_type_key;
- } else {
- key = pygobject_class_key;
- }
-
- return key;
-}
-
-static PyObject *
-_wrap_g_type_wrapper__get_pytype(PyGTypeWrapper *self, void *closure)
-{
- GQuark key;
- PyObject *py_type;
-
- key = _pyg_type_key(self->type);
-
- py_type = g_type_get_qdata(self->type, key);
- if (!py_type)
- py_type = Py_None;
-
- Py_INCREF(py_type);
- return py_type;
-}
-
-static int
-_wrap_g_type_wrapper__set_pytype(PyGTypeWrapper *self, PyObject* value, void *closure)
-{
- GQuark key;
- PyObject *py_type;
-
- key = _pyg_type_key(self->type);
-
- py_type = g_type_get_qdata(self->type, key);
- Py_CLEAR(py_type);
- if (value == Py_None)
- g_type_set_qdata(self->type, key, NULL);
- else if (PyType_Check(value)) {
- Py_INCREF(value);
- g_type_set_qdata(self->type, key, value);
- } else {
- PyErr_SetString(PyExc_TypeError, "Value must be None or a type object");
- return -1;
- }
-
- return 0;
-}
-
-static PyObject *
-_wrap_g_type_wrapper__get_name(PyGTypeWrapper *self, void *closure)
-{
- const char *name = g_type_name(self->type);
- return PYGLIB_PyUnicode_FromString(name ? name : "invalid");
-}
-
-static PyObject *
-_wrap_g_type_wrapper__get_parent(PyGTypeWrapper *self, void *closure)
-{
- return pyg_type_wrapper_new(g_type_parent(self->type));
-}
-
-static PyObject *
-_wrap_g_type_wrapper__get_fundamental(PyGTypeWrapper *self, void *closure)
-{
- return pyg_type_wrapper_new(g_type_fundamental(self->type));
-}
-
-static PyObject *
-_wrap_g_type_wrapper__get_children(PyGTypeWrapper *self, void *closure)
-{
- guint n_children, i;
- GType *children;
- PyObject *retval;
-
- children = g_type_children(self->type, &n_children);
-
- retval = PyList_New(n_children);
- for (i = 0; i < n_children; i++)
- PyList_SetItem(retval, i, pyg_type_wrapper_new(children[i]));
- g_free(children);
-
- return retval;
-}
-
-static PyObject *
-_wrap_g_type_wrapper__get_interfaces(PyGTypeWrapper *self, void *closure)
-{
- guint n_interfaces, i;
- GType *interfaces;
- PyObject *retval;
-
- interfaces = g_type_interfaces(self->type, &n_interfaces);
-
- retval = PyList_New(n_interfaces);
- for (i = 0; i < n_interfaces; i++)
- PyList_SetItem(retval, i, pyg_type_wrapper_new(interfaces[i]));
- g_free(interfaces);
-
- return retval;
-}
-
-static PyObject *
-_wrap_g_type_wrapper__get_depth(PyGTypeWrapper *self, void *closure)
-{
- return PYGLIB_PyLong_FromLong(g_type_depth(self->type));
-}
-
-static PyGetSetDef _PyGTypeWrapper_getsets[] = {
- { "pytype", (getter)_wrap_g_type_wrapper__get_pytype, (setter)_wrap_g_type_wrapper__set_pytype },
- { "name", (getter)_wrap_g_type_wrapper__get_name, (setter)0 },
- { "fundamental", (getter)_wrap_g_type_wrapper__get_fundamental, (setter)0 },
- { "parent", (getter)_wrap_g_type_wrapper__get_parent, (setter)0 },
- { "children", (getter)_wrap_g_type_wrapper__get_children, (setter)0 },
- { "interfaces", (getter)_wrap_g_type_wrapper__get_interfaces, (setter)0 },
- { "depth", (getter)_wrap_g_type_wrapper__get_depth, (setter)0 },
- { NULL, (getter)0, (setter)0 }
-};
-
-static PyObject*
-_wrap_g_type_is_interface(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_IS_INTERFACE(self->type));
-}
-
-static PyObject*
-_wrap_g_type_is_classed(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_IS_CLASSED(self->type));
-}
-
-static PyObject*
-_wrap_g_type_is_instantiatable(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_IS_INSTANTIATABLE(self->type));
-}
-
-static PyObject*
-_wrap_g_type_is_derivable(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_IS_DERIVABLE(self->type));
-}
-
-static PyObject*
-_wrap_g_type_is_deep_derivable(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_IS_DEEP_DERIVABLE(self->type));
-}
-
-static PyObject*
-_wrap_g_type_is_abstract(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_IS_ABSTRACT(self->type));
-}
-
-static PyObject*
-_wrap_g_type_is_value_abstract(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_IS_VALUE_ABSTRACT(self->type));
-}
-
-static PyObject*
-_wrap_g_type_is_value_type(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_IS_VALUE_TYPE(self->type));
-}
-
-static PyObject*
-_wrap_g_type_has_value_table(PyGTypeWrapper *self)
-{
- return PyBool_FromLong(G_TYPE_HAS_VALUE_TABLE(self->type));
-}
-
-static PyObject*
-_wrap_g_type_from_name(PyGTypeWrapper *_, PyObject *args)
-{
- char *type_name;
- GType type;
-
- if (!PyArg_ParseTuple(args, "s:GType.from_name", &type_name))
- return NULL;
-
- type = g_type_from_name(type_name);
- if (type == 0) {
- PyErr_SetString(PyExc_RuntimeError, "unknown type name");
- return NULL;
- }
-
- return pyg_type_wrapper_new(type);
-}
-
-static PyObject*
-_wrap_g_type_is_a(PyGTypeWrapper *self, PyObject *args)
-{
- PyObject *gparent;
- GType parent;
-
- if (!PyArg_ParseTuple(args, "O:GType.is_a", &gparent))
- return NULL;
- else if ((parent = pyg_type_from_object(gparent)) == 0)
- return NULL;
-
- return PyBool_FromLong(g_type_is_a(self->type, parent));
-}
-
-static PyMethodDef _PyGTypeWrapper_methods[] = {
- { "is_interface", (PyCFunction)_wrap_g_type_is_interface, METH_NOARGS },
- { "is_classed", (PyCFunction)_wrap_g_type_is_classed, METH_NOARGS },
- { "is_instantiatable", (PyCFunction)_wrap_g_type_is_instantiatable, METH_NOARGS },
- { "is_derivable", (PyCFunction)_wrap_g_type_is_derivable, METH_NOARGS },
- { "is_deep_derivable", (PyCFunction)_wrap_g_type_is_deep_derivable, METH_NOARGS },
- { "is_abstract", (PyCFunction)_wrap_g_type_is_abstract, METH_NOARGS },
- { "is_value_abstract", (PyCFunction)_wrap_g_type_is_value_abstract, METH_NOARGS },
- { "is_value_type", (PyCFunction)_wrap_g_type_is_value_type, METH_NOARGS },
- { "has_value_table", (PyCFunction)_wrap_g_type_has_value_table, METH_NOARGS },
- { "from_name", (PyCFunction)_wrap_g_type_from_name, METH_VARARGS | METH_STATIC },
- { "is_a", (PyCFunction)_wrap_g_type_is_a, METH_VARARGS },
- { NULL, 0, 0 }
-};
-
-static int
-pyg_type_wrapper_init(PyGTypeWrapper *self, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist[] = { "object", NULL };
- PyObject *py_object;
- GType type;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O:GType.__init__",
- kwlist, &py_object))
- return -1;
-
- if (!(type = pyg_type_from_object(py_object)))
- return -1;
-
- self->type = type;
-
- return 0;
-}
-
-/**
- * pyg_type_wrapper_new:
- * type: a GType
- *
- * Creates a Python wrapper for a GType.
- *
- * Returns: the Python wrapper.
- */
-PyObject *
-pyg_type_wrapper_new(GType type)
-{
- PyGTypeWrapper *self;
-
- self = (PyGTypeWrapper *)PyObject_NEW(PyGTypeWrapper,
- &PyGTypeWrapper_Type);
- if (self == NULL)
- return NULL;
-
- self->type = type;
- return (PyObject *)self;
-}
-
-/**
- * pyg_type_from_object_strict:
- * obj: a Python object
- * strict: if set to TRUE, raises an exception if it can't perform the
- * conversion
- *
- * converts a python object to a GType. If strict is set, raises an
- * exception if it can't perform the conversion, otherwise returns
- * PY_TYPE_OBJECT.
- *
- * Returns: the corresponding GType, or 0 on error.
- */
-
-GType
-pyg_type_from_object_strict(PyObject *obj, gboolean strict)
-{
- PyObject *gtype;
- GType type;
-
- /* NULL check */
- if (!obj) {
- PyErr_SetString(PyExc_TypeError, "can't get type from NULL object");
- return 0;
- }
-
- /* map some standard types to primitive GTypes ... */
- if (obj == Py_None)
- return G_TYPE_NONE;
- if (PyType_Check(obj)) {
- PyTypeObject *tp = (PyTypeObject *)obj;
-
- if (tp == &PYGLIB_PyLong_Type)
- return G_TYPE_INT;
- else if (tp == &PyBool_Type)
- return G_TYPE_BOOLEAN;
- else if (tp == &PyLong_Type)
- return G_TYPE_LONG;
- else if (tp == &PyFloat_Type)
- return G_TYPE_DOUBLE;
- else if (tp == &PYGLIB_PyUnicode_Type)
- return G_TYPE_STRING;
- else if (tp == &PyBaseObject_Type)
- return PY_TYPE_OBJECT;
- }
-
- if (Py_TYPE(obj) == &PyGTypeWrapper_Type) {
- return ((PyGTypeWrapper *)obj)->type;
- }
-
- /* handle strings */
- if (PYGLIB_PyUnicode_Check(obj)) {
- gchar *name = PYGLIB_PyUnicode_AsString(obj);
-
- type = g_type_from_name(name);
- if (type != 0) {
- return type;
- }
- }
-
- /* finally, look for a __gtype__ attribute on the object */
- gtype = PyObject_GetAttrString(obj, "__gtype__");
-
- if (gtype) {
- if (Py_TYPE(gtype) == &PyGTypeWrapper_Type) {
- type = ((PyGTypeWrapper *)gtype)->type;
- Py_DECREF(gtype);
- return type;
- }
- Py_DECREF(gtype);
- }
-
- PyErr_Clear();
-
- /* Some API like those that take GValues can hold a python object as
- * a pointer. This is potentially dangerous becuase everything is
- * passed in as a PyObject so we can't actually type check it. Only
- * fallback to PY_TYPE_OBJECT if strict checking is disabled
- */
- if (!strict)
- return PY_TYPE_OBJECT;
-
- PyErr_SetString(PyExc_TypeError, "could not get typecode from object");
- return 0;
-}
-
-/**
- * pyg_type_from_object:
- * obj: a Python object
- *
- * converts a python object to a GType. Raises an exception if it
- * can't perform the conversion.
- *
- * Returns: the corresponding GType, or 0 on error.
- */
-GType
-pyg_type_from_object(PyObject *obj)
-{
- /* Legacy call always defaults to strict type checking */
- return pyg_type_from_object_strict(obj, TRUE);
-}
-
-/* -------------- GValue marshalling ------------------ */
-
-/**
- * pyg_enum_get_value:
- * @enum_type: the GType of the flag.
- * @obj: a Python object representing the flag value
- * @val: a pointer to the location to store the integer representation of the flag.
- *
- * Converts a Python object to the integer equivalent. The conversion
- * will depend on the type of the Python object. If the object is an
- * integer, it is passed through directly. If it is a string, it will
- * be treated as a full or short enum name as defined in the GType.
- *
- * Returns: 0 on success or -1 on failure
- */
-gint
-pyg_enum_get_value(GType enum_type, PyObject *obj, gint *val)
-{
- GEnumClass *eclass = NULL;
- gint res = -1;
-
- g_return_val_if_fail(val != NULL, -1);
- if (!obj) {
- *val = 0;
- res = 0;
- } else if (PYGLIB_PyLong_Check(obj)) {
- *val = PYGLIB_PyLong_AsLong(obj);
- res = 0;
-
- if (PyObject_TypeCheck(obj, &PyGEnum_Type) && ((PyGEnum *) obj)->gtype != enum_type) {
- g_warning("expected enumeration type %s, but got %s instead",
- g_type_name(enum_type),
- g_type_name(((PyGEnum *) obj)->gtype));
- }
- /* Dumb code duplication, but probably not worth it to have yet another macro. */
- } else if (PyLong_Check(obj)) {
- *val = PyLong_AsLong(obj);
- res = 0;
-
- if (PyObject_TypeCheck(obj, &PyGEnum_Type) && ((PyGEnum *) obj)->gtype != enum_type) {
- g_warning("expected enumeration type %s, but got %s instead",
- g_type_name(enum_type),
- g_type_name(((PyGEnum *) obj)->gtype));
- }
- } else if (PYGLIB_PyUnicode_Check(obj)) {
- GEnumValue *info;
- char *str = PYGLIB_PyUnicode_AsString(obj);
-
- if (enum_type != G_TYPE_NONE)
- eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
- else {
- PyErr_SetString(PyExc_TypeError, "could not convert string to enum because there is no GType associated to look up the value");
- res = -1;
- }
- info = g_enum_get_value_by_name(eclass, str);
- g_type_class_unref(eclass);
-
- if (!info)
- info = g_enum_get_value_by_nick(eclass, str);
- if (info) {
- *val = info->value;
- res = 0;
- } else {
- PyErr_SetString(PyExc_TypeError, "could not convert string");
- res = -1;
- }
- } else {
- PyErr_SetString(PyExc_TypeError,"enum values must be strings or ints");
- res = -1;
- }
- return res;
-}
-
-/**
- * pyg_flags_get_value:
- * @flag_type: the GType of the flag.
- * @obj: a Python object representing the flag value
- * @val: a pointer to the location to store the integer representation of the flag.
- *
- * Converts a Python object to the integer equivalent. The conversion
- * will depend on the type of the Python object. If the object is an
- * integer, it is passed through directly. If it is a string, it will
- * be treated as a full or short flag name as defined in the GType.
- * If it is a tuple, then the items are treated as strings and ORed
- * together.
- *
- * Returns: 0 on success or -1 on failure
- */
-gint
-pyg_flags_get_value(GType flag_type, PyObject *obj, guint *val)
-{
- GFlagsClass *fclass = NULL;
- gint res = -1;
-
- g_return_val_if_fail(val != NULL, -1);
- if (!obj) {
- *val = 0;
- res = 0;
- } else if (PYGLIB_PyLong_Check(obj)) {
- *val = PYGLIB_PyLong_AsUnsignedLong(obj);
- res = 0;
- } else if (PyLong_Check(obj)) {
- *val = PyLong_AsLongLong(obj);
- res = 0;
- } else if (PYGLIB_PyUnicode_Check(obj)) {
- GFlagsValue *info;
- char *str = PYGLIB_PyUnicode_AsString(obj);
-
- if (flag_type != G_TYPE_NONE)
- fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
- else {
- PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
- res = -1;
- }
- info = g_flags_get_value_by_name(fclass, str);
- g_type_class_unref(fclass);
-
- if (!info)
- info = g_flags_get_value_by_nick(fclass, str);
- if (info) {
- *val = info->value;
- res = 0;
- } else {
- PyErr_SetString(PyExc_TypeError, "could not convert string");
- res = -1;
- }
- } else if (PyTuple_Check(obj)) {
- int i, len;
-
- len = PyTuple_Size(obj);
- *val = 0;
- res = 0;
-
- if (flag_type != G_TYPE_NONE)
- fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
- else {
- PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
- res = -1;
- }
-
- for (i = 0; i < len; i++) {
- PyObject *item = PyTuple_GetItem(obj, i);
- char *str = PYGLIB_PyUnicode_AsString(item);
- GFlagsValue *info = g_flags_get_value_by_name(fclass, str);
-
- if (!info)
- info = g_flags_get_value_by_nick(fclass, str);
- if (info) {
- *val |= info->value;
- } else {
- PyErr_SetString(PyExc_TypeError, "could not convert string");
- res = -1;
- break;
- }
- }
- g_type_class_unref(fclass);
- } else {
- PyErr_SetString(PyExc_TypeError,
- "flag values must be strings, ints, longs, or tuples");
- res = -1;
- }
- return res;
-}
-
-typedef struct {
- fromvaluefunc fromvalue;
- tovaluefunc tovalue;
-} PyGTypeMarshal;
-static GQuark pyg_type_marshal_key = 0;
-
-static PyGTypeMarshal *
-pyg_type_lookup(GType type)
-{
- GType ptype = type;
- PyGTypeMarshal *tm = NULL;
-
- /* recursively lookup types */
- while (ptype) {
- if ((tm = g_type_get_qdata(ptype, pyg_type_marshal_key)) != NULL)
- break;
- ptype = g_type_parent(ptype);
- }
- return tm;
-}
-
-/**
- * pyg_register_gtype_custom:
- * @gtype: the GType for the new type
- * @from_func: a function to convert GValues to Python objects
- * @to_func: a function to convert Python objects to GValues
- *
- * In order to handle specific conversion of gboxed types or new
- * fundamental types, you may use this function to register conversion
- * handlers.
- */
-
-void
-pyg_register_gtype_custom(GType gtype,
- fromvaluefunc from_func,
- tovaluefunc to_func)
-{
- PyGTypeMarshal *tm;
-
- if (!pyg_type_marshal_key)
- pyg_type_marshal_key = g_quark_from_static_string("PyGType::marshal");
-
- tm = g_new(PyGTypeMarshal, 1);
- tm->fromvalue = from_func;
- tm->tovalue = to_func;
- g_type_set_qdata(gtype, pyg_type_marshal_key, tm);
-}
-
-static int
-pyg_value_array_from_pyobject(GValue *value,
- PyObject *obj,
- const GParamSpecValueArray *pspec)
-{
- int len;
- GValueArray *value_array;
- int i;
-
- len = PySequence_Length(obj);
- if (len == -1) {
- PyErr_Clear();
- return -1;
- }
-
- if (pspec && pspec->fixed_n_elements > 0 && len != pspec->fixed_n_elements)
- return -1;
-
- value_array = g_value_array_new(len);
-
- for (i = 0; i < len; ++i) {
- PyObject *item = PySequence_GetItem(obj, i);
- GType type;
- GValue item_value = { 0, };
- int status;
-
- if (! item) {
- PyErr_Clear();
- g_value_array_free(value_array);
- return -1;
- }
-
- if (pspec && pspec->element_spec)
- type = G_PARAM_SPEC_VALUE_TYPE(pspec->element_spec);
- else if (item == Py_None)
- type = G_TYPE_POINTER; /* store None as NULL */
- else {
- type = pyg_type_from_object((PyObject*)Py_TYPE(item));
- if (! type) {
- PyErr_Clear();
- g_value_array_free(value_array);
- Py_DECREF(item);
- return -1;
- }
- }
-
- g_value_init(&item_value, type);
- status = (pspec && pspec->element_spec)
- ? pyg_param_gvalue_from_pyobject(&item_value, item, pspec->element_spec)
- : pyg_value_from_pyobject(&item_value, item);
- Py_DECREF(item);
-
- if (status == -1) {
- g_value_array_free(value_array);
- g_value_unset(&item_value);
- return -1;
- }
-
- g_value_array_append(value_array, &item_value);
- g_value_unset(&item_value);
- }
-
- g_value_take_boxed(value, value_array);
- return 0;
-}
-
-static int
-pyg_array_from_pyobject(GValue *value,
- PyObject *obj)
-{
- int len;
- GArray *array;
- int i;
-
- len = PySequence_Length(obj);
- if (len == -1) {
- PyErr_Clear();
- return -1;
- }
-
- array = g_array_new(FALSE, TRUE, sizeof(GValue));
-
- for (i = 0; i < len; ++i) {
- PyObject *item = PySequence_GetItem(obj, i);
- GType type;
- GValue item_value = { 0, };
- int status;
-
- if (! item) {
- PyErr_Clear();
- g_array_free(array, FALSE);
- return -1;
- }
-
- if (item == Py_None)
- type = G_TYPE_POINTER; /* store None as NULL */
- else {
- type = pyg_type_from_object((PyObject*)Py_TYPE(item));
- if (! type) {
- PyErr_Clear();
- g_array_free(array, FALSE);
- Py_DECREF(item);
- return -1;
- }
- }
-
- g_value_init(&item_value, type);
- status = pyg_value_from_pyobject(&item_value, item);
- Py_DECREF(item);
-
- if (status == -1) {
- g_array_free(array, FALSE);
- g_value_unset(&item_value);
- return -1;
- }
-
- g_array_append_val(array, item_value);
- }
-
- g_value_take_boxed(value, array);
- return 0;
-}
-
-/**
- * pyg_value_from_pyobject_with_error:
- * @value: the GValue object to store the converted value in.
- * @obj: the Python object to convert.
- *
- * This function converts a Python object and stores the result in a
- * GValue. The GValue must be initialised in advance with
- * g_value_init(). If the Python object can't be converted to the
- * type of the GValue, then an error is returned.
- *
- * Returns: 0 on success, -1 on error.
- */
-int
-pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj)
-{
- PyObject *tmp;
- GType value_type = G_VALUE_TYPE(value);
-
- switch (G_TYPE_FUNDAMENTAL(value_type)) {
- case G_TYPE_INTERFACE:
- /* we only handle interface types that have a GObject prereq */
- if (g_type_is_a(value_type, G_TYPE_OBJECT)) {
- if (obj == Py_None)
- g_value_set_object(value, NULL);
- else {
- if (!PyObject_TypeCheck(obj, &PyGObject_Type)) {
- PyErr_SetString(PyExc_TypeError, "GObject is required");
- return -1;
- }
- if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
- value_type)) {
- PyErr_SetString(PyExc_TypeError, "Invalid GObject type for assignment");
- return -1;
- }
- g_value_set_object(value, pygobject_get(obj));
- }
- } else {
- PyErr_SetString(PyExc_TypeError, "Unsupported conversion");
- return -1;
- }
- break;
- case G_TYPE_CHAR:
- if (PYGLIB_PyLong_Check(obj)) {
- glong val;
- val = PYGLIB_PyLong_AsLong(obj);
- if (val >= -128 && val <= 127)
- g_value_set_schar(value, (gchar) val);
- else
- return -1;
- }
-#if PY_VERSION_HEX < 0x03000000
- else if (PyString_Check(obj)) {
- g_value_set_schar(value, PyString_AsString(obj)[0]);
- }
-#endif
- else if (PyUnicode_Check(obj)) {
- tmp = PyUnicode_AsUTF8String(obj);
- g_value_set_schar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
- Py_DECREF(tmp);
- } else {
- PyErr_SetString(PyExc_TypeError, "Cannot convert to TYPE_CHAR");
- return -1;
- }
-
- break;
- case G_TYPE_UCHAR:
- if (PYGLIB_PyLong_Check(obj)) {
- glong val;
- val = PYGLIB_PyLong_AsLong(obj);
- if (val >= 0 && val <= 255)
- g_value_set_uchar(value, (guchar) val);
- else
- return -1;
-#if PY_VERSION_HEX < 0x03000000
- } else if (PyString_Check(obj)) {
- g_value_set_uchar(value, PyString_AsString(obj)[0]);
-#endif
- } else if (PyUnicode_Check(obj)) {
- tmp = PyUnicode_AsUTF8String(obj);
- g_value_set_uchar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
- Py_DECREF(tmp);
- } else {
- PyErr_Clear();
- return -1;
- }
- break;
- case G_TYPE_BOOLEAN:
- g_value_set_boolean(value, PyObject_IsTrue(obj));
- break;
- case G_TYPE_INT:
- g_value_set_int(value, PYGLIB_PyLong_AsLong(obj));
- break;
- case G_TYPE_UINT:
- {
- if (PYGLIB_PyLong_Check(obj)) {
- guint val;
-
- /* check that number is not negative */
- if (PyLong_AsLongLong(obj) < 0)
- return -1;
-
- val = PyLong_AsUnsignedLong(obj);
- if (val <= G_MAXUINT)
- g_value_set_uint(value, val);
- else
- return -1;
- } else {
- g_value_set_uint(value, PyLong_AsUnsignedLong(obj));
- }
- }
- break;
- case G_TYPE_LONG:
- g_value_set_long(value, PYGLIB_PyLong_AsLong(obj));
- break;
- case G_TYPE_ULONG:
-#if PY_VERSION_HEX < 0x03000000
- if (PyInt_Check(obj)) {
- long val;
-
- val = PYGLIB_PyLong_AsLong(obj);
- if (val < 0) {
- PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property");
- return -1;
- }
- g_value_set_ulong(value, (gulong)val);
- } else
-#endif
- if (PyLong_Check(obj))
- g_value_set_ulong(value, PyLong_AsUnsignedLong(obj));
- else
- return -1;
- break;
- case G_TYPE_INT64:
- g_value_set_int64(value, PyLong_AsLongLong(obj));
- break;
- case G_TYPE_UINT64:
-#if PY_VERSION_HEX < 0x03000000
- if (PyInt_Check(obj)) {
- long v = PyInt_AsLong(obj);
- if (v < 0) {
- PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property");
- return -1;
- }
- g_value_set_uint64(value, v);
- } else
-#endif
- if (PyLong_Check(obj))
- g_value_set_uint64(value, PyLong_AsUnsignedLongLong(obj));
- else
- return -1;
- break;
- case G_TYPE_ENUM:
- {
- gint val = 0;
- if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
- return -1;
- }
- g_value_set_enum(value, val);
- }
- break;
- case G_TYPE_FLAGS:
- {
- guint val = 0;
- if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
- return -1;
- }
- g_value_set_flags(value, val);
- }
- break;
- case G_TYPE_FLOAT:
- g_value_set_float(value, PyFloat_AsDouble(obj));
- break;
- case G_TYPE_DOUBLE:
- g_value_set_double(value, PyFloat_AsDouble(obj));
- break;
- case G_TYPE_STRING:
- if (obj == Py_None) {
- g_value_set_string(value, NULL);
- } else {
- PyObject* tmp_str = PyObject_Str(obj);
- if (tmp_str == NULL) {
- PyErr_Clear();
- if (PyUnicode_Check(obj)) {
- tmp = PyUnicode_AsUTF8String(obj);
- g_value_set_string(value, PYGLIB_PyBytes_AsString(tmp));
- Py_DECREF(tmp);
- } else {
- PyErr_SetString(PyExc_TypeError, "Expected string");
- return -1;
- }
- } else {
-#if PY_VERSION_HEX < 0x03000000
- g_value_set_string(value, PyString_AsString(tmp_str));
-#else
- tmp = PyUnicode_AsUTF8String(tmp_str);
- g_value_set_string(value, PyBytes_AsString(tmp));
- Py_DECREF(tmp);
-#endif
- }
- Py_XDECREF(tmp_str);
- }
- break;
- case G_TYPE_POINTER:
- if (obj == Py_None)
- g_value_set_pointer(value, NULL);
- else if (PyObject_TypeCheck(obj, &PyGPointer_Type) &&
- G_VALUE_HOLDS(value, ((PyGPointer *)obj)->gtype))
- g_value_set_pointer(value, pyg_pointer_get(obj, gpointer));
- else if (PYGLIB_CPointer_Check(obj))
- g_value_set_pointer(value, PYGLIB_CPointer_GetPointer(obj, NULL));
- else if (G_VALUE_HOLDS_GTYPE (value))
- g_value_set_gtype (value, pyg_type_from_object (obj));
- else {
- PyErr_SetString(PyExc_TypeError, "Expected pointer");
- return -1;
- }
- break;
- case G_TYPE_BOXED: {
- PyGTypeMarshal *bm;
-
- if (obj == Py_None)
- g_value_set_boxed(value, NULL);
- else if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
- g_value_set_boxed(value, obj);
- else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) &&
- G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype))
- g_value_set_boxed(value, pyg_boxed_get(obj, gpointer));
- else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
- GType type;
- GValue *n_value;
-
- type = pyg_type_from_object((PyObject*)Py_TYPE(obj));
- if (G_UNLIKELY (! type)) {
- return -1;
- }
- n_value = g_new0 (GValue, 1);
- g_value_init (n_value, type);
- g_value_take_boxed (value, n_value);
- return pyg_value_from_pyobject_with_error (n_value, obj);
- }
- else if (PySequence_Check(obj) &&
- G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY))
- return pyg_value_array_from_pyobject(value, obj, NULL);
- else if (PySequence_Check(obj) &&
- G_VALUE_HOLDS(value, G_TYPE_ARRAY))
- return pyg_array_from_pyobject(value, obj);
- else if (PYGLIB_PyUnicode_Check(obj) &&
- G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
- GString *string;
- char *buffer;
- Py_ssize_t len;
- if (PYGLIB_PyUnicode_AsStringAndSize(obj, &buffer, &len))
- return -1;
- string = g_string_new_len(buffer, len);
- g_value_set_boxed(value, string);
- g_string_free (string, TRUE);
- break;
- }
- else if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
- return bm->tovalue(value, obj);
- else if (PYGLIB_CPointer_Check(obj))
- g_value_set_boxed(value, PYGLIB_CPointer_GetPointer(obj, NULL));
- else {
- PyErr_SetString(PyExc_TypeError, "Expected Boxed");
- return -1;
- }
- break;
- }
- case G_TYPE_PARAM:
- /* we need to support both the wrapped _gobject.GParamSpec and the GI
- * GObject.ParamSpec */
- if (G_IS_PARAM_SPEC (pygobject_get (obj)))
- g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj)));
- else if (PyGParamSpec_Check(obj))
- g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL));
- else {
- PyErr_SetString(PyExc_TypeError, "Expected ParamSpec");
- return -1;
- }
- break;
- case G_TYPE_OBJECT:
- if (obj == Py_None) {
- g_value_set_object(value, NULL);
- } else if (PyObject_TypeCheck(obj, &PyGObject_Type) &&
- G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
- G_VALUE_TYPE(value))) {
- g_value_set_object(value, pygobject_get(obj));
- } else {
- PyErr_SetString(PyExc_TypeError, "Expected GObject");
- return -1;
- }
- break;
- case G_TYPE_VARIANT:
- {
- if (obj == Py_None)
- g_value_set_variant(value, NULL);
- else if (pyg_type_from_object_strict(obj, FALSE) == G_TYPE_VARIANT)
- g_value_set_variant(value, pyg_boxed_get(obj, GVariant));
- else {
- PyErr_SetString(PyExc_TypeError, "Expected Variant");
- return -1;
- }
- break;
- }
- default:
- {
- PyGTypeMarshal *bm;
- if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) {
- return bm->tovalue(value, obj);
- } else {
- PyErr_SetString(PyExc_TypeError, "Unknown value type");
- return -1;
- }
- break;
- }
- }
-
- /* If an error occurred, unset the GValue but don't clear the Python error. */
- if (PyErr_Occurred()) {
- g_value_unset(value);
- return -1;
- }
-
- return 0;
-}
-
-/**
- * pyg_value_from_pyobject:
- * @value: the GValue object to store the converted value in.
- * @obj: the Python object to convert.
- *
- * Same basic function as pyg_value_from_pyobject_with_error but clears
- * any Python errors before returning.
- *
- * Returns: 0 on success, -1 on error.
- */
-int
-pyg_value_from_pyobject(GValue *value, PyObject *obj)
-{
- int res = pyg_value_from_pyobject_with_error (value, obj);
-
- if (PyErr_Occurred()) {
- PyErr_Clear();
- return -1;
- }
- return res;
-}
-
-/**
- * pyg_value_as_pyobject:
- * @value: the GValue object.
- * @copy_boxed: true if boxed values should be copied.
- *
- * This function creates/returns a Python wrapper object that
- * represents the GValue passed as an argument.
- *
- * Returns: a PyObject representing the value.
- */
-PyObject *
-pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed)
-{
- gchar buf[128];
-
- switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value))) {
- case G_TYPE_INTERFACE:
- if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_OBJECT))
- return pygobject_new(g_value_get_object(value));
- else
- break;
- case G_TYPE_CHAR: {
- gint8 val = g_value_get_schar(value);
- return PYGLIB_PyUnicode_FromStringAndSize((char *)&val, 1);
- }
- case G_TYPE_UCHAR: {
- guint8 val = g_value_get_uchar(value);
- return PYGLIB_PyBytes_FromStringAndSize((char *)&val, 1);
- }
- case G_TYPE_BOOLEAN: {
- return PyBool_FromLong(g_value_get_boolean(value));
- }
- case G_TYPE_INT:
- return PYGLIB_PyLong_FromLong(g_value_get_int(value));
- case G_TYPE_UINT:
- {
- /* in Python, the Int object is backed by a long. If a
- long can hold the whole value of an unsigned int, use
- an Int. Otherwise, use a Long object to avoid overflow.
- This matches the ULongArg behavior in codegen/argtypes.h */
-#if (G_MAXUINT <= G_MAXLONG)
- return PYGLIB_PyLong_FromLong((glong) g_value_get_uint(value));
-#else
- return PyLong_FromUnsignedLong((gulong) g_value_get_uint(value));
-#endif
- }
- case G_TYPE_LONG:
- return PYGLIB_PyLong_FromLong(g_value_get_long(value));
- case G_TYPE_ULONG:
- {
- gulong val = g_value_get_ulong(value);
-
- if (val <= G_MAXLONG)
- return PYGLIB_PyLong_FromLong((glong) val);
- else
- return PyLong_FromUnsignedLong(val);
- }
- case G_TYPE_INT64:
- {
- gint64 val = g_value_get_int64(value);
-
- if (G_MINLONG <= val && val <= G_MAXLONG)
- return PYGLIB_PyLong_FromLong((glong) val);
- else
- return PyLong_FromLongLong(val);
- }
- case G_TYPE_UINT64:
- {
- guint64 val = g_value_get_uint64(value);
-
- if (val <= G_MAXLONG)
- return PYGLIB_PyLong_FromLong((glong) val);
- else
- return PyLong_FromUnsignedLongLong(val);
- }
- case G_TYPE_ENUM:
- return pyg_enum_from_gtype(G_VALUE_TYPE(value), g_value_get_enum(value));
- case G_TYPE_FLAGS:
- return pyg_flags_from_gtype(G_VALUE_TYPE(value), g_value_get_flags(value));
- case G_TYPE_FLOAT:
- return PyFloat_FromDouble(g_value_get_float(value));
- case G_TYPE_DOUBLE:
- return PyFloat_FromDouble(g_value_get_double(value));
- case G_TYPE_STRING:
- {
- const gchar *str = g_value_get_string(value);
-
- if (str)
- return PYGLIB_PyUnicode_FromString(str);
- Py_INCREF(Py_None);
- return Py_None;
- }
- case G_TYPE_POINTER:
- if (G_VALUE_HOLDS_GTYPE (value))
- return pyg_type_wrapper_new (g_value_get_gtype (value));
- else
- return pyg_pointer_new(G_VALUE_TYPE(value),
- g_value_get_pointer(value));
- case G_TYPE_BOXED: {
- PyGTypeMarshal *bm;
-
- if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) {
- PyObject *ret = (PyObject *)g_value_dup_boxed(value);
- if (ret == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return ret;
- } else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
- GValue *n_value = g_value_get_boxed (value);
- return pyg_value_as_pyobject(n_value, copy_boxed);
- } else if (G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY)) {
- GValueArray *array = (GValueArray *) g_value_get_boxed(value);
- PyObject *ret = PyList_New(array->n_values);
- int i;
- for (i = 0; i < array->n_values; ++i)
- PyList_SET_ITEM(ret, i, pyg_value_as_pyobject
- (array->values + i, copy_boxed));
- return ret;
- } else if (G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
- GString *string = (GString *) g_value_get_boxed(value);
- PyObject *ret = PYGLIB_PyUnicode_FromStringAndSize(string->str, string->len);
- return ret;
- }
- bm = pyg_type_lookup(G_VALUE_TYPE(value));
- if (bm) {
- return bm->fromvalue(value);
- } else {
- if (copy_boxed)
- return pyg_boxed_new(G_VALUE_TYPE(value),
- g_value_get_boxed(value), TRUE, TRUE);
- else
- return pyg_boxed_new(G_VALUE_TYPE(value),
- g_value_get_boxed(value),FALSE,FALSE);
- }
- }
- case G_TYPE_PARAM:
- return pyg_param_spec_new(g_value_get_param(value));
- case G_TYPE_OBJECT:
- return pygobject_new(g_value_get_object(value));
- case G_TYPE_VARIANT:
- {
- GVariant *v = g_value_get_variant(value);
- if (v == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return pyg_boxed_new(G_TYPE_VARIANT, g_variant_ref(v), FALSE, FALSE);
- }
- default:
- {
- PyGTypeMarshal *bm;
- if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))))
- return bm->fromvalue(value);
- break;
- }
- }
- g_snprintf(buf, sizeof(buf), "unknown type %s",
- g_type_name(G_VALUE_TYPE(value)));
- PyErr_SetString(PyExc_TypeError, buf);
- return NULL;
-}
-
-/* -------------- PyGClosure ----------------- */
-
-static void
-pyg_closure_invalidate(gpointer data, GClosure *closure)
-{
- PyGClosure *pc = (PyGClosure *)closure;
- PyGILState_STATE state;
-
- state = pyglib_gil_state_ensure();
- Py_XDECREF(pc->callback);
- Py_XDECREF(pc->extra_args);
- Py_XDECREF(pc->swap_data);
- pyglib_gil_state_release(state);
-
- pc->callback = NULL;
- pc->extra_args = NULL;
- pc->swap_data = NULL;
-}
-
-static void
-pyg_closure_marshal(GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data)
-{
- PyGILState_STATE state;
- PyGClosure *pc = (PyGClosure *)closure;
- PyObject *params, *ret;
- guint i;
-
- state = pyglib_gil_state_ensure();
-
- /* construct Python tuple for the parameter values */
- params = PyTuple_New(n_param_values);
- for (i = 0; i < n_param_values; i++) {
- /* swap in a different initial data for connect_object() */
- if (i == 0 && G_CCLOSURE_SWAP_DATA(closure)) {
- g_return_if_fail(pc->swap_data != NULL);
- Py_INCREF(pc->swap_data);
- PyTuple_SetItem(params, 0, pc->swap_data);
- } else {
- PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
-
- /* error condition */
- if (!item) {
- goto out;
- }
- PyTuple_SetItem(params, i, item);
- }
- }
- /* params passed to function may have extra arguments */
- if (pc->extra_args) {
- PyObject *tuple = params;
- params = PySequence_Concat(tuple, pc->extra_args);
- Py_DECREF(tuple);
- }
- ret = PyObject_CallObject(pc->callback, params);
- if (ret == NULL) {
- if (pc->exception_handler)
- pc->exception_handler(return_value, n_param_values, param_values);
- else
- PyErr_Print();
- goto out;
- }
-
- if (G_IS_VALUE(return_value) && pyg_value_from_pyobject(return_value, ret) != 0) {
- /* If we already have an exception set, use that, otherwise set a
- * generic one */
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_TypeError,
- "can't convert return value to desired type");
-
- if (pc->exception_handler)
- pc->exception_handler(return_value, n_param_values, param_values);
- else
- PyErr_Print();
- }
- Py_DECREF(ret);
-
- out:
- Py_DECREF(params);
- pyglib_gil_state_release(state);
-}
-
-/**
- * pyg_closure_new:
- * callback: a Python callable object
- * extra_args: a tuple of extra arguments, or None/NULL.
- * swap_data: an alternative python object to pass first.
- *
- * Creates a GClosure wrapping a Python callable and optionally a set
- * of additional function arguments. This is needed to attach python
- * handlers to signals, for instance.
- *
- * Returns: the new closure.
- */
-GClosure *
-pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data)
-{
- GClosure *closure;
-
- g_return_val_if_fail(callback != NULL, NULL);
- closure = g_closure_new_simple(sizeof(PyGClosure), NULL);
- g_closure_add_invalidate_notifier(closure, NULL, pyg_closure_invalidate);
- g_closure_set_marshal(closure, pyg_closure_marshal);
- Py_INCREF(callback);
- ((PyGClosure *)closure)->callback = callback;
- if (extra_args && extra_args != Py_None) {
- Py_INCREF(extra_args);
- if (!PyTuple_Check(extra_args)) {
- PyObject *tmp = PyTuple_New(1);
- PyTuple_SetItem(tmp, 0, extra_args);
- extra_args = tmp;
- }
- ((PyGClosure *)closure)->extra_args = extra_args;
- }
- if (swap_data) {
- Py_INCREF(swap_data);
- ((PyGClosure *)closure)->swap_data = swap_data;
- closure->derivative_flag = TRUE;
- }
- return closure;
-}
-
-/**
- * pyg_closure_set_exception_handler:
- * @closure: a closure created with pyg_closure_new()
- * @handler: the handler to call when an exception occurs or NULL for none
- *
- * Sets the handler to call when an exception occurs during closure invocation.
- * The handler is responsible for providing a proper return value to the
- * closure invocation. If @handler is %NULL, the default handler will be used.
- * The default handler prints the exception to stderr and doesn't touch the
- * closure's return value.
- */
-void
-pyg_closure_set_exception_handler(GClosure *closure,
- PyClosureExceptionHandler handler)
-{
- PyGClosure *pygclosure;
-
- g_return_if_fail(closure != NULL);
-
- pygclosure = (PyGClosure *)closure;
- pygclosure->exception_handler = handler;
-}
-/* -------------- PySignalClassClosure ----------------- */
-/* a closure used for the `class closure' of a signal. As this gets
- * all the info from the first argument to the closure and the
- * invocation hint, we can have a single closure that handles all
- * class closure cases. We call a method by the name of the signal
- * with "do_" prepended.
- *
- * We also remove the first argument from the * param list, as it is
- * the instance object, which is passed * implicitly to the method
- * object. */
-
-static void
-pyg_signal_class_closure_marshal(GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data)
-{
- PyGILState_STATE state;
- GObject *object;
- PyObject *object_wrapper;
- GSignalInvocationHint *hint = (GSignalInvocationHint *)invocation_hint;
- gchar *method_name, *tmp;
- PyObject *method;
- PyObject *params, *ret;
- guint i, len;
-
- state = pyglib_gil_state_ensure();
-
- g_return_if_fail(invocation_hint != NULL);
- /* get the object passed as the first argument to the closure */
- object = g_value_get_object(&param_values[0]);
- g_return_if_fail(object != NULL && G_IS_OBJECT(object));
-
- /* get the wrapper for this object */
- object_wrapper = pygobject_new(object);
- g_return_if_fail(object_wrapper != NULL);
-
- /* construct method name for this class closure */
- method_name = g_strconcat("do_", g_signal_name(hint->signal_id), NULL);
-
- /* convert dashes to underscores. For some reason, g_signal_name
- * seems to convert all the underscores in the signal name to
- dashes??? */
- for (tmp = method_name; *tmp != '\0'; tmp++)
- if (*tmp == '-') *tmp = '_';
-
- method = PyObject_GetAttrString(object_wrapper, method_name);
- g_free(method_name);
-
- if (!method) {
- PyErr_Clear();
- Py_DECREF(object_wrapper);
- pyglib_gil_state_release(state);
- return;
- }
- Py_DECREF(object_wrapper);
-
- /* construct Python tuple for the parameter values; don't copy boxed values
- initially because we'll check after the call to see if a copy is needed. */
- params = PyTuple_New(n_param_values - 1);
- for (i = 1; i < n_param_values; i++) {
- PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
-
- /* error condition */
- if (!item) {
- Py_DECREF(params);
- pyglib_gil_state_release(state);
- return;
- }
- PyTuple_SetItem(params, i - 1, item);
- }
-
- ret = PyObject_CallObject(method, params);
-
- /* Copy boxed values if others ref them, this needs to be done regardless of
- exception status. */
- len = PyTuple_Size(params);
- for (i = 0; i < len; i++) {
- PyObject *item = PyTuple_GetItem(params, i);
- if (item != NULL && PyObject_TypeCheck(item, &PyGBoxed_Type)
- && item->ob_refcnt != 1) {
- PyGBoxed* boxed_item = (PyGBoxed*)item;
- if (!boxed_item->free_on_dealloc) {
- boxed_item->boxed = g_boxed_copy(boxed_item->gtype, boxed_item->boxed);
- boxed_item->free_on_dealloc = TRUE;
- }
- }
- }
-
- if (ret == NULL) {
- PyErr_Print();
- Py_DECREF(method);
- Py_DECREF(params);
- pyglib_gil_state_release(state);
- return;
- }
- Py_DECREF(method);
- Py_DECREF(params);
- if (G_IS_VALUE(return_value))
- pyg_value_from_pyobject(return_value, ret);
- Py_DECREF(ret);
- pyglib_gil_state_release(state);
-}
-
-/**
- * pyg_signal_class_closure_get:
- *
- * Returns the GClosure used for the class closure of signals. When
- * called, it will invoke the method do_signalname (for the signal
- * "signalname").
- *
- * Returns: the closure.
- */
-GClosure *
-pyg_signal_class_closure_get(void)
-{
- static GClosure *closure;
-
- if (closure == NULL) {
- closure = g_closure_new_simple(sizeof(GClosure), NULL);
- g_closure_set_marshal(closure, pyg_signal_class_closure_marshal);
-
- g_closure_ref(closure);
- g_closure_sink(closure);
- }
- return closure;
-}
-
-GClosure *
-gclosure_from_pyfunc(PyGObject *object, PyObject *func)
-{
- GSList *l;
- PyGObjectData *inst_data;
- inst_data = pyg_object_peek_inst_data(object->obj);
- if (inst_data) {
- for (l = inst_data->closures; l; l = l->next) {
- PyGClosure *pyclosure = l->data;
- int res = PyObject_RichCompareBool(pyclosure->callback, func, Py_EQ);
- if (res == -1) {
- PyErr_Clear(); // Is there anything else to do?
- } else if (res) {
- return (GClosure*)pyclosure;
- }
- }
- }
- return NULL;
-}
-
-/* ----- __doc__ descriptor for GObject and GInterface ----- */
-
-static void
-object_doc_dealloc(PyObject *self)
-{
- PyObject_FREE(self);
-}
-
-/* append information about signals of a particular gtype */
-static void
-add_signal_docs(GType gtype, GString *string)
-{
- GTypeClass *class = NULL;
- guint *signal_ids, n_ids = 0, i;
-
- if (G_TYPE_IS_CLASSED(gtype))
- class = g_type_class_ref(gtype);
- signal_ids = g_signal_list_ids(gtype, &n_ids);
-
- if (n_ids > 0) {
- g_string_append_printf(string, "Signals from %s:\n",
- g_type_name(gtype));
-
- for (i = 0; i < n_ids; i++) {
- GSignalQuery query;
- guint j;
-
- g_signal_query(signal_ids[i], &query);
-
- g_string_append(string, " ");
- g_string_append(string, query.signal_name);
- g_string_append(string, " (");
- for (j = 0; j < query.n_params; j++) {
- g_string_append(string, g_type_name(query.param_types[j]));
- if (j != query.n_params - 1)
- g_string_append(string, ", ");
- }
- g_string_append(string, ")");
- if (query.return_type && query.return_type != G_TYPE_NONE) {
- g_string_append(string, " -> ");
- g_string_append(string, g_type_name(query.return_type));
- }
- g_string_append(string, "\n");
- }
- g_free(signal_ids);
- g_string_append(string, "\n");
- }
- if (class)
- g_type_class_unref(class);
-}
-
-static void
-add_property_docs(GType gtype, GString *string)
-{
- GObjectClass *class;
- GParamSpec **props;
- guint n_props = 0, i;
- gboolean has_prop = FALSE;
- G_CONST_RETURN gchar *blurb=NULL;
-
- class = g_type_class_ref(gtype);
- props = g_object_class_list_properties(class, &n_props);
-
- for (i = 0; i < n_props; i++) {
- if (props[i]->owner_type != gtype)
- continue; /* these are from a parent type */
-
- /* print out the heading first */
- if (!has_prop) {
- g_string_append_printf(string, "Properties from %s:\n",
- g_type_name(gtype));
- has_prop = TRUE;
- }
- g_string_append_printf(string, " %s -> %s: %s\n",
- g_param_spec_get_name(props[i]),
- g_type_name(props[i]->value_type),
- g_param_spec_get_nick(props[i]));
-
- /* g_string_append_printf crashes on win32 if the third
- argument is NULL. */
- blurb=g_param_spec_get_blurb(props[i]);
- if (blurb)
- g_string_append_printf(string, " %s\n",blurb);
- }
- g_free(props);
- if (has_prop)
- g_string_append(string, "\n");
- g_type_class_unref(class);
-}
-
-static PyObject *
-object_doc_descr_get(PyObject *self, PyObject *obj, PyObject *type)
-{
- GType gtype = 0;
- GString *string;
- PyObject *pystring;
-
- if (obj && pygobject_check(obj, &PyGObject_Type)) {
- gtype = G_OBJECT_TYPE(pygobject_get(obj));
- if (!gtype)
- PyErr_SetString(PyExc_RuntimeError, "could not get object type");
- } else {
- gtype = pyg_type_from_object(type);
- }
- if (!gtype)
- return NULL;
-
- string = g_string_new_len(NULL, 512);
-
- if (g_type_is_a(gtype, G_TYPE_INTERFACE))
- g_string_append_printf(string, "Interface %s\n\n", g_type_name(gtype));
- else if (g_type_is_a(gtype, G_TYPE_OBJECT))
- g_string_append_printf(string, "Object %s\n\n", g_type_name(gtype));
- else
- g_string_append_printf(string, "%s\n\n", g_type_name(gtype));
-
- if (((PyTypeObject *) type)->tp_doc)
- g_string_append_printf(string, "%s\n\n", ((PyTypeObject *) type)->tp_doc);
-
- if (g_type_is_a(gtype, G_TYPE_OBJECT)) {
- GType parent = G_TYPE_OBJECT;
- GArray *parents = g_array_new(FALSE, FALSE, sizeof(GType));
- int iparent;
-
- while (parent) {
- g_array_append_val(parents, parent);
- parent = g_type_next_base(gtype, parent);
- }
-
- for (iparent = parents->len - 1; iparent >= 0; --iparent) {
- GType *interfaces;
- guint n_interfaces, i;
-
- parent = g_array_index(parents, GType, iparent);
- add_signal_docs(parent, string);
- add_property_docs(parent, string);
-
- /* add docs for implemented interfaces */
- interfaces = g_type_interfaces(parent, &n_interfaces);
- for (i = 0; i < n_interfaces; i++)
- add_signal_docs(interfaces[i], string);
- g_free(interfaces);
- }
- g_array_free(parents, TRUE);
- }
-
- pystring = PYGLIB_PyUnicode_FromStringAndSize(string->str, string->len);
- g_string_free(string, TRUE);
- return pystring;
-}
-
-PYGLIB_DEFINE_TYPE("gobject.GObject.__doc__", PyGObjectDoc_Type, PyObject);
-
-/**
- * pyg_object_descr_doc_get:
- *
- * Returns an object intended to be the __doc__ attribute of GObject
- * wrappers. When read in the context of the object it will return
- * some documentation about the signals and properties of the object.
- *
- * Returns: the descriptor.
- */
-PyObject *
-pyg_object_descr_doc_get(void)
-{
- static PyObject *doc_descr = NULL;
-
- if (!doc_descr) {
- Py_TYPE(&PyGObjectDoc_Type) = &PyType_Type;
- if (PyType_Ready(&PyGObjectDoc_Type))
- return NULL;
-
- doc_descr = PyObject_NEW(PyObject, &PyGObjectDoc_Type);
- if (doc_descr == NULL)
- return NULL;
- }
- return doc_descr;
-}
-
-
-/**
- * pyg_pyobj_to_unichar_conv:
- *
- * Converts PyObject value to a unichar and write result to memory
- * pointed to by ptr. Follows the calling convention of a ParseArgs
- * converter (O& format specifier) so it may be used to convert function
- * arguments.
- *
- * Returns: 1 if the conversion succeeds and 0 otherwise. If the conversion
- * did not succeesd, a Python exception is raised
- */
-int pyg_pyobj_to_unichar_conv(PyObject* py_obj, void* ptr)
-{
- gunichar* u = ptr;
- const Py_UNICODE* uni_buffer;
- PyObject* tmp_uni = NULL;
-
- if (PyUnicode_Check(py_obj)) {
- tmp_uni = py_obj;
- Py_INCREF(tmp_uni);
- }
- else {
- tmp_uni = PyUnicode_FromObject(py_obj);
- if (tmp_uni == NULL)
- goto failure;
- }
-
- if ( PyUnicode_GetSize(tmp_uni) != 1) {
- PyErr_SetString(PyExc_ValueError, "unicode character value must be 1 character uniode string");
- goto failure;
- }
- uni_buffer = PyUnicode_AsUnicode(tmp_uni);
- if ( uni_buffer == NULL)
- goto failure;
- *u = uni_buffer[0];
-
- Py_DECREF(tmp_uni);
- return 1;
-
- failure:
- Py_XDECREF(tmp_uni);
- return 0;
-}
-
-
-int
-pyg_param_gvalue_from_pyobject(GValue* value,
- PyObject* py_obj,
- const GParamSpec* pspec)
-{
- if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
- gunichar u;
-
- if (!pyg_pyobj_to_unichar_conv(py_obj, &u)) {
- PyErr_Clear();
- return -1;
- }
- g_value_set_uint(value, u);
- return 0;
- }
- else if (G_IS_PARAM_SPEC_VALUE_ARRAY(pspec))
- return pyg_value_array_from_pyobject(value, py_obj,
- G_PARAM_SPEC_VALUE_ARRAY(pspec));
- else {
- return pyg_value_from_pyobject(value, py_obj);
- }
-}
-
-PyObject*
-pyg_param_gvalue_as_pyobject(const GValue* gvalue,
- gboolean copy_boxed,
- const GParamSpec* pspec)
-{
- if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
- gunichar u;
- Py_UNICODE uni_buffer[2] = { 0, 0 };
-
- u = g_value_get_uint(gvalue);
- uni_buffer[0] = u;
- return PyUnicode_FromUnicode(uni_buffer, 1);
- }
- else {
- return pyg_value_as_pyobject(gvalue, copy_boxed);
- }
-}
-
-gboolean
-pyg_gtype_is_custom(GType gtype)
-{
- return g_type_get_qdata (gtype, pygobject_custom_key) != NULL;
-}
-
-static PyObject *
-_pyg_strv_from_gvalue(const GValue *value)
-{
- gchar **argv = (gchar **) g_value_get_boxed(value);
- int argc = 0, i;
- PyObject *py_argv;
-
- if (argv) {
- while (argv[argc])
- argc++;
- }
- py_argv = PyList_New(argc);
- for (i = 0; i < argc; ++i)
- PyList_SET_ITEM(py_argv, i, PYGLIB_PyUnicode_FromString(argv[i]));
- return py_argv;
-}
-
-static int
-_pyg_strv_to_gvalue(GValue *value, PyObject *obj)
-{
- Py_ssize_t argc, i;
- gchar **argv;
-
- if (!(PyTuple_Check(obj) || PyList_Check(obj)))
- return -1;
-
- argc = PySequence_Length(obj);
- for (i = 0; i < argc; ++i)
- if (!PYGLIB_PyUnicode_Check(PySequence_Fast_GET_ITEM(obj, i)))
- return -1;
- argv = g_new(gchar *, argc + 1);
- for (i = 0; i < argc; ++i)
- argv[i] = g_strdup(PYGLIB_PyUnicode_AsString(PySequence_Fast_GET_ITEM(obj, i)));
- argv[i] = NULL;
- g_value_take_boxed(value, argv);
- return 0;
-}
-
-void
-pygobject_type_register_types(PyObject *d)
-{
- PyGTypeWrapper_Type.tp_dealloc = (destructor)pyg_type_wrapper_dealloc;
- PyGTypeWrapper_Type.tp_richcompare = pyg_type_wrapper_richcompare;
- PyGTypeWrapper_Type.tp_repr = (reprfunc)pyg_type_wrapper_repr;
- PyGTypeWrapper_Type.tp_hash = (hashfunc)pyg_type_wrapper_hash;
- PyGTypeWrapper_Type.tp_flags = Py_TPFLAGS_DEFAULT;
- PyGTypeWrapper_Type.tp_methods = _PyGTypeWrapper_methods;
- PyGTypeWrapper_Type.tp_getset = _PyGTypeWrapper_getsets;
- PyGTypeWrapper_Type.tp_init = (initproc)pyg_type_wrapper_init;
- PYGLIB_REGISTER_TYPE(d, PyGTypeWrapper_Type, "GType");
-
- /* This type lazily registered in pyg_object_descr_doc_get */
- PyGObjectDoc_Type.tp_dealloc = (destructor)object_doc_dealloc;
- PyGObjectDoc_Type.tp_flags = Py_TPFLAGS_DEFAULT;
- PyGObjectDoc_Type.tp_descr_get = (descrgetfunc)object_doc_descr_get;
-
- pyg_register_gtype_custom(G_TYPE_STRV,
- _pyg_strv_from_gvalue,
- _pyg_strv_to_gvalue);
-}
diff --git a/gi/_gobject/pygtype.h b/gi/_gobject/pygtype.h
deleted file mode 100644
index 2f9e7ad..0000000
--- a/gi/_gobject/pygtype.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * pygtk- Python bindings for the GTK toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- * 2004-2008 Johan Dahlin
- * pyginterface.c: wrapper for the gobject library.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGOBJECT_TYPE_H__
-#define __PYGOBJECT_TYPE_H__
-
-void pygobject_type_register_types(PyObject *d);
-
-#endif /* __PYGOBJECT_TYPE_H__ */
diff --git a/gi/_gtktemplate.py b/gi/_gtktemplate.py
new file mode 100644
index 0000000..f253887
--- /dev/null
+++ b/gi/_gtktemplate.py
@@ -0,0 +1,307 @@
+# Copyright 2015 Dustin Spicuzza <dustin@virtualroadside.com>
+# 2018 Nikita Churaev <lamefun.x0r@gmail.com>
+# 2018 Christoph Reiter <reiter.christoph@gmail.com>
+#
+# 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
+
+import os
+from collections import abc
+from functools import partial
+
+from gi.repository import GLib, GObject, Gio
+
+
+def _extract_handler_and_args(obj_or_map, handler_name):
+ handler = None
+ if isinstance(obj_or_map, abc.Mapping):
+ handler = obj_or_map.get(handler_name, None)
+ else:
+ handler = getattr(obj_or_map, handler_name, None)
+
+ if handler is None:
+ raise AttributeError('Handler %s not found' % handler_name)
+
+ args = ()
+ if isinstance(handler, abc.Sequence):
+ if len(handler) == 0:
+ raise TypeError("Handler %s tuple can not be empty" % handler)
+ args = handler[1:]
+ handler = handler[0]
+
+ elif not callable(handler):
+ raise TypeError('Handler %s is not a method, function or tuple' % handler)
+
+ return handler, args
+
+
+def define_builder_scope():
+ from gi.repository import Gtk
+
+ class BuilderScope(GObject.GObject, Gtk.BuilderScope):
+
+ def __init__(self, scope_object=None):
+ super().__init__()
+ self._scope_object = scope_object
+
+ def do_create_closure(self, builder, func_name, flags, obj):
+ current_object = builder.get_current_object() or self._scope_object
+
+ if not self._scope_object:
+ current_object = builder.get_current_object()
+ if func_name not in current_object.__gtktemplate_methods__:
+ return None
+
+ current_object.__gtktemplate_handlers__.add(func_name)
+ handler_name = current_object.__gtktemplate_methods__[func_name]
+ else:
+ current_object = self._scope_object
+ handler_name = func_name
+
+ swapped = int(flags & Gtk.BuilderClosureFlags.SWAPPED)
+ if swapped:
+ raise RuntimeError(
+ "%r not supported" % GObject.ConnectFlags.SWAPPED)
+ return None
+
+ handler, args = _extract_handler_and_args(current_object, handler_name)
+
+ if obj:
+ p = partial(handler, *args, swap_data=obj)
+ else:
+ p = partial(handler, *args)
+
+ p.__gtk_template__ = True
+ return p
+
+ return BuilderScope
+
+
+def connect_func(builder, obj, signal_name, handler_name,
+ connect_object, flags, cls):
+
+ if handler_name not in cls.__gtktemplate_methods__:
+ return
+
+ method_name = cls.__gtktemplate_methods__[handler_name]
+ template_inst = builder.get_object(cls.__gtype_name__)
+ template_inst.__gtktemplate_handlers__.add(handler_name)
+ handler = getattr(template_inst, method_name)
+
+ after = int(flags & GObject.ConnectFlags.AFTER)
+ swapped = int(flags & GObject.ConnectFlags.SWAPPED)
+ if swapped:
+ raise RuntimeError(
+ "%r not supported" % GObject.ConnectFlags.SWAPPED)
+
+ if connect_object is not None:
+ if after:
+ func = obj.connect_object_after
+ else:
+ func = obj.connect_object
+ func(signal_name, handler, connect_object)
+ else:
+ if after:
+ func = obj.connect_after
+ else:
+ func = obj.connect
+ func(signal_name, handler)
+
+
+def register_template(cls):
+ from gi.repository import Gtk
+
+ bound_methods = {}
+ bound_widgets = {}
+
+ for attr_name, obj in list(cls.__dict__.items()):
+ if isinstance(obj, CallThing):
+ setattr(cls, attr_name, obj._func)
+ handler_name = obj._name
+ if handler_name is None:
+ handler_name = attr_name
+
+ if handler_name in bound_methods:
+ old_attr_name = bound_methods[handler_name]
+ raise RuntimeError(
+ "Error while exposing handler %r as %r, "
+ "already available as %r" % (
+ handler_name, attr_name, old_attr_name))
+ else:
+ bound_methods[handler_name] = attr_name
+ elif isinstance(obj, Child):
+ widget_name = obj._name
+ if widget_name is None:
+ widget_name = attr_name
+
+ if widget_name in bound_widgets:
+ old_attr_name = bound_widgets[widget_name]
+ raise RuntimeError(
+ "Error while exposing child %r as %r, "
+ "already available as %r" % (
+ widget_name, attr_name, old_attr_name))
+ else:
+ bound_widgets[widget_name] = attr_name
+ cls.bind_template_child_full(widget_name, obj._internal, 0)
+
+ cls.__gtktemplate_methods__ = bound_methods
+ cls.__gtktemplate_widgets__ = bound_widgets
+
+ if Gtk._version == "4.0":
+ BuilderScope = define_builder_scope()
+ cls.set_template_scope(BuilderScope())
+ else:
+ cls.set_connect_func(connect_func, cls)
+
+ base_init_template = cls.init_template
+ cls.__dontuse_ginstance_init__ = \
+ lambda s: init_template(s, cls, base_init_template)
+ # To make this file work with older PyGObject we expose our init code
+ # as init_template() but make it a noop when we call it ourselves first
+ cls.init_template = cls.__dontuse_ginstance_init__
+
+
+def init_template(self, cls, base_init_template):
+ self.init_template = lambda: None
+
+ if self.__class__ is not cls:
+ raise TypeError(
+ "Inheritance from classes with @Gtk.Template decorators "
+ "is not allowed at this time")
+
+ self.__gtktemplate_handlers__ = set()
+
+ base_init_template(self)
+
+ for widget_name, attr_name in self.__gtktemplate_widgets__.items():
+ self.__dict__[attr_name] = self.get_template_child(cls, widget_name)
+
+ for handler_name, attr_name in self.__gtktemplate_methods__.items():
+ if handler_name not in self.__gtktemplate_handlers__:
+ raise RuntimeError(
+ "Handler '%s' was declared with @Gtk.Template.Callback "
+ "but was not present in template" % handler_name)
+
+
+class Child(object):
+
+ def __init__(self, name=None, **kwargs):
+ self._name = name
+ self._internal = kwargs.pop("internal", False)
+ if kwargs:
+ raise TypeError("Unhandled arguments: %r" % kwargs)
+
+
+class CallThing(object):
+
+ def __init__(self, name, func):
+ self._name = name
+ self._func = func
+
+
+class Callback(object):
+
+ def __init__(self, name=None):
+ self._name = name
+
+ def __call__(self, func):
+ return CallThing(self._name, func)
+
+
+def validate_resource_path(path):
+ """Raises GLib.Error in case the resource doesn't exist"""
+
+ try:
+ Gio.resources_get_info(path, Gio.ResourceLookupFlags.NONE)
+ except GLib.Error:
+ # resources_get_info() doesn't handle overlays but we keep using it
+ # as a fast path.
+ # https://gitlab.gnome.org/GNOME/pygobject/issues/230
+ Gio.resources_lookup_data(path, Gio.ResourceLookupFlags.NONE)
+
+
+class Template(object):
+
+ def __init__(self, **kwargs):
+ self.string = None
+ self.filename = None
+ self.resource_path = None
+ if "string" in kwargs:
+ self.string = kwargs.pop("string")
+ elif "filename" in kwargs:
+ self.filename = kwargs.pop("filename")
+ elif "resource_path" in kwargs:
+ self.resource_path = kwargs.pop("resource_path")
+ else:
+ raise TypeError(
+ "Requires one of the following arguments: "
+ "string, filename, resource_path")
+
+ if kwargs:
+ raise TypeError("Unhandled keyword arguments %r" % kwargs)
+
+ @classmethod
+ def from_file(cls, filename):
+ return cls(filename=filename)
+
+ @classmethod
+ def from_string(cls, string):
+ return cls(string=string)
+
+ @classmethod
+ def from_resource(cls, resource_path):
+ return cls(resource_path=resource_path)
+
+ Callback = Callback
+
+ Child = Child
+
+ def __call__(self, cls):
+ from gi.repository import Gtk
+
+ if not isinstance(cls, type) or not issubclass(cls, Gtk.Widget):
+ raise TypeError("Can only use @Gtk.Template on Widgets")
+
+ if "__gtype_name__" not in cls.__dict__:
+ raise TypeError(
+ "%r does not have a __gtype_name__. Set it to the name "
+ "of the class in your template" % cls.__name__)
+
+ if hasattr(cls, "__gtktemplate_methods__"):
+ raise TypeError("Cannot nest template classes")
+
+ if self.string is not None:
+ data = self.string
+ if not isinstance(data, bytes):
+ data = data.encode("utf-8")
+ bytes_ = GLib.Bytes.new(data)
+ cls.set_template(bytes_)
+ register_template(cls)
+ return cls
+ elif self.resource_path is not None:
+ validate_resource_path(self.resource_path)
+ cls.set_template_from_resource(self.resource_path)
+ register_template(cls)
+ return cls
+ else:
+ assert self.filename is not None
+ file_ = Gio.File.new_for_path(os.fspath(self.filename))
+ bytes_ = GLib.Bytes.new(file_.load_contents()[1])
+ cls.set_template(bytes_)
+ register_template(cls)
+ return cls
+
+
+__all__ = ["Template"]
diff --git a/gi/_glib/option.py b/gi/_option.py
index 54e802f..2fa54d8 100644
--- a/gi/_glib/option.py
+++ b/gi/_option.py
@@ -15,9 +15,7 @@
# 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 Street, Fifth Floor, Boston, MA 02110-1301
-# USA
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
"""GOption command line parser
@@ -33,16 +31,10 @@ import sys
import optparse
from optparse import OptParseError, OptionError, OptionValueError, \
BadOptionError, OptionConflictError
-from ..module import get_introspection_module
+from .module import get_introspection_module
-if sys.version_info >= (3, 0):
- _basestring = str
- _bytes = lambda s: s.encode()
-else:
- _basestring = basestring
- _bytes = str
-
-from gi._glib import _glib
+from gi import _gi
+from gi._error import GError
GLib = get_introspection_module('GLib')
OPTION_CONTEXT_ERROR_QUARK = GLib.quark_to_string(GLib.option_error_quark())
@@ -70,17 +62,20 @@ class Option(optparse.Option):
filename The supplied arguments are read as filename, GOption
parses this type in with the GLib filename encoding.
- Attributes:
- optional_arg This does not need a arguement, but it can be supplied.
- hidden The help list does not show this option
- in_main This option apears in the main group, this should only
- be used for backwards compatibility.
+ :ivar optional_arg:
+ This does not need a arguement, but it can be supplied.
+ :ivar hidden:
+ The help list does not show this option
+ :ivar in_main:
+ This option apears in the main group, this should only
+ be used for backwards compatibility.
Use Option.REMAINING as option name to get all positional arguments.
- NOTE: Every argument to an option is passed as utf-8 coded string, the only
- exception are options which use the 'filename' type, its arguments
- are passed as strings in the GLib filename encoding.
+ .. NOTE::
+ Every argument to an option is passed as utf-8 coded string, the only
+ exception are options which use the 'filename' type, its arguments
+ are passed as strings in the GLib filename encoding.
For further help, see optparse.Option.
"""
@@ -135,28 +130,36 @@ class Option(optparse.Option):
flags |= GLib.OptionFlags.FILENAME
for (long_name, short_name) in zip(self._long_opts, self._short_opts):
- yield (long_name[2:], _bytes(short_name[1]), flags, self.help, self.metavar)
+ short_bytes = short_name[1]
+ if not isinstance(short_bytes, bytes):
+ short_bytes = short_bytes.encode("utf-8")
+ yield (long_name[2:], short_bytes, flags, self.help, self.metavar)
for long_name in self._long_opts[len(self._short_opts):]:
- yield (long_name[2:], _bytes('\0'), flags, self.help, self.metavar)
+ yield (long_name[2:], b'\0', flags, self.help, self.metavar)
class OptionGroup(optparse.OptionGroup):
"""A group of command line options.
- Arguements:
- name: The groups name, used to create the
- --help-{name} option
- description: Shown as title of the groups help view
- help_description: Shown as help to the --help-{name} option
- option_list: The options used in this group, must be option.Option()
- defaults: A dicitionary of default values
- translation_domain: Sets the translation domain for gettext().
-
- NOTE: This OptionGroup does not exactly map the optparse.OptionGroup
- interface. There is no parser object to supply, but it is possible
- to set default values and option_lists. Also the default values and
- values are not shared with the OptionParser.
+ :param str name:
+ The groups name, used to create the --help-{name} option
+ :param str description:
+ Shown as title of the groups help view
+ :param str help_description:
+ Shown as help to the --help-{name} option
+ :param list option_list:
+ The options used in this group, must be option.Option()
+ :param dict defaults:
+ A dicitionary of default values
+ :param translation_domain:
+ Sets the translation domain for gettext().
+
+ .. NOTE::
+ This OptionGroup does not exactly map the optparse.OptionGroup
+ interface. There is no parser object to supply, but it is possible
+ to set default values and option_lists. Also the default values and
+ values are not shared with the OptionParser.
To pass a OptionGroup into a function which expects a GOptionGroup (e.g.
gnome_program_init() ). OptionGroup.get_option_group() can be used.
@@ -196,14 +199,14 @@ class OptionGroup(optparse.OptionGroup):
opt.process(option_name, option_value, self.values, parser)
except OptionValueError:
error = sys.exc_info()[1]
- gerror = _glib.GError(str(error))
+ gerror = GError(str(error))
gerror.domain = OPTION_CONTEXT_ERROR_QUARK
gerror.code = GLib.OptionError.BAD_VALUE
gerror.message = str(error)
raise gerror
- group = _glib.OptionGroup(self.name, self.description,
- self.help_description, callback)
+ group = _gi.OptionGroup(self.name, self.description,
+ self.help_description, callback)
if self.translation_domain:
group.set_translation_domain(self.translation_domain)
@@ -226,7 +229,7 @@ class OptionGroup(optparse.OptionGroup):
def set_values_to_defaults(self):
for option in self.option_list:
default = self.defaults.get(option.dest)
- if isinstance(default, _basestring):
+ if isinstance(default, str):
opt_str = option.get_opt_string()
self.defaults[option.dest] = option.check_value(
opt_str, default)
@@ -236,15 +239,16 @@ class OptionGroup(optparse.OptionGroup):
class OptionParser(optparse.OptionParser):
"""Command line parser with GOption support.
- NOTE: The OptionParser interface is not the exactly the same as the
- optparse.OptionParser interface. Especially the usage parameter
- is only used to show the metavar of the arguements.
+ :param bool help_enabled:
+ The --help, --help-all and --help-{group} options are enabled (default).
+ :param bool ignore_unknown_options:
+ Do not throw a exception when a option is not knwon, the option
+ will be in the result list.
- Attribues:
- help_enabled: The --help, --help-all and --help-{group}
- options are enabled (default).
- ignore_unknown_options: Do not throw a exception when a option is not
- knwon, the option will be in the result list.
+ .. NOTE::
+ The OptionParser interface is not the exactly the same as the
+ optparse.OptionParser interface. Especially the usage parameter
+ is only used to show the metavar of the arguements.
OptionParser.add_option_group() does not only accept OptionGroup instances
but also glib.OptionGroup, which is returned by gtk_get_option_group().
@@ -277,12 +281,12 @@ class OptionParser(optparse.OptionParser):
parameter_string = self.usage + " - " + self.description
else:
parameter_string = self.usage
- context = _glib.OptionContext(parameter_string)
+ context = _gi.OptionContext(parameter_string)
context.set_help_enabled(self.help_enabled)
context.set_ignore_unknown_options(self.ignore_unknown_options)
for option_group in self.option_groups:
- if isinstance(option_group, _glib.OptionGroup):
+ if isinstance(option_group, _gi.OptionGroup):
g_group = option_group
else:
g_group = option_group.get_option_group(self)
@@ -295,7 +299,7 @@ class OptionParser(optparse.OptionParser):
opt = self._short_opt[option_name]
opt.process(option_name, option_value, values, self)
- main_group = _glib.OptionGroup(None, None, None, callback)
+ main_group = _gi.OptionGroup(None, None, None, callback)
main_entries = []
for option in self.option_list:
main_entries.extend(option._to_goptionentries())
@@ -305,7 +309,7 @@ class OptionParser(optparse.OptionParser):
return context
def add_option_group(self, *args, **kwargs):
- if isinstance(args[0], _basestring):
+ if isinstance(args[0], str):
optparse.OptionParser.add_option_group(self,
OptionGroup(self, *args, **kwargs))
return
@@ -315,7 +319,7 @@ class OptionParser(optparse.OptionParser):
args[0].parser = self
if args[0].parser is not self:
raise ValueError("invalid OptionGroup (wrong parser)")
- if isinstance(args[0], _glib.OptionGroup):
+ if isinstance(args[0], _gi.OptionGroup):
self.option_groups.append(args[0])
return
optparse.OptionParser.add_option_group(self, *args, **kwargs)
@@ -336,11 +340,10 @@ class OptionParser(optparse.OptionParser):
rargs[:] = context.parse([sys.argv[0]] + rargs)[1:]
def parse_args(self, args=None, values=None):
- old_args = args or []
try:
options, args = optparse.OptionParser.parse_args(
self, args, values)
- except _glib.GError:
+ except GError:
error = sys.exc_info()[1]
if error.domain != OPTION_CONTEXT_ERROR_QUARK:
raise
@@ -357,7 +360,7 @@ class OptionParser(optparse.OptionParser):
for key, value in group.values.__dict__.items():
options.ensure_value(key, value)
- args = args[2:-len(old_args)]
return options, args
+
make_option = Option
diff --git a/gi/_ossighelper.py b/gi/_ossighelper.py
new file mode 100644
index 0000000..fba24e6
--- /dev/null
+++ b/gi/_ossighelper.py
@@ -0,0 +1,239 @@
+# Copyright 2017 Christoph Reiter
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import print_function
+
+import os
+import socket
+import signal
+import threading
+from contextlib import closing, contextmanager
+
+from . import _gi
+
+
+def ensure_socket_not_inheritable(sock):
+ """Ensures that the socket is not inherited by child processes
+
+ Raises:
+ EnvironmentError
+ NotImplementedError: With Python <3.4 on Windows
+ """
+
+ if hasattr(sock, "set_inheritable"):
+ sock.set_inheritable(False)
+ else:
+ try:
+ import fcntl
+ except ImportError:
+ raise NotImplementedError(
+ "Not implemented for older Python on Windows")
+ else:
+ fd = sock.fileno()
+ flags = fcntl.fcntl(fd, fcntl.F_GETFD)
+ fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)
+
+
+_wakeup_fd_is_active = False
+"""Since we can't check if set_wakeup_fd() is already used for nested event
+loops without introducing a race condition we keep track of it globally.
+"""
+
+
+@contextmanager
+def wakeup_on_signal():
+ """A decorator for functions which create a glib event loop to keep
+ Python signal handlers working while the event loop is idling.
+
+ In case an OS signal is received will wake the default event loop up
+ shortly so that any registered Python signal handlers registered through
+ signal.signal() can run.
+
+ In case the wrapped function is not called from the main thread it will be
+ called as is and it will not wake up the default loop for signals.
+ """
+
+ global _wakeup_fd_is_active
+
+ if _wakeup_fd_is_active:
+ yield
+ return
+
+ from gi.repository import GLib
+
+ read_socket, write_socket = socket.socketpair()
+ with closing(read_socket), closing(write_socket):
+
+ for sock in [read_socket, write_socket]:
+ sock.setblocking(False)
+ ensure_socket_not_inheritable(sock)
+
+ try:
+ orig_fd = signal.set_wakeup_fd(write_socket.fileno())
+ except ValueError:
+ # Raised in case this is not the main thread -> give up.
+ yield
+ return
+ else:
+ _wakeup_fd_is_active = True
+
+ def signal_notify(source, condition):
+ if condition & GLib.IO_IN:
+ try:
+ return bool(read_socket.recv(1))
+ except EnvironmentError as e:
+ print(e)
+ return False
+ return True
+ else:
+ return False
+
+ try:
+ if os.name == "nt":
+ channel = GLib.IOChannel.win32_new_socket(
+ read_socket.fileno())
+ else:
+ channel = GLib.IOChannel.unix_new(read_socket.fileno())
+
+ source_id = GLib.io_add_watch(
+ channel,
+ GLib.PRIORITY_DEFAULT,
+ (GLib.IOCondition.IN | GLib.IOCondition.HUP |
+ GLib.IOCondition.NVAL | GLib.IOCondition.ERR),
+ signal_notify)
+ try:
+ yield
+ finally:
+ GLib.source_remove(source_id)
+ finally:
+ write_fd = signal.set_wakeup_fd(orig_fd)
+ if write_fd != write_socket.fileno():
+ # Someone has called set_wakeup_fd while func() was active,
+ # so let's re-revert again.
+ signal.set_wakeup_fd(write_fd)
+ _wakeup_fd_is_active = False
+
+
+PyOS_getsig = _gi.pyos_getsig
+
+# We save the signal pointer so we can detect if glib has changed the
+# signal handler behind Python's back (GLib.unix_signal_add)
+if signal.getsignal(signal.SIGINT) is signal.default_int_handler:
+ startup_sigint_ptr = PyOS_getsig(signal.SIGINT)
+else:
+ # Something has set the handler before import, we can't get a ptr
+ # for the default handler so make sure the pointer will never match.
+ startup_sigint_ptr = -1
+
+
+def sigint_handler_is_default():
+ """Returns if on SIGINT the default Python handler would be called"""
+
+ return (signal.getsignal(signal.SIGINT) is signal.default_int_handler and
+ PyOS_getsig(signal.SIGINT) == startup_sigint_ptr)
+
+
+@contextmanager
+def sigint_handler_set_and_restore_default(handler):
+ """Context manager for saving/restoring the SIGINT handler default state.
+
+ Will only restore the default handler again if the handler is not changed
+ while the context is active.
+ """
+
+ assert sigint_handler_is_default()
+
+ signal.signal(signal.SIGINT, handler)
+ sig_ptr = PyOS_getsig(signal.SIGINT)
+ try:
+ yield
+ finally:
+ if signal.getsignal(signal.SIGINT) is handler and \
+ PyOS_getsig(signal.SIGINT) == sig_ptr:
+ signal.signal(signal.SIGINT, signal.default_int_handler)
+
+
+def is_main_thread():
+ """Returns True in case the function is called from the main thread"""
+
+ return threading.current_thread().name == "MainThread"
+
+
+_callback_stack = []
+_sigint_called = False
+
+
+@contextmanager
+def register_sigint_fallback(callback):
+ """Installs a SIGINT signal handler in case the default Python one is
+ active which calls 'callback' in case the signal occurs.
+
+ Only does something if called from the main thread.
+
+ In case of nested context managers the signal handler will be only
+ installed once and the callbacks will be called in the reverse order
+ of their registration.
+
+ The old signal handler will be restored in case no signal handler is
+ registered while the context is active.
+ """
+
+ # To handle multiple levels of event loops we need to call the last
+ # callback first, wait until the inner most event loop returns control
+ # and only then call the next callback, and so on... until we
+ # reach the outer most which manages the signal handler and raises
+ # in the end
+
+ global _callback_stack, _sigint_called
+
+ if not is_main_thread():
+ yield
+ return
+
+ if not sigint_handler_is_default():
+ if _callback_stack:
+ # This is an inner event loop, append our callback
+ # to the stack so the parent context can call it.
+ _callback_stack.append(callback)
+ try:
+ yield
+ finally:
+ cb = _callback_stack.pop()
+ if _sigint_called:
+ cb()
+ else:
+ # There is a signal handler set by the user, just do nothing
+ yield
+ return
+
+ _sigint_called = False
+
+ def sigint_handler(sig_num, frame):
+ global _callback_stack, _sigint_called
+
+ if _sigint_called:
+ return
+ _sigint_called = True
+ _callback_stack.pop()()
+
+ _callback_stack.append(callback)
+ try:
+ with sigint_handler_set_and_restore_default(sigint_handler):
+ yield
+ finally:
+ if _sigint_called:
+ signal.default_int_handler(signal.SIGINT, None)
+ else:
+ _callback_stack.pop()
diff --git a/gi/_gobject/propertyhelper.py b/gi/_propertyhelper.py
index c9400df..def34b2 100644
--- a/gi/_gobject/propertyhelper.py
+++ b/gi/_propertyhelper.py
@@ -2,7 +2,7 @@
# pygobject - Python bindings for the GObject library
# Copyright (C) 2007 Johan Dahlin
#
-# gobject/propertyhelper.py: GObject property wrapper/helper
+# gi/_propertyhelper.py: GObject property wrapper/helper
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -15,67 +15,83 @@
# 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 Street, Fifth Floor, Boston, MA 02110-1301
-# USA
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
-import sys
-
-from . import _gobject
-
-from .constants import \
+from . import _gi
+from ._constants import \
TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, \
TYPE_BOOLEAN, TYPE_INT, TYPE_UINT, TYPE_LONG, \
TYPE_ULONG, TYPE_INT64, TYPE_UINT64, TYPE_ENUM, TYPE_FLAGS, \
TYPE_FLOAT, TYPE_DOUBLE, TYPE_STRING, \
TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, \
TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV, TYPE_VARIANT
-from ._gobject import \
- G_MAXFLOAT, G_MAXDOUBLE, \
- G_MININT, G_MAXINT, G_MAXUINT, G_MINLONG, G_MAXLONG, \
- G_MAXULONG
-if sys.version_info >= (3, 0):
- _basestring = str
- _long = int
-else:
- _basestring = basestring
- _long = long
+G_MAXFLOAT = _gi.G_MAXFLOAT
+G_MAXDOUBLE = _gi.G_MAXDOUBLE
+G_MININT = _gi.G_MININT
+G_MAXINT = _gi.G_MAXINT
+G_MAXUINT = _gi.G_MAXUINT
+G_MINLONG = _gi.G_MINLONG
+G_MAXLONG = _gi.G_MAXLONG
+G_MAXULONG = _gi.G_MAXULONG
class Property(object):
- """
- Creates a new property which in conjunction with GObject subclass will
- create a property proxy:
-
- class MyObject(GObject.GObject):
- ... prop = GObject.Property(type=str)
+ """Creates a new Property which when used in conjunction with
+ GObject subclass will create a Python property accessor for the
+ GObject ParamSpec.
+
+ :param callable getter:
+ getter to get the value of the property
+ :param callable setter:
+ setter to set the value of the property
+ :param type type:
+ type of property
+ :param default:
+ default value, must match the property type.
+ :param str nick:
+ short description
+ :param str blurb:
+ long description
+ :param GObject.ParamFlags flags:
+ parameter flags
+ :keyword minimum:
+ minimum allowed value (int, float, long only)
+ :keyword maximum:
+ maximum allowed value (int, float, long only)
+
+ .. code-block:: python
+
+ class MyObject(GObject.Object):
+ prop = GObject.Property(type=str)
obj = MyObject()
obj.prop = 'value'
obj.prop # now is 'value'
- The API is similar to the builtin property:
+ The API is similar to the builtin :py:func:`property`:
+
+ .. code-block:: python
- class AnotherObject(GObject.GObject):
- @GObject.Property
- def prop(self):
- '''Read only property.'''
- return ...
+ class AnotherObject(GObject.Object):
+ value = 0
- @GObject.Property(type=int)
- def propInt(self):
- '''Read-write integer property.'''
- return ...
+ @GObject.Property
+ def prop(self):
+ 'Read only property.'
+ return 1
- @propInt.setter
- def propInt(self, value):
- ...
+ @GObject.Property(type=int)
+ def propInt(self):
+ 'Read-write integer property.'
+ return self.value
+
+ @propInt.setter
+ def propInt(self, value):
+ self.value = value
"""
_type_from_pytype_lookup = {
- # Put long_ first in case long_ and int are the same so int clobbers long_
- _long: TYPE_LONG,
int: TYPE_INT,
bool: TYPE_BOOLEAN,
float: TYPE_DOUBLE,
@@ -123,31 +139,8 @@ class Property(object):
return "<class 'GObject.Property'>"
def __init__(self, getter=None, setter=None, type=None, default=None,
- nick='', blurb='', flags=_gobject.PARAM_READWRITE,
+ nick='', blurb='', flags=_gi.PARAM_READWRITE,
minimum=None, maximum=None):
- """
- @param getter: getter to get the value of the property
- @type getter: callable
- @param setter: setter to set the value of the property
- @type setter: callable
- @param type: type of property
- @type type: type
- @param default: default value
- @param nick: short description
- @type nick: string
- @param blurb: long description
- @type blurb: string
- @param flags: parameter flags, one of:
- - gobject.PARAM_READABLE
- - gobject.PARAM_READWRITE
- - gobject.PARAM_WRITABLE
- - gobject.PARAM_CONSTRUCT
- - gobject.PARAM_CONSTRUCT_ONLY
- - gobject.PARAM_LAX_VALIDATION
- @keyword minimum: minimum allowed value (int, float, long only)
- @keyword maximum: maximum allowed value (int, float, long only)
- """
-
self.name = None
if type is None:
@@ -156,11 +149,11 @@ class Property(object):
self.default = self._get_default(default)
self._check_default()
- if not isinstance(nick, _basestring):
+ if not isinstance(nick, str):
raise TypeError("nick must be a string")
self.nick = nick
- if not isinstance(blurb, _basestring):
+ if not isinstance(blurb, str):
raise TypeError("blurb must be a string")
self.blurb = blurb
# Always clobber __doc__ with blurb even if blurb is empty because
@@ -204,14 +197,14 @@ class Property(object):
def __repr__(self):
return '<GObject Property %s (%s)>' % (
self.name or '(uninitialized)',
- _gobject.type_name(self.type))
+ self.type.name)
def __get__(self, instance, klass):
if instance is None:
return self
self._exc = None
- value = instance.get_property(self.name)
+ value = self.fget(instance)
if self._exc:
exc = self._exc
self._exc = None
@@ -257,11 +250,11 @@ class Property(object):
if type_ in self._type_from_pytype_lookup:
return self._type_from_pytype_lookup[type_]
elif (isinstance(type_, type) and
- issubclass(type_, (_gobject.GObject,
- _gobject.GEnum,
- _gobject.GFlags,
- _gobject.GBoxed,
- _gobject.GInterface))):
+ issubclass(type_, (_gi.GObject,
+ _gi.GEnum,
+ _gi.GFlags,
+ _gi.GBoxed,
+ _gi.GInterface))):
return type_.__gtype__
elif type_ in (TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR,
TYPE_INT, TYPE_UINT, TYPE_BOOLEAN, TYPE_LONG,
@@ -290,24 +283,24 @@ class Property(object):
elif ptype == TYPE_GTYPE:
if default is not None:
raise TypeError("GType types does not have default values")
- elif _gobject.type_is_a(ptype, TYPE_ENUM):
+ elif ptype.is_a(TYPE_ENUM):
if default is None:
raise TypeError("enum properties needs a default value")
- elif not _gobject.type_is_a(default, ptype):
+ elif not _gi.GType(default).is_a(ptype):
raise TypeError("enum value %s must be an instance of %r" %
(default, ptype))
- elif _gobject.type_is_a(ptype, TYPE_FLAGS):
- if not _gobject.type_is_a(default, ptype):
+ elif ptype.is_a(TYPE_FLAGS):
+ if not _gi.GType(default).is_a(ptype):
raise TypeError("flags value %s must be an instance of %r" %
(default, ptype))
- elif _gobject.type_is_a(ptype, TYPE_STRV) and default is not None:
+ elif ptype.is_a(TYPE_STRV) and default is not None:
if not isinstance(default, list):
raise TypeError("Strv value %s must be a list" % repr(default))
for val in default:
if type(val) not in (str, bytes):
raise TypeError("Strv value %s must contain only strings" % str(default))
- elif _gobject.type_is_a(ptype, TYPE_VARIANT) and default is not None:
- if not hasattr(default, '__gtype__') or not _gobject.type_is_a(default, TYPE_VARIANT):
+ elif ptype.is_a(TYPE_VARIANT) and default is not None:
+ if not hasattr(default, '__gtype__') or not _gi.GType(default).is_a(TYPE_VARIANT):
raise TypeError("variant value %s must be an instance of %r" %
(default, ptype))
@@ -398,9 +391,7 @@ def install_properties(cls):
def obj_get_property(self, pspec):
name = pspec.name.replace('-', '_')
- prop = getattr(cls, name, None)
- if prop:
- return prop.fget(self)
+ return getattr(self, name, None)
cls.do_get_property = obj_get_property
def obj_set_property(self, pspec, value):
diff --git a/gi/_gobject/signalhelper.py b/gi/_signalhelper.py
index b630158..8a1f0a4 100644
--- a/gi/_gobject/signalhelper.py
+++ b/gi/_signalhelper.py
@@ -2,7 +2,7 @@
# pygobject - Python bindings for the GObject library
# Copyright (C) 2012 Simon Feltman
#
-# gobject/signalhelper.py: GObject signal binding decorator object
+# gi/_signalhelper.py: GObject signal binding decorator object
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -15,52 +15,60 @@
# 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 Street, Fifth Floor, Boston, MA 02110-1301
-# USA
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
-import sys
-import inspect
-
-from . import _gobject
-
-# Callable went away in python 3.0 and came back in 3.2.
-# Use versioning to figure out when to define it, otherwise we have to deal with
-# the complexity of using __builtin__ or builtin between python versions to
-# check if callable exists which PyFlakes will also complain about.
-if (3, 0) <= sys.version_info < (3, 2):
- def callable(fn):
- return hasattr(fn, '__call__')
+from . import _gi
class Signal(str):
- """
- Object which gives a nice API for creating and binding signals.
-
- Example:
- class Spam(GObject.GObject):
- velocity = 0
-
- @GObject.Signal
- def pushed(self):
- self.velocity += 1
-
- @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST)
- def pulled(self):
- self.velocity -= 1
-
- stomped = GObject.Signal('stomped', arg_types=(int,))
-
- @GObject.Signal
- def annotated_signal(self, a:int, b:str):
- "Python3 annotation support for parameter types.
-
- def on_pushed(obj):
- print(obj)
-
- spam = Spam()
- spam.pushed.connect(on_pushed)
- spam.pushed.emit()
+ """Object which gives a nice API for creating and binding signals.
+
+ :param name:
+ Name of signal or callable closure when used as a decorator.
+ :type name: str or callable
+ :param callable func:
+ Callable closure method.
+ :param GObject.SignalFlags flags:
+ Flags specifying when to run closure.
+ :param type return_type:
+ Return type of the Signal.
+ :param list arg_types:
+ List of argument types specifying the signals function signature
+ :param str doc:
+ Documentation of signal object.
+ :param callable accumulator:
+ Accumulator method with the signature:
+ func(ihint, return_accu, handler_return, accu_data) -> boolean
+ :param object accu_data:
+ User data passed to the accumulator.
+
+ :Example:
+
+ .. code-block:: python
+
+ class Spam(GObject.Object):
+ velocity = 0
+
+ @GObject.Signal
+ def pushed(self):
+ self.velocity += 1
+
+ @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST)
+ def pulled(self):
+ self.velocity -= 1
+
+ stomped = GObject.Signal('stomped', arg_types=(int,))
+
+ @GObject.Signal
+ def annotated_signal(self, a:int, b:str):
+ "Python3 annotation support for parameter types.
+
+ def on_pushed(obj):
+ print(obj)
+
+ spam = Spam()
+ spam.pushed.connect(on_pushed)
+ spam.pushed.emit()
"""
class BoundSignal(str):
"""
@@ -83,12 +91,12 @@ class Signal(str):
return self.signal.func(self.gobj, *args, **kargs)
def connect(self, callback, *args, **kargs):
- """Same as GObject.GObject.connect except there is no need to specify
+ """Same as GObject.Object.connect except there is no need to specify
the signal name."""
return self.gobj.connect(self, callback, *args, **kargs)
def connect_detailed(self, callback, detail, *args, **kargs):
- """Same as GObject.GObject.connect except there is no need to specify
+ """Same as GObject.Object.connect except there is no need to specify
the signal name. In addition concats "::<detail>" to the signal name
when connecting; for use with notifications like "notify" when a property
changes.
@@ -96,11 +104,11 @@ class Signal(str):
return self.gobj.connect(self + '::' + detail, callback, *args, **kargs)
def disconnect(self, handler_id):
- """Same as GObject.GObject.disconnect."""
- self.instance.disconnect(handler_id)
+ """Same as GObject.Object.disconnect."""
+ self.gobj.disconnect(handler_id)
def emit(self, *args, **kargs):
- """Same as GObject.GObject.emit except there is no need to specify
+ """Same as GObject.Object.emit except there is no need to specify
the signal name."""
return self.gobj.emit(str(self), *args, **kargs)
@@ -109,32 +117,11 @@ class Signal(str):
name = name.__name__
return str.__new__(cls, name)
- def __init__(self, name='', func=None, flags=_gobject.SIGNAL_RUN_FIRST,
+ def __init__(self, name='', func=None, flags=_gi.SIGNAL_RUN_FIRST,
return_type=None, arg_types=None, doc='', accumulator=None, accu_data=None):
- """
- @param name: name of signal or closure method when used as direct decorator.
- @type name: string or callable
- @param func: closure method.
- @type func: callable
- @param flags: flags specifying when to run closure
- @type flags: GObject.SignalFlags
- @param return_type: return type
- @type return_type: type
- @param arg_types: list of argument types specifying the signals function signature
- @type arg_types: None
- @param doc: documentation of signal object
- @type doc: string
- @param accumulator: accumulator method with the signature:
- func(ihint, return_accu, handler_return, accu_data) -> boolean
- @type accumulator: function
- @param accu_data: user data passed to the accumulator
- @type accu_data: object
- """
- if func and not name:
- name = func.__name__
- elif callable(name):
+ if func is None and callable(name):
func = name
- name = func.__name__
+
if func and not doc:
doc = func.__doc__
@@ -165,7 +152,7 @@ class Signal(str):
# If obj is a GObject, than we call this signal as a closure otherwise
# it is used as a re-application of a decorator.
- if isinstance(obj, _gobject.GObject):
+ if isinstance(obj, _gi.GObject):
self.func(obj, *args, **kargs)
else:
# If self is already an allocated name, use it otherwise create a new named
@@ -181,8 +168,7 @@ class Signal(str):
def copy(self, newName=None):
"""Returns a renamed copy of the Signal."""
- if newName is None:
- newName = self.name
+
return type(self)(name=newName, func=self.func, flags=self.flags,
return_type=self.return_type, arg_types=self.arg_types,
doc=self.__doc__, accumulator=self.accumulator, accu_data=self.accu_data)
@@ -193,14 +179,17 @@ class Signal(str):
class SignalOverride(Signal):
- """Specialized sub-class of signal which can be used as a decorator for overriding
+ """Specialized sub-class of Signal which can be used as a decorator for overriding
existing signals on GObjects.
- Example:
- class MyWidget(Gtk.Widget):
- @GObject.SignalOverride
- def configure_event(self):
- pass
+ :Example:
+
+ .. code-block:: python
+
+ class MyWidget(Gtk.Widget):
+ @GObject.SignalOverride
+ def configure_event(self):
+ pass
"""
def get_signal_args(self):
"""Returns the string 'override'."""
@@ -217,6 +206,8 @@ def get_signal_annotations(func):
return_type = None
if hasattr(func, '__annotations__'):
+ # import inspect only when needed because it takes ~10 msec to load
+ import inspect
spec = inspect.getfullargspec(func)
arg_types = tuple(spec.annotations[arg] for arg in spec.args
if arg in spec.annotations)
diff --git a/gi/docstring.py b/gi/docstring.py
index 713bb6e..08bcef9 100644
--- a/gi/docstring.py
+++ b/gi/docstring.py
@@ -23,9 +23,11 @@
from ._gi import \
VFuncInfo, \
FunctionInfo, \
- DIRECTION_IN, \
- DIRECTION_OUT, \
- DIRECTION_INOUT
+ CallableInfo, \
+ ObjectInfo, \
+ StructInfo, \
+ Direction, \
+ TypeTag
#: Module storage for currently registered doc string generator function.
@@ -35,21 +37,26 @@ _generate_doc_string_func = None
def set_doc_string_generator(func):
"""Set doc string generator function
- :Parameters:
- func : callable
- Function which takes a GIInfoStruct and returns
- documentation for it.
+ :param callable func:
+ Callable which takes a GIInfoStruct and returns documentation for it.
"""
global _generate_doc_string_func
_generate_doc_string_func = func
def get_doc_string_generator():
+ """Returns the currently registered doc string generator."""
return _generate_doc_string_func
def generate_doc_string(info):
- """Generator a doc string given a GIInfoStruct
+ """Generate a doc string given a GIInfoStruct.
+
+ :param gi.types.BaseInfo info:
+ GI info instance to generate documentation for.
+ :returns:
+ Generated documentation as a string.
+ :rtype: str
This passes the info struct to the currently registered doc string
generator and returns the result.
@@ -57,50 +64,142 @@ def generate_doc_string(info):
return _generate_doc_string_func(info)
-def split_function_info_args(info):
- """Split a functions args into a tuple of two lists.
-
- Note that args marked as DIRECTION_INOUT will be in both lists.
-
- :Returns:
- Tuple of (in_args, out_args)
- """
- in_args = []
- out_args = []
- for arg in info.get_arguments():
- direction = arg.get_direction()
- if direction in (DIRECTION_IN, DIRECTION_INOUT):
- in_args.append(arg)
- if direction in (DIRECTION_OUT, DIRECTION_INOUT):
- out_args.append(arg)
- return (in_args, out_args)
-
-
-def _generate_callable_info_function_signature(info):
- """Default doc string generator"""
- in_args, out_args = split_function_info_args(info)
+_type_tag_to_py_type = {TypeTag.BOOLEAN: bool,
+ TypeTag.INT8: int,
+ TypeTag.UINT8: int,
+ TypeTag.INT16: int,
+ TypeTag.UINT16: int,
+ TypeTag.INT32: int,
+ TypeTag.UINT32: int,
+ TypeTag.INT64: int,
+ TypeTag.UINT64: int,
+ TypeTag.FLOAT: float,
+ TypeTag.DOUBLE: float,
+ TypeTag.GLIST: list,
+ TypeTag.GSLIST: list,
+ TypeTag.ARRAY: list,
+ TypeTag.GHASH: dict,
+ TypeTag.UTF8: str,
+ TypeTag.FILENAME: str,
+ TypeTag.UNICHAR: str,
+ TypeTag.INTERFACE: None,
+ TypeTag.GTYPE: None,
+ TypeTag.ERROR: None,
+ TypeTag.VOID: None,
+ }
+
+
+def _get_pytype_hint(gi_type):
+ type_tag = gi_type.get_tag()
+ py_type = _type_tag_to_py_type.get(type_tag, None)
+
+ if py_type and hasattr(py_type, '__name__'):
+ return py_type.__name__
+ elif type_tag == TypeTag.INTERFACE:
+ iface = gi_type.get_interface()
+
+ info_name = iface.get_name()
+ if not info_name:
+ return gi_type.get_tag_as_string()
+
+ return '%s.%s' % (iface.get_namespace(), info_name)
+
+ return gi_type.get_tag_as_string()
+
+
+def _generate_callable_info_doc(info):
in_args_strs = []
if isinstance(info, VFuncInfo):
in_args_strs = ['self']
elif isinstance(info, FunctionInfo):
if info.is_method():
in_args_strs = ['self']
- elif info.is_constructor():
- in_args_strs = ['cls']
- for arg in in_args:
- argstr = arg.get_name() + ':' + arg.get_pytype_hint()
- if arg.is_optional():
+ args = info.get_arguments()
+ hint_blacklist = ('void',)
+
+ # Build lists of indices prior to adding the docs because it is possible
+ # the index retrieved comes before input arguments being used.
+ ignore_indices = {info.get_return_type().get_array_length()}
+ user_data_indices = set()
+ for arg in args:
+ ignore_indices.add(arg.get_destroy())
+ ignore_indices.add(arg.get_type().get_array_length())
+ user_data_indices.add(arg.get_closure())
+
+ # Build input argument strings
+ for i, arg in enumerate(args):
+ if arg.get_direction() == Direction.OUT:
+ continue # skip exclusively output args
+ if i in ignore_indices:
+ continue
+ argstr = arg.get_name()
+ hint = _get_pytype_hint(arg.get_type())
+ if hint not in hint_blacklist:
+ argstr += ':' + hint
+ if arg.may_be_null() or i in user_data_indices:
+ # allow-none or user_data from a closure
+ argstr += '=None'
+ elif arg.is_optional():
argstr += '=<optional>'
in_args_strs.append(argstr)
in_args_str = ', '.join(in_args_strs)
- if out_args:
- out_args_str = ', '.join(arg.get_name() + ':' + arg.get_pytype_hint()
- for arg in out_args)
- return '%s(%s) -> %s' % (info.get_name(), in_args_str, out_args_str)
+ # Build return + output argument strings
+ out_args_strs = []
+ return_hint = _get_pytype_hint(info.get_return_type())
+ if not info.skip_return() and return_hint and return_hint not in hint_blacklist:
+ argstr = return_hint
+ if info.may_return_null():
+ argstr += ' or None'
+ out_args_strs.append(argstr)
+
+ for i, arg in enumerate(args):
+ if arg.get_direction() == Direction.IN:
+ continue # skip exclusively input args
+ if i in ignore_indices:
+ continue
+ argstr = arg.get_name()
+ hint = _get_pytype_hint(arg.get_type())
+ if hint not in hint_blacklist:
+ argstr += ':' + hint
+ out_args_strs.append(argstr)
+
+ if out_args_strs:
+ return '%s(%s) -> %s' % (info.__name__, in_args_str, ', '.join(out_args_strs))
+ else:
+ return '%s(%s)' % (info.__name__, in_args_str)
+
+
+def _generate_class_info_doc(info):
+ header = '\n:Constructors:\n\n::\n\n' # start with \n to avoid auto indent of other lines
+ doc = ''
+
+ if isinstance(info, StructInfo):
+ # Don't show default constructor for disguised (0 length) structs
+ if info.get_size() > 0:
+ doc += ' ' + info.get_name() + '()\n'
else:
- return '%s(%s)' % (info.get_name(), in_args_str)
+ doc += ' ' + info.get_name() + '(**properties)\n'
+
+ for method_info in info.get_methods():
+ if method_info.is_constructor():
+ doc += ' ' + _generate_callable_info_doc(method_info) + '\n'
+
+ if doc:
+ return header + doc
+ else:
+ return ''
+
+
+def _generate_doc_dispatch(info):
+ if isinstance(info, (ObjectInfo, StructInfo)):
+ return _generate_class_info_doc(info)
+
+ elif isinstance(info, CallableInfo):
+ return _generate_callable_info_doc(info)
+
+ return ''
-set_doc_string_generator(_generate_callable_info_function_signature)
+set_doc_string_generator(_generate_doc_dispatch)
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 12dfb36..9bc86be 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -21,14 +21,1469 @@
* USA
*/
-#include "pygi-private.h"
-#include "pygi.h"
-#include "pyglib.h"
+#include <Python.h>
+#include <glib-object.h>
+
+#include "config.h"
+#include "pyginterface.h"
+#include "pygi-repository.h"
+#include "pygi-type.h"
+#include "pygenum.h"
+#include "pygboxed.h"
+#include "pygflags.h"
+#include "pygi-error.h"
+#include "pygi-foreign.h"
+#include "pygi-resulttuple.h"
+#include "pygi-source.h"
+#include "pygi-ccallback.h"
+#include "pygi-closure.h"
+#include "pygi-type.h"
+#include "pygi-boxed.h"
+#include "pygi-info.h"
+#include "pygi-struct.h"
+#include "pygobject-object.h"
+#include "pygoptioncontext.h"
+#include "pygoptiongroup.h"
+#include "pygspawn.h"
+#include "pygparamspec.h"
+#include "pygpointer.h"
+#include "pygobject-internal.h"
+#include "pygi-value.h"
+#include "pygi-property.h"
+#include "pygi-util.h"
+#include "gimodule.h"
+#include "pygi-basictype.h"
+
+PyObject *PyGIWarning;
+PyObject *PyGIDeprecationWarning;
+PyObject *_PyGIDefaultArgPlaceholder;
-#include <pygobject.h>
-#include <pyglib-python-compat.h>
+/* Returns a new flag/enum type or %NULL */
+static PyObject *
+flags_enum_from_gtype (GType g_type,
+ PyObject * (add_func) (PyObject *, const char *,
+ const char *, GType))
+{
+ PyObject *new_type;
+ GIRepository *repository;
+ GIBaseInfo *info;
+ const gchar *type_name;
-PyObject *PyGIDeprecationWarning;
+ repository = g_irepository_get_default ();
+ info = g_irepository_find_by_gtype (repository, g_type);
+ if (info != NULL) {
+ type_name = g_base_info_get_name (info);
+ new_type = add_func (NULL, type_name, NULL, g_type);
+ g_base_info_unref (info);
+ } else {
+ type_name = g_type_name (g_type);
+ new_type = add_func (NULL, type_name, NULL, g_type);
+ }
+
+ return new_type;
+}
+
+static void pyg_flags_add_constants(PyObject *module, GType flags_type,
+ const gchar *strip_prefix);
+
+/**
+ * pyg_enum_add_constants:
+ * @module: a Python module
+ * @enum_type: the GType of the enumeration.
+ * @strip_prefix: the prefix to strip from the constant names.
+ *
+ * Adds constants to the given Python module for each value name of
+ * the enumeration. A prefix will be stripped from each enum name.
+ */
+static void
+pyg_enum_add_constants(PyObject *module, GType enum_type,
+ const gchar *strip_prefix)
+{
+ GEnumClass *eclass;
+ guint i;
+
+ if (!G_TYPE_IS_ENUM(enum_type)) {
+ if (G_TYPE_IS_FLAGS(enum_type)) /* See bug #136204 */
+ pyg_flags_add_constants(module, enum_type, strip_prefix);
+ else
+ g_warning("`%s' is not an enum type", g_type_name(enum_type));
+ return;
+ }
+ g_return_if_fail (strip_prefix != NULL);
+
+ eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
+
+ for (i = 0; i < eclass->n_values; i++) {
+ const gchar *name = eclass->values[i].value_name;
+ gint value = eclass->values[i].value;
+
+ PyModule_AddIntConstant(module,
+ (char*) pyg_constant_strip_prefix(name, strip_prefix),
+ (long) value);
+ }
+
+ g_type_class_unref(eclass);
+}
+
+/**
+ * pyg_flags_add_constants:
+ * @module: a Python module
+ * @flags_type: the GType of the flags type.
+ * @strip_prefix: the prefix to strip from the constant names.
+ *
+ * Adds constants to the given Python module for each value name of
+ * the flags set. A prefix will be stripped from each flag name.
+ */
+static void
+pyg_flags_add_constants(PyObject *module, GType flags_type,
+ const gchar *strip_prefix)
+{
+ GFlagsClass *fclass;
+ guint i;
+
+ if (!G_TYPE_IS_FLAGS(flags_type)) {
+ if (G_TYPE_IS_ENUM(flags_type)) /* See bug #136204 */
+ pyg_enum_add_constants(module, flags_type, strip_prefix);
+ else
+ g_warning("`%s' is not an flags type", g_type_name(flags_type));
+ return;
+ }
+ g_return_if_fail (strip_prefix != NULL);
+
+ fclass = G_FLAGS_CLASS(g_type_class_ref(flags_type));
+
+ for (i = 0; i < fclass->n_values; i++) {
+ const gchar *name = fclass->values[i].value_name;
+ guint value = fclass->values[i].value;
+
+ PyModule_AddIntConstant(module,
+ (char*) pyg_constant_strip_prefix(name, strip_prefix),
+ (long) value);
+ }
+
+ g_type_class_unref(fclass);
+}
+
+/**
+ * pyg_set_thread_block_funcs:
+ * Deprecated, only available for ABI compatibility.
+ */
+static void
+_pyg_set_thread_block_funcs (PyGThreadBlockFunc block_threads_func,
+ PyGThreadBlockFunc unblock_threads_func)
+{
+ PyGILState_STATE state = PyGILState_Ensure ();
+ PyErr_Warn (PyExc_DeprecationWarning,
+ "Using pyg_set_thread_block_funcs is not longer needed. "
+ "PyGObject always uses Py_BLOCK/UNBLOCK_THREADS.");
+ PyGILState_Release (state);
+}
+
+static GParamSpec *
+create_property (const gchar *prop_name,
+ GType prop_type,
+ const gchar *nick,
+ const gchar *blurb,
+ PyObject *args,
+ GParamFlags flags)
+{
+ GParamSpec *pspec = NULL;
+
+ switch (G_TYPE_FUNDAMENTAL(prop_type)) {
+ case G_TYPE_CHAR:
+ {
+ gchar minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_char (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_UCHAR:
+ {
+ gchar minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "ccc", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_uchar (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_BOOLEAN:
+ {
+ gboolean default_value;
+
+ if (!PyArg_ParseTuple(args, "i", &default_value))
+ return NULL;
+ pspec = g_param_spec_boolean (prop_name, nick, blurb,
+ default_value, flags);
+ }
+ break;
+ case G_TYPE_INT:
+ {
+ gint minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "iii", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_int (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_UINT:
+ {
+ guint minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "III", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_uint (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_LONG:
+ {
+ glong minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "lll", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_long (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_ULONG:
+ {
+ gulong minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "kkk", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_ulong (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_INT64:
+ {
+ gint64 minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "LLL", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_int64 (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_UINT64:
+ {
+ guint64 minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "KKK", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_uint64 (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_ENUM:
+ {
+ gint default_value;
+ PyObject *pydefault;
+
+ if (!PyArg_ParseTuple(args, "O", &pydefault))
+ return NULL;
+
+ if (pyg_enum_get_value(prop_type, pydefault,
+ (gint *)&default_value))
+ return NULL;
+
+ pspec = g_param_spec_enum (prop_name, nick, blurb,
+ prop_type, default_value, flags);
+ }
+ break;
+ case G_TYPE_FLAGS:
+ {
+ guint default_value;
+ PyObject *pydefault;
+
+ if (!PyArg_ParseTuple(args, "O", &pydefault))
+ return NULL;
+
+ if (pyg_flags_get_value(prop_type, pydefault,
+ &default_value))
+ return NULL;
+
+ pspec = g_param_spec_flags (prop_name, nick, blurb,
+ prop_type, default_value, flags);
+ }
+ break;
+ case G_TYPE_FLOAT:
+ {
+ gfloat minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "fff", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_float (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_DOUBLE:
+ {
+ gdouble minimum, maximum, default_value;
+
+ if (!PyArg_ParseTuple(args, "ddd", &minimum, &maximum,
+ &default_value))
+ return NULL;
+ pspec = g_param_spec_double (prop_name, nick, blurb, minimum,
+ maximum, default_value, flags);
+ }
+ break;
+ case G_TYPE_STRING:
+ {
+ const gchar *default_value;
+
+ if (!PyArg_ParseTuple(args, "z", &default_value))
+ return NULL;
+ pspec = g_param_spec_string (prop_name, nick, blurb,
+ default_value, flags);
+ }
+ break;
+ case G_TYPE_PARAM:
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ pspec = g_param_spec_param (prop_name, nick, blurb, prop_type, flags);
+ break;
+ case G_TYPE_BOXED:
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ pspec = g_param_spec_boxed (prop_name, nick, blurb, prop_type, flags);
+ break;
+ case G_TYPE_POINTER:
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (prop_type == G_TYPE_GTYPE)
+ pspec = g_param_spec_gtype (prop_name, nick, blurb, G_TYPE_NONE, flags);
+ else
+ pspec = g_param_spec_pointer (prop_name, nick, blurb, flags);
+ break;
+ case G_TYPE_OBJECT:
+ case G_TYPE_INTERFACE:
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ pspec = g_param_spec_object (prop_name, nick, blurb, prop_type, flags);
+ break;
+ case G_TYPE_VARIANT:
+ {
+ PyObject *pydefault;
+ GVariant *default_value = NULL;
+
+ if (!PyArg_ParseTuple(args, "O", &pydefault))
+ return NULL;
+ if (pydefault != Py_None)
+ default_value = pyg_boxed_get (pydefault, GVariant);
+ pspec = g_param_spec_variant (prop_name, nick, blurb, G_VARIANT_TYPE_ANY, default_value, flags);
+ }
+ break;
+ default:
+ /* unhandled pspec type ... */
+ break;
+ }
+
+ if (!pspec) {
+ char buf[128];
+
+ g_snprintf(buf, sizeof(buf), "could not create param spec for type %s",
+ g_type_name(prop_type));
+ PyErr_SetString(PyExc_TypeError, buf);
+ return NULL;
+ }
+
+ return pspec;
+}
+
+static GParamSpec *
+pyg_param_spec_from_object (PyObject *tuple)
+{
+ Py_ssize_t val_length;
+ const gchar *prop_name;
+ GType prop_type;
+ const gchar *nick, *blurb;
+ PyObject *slice, *item, *py_prop_type;
+ GParamSpec *pspec;
+ gint intvalue;
+
+ val_length = PyTuple_Size(tuple);
+ if (val_length < 4) {
+ PyErr_SetString(PyExc_TypeError,
+ "paramspec tuples must be at least 4 elements long");
+ return NULL;
+ }
+
+ slice = PySequence_GetSlice(tuple, 0, 4);
+ if (!slice) {
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(slice, "sOzz", &prop_name, &py_prop_type, &nick, &blurb)) {
+ Py_DECREF(slice);
+ return NULL;
+ }
+
+ Py_DECREF(slice);
+
+ prop_type = pyg_type_from_object(py_prop_type);
+ if (!prop_type) {
+ return NULL;
+ }
+
+ item = PyTuple_GetItem(tuple, val_length-1);
+ if (!PyLong_Check (item)) {
+ PyErr_SetString(PyExc_TypeError,
+ "last element in tuple must be an int");
+ return NULL;
+ }
+
+ if (!pygi_gint_from_py (item, &intvalue))
+ return NULL;
+
+ /* slice is the extra items in the tuple */
+ slice = PySequence_GetSlice(tuple, 4, val_length-1);
+ pspec = create_property(prop_name, prop_type,
+ nick, blurb, slice,
+ intvalue);
+
+ return pspec;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+/**
+ * pyg_parse_constructor_args: helper function for PyGObject constructors
+ * @obj_type: GType of the GObject, for parameter introspection
+ * @arg_names: %NULL-terminated array of constructor argument names
+ * @prop_names: %NULL-terminated array of property names, with direct
+ * correspondence to @arg_names
+ * @params: GParameter array where parameters will be placed; length
+ * of this array must be at least equal to the number of
+ * arguments/properties
+ * @nparams: output parameter to contain actual number of arguments found
+ * @py_args: array of PyObject* containing the actual constructor arguments
+ *
+ * Parses an array of PyObject's and creates a GParameter array
+ *
+ * Return value: %TRUE if all is successful, otherwise %FALSE and
+ * python exception set.
+ **/
+static gboolean
+pyg_parse_constructor_args(GType obj_type,
+ char **arg_names,
+ char **prop_names,
+ GParameter *params,
+ guint *nparams,
+ PyObject **py_args)
+{
+ guint arg_i, param_i;
+ GObjectClass *oclass;
+
+ oclass = g_type_class_ref(obj_type);
+ g_return_val_if_fail(oclass, FALSE);
+
+ for (param_i = arg_i = 0; arg_names[arg_i]; ++arg_i) {
+ GParamSpec *spec;
+ if (!py_args[arg_i])
+ continue;
+ spec = g_object_class_find_property(oclass, prop_names[arg_i]);
+ params[param_i].name = prop_names[arg_i];
+ g_value_init(&params[param_i].value, spec->value_type);
+ if (pyg_value_from_pyobject(&params[param_i].value, py_args[arg_i]) == -1) {
+ guint i;
+ PyErr_Format(PyExc_TypeError, "could not convert parameter '%s' of type '%s'",
+ arg_names[arg_i], g_type_name(spec->value_type));
+ g_type_class_unref(oclass);
+ for (i = 0; i < param_i; ++i)
+ g_value_unset(&params[i].value);
+ return FALSE;
+ }
+ ++param_i;
+ }
+ g_type_class_unref(oclass);
+ *nparams = param_i;
+ return TRUE;
+}
+
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+/* Only for backwards compatibility */
+static int
+pygobject_enable_threads(void)
+{
+ return 0;
+}
+
+static int
+pygobject_gil_state_ensure (void)
+{
+ return PyGILState_Ensure ();
+}
+
+static void
+pygobject_gil_state_release (int flag)
+{
+ PyGILState_Release(flag);
+}
+
+static void
+pyg_register_class_init(GType gtype, PyGClassInitFunc class_init)
+{
+ GSList *list;
+
+ list = g_type_get_qdata(gtype, pygobject_class_init_key);
+ list = g_slist_prepend(list, class_init);
+ g_type_set_qdata(gtype, pygobject_class_init_key, list);
+}
+
+static gboolean
+add_properties (GObjectClass *klass, PyObject *properties)
+{
+ gboolean ret = TRUE;
+ Py_ssize_t pos = 0;
+ PyObject *key, *value;
+
+ while (PyDict_Next(properties, &pos, &key, &value)) {
+ const gchar *prop_name;
+ GType prop_type;
+ const gchar *nick, *blurb;
+ GParamFlags flags;
+ Py_ssize_t val_length;
+ PyObject *slice, *item, *py_prop_type;
+ GParamSpec *pspec;
+
+ /* values are of format (type,nick,blurb, type_specific_args, flags) */
+
+ if (!PyUnicode_Check(key)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gproperties__ keys must be strings");
+ ret = FALSE;
+ break;
+ }
+ prop_name = PyUnicode_AsUTF8 (key);
+
+ if (!PyTuple_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gproperties__ values must be tuples");
+ ret = FALSE;
+ break;
+ }
+ val_length = PyTuple_Size(value);
+ if (val_length < 4) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gproperties__ values must be at least 4 elements long");
+ ret = FALSE;
+ break;
+ }
+
+ slice = PySequence_GetSlice(value, 0, 3);
+ if (!slice) {
+ ret = FALSE;
+ break;
+ }
+ if (!PyArg_ParseTuple(slice, "Ozz", &py_prop_type, &nick, &blurb)) {
+ Py_DECREF(slice);
+ ret = FALSE;
+ break;
+ }
+ Py_DECREF(slice);
+ prop_type = pyg_type_from_object(py_prop_type);
+ if (!prop_type) {
+ ret = FALSE;
+ break;
+ }
+ item = PyTuple_GetItem(value, val_length-1);
+ if (!PyLong_Check (item)) {
+ PyErr_SetString(PyExc_TypeError,
+ "last element in __gproperties__ value tuple must be an int");
+ ret = FALSE;
+ break;
+ }
+ if (!pygi_gint_from_py (item, &flags)) {
+ ret = FALSE;
+ break;
+ }
+
+ /* slice is the extra items in the tuple */
+ slice = PySequence_GetSlice(value, 3, val_length-1);
+ pspec = create_property(prop_name, prop_type, nick, blurb,
+ slice, flags);
+ Py_DECREF(slice);
+
+ if (pspec) {
+ g_object_class_install_property(klass, 1, pspec);
+ } else {
+ PyObject *type, *pvalue, *traceback;
+ ret = FALSE;
+ PyErr_Fetch(&type, &pvalue, &traceback);
+ if (PyUnicode_Check(pvalue)) {
+ char msg[256];
+ g_snprintf(msg, 256,
+ "%s (while registering property '%s' for GType '%s')",
+ PyUnicode_AsUTF8 (pvalue),
+ prop_name, G_OBJECT_CLASS_NAME(klass));
+ Py_DECREF(pvalue);
+ value = PyUnicode_FromString (msg);
+ }
+ PyErr_Restore(type, pvalue, traceback);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static gboolean
+override_signal(GType instance_type, const gchar *signal_name)
+{
+ guint signal_id;
+
+ signal_id = g_signal_lookup(signal_name, instance_type);
+ if (!signal_id) {
+ gchar buf[128];
+
+ g_snprintf(buf, sizeof(buf), "could not look up %s", signal_name);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return FALSE;
+ }
+ g_signal_override_class_closure(signal_id, instance_type,
+ pyg_signal_class_closure_get());
+ return TRUE;
+}
+
+typedef struct _PyGSignalAccumulatorData {
+ PyObject *callable;
+ PyObject *user_data;
+} PyGSignalAccumulatorData;
+
+
+static gboolean
+_pyg_signal_accumulator(GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer _data)
+{
+ PyObject *py_ihint, *py_return_accu, *py_handler_return, *py_detail;
+ PyObject *py_retval;
+ gboolean retval = FALSE;
+ PyGSignalAccumulatorData *data = _data;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+ if (ihint->detail)
+ py_detail = PyUnicode_FromString (g_quark_to_string(ihint->detail));
+ else {
+ Py_INCREF(Py_None);
+ py_detail = Py_None;
+ }
+
+ py_ihint = Py_BuildValue("lNi", (long int) ihint->signal_id,
+ py_detail, ihint->run_type);
+ py_handler_return = pyg_value_as_pyobject(handler_return, TRUE);
+ py_return_accu = pyg_value_as_pyobject(return_accu, FALSE);
+ if (data->user_data)
+ py_retval = PyObject_CallFunction(data->callable, "NNNO", py_ihint,
+ py_return_accu, py_handler_return,
+ data->user_data);
+ else
+ py_retval = PyObject_CallFunction(data->callable, "NNN", py_ihint,
+ py_return_accu, py_handler_return);
+ if (!py_retval)
+ PyErr_Print();
+ else {
+ if (!PyTuple_Check(py_retval) || PyTuple_Size(py_retval) != 2) {
+ PyErr_SetString(PyExc_TypeError, "accumulator function must return"
+ " a (bool, object) tuple");
+ PyErr_Print();
+ } else {
+ retval = PyObject_IsTrue(PyTuple_GET_ITEM(py_retval, 0));
+ if (pyg_value_from_pyobject(return_accu, PyTuple_GET_ITEM(py_retval, 1))) {
+ PyErr_Print();
+ }
+ }
+ Py_DECREF(py_retval);
+ }
+ PyGILState_Release(state);
+ return retval;
+}
+
+static gboolean
+create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple)
+{
+ GSignalFlags signal_flags;
+ PyObject *py_return_type, *py_param_types;
+ GType return_type;
+ guint n_params, i;
+ Py_ssize_t py_n_params;
+ GType *param_types;
+ guint signal_id;
+ GSignalAccumulator accumulator = NULL;
+ PyGSignalAccumulatorData *accum_data = NULL;
+ PyObject *py_accum = NULL, *py_accum_data = NULL;
+
+ if (!PyArg_ParseTuple(tuple, "iOO|OO", &signal_flags, &py_return_type,
+ &py_param_types, &py_accum, &py_accum_data))
+ {
+ gchar buf[128];
+
+ PyErr_Clear();
+ g_snprintf(buf, sizeof(buf),
+ "value for __gsignals__['%s'] not in correct format", signal_name);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return FALSE;
+ }
+
+ if (py_accum && py_accum != Py_None && !PyCallable_Check(py_accum))
+ {
+ gchar buf[128];
+
+ g_snprintf(buf, sizeof(buf),
+ "accumulator for __gsignals__['%s'] must be callable", signal_name);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return FALSE;
+ }
+
+ return_type = pyg_type_from_object(py_return_type);
+ if (!return_type)
+ return FALSE;
+ if (!PySequence_Check(py_param_types)) {
+ gchar buf[128];
+
+ g_snprintf(buf, sizeof(buf),
+ "third element of __gsignals__['%s'] tuple must be a sequence", signal_name);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return FALSE;
+ }
+ py_n_params = PySequence_Length(py_param_types);
+ if (py_n_params < 0)
+ return FALSE;
+
+ if (!pygi_guint_from_pyssize (py_n_params, &n_params))
+ return FALSE;
+
+ param_types = g_new(GType, n_params);
+ for (i = 0; i < n_params; i++) {
+ PyObject *item = PySequence_GetItem(py_param_types, i);
+
+ param_types[i] = pyg_type_from_object(item);
+ if (param_types[i] == 0) {
+ Py_DECREF(item);
+ g_free(param_types);
+ return FALSE;
+ }
+ Py_DECREF(item);
+ }
+
+ if (py_accum != NULL && py_accum != Py_None) {
+ accum_data = g_new(PyGSignalAccumulatorData, 1);
+ accum_data->callable = py_accum;
+ Py_INCREF(py_accum);
+ accum_data->user_data = py_accum_data;
+ Py_XINCREF(py_accum_data);
+ accumulator = _pyg_signal_accumulator;
+ }
+
+ signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
+ pyg_signal_class_closure_get(),
+ accumulator, accum_data,
+ gi_cclosure_marshal_generic,
+ return_type, n_params, param_types);
+ g_free(param_types);
+
+ if (signal_id == 0) {
+ gchar buf[128];
+
+ g_snprintf(buf, sizeof(buf), "could not create signal for %s",
+ signal_name);
+ PyErr_SetString(PyExc_RuntimeError, buf);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+static PyObject *
+add_signals (GObjectClass *klass, PyObject *signals)
+{
+ gboolean ret = TRUE;
+ Py_ssize_t pos = 0;
+ PyObject *key, *value, *overridden_signals = NULL;
+ GType instance_type = G_OBJECT_CLASS_TYPE (klass);
+
+ overridden_signals = PyDict_New();
+ while (PyDict_Next(signals, &pos, &key, &value)) {
+ const gchar *signal_name;
+ gchar *signal_name_canon, *c;
+
+ if (!PyUnicode_Check(key)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gsignals__ keys must be strings");
+ ret = FALSE;
+ break;
+ }
+ signal_name = PyUnicode_AsUTF8 (key);
+
+ if (value == Py_None ||
+ (PyUnicode_Check(value) &&
+ !strcmp(PyUnicode_AsUTF8 (value), "override")))
+ {
+ /* canonicalize signal name, replacing '-' with '_' */
+ signal_name_canon = g_strdup(signal_name);
+ for (c = signal_name_canon; *c; ++c)
+ if (*c == '-')
+ *c = '_';
+ if (PyDict_SetItemString(overridden_signals,
+ signal_name_canon, key)) {
+ g_free(signal_name_canon);
+ ret = FALSE;
+ break;
+ }
+ g_free(signal_name_canon);
+
+ ret = override_signal(instance_type, signal_name);
+ } else {
+ ret = create_signal(instance_type, signal_name, value);
+ }
+
+ if (!ret)
+ break;
+ }
+ if (ret)
+ return overridden_signals;
+ else {
+ Py_XDECREF(overridden_signals);
+ return NULL;
+ }
+}
+
+static void
+pyg_object_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ PyObject *object_wrapper, *retval;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+
+ object_wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
+
+ if (object_wrapper)
+ Py_INCREF (object_wrapper);
+ else
+ object_wrapper = pygobject_new(object);
+
+ if (object_wrapper == NULL) {
+ PyGILState_Release(state);
+ return;
+ }
+
+ retval = pygi_call_do_get_property (object_wrapper, pspec);
+ if (retval && pyg_value_from_pyobject (value, retval) < 0) {
+ PyErr_Print();
+ }
+ Py_DECREF(object_wrapper);
+ Py_XDECREF(retval);
+
+ PyGILState_Release(state);
+}
+
+static void
+pyg_object_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ PyObject *object_wrapper, *retval;
+ PyObject *py_pspec, *py_value;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+
+ object_wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
+
+ if (object_wrapper)
+ Py_INCREF (object_wrapper);
+ else
+ object_wrapper = pygobject_new(object);
+
+ if (object_wrapper == NULL) {
+ PyGILState_Release(state);
+ return;
+ }
+
+ py_pspec = pyg_param_spec_new(pspec);
+ py_value = pyg_value_as_pyobject (value, TRUE);
+
+ retval = PyObject_CallMethod(object_wrapper, "do_set_property",
+ "OO", py_pspec, py_value);
+ if (retval) {
+ Py_DECREF(retval);
+ } else {
+ PyErr_Print();
+ }
+
+ Py_DECREF(object_wrapper);
+ Py_DECREF(py_pspec);
+ Py_DECREF(py_value);
+
+ PyGILState_Release(state);
+}
+
+static void
+pyg_object_class_init(GObjectClass *class, PyObject *py_class)
+{
+ PyObject *gproperties, *gsignals, *overridden_signals;
+ PyObject *class_dict = ((PyTypeObject*) py_class)->tp_dict;
+
+ class->set_property = pyg_object_set_property;
+ class->get_property = pyg_object_get_property;
+
+ /* install signals */
+ /* we look this up in the instance dictionary, so we don't
+ * accidentally get a parent type's __gsignals__ attribute. */
+ gsignals = PyDict_GetItemString(class_dict, "__gsignals__");
+ if (gsignals) {
+ if (!PyDict_Check(gsignals)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gsignals__ attribute not a dict!");
+ return;
+ }
+ if (!(overridden_signals = add_signals(class, gsignals))) {
+ return;
+ }
+ if (PyDict_SetItemString(class_dict, "__gsignals__",
+ overridden_signals)) {
+ return;
+ }
+ Py_DECREF(overridden_signals);
+
+ PyDict_DelItemString(class_dict, "__gsignals__");
+ } else {
+ PyErr_Clear();
+ }
+
+ /* install properties */
+ /* we look this up in the instance dictionary, so we don't
+ * accidentally get a parent type's __gproperties__ attribute. */
+ gproperties = PyDict_GetItemString(class_dict, "__gproperties__");
+ if (gproperties) {
+ if (!PyDict_Check(gproperties)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__gproperties__ attribute not a dict!");
+ return;
+ }
+ if (!add_properties(class, gproperties)) {
+ return;
+ }
+ PyDict_DelItemString(class_dict, "__gproperties__");
+ /* Borrowed reference. Py_DECREF(gproperties); */
+ } else {
+ PyErr_Clear();
+ }
+}
+
+static GPrivate pygobject_construction_wrapper;
+
+static inline void
+pygobject_init_wrapper_set(PyObject *wrapper)
+{
+ g_private_set(&pygobject_construction_wrapper, wrapper);
+}
+
+static inline PyObject *
+pygobject_init_wrapper_get(void)
+{
+ return (PyObject *) g_private_get(&pygobject_construction_wrapper);
+}
+
+/**
+ * Like g_object_new_with_properties() but also works with older glib versions.
+ */
+GObject *
+pygobject_object_new_with_properties(GType object_type,
+ guint n_properties,
+ const char *names[],
+ const GValue values[])
+{
+ GObject *obj;
+
+#if GLIB_CHECK_VERSION(2, 54, 0)
+ obj = g_object_new_with_properties(object_type, n_properties, names, values);
+#else
+ {
+ GParameter *parameters;
+ uint i;
+
+ parameters = g_new(GParameter, n_properties);
+ for (i = 0; i < n_properties; i++) {
+ parameters[i].name = names[i];
+ parameters[i].value = values[i];
+ }
+ obj = g_object_newv(object_type, n_properties, parameters);
+ g_free(parameters);
+ }
+#endif
+
+ return obj;
+}
+
+int
+pygobject_constructv (PyGObject *self,
+ guint n_properties,
+ const char *names[],
+ const GValue values[])
+{
+ GObject *obj;
+
+ g_assert (self->obj == NULL);
+ pygobject_init_wrapper_set((PyObject *) self);
+
+ obj = pygobject_object_new_with_properties(pyg_type_from_object((PyObject *) self),
+ n_properties,
+ names,
+ values);
+
+ if (g_object_is_floating (obj))
+ self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
+ pygobject_sink (obj);
+
+ pygobject_init_wrapper_set(NULL);
+ self->obj = obj;
+ pygobject_register_wrapper((PyObject *) self);
+
+ return 0;
+}
+
+static void
+pygobject__g_instance_init(GTypeInstance *instance,
+ gpointer g_class)
+{
+ GObject *object;
+ PyObject *wrapper, *result;
+ PyGILState_STATE state;
+ gboolean needs_init = FALSE;
+
+ g_return_if_fail(G_IS_OBJECT(instance));
+
+ object = (GObject *) instance;
+
+ wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
+ if (wrapper == NULL) {
+ wrapper = pygobject_init_wrapper_get();
+ if (wrapper && ((PyGObject *) wrapper)->obj == NULL) {
+ ((PyGObject *) wrapper)->obj = object;
+ pygobject_register_wrapper(wrapper);
+ }
+ }
+ pygobject_init_wrapper_set(NULL);
+
+ state = PyGILState_Ensure();
+
+ if (wrapper == NULL) {
+ /* this looks like a python object created through
+ * g_object_new -> we have no python wrapper, so create it
+ * now */
+
+ if (g_object_is_floating (object)) {
+ g_object_ref (object);
+ wrapper = pygobject_new_full(object,
+ /*steal=*/ TRUE,
+ g_class);
+ g_object_force_floating (object);
+ } else {
+ wrapper = pygobject_new_full(object,
+ /*steal=*/ FALSE,
+ g_class);
+ }
+
+ /* float the wrapper ref here because we are going to orphan it
+ * so we don't destroy the wrapper. The next call to pygobject_new_full
+ * will take the ref */
+ pygobject_ref_float ((PyGObject *) wrapper);
+
+ needs_init = TRUE;
+ }
+
+ /* XXX: used for Gtk.Template */
+ if (PyObject_HasAttrString ((PyObject*) Py_TYPE (wrapper), "__dontuse_ginstance_init__")) {
+ result = PyObject_CallMethod (wrapper, "__dontuse_ginstance_init__", NULL);
+ if (result == NULL)
+ PyErr_Print ();
+ else
+ Py_DECREF (result);
+ }
+
+ if (needs_init) {
+ result = PyObject_CallMethod (wrapper, "__init__", NULL);
+ if (result == NULL)
+ PyErr_Print ();
+ else
+ Py_DECREF (result);
+ }
+
+ PyGILState_Release(state);
+}
+
+/* This implementation is bad, see bug 566571 for an example why.
+ * Instead of scanning explicitly declared bases for interfaces, we
+ * should automatically initialize all implemented interfaces to
+ * prevent bugs like that one. However, this will lead to
+ * performance degradation as each virtual method in derived classes
+ * will round-trip through do_*() stuff, *even* if it is not
+ * overriden. We need to teach codegen to retain parent method
+ * instead of setting virtual to *_proxy_do_*() if corresponding
+ * do_*() is not overriden. Ok, that was a messy explanation.
+ */
+static void
+pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
+ PyObject *bases,
+ GType *parent_interfaces, guint n_parent_interfaces)
+{
+ int i;
+
+ if (!bases) {
+ g_warning("type has no bases");
+ return;
+ }
+
+ for (i = 0; i < PyTuple_GET_SIZE(bases); ++i) {
+ PyObject *base = PyTuple_GET_ITEM(bases, i);
+ GType itype;
+ const GInterfaceInfo *iinfo;
+ GInterfaceInfo iinfo_copy;
+
+ /* 'base' can also be a PyClassObject, see bug #566571. */
+ if (!PyType_Check(base))
+ continue;
+
+ if (!PyType_IsSubtype((PyTypeObject*) base, &PyGInterface_Type))
+ continue;
+
+ itype = pyg_type_from_object(base);
+
+ /* Happens for _implementations_ of an interface. */
+ if (!G_TYPE_IS_INTERFACE(itype))
+ continue;
+
+ iinfo = pyg_lookup_interface_info(itype);
+ if (!iinfo) {
+ gchar *error;
+ error = g_strdup_printf("Interface type %s "
+ "has no Python implementation support",
+ ((PyTypeObject *) base)->tp_name);
+ PyErr_Warn(PyExc_RuntimeWarning, error);
+ g_free(error);
+ continue;
+ }
+
+ iinfo_copy = *iinfo;
+ iinfo_copy.interface_data = class;
+ g_type_add_interface_static(instance_type, itype, &iinfo_copy);
+ }
+}
+
+static int
+pyg_run_class_init(GType gtype, gpointer gclass, PyTypeObject *pyclass)
+{
+ GSList *list;
+ PyGClassInitFunc class_init;
+ GType parent_type;
+ int rv;
+
+ parent_type = g_type_parent(gtype);
+ if (parent_type) {
+ rv = pyg_run_class_init(parent_type, gclass, pyclass);
+ if (rv)
+ return rv;
+ }
+
+ list = g_type_get_qdata(gtype, pygobject_class_init_key);
+ for (; list; list = list->next) {
+ class_init = list->data;
+ rv = class_init(gclass, pyclass);
+ if (rv)
+ return rv;
+ }
+
+ return 0;
+}
+
+static char *
+get_type_name_for_class(PyTypeObject *class)
+{
+ gint i, name_serial;
+ char name_serial_str[16];
+ PyObject *module;
+ char *type_name = NULL;
+
+ /* make name for new GType */
+ name_serial = 1;
+ /* give up after 1000 tries, just in case.. */
+ while (name_serial < 1000)
+ {
+ g_free(type_name);
+ g_snprintf(name_serial_str, 16, "-v%i", name_serial);
+ module = PyObject_GetAttrString((PyObject *)class, "__module__");
+ if (module && PyUnicode_Check (module)) {
+ type_name = g_strconcat(PyUnicode_AsUTF8 (module), ".",
+ class->tp_name,
+ name_serial > 1 ? name_serial_str : NULL,
+ NULL);
+ Py_DECREF(module);
+ } else {
+ if (module)
+ Py_DECREF(module);
+ else
+ PyErr_Clear();
+ type_name = g_strconcat(class->tp_name,
+ name_serial > 1 ? name_serial_str : NULL,
+ NULL);
+ }
+ /* convert '.' in type name to '+', which isn't banned (grumble) */
+ for (i = 0; type_name[i] != '\0'; i++)
+ if (type_name[i] == '.')
+ type_name[i] = '+';
+ if (g_type_from_name(type_name) == 0)
+ break; /* we now have a unique name */
+ ++name_serial;
+ }
+
+ return type_name;
+}
+
+static int
+pyg_type_register(PyTypeObject *class, const char *type_name)
+{
+ PyObject *gtype;
+ GType parent_type, instance_type;
+ GType *parent_interfaces;
+ guint n_parent_interfaces;
+ GTypeQuery query;
+ gpointer gclass;
+ GTypeInfo type_info = {
+ 0, /* class_size */
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+
+ (GClassInitFunc) pyg_object_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+
+ 0, /* instance_size */
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pygobject__g_instance_init
+ };
+ gchar *new_type_name;
+
+ /* find the GType of the parent */
+ parent_type = pyg_type_from_object((PyObject *)class);
+ if (!parent_type)
+ return -1;
+
+ parent_interfaces = g_type_interfaces(parent_type, &n_parent_interfaces);
+
+ if (type_name)
+ /* care is taken below not to free this */
+ new_type_name = (gchar *) type_name;
+ else
+ new_type_name = get_type_name_for_class(class);
+
+ /* set class_data that will be passed to the class_init function. */
+ type_info.class_data = class;
+
+ /* fill in missing values of GTypeInfo struct */
+ g_type_query(parent_type, &query);
+ type_info.class_size = (guint16)query.class_size;
+ type_info.instance_size = (guint16)query.instance_size;
+
+ /* create new typecode */
+ instance_type = g_type_register_static(parent_type, new_type_name,
+ &type_info, 0);
+ if (instance_type == 0) {
+ PyErr_Format(PyExc_RuntimeError,
+ "could not create new GType: %s (subclass of %s)",
+ new_type_name,
+ g_type_name(parent_type));
+
+ if (type_name == NULL)
+ g_free(new_type_name);
+
+ return -1;
+ }
+
+ if (type_name == NULL)
+ g_free(new_type_name);
+
+ /* store pointer to the class with the GType */
+ Py_INCREF(class);
+ g_type_set_qdata(instance_type, pygobject_class_key,
+ class);
+
+ /* Mark this GType as a custom python type */
+ g_type_set_qdata(instance_type, pygobject_custom_key,
+ GINT_TO_POINTER (1));
+
+ /* set new value of __gtype__ on class */
+ gtype = pyg_type_wrapper_new(instance_type);
+ PyObject_SetAttrString((PyObject *)class, "__gtype__", gtype);
+ Py_DECREF(gtype);
+
+ /* if no __doc__, set it to the auto doc descriptor */
+ if (PyDict_GetItemString(class->tp_dict, "__doc__") == NULL) {
+ PyDict_SetItemString(class->tp_dict, "__doc__",
+ pyg_object_descr_doc_get());
+ }
+
+ /*
+ * Note, all interfaces need to be registered before the first
+ * g_type_class_ref(), see bug #686149.
+ *
+ * See also comment above pyg_type_add_interfaces().
+ */
+ pyg_type_add_interfaces(class, instance_type, class->tp_bases,
+ parent_interfaces, n_parent_interfaces);
+
+
+ gclass = g_type_class_ref(instance_type);
+ if (PyErr_Occurred() != NULL) {
+ g_type_class_unref(gclass);
+ g_free(parent_interfaces);
+ return -1;
+ }
+
+ if (pyg_run_class_init(instance_type, gclass, class)) {
+ g_type_class_unref(gclass);
+ g_free(parent_interfaces);
+ return -1;
+ }
+ g_type_class_unref(gclass);
+ g_free(parent_interfaces);
+
+ if (PyErr_Occurred() != NULL)
+ return -1;
+ return 0;
+}
+
+static PyObject *
+_wrap_pyg_type_register(PyObject *self, PyObject *args)
+{
+ PyTypeObject *class;
+ char *type_name = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!|z:gobject.type_register",
+ &PyType_Type, &class, &type_name))
+ return NULL;
+ if (!PyType_IsSubtype(class, &PyGObject_Type)) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument must be a GObject subclass");
+ return NULL;
+ }
+
+ /* Check if type already registered */
+ if (pyg_type_from_object((PyObject *) class) ==
+ pyg_type_from_object((PyObject *) class->tp_base))
+ {
+ if (pyg_type_register(class, type_name))
+ return NULL;
+ }
+
+ Py_INCREF(class);
+ return (PyObject *) class;
+}
+
+static GHashTable *log_handlers = NULL;
+static gboolean log_handlers_disabled = FALSE;
+
+static void
+remove_handler(gpointer domain,
+ gpointer handler,
+ gpointer unused)
+{
+ g_log_remove_handler(domain, GPOINTER_TO_UINT(handler));
+}
+
+static void
+_log_func(const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ if (G_LIKELY(Py_IsInitialized()))
+ {
+ PyGILState_STATE state;
+ PyObject* warning = user_data;
+
+ state = PyGILState_Ensure();
+ PyErr_Warn(warning, (char *) message);
+ PyGILState_Release(state);
+ } else
+ g_log_default_handler(log_domain, log_level, message, user_data);
+}
+
+static void
+add_warning_redirection(const char *domain,
+ PyObject *warning)
+{
+ g_return_if_fail(domain != NULL);
+ g_return_if_fail(warning != NULL);
+
+ if (!log_handlers_disabled)
+ {
+ guint handler;
+ gpointer old_handler;
+
+ if (!log_handlers)
+ log_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+ if ((old_handler = g_hash_table_lookup(log_handlers, domain)))
+ g_log_remove_handler(domain, GPOINTER_TO_UINT(old_handler));
+
+ handler = g_log_set_handler(domain, G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING,
+ _log_func, warning);
+ g_hash_table_insert(log_handlers, g_strdup(domain), GUINT_TO_POINTER(handler));
+ }
+}
+
+static void
+disable_warning_redirections(void)
+{
+ log_handlers_disabled = TRUE;
+
+ if (log_handlers)
+ {
+ g_hash_table_foreach(log_handlers, remove_handler, NULL);
+ g_hash_table_destroy(log_handlers);
+ log_handlers = NULL;
+ }
+}
+
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+static int
+pygi_register_warnings(PyObject *d)
+{
+ PyObject *warning;
+
+ warning = PyErr_NewException("gobject.Warning", PyExc_Warning, NULL);
+ if (warning == NULL)
+ return -1;
+ PyDict_SetItemString(d, "Warning", warning);
+ add_warning_redirection("GLib", warning);
+ add_warning_redirection("GLib-GObject", warning);
+ add_warning_redirection("GThread", warning);
+
+ return 0;
+}
static PyObject *
_wrap_pyg_enum_add (PyObject *self,
@@ -50,7 +1505,7 @@ _wrap_pyg_enum_add (PyObject *self,
return NULL;
}
- return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type);
+ return flags_enum_from_gtype (g_type, pyg_enum_add);
}
static PyObject *
@@ -102,7 +1557,7 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
enum_value = &g_enum_values[i];
enum_value->value_nick = g_strdup (name);
- enum_value->value = g_value_info_get_value (value_info);
+ enum_value->value = (gint)g_value_info_get_value (value_info);
if (c_identifier == NULL) {
enum_value->value_name = enum_value->value_nick;
@@ -146,7 +1601,7 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
}
g_free (full_name);
- return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type);
+ return pyg_enum_add (NULL, type_name, NULL, g_type);
}
static PyObject *
@@ -169,7 +1624,7 @@ _wrap_pyg_flags_add (PyObject *self,
return NULL;
}
- return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type);
+ return flags_enum_from_gtype (g_type, pyg_flags_add);
}
static PyObject *
@@ -221,7 +1676,7 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
flags_value = &g_flags_values[i];
flags_value->value_nick = g_strdup (name);
- flags_value->value = g_value_info_get_value (value_info);
+ flags_value->value = (guint)g_value_info_get_value (value_info);
if (c_identifier == NULL) {
flags_value->value_name = flags_value->value_nick;
@@ -265,13 +1720,13 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
}
g_free (full_name);
- return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type);
+ return pyg_flags_add (NULL, type_name, NULL, g_type);
}
static void
initialize_interface (GTypeInterface *iface, PyTypeObject *pytype)
{
- // pygobject prints a warning if interface_init is NULL
+ /* pygobject prints a warning if interface_init is NULL */
}
static PyObject *
@@ -296,6 +1751,7 @@ _wrap_pyg_register_interface_info (PyObject *self, PyObject *args)
info->interface_init = (GInterfaceInitFunc) initialize_interface;
pyg_register_interface_info (g_type, info);
+ g_free (info);
Py_RETURN_NONE;
}
@@ -308,11 +1764,11 @@ find_vfunc_info (GIBaseInfo *vfunc_info,
GIFieldInfo **field_info_ret)
{
GType ancestor_g_type = 0;
- int length, i;
GIBaseInfo *ancestor_info;
GIStructInfo *struct_info;
gpointer implementor_class = NULL;
gboolean is_interface = FALSE;
+ GIFieldInfo *field_info;
ancestor_info = g_base_info_get_container (vfunc_info);
is_interface = g_base_info_get_type (ancestor_info) == GI_INFO_TYPE_INTERFACE;
@@ -343,28 +1799,18 @@ find_vfunc_info (GIBaseInfo *vfunc_info,
*implementor_class_ret = implementor_class;
- length = g_struct_info_get_n_fields (struct_info);
- for (i = 0; i < length; i++) {
- GIFieldInfo *field_info;
+ field_info = g_struct_info_find_field (struct_info,
+ g_base_info_get_name ( (GIBaseInfo*) vfunc_info));
+ if (field_info != NULL) {
GITypeInfo *type_info;
- 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_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) {
- g_base_info_unref (type_info);
*field_info_ret = field_info;
- break;
+ } else {
+ g_base_info_unref (field_info);
}
-
g_base_info_unref (type_info);
- g_base_info_unref (field_info);
}
g_base_info_unref (struct_info);
@@ -382,6 +1828,7 @@ _wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args)
GIFieldInfo *field_info = NULL;
gpointer *method_ptr = NULL;
PyGICClosure *closure = NULL;
+ PyGIClosureCache *cache = NULL;
if (!PyArg_ParseTuple (args, "O!O!O:hook_up_vfunc_implementation",
&PyGIBaseInfo_Type, &py_info,
@@ -408,10 +1855,15 @@ _wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args)
offset = g_field_info_get_offset (field_info);
method_ptr = G_STRUCT_MEMBER_P (implementor_vtable, offset);
- closure = _pygi_make_native_closure ( (GICallableInfo*) callback_info,
+ cache = pygi_closure_cache_new (callback_info);
+ closure = _pygi_make_native_closure ( (GICallableInfo*) callback_info, cache,
GI_SCOPE_TYPE_NOTIFIED, py_function, NULL);
+#if GI_CHECK_VERSION (1, 72, 0)
+ *method_ptr = g_callable_info_get_closure_native_address (callback_info, closure->closure);
+#else
*method_ptr = closure->closure;
+#endif
g_base_info_unref (interface_info);
g_base_info_unref (type_info);
@@ -465,43 +1917,6 @@ _wrap_pyg_has_vfunc_implementation (PyObject *self, PyObject *args)
#endif
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 %" G_GSSIZE_FORMAT " 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;
@@ -513,19 +1928,13 @@ _wrap_pyg_variant_type_from_string (PyObject *self, PyObject *args)
return NULL;
}
- py_type = _pygi_type_import_by_name ("GLib", "VariantType");
+ py_type = pygi_type_import_by_name ("GLib", "VariantType");
- py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE, 0);
+ py_variant = pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE, 0);
return py_variant;
}
-static PyObject *
-_wrap_pyg_source_new (PyObject *self, PyObject *args)
-{
- return pyg_source_new ();
-}
-
#define CHUNK_SIZE 8192
static PyObject*
@@ -545,50 +1954,50 @@ pyg_channel_read(PyObject* self, PyObject *args, PyObject *kwargs)
PyErr_SetString(PyExc_TypeError, "first argument is not a GLib.IOChannel");
return NULL;
}
-
+
if (max_count == 0)
- return PYGLIB_PyBytes_FromString("");
+ return PyBytes_FromString ("");
iochannel = pyg_boxed_get (py_iochannel, GIOChannel);
while (status == G_IO_STATUS_NORMAL
- && (max_count == -1 || total_read < max_count)) {
+ && (max_count == -1 || total_read < (gsize)max_count)) {
gsize single_read;
char* buf;
gsize buf_size;
-
- if (max_count == -1)
+
+ if (max_count == -1)
buf_size = CHUNK_SIZE;
else {
buf_size = max_count - total_read;
if (buf_size > CHUNK_SIZE)
buf_size = CHUNK_SIZE;
}
-
+
if ( ret_obj == NULL ) {
- ret_obj = PYGLIB_PyBytes_FromStringAndSize((char *)NULL, buf_size);
+ ret_obj = PyBytes_FromStringAndSize ((char *)NULL, buf_size);
if (ret_obj == NULL)
goto failure;
}
- else if (buf_size + total_read > PYGLIB_PyBytes_Size(ret_obj)) {
- if (PYGLIB_PyBytes_Resize(&ret_obj, buf_size + total_read) == -1)
+ else if (buf_size + total_read > (gsize)PyBytes_Size (ret_obj)) {
+ if (_PyBytes_Resize (&ret_obj, buf_size + total_read) == -1)
goto failure;
}
-
- buf = PYGLIB_PyBytes_AsString(ret_obj) + total_read;
+
+ buf = PyBytes_AsString (ret_obj) + total_read;
Py_BEGIN_ALLOW_THREADS;
status = g_io_channel_read_chars (iochannel, buf, buf_size, &single_read, &error);
Py_END_ALLOW_THREADS;
- if (pyglib_error_check(&error))
+ if (pygi_error_check (&error))
goto failure;
-
+
total_read += single_read;
}
-
- if ( total_read != PYGLIB_PyBytes_Size(ret_obj) ) {
- if (PYGLIB_PyBytes_Resize(&ret_obj, total_read) == -1)
+
+ if ( total_read != (gsize)PyBytes_Size (ret_obj) ) {
+ if (_PyBytes_Resize (&ret_obj, total_read) == -1)
goto failure;
}
@@ -599,8 +2008,314 @@ pyg_channel_read(PyObject* self, PyObject *args, PyObject *kwargs)
return NULL;
}
+static gboolean
+marshal_emission_hook(GSignalInvocationHint *ihint,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer user_data)
+{
+ PyGILState_STATE state;
+ gboolean retval = FALSE;
+ PyObject *func, *args;
+ PyObject *retobj;
+ PyObject *params;
+ guint i;
+
+ state = PyGILState_Ensure();
+
+ /* construct Python tuple for the parameter values */
+ params = PyTuple_New(n_param_values);
+
+ for (i = 0; i < n_param_values; i++) {
+ PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
+
+ /* error condition */
+ if (!item) {
+ goto out;
+ }
+ PyTuple_SetItem(params, i, item);
+ }
+
+ args = (PyObject *)user_data;
+ func = PyTuple_GetItem(args, 0);
+ args = PySequence_Concat(params, PyTuple_GetItem(args, 1));
+ Py_DECREF(params);
+
+ /* params passed to function may have extra arguments */
+
+ retobj = PyObject_CallObject(func, args);
+ Py_DECREF(args);
+ if (retobj == NULL) {
+ PyErr_Print();
+ }
+
+ retval = (retobj == Py_True ? TRUE : FALSE);
+ Py_XDECREF(retobj);
+out:
+ PyGILState_Release(state);
+ return retval;
+}
+
+/**
+ * pyg_destroy_notify:
+ * @user_data: a PyObject pointer.
+ *
+ * A function that can be used as a GDestroyNotify callback that will
+ * call Py_DECREF on the data.
+ */
+static void
+pyg_destroy_notify(gpointer user_data)
+{
+ PyObject *obj = (PyObject *)user_data;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+ Py_DECREF(obj);
+ PyGILState_Release(state);
+}
+
+static PyObject *
+pyg_add_emission_hook(PyGObject *self, PyObject *args)
+{
+ PyObject *first, *callback, *extra_args, *data, *repr;
+ gchar *name;
+ gulong hook_id;
+ guint sigid;
+ Py_ssize_t len;
+ GQuark detail = 0;
+ GType gtype;
+ PyObject *pygtype;
+
+ len = PyTuple_Size(args);
+ if (len < 3) {
+ PyErr_SetString(PyExc_TypeError,
+ "gobject.add_emission_hook requires at least 3 arguments");
+ return NULL;
+ }
+ first = PySequence_GetSlice(args, 0, 3);
+ if (!PyArg_ParseTuple(first, "OsO:add_emission_hook",
+ &pygtype, &name, &callback)) {
+ Py_DECREF(first);
+ return NULL;
+ }
+ Py_DECREF(first);
+
+ if ((gtype = pyg_type_from_object(pygtype)) == 0) {
+ return NULL;
+ }
+ if (!PyCallable_Check(callback)) {
+ PyErr_SetString(PyExc_TypeError, "third argument must be callable");
+ return NULL;
+ }
+
+ if (!g_signal_parse_name(name, gtype, &sigid, &detail, TRUE)) {
+ repr = PyObject_Repr((PyObject*)self);
+ PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
+ PyUnicode_AsUTF8 (repr),
+ name);
+ Py_DECREF(repr);
+ return NULL;
+ }
+ extra_args = PySequence_GetSlice(args, 3, len);
+ if (extra_args == NULL)
+ return NULL;
+
+ data = Py_BuildValue("(ON)", callback, extra_args);
+ if (data == NULL)
+ return NULL;
+
+ hook_id = g_signal_add_emission_hook(sigid, detail,
+ marshal_emission_hook,
+ data,
+ (GDestroyNotify)pyg_destroy_notify);
+
+ return pygi_gulong_to_py (hook_id);
+}
+
+static PyObject *
+pyg_signal_new(PyObject *self, PyObject *args)
+{
+ gchar *signal_name;
+ PyObject *py_type;
+ GSignalFlags signal_flags;
+ GType return_type;
+ PyObject *py_return_type, *py_param_types;
+
+ GType instance_type = 0;
+ Py_ssize_t py_n_params;
+ guint n_params, i;
+ GType *param_types;
+
+ guint signal_id;
+
+ if (!PyArg_ParseTuple(args, "sOiOO:gobject.signal_new", &signal_name,
+ &py_type, &signal_flags, &py_return_type,
+ &py_param_types))
+ return NULL;
+
+ instance_type = pyg_type_from_object(py_type);
+ if (!instance_type)
+ return NULL;
+ if (!(G_TYPE_IS_INSTANTIATABLE(instance_type) || G_TYPE_IS_INTERFACE(instance_type))) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument 2 must be an object type or interface type");
+ return NULL;
+ }
+
+ return_type = pyg_type_from_object(py_return_type);
+ if (!return_type)
+ return NULL;
+
+ if (!PySequence_Check(py_param_types)) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument 5 must be a sequence of GType codes");
+ return NULL;
+ }
+
+ py_n_params = PySequence_Length(py_param_types);
+ if (py_n_params < 0)
+ return FALSE;
+
+ if (!pygi_guint_from_pyssize (py_n_params, &n_params))
+ return FALSE;
+
+ param_types = g_new(GType, n_params);
+ for (i = 0; i < n_params; i++) {
+ PyObject *item = PySequence_GetItem(py_param_types, i);
+
+ param_types[i] = pyg_type_from_object(item);
+ if (param_types[i] == 0) {
+ PyErr_Clear();
+ Py_DECREF(item);
+ PyErr_SetString(PyExc_TypeError,
+ "argument 5 must be a sequence of GType codes");
+ g_free(param_types);
+ return NULL;
+ }
+ Py_DECREF(item);
+ }
+
+ signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
+ pyg_signal_class_closure_get(),
+ (GSignalAccumulator)0, NULL,
+ (GSignalCMarshaller)0,
+ return_type, n_params, param_types);
+ g_free(param_types);
+ if (signal_id != 0)
+ return pygi_guint_to_py (signal_id);
+ PyErr_SetString(PyExc_RuntimeError, "could not create signal");
+ return NULL;
+}
+
+static PyObject *
+pyg_object_class_list_properties (PyObject *self, PyObject *args)
+{
+ GParamSpec **specs;
+ PyObject *py_itype, *list;
+ GType itype;
+ GObjectClass *class = NULL;
+ gpointer iface = NULL;
+ guint nprops;
+ guint i;
+
+ if (!PyArg_ParseTuple(args, "O:gobject.list_properties",
+ &py_itype))
+ return NULL;
+ if ((itype = pyg_type_from_object(py_itype)) == 0)
+ return NULL;
+
+ if (G_TYPE_IS_INTERFACE(itype)) {
+ iface = g_type_default_interface_ref(itype);
+ if (!iface) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "could not get a reference to interface type");
+ return NULL;
+ }
+ specs = g_object_interface_list_properties(iface, &nprops);
+ } else if (g_type_is_a(itype, G_TYPE_OBJECT)) {
+ class = g_type_class_ref(itype);
+ if (!class) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "could not get a reference to type class");
+ return NULL;
+ }
+ specs = g_object_class_list_properties(class, &nprops);
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "type must be derived from GObject or an interface");
+ return NULL;
+ }
+
+ list = PyTuple_New(nprops);
+ if (list == NULL) {
+ g_free(specs);
+ g_type_class_unref(class);
+ return NULL;
+ }
+ for (i = 0; i < nprops; i++) {
+ PyTuple_SetItem(list, i, pyg_param_spec_new(specs[i]));
+ }
+ g_free(specs);
+ if (class)
+ g_type_class_unref(class);
+ else
+ g_type_default_interface_unref(iface);
+
+ return list;
+}
+
+static PyObject *
+pyg__install_metaclass(PyObject *dummy, PyTypeObject *metaclass)
+{
+ Py_INCREF(metaclass);
+ PyGObject_MetaType = metaclass;
+ Py_INCREF(metaclass);
+
+ Py_SET_TYPE(&PyGObject_Type, metaclass);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_pyig_pyos_getsig (PyObject *self, PyObject *args)
+{
+ int sig_num;
+
+ if (!PyArg_ParseTuple (args, "i:pyos_getsig", &sig_num))
+ return NULL;
+
+ return PyLong_FromVoidPtr ((void *)(PyOS_getsig (sig_num)));
+}
+
+static PyObject *
+_wrap_pygobject_new_full (PyObject *self, PyObject *args)
+{
+ PyObject *ptr_value, *long_value;
+ PyObject *steal;
+ GObject *obj;
+
+ if (!PyArg_ParseTuple (args, "OO", &ptr_value, &steal))
+ return NULL;
+
+ long_value = PyNumber_Long (ptr_value);
+ if (!long_value) {
+ PyErr_SetString (PyExc_TypeError, "first argument must be an integer");
+ return NULL;
+ }
+ obj = PyLong_AsVoidPtr (long_value);
+ Py_DECREF (long_value);
+
+ if (!G_IS_OBJECT (obj)) {
+ PyErr_SetString (PyExc_TypeError, "pointer is not a GObject");
+ return NULL;
+ }
+
+ return pygobject_new_full (obj, PyObject_IsTrue (steal), NULL);
+}
static PyMethodDef _gi_functions[] = {
+ { "pygobject_new_full", (PyCFunction) _wrap_pygobject_new_full, METH_VARARGS },
{ "enum_add", (PyCFunction) _wrap_pyg_enum_add, METH_VARARGS | METH_KEYWORDS },
{ "enum_register_new_gtype_and_add", (PyCFunction) _wrap_pyg_enum_register_new_gtype_and_add, METH_VARARGS | METH_KEYWORDS },
{ "flags_add", (PyCFunction) _wrap_pyg_flags_add, METH_VARARGS | METH_KEYWORDS },
@@ -608,61 +2323,309 @@ static PyMethodDef _gi_functions[] = {
{ "register_interface_info", (PyCFunction) _wrap_pyg_register_interface_info, METH_VARARGS },
{ "hook_up_vfunc_implementation", (PyCFunction) _wrap_pyg_hook_up_vfunc_implementation, METH_VARARGS },
- { "variant_new_tuple", (PyCFunction) _wrap_pyg_variant_new_tuple, METH_VARARGS },
{ "variant_type_from_string", (PyCFunction) _wrap_pyg_variant_type_from_string, METH_VARARGS },
- { "source_new", (PyCFunction) _wrap_pyg_source_new, METH_NOARGS },
- { "source_set_callback", (PyCFunction) pyg_source_set_callback, METH_VARARGS },
+ { "source_new", (PyCFunction) pygi_source_new, METH_NOARGS },
+ { "pyos_getsig", (PyCFunction) _wrap_pyig_pyos_getsig, METH_VARARGS },
+ { "source_set_callback", (PyCFunction) pygi_source_set_callback, METH_VARARGS },
{ "io_channel_read", (PyCFunction) pyg_channel_read, METH_VARARGS },
+ { "require_foreign", (PyCFunction) pygi_require_foreign, METH_VARARGS | METH_KEYWORDS },
+ { "register_foreign", (PyCFunction) pygi_register_foreign, METH_NOARGS },
+ { "spawn_async",
+ (PyCFunction)pyglib_spawn_async, METH_VARARGS|METH_KEYWORDS,
+ "spawn_async(argv, envp=None, working_directory=None,\n"
+ " flags=0, child_setup=None, user_data=None,\n"
+ " standard_input=None, standard_output=None,\n"
+ " standard_error=None) -> (pid, stdin, stdout, stderr)\n"
+ "\n"
+ "Execute a child program asynchronously within a glib.MainLoop()\n"
+ "See the reference manual for a complete reference.\n" },
+ { "type_register", _wrap_pyg_type_register, METH_VARARGS },
+ { "signal_new", pyg_signal_new, METH_VARARGS },
+ { "list_properties",
+ pyg_object_class_list_properties, METH_VARARGS },
+ { "new",
+ (PyCFunction)pyg_object_new, METH_VARARGS|METH_KEYWORDS },
+ { "add_emission_hook",
+ (PyCFunction)pyg_add_emission_hook, METH_VARARGS },
+ { "_install_metaclass",
+ (PyCFunction)pyg__install_metaclass, METH_O },
+ { "_gvalue_get",
+ (PyCFunction)pyg__gvalue_get, METH_O },
+ { "_gvalue_get_type",
+ (PyCFunction)pyg__gvalue_get_type, METH_O },
+ { "_gvalue_set",
+ (PyCFunction)pyg__gvalue_set, 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_signal_closure_new_real,
- pygi_register_foreign_struct_real,
+ pygi_register_foreign_struct,
};
-PYGLIB_MODULE_START(_gi, "_gi")
+struct _PyGObject_Functions pygobject_api_functions = {
+ pygobject_register_class,
+ pygobject_register_wrapper,
+ pygobject_lookup_class,
+ pygobject_new,
+
+ pyg_closure_new,
+ pygobject_watch_closure,
+ pyg_destroy_notify,
+
+ pyg_type_from_object,
+ pyg_type_wrapper_new,
+ pyg_enum_get_value,
+ pyg_flags_get_value,
+ pyg_register_gtype_custom,
+ pyg_value_from_pyobject,
+ pyg_value_as_pyobject,
+
+ pyg_register_interface,
+
+ &PyGBoxed_Type,
+ pygi_register_gboxed,
+ pygi_gboxed_new,
+
+ &PyGPointer_Type,
+ pyg_register_pointer,
+ pyg_pointer_new,
+
+ pyg_enum_add_constants,
+ pyg_flags_add_constants,
+
+ pyg_constant_strip_prefix,
+
+ pygi_error_check,
+
+ _pyg_set_thread_block_funcs,
+ (PyGThreadBlockFunc)0, /* block_threads */
+ (PyGThreadBlockFunc)0, /* unblock_threads */
+
+ &PyGParamSpec_Type,
+ pyg_param_spec_new,
+ pyg_param_spec_from_object,
+
+ pyg_pyobj_to_unichar_conv,
+ pyg_parse_constructor_args,
+ pyg_param_gvalue_as_pyobject,
+ pyg_param_gvalue_from_pyobject,
+
+ &PyGEnum_Type,
+ pyg_enum_add,
+ pyg_enum_from_gtype,
+
+ &PyGFlags_Type,
+ pyg_flags_add,
+ pyg_flags_from_gtype,
+
+ TRUE, /* threads_enabled */
+
+ pygobject_enable_threads,
+ pygobject_gil_state_ensure,
+ pygobject_gil_state_release,
+ pyg_register_class_init,
+ pyg_register_interface_info,
+
+ pyg_closure_set_exception_handler,
+
+ add_warning_redirection,
+ disable_warning_redirections,
+
+ NULL, /* previously type_register_custom */
+
+ pygi_gerror_exception_check,
+
+ pyg_option_group_new,
+ pyg_type_from_object_strict,
+
+ pygobject_new_full,
+ &PyGObject_Type,
+
+ pyg_value_from_pyobject_with_error
+};
+
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+static int
+pygi_register_api(PyObject *d)
{
PyObject *api;
- if (pygobject_init (-1, -1, -1) == NULL) {
- return PYGLIB_MODULE_ERROR_RETURN;
- }
+ api = PyCapsule_New (&pygobject_api_functions, "gobject._PyGObject_API", NULL);
+ if (api == NULL)
+ return -1;
+ PyDict_SetItemString(d, "_PyGObject_API", api);
+ Py_DECREF(api);
+ return 0;
+}
- if (_pygobject_import() < 0) {
- return PYGLIB_MODULE_ERROR_RETURN;
- }
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+static int
+pygi_register_constants(PyObject *m)
+{
+ /* PyFloat_ return a new ref, and add object takes the ref */
+ PyModule_AddObject(m, "G_MINFLOAT", pygi_gfloat_to_py (G_MINFLOAT));
+ PyModule_AddObject(m, "G_MAXFLOAT", pygi_gfloat_to_py (G_MAXFLOAT));
+ PyModule_AddObject(m, "G_MINDOUBLE", pygi_gdouble_to_py (G_MINDOUBLE));
+ PyModule_AddObject(m, "G_MAXDOUBLE", pygi_gdouble_to_py (G_MAXDOUBLE));
+ PyModule_AddIntConstant(m, "G_MINSHORT", G_MINSHORT);
+ PyModule_AddIntConstant(m, "G_MAXSHORT", G_MAXSHORT);
+ PyModule_AddIntConstant(m, "G_MAXUSHORT", G_MAXUSHORT);
+ PyModule_AddIntConstant(m, "G_MININT", G_MININT);
+ PyModule_AddIntConstant(m, "G_MAXINT", G_MAXINT);
+ PyModule_AddObject(m, "G_MAXUINT", pygi_guint_to_py (G_MAXUINT));
+ PyModule_AddObject(m, "G_MINLONG", pygi_glong_to_py (G_MINLONG));
+ PyModule_AddObject(m, "G_MAXLONG", pygi_glong_to_py (G_MAXLONG));
+ PyModule_AddObject(m, "G_MAXULONG", pygi_gulong_to_py (G_MAXULONG));
+ PyModule_AddObject(m, "G_MAXSIZE", pygi_gsize_to_py (G_MAXSIZE));
+ PyModule_AddObject(m, "G_MAXSSIZE", pygi_gssize_to_py (G_MAXSSIZE));
+ PyModule_AddObject(m, "G_MINSSIZE", pygi_gssize_to_py (G_MINSSIZE));
+ PyModule_AddObject(m, "G_MINOFFSET", pygi_gint64_to_py (G_MINOFFSET));
+ PyModule_AddObject(m, "G_MAXOFFSET", pygi_gint64_to_py (G_MAXOFFSET));
+
+ PyModule_AddIntConstant(m, "SIGNAL_RUN_FIRST", G_SIGNAL_RUN_FIRST);
+ PyModule_AddIntConstant(m, "PARAM_READWRITE", G_PARAM_READWRITE);
+
+ /* The rest of the types are set in __init__.py */
+ PyModule_AddObject(m, "TYPE_INVALID", pyg_type_wrapper_new(G_TYPE_INVALID));
+ PyModule_AddObject(m, "TYPE_GSTRING", pyg_type_wrapper_new(G_TYPE_GSTRING));
+
+ return 0;
+}
- _pygi_repository_register_types (module);
- _pygi_info_register_types (module);
- _pygi_struct_register_types (module);
- _pygi_boxed_register_types (module);
- _pygi_ccallback_register_types (module);
- _pygi_argument_init();
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+static int
+pygi_register_version_tuples(PyObject *d)
+{
+ PyObject *tuple;
+
+ /* pygobject version */
+ tuple = Py_BuildValue ("(iii)",
+ PYGOBJECT_MAJOR_VERSION,
+ PYGOBJECT_MINOR_VERSION,
+ PYGOBJECT_MICRO_VERSION);
+ PyDict_SetItemString(d, "pygobject_version", tuple);
+ Py_DECREF (tuple);
+ return 0;
+}
- /* Use RuntimeWarning as the base class of PyGIDeprecationWarning
- * for unstable (odd minor version) and use DeprecationWarning for
- * stable (even minor version). This is so PyGObject deprecations
- * behave the same as regular Python deprecations in stable releases.
- */
-#if PYGOBJECT_MINOR_VERSION % 2
- PyGIDeprecationWarning = PyErr_NewException("gi.PyGIDeprecationWarning",
- PyExc_RuntimeWarning, NULL);
+static struct PyModuleDef __gimodule = {
+ PyModuleDef_HEAD_INIT,
+ "_gi",
+ NULL,
+ -1,
+ _gi_functions,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+#ifdef __GNUC__
+#define PYGI_MODINIT_FUNC __attribute__((visibility("default"))) PyMODINIT_FUNC
#else
+#define PYGI_MODINIT_FUNC PyMODINIT_FUNC
+#endif
+
+PYGI_MODINIT_FUNC PyInit__gi(void);
+
+PYGI_MODINIT_FUNC PyInit__gi(void) {
+ PyObject *module;
+ PyObject *api;
+ module = PyModule_Create(&__gimodule);
+ PyObject *module_dict = PyModule_GetDict (module);
+
+#if PY_VERSION_HEX < 0x03090000 || defined(PYPY_VERSION)
+ /* Deprecated since 3.9 */
+ /* Except in PyPy it's still not a no-op: https://foss.heptapod.net/pypy/pypy/-/issues/3691 */
+
+ /* Always enable Python threads since we cannot predict which GI repositories
+ * might accept Python callbacks run within non-Python threads or might trigger
+ * toggle ref notifications.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=709223
+ */
+ PyEval_InitThreads ();
+#endif
+
+ PyModule_AddStringConstant(module, "__package__", "gi._gi");
+
+ if (pygi_foreign_init () < 0)
+ return NULL;
+ if (pygi_error_register_types (module) < 0)
+ return NULL;
+ if (pygi_repository_register_types (module) < 0)
+ return NULL;
+ if (pygi_info_register_types (module) < 0)
+ return NULL;
+ if (pygi_type_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_pointer_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_struct_register_types (module) < 0)
+ return NULL;
+ if (pygi_gboxed_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_boxed_register_types (module) < 0)
+ return NULL;
+ if (pygi_ccallback_register_types (module) < 0)
+ return NULL;
+ if (pygi_resulttuple_register_types (module) < 0)
+ return NULL;
+
+ if (pygi_spawn_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_option_context_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_option_group_register_types (module_dict) < 0)
+ return NULL;
+
+ if (pygi_register_api (module_dict) < 0)
+ return NULL;
+ if (pygi_register_constants (module) < 0)
+ return NULL;
+ if (pygi_register_version_tuples (module_dict) < 0)
+ return NULL;
+ if (pygi_register_warnings (module_dict) < 0)
+ return NULL;
+ if (pyi_object_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_interface_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_paramspec_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_enum_register_types (module_dict) < 0)
+ return NULL;
+ if (pygi_flags_register_types (module_dict) < 0)
+ return NULL;
+
+ PyGIWarning = PyErr_NewException ("gi.PyGIWarning", PyExc_Warning, NULL);
+ if (PyGIWarning == NULL)
+ return NULL;
+
PyGIDeprecationWarning = PyErr_NewException("gi.PyGIDeprecationWarning",
PyExc_DeprecationWarning, NULL);
-#endif
+
+ /* Place holder object used to fill in "from Python" argument lists
+ * for values not supplied by the caller but support a GI default.
+ */
+ _PyGIDefaultArgPlaceholder = PyList_New(0);
+
+ Py_INCREF (PyGIWarning);
+ PyModule_AddObject (module, "PyGIWarning", PyGIWarning);
Py_INCREF(PyGIDeprecationWarning);
PyModule_AddObject(module, "PyGIDeprecationWarning", PyGIDeprecationWarning);
- api = PYGLIB_CPointer_WrapPointer ( (void *) &CAPI, "gi._API");
+ api = PyCapsule_New ( (void *) &CAPI, "gi._API", NULL);
if (api == NULL) {
- return PYGLIB_MODULE_ERROR_RETURN;
+ return NULL;
}
PyModule_AddObject (module, "_API", api);
+
+ return module;
}
-PYGLIB_MODULE_END
diff --git a/gi/gimodule.h b/gi/gimodule.h
new file mode 100644
index 0000000..b9274bc
--- /dev/null
+++ b/gi/gimodule.h
@@ -0,0 +1,17 @@
+#ifndef _PYGOBJECT_GIMODULE_H_
+#define _PYGOBJECT_GIMODULE_H_
+
+#include "pygobject-internal.h"
+
+int pygobject_constructv (PyGObject *self,
+ guint n_properties,
+ const char *names[],
+ const GValue values[]);
+
+GObject *
+pygobject_object_new_with_properties(GType object_type,
+ guint n_properties,
+ const char *names[],
+ const GValue values[]);
+
+#endif /*_PYGOBJECT_GIMODULE_H_*/
diff --git a/gi/importer.py b/gi/importer.py
index aa95cf6..73d0c5c 100644
--- a/gi/importer.py
+++ b/gi/importer.py
@@ -2,6 +2,7 @@
# vim: tabstop=4 shiftwidth=4 expandtab
#
# Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org>
+# 2015 Christoph Reiter
#
# importer.py: dynamic importer for introspected libraries.
#
@@ -20,18 +21,85 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-from __future__ import absolute_import
-import logging
import sys
+import warnings
+import importlib
+from contextlib import contextmanager
-from ._gi import Repository
-from .module import DynamicModule
+import gi
+from ._gi import Repository, RepositoryError
+from ._gi import PyGIWarning
+from .module import get_introspection_module
+from .overrides import load_overrides
repository = Repository.get_default()
+
+# only for backwards compatibility
modules = {}
+@contextmanager
+def _check_require_version(namespace, stacklevel):
+ """A context manager which tries to give helpful warnings
+ about missing gi.require_version() which could potentially
+ break code if only an older version than expected is installed
+ or a new version gets introduced.
+
+ ::
+
+ with _check_require_version("Gtk", stacklevel):
+ load_namespace_and_overrides()
+ """
+
+ was_loaded = repository.is_registered(namespace)
+
+ yield
+
+ if was_loaded:
+ # it was loaded before by another import which depended on this
+ # namespace or by C code like libpeas
+ return
+
+ if namespace in ("GLib", "GObject", "Gio"):
+ # part of glib (we have bigger problems if versions change there)
+ return
+
+ if gi.get_required_version(namespace) is not None:
+ # the version was forced using require_version()
+ return
+
+ version = repository.get_version(namespace)
+ warnings.warn(
+ "%(namespace)s was imported without specifying a version first. "
+ "Use gi.require_version('%(namespace)s', '%(version)s') before "
+ "import to ensure that the right version gets loaded."
+ % {"namespace": namespace, "version": version},
+ PyGIWarning, stacklevel=stacklevel)
+
+
+def get_import_stacklevel(import_hook):
+ """Returns the stacklevel value for warnings.warn() for when the warning
+ gets emitted by an imported module, but the warning should point at the
+ code doing the import.
+
+ Pass import_hook=True if the warning gets generated by an import hook
+ (warn() gets called in load_module(), see PEP302)
+ """
+
+ py_version = sys.version_info[:2]
+ if py_version <= (3, 2):
+ # 2.7 included
+ return 4 if import_hook else 2
+ elif py_version == (3, 3):
+ return 8 if import_hook else 10
+ elif py_version == (3, 4):
+ return 10 if import_hook else 8
+ else:
+ # fixed again in 3.5+, see https://bugs.python.org/issue24305
+ return 4 if import_hook else 2
+
+
class DynamicImporter(object):
# Note: see PEP302 for the Importer Protocol implemented below.
@@ -39,32 +107,47 @@ class DynamicImporter(object):
def __init__(self, path):
self.path = path
- def find_module(self, fullname, path=None):
+ def _find_module_check(self, fullname):
if not fullname.startswith(self.path):
- return
+ return False
path, namespace = fullname.rsplit('.', 1)
- if path != self.path:
- return
-
- if not repository.enumerate_versions(namespace):
- logging.error('Could not find any typelib for %s', namespace)
- return None
- else:
- return self
+ return path == self.path
- def load_module(self, fullname):
- if fullname in sys.modules:
- return sys.modules[fullname]
+ def find_spec(self, fullname, path=None, target=None):
+ if self._find_module_check(fullname):
+ return importlib.util.spec_from_loader(fullname, self)
- path, namespace = fullname.rsplit('.', 1)
- dynamic_module = DynamicModule(namespace)
- modules[namespace] = dynamic_module
-
- dynamic_module.__file__ = '<%s>' % fullname
- dynamic_module.__loader__ = self
+ def find_module(self, fullname, path=None):
+ if self._find_module_check(fullname):
+ return self
- sys.modules[fullname] = dynamic_module
- dynamic_module._load()
+ def create_module(self, spec):
+ path, namespace = spec.name.rsplit('.', 1)
+
+ # is_registered() is faster than enumerate_versions() and
+ # in the common case of a namespace getting loaded before its
+ # dependencies, is_registered() returns True for all dependencies.
+ if not repository.is_registered(namespace) and not \
+ repository.enumerate_versions(namespace):
+ raise ImportError('cannot import name %s, '
+ 'introspection typelib not found' % namespace)
+
+ stacklevel = get_import_stacklevel(import_hook=True)
+ with _check_require_version(namespace, stacklevel=stacklevel):
+ try:
+ introspection_module = get_introspection_module(namespace)
+ except RepositoryError as e:
+ raise ImportError(e)
+ # Import all dependencies first so their init functions
+ # (gdk_init, ..) in overrides get called.
+ # https://bugzilla.gnome.org/show_bug.cgi?id=656314
+ for dep in repository.get_immediate_dependencies(namespace):
+ importlib.import_module('gi.repository.' + dep.split("-")[0])
+ dynamic_module = load_overrides(introspection_module)
return dynamic_module
+
+ def exec_module(self, fullname):
+ # “exec” the module and consequently populate the module’s namespace
+ pass
diff --git a/gi/meson.build b/gi/meson.build
new file mode 100644
index 0000000..8edf832
--- /dev/null
+++ b/gi/meson.build
@@ -0,0 +1,91 @@
+sources = [
+ 'pygboxed.c',
+ 'pygenum.c',
+ 'pygflags.c',
+ 'pyginterface.c',
+ 'pygobject-object.c',
+ 'pygparamspec.c',
+ 'pygpointer.c',
+ 'pygoptioncontext.c',
+ 'pygoptiongroup.c',
+ 'pygspawn.c',
+ 'gimodule.c',
+ 'pygi-repository.c',
+ 'pygi-info.c',
+ 'pygi-foreign.c',
+ 'pygi-struct.c',
+ 'pygi-source.c',
+ 'pygi-argument.c',
+ 'pygi-resulttuple.c',
+ 'pygi-type.c',
+ 'pygi-boxed.c',
+ 'pygi-closure.c',
+ 'pygi-ccallback.c',
+ 'pygi-util.c',
+ 'pygi-property.c',
+ 'pygi-signal-closure.c',
+ 'pygi-invoke.c',
+ 'pygi-cache.c',
+ 'pygi-marshal-cleanup.c',
+ 'pygi-basictype.c',
+ 'pygi-list.c',
+ 'pygi-array.c',
+ 'pygi-error.c',
+ 'pygi-object.c',
+ 'pygi-value.c',
+ 'pygi-enum-marshal.c',
+ 'pygi-struct-marshal.c',
+ 'pygi-hashtable.c']
+
+headers = [
+ 'pygobject.h'
+]
+
+install_headers(headers, subdir : 'pygobject-@0@'.format(platform_version))
+
+python_sources = [
+ '_constants.py',
+ 'docstring.py',
+ '_error.py',
+ '_gtktemplate.py',
+ 'importer.py',
+ '__init__.py',
+ 'module.py',
+ '_option.py',
+ '_ossighelper.py',
+ '_propertyhelper.py',
+ 'pygtkcompat.py',
+ '_signalhelper.py',
+ 'types.py',
+]
+
+python.install_sources(python_sources,
+ pure : false,
+ subdir : 'gi'
+)
+
+# https://github.com/mesonbuild/meson/issues/4117
+if host_machine.system() == 'windows'
+ python_ext_dep = python_dep
+else
+ python_ext_dep = python_dep.partial_dependency(compile_args: true)
+endif
+
+giext = python.extension_module('_gi', sources,
+ dependencies : [python_ext_dep, glib_dep, gi_dep, ffi_dep],
+ include_directories: include_directories('..'),
+ install: true,
+ subdir : 'gi',
+ c_args: pyext_c_args + main_c_args
+)
+
+if cairo_dep.found()
+ gicairoext = python.extension_module('_gi_cairo', ['pygi-foreign-cairo.c'],
+ dependencies : [python_ext_dep, glib_dep, gi_dep, ffi_dep, pycairo_dep, cairo_dep, cairo_gobject_dep],
+ install: true,
+ subdir : 'gi',
+ c_args: pyext_c_args + main_c_args)
+endif
+
+subdir('overrides')
+subdir('repository')
diff --git a/gi/module.py b/gi/module.py
index 71f8ac5..93b8e6a 100644
--- a/gi/module.py
+++ b/gi/module.py
@@ -20,22 +20,10 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-from __future__ import absolute_import
-
-import sys
-import types
import importlib
-
-_have_py3 = (sys.version_info[0] >= 3)
-
-try:
- maketrans = ''.maketrans
-except AttributeError:
- # fallback for Python 2
- from string import maketrans
+from threading import Lock
import gi
-from .overrides import registry
from ._gi import \
Repository, \
@@ -54,16 +42,13 @@ from ._gi import \
enum_add, \
enum_register_new_gtype_and_add, \
flags_add, \
- flags_register_new_gtype_and_add
+ flags_register_new_gtype_and_add, \
+ GInterface
from .types import \
GObjectMeta, \
StructMeta
-from ._gobject._gobject import \
- GInterface, \
- GObject
-
-from ._gobject.constants import \
+from ._constants import \
TYPE_NONE, \
TYPE_BOXED, \
TYPE_POINTER, \
@@ -81,10 +66,16 @@ def get_parent_for_object(object_info):
parent_object_info = object_info.get_parent()
if not parent_object_info:
- # Special case GObject.Object as being derived from the static GObject.
- if object_info.get_namespace() == 'GObject' and object_info.get_name() == 'Object':
- return GObject
-
+ # If we reach the end of the introspection info class hierarchy, look
+ # for an existing wrapper on the GType and use it as a base for the
+ # new introspection wrapper. This allows static C wrappers already
+ # registered with the GType to be used as the introspection base
+ # (_gi.GObject for example)
+ gtype = object_info.get_g_type()
+ if gtype and gtype.pytype:
+ return gtype.pytype
+
+ # Otherwise use builtins.object as the base
return object
namespace = parent_object_info.get_namespace()
@@ -114,19 +105,21 @@ class IntrospectionModule(object):
These members are then cached on this introspection module.
"""
def __init__(self, namespace, version=None):
+ """Might raise gi._gi.RepositoryError"""
+
repository.require(namespace, version)
self._namespace = namespace
self._version = version
self.__name__ = 'gi.repository.' + namespace
- self.__path__ = repository.get_typelib_path(self._namespace)
- if _have_py3:
- # get_typelib_path() delivers bytes, not a string
- self.__path__ = self.__path__.decode('UTF-8')
+ path = repository.get_typelib_path(self._namespace)
+ self.__path__ = [path]
if self._version is None:
self._version = repository.get_version(self._namespace)
+ self._lock = Lock()
+
def __getattr__(self, name):
info = repository.find_by_name(self._namespace, name)
if not info:
@@ -135,37 +128,41 @@ class IntrospectionModule(object):
if isinstance(info, EnumInfo):
g_type = info.get_g_type()
- wrapper = g_type.pytype
- if wrapper is None:
- if info.is_flags():
- if g_type.is_a(TYPE_FLAGS):
- wrapper = flags_add(g_type)
- else:
- assert g_type == TYPE_NONE
- wrapper = flags_register_new_gtype_and_add(info)
- else:
- if g_type.is_a(TYPE_ENUM):
- wrapper = enum_add(g_type)
- else:
- assert g_type == TYPE_NONE
- wrapper = enum_register_new_gtype_and_add(info)
-
- wrapper.__info__ = info
- wrapper.__module__ = 'gi.repository.' + info.get_namespace()
-
- # Don't use upper() here to avoid locale specific
- # identifier conversion (e. g. in Turkish 'i'.upper() == 'i')
- # see https://bugzilla.gnome.org/show_bug.cgi?id=649165
- ascii_upper_trans = maketrans(
- 'abcdefgjhijklmnopqrstuvwxyz',
- 'ABCDEFGJHIJKLMNOPQRSTUVWXYZ')
- for value_info in info.get_values():
- value_name = value_info.get_name_unescaped().translate(ascii_upper_trans)
- setattr(wrapper, value_name, wrapper(value_info.get_value()))
+ with self._lock:
+ wrapper = g_type.pytype
- if g_type != TYPE_NONE:
- g_type.pytype = wrapper
+ if wrapper is None:
+ if info.is_flags():
+ if g_type.is_a(TYPE_FLAGS):
+ wrapper = flags_add(g_type)
+ else:
+ assert g_type == TYPE_NONE
+ wrapper = flags_register_new_gtype_and_add(info)
+ else:
+ if g_type.is_a(TYPE_ENUM):
+ wrapper = enum_add(g_type)
+ else:
+ assert g_type == TYPE_NONE
+ wrapper = enum_register_new_gtype_and_add(info)
+
+ wrapper.__info__ = info
+ wrapper.__module__ = 'gi.repository.' + info.get_namespace()
+
+ # Don't use upper() here to avoid locale specific
+ # identifier conversion (e. g. in Turkish 'i'.upper() == 'i')
+ # see https://bugzilla.gnome.org/show_bug.cgi?id=649165
+ ascii_upper_trans = ''.maketrans(
+ 'abcdefgjhijklmnopqrstuvwxyz',
+ 'ABCDEFGJHIJKLMNOPQRSTUVWXYZ')
+ for value_info in info.get_values():
+ value_name = value_info.get_name_unescaped().translate(ascii_upper_trans)
+ setattr(wrapper, value_name, wrapper(value_info.get_value()))
+ for method_info in info.get_methods():
+ setattr(wrapper, method_info.__name__, method_info)
+
+ if g_type != TYPE_NONE:
+ g_type.pytype = wrapper
elif isinstance(info, RegisteredTypeInfo):
g_type = info.get_g_type()
@@ -196,27 +193,28 @@ class IntrospectionModule(object):
else:
raise NotImplementedError(info)
- # Check if there is already a Python wrapper that is not a parent class
- # of the wrapper being created. If it is a parent, it is ok to clobber
- # g_type.pytype with a new child class wrapper of the existing parent.
- # Note that the return here never occurs under normal circumstances due
- # to caching on the __dict__ itself.
- if g_type != TYPE_NONE:
- type_ = g_type.pytype
- if type_ is not None and type_ not in bases:
- self.__dict__[name] = type_
- return type_
-
- dict_ = {
- '__info__': info,
- '__module__': 'gi.repository.' + self._namespace,
- '__gtype__': g_type
- }
- wrapper = metaclass(name, bases, dict_)
-
- # Register the new Python wrapper.
- if g_type != TYPE_NONE:
- g_type.pytype = wrapper
+ with self._lock:
+ # Check if there is already a Python wrapper that is not a parent class
+ # of the wrapper being created. If it is a parent, it is ok to clobber
+ # g_type.pytype with a new child class wrapper of the existing parent.
+ # Note that the return here never occurs under normal circumstances due
+ # to caching on the __dict__ itself.
+ if g_type != TYPE_NONE:
+ type_ = g_type.pytype
+ if type_ is not None and type_ not in bases:
+ self.__dict__[name] = type_
+ return type_
+
+ dict_ = {
+ '__info__': info,
+ '__module__': 'gi.repository.' + self._namespace,
+ '__gtype__': g_type
+ }
+ wrapper = metaclass(name, bases, dict_)
+
+ # Register the new Python wrapper.
+ if g_type != TYPE_NONE:
+ g_type.pytype = wrapper
elif isinstance(info, FunctionInfo):
wrapper = info
@@ -233,9 +231,6 @@ class IntrospectionModule(object):
def __repr__(self):
path = repository.get_typelib_path(self._namespace)
- if _have_py3:
- # get_typelib_path() delivers bytes, not a string
- path = path.decode('UTF-8')
return "<IntrospectionModule %r from %r>" % (self._namespace, path)
def __dir__(self):
@@ -258,6 +253,8 @@ def get_introspection_module(namespace):
"""
:Returns:
An object directly wrapping the gi module without overrides.
+
+ Might raise gi._gi.RepositoryError
"""
if namespace in _introspection_modules:
return _introspection_modules[namespace]
@@ -266,69 +263,3 @@ def get_introspection_module(namespace):
module = IntrospectionModule(namespace, version)
_introspection_modules[namespace] = module
return module
-
-
-class DynamicModule(types.ModuleType):
- """A module composed of an IntrospectionModule and an overrides module.
-
- DynamicModule wraps up an IntrospectionModule and an overrides module
- into a single accessible module. This is what is returned from statements
- like "from gi.repository import Foo". Accessing attributes on a DynamicModule
- will first look overrides (or the gi.overrides.registry cache) and then
- in the introspection module if it was not found as an override.
- """
- def __init__(self, namespace):
- self._namespace = namespace
- self._introspection_module = None
- self._overrides_module = None
- self.__path__ = None
-
- def _load(self):
- self._introspection_module = get_introspection_module(self._namespace)
- try:
- self._overrides_module = importlib.import_module('gi.overrides.' + self._namespace)
- except ImportError:
- self._overrides_module = None
-
- self.__path__ = repository.get_typelib_path(self._namespace)
- if _have_py3:
- # get_typelib_path() delivers bytes, not a string
- self.__path__ = self.__path__.decode('UTF-8')
-
- def __getattr__(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)
- else:
- # check the registry just in case the module hasn't loaded yet
- # TODO: Only gtypes are registered in the registry right now
- # but it would be nice to register all overrides and
- # get rid of the module imports. We might actually see a
- # speedup.
- key = '%s.%s' % (self._namespace, name)
- if key in registry:
- return registry[key]
-
- return getattr(self._introspection_module, name)
-
- def __dir__(self):
- # Python's default dir() is just dir(self.__class__) + self.__dict__.keys()
- result = set(dir(self.__class__))
- result.update(self.__dict__.keys())
-
- result.update(dir(self._introspection_module))
- override_exports = getattr(self._overrides_module, '__all__', ())
- result.update(override_exports)
- return list(result)
-
- def __repr__(self):
- path = repository.get_typelib_path(self._namespace)
- if _have_py3:
- # get_typelib_path() delivers bytes, not a string
- path = path.decode('UTF-8')
-
- return "<%s.%s %r from %r>" % (self.__class__.__module__,
- self.__class__.__name__,
- self._namespace,
- path)
diff --git a/gi/overrides/GIMarshallingTests.py b/gi/overrides/GIMarshallingTests.py
index cc967b4..e9f8e33 100644
--- a/gi/overrides/GIMarshallingTests.py
+++ b/gi/overrides/GIMarshallingTests.py
@@ -41,6 +41,7 @@ class OverridesStruct(GIMarshallingTests.OverridesStruct):
def method(self):
return GIMarshallingTests.OverridesStruct.method(self) / 7
+
OverridesStruct = override(OverridesStruct)
__all__.append('OverridesStruct')
@@ -53,18 +54,19 @@ class OverridesObject(GIMarshallingTests.OverridesObject):
def __init__(self, long_):
GIMarshallingTests.OverridesObject.__init__(self)
# FIXME: doesn't work yet
- #self.long_ = long_
+ # self.long_ = long_
@classmethod
def new(cls, long_):
self = GIMarshallingTests.OverridesObject.new()
# FIXME: doesn't work yet
- #self.long_ = long_
+ # self.long_ = long_
return self
def method(self):
"""Overridden doc string."""
return GIMarshallingTests.OverridesObject.method(self) / 7
+
OverridesObject = override(OverridesObject)
__all__.append('OverridesObject')
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index f4b1ef5..78d309b 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -19,41 +19,67 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-import signal
import warnings
import sys
+import socket
+from .._ossighelper import wakeup_on_signal, register_sigint_fallback
from ..module import get_introspection_module
-from .._gi import (variant_new_tuple, variant_type_from_string, source_new,
+from .._gi import (variant_type_from_string, source_new,
source_set_callback, io_channel_read)
-from ..overrides import override, deprecated
+from ..overrides import override, deprecated, deprecated_attr
from gi import PyGIDeprecationWarning, version_info
GLib = get_introspection_module('GLib')
__all__ = []
-from gi._glib import option
+from gi import _option as option
option # pyflakes
__all__.append('option')
# Types and functions still needed from static bindings
-from gi._glib import _glib
-GError = _glib.GError
-OptionContext = _glib.OptionContext
-OptionGroup = _glib.OptionGroup
-Pid = _glib.Pid
-spawn_async = _glib.spawn_async
+from gi import _gi
+from gi._error import GError
+
+Error = GError
+OptionContext = _gi.OptionContext
+OptionGroup = _gi.OptionGroup
+Pid = _gi.Pid
+spawn_async = _gi.spawn_async
def threads_init():
- warnings.warn('threads_init no longer needs to be called. '
- 'See: https://bugzilla.gnome.org/show_bug.cgi?id=686914',
- PyGIDeprecationWarning)
+ warnings.warn('Since version 3.11, calling threads_init is no longer needed. '
+ 'See: https://wiki.gnome.org/PyGObject/Threading',
+ PyGIDeprecationWarning, stacklevel=2)
+
+
+def gerror_matches(self, domain, code):
+ # Handle cases where self.domain was set to an integer for compatibility
+ # with the introspected GLib.Error.
+ if isinstance(self.domain, str):
+ self_domain_quark = GLib.quark_from_string(self.domain)
+ else:
+ self_domain_quark = self.domain
+ return (self_domain_quark, self.code) == (domain, code)
+
+def gerror_new_literal(domain, message, code):
+ domain_quark = GLib.quark_to_string(domain)
+ return GError(message, domain_quark, code)
-__all__ += ['GError', 'OptionContext', 'OptionGroup', 'Pid',
+
+# Monkey patch methods that rely on GLib introspection to be loaded at runtime.
+Error.__name__ = 'Error'
+Error.__module__ = 'gi.repository.GLib'
+Error.__gtype__ = GLib.Error.__gtype__
+Error.matches = gerror_matches
+Error.new_literal = staticmethod(gerror_new_literal)
+
+
+__all__ += ['GError', 'Error', 'OptionContext', 'OptionGroup', 'Pid',
'spawn_async', 'threads_init']
@@ -76,132 +102,77 @@ class _VariantCreator(object):
'v': GLib.Variant.new_variant,
}
- def _create(self, format, args):
- '''Create a GVariant object from given format and argument list.
+ def _create(self, format, value):
+ """Create a GVariant object from given format and a value that matches
+ the format.
This method recursively calls itself for complex structures (arrays,
dictionaries, boxed).
- Return a tuple (variant, rest_format, rest_args) with the generated
- GVariant, the remainder of the format string, and the remainder of the
- arguments.
-
- If args is None, then this won't actually consume any arguments, and
- just parse the format string and generate empty GVariant structures.
- This is required for creating empty dictionaries or arrays.
- '''
- # leaves (simple types)
- constructor = self._LEAF_CONSTRUCTORS.get(format[0])
- if constructor:
- if args is not None:
- if not args:
- raise TypeError('not enough arguments for GVariant format string')
- v = constructor(args[0])
- return (v, format[1:], args[1:])
- else:
- return (None, format[1:], None)
-
- if format[0] == '(':
- return self._create_tuple(format, args)
-
- if format.startswith('a{'):
- return self._create_dict(format, args)
-
- if format[0] == 'a':
- return self._create_array(format, args)
-
- raise NotImplementedError('cannot handle GVariant type ' + format)
-
- def _create_tuple(self, format, args):
- '''Handle the case where the outermost type of format is a tuple.'''
-
- format = format[1:] # eat the '('
- if args is None:
- # empty value: we need to call _create() to parse the subtype
- rest_format = format
- while rest_format:
- if rest_format.startswith(')'):
- break
- rest_format = self._create(rest_format, None)[1]
- else:
- raise TypeError('tuple type string not closed with )')
-
- rest_format = rest_format[1:] # eat the )
- return (None, rest_format, None)
- else:
- if not args or not isinstance(args[0], tuple):
- raise TypeError('expected tuple argument')
-
- builder = GLib.VariantBuilder.new(variant_type_from_string('r'))
- for i in range(len(args[0])):
- if format.startswith(')'):
- raise TypeError('too many arguments for tuple signature')
-
- (v, format, _) = self._create(format, args[0][i:])
- builder.add_value(v)
- args = args[1:]
- if not format.startswith(')'):
- raise TypeError('tuple type string not closed with )')
-
- rest_format = format[1:] # eat the )
- return (builder.end(), rest_format, args)
-
- def _create_dict(self, format, args):
- '''Handle the case where the outermost type of format is a dict.'''
-
- builder = None
- if args is None or not args[0]:
- # empty value: we need to call _create() to parse the subtype,
- # and specify the element type precisely
- rest_format = self._create(format[2:], None)[1]
- rest_format = self._create(rest_format, None)[1]
- if not rest_format.startswith('}'):
- raise TypeError('dictionary type string not closed with }')
- rest_format = rest_format[1:] # eat the }
- element_type = format[:len(format) - len(rest_format)]
- builder = GLib.VariantBuilder.new(variant_type_from_string(element_type))
- else:
- builder = GLib.VariantBuilder.new(variant_type_from_string('a{?*}'))
- for k, v in args[0].items():
- (key_v, rest_format, _) = self._create(format[2:], [k])
- (val_v, rest_format, _) = self._create(rest_format, [v])
-
- if not rest_format.startswith('}'):
- raise TypeError('dictionary type string not closed with }')
- rest_format = rest_format[1:] # eat the }
-
- entry = GLib.VariantBuilder.new(variant_type_from_string('{?*}'))
- entry.add_value(key_v)
- entry.add_value(val_v)
- builder.add_value(entry.end())
-
- if args is not None:
- args = args[1:]
- return (builder.end(), rest_format, args)
-
- def _create_array(self, format, args):
- '''Handle the case where the outermost type of format is an array.'''
-
- builder = None
- if args is None or not args[0]:
- # empty value: we need to call _create() to parse the subtype,
- # and specify the element type precisely
- rest_format = self._create(format[1:], None)[1]
- element_type = format[:len(format) - len(rest_format)]
- builder = GLib.VariantBuilder.new(variant_type_from_string(element_type))
+ Returns the generated GVariant.
+
+ If value is None it will generate an empty GVariant container type.
+ """
+ gvtype = GLib.VariantType(format)
+ if format in self._LEAF_CONSTRUCTORS:
+ return self._LEAF_CONSTRUCTORS[format](value)
+
+ # Since we discarded all leaf types, this must be a container
+ builder = GLib.VariantBuilder.new(gvtype)
+ if value is None:
+ return builder.end()
+
+ if gvtype.is_maybe():
+ builder.add_value(self._create(gvtype.element().dup_string(), value))
+ return builder.end()
+
+ try:
+ iter(value)
+ except TypeError:
+ raise TypeError("Could not create array, tuple or dictionary entry from non iterable value %s %s" %
+ (format, value))
+
+ if gvtype.is_tuple() and gvtype.n_items() != len(value):
+ raise TypeError("Tuple mismatches value's number of elements %s %s" % (format, value))
+ if gvtype.is_dict_entry() and len(value) != 2:
+ raise TypeError("Dictionary entries must have two elements %s %s" % (format, value))
+
+ if gvtype.is_array():
+ element_type = gvtype.element().dup_string()
+ if isinstance(value, dict):
+ value = value.items()
+ for i in value:
+ builder.add_value(self._create(element_type, i))
else:
- builder = GLib.VariantBuilder.new(variant_type_from_string('a*'))
- for i in range(len(args[0])):
- (v, rest_format, _) = self._create(format[1:], args[0][i:])
- builder.add_value(v)
- if args is not None:
- args = args[1:]
- return (builder.end(), rest_format, args)
+ remainer_format = format[1:]
+ for i in value:
+ dup = variant_type_from_string(remainer_format).dup_string()
+ builder.add_value(self._create(dup, i))
+ remainer_format = remainer_format[len(dup):]
+
+ return builder.end()
+
+
+LEAF_ACCESSORS = {
+ 'b': 'get_boolean',
+ 'y': 'get_byte',
+ 'n': 'get_int16',
+ 'q': 'get_uint16',
+ 'i': 'get_int32',
+ 'u': 'get_uint32',
+ 'x': 'get_int64',
+ 't': 'get_uint64',
+ 'h': 'get_handle',
+ 'd': 'get_double',
+ 's': 'get_string',
+ 'o': 'get_string', # object path
+ 'g': 'get_string', # signature
+}
class Variant(GLib.Variant):
def __new__(cls, format_string, value):
- '''Create a GVariant from a native Python object.
+ """Create a GVariant from a native Python object.
format_string is a standard GVariant type signature, value is a Python
object whose structure has to match the signature.
@@ -211,16 +182,29 @@ class Variant(GLib.Variant):
GLib.Variant('(is)', (1, 'hello'))
GLib.Variant('(asa{sv})', ([], {'foo': GLib.Variant('b', True),
'bar': GLib.Variant('i', 2)}))
- '''
+ """
+ if not GLib.VariantType.string_is_valid(format_string):
+ raise TypeError("Invalid GVariant format string '%s'", format_string)
creator = _VariantCreator()
- (v, rest_format, _) = creator._create(format_string, [value])
- if rest_format:
- raise TypeError('invalid remaining format string: "%s"' % rest_format)
+ v = creator._create(format_string, value)
v.format_string = format_string
return v
+ @staticmethod
+ def new_tuple(*elements):
+ return GLib.Variant.new_tuple(elements)
+
def __del__(self):
- self.unref()
+ try:
+ self.unref()
+ except ImportError:
+ # Calling unref will cause gi and gi.repository.GLib to be
+ # imported. However, if the program is exiting, then these
+ # modules have likely been removed from sys.modules and will
+ # raise an exception. Assume that's the case for ImportError
+ # and ignore the exception since everything will be cleaned
+ # up, anyways.
+ pass
def __str__(self):
return self.print_(True)
@@ -251,37 +235,22 @@ class Variant(GLib.Variant):
return hash((self.get_type_string(), self.unpack()))
def unpack(self):
- '''Decompose a GVariant into a native Python object.'''
-
- LEAF_ACCESSORS = {
- 'b': self.get_boolean,
- 'y': self.get_byte,
- 'n': self.get_int16,
- 'q': self.get_uint16,
- 'i': self.get_int32,
- 'u': self.get_uint32,
- 'x': self.get_int64,
- 't': self.get_uint64,
- 'h': self.get_handle,
- 'd': self.get_double,
- 's': self.get_string,
- 'o': self.get_string, # object path
- 'g': self.get_string, # signature
- }
+ """Decompose a GVariant into a native Python object."""
+
+ type_string = self.get_type_string()
# simple values
- la = LEAF_ACCESSORS.get(self.get_type_string())
+ la = LEAF_ACCESSORS.get(type_string)
if la:
- return la()
+ return getattr(self, la)()
# tuple
- if self.get_type_string().startswith('('):
- res = [self.get_child_value(i).unpack()
- for i in range(self.n_children())]
- return tuple(res)
+ if type_string.startswith('('):
+ return tuple(self.get_child_value(i).unpack()
+ for i in range(self.n_children()))
# dictionary
- if self.get_type_string().startswith('a{'):
+ if type_string.startswith('a{'):
res = {}
for i in range(self.n_children()):
v = self.get_child_value(i)
@@ -289,31 +258,32 @@ class Variant(GLib.Variant):
return res
# array
- if self.get_type_string().startswith('a'):
+ if type_string.startswith('a'):
return [self.get_child_value(i).unpack()
for i in range(self.n_children())]
# variant (just unbox transparently)
- if self.get_type_string().startswith('v'):
+ if type_string.startswith('v'):
return self.get_variant().unpack()
# maybe
- if self.get_type_string().startswith('m'):
- m = self.get_maybe()
- return m.unpack() if m else None
+ if type_string.startswith('m'):
+ if not self.n_children():
+ return None
+ return self.get_child_value(0).unpack()
- raise NotImplementedError('unsupported GVariant type ' + self.get_type_string())
+ raise NotImplementedError('unsupported GVariant type ' + type_string)
@classmethod
def split_signature(klass, signature):
- '''Return a list of the element signatures of the topmost signature tuple.
+ """Return a list of the element signatures of the topmost signature tuple.
If the signature is not a tuple, it returns one element with the entire
signature. If the signature is an empty tuple, the result is [].
This is useful for e. g. iterating over method parameters which are
passed as a single Variant.
- '''
+ """
if signature == '()':
return []
@@ -416,15 +386,12 @@ class Variant(GLib.Variant):
# Array, dict, tuple
if self.get_type_string().startswith('a') or self.get_type_string().startswith('('):
return self.n_children() != 0
- if self.get_type_string() in ['v']:
- # unpack works recursively, hence bool also works recursively
- return bool(self.unpack())
- # Everything else is True
- return True
+ # unpack works recursively, hence bool also works recursively
+ return bool(self.unpack())
def keys(self):
if not self.get_type_string().startswith('a{'):
- return TypeError, 'GVariant type %s is not a dictionary' % self.get_type_string()
+ raise TypeError('GVariant type %s is not a dictionary' % self.get_type_string())
res = []
for i in range(self.n_children()):
@@ -433,16 +400,11 @@ class Variant(GLib.Variant):
return res
-@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')
@@ -453,14 +415,18 @@ def markup_escape_text(text, length=-1):
return GLib.markup_escape_text(text.decode('UTF-8'), length)
else:
return GLib.markup_escape_text(text, length)
+
+
__all__.append('markup_escape_text')
# backwards compatible names from old static bindings
for n in ['DESKTOP', 'DOCUMENTS', 'DOWNLOAD', 'MUSIC', 'PICTURES',
'PUBLIC_SHARE', 'TEMPLATES', 'VIDEOS']:
- globals()['USER_DIRECTORY_' + n] = getattr(GLib.UserDirectory, 'DIRECTORY_' + n)
- __all__.append('USER_DIRECTORY_' + n)
+ attr = 'USER_DIRECTORY_' + n
+ deprecated_attr("GLib", attr, "GLib.UserDirectory.DIRECTORY_" + n)
+ globals()[attr] = getattr(GLib.UserDirectory, 'DIRECTORY_' + n)
+ __all__.append(attr)
for n in ['ERR', 'HUP', 'IN', 'NVAL', 'OUT', 'PRI']:
globals()['IO_' + n] = getattr(GLib.IOCondition, n)
@@ -468,30 +434,53 @@ for n in ['ERR', 'HUP', 'IN', 'NVAL', 'OUT', 'PRI']:
for n in ['APPEND', 'GET_MASK', 'IS_READABLE', 'IS_SEEKABLE',
'MASK', 'NONBLOCK', 'SET_MASK']:
- globals()['IO_FLAG_' + n] = getattr(GLib.IOFlags, n)
- __all__.append('IO_FLAG_' + n)
+ attr = 'IO_FLAG_' + n
+ deprecated_attr("GLib", attr, "GLib.IOFlags." + n)
+ globals()[attr] = getattr(GLib.IOFlags, n)
+ __all__.append(attr)
+
# spelling for the win
IO_FLAG_IS_WRITEABLE = GLib.IOFlags.IS_WRITABLE
+deprecated_attr("GLib", "IO_FLAG_IS_WRITEABLE", "GLib.IOFlags.IS_WRITABLE")
__all__.append('IO_FLAG_IS_WRITEABLE')
for n in ['AGAIN', 'EOF', 'ERROR', 'NORMAL']:
- globals()['IO_STATUS_' + n] = getattr(GLib.IOStatus, n)
- __all__.append('IO_STATUS_' + n)
+ attr = 'IO_STATUS_' + n
+ globals()[attr] = getattr(GLib.IOStatus, n)
+ deprecated_attr("GLib", attr, "GLib.IOStatus." + n)
+ __all__.append(attr)
for n in ['CHILD_INHERITS_STDIN', 'DO_NOT_REAP_CHILD', 'FILE_AND_ARGV_ZERO',
'LEAVE_DESCRIPTORS_OPEN', 'SEARCH_PATH', 'STDERR_TO_DEV_NULL',
'STDOUT_TO_DEV_NULL']:
- globals()['SPAWN_' + n] = getattr(GLib.SpawnFlags, n)
- __all__.append('SPAWN_' + n)
+ attr = 'SPAWN_' + n
+ globals()[attr] = getattr(GLib.SpawnFlags, n)
+ deprecated_attr("GLib", attr, "GLib.SpawnFlags." + n)
+ __all__.append(attr)
for n in ['HIDDEN', 'IN_MAIN', 'REVERSE', 'NO_ARG', 'FILENAME', 'OPTIONAL_ARG',
'NOALIAS']:
- globals()['OPTION_FLAG_' + n] = getattr(GLib.OptionFlags, n)
- __all__.append('OPTION_FLAG_' + n)
+ attr = 'OPTION_FLAG_' + n
+ globals()[attr] = getattr(GLib.OptionFlags, n)
+ deprecated_attr("GLib", attr, "GLib.OptionFlags." + n)
+ __all__.append(attr)
for n in ['UNKNOWN_OPTION', 'BAD_VALUE', 'FAILED']:
- globals()['OPTION_ERROR_' + n] = getattr(GLib.OptionError, n)
- __all__.append('OPTION_ERROR_' + n)
+ attr = 'OPTION_ERROR_' + n
+ deprecated_attr("GLib", attr, "GLib.OptionError." + n)
+ globals()[attr] = getattr(GLib.OptionError, n)
+ __all__.append(attr)
+
+
+# these are not currently exported in GLib gir, presumably because they are
+# platform dependent; so get them from our static bindings
+for name in ['G_MINFLOAT', 'G_MAXFLOAT', 'G_MINDOUBLE', 'G_MAXDOUBLE',
+ 'G_MINSHORT', 'G_MAXSHORT', 'G_MAXUSHORT', 'G_MININT', 'G_MAXINT',
+ 'G_MAXUINT', 'G_MINLONG', 'G_MAXLONG', 'G_MAXULONG', 'G_MAXSIZE',
+ 'G_MINSSIZE', 'G_MAXSSIZE', 'G_MINOFFSET', 'G_MAXOFFSET']:
+ attr = name.split("_", 1)[-1]
+ globals()[attr] = getattr(_gi, name)
+ __all__.append(attr)
class MainLoop(GLib.MainLoop):
@@ -499,28 +488,14 @@ class MainLoop(GLib.MainLoop):
def __new__(cls, context=None):
return GLib.MainLoop.new(context, False)
- # Retain classic pygobject behaviour of quitting main loops on SIGINT
def __init__(self, context=None):
- def _handler(loop):
- loop.quit()
- loop._quit_by_sigint = True
- if sys.platform != 'win32':
- # compatibility shim, keep around until we depend on glib 2.36
- if hasattr(GLib, 'unix_signal_add'):
- fn = GLib.unix_signal_add
- else:
- fn = GLib.unix_signal_add_full
- self._signal_source = fn(GLib.PRIORITY_DEFAULT, signal.SIGINT, _handler, self)
-
- def __del__(self):
- if hasattr(self, '_signal_source'):
- GLib.source_remove(self._signal_source)
+ pass
def run(self):
- super(MainLoop, self).run()
- if hasattr(self, '_quit_by_sigint'):
- # caught by _main_loop_sigint_handler()
- raise KeyboardInterrupt
+ with register_sigint_fallback(self.quit):
+ with wakeup_on_signal():
+ super(MainLoop, self).run()
+
MainLoop = override(MainLoop)
__all__.append('MainLoop')
@@ -531,31 +506,34 @@ class MainContext(GLib.MainContext):
def iteration(self, may_block=True):
return super(MainContext, self).iteration(may_block)
+
MainContext = override(MainContext)
__all__.append('MainContext')
class Source(GLib.Source):
def __new__(cls, *args, **kwargs):
- # use our custom pyg_source_new() here as g_source_new() is not
+ # use our custom pygi_source_new() here as g_source_new() is not
# bindable
source = source_new()
source.__class__ = cls
setattr(source, '__pygi_custom_source', True)
return source
+ def __init__(self, *args, **kwargs):
+ return super(Source, self).__init__()
+
def __del__(self):
if hasattr(self, '__pygi_custom_source'):
- self.unref()
-
- # Backwards compatible API for optional arguments
- def attach(self, context=None):
- id = super(Source, self).attach(context)
- return id
+ self.destroy()
+ # XXX: We have to unref the underlying source while the Python
+ # wrapper is still valid, so the source can call into the
+ # wrapper methods for the finalized callback.
+ self._clear_boxed()
def set_callback(self, fn, user_data=None):
if hasattr(self, '__pygi_custom_source'):
- # use our custom pyg_source_set_callback() if for a GSource object
+ # use our custom pygi_source_set_callback() if for a GSource object
# with custom functions
source_set_callback(self, fn, user_data)
else:
@@ -586,6 +564,7 @@ class Source(GLib.Source):
can_recurse = property(__get_can_recurse, __set_can_recurse)
+
Source = override(Source)
__all__.append('Source')
@@ -601,6 +580,7 @@ class Idle(Source):
if priority != GLib.PRIORITY_DEFAULT:
self.set_priority(priority)
+
__all__.append('Idle')
@@ -614,63 +594,48 @@ class Timeout(Source):
if priority != GLib.PRIORITY_DEFAULT:
self.set_priority(priority)
-__all__.append('Timeout')
-
-def user_data_varargs_shim(callback, user_data, cb_num_args=0):
- '''Adjust callback and user_data varargs for PyGTK backwards compatibility
-
- GLib only accepts exactly one user_data argument, but older pygtk
- traditionally accepted zero or more for some specific functions. For "one
- argument", use the actual user-supplied callback for efficiency; for all
- others, rewire it to accept zero or more than one.
-
- Return the adjusted callback and the real user data to pass to GLib.
- '''
- if len(user_data) == 1:
- return (callback, user_data[0])
-
- if cb_num_args == 0:
- return (lambda data: callback(*data), user_data)
- if cb_num_args == 2:
- return (lambda a1, a2, data: callback(a1, a2, *data), user_data)
- raise NotImplementedError('%i number of callback arguments not supported' % cb_num_args)
+__all__.append('Timeout')
# backwards compatible API
def idle_add(function, *user_data, **kwargs):
- (fn, data) = user_data_varargs_shim(function, user_data)
priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT_IDLE)
- return GLib.idle_add(priority, fn, data)
+ return GLib.idle_add(priority, function, *user_data)
+
__all__.append('idle_add')
def timeout_add(interval, function, *user_data, **kwargs):
- (fn, data) = user_data_varargs_shim(function, user_data)
priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
- return GLib.timeout_add(priority, interval, fn, data)
+ return GLib.timeout_add(priority, interval, function, *user_data)
+
__all__.append('timeout_add')
def timeout_add_seconds(interval, function, *user_data, **kwargs):
- (fn, data) = user_data_varargs_shim(function, user_data)
priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
- return GLib.timeout_add_seconds(priority, interval, fn, data)
+ return GLib.timeout_add_seconds(priority, interval, function, *user_data)
+
__all__.append('timeout_add_seconds')
-# The real GLib API is io_add_watch(IOChannel, priority, condition, callback,
-# user_data). This needs to take into account several historical APIs:
+# The GI GLib API uses g_io_add_watch_full renamed to g_io_add_watch with
+# a signature of (channel, priority, condition, func, user_data).
+# Prior to PyGObject 3.8, this function was statically bound with an API closer to the
+# non-full version with a signature of: (fd, condition, func, *user_data)
+# We need to support this until we are okay with breaking API in a way which is
+# not backwards compatible.
+#
+# This needs to take into account several historical APIs:
# - calling with an fd as first argument
# - calling with a Python file object as first argument (we keep this one as
# it's really convenient and does not change the number of arguments)
# - calling without a priority as second argument
-# and the usual "call without or multiple user_data", in which case the
-# callback gets the same user data arguments.
-def io_add_watch(channel, priority_, condition, *cb_and_user_data, **kwargs):
+def _io_add_watch_get_args(channel, priority_, condition, *cb_and_user_data, **kwargs):
if not isinstance(priority_, int) or isinstance(priority_, GLib.IOCondition):
warnings.warn('Calling io_add_watch without priority as second argument is deprecated',
PyGIDeprecationWarning)
@@ -694,23 +659,33 @@ def io_add_watch(channel, priority_, condition, *cb_and_user_data, **kwargs):
callback = cb_and_user_data[0]
user_data = cb_and_user_data[1:]
- (func, user_data) = user_data_varargs_shim(callback, user_data, 2)
-
# backwards compatibility: Allow calling with fd
if isinstance(channel, int):
- func_fdtransform = lambda _, cond, data: func(channel, cond, data)
+ func_fdtransform = lambda _, cond, *data: callback(channel, cond, *data)
real_channel = GLib.IOChannel.unix_new(channel)
+ elif isinstance(channel, socket.socket) and sys.platform == 'win32':
+ func_fdtransform = lambda _, cond, *data: callback(channel, cond, *data)
+ real_channel = GLib.IOChannel.win32_new_socket(channel.fileno())
elif hasattr(channel, 'fileno'):
# backwards compatibility: Allow calling with Python file
- func_fdtransform = lambda _, cond, data: func(channel, cond, data)
+ func_fdtransform = lambda _, cond, *data: callback(channel, cond, *data)
real_channel = GLib.IOChannel.unix_new(channel.fileno())
else:
assert isinstance(channel, GLib.IOChannel)
- func_fdtransform = func
+ func_fdtransform = callback
real_channel = channel
- return GLib.io_add_watch(real_channel, priority_, condition,
- func_fdtransform, user_data)
+ return real_channel, priority_, condition, func_fdtransform, user_data
+
+
+__all__.append('_io_add_watch_get_args')
+
+
+def io_add_watch(*args, **kwargs):
+ """io_add_watch(channel, priority, condition, func, *user_data) -> event_source_id"""
+ channel, priority, condition, func, user_data = _io_add_watch_get_args(*args, **kwargs)
+ return GLib.io_add_watch(channel, priority, condition, func, *user_data)
+
__all__.append('io_add_watch')
@@ -726,6 +701,9 @@ class IOChannel(GLib.IOChannel):
return GLib.IOChannel.win32_new_fd(hwnd)
raise TypeError('either a valid file descriptor, file name, or window handle must be supplied')
+ def __init__(self, *args, **kwargs):
+ return super(IOChannel, self).__init__()
+
def read(self, max_count=-1):
return io_channel_read(self, max_count)
@@ -790,6 +768,7 @@ class IOChannel(GLib.IOChannel):
# Python 2.x compatibility
next = __next__
+
IOChannel = override(IOChannel)
__all__.append('IOChannel')
@@ -804,18 +783,19 @@ class PollFD(GLib.PollFD):
self.fd = fd
self.events = events
+
PollFD = override(PollFD)
__all__.append('PollFD')
-# The real GLib API is child_watch_add(priority, pid, callback, data).
-# The old static bindings had the following API which we still need to support
-# for a while:
-# child_watch_add(pid, callback, data=None, priority=GLib.PRIORITY_DEFAULT)
-# and the usual "call without user_data", in which case the callback does not
-# get an user_data either.
-def child_watch_add(priority_or_pid, pid_or_callback, *args, **kwargs):
- _unspecified = object()
+# The GI GLib API uses g_child_watch_add_full renamed to g_child_watch_add with
+# a signature of (priority, pid, callback, data).
+# Prior to PyGObject 3.8, this function was statically bound with an API closer to the
+# non-full version with a signature of: (pid, callback, data=None, priority=GLib.PRIORITY_DEFAULT)
+# We need to support this until we are okay with breaking API in a way which is
+# not backwards compatible.
+def _child_watch_add_get_args(priority_or_pid, pid_or_callback, *args, **kwargs):
+ user_data = []
if callable(pid_or_callback):
warnings.warn('Calling child_watch_add without priority as first argument is deprecated',
@@ -823,35 +803,44 @@ def child_watch_add(priority_or_pid, pid_or_callback, *args, **kwargs):
pid = priority_or_pid
callback = pid_or_callback
if len(args) == 0:
- user_data = kwargs.get('data', _unspecified)
priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
elif len(args) == 1:
- user_data = args[0]
+ user_data = args
priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
elif len(args) == 2:
- user_data = args[0]
+ user_data = [args[0]]
priority = args[1]
else:
raise TypeError('expected at most 4 positional arguments')
else:
priority = priority_or_pid
pid = pid_or_callback
- if len(args) == 0 or not callable(args[0]):
- raise TypeError('expected callback as third argument')
- callback = args[0]
- if len(args) == 1:
- user_data = kwargs.get('data', _unspecified)
+ if 'function' in kwargs:
+ callback = kwargs['function']
+ user_data = args
+ elif len(args) > 0 and callable(args[0]):
+ callback = args[0]
+ user_data = args[1:]
else:
- user_data = args[1]
+ raise TypeError('expected callback as third argument')
+
+ if 'data' in kwargs:
+ if user_data:
+ raise TypeError('got multiple values for "data" argument')
+ user_data = (kwargs['data'],)
+
+ return priority, pid, callback, user_data
- if user_data is _unspecified:
- # we have to call the callback without the user_data argument
- func = lambda pid, status, data: callback(pid, status)
- user_data = None
- else:
- func = callback
- return GLib.child_watch_add(priority, pid, func, user_data)
+# we need this to be accessible for unit testing
+__all__.append('_child_watch_add_get_args')
+
+
+def child_watch_add(*args, **kwargs):
+ """child_watch_add(priority, pid, function, *data)"""
+ priority, pid, function, data = _child_watch_add_get_args(*args, **kwargs)
+ return GLib.child_watch_add(priority, pid, function, *data)
+
__all__.append('child_watch_add')
@@ -859,6 +848,7 @@ __all__.append('child_watch_add')
def get_current_time():
return GLib.get_real_time() * 0.000001
+
get_current_time = deprecated(get_current_time, 'GLib.get_real_time()')
__all__.append('get_current_time')
@@ -869,21 +859,22 @@ __all__.append('get_current_time')
def filename_from_utf8(utf8string, len=-1):
return GLib.filename_from_utf8(utf8string, len)[0]
-__all__.append('filename_from_utf8')
+__all__.append('filename_from_utf8')
-# backwards compatible API for renamed function
-if not hasattr(GLib, 'unix_signal_add_full'):
- def add_full_compat(*args):
- warnings.warn('GLib.unix_signal_add_full() was renamed to GLib.unix_signal_add()',
- PyGIDeprecationWarning)
- return GLib.unix_signal_add(*args)
- GLib.unix_signal_add_full = add_full_compat
+if hasattr(GLib, "unix_signal_add"):
+ unix_signal_add_full = GLib.unix_signal_add
+ __all__.append('unix_signal_add_full')
+ deprecated_attr("GLib", "unix_signal_add_full", "GLib.unix_signal_add")
# obsolete constants for backwards compatibility
glib_version = (GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION)
__all__.append('glib_version')
+deprecated_attr("GLib", "glib_version",
+ "(GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION)")
+
pyglib_version = version_info
__all__.append('pyglib_version')
+deprecated_attr("GLib", "pyglib_version", "gi.version_info")
diff --git a/gi/overrides/GObject.py b/gi/overrides/GObject.py
index b3aad47..823c0b0 100644
--- a/gi/overrides/GObject.py
+++ b/gi/overrides/GObject.py
@@ -21,28 +21,26 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-import sys
-import warnings
import functools
+import warnings
from collections import namedtuple
-import gi.overrides
import gi.module
-from gi.overrides import override
+from gi.overrides import override, deprecated_attr
from gi.repository import GLib
from gi import PyGIDeprecationWarning
+from gi import _propertyhelper as propertyhelper
+from gi import _signalhelper as signalhelper
+from gi import _gi
-from gi._gobject import _gobject
-from gi._gobject import propertyhelper
-from gi._gobject import signalhelper
GObjectModule = gi.module.get_introspection_module('GObject')
__all__ = []
-from gi._glib import option
-sys.modules['gi._gobject.option'] = option
+from gi import _option as option
+option = option
# API aliases for backwards compatibility
@@ -56,10 +54,11 @@ for name in ['markup_escape_text', 'get_application_name',
'idle_add', 'timeout_add', 'timeout_add_seconds',
'io_add_watch', 'child_watch_add', 'get_current_time',
'spawn_async']:
- globals()[name] = gi.overrides.deprecated(getattr(GLib, name), 'GLib.' + name)
+ globals()[name] = getattr(GLib, name)
+ deprecated_attr("GObject", name, "GLib." + name)
__all__.append(name)
-# constants are also deprecated, but cannot mark them as such
+# deprecated constants
for name in ['PRIORITY_DEFAULT', 'PRIORITY_DEFAULT_IDLE', 'PRIORITY_HIGH',
'PRIORITY_HIGH_IDLE', 'PRIORITY_LOW',
'IO_IN', 'IO_OUT', 'IO_PRI', 'IO_ERR', 'IO_HUP', 'IO_NVAL',
@@ -77,25 +76,21 @@ for name in ['PRIORITY_DEFAULT', 'PRIORITY_DEFAULT_IDLE', 'PRIORITY_HIGH',
'OPTION_FLAG_NOALIAS', 'OPTION_ERROR_UNKNOWN_OPTION',
'OPTION_ERROR_BAD_VALUE', 'OPTION_ERROR_FAILED', 'OPTION_REMAINING',
'glib_version']:
- globals()[name] = getattr(GLib, name)
+ with warnings.catch_warnings():
+ # TODO: this uses deprecated Glib attributes, silence for now
+ warnings.simplefilter('ignore', PyGIDeprecationWarning)
+ globals()[name] = getattr(GLib, name)
+ deprecated_attr("GObject", name, "GLib." + name)
__all__.append(name)
-G_MININT8 = GLib.MININT8
-G_MAXINT8 = GLib.MAXINT8
-G_MAXUINT8 = GLib.MAXUINT8
-G_MININT16 = GLib.MININT16
-G_MAXINT16 = GLib.MAXINT16
-G_MAXUINT16 = GLib.MAXUINT16
-G_MININT32 = GLib.MININT32
-G_MAXINT32 = GLib.MAXINT32
-G_MAXUINT32 = GLib.MAXUINT32
-G_MININT64 = GLib.MININT64
-G_MAXINT64 = GLib.MAXINT64
-G_MAXUINT64 = GLib.MAXUINT64
-__all__ += ['G_MININT8', 'G_MAXINT8', 'G_MAXUINT8', 'G_MININT16',
- 'G_MAXINT16', 'G_MAXUINT16', 'G_MININT32', 'G_MAXINT32',
- 'G_MAXUINT32', 'G_MININT64', 'G_MAXINT64', 'G_MAXUINT64']
+for name in ['G_MININT8', 'G_MAXINT8', 'G_MAXUINT8', 'G_MININT16',
+ 'G_MAXINT16', 'G_MAXUINT16', 'G_MININT32', 'G_MAXINT32',
+ 'G_MAXUINT32', 'G_MININT64', 'G_MAXINT64', 'G_MAXUINT64']:
+ new_name = name.split("_", 1)[-1]
+ globals()[name] = getattr(GLib, new_name)
+ deprecated_attr("GObject", name, "GLib." + new_name)
+ __all__.append(name)
# these are not currently exported in GLib gir, presumably because they are
# platform dependent; so get them from our static bindings
@@ -103,7 +98,9 @@ for name in ['G_MINFLOAT', 'G_MAXFLOAT', 'G_MINDOUBLE', 'G_MAXDOUBLE',
'G_MINSHORT', 'G_MAXSHORT', 'G_MAXUSHORT', 'G_MININT', 'G_MAXINT',
'G_MAXUINT', 'G_MINLONG', 'G_MAXLONG', 'G_MAXULONG', 'G_MAXSIZE',
'G_MINSSIZE', 'G_MAXSSIZE', 'G_MINOFFSET', 'G_MAXOFFSET']:
- globals()[name] = getattr(_gobject, name)
+ new_name = name.split("_", 1)[-1]
+ globals()[name] = getattr(GLib, new_name)
+ deprecated_attr("GObject", name, "GLib." + new_name)
__all__.append(name)
@@ -145,69 +142,64 @@ __all__ += ['TYPE_INVALID', 'TYPE_NONE', 'TYPE_INTERFACE', 'TYPE_CHAR',
# Deprecated, use GLib directly
-Pid = GLib.Pid
-GError = GLib.GError
-OptionGroup = GLib.OptionGroup
-OptionContext = GLib.OptionContext
-__all__ += ['Pid', 'GError', 'OptionGroup', 'OptionContext']
+for name in ['Pid', 'GError', 'OptionGroup', 'OptionContext']:
+ globals()[name] = getattr(GLib, name)
+ deprecated_attr("GObject", name, "GLib." + name)
+ __all__.append(name)
# Deprecated, use: GObject.ParamFlags.* directly
-PARAM_CONSTRUCT = GObjectModule.ParamFlags.CONSTRUCT
-PARAM_CONSTRUCT_ONLY = GObjectModule.ParamFlags.CONSTRUCT_ONLY
-PARAM_LAX_VALIDATION = GObjectModule.ParamFlags.LAX_VALIDATION
-PARAM_READABLE = GObjectModule.ParamFlags.READABLE
-PARAM_WRITABLE = GObjectModule.ParamFlags.WRITABLE
+for name in ['PARAM_CONSTRUCT', 'PARAM_CONSTRUCT_ONLY', 'PARAM_LAX_VALIDATION',
+ 'PARAM_READABLE', 'PARAM_WRITABLE']:
+ new_name = name.split("_", 1)[-1]
+ globals()[name] = getattr(GObjectModule.ParamFlags, new_name)
+ deprecated_attr("GObject", name, "GObject.ParamFlags." + new_name)
+ __all__.append(name)
+
# PARAM_READWRITE should come from the gi module but cannot due to:
-# https://bugzilla.gnome.org/show_bug.cgi?id=687615
-PARAM_READWRITE = PARAM_READABLE | PARAM_WRITABLE
-__all__ += ['PARAM_CONSTRUCT', 'PARAM_CONSTRUCT_ONLY', 'PARAM_LAX_VALIDATION',
- 'PARAM_READABLE', 'PARAM_WRITABLE', 'PARAM_READWRITE']
+# https://gitlab.gnome.org/GNOME/gobject-introspection/issues/75
+PARAM_READWRITE = GObjectModule.ParamFlags.READABLE | \
+ GObjectModule.ParamFlags.WRITABLE
+deprecated_attr("GObject", "PARAM_READWRITE", "GObject.ParamFlags.READWRITE")
+__all__.append("PARAM_READWRITE")
# Deprecated, use: GObject.SignalFlags.* directly
-SIGNAL_ACTION = GObjectModule.SignalFlags.ACTION
-SIGNAL_DETAILED = GObjectModule.SignalFlags.DETAILED
-SIGNAL_NO_HOOKS = GObjectModule.SignalFlags.NO_HOOKS
-SIGNAL_NO_RECURSE = GObjectModule.SignalFlags.NO_RECURSE
-SIGNAL_RUN_CLEANUP = GObjectModule.SignalFlags.RUN_CLEANUP
-SIGNAL_RUN_FIRST = GObjectModule.SignalFlags.RUN_FIRST
-SIGNAL_RUN_LAST = GObjectModule.SignalFlags.RUN_LAST
-__all__ += ['SIGNAL_ACTION', 'SIGNAL_DETAILED', 'SIGNAL_NO_HOOKS',
- 'SIGNAL_NO_RECURSE', 'SIGNAL_RUN_CLEANUP', 'SIGNAL_RUN_FIRST',
- 'SIGNAL_RUN_LAST']
-
+for name in ['SIGNAL_ACTION', 'SIGNAL_DETAILED', 'SIGNAL_NO_HOOKS',
+ 'SIGNAL_NO_RECURSE', 'SIGNAL_RUN_CLEANUP', 'SIGNAL_RUN_FIRST',
+ 'SIGNAL_RUN_LAST']:
+ new_name = name.split("_", 1)[-1]
+ globals()[name] = getattr(GObjectModule.SignalFlags, new_name)
+ deprecated_attr("GObject", name, "GObject.SignalFlags." + new_name)
+ __all__.append(name)
# Static types
-GBoxed = _gobject.GBoxed
-GEnum = _gobject.GEnum
-GFlags = _gobject.GFlags
-GInterface = _gobject.GInterface
-GObject = _gobject.GObject
-GObjectWeakRef = _gobject.GObjectWeakRef
-GParamSpec = _gobject.GParamSpec
-GPointer = _gobject.GPointer
-GType = _gobject.GType
-Warning = _gobject.Warning
+GBoxed = _gi.GBoxed
+GEnum = _gi.GEnum
+GFlags = _gi.GFlags
+GInterface = _gi.GInterface
+GObject = _gi.GObject
+GObjectWeakRef = _gi.GObjectWeakRef
+GParamSpec = _gi.GParamSpec
+GPointer = _gi.GPointer
+GType = _gi.GType
+Warning = _gi.Warning
__all__ += ['GBoxed', 'GEnum', 'GFlags', 'GInterface', 'GObject',
'GObjectWeakRef', 'GParamSpec', 'GPointer', 'GType',
'Warning']
-features = _gobject.features
-list_properties = _gobject.list_properties
-new = _gobject.new
-pygobject_version = _gobject.pygobject_version
+features = {'generic-c-marshaller': True}
+list_properties = _gi.list_properties
+new = _gi.new
+pygobject_version = _gi.pygobject_version
threads_init = GLib.threads_init
-type_register = _gobject.type_register
+type_register = _gi.type_register
__all__ += ['features', 'list_properties', 'new',
'pygobject_version', 'threads_init', 'type_register']
class Value(GObjectModule.Value):
- def __new__(cls, *args, **kwargs):
- return GObjectModule.Value.__new__(cls)
-
def __init__(self, value_type=None, py_value=None):
GObjectModule.Value.__init__(self)
if value_type is not None:
@@ -215,136 +207,91 @@ class Value(GObjectModule.Value):
if py_value is not None:
self.set_value(py_value)
- def __del__(self):
- if self._free_on_dealloc and self.g_type != TYPE_INVALID:
- self.unset()
+ @property
+ def __g_type(self):
+ # XXX: This is the same as self.g_type, but the field marshalling
+ # code is currently very slow.
+ return _gi._gvalue_get_type(self)
def set_boxed(self, boxed):
+ if not self.__g_type.is_a(TYPE_BOXED):
+ warnings.warn('Calling set_boxed() on a non-boxed type deprecated',
+ PyGIDeprecationWarning, stacklevel=2)
# Workaround the introspection marshalers inability to know
# these methods should be marshaling boxed types. This is because
# the type information is stored on the GValue.
- _gobject._gvalue_set(self, boxed)
+ _gi._gvalue_set(self, boxed)
def get_boxed(self):
- return _gobject._gvalue_get(self)
+ if not self.__g_type.is_a(TYPE_BOXED):
+ warnings.warn('Calling get_boxed() on a non-boxed type deprecated',
+ PyGIDeprecationWarning, stacklevel=2)
+ return _gi._gvalue_get(self)
def set_value(self, py_value):
- gtype = self.g_type
+ gtype = self.__g_type
- if gtype == _gobject.TYPE_INVALID:
- raise TypeError("GObject.Value needs to be initialized first")
- elif gtype == TYPE_BOOLEAN:
- self.set_boolean(py_value)
- elif gtype == TYPE_CHAR:
+ if gtype == TYPE_CHAR:
self.set_char(py_value)
elif gtype == TYPE_UCHAR:
self.set_uchar(py_value)
- elif gtype == TYPE_INT:
- self.set_int(py_value)
- elif gtype == TYPE_UINT:
- self.set_uint(py_value)
- elif gtype == TYPE_LONG:
- self.set_long(py_value)
- elif gtype == TYPE_ULONG:
- self.set_ulong(py_value)
- elif gtype == TYPE_INT64:
- self.set_int64(py_value)
- elif gtype == TYPE_UINT64:
- self.set_uint64(py_value)
- elif gtype == TYPE_FLOAT:
- self.set_float(py_value)
- elif gtype == TYPE_DOUBLE:
- self.set_double(py_value)
elif gtype == TYPE_STRING:
- if isinstance(py_value, str):
- py_value = str(py_value)
- elif sys.version_info < (3, 0):
- if isinstance(py_value, unicode):
- py_value = py_value.encode('UTF-8')
- else:
- raise ValueError("Expected string or unicode but got %s%s" %
- (py_value, type(py_value)))
- else:
- raise ValueError("Expected string but got %s%s" %
- (py_value, type(py_value)))
- self.set_string(py_value)
+ if not isinstance(py_value, str) and py_value is not None:
+ raise TypeError("Expected string but got %s%s" %
+ (py_value, type(py_value)))
+ _gi._gvalue_set(self, py_value)
elif gtype == TYPE_PARAM:
self.set_param(py_value)
- elif gtype.is_a(TYPE_ENUM):
- self.set_enum(py_value)
elif gtype.is_a(TYPE_FLAGS):
self.set_flags(py_value)
- elif gtype.is_a(TYPE_BOXED):
- self.set_boxed(py_value)
elif gtype == TYPE_POINTER:
self.set_pointer(py_value)
- elif gtype.is_a(TYPE_OBJECT):
- self.set_object(py_value)
- elif gtype == TYPE_UNICHAR:
- self.set_uint(int(py_value))
- # elif gtype == TYPE_OVERRIDE:
- # pass
elif gtype == TYPE_GTYPE:
self.set_gtype(py_value)
elif gtype == TYPE_VARIANT:
self.set_variant(py_value)
- elif gtype == TYPE_PYOBJECT:
- self.set_boxed(py_value)
else:
- raise TypeError("Unknown value type %s" % gtype)
+ # Fall back to _gvalue_set which handles some more cases
+ # like fundamentals for which a converter is registered
+ try:
+ _gi._gvalue_set(self, py_value)
+ except TypeError:
+ if gtype == TYPE_INVALID:
+ raise TypeError("GObject.Value needs to be initialized first")
+ raise
def get_value(self):
- gtype = self.g_type
+ gtype = self.__g_type
- if gtype == TYPE_BOOLEAN:
- return self.get_boolean()
- elif gtype == TYPE_CHAR:
+ if gtype == TYPE_CHAR:
return self.get_char()
elif gtype == TYPE_UCHAR:
return self.get_uchar()
- elif gtype == TYPE_INT:
- return self.get_int()
- elif gtype == TYPE_UINT:
- return self.get_uint()
- elif gtype == TYPE_LONG:
- return self.get_long()
- elif gtype == TYPE_ULONG:
- return self.get_ulong()
- elif gtype == TYPE_INT64:
- return self.get_int64()
- elif gtype == TYPE_UINT64:
- return self.get_uint64()
- elif gtype == TYPE_FLOAT:
- return self.get_float()
- elif gtype == TYPE_DOUBLE:
- return self.get_double()
- elif gtype == TYPE_STRING:
- return self.get_string()
elif gtype == TYPE_PARAM:
return self.get_param()
elif gtype.is_a(TYPE_ENUM):
return self.get_enum()
elif gtype.is_a(TYPE_FLAGS):
return self.get_flags()
- elif gtype.is_a(TYPE_BOXED):
- return self.get_boxed()
elif gtype == TYPE_POINTER:
return self.get_pointer()
- elif gtype.is_a(TYPE_OBJECT):
- return self.get_object()
- elif gtype == TYPE_UNICHAR:
- return self.get_uint()
elif gtype == TYPE_GTYPE:
return self.get_gtype()
elif gtype == TYPE_VARIANT:
- return self.get_variant()
- elif gtype == TYPE_PYOBJECT:
- pass
+ # get_variant was missing annotations
+ # https://gitlab.gnome.org/GNOME/glib/merge_requests/492
+ return self.dup_variant()
else:
- return None
+ try:
+ return _gi._gvalue_get(self)
+ except TypeError:
+ if gtype == TYPE_INVALID:
+ return None
+ raise
def __repr__(self):
- return '<Value (%s) %s>' % (self.g_type.name, self.get_value())
+ return '<Value (%s) %s>' % (self.__g_type.name, self.get_value())
+
Value = override(Value)
__all__.append('Value')
@@ -356,6 +303,7 @@ def type_from_name(name):
raise RuntimeError('unknown type name: %s' % name)
return type_
+
__all__.append('type_from_name')
@@ -365,6 +313,7 @@ def type_parent(type_):
raise RuntimeError('no parent for type')
return parent
+
__all__.append('type_parent')
@@ -379,6 +328,7 @@ def signal_list_ids(type_):
_validate_type_for_signal_method(type_)
return GObjectModule.signal_list_ids(type_)
+
__all__.append('signal_list_ids')
@@ -386,6 +336,7 @@ def signal_list_names(type_):
ids = signal_list_ids(type_)
return tuple(GObjectModule.signal_name(i) for i in ids)
+
__all__.append('signal_list_names')
@@ -393,51 +344,40 @@ def signal_lookup(name, type_):
_validate_type_for_signal_method(type_)
return GObjectModule.signal_lookup(name, type_)
+
__all__.append('signal_lookup')
+SignalQuery = namedtuple('SignalQuery',
+ ['signal_id',
+ 'signal_name',
+ 'itype',
+ 'signal_flags',
+ 'return_type',
+ # n_params',
+ 'param_types'])
+
+
def signal_query(id_or_name, type_=None):
- SignalQuery = namedtuple('SignalQuery',
- ['signal_id',
- 'signal_name',
- 'itype',
- 'signal_flags',
- 'return_type',
- # n_params',
- 'param_types'])
-
- # signal_query needs to use a static method until the following bugs are fixed:
- # https://bugzilla.gnome.org/show_bug.cgi?id=687550
- # https://bugzilla.gnome.org/show_bug.cgi?id=687545
- # https://bugzilla.gnome.org/show_bug.cgi?id=687541
if type_ is not None:
id_or_name = signal_lookup(id_or_name, type_)
- res = _gobject.signal_query(id_or_name)
- if res is None:
- return None
-
- # Return a named tuple which allows indexing like the static bindings
- # along with field like access of the gi struct.
- # Note however that the n_params was not returned from the static bindings.
- return SignalQuery(*res)
-
-__all__.append('signal_query')
+ res = GObjectModule.signal_query(id_or_name)
+ assert res is not None
+ if res.signal_id == 0:
+ return None
-# Check needed for glib versions which annotate signal related methods
-# with a void pointer instead of GObject.Object.
-# See: https://bugzilla.gnome.org/show_bug.cgi?id=685387
-_is_first_signal_arg_void = GObjectModule.signal_stop_emission.get_arguments()[0].get_pytype_hint() == 'void'
+ # Return a named tuple to allows indexing which is compatible with the
+ # static bindings along with field like access of the gi struct.
+ # Note however that the n_params was not returned from the static bindings
+ # so we must skip over it.
+ return SignalQuery(res.signal_id, res.signal_name, res.itype,
+ res.signal_flags, res.return_type,
+ tuple(res.param_types))
-def _get_instance_for_signal(obj):
- if not _is_first_signal_arg_void:
- return obj
- elif isinstance(obj, GObjectModule.Object):
- return obj.__gpointer__
- else:
- raise TypeError('Unsupported object "%s" for signal function' % obj)
+__all__.append('signal_query')
class _HandlerBlockManager(object):
@@ -449,75 +389,43 @@ class _HandlerBlockManager(object):
pass
def __exit__(self, exc_type, exc_value, traceback):
- signal_handler_unblock(self.obj, self.handler_id)
+ GObjectModule.signal_handler_unblock(self.obj, self.handler_id)
def signal_handler_block(obj, handler_id):
- """Blocks the signal handler from being invoked until handler_unblock() is called.
+ """Blocks the signal handler from being invoked until
+ handler_unblock() is called.
- Returns a context manager which optionally can be used to
- automatically unblock the handler:
+ :param GObject.Object obj:
+ Object instance to block handlers for.
+ :param int handler_id:
+ Id of signal to block.
+ :returns:
+ A context manager which optionally can be used to
+ automatically unblock the handler:
- with GObject.signal_handler_block(obj, id):
- pass
+ .. code-block:: python
+
+ with GObject.signal_handler_block(obj, id):
+ pass
"""
- GObjectModule.signal_handler_block(_get_instance_for_signal(obj), handler_id)
+ GObjectModule.signal_handler_block(obj, handler_id)
return _HandlerBlockManager(obj, handler_id)
-__all__.append('signal_handler_block')
-
-if _is_first_signal_arg_void:
- # The following functions wrap GI functions but coerce the first arg into
- # something compatible with gpointer
-
- def _wrap_signal_func(func):
- @functools.wraps(func)
- def wrapper(obj, *args, **kwargs):
- return func(_get_instance_for_signal(obj), *args, **kwargs)
- return wrapper
-
- signal_handler_unblock = _wrap_signal_func(GObjectModule.signal_handler_unblock)
- signal_handler_disconnect = _wrap_signal_func(GObjectModule.signal_handler_disconnect)
- signal_handler_is_connected = _wrap_signal_func(GObjectModule.signal_handler_is_connected)
- signal_stop_emission = _wrap_signal_func(GObjectModule.signal_stop_emission)
- signal_stop_emission_by_name = _wrap_signal_func(GObjectModule.signal_stop_emission_by_name)
- signal_has_handler_pending = _wrap_signal_func(GObjectModule.signal_has_handler_pending)
- signal_get_invocation_hint = _wrap_signal_func(GObjectModule.signal_get_invocation_hint)
- signal_connect_closure = _wrap_signal_func(GObjectModule.signal_connect_closure)
- signal_connect_closure_by_id = _wrap_signal_func(GObjectModule.signal_connect_closure_by_id)
- signal_handler_find = _wrap_signal_func(GObjectModule.signal_handler_find)
- signal_handlers_destroy = _wrap_signal_func(GObjectModule.signal_handlers_destroy)
- signal_handlers_block_matched = _wrap_signal_func(GObjectModule.signal_handlers_block_matched)
- signal_handlers_unblock_matched = _wrap_signal_func(GObjectModule.signal_handlers_unblock_matched)
- signal_handlers_disconnect_matched = _wrap_signal_func(GObjectModule.signal_handlers_disconnect_matched)
-
- __all__ += ['signal_handler_unblock',
- 'signal_handler_disconnect', 'signal_handler_is_connected',
- 'signal_stop_emission', 'signal_stop_emission_by_name',
- 'signal_has_handler_pending', 'signal_get_invocation_hint',
- 'signal_connect_closure', 'signal_connect_closure_by_id',
- 'signal_handler_find', 'signal_handlers_destroy',
- 'signal_handlers_block_matched', 'signal_handlers_unblock_matched',
- 'signal_handlers_disconnect_matched']
-else:
- # First signal arg is GObject.Object but we need these as globals for
- # our GObject.Object class override below
- signal_handler_disconnect = GObjectModule.signal_handler_disconnect
- signal_handler_unblock = GObjectModule.signal_handler_unblock
- signal_handler_disconnect = GObjectModule.signal_handler_disconnect
- signal_handler_is_connected = GObjectModule.signal_handler_is_connected
- signal_stop_emission_by_name = GObjectModule.signal_stop_emission_by_name
+__all__.append('signal_handler_block')
def signal_parse_name(detailed_signal, itype, force_detail_quark):
"""Parse a detailed signal name into (signal_id, detail).
- :Raises ValueError:
- If the given signal is unknown.
-
- :Returns:
+ :param str detailed_signal:
+ Signal name which can include detail.
+ For example: "notify:prop_name"
+ :returns:
Tuple of (signal_id, detail)
+ :raises ValueError:
+ If the given signal is unknown.
"""
res, signal_id, detail = GObjectModule.signal_parse_name(detailed_signal, itype,
force_detail_quark)
@@ -526,6 +434,7 @@ def signal_parse_name(detailed_signal, itype, force_detail_quark):
else:
raise ValueError('%s: unknown signal name: %s' % (itype, detailed_signal))
+
__all__.append('signal_parse_name')
@@ -533,6 +442,7 @@ def remove_emission_hook(obj, detailed_signal, hook_id):
signal_id, detail = signal_parse_name(detailed_signal, obj, True)
GObjectModule.signal_remove_emission_hook(signal_id, hook_id)
+
__all__.append('remove_emission_hook')
@@ -543,6 +453,7 @@ def signal_accumulator_first_wins(ihint, return_accu, handler_return, user_data=
# Stop emission but return the result of the last handler
return (False, handler_return)
+
__all__.append('signal_accumulator_first_wins')
@@ -550,13 +461,14 @@ def signal_accumulator_true_handled(ihint, return_accu, handler_return, user_dat
# Stop emission if the last handler returns True
return (not handler_return, handler_return)
+
__all__.append('signal_accumulator_true_handled')
# Statically bound signal functions which need to clobber GI (for now)
-add_emission_hook = _gobject.add_emission_hook
-signal_new = _gobject.signal_new
+add_emission_hook = _gi.add_emission_hook
+signal_new = _gi.signal_new
__all__ += ['add_emission_hook', 'signal_new']
@@ -608,7 +520,6 @@ class Object(GObjectModule.Object):
interface_install_property = _unsupported_method
interface_list_properties = _unsupported_method
notify_by_pspec = _unsupported_method
- run_dispose = _unsupported_method
watch_closure = _unsupported_method
# Make all reference management methods private but still accessible.
@@ -624,49 +535,89 @@ class Object(GObjectModule.Object):
# The following methods are static APIs which need to leap frog the
# gi methods until we verify the gi methods can replace them.
- get_property = _gobject.GObject.get_property
- get_properties = _gobject.GObject.get_properties
- set_property = _gobject.GObject.set_property
- set_properties = _gobject.GObject.set_properties
- bind_property = _gobject.GObject.bind_property
- connect = _gobject.GObject.connect
- connect_after = _gobject.GObject.connect_after
- connect_object = _gobject.GObject.connect_object
- connect_object_after = _gobject.GObject.connect_object_after
- disconnect_by_func = _gobject.GObject.disconnect_by_func
- handler_block_by_func = _gobject.GObject.handler_block_by_func
- handler_unblock_by_func = _gobject.GObject.handler_unblock_by_func
- emit = _gobject.GObject.emit
- chain = _gobject.GObject.chain
- weak_ref = _gobject.GObject.weak_ref
- __copy__ = _gobject.GObject.__copy__
- __deepcopy__ = _gobject.GObject.__deepcopy__
+ get_property = _gi.GObject.get_property
+ get_properties = _gi.GObject.get_properties
+ set_property = _gi.GObject.set_property
+ set_properties = _gi.GObject.set_properties
+ bind_property = _gi.GObject.bind_property
+ connect = _gi.GObject.connect
+ connect_after = _gi.GObject.connect_after
+ connect_object = _gi.GObject.connect_object
+ connect_object_after = _gi.GObject.connect_object_after
+ disconnect_by_func = _gi.GObject.disconnect_by_func
+ handler_block_by_func = _gi.GObject.handler_block_by_func
+ handler_unblock_by_func = _gi.GObject.handler_unblock_by_func
+ emit = _gi.GObject.emit
+ chain = _gi.GObject.chain
+ weak_ref = _gi.GObject.weak_ref
+ __copy__ = _gi.GObject.__copy__
+ __deepcopy__ = _gi.GObject.__deepcopy__
def freeze_notify(self):
"""Freezes the object's property-changed notification queue.
+ :returns:
+ A context manager which optionally can be used to
+ automatically thaw notifications.
+
This will freeze the object so that "notify" signals are blocked until
the thaw_notify() method is called.
- Returns a context manager which optionally can be used to
- automatically thaw notifications:
+ .. code-block:: python
- with obj.freeze_notify():
- pass
+ with obj.freeze_notify():
+ pass
"""
super(Object, self).freeze_notify()
return _FreezeNotifyManager(self)
+ def connect_data(self, detailed_signal, handler, *data, **kwargs):
+ """Connect a callback to the given signal with optional user data.
+
+ :param str detailed_signal:
+ A detailed signal to connect to.
+ :param callable handler:
+ Callback handler to connect to the signal.
+ :param *data:
+ Variable data which is passed through to the signal handler.
+ :param GObject.ConnectFlags connect_flags:
+ Flags used for connection options.
+ :returns:
+ A signal id which can be used with disconnect.
+ """
+ flags = kwargs.get('connect_flags', 0)
+ if flags & GObjectModule.ConnectFlags.AFTER:
+ connect_func = _gi.GObject.connect_after
+ else:
+ connect_func = _gi.GObject.connect
+
+ if flags & GObjectModule.ConnectFlags.SWAPPED:
+ if len(data) != 1:
+ raise ValueError('Using GObject.ConnectFlags.SWAPPED requires exactly '
+ 'one argument for user data, got: %s' % [data])
+
+ def new_handler(obj, *args):
+ # Swap obj with the last element in args which will be the user
+ # data passed to the connect function.
+ args = list(args)
+ swap = args.pop()
+ args = args + [obj]
+ return handler(swap, *args)
+ else:
+ new_handler = handler
+
+ return connect_func(self, detailed_signal, new_handler, *data)
+
#
# Aliases
#
- disconnect = _signalmethod(signal_handler_disconnect)
- handler_block = _signalmethod(signal_handler_block)
- handler_unblock = _signalmethod(signal_handler_unblock)
- handler_disconnect = _signalmethod(signal_handler_disconnect)
- handler_is_connected = _signalmethod(signal_handler_is_connected)
- stop_emission_by_name = _signalmethod(signal_stop_emission_by_name)
+ handler_block = signal_handler_block
+ handler_unblock = _signalmethod(GObjectModule.signal_handler_unblock)
+ disconnect = _signalmethod(GObjectModule.signal_handler_disconnect)
+ handler_disconnect = _signalmethod(GObjectModule.signal_handler_disconnect)
+ handler_is_connected = _signalmethod(GObjectModule.signal_handler_is_connected)
+ stop_emission_by_name = _signalmethod(GObjectModule.signal_stop_emission_by_name)
#
# Deprecated Methods
@@ -675,7 +626,7 @@ class Object(GObjectModule.Object):
def stop_emission(self, detailed_signal):
"""Deprecated, please use stop_emission_by_name."""
warnings.warn(self.stop_emission.__doc__, PyGIDeprecationWarning, stacklevel=2)
- return signal_stop_emission_by_name(self, detailed_signal)
+ return self.stop_emission_by_name(detailed_signal)
emit_stop_by_name = stop_emission
@@ -685,10 +636,34 @@ GObject = Object
__all__ += ['Object', 'GObject']
+class Binding(GObjectModule.Binding):
+ def __call__(self):
+ warnings.warn('Using parentheses (binding()) to retrieve the Binding object is no '
+ 'longer needed because the binding is returned directly from "bind_property.',
+ PyGIDeprecationWarning, stacklevel=2)
+ return self
+
+ def unbind(self):
+ # Fixed in newer glib
+ if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION) >= (2, 57, 3):
+ return super(Binding, self).unbind()
+
+ if hasattr(self, '_unbound'):
+ raise ValueError('binding has already been cleared out')
+ else:
+ setattr(self, '_unbound', True)
+ super(Binding, self).unbind()
+
+
+Binding = override(Binding)
+__all__.append('Binding')
+
+
Property = propertyhelper.Property
Signal = signalhelper.Signal
SignalOverride = signalhelper.SignalOverride
# Deprecated naming "property" available for backwards compatibility.
# Keep this at the end of the file to avoid clobbering the builtin.
property = Property
+deprecated_attr("GObject", "property", "GObject.Property")
__all__ += ['Property', 'Signal', 'SignalOverride', 'property']
diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py
index 14edc70..73f309f 100644
--- a/gi/overrides/Gdk.py
+++ b/gi/overrides/Gdk.py
@@ -19,60 +19,80 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
+import sys
+import warnings
+
from ..overrides import override, strip_boolean_result
from ..module import get_introspection_module
-
-import sys
+from gi import PyGIDeprecationWarning, require_version
Gdk = get_introspection_module('Gdk')
+GDK2 = Gdk._version == '2.0'
+GDK3 = Gdk._version == '3.0'
+GDK4 = Gdk._version == '4.0'
__all__ = []
-class Color(Gdk.Color):
- MAX_VALUE = 65535
+# https://bugzilla.gnome.org/show_bug.cgi?id=673396
+try:
+ require_version("GdkX11", Gdk._version)
+ from gi.repository import GdkX11
+ GdkX11 # pyflakes
+except (ValueError, ImportError):
+ pass
- def __init__(self, red, green, blue):
- Gdk.Color.__init__(self)
- self.red = red
- self.green = green
- self.blue = blue
+if GDK2 or GDK3:
+ # Gdk.Color was deprecated since 3.14 and dropped in Gtk-4.0
+ class Color(Gdk.Color):
+ MAX_VALUE = 65535
+
+ def __init__(self, red, green, blue):
+ Gdk.Color.__init__(self)
+ self.red = red
+ self.green = green
+ self.blue = blue
- def __new__(cls, *args, **kwargs):
- return Gdk.Color.__new__(cls)
+ def __eq__(self, other):
+ if not isinstance(other, Gdk.Color):
+ return False
+ return self.equal(other)
- def __eq__(self, other):
- return self.equal(other)
+ # This is required (even when __eq__ is defined) in order
+ # for != operator to work as expected
+ def __ne__(self, other):
+ return not self == other
- def __repr__(self):
- return '<Gdk.Color(red=%d, green=%d, blue=%d)>' % (self.red, self.green, self.blue)
+ def __repr__(self):
+ return 'Gdk.Color(red=%d, green=%d, blue=%d)' % (self.red, self.green, self.blue)
- red_float = property(fget=lambda self: self.red / float(self.MAX_VALUE),
- fset=lambda self, v: setattr(self, 'red', int(v * self.MAX_VALUE)))
+ red_float = property(fget=lambda self: self.red / float(self.MAX_VALUE),
+ fset=lambda self, v: setattr(self, 'red', int(v * self.MAX_VALUE)))
- green_float = property(fget=lambda self: self.green / float(self.MAX_VALUE),
- fset=lambda self, v: setattr(self, 'green', int(v * self.MAX_VALUE)))
+ green_float = property(fget=lambda self: self.green / float(self.MAX_VALUE),
+ fset=lambda self, v: setattr(self, 'green', int(v * self.MAX_VALUE)))
- blue_float = property(fget=lambda self: self.blue / float(self.MAX_VALUE),
- fset=lambda self, v: setattr(self, 'blue', int(v * self.MAX_VALUE)))
+ blue_float = property(fget=lambda self: self.blue / float(self.MAX_VALUE),
+ fset=lambda self, v: setattr(self, 'blue', int(v * self.MAX_VALUE)))
- def to_floats(self):
- """Return (red_float, green_float, blue_float) triple."""
+ def to_floats(self):
+ """Return (red_float, green_float, blue_float) triple."""
- return (self.red_float, self.green_float, self.blue_float)
+ return (self.red_float, self.green_float, self.blue_float)
- @staticmethod
- def from_floats(red, green, blue):
- """Return a new Color object from red/green/blue values from 0.0 to 1.0."""
+ @staticmethod
+ def from_floats(red, green, blue):
+ """Return a new Color object from red/green/blue values from 0.0 to 1.0."""
- return Color(int(red * Color.MAX_VALUE),
- int(green * Color.MAX_VALUE),
- int(blue * Color.MAX_VALUE))
+ return Color(int(red * Color.MAX_VALUE),
+ int(green * Color.MAX_VALUE),
+ int(blue * Color.MAX_VALUE))
-Color = override(Color)
-__all__.append('Color')
+ Color = override(Color)
+ __all__.append('Color')
-if Gdk._version == '3.0':
+if GDK3:
+ # Introduced since Gtk-3.0
class RGBA(Gdk.RGBA):
def __init__(self, red=1.0, green=1.0, blue=1.0, alpha=1.0):
Gdk.RGBA.__init__(self)
@@ -81,14 +101,18 @@ if Gdk._version == '3.0':
self.blue = blue
self.alpha = alpha
- def __new__(cls, *args, **kwargs):
- return Gdk.RGBA.__new__(cls)
-
def __eq__(self, other):
+ if not isinstance(other, Gdk.RGBA):
+ return False
return self.equal(other)
+ # This is required (even when __eq__ is defined) in order
+ # for != operator to work as expected
+ def __ne__(self, other):
+ return not self == other
+
def __repr__(self):
- return '<Gdk.Color(red=%f, green=%f, blue=%f, alpha=%f)>' % (self.red, self.green, self.blue, self.alpha)
+ return 'Gdk.RGBA(red=%f, green=%f, blue=%f, alpha=%f)' % (self.red, self.green, self.blue, self.alpha)
def __iter__(self):
"""Iterator which allows easy conversion to tuple and list types."""
@@ -114,7 +138,7 @@ if Gdk._version == '3.0':
RGBA = override(RGBA)
__all__.append('RGBA')
-if Gdk._version == '2.0':
+if GDK2:
class Rectangle(Gdk.Rectangle):
def __init__(self, x, y, width, height):
@@ -124,28 +148,37 @@ if Gdk._version == '2.0':
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)
+ 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')
-else:
- from gi.repository import cairo as _cairo
- Rectangle = _cairo.RectangleInt
-
- __all__.append('Rectangle')
-
-if Gdk._version == '2.0':
+elif GDK3:
+ # Newer GTK/gobject-introspection (3.17.x) include GdkRectangle in the
+ # typelib. See https://bugzilla.gnome.org/show_bug.cgi?id=748832 and
+ # https://bugzilla.gnome.org/show_bug.cgi?id=748833
+ if not hasattr(Gdk, 'Rectangle'):
+ from gi.repository import cairo as _cairo
+ Rectangle = _cairo.RectangleInt
+
+ __all__.append('Rectangle')
+ else:
+ # https://bugzilla.gnome.org/show_bug.cgi?id=756364
+ # These methods used to be functions, keep aliases for backwards compat
+ rectangle_intersect = Gdk.Rectangle.intersect
+ rectangle_union = Gdk.Rectangle.union
+
+ __all__.append('rectangle_intersect')
+ __all__.append('rectangle_union')
+
+if GDK2:
class Drawable(Gdk.Drawable):
def cairo_create(self):
return Gdk.cairo_create(self)
Drawable = override(Drawable)
__all__.append('Drawable')
-else:
+elif GDK3:
class Window(Gdk.Window):
def __new__(cls, parent, attributes, attributes_mask):
# Gdk.Window had to be made abstract,
@@ -161,195 +194,243 @@ else:
Window = override(Window)
__all__.append('Window')
-Gdk.EventType._2BUTTON_PRESS = getattr(Gdk.EventType, "2BUTTON_PRESS")
-Gdk.EventType._3BUTTON_PRESS = getattr(Gdk.EventType, "3BUTTON_PRESS")
-
-
-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',
- }
-
- if Gdk._version == '2.0':
- _UNION_MEMBERS[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:
- raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
-
-Event = override(Event)
-__all__.append('Event')
-
-# manually bind GdkEvent members to GdkEvent
-
-modname = globals()['__name__']
-module = sys.modules[modname]
-
-# right now we can't get the type_info from the
-# field info so manually list the class names
-event_member_classes = ['EventAny',
- 'EventExpose',
- 'EventVisibility',
- 'EventMotion',
- 'EventButton',
- 'EventScroll',
- 'EventKey',
- 'EventCrossing',
- 'EventFocus',
- 'EventConfigure',
- 'EventProperty',
- 'EventSelection',
- 'EventOwnerChange',
- 'EventProximity',
- 'EventDND',
- 'EventWindowState',
- 'EventSetting',
- 'EventGrabBroken']
-
-if Gdk._version == '2.0':
- event_member_classes.append('EventNoExpose')
-
-# whitelist all methods that have a success return we want to mask
-gsuccess_mask_funcs = ['get_state',
- 'get_axis',
- 'get_coords',
- 'get_root_coords']
-
-
-for event_class in event_member_classes:
- override_class = type(event_class, (getattr(Gdk, event_class),), {})
- # add the event methods
- for method_info in Gdk.Event.__info__.get_methods():
- name = method_info.get_name()
- event_method = getattr(Gdk.Event, name)
- # python2 we need to use the __func__ attr to avoid internal
- # instance checks
- event_method = getattr(event_method, '__func__', event_method)
-
- # use the _gsuccess_mask decorator if this method is whitelisted
- if name in gsuccess_mask_funcs:
- event_method = strip_boolean_result(event_method)
- setattr(override_class, name, event_method)
-
- setattr(module, event_class, override_class)
- __all__.append(event_class)
-
-# end GdkEvent overrides
-
-
-class DragContext(Gdk.DragContext):
- def finish(self, success, del_, time):
- Gtk = get_introspection_module('Gtk')
- Gtk.drag_finish(self, success, del_, time)
-
-DragContext = override(DragContext)
-__all__.append('DragContext')
-
-
-class Cursor(Gdk.Cursor):
- def __new__(cls, *args, **kwds):
- arg_len = len(args)
- kwd_len = len(kwds)
- total_len = arg_len + kwd_len
-
- def _new(cursor_type):
- return cls.new(cursor_type)
-
- def _new_for_display(display, cursor_type):
- return cls.new_for_display(display, cursor_type)
-
- def _new_from_pixbuf(display, pixbuf, x, y):
- return cls.new_from_pixbuf(display, pixbuf, x, y)
-
- def _new_from_pixmap(source, mask, fg, bg, x, y):
- return cls.new_from_pixmap(source, mask, fg, bg, x, y)
-
- _constructor = None
- if total_len == 1:
- _constructor = _new
- elif total_len == 2:
- _constructor = _new_for_display
- elif total_len == 4:
- _constructor = _new_from_pixbuf
- elif total_len == 6:
- if Gdk._version != '2.0':
- # pixmaps don't exist in Gdk 3.0
- raise ValueError("Wrong number of parameters")
- _constructor = _new_from_pixmap
- else:
- raise ValueError("Wrong number of parameters")
-
- return _constructor(*args, **kwds)
-
- def __init__(self, *args, **kwargs):
- Gdk.Cursor.__init__(self)
-
-Cursor = override(Cursor)
-__all__.append('Cursor')
-
-color_parse = strip_boolean_result(Gdk.color_parse)
-__all__.append('color_parse')
+if GDK2 or GDK3:
+ Gdk.EventType._2BUTTON_PRESS = getattr(Gdk.EventType, "2BUTTON_PRESS")
+ Gdk.EventType._3BUTTON_PRESS = getattr(Gdk.EventType, "3BUTTON_PRESS")
+
+ class Event(Gdk.Event):
+ _UNION_MEMBERS = {
+ Gdk.EventType.DELETE: 'any',
+ Gdk.EventType.DESTROY: 'any',
+ Gdk.EventType.MOTION_NOTIFY: 'motion',
+ Gdk.EventType.BUTTON_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.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.DROP_START: 'dnd',
+ Gdk.EventType._2BUTTON_PRESS: 'button',
+ Gdk.EventType._3BUTTON_PRESS: 'button',
+ Gdk.EventType.PROPERTY_NOTIFY: 'property',
+ Gdk.EventType.SELECTION_CLEAR: 'selection',
+ Gdk.EventType.SELECTION_REQUEST: 'selection',
+ Gdk.EventType.SELECTION_NOTIFY: 'selection',
+ Gdk.EventType.DRAG_STATUS: 'dnd',
+ Gdk.EventType.DROP_FINISHED: 'dnd',
+ Gdk.EventType.CLIENT_EVENT: 'client',
+ Gdk.EventType.VISIBILITY_NOTIFY: 'visibility',
+ Gdk.EventType.SCROLL: 'scroll',
+ Gdk.EventType.EXPOSE: 'expose',
+ Gdk.EventType.MAP: 'any',
+ Gdk.EventType.UNMAP: 'any',
+ }
+
+ if GDK2:
+ _UNION_MEMBERS[Gdk.EventType.NO_EXPOSE] = 'no_expose'
+
+ if hasattr(Gdk.EventType, 'TOUCH_BEGIN'):
+ _UNION_MEMBERS.update(
+ {
+ Gdk.EventType.TOUCH_BEGIN: 'touch',
+ Gdk.EventType.TOUCH_UPDATE: 'touch',
+ Gdk.EventType.TOUCH_END: 'touch',
+ Gdk.EventType.TOUCH_CANCEL: 'touch',
+ })
+
+ def __getattr__(self, name):
+ real_event = getattr(self, '_UNION_MEMBERS').get(self.type)
+ if real_event:
+ return getattr(getattr(self, real_event), name)
+ else:
+ raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
+
+ def __setattr__(self, name, value):
+ real_event = getattr(self, '_UNION_MEMBERS').get(self.type)
+ if real_event:
+ setattr(getattr(self, real_event), name, value)
+ else:
+ Gdk.Event.__setattr__(self, name, value)
+ def __repr__(self):
+ base_repr = Gdk.Event.__repr__(self).strip("><")
+ return "<%s type=%r>" % (base_repr, self.type)
+
+ Event = override(Event)
+ __all__.append('Event')
+
+ # manually bind GdkEvent members to GdkEvent
+
+ modname = globals()['__name__']
+ module = sys.modules[modname]
+
+ # right now we can't get the type_info from the
+ # field info so manually list the class names
+ event_member_classes = ['EventAny',
+ 'EventExpose',
+ 'EventMotion',
+ 'EventButton',
+ 'EventScroll',
+ 'EventKey',
+ 'EventCrossing',
+ 'EventFocus',
+ 'EventConfigure',
+ 'EventProximity',
+ 'EventDND',
+ 'EventSetting',
+ 'EventGrabBroken',
+ 'EventVisibility',
+ 'EventProperty',
+ 'EventSelection',
+ 'EventOwnerChange',
+ 'EventWindowState',
+ 'EventVisibility']
+
+ if GDK2:
+ event_member_classes.append('EventNoExpose')
+
+ if hasattr(Gdk, 'EventTouch'):
+ event_member_classes.append('EventTouch')
+
+ # whitelist all methods that have a success return we want to mask
+ gsuccess_mask_funcs = ['get_state',
+ 'get_axis',
+ 'get_coords',
+ 'get_root_coords']
+
+ for event_class in event_member_classes:
+ override_class = type(event_class, (getattr(Gdk, event_class),), {})
+ # add the event methods
+ for method_info in Gdk.Event.__info__.get_methods():
+ name = method_info.get_name()
+ event_method = getattr(Gdk.Event, name)
+
+ # use the _gsuccess_mask decorator if this method is whitelisted
+ if name in gsuccess_mask_funcs:
+ event_method = strip_boolean_result(event_method)
+ setattr(override_class, name, event_method)
+
+ setattr(module, event_class, override_class)
+ __all__.append(event_class)
+
+ # end GdkEvent overrides
+
+ class DragContext(Gdk.DragContext):
+ def finish(self, success, del_, time):
+ Gtk = get_introspection_module('Gtk')
+ Gtk.drag_finish(self, success, del_, time)
+
+ DragContext = override(DragContext)
+ __all__.append('DragContext')
+
+ class Cursor(Gdk.Cursor):
+
+ def __new__(cls, *args, **kwds):
+ arg_len = len(args)
+ kwd_len = len(kwds)
+ total_len = arg_len + kwd_len
+
+ if total_len == 1:
+ # Since g_object_newv (super.__new__) does not seem valid for
+ # direct use with GdkCursor, we must assume usage of at least
+ # one of the C constructors to be valid.
+ return cls.new(*args, **kwds)
+
+ elif total_len == 2:
+ warnings.warn('Calling "Gdk.Cursor(display, cursor_type)" has been deprecated. '
+ 'Please use Gdk.Cursor.new_for_display(display, cursor_type). '
+ 'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations',
+ PyGIDeprecationWarning)
+ return cls.new_for_display(*args, **kwds)
+
+ elif total_len == 4:
+ warnings.warn('Calling "Gdk.Cursor(display, pixbuf, x, y)" has been deprecated. '
+ 'Please use Gdk.Cursor.new_from_pixbuf(display, pixbuf, x, y). '
+ 'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations',
+ PyGIDeprecationWarning)
+ return cls.new_from_pixbuf(*args, **kwds)
+
+ elif total_len == 6:
+ if not GDK2:
+ # pixmaps don't exist in Gdk 3.0
+ raise ValueError("Wrong number of parameters")
+
+ warnings.warn('Calling "Gdk.Cursor(source, mask, fg, bg, x, y)" has been deprecated. '
+ 'Please use Gdk.Cursor.new_from_pixmap(source, mask, fg, bg, x, y). '
+ 'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations',
+ PyGIDeprecationWarning)
+ return cls.new_from_pixmap(*args, **kwds)
+
+ else:
+ raise ValueError("Wrong number of parameters")
-# Note, we cannot override the entire class as Gdk.Atom has no gtype, so just
-# hack some individual methods
-def _gdk_atom_str(atom):
- n = atom.name()
- if n:
- return n
- # fall back to atom index
- return 'Gdk.Atom<%i>' % hash(atom)
+ Cursor = override(Cursor)
+ __all__.append('Cursor')
+
+ # Gdk.Color was deprecated since 3.14 and dropped in Gtk-4.0
+ color_parse = strip_boolean_result(Gdk.color_parse)
+ __all__.append('color_parse')
+
+ # Note, we cannot override the entire class as Gdk.Atom has no gtype, so just
+ # hack some individual methods
+ def _gdk_atom_str(atom):
+ n = atom.name()
+ if n:
+ return n
+ # fall back to atom index
+ return 'Gdk.Atom<%i>' % hash(atom)
+
+ def _gdk_atom_repr(atom):
+ n = atom.name()
+ if n:
+ return 'Gdk.Atom.intern("%s", False)' % n
+ # fall back to atom index
+ return '<Gdk.Atom(%i)>' % hash(atom)
+
+ Gdk.Atom.__str__ = _gdk_atom_str
+ Gdk.Atom.__repr__ = _gdk_atom_repr
+
+
+if GDK4:
+ from gi.repository import Gio
+
+ class FileList(Gdk.FileList):
+
+ if hasattr(Gdk.FileList, "new_from_list"):
+ def __new__(cls, files):
+ files_list = []
+ if isinstance(files, (tuple, list)):
+ for f in files:
+ if isinstance(f, Gio.File):
+ files_list.append(f)
+ else:
+ raise TypeError('Constructor requires a list or tuple of Gio.File instances')
+ else:
+ raise TypeError('Constructor requires a list or tuple of Gio.File instances')
+ return Gdk.FileList.new_from_list(files)
+ def __iter__(self):
+ return iter(self.get_files())
-def _gdk_atom_repr(atom):
- n = atom.name()
- if n:
- return 'Gdk.Atom<%s>' % n
- # fall back to atom index
- return 'Gdk.Atom<%i>' % hash(atom)
+ def __len__(self):
+ return len(self.get_files())
+ def __getitem__(self, index):
+ return self.get_files()[index]
-Gdk.Atom.__str__ = _gdk_atom_str
-Gdk.Atom.__repr__ = _gdk_atom_repr
+ FileList = override(FileList)
+ __all__.append('FileList')
# constants
-if Gdk._version >= '3.0':
+if GDK3:
SELECTION_PRIMARY = Gdk.atom_intern('PRIMARY', True)
__all__.append('SELECTION_PRIMARY')
@@ -398,6 +479,6 @@ if Gdk._version >= '3.0':
SELECTION_TYPE_STRING = Gdk.atom_intern('STRING', True)
__all__.append('SELECTION_TYPE_STRING')
-import sys
-
-initialized, argv = Gdk.init_check(sys.argv)
+if GDK2 or GDK3:
+ import sys
+ initialized, argv = Gdk.init_check(sys.argv)
diff --git a/gi/overrides/GdkPixbuf.py b/gi/overrides/GdkPixbuf.py
new file mode 100644
index 0000000..0f6cd75
--- /dev/null
+++ b/gi/overrides/GdkPixbuf.py
@@ -0,0 +1,53 @@
+# Copyright 2018 Christoph Reiter <reiter.christoph@gmail.com>
+#
+# 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
+
+import warnings
+
+from gi import PyGIDeprecationWarning
+from gi.repository import GLib
+
+from ..overrides import override
+from ..module import get_introspection_module
+
+
+GdkPixbuf = get_introspection_module('GdkPixbuf')
+__all__ = []
+
+
+@override
+class Pixbuf(GdkPixbuf.Pixbuf):
+
+ @classmethod
+ def new_from_data(
+ cls, data, colorspace, has_alpha, bits_per_sample,
+ width, height, rowstride,
+ destroy_fn=None, *destroy_fn_data):
+
+ if destroy_fn is not None:
+ w = PyGIDeprecationWarning("destroy_fn argument deprecated")
+ warnings.warn(w)
+ if destroy_fn_data:
+ w = PyGIDeprecationWarning("destroy_fn_data argument deprecated")
+ warnings.warn(w)
+
+ data = GLib.Bytes.new(data)
+ return cls.new_from_bytes(
+ data, colorspace, has_alpha, bits_per_sample,
+ width, height, rowstride)
+
+
+__all__.append('Pixbuf')
diff --git a/gi/overrides/Gio.py b/gi/overrides/Gio.py
index 6ecd1c4..c807fe0 100644
--- a/gi/overrides/Gio.py
+++ b/gi/overrides/Gio.py
@@ -18,8 +18,12 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-from ..overrides import override
+import warnings
+
+from .._ossighelper import wakeup_on_signal, register_sigint_fallback
+from ..overrides import override, deprecated_init, wrap_list_store_sort_func
from ..module import get_introspection_module
+from gi import PyGIWarning
from gi.repository import GLib
@@ -30,6 +34,171 @@ Gio = get_introspection_module('Gio')
__all__ = []
+class Application(Gio.Application):
+
+ def run(self, *args, **kwargs):
+ with register_sigint_fallback(self.quit):
+ with wakeup_on_signal():
+ return Gio.Application.run(self, *args, **kwargs)
+
+
+Application = override(Application)
+__all__.append('Application')
+
+
+def _warn_init(cls, instead=None):
+
+ def new_init(self, *args, **kwargs):
+ super(cls, self).__init__(*args, **kwargs)
+ name = cls.__module__.rsplit(".", 1)[-1] + "." + cls.__name__
+ if instead:
+ warnings.warn(
+ ("%s shouldn't be instantiated directly, "
+ "use %s instead." % (name, instead)),
+ PyGIWarning, stacklevel=2)
+ else:
+ warnings.warn(
+ "%s shouldn't be instantiated directly." % (name,),
+ PyGIWarning, stacklevel=2)
+
+ return new_init
+
+
+@override
+class VolumeMonitor(Gio.VolumeMonitor):
+ # https://bugzilla.gnome.org/show_bug.cgi?id=744690
+ __init__ = _warn_init(Gio.VolumeMonitor, "Gio.VolumeMonitor.get()")
+
+
+__all__.append('VolumeMonitor')
+
+
+@override
+class DBusAnnotationInfo(Gio.DBusAnnotationInfo):
+ __init__ = _warn_init(Gio.DBusAnnotationInfo)
+
+
+__all__.append('DBusAnnotationInfo')
+
+
+@override
+class DBusArgInfo(Gio.DBusArgInfo):
+ __init__ = _warn_init(Gio.DBusArgInfo)
+
+
+__all__.append('DBusArgInfo')
+
+
+@override
+class DBusMethodInfo(Gio.DBusMethodInfo):
+ __init__ = _warn_init(Gio.DBusMethodInfo)
+
+
+__all__.append('DBusMethodInfo')
+
+
+@override
+class DBusSignalInfo(Gio.DBusSignalInfo):
+ __init__ = _warn_init(Gio.DBusSignalInfo)
+
+
+__all__.append('DBusSignalInfo')
+
+
+@override
+class DBusInterfaceInfo(Gio.DBusInterfaceInfo):
+ __init__ = _warn_init(Gio.DBusInterfaceInfo)
+
+
+__all__.append('DBusInterfaceInfo')
+
+
+@override
+class DBusNodeInfo(Gio.DBusNodeInfo):
+ __init__ = _warn_init(Gio.DBusNodeInfo)
+
+
+__all__.append('DBusNodeInfo')
+
+
+class ActionMap(Gio.ActionMap):
+ def add_action_entries(self, entries, user_data=None):
+ """
+ The add_action_entries() method is a convenience function for creating
+ multiple Gio.SimpleAction instances and adding them to a Gio.ActionMap.
+ Each action is constructed as per one entry.
+
+ :param list entries:
+ List of entry tuples for add_action() method. The entry tuple can
+ vary in size with the following information:
+
+ * The name of the action. Must be specified.
+ * The callback to connect to the "activate" signal of the
+ action. Since GLib 2.40, this can be None for stateful
+ actions, in which case the default handler is used. For
+ boolean-stated actions with no parameter, this is a toggle.
+ For other state types (and parameter type equal to the state
+ type) this will be a function that just calls change_state
+ (which you should provide).
+ * The type of the parameter that must be passed to the activate
+ function for this action, given as a single GLib.Variant type
+ string (or None for no parameter)
+ * The initial state for this action, given in GLib.Variant text
+ format. The state is parsed with no extra type information, so
+ type tags must be added to the string if they are necessary.
+ Stateless actions should give None here.
+ * The callback to connect to the "change-state" signal of the
+ action. All stateful actions should provide a handler here;
+ stateless actions should not.
+
+ :param user_data:
+ The user data for signal connections, or None
+ """
+ try:
+ iter(entries)
+ except (TypeError):
+ raise TypeError('entries must be iterable')
+
+ def _process_action(name, activate=None, parameter_type=None,
+ state=None, change_state=None):
+ if parameter_type:
+ if not GLib.VariantType.string_is_valid(parameter_type):
+ raise TypeError("The type string '%s' given as the "
+ "parameter type for action '%s' is "
+ "not a valid GVariant type string. " %
+ (parameter_type, name))
+ variant_parameter = GLib.VariantType.new(parameter_type)
+ else:
+ variant_parameter = None
+
+ if state is not None:
+ # stateful action
+ variant_state = GLib.Variant.parse(None, state, None, None)
+ action = Gio.SimpleAction.new_stateful(name, variant_parameter,
+ variant_state)
+ if change_state is not None:
+ action.connect('change-state', change_state, user_data)
+ else:
+ # stateless action
+ if change_state is not None:
+ raise ValueError("Stateless action '%s' should give "
+ "None for 'change_state', not '%s'." %
+ (name, change_state))
+ action = Gio.SimpleAction(name=name, parameter_type=variant_parameter)
+
+ if activate is not None:
+ action.connect('activate', activate, user_data)
+ self.add_action(action)
+
+ for entry in entries:
+ # using inner function above since entries can leave out optional arguments
+ _process_action(*entry)
+
+
+ActionMap = override(ActionMap)
+__all__.append('ActionMap')
+
+
class FileEnumerator(Gio.FileEnumerator):
def __iter__(self):
return self
@@ -63,8 +232,8 @@ __all__.append('MenuItem')
class Settings(Gio.Settings):
'''Provide dictionary-like access to GLib.Settings.'''
- def __init__(self, schema, path=None, backend=None, **kwargs):
- Gio.Settings.__init__(self, schema=schema, backend=backend, path=path, **kwargs)
+ __init__ = deprecated_init(Gio.Settings.__init__,
+ arg_names=('schema', 'path', 'backend'))
def __contains__(self, key):
return key in self.list_keys()
@@ -72,6 +241,10 @@ class Settings(Gio.Settings):
def __len__(self):
return len(self.list_keys())
+ def __iter__(self):
+ for key in self.list_keys():
+ yield key
+
def __bool__(self):
# for "if mysettings" we don't want a dictionary-like test here, just
# if the object isn't None
@@ -82,14 +255,14 @@ class Settings(Gio.Settings):
def __getitem__(self, key):
# get_value() aborts the program on an unknown key
- if not key in self:
+ if key not in self:
raise KeyError('unknown key: %r' % (key,))
return self.get_value(key).unpack()
def __setitem__(self, key, value):
# set_value() aborts the program on an unknown key
- if not key in self:
+ if key not in self:
raise KeyError('unknown key: %r' % (key,))
# determine type string of this key
@@ -108,6 +281,13 @@ class Settings(Gio.Settings):
allowed = v.unpack()
if value not in allowed:
raise ValueError('value %s is not an allowed enum (%s)' % (value, allowed))
+ elif type_ == 'range':
+ tuple_ = v.get_child_value(0)
+ type_str = tuple_.get_child_value(0).get_type_string()
+ min_, max_ = tuple_.unpack()
+ if value < min_ or value > max_:
+ raise ValueError(
+ 'value %s not in range (%s - %s)' % (value, min_, max_))
else:
raise NotImplementedError('Cannot handle allowed type range class ' + str(type_))
@@ -116,6 +296,7 @@ class Settings(Gio.Settings):
def keys(self):
return self.list_keys()
+
Settings = override(Settings)
__all__.append('Settings')
@@ -235,5 +416,135 @@ class DBusProxy(Gio.DBusProxy):
def __getattr__(self, name):
return _DBusProxyMethodCall(self, name)
+
DBusProxy = override(DBusProxy)
__all__.append('DBusProxy')
+
+
+class ListModel(Gio.ListModel):
+
+ def __getitem__(self, key):
+ if isinstance(key, slice):
+ return [self.get_item(i) for i in range(*key.indices(len(self)))]
+ elif isinstance(key, int):
+ if key < 0:
+ key += len(self)
+ if key < 0:
+ raise IndexError
+ ret = self.get_item(key)
+ if ret is None:
+ raise IndexError
+ return ret
+ else:
+ raise TypeError
+
+ def __contains__(self, item):
+ pytype = self.get_item_type().pytype
+ if not isinstance(item, pytype):
+ raise TypeError(
+ "Expected type %s.%s" % (pytype.__module__, pytype.__name__))
+ for i in self:
+ if i == item:
+ return True
+ return False
+
+ def __len__(self):
+ return self.get_n_items()
+
+ def __iter__(self):
+ for i in range(len(self)):
+ yield self.get_item(i)
+
+
+ListModel = override(ListModel)
+__all__.append('ListModel')
+
+
+if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION) < (2, 57, 1):
+ # The "additions" functionality in splice() was broken in older glib
+ # https://bugzilla.gnome.org/show_bug.cgi?id=795307
+ # This is a slower fallback which emits a signal per added item
+ def _list_store_splice(self, position, n_removals, additions):
+ self.splice(position, n_removals, [])
+ for v in reversed(additions):
+ self.insert(position, v)
+else:
+ def _list_store_splice(self, position, n_removals, additions):
+ self.splice(position, n_removals, additions)
+
+
+class ListStore(Gio.ListStore):
+
+ def sort(self, compare_func, *user_data):
+ compare_func = wrap_list_store_sort_func(compare_func)
+ return super(ListStore, self).sort(compare_func, *user_data)
+
+ def insert_sorted(self, item, compare_func, *user_data):
+ compare_func = wrap_list_store_sort_func(compare_func)
+ return super(ListStore, self).insert_sorted(
+ item, compare_func, *user_data)
+
+ def __delitem__(self, key):
+ if isinstance(key, slice):
+ start, stop, step = key.indices(len(self))
+ if step == 1:
+ _list_store_splice(self, start, max(stop - start, 0), [])
+ elif step == -1:
+ _list_store_splice(self, stop + 1, max(start - stop, 0), [])
+ else:
+ for i in sorted(range(start, stop, step), reverse=True):
+ self.remove(i)
+ elif isinstance(key, int):
+ if key < 0:
+ key += len(self)
+ if key < 0 or key >= len(self):
+ raise IndexError
+ self.remove(key)
+ else:
+ raise TypeError
+
+ def __setitem__(self, key, value):
+ if isinstance(key, slice):
+ pytype = self.get_item_type().pytype
+ valuelist = []
+ for v in value:
+ if not isinstance(v, pytype):
+ raise TypeError(
+ "Expected type %s.%s" % (
+ pytype.__module__, pytype.__name__))
+ valuelist.append(v)
+
+ start, stop, step = key.indices(len(self))
+ if step == 1:
+ _list_store_splice(
+ self, start, max(stop - start, 0), valuelist)
+ else:
+ indices = list(range(start, stop, step))
+ if len(indices) != len(valuelist):
+ raise ValueError
+
+ if step == -1:
+ _list_store_splice(
+ self, stop + 1, max(start - stop, 0), valuelist[::-1])
+ else:
+ for i, v in zip(indices, valuelist):
+ _list_store_splice(self, i, 1, [v])
+ elif isinstance(key, int):
+ if key < 0:
+ key += len(self)
+ if key < 0 or key >= len(self):
+ raise IndexError
+
+ pytype = self.get_item_type().pytype
+ if not isinstance(value, pytype):
+ raise TypeError(
+ "Expected type %s.%s" % (
+ pytype.__module__, pytype.__name__))
+
+ _list_store_splice(self, key, 1, [value])
+ else:
+ raise TypeError
+
+
+ListStore = override(ListStore)
+__all__.append('ListStore')
diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
index 5899596..f75da7b 100644
--- a/gi/overrides/Gtk.py
+++ b/gi/overrides/Gtk.py
@@ -19,96 +19,177 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-import collections
import sys
+import warnings
+
from gi.repository import GObject
-from ..overrides import override, strip_boolean_result
+from .._ossighelper import wakeup_on_signal, register_sigint_fallback
+from .._gtktemplate import Template, _extract_handler_and_args
+from ..overrides import (override, strip_boolean_result, deprecated_init,
+ wrap_list_store_sort_func)
from ..module import get_introspection_module
from gi import PyGIDeprecationWarning
-if sys.version_info >= (3, 0):
- _basestring = str
- _callable = lambda c: hasattr(c, '__call__')
-else:
- _basestring = basestring
- _callable = callable
Gtk = get_introspection_module('Gtk')
+GTK3 = Gtk._version == '3.0'
+GTK4 = Gtk._version == '4.0'
__all__ = []
-if Gtk._version == '2.0':
- import warnings
- warn_msg = "You have imported the Gtk 2.0 module. Because Gtk 2.0 \
-was not designed for use with introspection some of the \
-interfaces and API will fail. As such this is not supported \
-by the pygobject development team and we encourage you to \
-port your app to Gtk 3 or greater. PyGTK is the recomended \
-python module to use with Gtk 2.0"
- warnings.warn(warn_msg, RuntimeWarning)
+Template = Template
+__all__.append('Template')
+
+# Exposed for unit-testing.
+_extract_handler_and_args = _extract_handler_and_args
+__all__.append('_extract_handler_and_args')
+
+
+class PyGTKDeprecationWarning(PyGIDeprecationWarning):
+ pass
+
+
+__all__.append('PyGTKDeprecationWarning')
+
+
+if GTK3:
+ def _construct_target_list(targets):
+ """Create a list of TargetEntry items from a list of tuples in the form (target, flags, info)
+
+ The list can also contain existing TargetEntry items in which case the existing entry
+ is re-used in the return list.
+ """
+ target_entries = []
+ for entry in targets:
+ if not isinstance(entry, Gtk.TargetEntry):
+ entry = Gtk.TargetEntry.new(*entry)
+ target_entries.append(entry)
+ return target_entries
+
+ __all__.append('_construct_target_list')
+
+
+def _builder_connect_callback(builder, gobj, signal_name, handler_name, connect_obj, flags, obj_or_map):
+ handler, args = _extract_handler_and_args(obj_or_map, handler_name)
+
+ after = flags & GObject.ConnectFlags.AFTER
+ if connect_obj is not None:
+ if after:
+ gobj.connect_object_after(signal_name, handler, connect_obj, *args)
+ else:
+ gobj.connect_object(signal_name, handler, connect_obj, *args)
+ else:
+ if after:
+ gobj.connect_after(signal_name, handler, *args)
+ else:
+ gobj.connect(signal_name, handler, *args)
-def _construct_target_list(targets):
- """Create a list of TargetEntry items from a list of tuples in the form (target, flags, info)
+class _FreezeNotifyManager(object):
+ def __init__(self, obj):
+ self.obj = obj
- The list can also contain existing TargetEntry items in which case the existing entry
- is re-used in the return list.
- """
- target_entries = []
- for entry in targets:
- if not isinstance(entry, Gtk.TargetEntry):
- entry = Gtk.TargetEntry.new(*entry)
- target_entries.append(entry)
- return target_entries
+ def __enter__(self):
+ pass
-__all__.append('_construct_target_list')
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.obj.thaw_child_notify()
class Widget(Gtk.Widget):
translate_coordinates = strip_boolean_result(Gtk.Widget.translate_coordinates)
- def render_icon(self, stock_id, size, detail=None):
- return super(Widget, self).render_icon(stock_id, size, detail)
-
- def drag_dest_set_target_list(self, target_list):
- if not isinstance(target_list, Gtk.TargetList):
- target_list = Gtk.TargetList.new(_construct_target_list(target_list))
- super(Widget, self).drag_dest_set_target_list(target_list)
+ if GTK4:
+ def __contains__(self, child):
+ return child in list(self)
+
+ def __iter__(self):
+ child = self.get_first_child()
+ while child:
+ yield child
+ child = child.get_next_sibling()
+
+ if GTK3:
+ def freeze_child_notify(self):
+ super(Widget, self).freeze_child_notify()
+ return _FreezeNotifyManager(self)
+
+ if GTK3:
+ def drag_dest_set_target_list(self, target_list):
+ if (target_list is not None) and (not isinstance(target_list, Gtk.TargetList)):
+ target_list = Gtk.TargetList.new(_construct_target_list(target_list))
+ super(Widget, self).drag_dest_set_target_list(target_list)
+
+ if GTK3:
+ def drag_source_set_target_list(self, target_list):
+ if (target_list is not None) and (not isinstance(target_list, Gtk.TargetList)):
+ target_list = Gtk.TargetList.new(_construct_target_list(target_list))
+ super(Widget, self).drag_source_set_target_list(target_list)
+
+ if GTK3:
+ def style_get_property(self, property_name, value=None):
+ if value is None:
+ prop = self.find_style_property(property_name)
+ if prop is None:
+ raise ValueError('Class "%s" does not contain style property "%s"' %
+ (self, property_name))
+ value = GObject.Value(prop.value_type)
- def drag_source_set_target_list(self, target_list):
- if not isinstance(target_list, Gtk.TargetList):
- target_list = Gtk.TargetList.new(_construct_target_list(target_list))
- super(Widget, self).drag_source_set_target_list(target_list)
+ Gtk.Widget.style_get_property(self, property_name, value)
+ return value.get_value()
Widget = override(Widget)
__all__.append('Widget')
-class Container(Gtk.Container, Widget):
+if GTK3:
+ class Container(Gtk.Container, Widget):
- def __len__(self):
- return len(self.get_children())
+ def __len__(self):
+ return len(self.get_children())
- def __contains__(self, child):
- return child in self.get_children()
+ def __contains__(self, child):
+ return child in self.get_children()
- def __iter__(self):
- return iter(self.get_children())
+ def __iter__(self):
+ return iter(self.get_children())
- def __bool__(self):
- return True
+ def __bool__(self):
+ return True
+
+ # alias for Python 2.x object protocol
+ __nonzero__ = __bool__
+
+ def child_get_property(self, child, property_name, value=None):
+ if value is None:
+ prop = self.find_child_property(property_name)
+ if prop is None:
+ raise ValueError('Class "%s" does not contain child property "%s"' %
+ (self, property_name))
+ value = GObject.Value(prop.value_type)
+
+ Gtk.Container.child_get_property(self, child, property_name, value)
+ return value.get_value()
- # alias for Python 2.x object protocol
- __nonzero__ = __bool__
+ def child_get(self, child, *prop_names):
+ """Returns a list of child property values for the given names."""
+ return [self.child_get_property(child, name) for name in prop_names]
- get_focus_chain = strip_boolean_result(Gtk.Container.get_focus_chain)
+ def child_set(self, child, **kwargs):
+ """Set a child properties on the given child to key/value pairs."""
+ for name, value in kwargs.items():
+ name = name.replace('_', '-')
+ self.child_set_property(child, name, value)
+ get_focus_chain = strip_boolean_result(Gtk.Container.get_focus_chain)
-Container = override(Container)
-__all__.append('Container')
+ Container = override(Container)
+ __all__.append('Container')
+else:
+ Container = object
class Editable(Gtk.Editable):
@@ -123,306 +204,288 @@ Editable = override(Editable)
__all__.append("Editable")
-class Action(Gtk.Action):
- def __init__(self, name, label, tooltip, stock_id, **kwds):
- Gtk.Action.__init__(self, name=name, label=label, tooltip=tooltip, stock_id=stock_id, **kwds)
+if GTK3:
+ class Action(Gtk.Action):
+ __init__ = deprecated_init(Gtk.Action.__init__,
+ arg_names=('name', 'label', 'tooltip', 'stock_id'),
+ category=PyGTKDeprecationWarning)
+
+ Action = override(Action)
+ __all__.append("Action")
+
+ class RadioAction(Gtk.RadioAction):
+ __init__ = deprecated_init(Gtk.RadioAction.__init__,
+ arg_names=('name', 'label', 'tooltip', 'stock_id', 'value'),
+ category=PyGTKDeprecationWarning)
+
+ RadioAction = override(RadioAction)
+ __all__.append("RadioAction")
+
+ class ActionGroup(Gtk.ActionGroup):
+ __init__ = deprecated_init(Gtk.ActionGroup.__init__,
+ arg_names=('name',),
+ category=PyGTKDeprecationWarning)
+
+ def add_actions(self, entries, user_data=None):
+ """
+ The add_actions() method is a convenience method that creates a number
+ of gtk.Action objects based on the information in the list of action
+ entry tuples contained in entries and adds them to the action group.
+ The entry tuples can vary in size from one to six items with the
+ following information:
+
+ * The name of the action. Must be specified.
+ * The stock id for the action. Optional with a default value of None
+ if a label is specified.
+ * The label for the action. This field should typically be marked
+ for translation, see the set_translation_domain() method. Optional
+ with a default value of None if a stock id is specified.
+ * The accelerator for the action, in the format understood by the
+ gtk.accelerator_parse() function. Optional with a default value of
+ None.
+ * The tooltip for the action. This field should typically be marked
+ for translation, see the set_translation_domain() method. Optional
+ with a default value of None.
+ * The callback function invoked when the action is activated.
+ Optional with a default value of None.
+
+ The "activate" signals of the actions are connected to the callbacks and
+ their accel paths are set to <Actions>/group-name/action-name.
+ """
+ try:
+ iter(entries)
+ except (TypeError):
+ raise TypeError('entries must be iterable')
+
+ def _process_action(name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None):
+ action = Action(name=name, label=label, tooltip=tooltip, stock_id=stock_id)
+ if callback is not None:
+ if user_data is None:
+ action.connect('activate', callback)
+ else:
+ action.connect('activate', callback, user_data)
+
+ self.add_action_with_accel(action, accelerator)
+
+ for e in entries:
+ # using inner function above since entries can leave out optional arguments
+ _process_action(*e)
+
+ def add_toggle_actions(self, entries, user_data=None):
+ """
+ The add_toggle_actions() method is a convenience method that creates a
+ number of gtk.ToggleAction objects based on the information in the list
+ of action entry tuples contained in entries and adds them to the action
+ group. The toggle action entry tuples can vary in size from one to seven
+ items with the following information:
+
+ * The name of the action. Must be specified.
+ * The stock id for the action. Optional with a default value of None
+ if a label is specified.
+ * The label for the action. This field should typically be marked
+ for translation, see the set_translation_domain() method. Optional
+ with a default value of None if a stock id is specified.
+ * The accelerator for the action, in the format understood by the
+ gtk.accelerator_parse() function. Optional with a default value of
+ None.
+ * The tooltip for the action. This field should typically be marked
+ for translation, see the set_translation_domain() method. Optional
+ with a default value of None.
+ * The callback function invoked when the action is activated.
+ Optional with a default value of None.
+ * A flag indicating whether the toggle action is active. Optional
+ with a default value of False.
+
+ The "activate" signals of the actions are connected to the callbacks and
+ their accel paths are set to <Actions>/group-name/action-name.
+ """
-Action = override(Action)
-__all__.append("Action")
+ try:
+ iter(entries)
+ except (TypeError):
+ raise TypeError('entries must be iterable')
+
+ def _process_action(name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None, is_active=False):
+ action = Gtk.ToggleAction(name=name, label=label, tooltip=tooltip, stock_id=stock_id)
+ action.set_active(is_active)
+ if callback is not None:
+ if user_data is None:
+ action.connect('activate', callback)
+ else:
+ action.connect('activate', callback, user_data)
+
+ self.add_action_with_accel(action, accelerator)
+
+ for e in entries:
+ # using inner function above since entries can leave out optional arguments
+ _process_action(*e)
+
+ def add_radio_actions(self, entries, value=None, on_change=None, user_data=None):
+ """
+ The add_radio_actions() method is a convenience method that creates a
+ number of gtk.RadioAction objects based on the information in the list
+ of action entry tuples contained in entries and adds them to the action
+ group. The entry tuples can vary in size from one to six items with the
+ following information:
+
+ * The name of the action. Must be specified.
+ * The stock id for the action. Optional with a default value of None
+ if a label is specified.
+ * The label for the action. This field should typically be marked
+ for translation, see the set_translation_domain() method. Optional
+ with a default value of None if a stock id is specified.
+ * The accelerator for the action, in the format understood by the
+ gtk.accelerator_parse() function. Optional with a default value of
+ None.
+ * The tooltip for the action. This field should typically be marked
+ for translation, see the set_translation_domain() method. Optional
+ with a default value of None.
+ * The value to set on the radio action. Optional with a default
+ value of 0. Should be specified in applications.
+
+ The value parameter specifies the radio action that should be set
+ active. The "changed" signal of the first radio action is connected to
+ the on_change callback (if specified and not None) and the accel paths
+ of the actions are set to <Actions>/group-name/action-name.
+ """
+ try:
+ iter(entries)
+ except (TypeError):
+ raise TypeError('entries must be iterable')
+ first_action = None
-class RadioAction(Gtk.RadioAction):
- def __init__(self, name, label, tooltip, stock_id, value, **kwds):
- Gtk.RadioAction.__init__(self, name=name, label=label, tooltip=tooltip, stock_id=stock_id, value=value, **kwds)
+ def _process_action(group_source, name, stock_id=None, label=None, accelerator=None, tooltip=None, entry_value=0):
+ action = RadioAction(name=name, label=label, tooltip=tooltip, stock_id=stock_id, value=entry_value)
-RadioAction = override(RadioAction)
-__all__.append("RadioAction")
+ if GTK3:
+ action.join_group(group_source)
+ if value == entry_value:
+ action.set_active(True)
-class ActionGroup(Gtk.ActionGroup):
- def __init__(self, name, **kwds):
- super(ActionGroup, self).__init__(name=name, **kwds)
+ self.add_action_with_accel(action, accelerator)
+ return action
- def add_actions(self, entries, user_data=None):
- """
- The add_actions() method is a convenience method that creates a number
- of gtk.Action objects based on the information in the list of action
- entry tuples contained in entries and adds them to the action group.
- The entry tuples can vary in size from one to six items with the
- following information:
-
- * The name of the action. Must be specified.
- * The stock id for the action. Optional with a default value of None
- if a label is specified.
- * The label for the action. This field should typically be marked
- for translation, see the set_translation_domain() method. Optional
- with a default value of None if a stock id is specified.
- * The accelerator for the action, in the format understood by the
- gtk.accelerator_parse() function. Optional with a default value of
- None.
- * The tooltip for the action. This field should typically be marked
- for translation, see the set_translation_domain() method. Optional
- with a default value of None.
- * The callback function invoked when the action is activated.
- Optional with a default value of None.
-
- The "activate" signals of the actions are connected to the callbacks and
- their accel paths are set to <Actions>/group-name/action-name.
- """
- try:
- iter(entries)
- except (TypeError):
- raise TypeError('entries must be iterable')
+ for e in entries:
+ # using inner function above since entries can leave out optional arguments
+ action = _process_action(first_action, *e)
+ if first_action is None:
+ first_action = action
- def _process_action(name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None):
- action = Action(name, label, tooltip, stock_id)
- if callback is not None:
+ if first_action is not None and on_change is not None:
if user_data is None:
- action.connect('activate', callback)
+ first_action.connect('changed', on_change)
else:
- action.connect('activate', callback, user_data)
+ first_action.connect('changed', on_change, user_data)
- self.add_action_with_accel(action, accelerator)
+ ActionGroup = override(ActionGroup)
+ __all__.append('ActionGroup')
- for e in entries:
- # using inner function above since entries can leave out optional arguments
- _process_action(*e)
+ class UIManager(Gtk.UIManager):
+ def add_ui_from_string(self, buffer):
+ if not isinstance(buffer, str):
+ raise TypeError('buffer must be a string')
- def add_toggle_actions(self, entries, user_data=None):
- """
- The add_toggle_actions() method is a convenience method that creates a
- number of gtk.ToggleAction objects based on the information in the list
- of action entry tuples contained in entries and adds them to the action
- group. The toggle action entry tuples can vary in size from one to seven
- items with the following information:
-
- * The name of the action. Must be specified.
- * The stock id for the action. Optional with a default value of None
- if a label is specified.
- * The label for the action. This field should typically be marked
- for translation, see the set_translation_domain() method. Optional
- with a default value of None if a stock id is specified.
- * The accelerator for the action, in the format understood by the
- gtk.accelerator_parse() function. Optional with a default value of
- None.
- * The tooltip for the action. This field should typically be marked
- for translation, see the set_translation_domain() method. Optional
- with a default value of None.
- * The callback function invoked when the action is activated.
- Optional with a default value of None.
- * A flag indicating whether the toggle action is active. Optional
- with a default value of False.
-
- The "activate" signals of the actions are connected to the callbacks and
- their accel paths are set to <Actions>/group-name/action-name.
- """
+ length = _get_utf8_length(buffer)
- try:
- iter(entries)
- except (TypeError):
- raise TypeError('entries must be iterable')
-
- def _process_action(name, stock_id=None, label=None, accelerator=None, tooltip=None, callback=None, is_active=False):
- action = Gtk.ToggleAction(name, label, tooltip, stock_id)
- action.set_active(is_active)
- if callback is not None:
- if user_data is None:
- action.connect('activate', callback)
- else:
- action.connect('activate', callback, user_data)
+ return Gtk.UIManager.add_ui_from_string(self, buffer, length)
- self.add_action_with_accel(action, accelerator)
+ def insert_action_group(self, buffer, length=-1):
+ return Gtk.UIManager.insert_action_group(self, buffer, length)
- for e in entries:
- # using inner function above since entries can leave out optional arguments
- _process_action(*e)
-
- def add_radio_actions(self, entries, value=None, on_change=None, user_data=None):
- """
- The add_radio_actions() method is a convenience method that creates a
- number of gtk.RadioAction objects based on the information in the list
- of action entry tuples contained in entries and adds them to the action
- group. The entry tuples can vary in size from one to six items with the
- following information:
-
- * The name of the action. Must be specified.
- * The stock id for the action. Optional with a default value of None
- if a label is specified.
- * The label for the action. This field should typically be marked
- for translation, see the set_translation_domain() method. Optional
- with a default value of None if a stock id is specified.
- * The accelerator for the action, in the format understood by the
- gtk.accelerator_parse() function. Optional with a default value of
- None.
- * The tooltip for the action. This field should typically be marked
- for translation, see the set_translation_domain() method. Optional
- with a default value of None.
- * The value to set on the radio action. Optional with a default
- value of 0. Should be specified in applications.
-
- The value parameter specifies the radio action that should be set
- active. The "changed" signal of the first radio action is connected to
- the on_change callback (if specified and not None) and the accel paths
- of the actions are set to <Actions>/group-name/action-name.
- """
- try:
- iter(entries)
- except (TypeError):
- raise TypeError('entries must be iterable')
-
- first_action = None
-
- def _process_action(group_source, name, stock_id=None, label=None, accelerator=None, tooltip=None, entry_value=0):
- action = RadioAction(name, label, tooltip, stock_id, entry_value)
-
- # FIXME: join_group is a patch to Gtk+ 3.0
- # otherwise we can't effectively add radio actions to a
- # group. Should we depend on 3.0 and error out here
- # or should we offer the functionality via a compat
- # C module?
- if hasattr(action, 'join_group'):
- action.join_group(group_source)
-
- if value == entry_value:
- action.set_active(True)
-
- self.add_action_with_accel(action, accelerator)
- return action
-
- for e in entries:
- # using inner function above since entries can leave out optional arguments
- action = _process_action(first_action, *e)
- if first_action is None:
- first_action = action
-
- if first_action is not None and on_change is not None:
- if user_data is None:
- first_action.connect('changed', on_change)
- else:
- first_action.connect('changed', on_change, user_data)
-
-ActionGroup = override(ActionGroup)
-__all__.append('ActionGroup')
-
-
-class UIManager(Gtk.UIManager):
- def add_ui_from_string(self, buffer):
- if not isinstance(buffer, _basestring):
- raise TypeError('buffer must be a string')
-
- length = len(buffer.encode('UTF-8'))
-
- return Gtk.UIManager.add_ui_from_string(self, buffer, length)
-
- def insert_action_group(self, buffer, length=-1):
- return Gtk.UIManager.insert_action_group(self, buffer, length)
-
-UIManager = override(UIManager)
-__all__.append('UIManager')
+ UIManager = override(UIManager)
+ __all__.append('UIManager')
class ComboBox(Gtk.ComboBox, Container):
get_active_iter = strip_boolean_result(Gtk.ComboBox.get_active_iter)
+
ComboBox = override(ComboBox)
__all__.append('ComboBox')
-class Box(Gtk.Box):
- def __init__(self, homogeneous=False, spacing=0, **kwds):
- super(Box, self).__init__(**kwds)
- self.set_homogeneous(homogeneous)
- self.set_spacing(spacing)
+if GTK3:
+ class Box(Gtk.Box):
+ __init__ = deprecated_init(Gtk.Box.__init__,
+ arg_names=('homogeneous', 'spacing'),
+ category=PyGTKDeprecationWarning)
-Box = override(Box)
-__all__.append('Box')
+ Box = override(Box)
+ __all__.append('Box')
-class SizeGroup(Gtk.SizeGroup):
- def __init__(self, mode=Gtk.SizeGroupMode.VERTICAL):
- super(SizeGroup, self).__init__(mode=mode)
+if GTK3:
+ class SizeGroup(Gtk.SizeGroup):
+ __init__ = deprecated_init(Gtk.SizeGroup.__init__,
+ arg_names=('mode',),
+ deprecated_defaults={'mode': Gtk.SizeGroupMode.VERTICAL},
+ category=PyGTKDeprecationWarning)
-SizeGroup = override(SizeGroup)
-__all__.append('SizeGroup')
+ SizeGroup = override(SizeGroup)
+ __all__.append('SizeGroup')
-class MenuItem(Gtk.MenuItem):
- def __init__(self, label=None, **kwds):
- if label:
- super(MenuItem, self).__init__(label=label, **kwds)
- else:
- super(MenuItem, self).__init__(**kwds)
-
-MenuItem = override(MenuItem)
-__all__.append('MenuItem')
+if GTK3:
+ class MenuItem(Gtk.MenuItem):
+ __init__ = deprecated_init(Gtk.MenuItem.__init__,
+ arg_names=('label',),
+ category=PyGTKDeprecationWarning)
+ MenuItem = override(MenuItem)
+ __all__.append('MenuItem')
-class Builder(Gtk.Builder):
- @staticmethod
- def _extract_handler_and_args(obj_or_map, handler_name):
- handler = None
- if isinstance(obj_or_map, collections.Mapping):
- handler = obj_or_map.get(handler_name, None)
- else:
- handler = getattr(obj_or_map, handler_name, None)
- if handler is None:
- raise AttributeError('Handler %s not found' % handler_name)
+def _get_utf8_length(string):
+ assert isinstance(string, str)
+ if not isinstance(string, bytes):
+ string = string.encode("utf-8")
+ return len(string)
- args = ()
- if isinstance(handler, collections.Sequence):
- if len(handler) == 0:
- raise TypeError("Handler %s tuple can not be empty" % handler)
- args = handler[1:]
- handler = handler[0]
- elif not _callable(handler):
- raise TypeError('Handler %s is not a method, function or tuple' % handler)
+class Builder(Gtk.Builder):
+ if GTK4:
+ from .._gtktemplate import define_builder_scope
+ BuilderScope = define_builder_scope()
- return handler, args
+ def __init__(self, scope_object_or_map=None):
+ super(Builder, self).__init__()
+ if scope_object_or_map:
+ self.set_scope(Builder.BuilderScope(scope_object_or_map))
- def connect_signals(self, obj_or_map):
- """Connect signals specified by this builder to a name, handler mapping.
+ else:
+ def connect_signals(self, obj_or_map):
+ """Connect signals specified by this builder to a name, handler mapping.
- Connect signal, name, and handler sets specified in the builder with
- the given mapping "obj_or_map". The handler/value aspect of the mapping
- can also contain a tuple in the form of (handler [,arg1 [,argN]])
- allowing for extra arguments to be passed to the handler. For example:
- builder.connect_signals({'on_clicked': (on_clicked, arg1, arg2)})
- """
- def _full_callback(builder, gobj, signal_name, handler_name, connect_obj, flags, obj_or_map):
- handler, args = self._extract_handler_and_args(obj_or_map, handler_name)
+ Connect signal, name, and handler sets specified in the builder with
+ the given mapping "obj_or_map". The handler/value aspect of the mapping
+ can also contain a tuple in the form of (handler [,arg1 [,argN]])
+ allowing for extra arguments to be passed to the handler. For example:
- after = flags & GObject.ConnectFlags.AFTER
- if connect_obj is not None:
- if after:
- gobj.connect_object_after(signal_name, handler, connect_obj, *args)
- else:
- gobj.connect_object(signal_name, handler, connect_obj, *args)
- else:
- if after:
- gobj.connect_after(signal_name, handler, *args)
- else:
- gobj.connect(signal_name, handler, *args)
+ .. code-block:: python
- self.connect_signals_full(_full_callback, obj_or_map)
+ builder.connect_signals({'on_clicked': (on_clicked, arg1, arg2)})
+ """
+ self.connect_signals_full(_builder_connect_callback, obj_or_map)
def add_from_string(self, buffer):
- if not isinstance(buffer, _basestring):
+ if not isinstance(buffer, str):
raise TypeError('buffer must be a string')
- length = len(buffer)
+ length = _get_utf8_length(buffer)
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, str):
raise TypeError('buffer must be a string')
- length = len(buffer)
+ length = _get_utf8_length(buffer)
return Gtk.Builder.add_objects_from_string(self, buffer, length, object_ids)
+
Builder = override(Builder)
__all__.append('Builder')
@@ -430,61 +493,88 @@ __all__.append('Builder')
# NOTE: This must come before any other Window/Dialog subclassing, to ensure
# that we have a correct inheritance hierarchy.
+if GTK4:
+ _window_init = Gtk.Window.__init__
+else:
+ _window_init = deprecated_init(Gtk.Window.__init__,
+ arg_names=('type',),
+ category=PyGTKDeprecationWarning,
+ stacklevel=3)
+
class Window(Gtk.Window):
- def __init__(self, type=Gtk.WindowType.TOPLEVEL, **kwds):
+ def __init__(self, *args, **kwargs):
if not initialized:
- raise RuntimeError("Gtk couldn't be initialized")
+ raise RuntimeError(
+ "Gtk couldn't be initialized. "
+ "Use Gtk.init_check() if you want to handle this case.")
+ _window_init(self, *args, **kwargs)
- # type is a construct-only property; if it is already set (e. g. by
- # GtkBuilder), do not try to set it again and just ignore it
- try:
- self.get_property('type')
- Gtk.Window.__init__(self, **kwds)
- except TypeError:
- Gtk.Window.__init__(self, type=type, **kwds)
Window = override(Window)
__all__.append('Window')
class Dialog(Gtk.Dialog, Container):
+ if GTK3:
+ _old_arg_names = ('title', 'parent', 'flags', 'buttons', '_buttons_property')
+ _init = deprecated_init(Gtk.Dialog.__init__,
+ arg_names=('title', 'transient_for', 'flags',
+ 'add_buttons', 'buttons'),
+ ignore=('flags', 'add_buttons'),
+ deprecated_aliases={'transient_for': 'parent',
+ 'buttons': '_buttons_property'},
+ category=PyGTKDeprecationWarning)
+
+ def __init__(self, *args, **kwargs):
+
+ new_kwargs = kwargs.copy()
+ old_kwargs = dict(zip(self._old_arg_names, args))
+ old_kwargs.update(kwargs)
+
+ # Increment the warning stacklevel for sub-classes which implement their own __init__.
+ stacklevel = 2
+ if self.__class__ != Dialog and self.__class__.__init__ != Dialog.__init__:
+ stacklevel += 1
+
+ # buttons was overloaded by PyGtk but is needed for Gtk.MessageDialog
+ # as a pass through, so type check the argument and give a deprecation
+ # when it is not of type Gtk.ButtonsType
+ add_buttons = old_kwargs.get('buttons', None)
+ if add_buttons is not None and not isinstance(add_buttons, Gtk.ButtonsType):
+ warnings.warn('The "buttons" argument must be a Gtk.ButtonsType enum value. '
+ 'Please use the "add_buttons" method for adding buttons. '
+ 'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations',
+ PyGTKDeprecationWarning, stacklevel=stacklevel)
+ new_kwargs.pop('buttons', None)
+ else:
+ add_buttons = None
+
+ flags = old_kwargs.get('flags', 0)
+ if flags:
+ warnings.warn('The "flags" argument for dialog construction is deprecated. '
+ 'Please use initializer keywords: modal=True and/or destroy_with_parent=True. '
+ 'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations',
+ PyGTKDeprecationWarning, stacklevel=stacklevel)
+
+ if flags & Gtk.DialogFlags.MODAL:
+ new_kwargs['modal'] = True
+
+ if flags & Gtk.DialogFlags.DESTROY_WITH_PARENT:
+ new_kwargs['destroy_with_parent'] = True
+
+ self._init(*args, **new_kwargs)
- def __init__(self,
- title=None,
- parent=None,
- flags=0,
- buttons=None,
- _buttons_property=None,
- **kwds):
-
- # buttons is overloaded by PyGtk so we have to do the same here
- # this breaks some subclasses of Dialog so add a _buttons_property
- # keyword to work around this
- if _buttons_property is not None:
- kwds['buttons'] = _buttons_property
-
- Gtk.Dialog.__init__(self, **kwds)
- if title:
- self.set_title(title)
- if parent:
- self.set_transient_for(parent)
- if flags & Gtk.DialogFlags.MODAL:
- self.set_modal(True)
- if flags & Gtk.DialogFlags.DESTROY_WITH_PARENT:
- self.set_destroy_with_parent(True)
-
- # NO_SEPARATOR has been removed from Gtk 3
- if hasattr(Gtk.DialogFlags, "NO_SEPARATOR") and (flags & Gtk.DialogFlags.NO_SEPARATOR):
- self.set_has_separator(False)
- import warnings
- warnings.warn("Gtk.DialogFlags.NO_SEPARATOR has been depricated since Gtk+-3.0", PyGIDeprecationWarning)
-
- if buttons is not None:
- self.add_buttons(*buttons)
-
- action_area = property(lambda dialog: dialog.get_action_area())
- vbox = property(lambda dialog: dialog.get_content_area())
+ if add_buttons:
+ self.add_buttons(*add_buttons)
+
+ def run(self, *args, **kwargs):
+ with register_sigint_fallback(self.destroy):
+ with wakeup_on_signal():
+ return Gtk.Dialog.run(self, *args, **kwargs)
+
+ action_area = property(lambda dialog: dialog.get_action_area())
+ vbox = property(lambda dialog: dialog.get_content_area())
def add_buttons(self, *args):
"""
@@ -494,148 +584,120 @@ class Dialog(Gtk.Dialog, Container):
pairs - button text (or stock ID) and a response ID integer are passed
individually. For example:
- dialog.add_buttons(Gtk.STOCK_OPEN, 42, "Close", Gtk.ResponseType.CLOSE)
+ .. code-block:: python
+
+ dialog.add_buttons(Gtk.STOCK_OPEN, 42, "Close", Gtk.ResponseType.CLOSE)
will add "Open" and "Close" buttons to dialog.
"""
def _button(b):
while b:
- t, r = b[0:2]
+ try:
+ t, r = b[0:2]
+ except ValueError:
+ raise ValueError('Must pass an even number of arguments')
b = b[2:]
yield t, r
- try:
- for text, response in _button(args):
- self.add_button(text, response)
- except (IndexError):
- raise TypeError('Must pass an even number of arguments')
+ for text, response in _button(args):
+ self.add_button(text, response)
+
Dialog = override(Dialog)
__all__.append('Dialog')
-class MessageDialog(Gtk.MessageDialog, Dialog):
- def __init__(self,
- parent=None,
- flags=0,
- message_type=Gtk.MessageType.INFO,
- buttons=Gtk.ButtonsType.NONE,
- message_format=None,
- **kwds):
+if GTK3:
+ class MessageDialog(Gtk.MessageDialog, Dialog):
+ __init__ = deprecated_init(Gtk.MessageDialog.__init__,
+ arg_names=('parent', 'flags', 'message_type',
+ 'buttons', 'message_format'),
+ deprecated_aliases={'text': 'message_format',
+ 'message_type': 'type'},
+ category=PyGTKDeprecationWarning)
- if message_format:
- kwds['text'] = message_format
+ def format_secondary_text(self, message_format):
+ self.set_property('secondary-use-markup', False)
+ self.set_property('secondary-text', message_format)
- # type keyword is used for backwards compat with PyGTK
- if 'type' in kwds:
- import warnings
- warnings.warn("The use of the keyword type as a parameter of the Gtk.MessageDialog constructor has been depricated. Please use message_type instead.", PyGIDeprecationWarning)
- message_type = kwds.pop('type')
+ def format_secondary_markup(self, message_format):
+ self.set_property('secondary-use-markup', True)
+ self.set_property('secondary-text', message_format)
- Gtk.MessageDialog.__init__(self,
- _buttons_property=buttons,
- message_type=message_type,
- parent=parent,
- flags=flags,
- **kwds)
+ MessageDialog = override(MessageDialog)
+ __all__.append('MessageDialog')
- def format_secondary_text(self, message_format):
- self.set_property('secondary-use-markup', False)
- self.set_property('secondary-text', message_format)
- def format_secondary_markup(self, message_format):
- self.set_property('secondary-use-markup', True)
- self.set_property('secondary-text', message_format)
+if GTK3:
+ class ColorSelectionDialog(Gtk.ColorSelectionDialog):
+ __init__ = deprecated_init(Gtk.ColorSelectionDialog.__init__,
+ arg_names=('title',),
+ category=PyGTKDeprecationWarning)
-MessageDialog = override(MessageDialog)
-__all__.append('MessageDialog')
+ ColorSelectionDialog = override(ColorSelectionDialog)
+ __all__.append('ColorSelectionDialog')
+ class FileChooserDialog(Gtk.FileChooserDialog):
+ __init__ = deprecated_init(Gtk.FileChooserDialog.__init__,
+ arg_names=('title', 'parent', 'action', 'buttons'),
+ category=PyGTKDeprecationWarning)
-class AboutDialog(Gtk.AboutDialog):
- def __init__(self, **kwds):
- Gtk.AboutDialog.__init__(self, **kwds)
+ FileChooserDialog = override(FileChooserDialog)
+ __all__.append('FileChooserDialog')
-AboutDialog = override(AboutDialog)
-__all__.append('AboutDialog')
+if GTK3:
+ class FontSelectionDialog(Gtk.FontSelectionDialog):
+ __init__ = deprecated_init(Gtk.FontSelectionDialog.__init__,
+ arg_names=('title',),
+ category=PyGTKDeprecationWarning)
-class ColorSelectionDialog(Gtk.ColorSelectionDialog):
- def __init__(self, title=None, **kwds):
- Gtk.ColorSelectionDialog.__init__(self, title=title, **kwds)
+ FontSelectionDialog = override(FontSelectionDialog)
+ __all__.append('FontSelectionDialog')
-ColorSelectionDialog = override(ColorSelectionDialog)
-__all__.append('ColorSelectionDialog')
+if GTK3:
+ class RecentChooserDialog(Gtk.RecentChooserDialog):
+ # Note, the "manager" keyword must work across the entire 3.x series because
+ # "recent_manager" is not backwards compatible with PyGObject versions prior to 3.10.
+ __init__ = deprecated_init(Gtk.RecentChooserDialog.__init__,
+ arg_names=('title', 'parent', 'recent_manager', 'buttons'),
+ deprecated_aliases={'recent_manager': 'manager'},
+ category=PyGTKDeprecationWarning)
-class FileChooserDialog(Gtk.FileChooserDialog):
- def __init__(self,
- title=None,
- parent=None,
- action=Gtk.FileChooserAction.OPEN,
- buttons=None,
- **kwds):
- Gtk.FileChooserDialog.__init__(self,
- action=action,
- title=title,
- parent=parent,
- buttons=buttons,
- **kwds)
-FileChooserDialog = override(FileChooserDialog)
-__all__.append('FileChooserDialog')
-
-
-class FontSelectionDialog(Gtk.FontSelectionDialog):
- def __init__(self, title=None, **kwds):
- Gtk.FontSelectionDialog.__init__(self, title=title, **kwds)
-
-FontSelectionDialog = override(FontSelectionDialog)
-__all__.append('FontSelectionDialog')
-
-
-class RecentChooserDialog(Gtk.RecentChooserDialog):
- def __init__(self,
- title=None,
- parent=None,
- manager=None,
- buttons=None,
- **kwds):
-
- Gtk.RecentChooserDialog.__init__(self,
- recent_manager=manager,
- title=title,
- parent=parent,
- buttons=buttons,
- **kwds)
-
-RecentChooserDialog = override(RecentChooserDialog)
-__all__.append('RecentChooserDialog')
+ RecentChooserDialog = override(RecentChooserDialog)
+ __all__.append('RecentChooserDialog')
class IconView(Gtk.IconView):
-
- def __init__(self, model=None, **kwds):
- Gtk.IconView.__init__(self, model=model, **kwds)
+ if GTK3:
+ __init__ = deprecated_init(Gtk.IconView.__init__,
+ arg_names=('model',),
+ category=PyGTKDeprecationWarning)
get_item_at_pos = strip_boolean_result(Gtk.IconView.get_item_at_pos)
get_visible_range = strip_boolean_result(Gtk.IconView.get_visible_range)
get_dest_item_at_pos = strip_boolean_result(Gtk.IconView.get_dest_item_at_pos)
+
IconView = override(IconView)
__all__.append('IconView')
-class ToolButton(Gtk.ToolButton):
-
- def __init__(self, stock_id=None, **kwds):
- Gtk.ToolButton.__init__(self, stock_id=stock_id, **kwds)
+if GTK3:
+ class ToolButton(Gtk.ToolButton):
+ __init__ = deprecated_init(Gtk.ToolButton.__init__,
+ arg_names=('stock_id',),
+ category=PyGTKDeprecationWarning)
-ToolButton = override(ToolButton)
-__all__.append('ToolButton')
+ ToolButton = override(ToolButton)
+ __all__.append('ToolButton')
class IMContext(Gtk.IMContext):
get_surrounding = strip_boolean_result(Gtk.IMContext.get_surrounding)
+
IMContext = override(IMContext)
__all__.append('IMContext')
@@ -643,42 +705,39 @@ __all__.append('IMContext')
class RecentInfo(Gtk.RecentInfo):
get_application_info = strip_boolean_result(Gtk.RecentInfo.get_application_info)
+
RecentInfo = override(RecentInfo)
__all__.append('RecentInfo')
class TextBuffer(Gtk.TextBuffer):
- def _get_or_create_tag_table(self):
- table = self.get_tag_table()
- if table is None:
- table = Gtk.TextTagTable()
- self.set_tag_table(table)
-
- return table
def create_tag(self, tag_name=None, **properties):
- """
- @tag_name: name of the new tag, or None
- @properties: keyword list of properties and their values
+ """Creates a tag and adds it to the tag table of the TextBuffer.
+
+ :param str tag_name:
+ Name of the new tag, or None
+ :param **properties:
+ Keyword list of properties and their values
- Creates a tag and adds it to the tag table of the TextBuffer.
- Equivalent to creating a Gtk.TextTag and then adding the
+ This is equivalent to creating a Gtk.TextTag and then adding the
tag to the buffer's tag table. The returned tag is owned by
the buffer's tag table.
- If @tag_name is None, the tag is anonymous.
+ If ``tag_name`` is None, the tag is anonymous.
- If @tag_name is not None, a tag called @tag_name must not already
+ If ``tag_name`` is not None, a tag called ``tag_name`` must not already
exist in the tag table for this buffer.
Properties are passed as a keyword list of names and values (e.g.
- foreground = 'DodgerBlue', weight = Pango.Weight.BOLD)
+ foreground='DodgerBlue', weight=Pango.Weight.BOLD)
- Return value: a new tag
+ :returns:
+ A new tag.
"""
tag = Gtk.TextTag(name=tag_name, **properties)
- self._get_or_create_tag_table().add(tag)
+ self.get_tag_table().add(tag)
return tag
def create_mark(self, mark_name, where, left_gravity=False):
@@ -688,7 +747,7 @@ class TextBuffer(Gtk.TextBuffer):
Gtk.TextBuffer.set_text(self, text, length)
def insert(self, iter, text, length=-1):
- if not isinstance(text, _basestring):
+ if not isinstance(text, str):
raise TypeError('text must be a string, not %s' % type(text))
Gtk.TextBuffer.insert(self, iter, text, length)
@@ -706,9 +765,6 @@ class TextBuffer(Gtk.TextBuffer):
self.apply_tag(tag, start, iter)
def insert_with_tags_by_name(self, iter, text, *tags):
- if not tags:
- return
-
tag_objs = []
for tag in tags:
@@ -720,30 +776,22 @@ class TextBuffer(Gtk.TextBuffer):
self.insert_with_tags(iter, text, *tag_objs)
def insert_at_cursor(self, text, length=-1):
- if not isinstance(text, _basestring):
+ if not isinstance(text, str):
raise TypeError('text must be a string, not %s' % type(text))
Gtk.TextBuffer.insert_at_cursor(self, text, length)
get_selection_bounds = strip_boolean_result(Gtk.TextBuffer.get_selection_bounds, fail_ret=())
+
TextBuffer = override(TextBuffer)
__all__.append('TextBuffer')
class TextIter(Gtk.TextIter):
-
forward_search = strip_boolean_result(Gtk.TextIter.forward_search)
backward_search = strip_boolean_result(Gtk.TextIter.backward_search)
- def begins_tag(self, tag=None):
- return super(TextIter, self).begins_tag(tag)
-
- def ends_tag(self, tag=None):
- return super(TextIter, self).ends_tag(tag)
-
- def toggles_tag(self, tag=None):
- return super(TextIter, self).toggles_tag(tag)
TextIter = override(TextIter)
__all__.append('TextIter')
@@ -756,8 +804,9 @@ class TreeModel(Gtk.TreeModel):
def __bool__(self):
return True
- # alias for Python 2.x object protocol
- __nonzero__ = __bool__
+ if GTK3:
+ # alias for Python 2.x object protocol
+ __nonzero__ = __bool__
def _getiter(self, key):
if isinstance(key, Gtk.TreeIter):
@@ -766,11 +815,7 @@ class TreeModel(Gtk.TreeModel):
index = len(self) + key
if index < 0:
raise IndexError("row index is out of bounds: %d" % key)
- try:
- aiter = self.get_iter(index)
- except ValueError:
- raise IndexError("could not find tree path '%s'" % key)
- return aiter
+ return self.get_iter(index)
else:
try:
aiter = self.get_iter(key)
@@ -778,6 +823,13 @@ class TreeModel(Gtk.TreeModel):
raise IndexError("could not find tree path '%s'" % key)
return aiter
+ def sort_new_with_model(self):
+ super_object = super(TreeModel, self)
+ if hasattr(super_object, "sort_new_with_model"):
+ return super_object.sort_new_with_model()
+ else:
+ return TreeModelSort.new_with_model(self)
+
def _coerce_path(self, path):
if isinstance(path, Gtk.TreePath):
return path
@@ -848,11 +900,7 @@ class TreeModel(Gtk.TreeModel):
def set_row(self, treeiter, row):
converted_row, columns = self._convert_row(row)
for column in columns:
- value = row[column]
- if value is None:
- continue # None means skip this row
-
- self.set_value(treeiter, column, value)
+ self.set_value(treeiter, column, row[column])
def _convert_value(self, column, value):
'''Convert value to a GObject.Value of the expected type'''
@@ -876,9 +924,6 @@ class TreeModel(Gtk.TreeModel):
return tuple(values)
- def filter_new(self, root=None):
- return super(TreeModel, self).filter_new(root)
-
#
# Signals supporting python iterables as tree paths
#
@@ -914,16 +959,24 @@ class TreeSortable(Gtk.TreeSortable, ):
def set_default_sort_func(self, sort_func, user_data=None):
super(TreeSortable, self).set_default_sort_func(sort_func, user_data)
+
TreeSortable = override(TreeSortable)
__all__.append('TreeSortable')
-class TreeModelSort(Gtk.TreeModelSort):
- def __init__(self, model, **kwds):
- Gtk.TreeModelSort.__init__(self, model=model, **kwds)
+if GTK3:
+ class TreeModelSort(Gtk.TreeModelSort):
+ __init__ = deprecated_init(Gtk.TreeModelSort.__init__,
+ arg_names=('model',),
+ category=PyGTKDeprecationWarning)
-TreeModelSort = override(TreeModelSort)
-__all__.append('TreeModelSort')
+ if not hasattr(Gtk.TreeModelSort, "new_with_model"):
+ @classmethod
+ def new_with_model(self, child_model):
+ return TreeModel.sort_new_with_model(child_model)
+
+ TreeModelSort = override(TreeModelSort)
+ __all__.append('TreeModelSort')
class ListStore(Gtk.ListStore, TreeModel, TreeSortable):
@@ -931,10 +984,17 @@ class ListStore(Gtk.ListStore, TreeModel, TreeSortable):
Gtk.ListStore.__init__(self)
self.set_column_types(column_types)
+ # insert_with_valuesv got renamed to insert_with_values with 4.1.0
+ # https://gitlab.gnome.org/GNOME/gtk/-/commit/a1216599ff6b39bca3e9
+ if not hasattr(Gtk.ListStore, "insert_with_valuesv"):
+ insert_with_valuesv = Gtk.ListStore.insert_with_values
+ elif not hasattr(Gtk.ListStore, "insert_with_values"):
+ insert_with_values = Gtk.ListStore.insert_with_valuesv
+
def _do_insert(self, position, row):
if row is not None:
row, columns = self._convert_row(row)
- treeiter = self.insert_with_valuesv(position, columns, row)
+ treeiter = self.insert_with_values(position, columns, row)
else:
treeiter = Gtk.ListStore.insert(self, position)
@@ -954,58 +1014,59 @@ class ListStore(Gtk.ListStore, TreeModel, TreeSortable):
def insert(self, position, row=None):
return self._do_insert(position, row)
- # FIXME: sends two signals; check if this can use an atomic
- # insert_with_valuesv()
-
def insert_before(self, sibling, row=None):
- treeiter = Gtk.ListStore.insert_before(self, sibling)
-
if row is not None:
- self.set_row(treeiter, row)
-
- return treeiter
+ if sibling is None:
+ position = -1
+ else:
+ position = self.get_path(sibling).get_indices()[-1]
+ return self._do_insert(position, row)
- # FIXME: sends two signals; check if this can use an atomic
- # insert_with_valuesv()
+ return Gtk.ListStore.insert_before(self, sibling)
def insert_after(self, sibling, row=None):
- treeiter = Gtk.ListStore.insert_after(self, sibling)
-
if row is not None:
- self.set_row(treeiter, row)
+ if sibling is None:
+ position = 0
+ else:
+ position = self.get_path(sibling).get_indices()[-1] + 1
+ return self._do_insert(position, row)
- return treeiter
+ return Gtk.ListStore.insert_after(self, sibling)
def set_value(self, treeiter, column, value):
value = self._convert_value(column, value)
Gtk.ListStore.set_value(self, treeiter, column, value)
def set(self, treeiter, *args):
-
- def _set_lists(columns, values):
- if len(columns) != len(values):
+ def _set_lists(cols, vals):
+ if len(cols) != len(vals):
raise TypeError('The number of columns do not match the number of values')
- for col_num, val in zip(columns, values):
+
+ columns = []
+ values = []
+ for col_num, value in zip(cols, vals):
if not isinstance(col_num, int):
raise TypeError('TypeError: Expected integer argument for column.')
- self.set_value(treeiter, col_num, val)
+
+ columns.append(col_num)
+ values.append(self._convert_value(col_num, value))
+
+ Gtk.ListStore.set(self, treeiter, columns, values)
if args:
if isinstance(args[0], int):
- columns = args[::2]
- values = args[1::2]
- _set_lists(columns, values)
+ _set_lists(args[::2], args[1::2])
elif isinstance(args[0], (tuple, list)):
if len(args) != 2:
raise TypeError('Too many arguments')
_set_lists(args[0], args[1])
elif isinstance(args[0], dict):
- columns = args[0].keys()
- values = args[0].values()
- _set_lists(columns, values)
+ _set_lists(list(args[0]), args[0].values())
else:
raise TypeError('Argument list must be in the form of (column, value, ...), ((columns,...), (values, ...)) or {column: value}. No -1 termination is needed.')
+
ListStore = override(ListStore)
__all__.append('ListStore')
@@ -1021,8 +1082,8 @@ class TreeModelRow(object):
elif isinstance(iter_or_path, Gtk.TreeIter):
self.iter = iter_or_path
else:
- raise TypeError("expected Gtk.TreeIter or Gtk.TreePath, \
- %s found" % type(iter_or_path).__name__)
+ raise TypeError("expected Gtk.TreeIter or Gtk.TreePath, "
+ "%s found" % type(iter_or_path).__name__)
@property
def path(self):
@@ -1068,8 +1129,11 @@ class TreeModelRow(object):
for i in range(start, stop, step):
alist.append(self.model.get_value(self.iter, i))
return alist
+ elif isinstance(key, tuple):
+ return [self[k] for k in key]
else:
- raise TypeError("indices must be integers, not %s" % type(key).__name__)
+ raise TypeError("indices must be integers, slice or tuple, not %s"
+ % type(key).__name__)
def __setitem__(self, key, value):
if isinstance(key, int):
@@ -1088,8 +1152,16 @@ class TreeModelRow(object):
for i, v in enumerate(indexList):
self.model.set_value(self.iter, v, value[i])
+ elif isinstance(key, tuple):
+ if len(key) != len(value):
+ raise ValueError(
+ "attempt to assign sequence of size %d to sequence of size %d"
+ % (len(value), len(key)))
+ for k, v in zip(key, value):
+ self[k] = v
else:
- raise TypeError("index must be an integer or slice, not %s" % type(key).__name__)
+ raise TypeError("indices must be an integer, slice or tuple, not %s"
+ % type(key).__name__)
def _convert_negative_index(self, index):
new_index = self.model.get_n_columns() + index
@@ -1101,6 +1173,7 @@ class TreeModelRow(object):
child_iter = self.model.iter_children(self.iter)
return TreeModelRowIter(self.model, child_iter)
+
__all__.append('TreeModelRow')
@@ -1117,12 +1190,14 @@ class TreeModelRowIter(object):
self.iter = self.model.iter_next(self.iter)
return row
- # alias for Python 2.x object protocol
- next = __next__
+ if GTK3:
+ # alias for Python 2.x object protocol
+ next = __next__
def __iter__(self):
return self
+
__all__.append('TreeModelRowIter')
@@ -1131,7 +1206,7 @@ class TreePath(Gtk.TreePath):
def __new__(cls, path=0):
if isinstance(path, int):
path = str(path)
- elif not isinstance(path, _basestring):
+ elif not isinstance(path, str):
path = ":".join(str(val) for val in path)
if len(path) == 0:
@@ -1141,17 +1216,20 @@ class TreePath(Gtk.TreePath):
except TypeError:
raise TypeError("could not parse subscript '%s' as a tree path" % path)
+ def __init__(self, *args, **kwargs):
+ super(TreePath, self).__init__()
+
def __str__(self):
- return self.to_string()
+ return self.to_string() or ""
def __lt__(self, other):
- return not other is None and self.compare(other) < 0
+ return other is not None and self.compare(other) < 0
def __le__(self, other):
- return not other is None and self.compare(other) <= 0
+ return other is not None and self.compare(other) <= 0
def __eq__(self, other):
- return not other is None and self.compare(other) == 0
+ return other is not None and self.compare(other) == 0
def __ne__(self, other):
return other is None or self.compare(other) != 0
@@ -1171,12 +1249,12 @@ class TreePath(Gtk.TreePath):
def __getitem__(self, index):
return self.get_indices()[index]
+
TreePath = override(TreePath)
__all__.append('TreePath')
class TreeStore(Gtk.TreeStore, TreeModel, TreeSortable):
-
def __init__(self, *column_types):
Gtk.TreeStore.__init__(self)
self.set_column_types(column_types)
@@ -1199,83 +1277,89 @@ class TreeStore(Gtk.TreeStore, TreeModel, TreeSortable):
def insert(self, parent, position, row=None):
return self._do_insert(parent, position, row)
- # FIXME: sends two signals; check if this can use an atomic
- # insert_with_valuesv()
-
def insert_before(self, parent, sibling, row=None):
- treeiter = Gtk.TreeStore.insert_before(self, parent, sibling)
-
if row is not None:
- self.set_row(treeiter, row)
-
- return treeiter
+ if sibling is None:
+ position = -1
+ else:
+ if parent is None:
+ parent = self.iter_parent(sibling)
+ position = self.get_path(sibling).get_indices()[-1]
+ return self._do_insert(parent, position, row)
- # FIXME: sends two signals; check if this can use an atomic
- # insert_with_valuesv()
+ return Gtk.TreeStore.insert_before(self, parent, sibling)
def insert_after(self, parent, sibling, row=None):
- treeiter = Gtk.TreeStore.insert_after(self, parent, sibling)
-
if row is not None:
- self.set_row(treeiter, row)
+ if sibling is None:
+ position = 0
+ else:
+ if parent is None:
+ parent = self.iter_parent(sibling)
+ position = self.get_path(sibling).get_indices()[-1] + 1
+ return self._do_insert(parent, position, row)
- return treeiter
+ return Gtk.TreeStore.insert_after(self, parent, sibling)
def set_value(self, treeiter, column, value):
value = self._convert_value(column, value)
Gtk.TreeStore.set_value(self, treeiter, column, value)
def set(self, treeiter, *args):
-
- def _set_lists(columns, values):
- if len(columns) != len(values):
+ def _set_lists(cols, vals):
+ if len(cols) != len(vals):
raise TypeError('The number of columns do not match the number of values')
- for col_num, val in zip(columns, values):
+
+ columns = []
+ values = []
+ for col_num, value in zip(cols, vals):
if not isinstance(col_num, int):
raise TypeError('TypeError: Expected integer argument for column.')
- self.set_value(treeiter, col_num, val)
+
+ columns.append(col_num)
+ values.append(self._convert_value(col_num, value))
+
+ Gtk.TreeStore.set(self, treeiter, columns, values)
if args:
if isinstance(args[0], int):
- columns = args[::2]
- values = args[1::2]
- _set_lists(columns, values)
+ _set_lists(args[::2], args[1::2])
elif isinstance(args[0], (tuple, list)):
if len(args) != 2:
raise TypeError('Too many arguments')
_set_lists(args[0], args[1])
elif isinstance(args[0], dict):
- columns = args[0].keys()
- values = args[0].values()
- _set_lists(columns, values)
+ _set_lists(args[0].keys(), args[0].values())
else:
raise TypeError('Argument list must be in the form of (column, value, ...), ((columns,...), (values, ...)) or {column: value}. No -1 termination is needed.')
+
TreeStore = override(TreeStore)
__all__.append('TreeStore')
class TreeView(Gtk.TreeView, Container):
-
- def __init__(self, model=None):
- Gtk.TreeView.__init__(self)
- if model:
- self.set_model(model)
+ if GTK3:
+ __init__ = deprecated_init(Gtk.TreeView.__init__,
+ arg_names=('model',),
+ category=PyGTKDeprecationWarning)
get_path_at_pos = strip_boolean_result(Gtk.TreeView.get_path_at_pos)
get_visible_range = strip_boolean_result(Gtk.TreeView.get_visible_range)
get_dest_row_at_pos = strip_boolean_result(Gtk.TreeView.get_dest_row_at_pos)
- def enable_model_drag_source(self, start_button_mask, targets, actions):
- target_entries = _construct_target_list(targets)
- super(TreeView, self).enable_model_drag_source(start_button_mask,
- target_entries,
- actions)
+ if GTK3:
+ def enable_model_drag_source(self, start_button_mask, targets, actions):
+ target_entries = _construct_target_list(targets)
+ super(TreeView, self).enable_model_drag_source(start_button_mask,
+ target_entries,
+ actions)
- def enable_model_drag_dest(self, targets, actions):
- target_entries = _construct_target_list(targets)
- super(TreeView, self).enable_model_drag_dest(target_entries,
- actions)
+ if GTK3:
+ def enable_model_drag_dest(self, targets, actions):
+ target_entries = _construct_target_list(targets)
+ super(TreeView, self).enable_model_drag_dest(target_entries,
+ actions)
def scroll_to_cell(self, path, column=None, use_align=False, row_align=0.0, col_align=0.0):
if not isinstance(path, Gtk.TreePath):
@@ -1299,6 +1383,7 @@ class TreeView(Gtk.TreeView, Container):
self.insert_column(column, position)
column.set_attributes(cell, **kwargs)
+
TreeView = override(TreeView)
__all__.append('TreeView')
@@ -1355,140 +1440,183 @@ TreeSelection = override(TreeSelection)
__all__.append('TreeSelection')
-class Button(Gtk.Button, Container):
- def __init__(self, label=None, stock=None, use_stock=False, use_underline=False, **kwds):
- if stock:
- label = stock
- use_stock = True
- use_underline = True
- Gtk.Button.__init__(self, label=label, use_stock=use_stock,
- use_underline=use_underline, **kwds)
-Button = override(Button)
-__all__.append('Button')
+if GTK3:
+ class Button(Gtk.Button, Container):
+ _init = deprecated_init(Gtk.Button.__init__,
+ arg_names=('label', 'stock', 'use_stock', 'use_underline'),
+ ignore=('stock',),
+ category=PyGTKDeprecationWarning,
+ stacklevel=3)
+
+ def __init__(self, *args, **kwargs):
+ # Doubly deprecated initializer, the stock keyword is non-standard.
+ # Simply give a warning that stock items are deprecated even though
+ # we want to deprecate the non-standard keyword as well here from
+ # the overrides.
+ if 'stock' in kwargs and kwargs['stock']:
+ warnings.warn('Stock items are deprecated. '
+ 'Please use: Gtk.Button.new_with_mnemonic(label)',
+ PyGTKDeprecationWarning, stacklevel=2)
+ new_kwargs = kwargs.copy()
+ new_kwargs['label'] = new_kwargs['stock']
+ new_kwargs['use_stock'] = True
+ new_kwargs['use_underline'] = True
+ del new_kwargs['stock']
+ Gtk.Button.__init__(self, **new_kwargs)
+ else:
+ self._init(*args, **kwargs)
+ if hasattr(Gtk.Widget, "set_focus_on_click"):
+ def set_focus_on_click(self, *args, **kwargs):
+ # Gtk.Widget.set_focus_on_click should be used instead but it's
+ # no obvious how because of the shadowed method, so override here
+ return Gtk.Widget.set_focus_on_click(self, *args, **kwargs)
-class LinkButton(Gtk.LinkButton):
- def __init__(self, uri, label=None, **kwds):
- Gtk.LinkButton.__init__(self, uri=uri, label=label, **kwds)
+ if hasattr(Gtk.Widget, "get_focus_on_click"):
+ def get_focus_on_click(self, *args, **kwargs):
+ # Gtk.Widget.get_focus_on_click should be used instead but it's
+ # no obvious how because of the shadowed method, so override here
+ return Gtk.Widget.get_focus_on_click(self, *args, **kwargs)
-LinkButton = override(LinkButton)
-__all__.append('LinkButton')
+ Button = override(Button)
+ __all__.append('Button')
+ class LinkButton(Gtk.LinkButton):
+ __init__ = deprecated_init(Gtk.LinkButton.__init__,
+ arg_names=('uri', 'label'),
+ category=PyGTKDeprecationWarning)
-class Label(Gtk.Label):
- def __init__(self, label=None, **kwds):
- Gtk.Label.__init__(self, label=label, **kwds)
+ LinkButton = override(LinkButton)
+ __all__.append('LinkButton')
-Label = override(Label)
-__all__.append('Label')
+ class Label(Gtk.Label):
+ __init__ = deprecated_init(Gtk.Label.__init__,
+ arg_names=('label',),
+ category=PyGTKDeprecationWarning)
+ Label = override(Label)
+ __all__.append('Label')
-class Adjustment(Gtk.Adjustment):
- def __init__(self, *args, **kwds):
- arg_names = ('value', 'lower', 'upper',
- 'step_increment', 'page_increment', 'page_size')
- new_args = dict(zip(arg_names, args))
- new_args.update(kwds)
-
- # PyGTK compatiblity
- if 'page_incr' in new_args:
- new_args['page_increment'] = new_args.pop('page_incr')
- if 'step_incr' in new_args:
- new_args['step_increment'] = new_args.pop('step_incr')
- Gtk.Adjustment.__init__(self, **new_args)
-
- # The value property is set between lower and (upper - page_size).
- # Just in case lower, upper or page_size was still 0 when value
- # was set, we set it again here.
- if 'value' in new_args:
- self.set_value(new_args['value'])
-Adjustment = override(Adjustment)
-__all__.append('Adjustment')
-
-
-class Table(Gtk.Table, Container):
- def __init__(self, rows=1, columns=1, homogeneous=False, **kwds):
- if 'n_rows' in kwds:
- rows = kwds.pop('n_rows')
+class Adjustment(Gtk.Adjustment):
+ if GTK3:
+ _init = deprecated_init(Gtk.Adjustment.__init__,
+ arg_names=('value', 'lower', 'upper',
+ 'step_increment', 'page_increment', 'page_size'),
+ deprecated_aliases={'page_increment': 'page_incr',
+ 'step_increment': 'step_incr'},
+ category=PyGTKDeprecationWarning,
+ stacklevel=3)
+
+ def __init__(self, *args, **kwargs):
+ if GTK3:
+ self._init(*args, **kwargs)
+ # The value property is set between lower and (upper - page_size).
+ # Just in case lower, upper or page_size was still 0 when value
+ # was set, we set it again here.
+ if 'value' in kwargs:
+ self.set_value(kwargs['value'])
+ elif len(args) >= 1:
+ self.set_value(args[0])
+ else:
+ Gtk.Adjustment.__init__(self, *args, **kwargs)
- if 'n_columns' in kwds:
- columns = kwds.pop('n_columns')
+ # The value property is set between lower and (upper - page_size).
+ # Just in case lower, upper or page_size was still 0 when value
+ # was set, we set it again here.
+ if 'value' in kwargs:
+ self.set_value(kwargs['value'])
- Gtk.Table.__init__(self, n_rows=rows, n_columns=columns, homogeneous=homogeneous, **kwds)
- def attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions=Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, xpadding=0, ypadding=0):
- Gtk.Table.attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions, yoptions, xpadding, ypadding)
+Adjustment = override(Adjustment)
+__all__.append('Adjustment')
-Table = override(Table)
-__all__.append('Table')
+if GTK3:
+ class Table(Gtk.Table, Container):
+ __init__ = deprecated_init(Gtk.Table.__init__,
+ arg_names=('n_rows', 'n_columns', 'homogeneous'),
+ deprecated_aliases={'n_rows': 'rows', 'n_columns': 'columns'},
+ category=PyGTKDeprecationWarning)
-class ScrolledWindow(Gtk.ScrolledWindow):
- def __init__(self, hadjustment=None, vadjustment=None, **kwds):
- Gtk.ScrolledWindow.__init__(self, hadjustment=hadjustment, vadjustment=vadjustment, **kwds)
+ def attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions=Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, xpadding=0, ypadding=0):
+ Gtk.Table.attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions, yoptions, xpadding, ypadding)
-ScrolledWindow = override(ScrolledWindow)
-__all__.append('ScrolledWindow')
+ Table = override(Table)
+ __all__.append('Table')
+ class ScrolledWindow(Gtk.ScrolledWindow):
+ __init__ = deprecated_init(Gtk.ScrolledWindow.__init__,
+ arg_names=('hadjustment', 'vadjustment'),
+ category=PyGTKDeprecationWarning)
-class HScrollbar(Gtk.HScrollbar):
- def __init__(self, adjustment=None, **kwds):
- Gtk.HScrollbar.__init__(self, adjustment=adjustment, **kwds)
+ ScrolledWindow = override(ScrolledWindow)
+ __all__.append('ScrolledWindow')
-HScrollbar = override(HScrollbar)
-__all__.append('HScrollbar')
+if GTK3:
+ class HScrollbar(Gtk.HScrollbar):
+ __init__ = deprecated_init(Gtk.HScrollbar.__init__,
+ arg_names=('adjustment',),
+ category=PyGTKDeprecationWarning)
-class VScrollbar(Gtk.VScrollbar):
- def __init__(self, adjustment=None, **kwds):
- Gtk.VScrollbar.__init__(self, adjustment=adjustment, **kwds)
+ HScrollbar = override(HScrollbar)
+ __all__.append('HScrollbar')
-VScrollbar = override(VScrollbar)
-__all__.append('VScrollbar')
+ class VScrollbar(Gtk.VScrollbar):
+ __init__ = deprecated_init(Gtk.VScrollbar.__init__,
+ arg_names=('adjustment',),
+ category=PyGTKDeprecationWarning)
+ VScrollbar = override(VScrollbar)
+ __all__.append('VScrollbar')
-class Paned(Gtk.Paned):
- def pack1(self, child, resize=False, shrink=True):
- super(Paned, self).pack1(child, resize, shrink)
- def pack2(self, child, resize=True, shrink=True):
- super(Paned, self).pack2(child, resize, shrink)
+if GTK3:
+ class Paned(Gtk.Paned):
+ def pack1(self, child, resize=False, shrink=True):
+ super(Paned, self).pack1(child, resize, shrink)
-Paned = override(Paned)
-__all__.append('Paned')
+ def pack2(self, child, resize=True, shrink=True):
+ super(Paned, self).pack2(child, resize, shrink)
+ Paned = override(Paned)
+ __all__.append('Paned')
-class Arrow(Gtk.Arrow):
- def __init__(self, arrow_type, shadow_type, **kwds):
- Gtk.Arrow.__init__(self, arrow_type=arrow_type,
- shadow_type=shadow_type,
- **kwds)
-Arrow = override(Arrow)
-__all__.append('Arrow')
+if GTK3:
+ class Arrow(Gtk.Arrow):
+ __init__ = deprecated_init(Gtk.Arrow.__init__,
+ arg_names=('arrow_type', 'shadow_type'),
+ category=PyGTKDeprecationWarning)
+ Arrow = override(Arrow)
+ __all__.append('Arrow')
-class IconSet(Gtk.IconSet):
- def __new__(cls, pixbuf=None):
- if pixbuf is not None:
- iconset = Gtk.IconSet.new_from_pixbuf(pixbuf)
- else:
- iconset = Gtk.IconSet.__new__(cls)
- return iconset
+ class IconSet(Gtk.IconSet):
+ def __new__(cls, pixbuf=None):
+ if pixbuf is not None:
+ warnings.warn('Gtk.IconSet(pixbuf) has been deprecated. Please use: '
+ 'Gtk.IconSet.new_from_pixbuf(pixbuf)',
+ PyGTKDeprecationWarning, stacklevel=2)
+ iconset = Gtk.IconSet.new_from_pixbuf(pixbuf)
+ else:
+ iconset = Gtk.IconSet.__new__(cls)
+ return iconset
-IconSet = override(IconSet)
-__all__.append('IconSet')
+ def __init__(self, *args, **kwargs):
+ return super(IconSet, self).__init__()
+ IconSet = override(IconSet)
+ __all__.append('IconSet')
-class Viewport(Gtk.Viewport):
- def __init__(self, hadjustment=None, vadjustment=None, **kwds):
- Gtk.Viewport.__init__(self, hadjustment=hadjustment,
- vadjustment=vadjustment,
- **kwds)
+ class Viewport(Gtk.Viewport):
+ __init__ = deprecated_init(Gtk.Viewport.__init__,
+ arg_names=('hadjustment', 'vadjustment'),
+ category=PyGTKDeprecationWarning)
-Viewport = override(Viewport)
-__all__.append('Viewport')
+ Viewport = override(Viewport)
+ __all__.append('Viewport')
class TreeModelFilter(Gtk.TreeModelFilter):
@@ -1500,25 +1628,78 @@ class TreeModelFilter(Gtk.TreeModelFilter):
iter = self.convert_iter_to_child_iter(iter)
self.get_model().set_value(iter, column, value)
+
TreeModelFilter = override(TreeModelFilter)
__all__.append('TreeModelFilter')
-if Gtk._version != '2.0':
+
+class CssProvider(Gtk.CssProvider):
+ def load_from_data(self, text, length=-1):
+ if (Gtk.get_major_version(), Gtk.get_minor_version()) >= (4, 9):
+ if isinstance(text, bytes):
+ text = text.decode("utf-8")
+ super(CssProvider, self).load_from_data(text, length)
+ else:
+ if isinstance(text, str):
+ text = text.encode("utf-8")
+ super(CssProvider, self).load_from_data(text)
+
+
+CssProvider = override(CssProvider)
+__all__.append("CssProvider")
+
+if GTK4:
+ class CustomSorter(Gtk.CustomSorter):
+
+ @classmethod
+ def new(cls, sort_func, user_data=None):
+ if sort_func is not None:
+ compare_func = wrap_list_store_sort_func(sort_func)
+ else:
+ compare_func = None
+
+ return Gtk.CustomSorter.new(compare_func, user_data)
+
+ def set_sort_func(self, sort_func, user_data=None):
+ if sort_func is not None:
+ compare_func = wrap_list_store_sort_func(sort_func)
+ else:
+ compare_func = None
+
+ return super(CustomSorter, self).set_sort_func(compare_func, user_data)
+
+ CustomSorter = override(CustomSorter)
+ __all__.append("CustomSorter")
+
+if GTK3:
class Menu(Gtk.Menu):
def popup(self, parent_menu_shell, parent_menu_item, func, data, button, activate_time):
self.popup_for_device(None, parent_menu_shell, parent_menu_item, func, data, button, activate_time)
Menu = override(Menu)
__all__.append('Menu')
-_Gtk_main_quit = Gtk.main_quit
+if GTK3:
+ _Gtk_main_quit = Gtk.main_quit
+
+ @override(Gtk.main_quit)
+ def main_quit(*args):
+ _Gtk_main_quit()
+ _Gtk_main = Gtk.main
-@override(Gtk.main_quit)
-def main_quit(*args):
- _Gtk_main_quit()
+ @override(Gtk.main)
+ def main(*args, **kwargs):
+ with register_sigint_fallback(Gtk.main_quit):
+ with wakeup_on_signal():
+ return _Gtk_main(*args, **kwargs)
-stock_lookup = strip_boolean_result(Gtk.stock_lookup)
-__all__.append('stock_lookup')
-initialized, argv = Gtk.init_check(sys.argv)
-sys.argv = list(argv)
+if GTK3:
+ stock_lookup = strip_boolean_result(Gtk.stock_lookup)
+ __all__.append('stock_lookup')
+
+if GTK4:
+ initialized = Gtk.init_check()
+else:
+ initialized, argv = Gtk.init_check(sys.argv)
+ sys.argv = list(argv)
diff --git a/gi/overrides/Makefile.am b/gi/overrides/Makefile.am
deleted file mode 100644
index e69c91c..0000000
--- a/gi/overrides/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-pygioverridesdir = $(pyexecdir)/gi/overrides
-
-pygioverrides_PYTHON = \
- GLib.py \
- Gtk.py \
- Gdk.py \
- GObject.py \
- Gio.py \
- GIMarshallingTests.py \
- Pango.py \
- keysyms.py \
- __init__.py
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pygioverrides_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-all-local: build_pylinks
-check-local: build_pylinks
diff --git a/gi/overrides/Makefile.in b/gi/overrides/Makefile.in
deleted file mode 100644
index 7b2d5ab..0000000
--- a/gi/overrides/Makefile.in
+++ /dev/null
@@ -1,582 +0,0 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = gi/overrides
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(pygioverrides_PYTHON) $(top_srcdir)/py-compile
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
- $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-SOURCES =
-DIST_SOURCES =
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile)
-am__installdirs = "$(DESTDIR)$(pygioverridesdir)"
-am__pep3147_tweak = \
- sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|'
-py_compile = $(top_srcdir)/py-compile
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CAIRO_CFLAGS = @CAIRO_CFLAGS@
-CAIRO_LIBS = @CAIRO_LIBS@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
-CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
-CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DATADIR = @DATADIR@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FFI_CFLAGS = @FFI_CFLAGS@
-FFI_LIBS = @FFI_LIBS@
-FGREP = @FGREP@
-GENHTML = @GENHTML@
-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_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
-GLIB_LIBS = @GLIB_LIBS@
-GLIB_MKENUMS = @GLIB_MKENUMS@
-GOBJECT_QUERY = @GOBJECT_QUERY@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
-INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBFFI_PC = @LIBFFI_PC@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLATFORM = @PLATFORM@
-PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@
-PYCAIRO_LIBS = @PYCAIRO_LIBS@
-PYGOBJECT_MAJOR_VERSION = @PYGOBJECT_MAJOR_VERSION@
-PYGOBJECT_MICRO_VERSION = @PYGOBJECT_MICRO_VERSION@
-PYGOBJECT_MINOR_VERSION = @PYGOBJECT_MINOR_VERSION@
-PYTHON = @PYTHON@
-PYTHON_BASENAME = @PYTHON_BASENAME@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_INCLUDES = @PYTHON_INCLUDES@
-PYTHON_LIBS = @PYTHON_LIBS@
-PYTHON_LIB_LOC = @PYTHON_LIB_LOC@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_SO = @PYTHON_SO@
-PYTHON_VERSION = @PYTHON_VERSION@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-THREADING_CFLAGS = @THREADING_CFLAGS@
-VERSION = @VERSION@
-WARN_CFLAGS = @WARN_CFLAGS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-pygioverridesdir = $(pyexecdir)/gi/overrides
-pygioverrides_PYTHON = \
- GLib.py \
- Gtk.py \
- Gdk.py \
- GObject.py \
- Gio.py \
- GIMarshallingTests.py \
- Pango.py \
- keysyms.py \
- __init__.py
-
-all: all-am
-
-.SUFFIXES:
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign gi/overrides/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign gi/overrides/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-pygioverridesPYTHON: $(pygioverrides_PYTHON)
- @$(NORMAL_INSTALL)
- @list='$(pygioverrides_PYTHON)'; dlist=; list2=; test -n "$(pygioverridesdir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(pygioverridesdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pygioverridesdir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \
- if test -f $$b$$p; then \
- $(am__strip_dir) \
- dlist="$$dlist $$f"; \
- list2="$$list2 $$b$$p"; \
- else :; fi; \
- done; \
- for file in $$list2; do echo $$file; done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pygioverridesdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(pygioverridesdir)" || exit $$?; \
- done || exit $$?; \
- if test -n "$$dlist"; then \
- $(am__py_compile) --destdir "$(DESTDIR)" \
- --basedir "$(pygioverridesdir)" $$dlist; \
- else :; fi
-
-uninstall-pygioverridesPYTHON:
- @$(NORMAL_UNINSTALL)
- @list='$(pygioverrides_PYTHON)'; test -n "$(pygioverridesdir)" || list=; \
- py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$py_files" || exit 0; \
- dir='$(DESTDIR)$(pygioverridesdir)'; \
- pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \
- pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \
- py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \
- echo "$$py_files_pep3147";\
- pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \
- pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \
- st=0; \
- for files in \
- "$$py_files" \
- "$$pyc_files" \
- "$$pyo_files" \
- "$$pyc_files_pep3147" \
- "$$pyo_files_pep3147" \
- ; do \
- $(am__uninstall_files_from_dir) || st=$$?; \
- done; \
- exit $$st
-tags TAGS:
-
-ctags CTAGS:
-
-cscope cscopelist:
-
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) check-local
-check: check-am
-all-am: Makefile all-local
-installdirs:
- for dir in "$(DESTDIR)$(pygioverridesdir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-am
- -rm -f Makefile
-distclean-am: clean-am distclean-generic
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-pygioverridesPYTHON
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-pygioverridesPYTHON
-
-.MAKE: check-am install-am install-strip
-
-.PHONY: all all-am all-local check check-am check-local clean \
- clean-generic clean-libtool cscopelist-am ctags-am distclean \
- distclean-generic distclean-libtool distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-pdf install-pdf-am \
- install-ps install-ps-am install-pygioverridesPYTHON \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags-am uninstall uninstall-am uninstall-pygioverridesPYTHON
-
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pygioverrides_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-all-local: build_pylinks
-check-local: build_pylinks
-
-# 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.
-.NOEXPORT:
diff --git a/gi/overrides/Pango.py b/gi/overrides/Pango.py
index 15d5edc..7d0d8cf 100644
--- a/gi/overrides/Pango.py
+++ b/gi/overrides/Pango.py
@@ -26,15 +26,6 @@ Pango = get_introspection_module('Pango')
__all__ = []
-class Context(Pango.Context):
-
- def get_metrics(self, desc, language=None):
- return super(Context, self).get_metrics(desc, language)
-
-Context = override(Context)
-__all__.append('Context')
-
-
class FontDescription(Pango.FontDescription):
def __new__(cls, string=None):
@@ -43,6 +34,10 @@ class FontDescription(Pango.FontDescription):
else:
return Pango.FontDescription.__new__(cls)
+ def __init__(self, *args, **kwargs):
+ return super(FontDescription, self).__init__()
+
+
FontDescription = override(FontDescription)
__all__.append('FontDescription')
@@ -52,13 +47,12 @@ class Layout(Pango.Layout):
def __new__(cls, context):
return Pango.Layout.new(context)
- def __init__(self, context, **kwds):
- # simply discard 'context', since it was set by
- # __new__ and it is not a PangoLayout property
- super(Layout, self).__init__(**kwds)
-
def set_markup(self, text, length=-1):
super(Layout, self).set_markup(text, length)
+ def set_text(self, text, length=-1):
+ super(Layout, self).set_text(text, length)
+
+
Layout = override(Layout)
__all__.append('Layout')
diff --git a/gi/overrides/__init__.py b/gi/overrides/__init__.py
index 8aa9731..37dfbbe 100644
--- a/gi/overrides/__init__.py
+++ b/gi/overrides/__init__.py
@@ -1,10 +1,13 @@
+import functools
import types
import warnings
-import functools
+import importlib
+import sys
+from pkgutil import get_loader
from gi import PyGIDeprecationWarning
-from gi._gi import CallableInfo
-from gi._gobject.constants import \
+from gi._gi import CallableInfo, pygobject_new_full
+from gi._constants import \
TYPE_NONE, \
TYPE_INVALID
@@ -12,76 +15,200 @@ from gi._gobject.constants import \
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
-registry = None
+# namespace -> (attr, replacement)
+_deprecated_attrs = {}
+
+
+class OverridesProxyModule(types.ModuleType):
+ """Wraps a introspection module and contains all overrides"""
+
+ def __init__(self, introspection_module):
+ super(OverridesProxyModule, self).__init__(
+ introspection_module.__name__)
+ self._introspection_module = introspection_module
+
+ def __getattr__(self, name):
+ return getattr(self._introspection_module, name)
+
+ def __dir__(self):
+ result = set(dir(self.__class__))
+ result.update(self.__dict__.keys())
+ result.update(dir(self._introspection_module))
+ return sorted(result)
+
+ def __repr__(self):
+ return "<%s %r>" % (type(self).__name__, self._introspection_module)
+
+
+class _DeprecatedAttribute(object):
+ """A deprecation descriptor for OverridesProxyModule subclasses.
+
+ Emits a PyGIDeprecationWarning on every access and tries to act as a
+ normal instance attribute (can be replaced and deleted).
+ """
+
+ def __init__(self, namespace, attr, value, replacement):
+ self._attr = attr
+ self._value = value
+ self._warning = PyGIDeprecationWarning(
+ '%s.%s is deprecated; use %s instead' % (
+ namespace, attr, replacement))
+
+ def __get__(self, instance, owner):
+ if instance is None:
+ raise AttributeError(self._attr)
+ warnings.warn(self._warning, stacklevel=2)
+ return self._value
+
+ def __set__(self, instance, value):
+ attr = self._attr
+ # delete the descriptor, then set the instance value
+ delattr(type(instance), attr)
+ setattr(instance, attr, value)
+
+ def __delete__(self, instance):
+ # delete the descriptor
+ delattr(type(instance), self._attr)
+
+
+def load_overrides(introspection_module):
+ """Loads overrides for an introspection module.
+
+ Either returns the same module again in case there are no overrides or a
+ proxy module including overrides. Doesn't cache the result.
+ """
-class _Registry(dict):
- def __setitem__(self, key, value):
- '''We do checks here to make sure only submodules of the override
- module are added. Key and value should be the same object and come
- from the gi.override module.
+ namespace = introspection_module.__name__.rsplit(".", 1)[-1]
+ module_key = 'gi.repository.' + namespace
- We add the override to the dict as "override_module.name". For instance
- if we were overriding Gtk.Button you would retrive it as such:
- registry['Gtk.Button']
- '''
- if not key == value:
- raise KeyError('You have tried to modify the registry. This should only be done by the override decorator')
+ # We use sys.modules so overrides can import from gi.repository
+ # but restore everything at the end so this doesn't have any side effects
+ has_old = module_key in sys.modules
+ old_module = sys.modules.get(module_key)
+ # Create a new sub type, so we can separate descriptors like
+ # _DeprecatedAttribute for each namespace.
+ proxy_type = type(namespace + "ProxyModule", (OverridesProxyModule, ), {})
+
+ proxy = proxy_type(introspection_module)
+ sys.modules[module_key] = proxy
+
+ # backwards compat:
+ # gedit uses gi.importer.modules['Gedit']._introspection_module
+ from ..importer import modules
+ assert hasattr(proxy, "_introspection_module")
+ modules[namespace] = proxy
+
+ try:
+ override_package_name = 'gi.overrides.' + namespace
+
+ # http://bugs.python.org/issue14710
try:
- info = getattr(value, '__info__')
+ override_loader = get_loader(override_package_name)
+
except AttributeError:
- raise TypeError('Can not override a type %s, which is not in a gobject introspection typelib' % value.__name__)
+ override_loader = None
- if not value.__module__.startswith('gi.overrides'):
- raise KeyError('You have tried to modify the registry outside of the overrides module. '
- 'This is not allowed (%s, %s)' % (value, value.__module__))
+ # Avoid checking for an ImportError, an override might
+ # depend on a missing module thus causing an ImportError
+ if override_loader is None:
+ return introspection_module
- g_type = info.get_g_type()
- assert g_type != TYPE_NONE
- if g_type != TYPE_INVALID:
- g_type.pytype = value
-
- # strip gi.overrides from module name
- module = value.__module__[13:]
- key = "%s.%s" % (module, value.__name__)
- super(_Registry, self).__setitem__(key, value)
-
- def register(self, override_class):
- self[override_class] = override_class
-
-
-class overridefunc(object):
- '''decorator for overriding a function'''
- def __init__(self, func):
- if not isinstance(func, CallableInfo):
- raise TypeError("func must be a gi function, got %s" % func)
- from ..importer import modules
- module_name = func.__module__.rsplit('.', 1)[-1]
- self.module = modules[module_name]._introspection_module
-
- def __call__(self, func):
- def wrapper(*args, **kwargs):
- return func(*args, **kwargs)
- wrapper.__name__ = func.__name__
- wrapper.__doc__ = func.__doc__
- setattr(self.module, func.__name__, wrapper)
- return wrapper
+ override_mod = importlib.import_module(override_package_name)
-registry = _Registry()
+ finally:
+ del modules[namespace]
+ del sys.modules[module_key]
+ if has_old:
+ sys.modules[module_key] = old_module
+
+ # backwards compat: for gst-python/gstmodule.c,
+ # which tries to access Gst.Fraction through
+ # Gst._overrides_module.Fraction. We assign the proxy instead as that
+ # contains all overridden classes like Fraction during import anyway and
+ # there is no need to keep the real override module alive.
+ proxy._overrides_module = proxy
+
+ override_all = []
+ if hasattr(override_mod, "__all__"):
+ override_all = override_mod.__all__
+
+ for var in override_all:
+ try:
+ item = getattr(override_mod, var)
+ except (AttributeError, TypeError):
+ # Gedit puts a non-string in __all__, so catch TypeError here
+ continue
+ setattr(proxy, var, item)
+
+ # Replace deprecated module level attributes with a descriptor
+ # which emits a warning when accessed.
+ for attr, replacement in _deprecated_attrs.pop(namespace, []):
+ try:
+ value = getattr(proxy, attr)
+ except AttributeError:
+ raise AssertionError(
+ "%s was set deprecated but wasn't added to __all__" % attr)
+ delattr(proxy, attr)
+ deprecated_attr = _DeprecatedAttribute(
+ namespace, attr, value, replacement)
+ setattr(proxy_type, attr, deprecated_attr)
+
+ return proxy
def override(type_):
- '''Decorator for registering an override'''
- if isinstance(type_, (types.FunctionType, CallableInfo)):
- return overridefunc(type_)
+ """Decorator for registering an override.
+
+ Other than objects added to __all__, these can get referenced in the same
+ override module via the gi.repository module (get_parent_for_object() does
+ for example), so they have to be added to the module immediately.
+ """
+
+ if isinstance(type_, CallableInfo):
+ func = type_
+ namespace = func.__module__.rsplit('.', 1)[-1]
+ module = sys.modules["gi.repository." + namespace]
+
+ def wrapper(func):
+ setattr(module, func.__name__, func)
+ return func
+
+ return wrapper
+ elif isinstance(type_, types.FunctionType):
+ raise TypeError("func must be a gi function, got %s" % type_)
else:
- registry.register(type_)
+ try:
+ info = getattr(type_, '__info__')
+ except AttributeError:
+ raise TypeError(
+ 'Can not override a type %s, which is not in a gobject '
+ 'introspection typelib' % type_.__name__)
+
+ if not type_.__module__.startswith('gi.overrides'):
+ raise KeyError(
+ 'You have tried override outside of the overrides module. '
+ 'This is not allowed (%s, %s)' % (type_, type_.__module__))
+
+ g_type = info.get_g_type()
+ assert g_type != TYPE_NONE
+ if g_type != TYPE_INVALID:
+ g_type.pytype = type_
+
+ namespace = type_.__module__.rsplit(".", 1)[-1]
+ module = sys.modules["gi.repository." + namespace]
+ setattr(module, type_.__name__, type_)
+
return type_
+overridefunc = override
+"""Deprecated"""
+
+
def deprecated(fn, replacement):
- '''Decorator for marking methods and classes as deprecated'''
+ """Decorator for marking methods and classes as deprecated"""
@functools.wraps(fn)
def wrapped(*args, **kwargs):
warnings.warn('%s is deprecated; use %s instead' % (fn.__name__, replacement),
@@ -90,13 +217,117 @@ def deprecated(fn, replacement):
return wrapped
+def deprecated_attr(namespace, attr, replacement):
+ """Marks a module level attribute as deprecated. Accessing it will emit
+ a PyGIDeprecationWarning warning.
+
+ e.g. for ``deprecated_attr("GObject", "STATUS_FOO", "GLib.Status.FOO")``
+ accessing GObject.STATUS_FOO will emit:
+
+ "GObject.STATUS_FOO is deprecated; use GLib.Status.FOO instead"
+
+ :param str namespace:
+ The namespace of the override this is called in.
+ :param str namespace:
+ The attribute name (which gets added to __all__).
+ :param str replacement:
+ The replacement text which will be included in the warning.
+ """
+
+ _deprecated_attrs.setdefault(namespace, []).append((attr, replacement))
+
+
+def deprecated_init(super_init_func, arg_names, ignore=tuple(),
+ deprecated_aliases={}, deprecated_defaults={},
+ category=PyGIDeprecationWarning,
+ stacklevel=2):
+ """Wrapper for deprecating GObject based __init__ methods which specify
+ defaults already available or non-standard defaults.
+
+ :param callable super_init_func:
+ Initializer to wrap.
+ :param list arg_names:
+ Ordered argument name list.
+ :param list ignore:
+ List of argument names to ignore when calling the wrapped function.
+ This is useful for function which take a non-standard keyword that is munged elsewhere.
+ :param dict deprecated_aliases:
+ Dictionary mapping a keyword alias to the actual g_object_newv keyword.
+ :param dict deprecated_defaults:
+ Dictionary of non-standard defaults that will be used when the
+ keyword is not explicitly passed.
+ :param Exception category:
+ Exception category of the error.
+ :param int stacklevel:
+ Stack level for the deprecation passed on to warnings.warn
+ :returns: Wrapped version of ``super_init_func`` which gives a deprecation
+ warning when non-keyword args or aliases are used.
+ :rtype: callable
+ """
+ # We use a list of argument names to maintain order of the arguments
+ # being deprecated. This allows calls with positional arguments to
+ # continue working but with a deprecation message.
+ def new_init(self, *args, **kwargs):
+ """Initializer for a GObject based classes with support for property
+ sets through the use of explicit keyword arguments.
+ """
+ # Print warnings for calls with positional arguments.
+ if args:
+ warnings.warn('Using positional arguments with the GObject constructor has been deprecated. '
+ 'Please specify keyword(s) for "%s" or use a class specific constructor. '
+ 'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations' %
+ ', '.join(arg_names[:len(args)]),
+ category, stacklevel=stacklevel)
+ new_kwargs = dict(zip(arg_names, args))
+ else:
+ new_kwargs = {}
+ new_kwargs.update(kwargs)
+
+ # Print warnings for alias usage and transfer them into the new key.
+ aliases_used = []
+ for key, alias in deprecated_aliases.items():
+ if alias in new_kwargs:
+ new_kwargs[key] = new_kwargs.pop(alias)
+ aliases_used.append(key)
+
+ if aliases_used:
+ warnings.warn('The keyword(s) "%s" have been deprecated in favor of "%s" respectively. '
+ 'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations' %
+ (', '.join(deprecated_aliases[k] for k in sorted(aliases_used)),
+ ', '.join(sorted(aliases_used))),
+ category, stacklevel=stacklevel)
+
+ # Print warnings for defaults different than what is already provided by the property
+ defaults_used = []
+ for key, value in deprecated_defaults.items():
+ if key not in new_kwargs:
+ new_kwargs[key] = deprecated_defaults[key]
+ defaults_used.append(key)
+
+ if defaults_used:
+ warnings.warn('Initializer is relying on deprecated non-standard '
+ 'defaults. Please update to explicitly use: %s '
+ 'See: https://wiki.gnome.org/PyGObject/InitializerDeprecations' %
+ ', '.join('%s=%s' % (k, deprecated_defaults[k]) for k in sorted(defaults_used)),
+ category, stacklevel=stacklevel)
+
+ # Remove keywords that should be ignored.
+ for key in ignore:
+ if key in new_kwargs:
+ new_kwargs.pop(key)
+
+ return super_init_func(self, **new_kwargs)
+
+ return new_init
+
+
def strip_boolean_result(method, exc_type=None, exc_str=None, fail_ret=None):
- '''Translate method's return value for stripping off success flag.
+ """Translate method's return value for stripping off success flag.
There are a lot of methods which return a "success" boolean and have
several out arguments. Translate such a method to return the out arguments
on success and None on failure.
- '''
+ """
@functools.wraps(method)
def wrapped(*args, **kwargs):
ret = method(*args, **kwargs)
@@ -110,3 +341,13 @@ def strip_boolean_result(method, exc_type=None, exc_str=None, fail_ret=None):
raise exc_type(exc_str or 'call failed')
return fail_ret
return wrapped
+
+
+def wrap_list_store_sort_func(func):
+
+ def wrap(a, b, *user_data):
+ a = pygobject_new_full(a, False)
+ b = pygobject_new_full(b, False)
+ return func(a, b, *user_data)
+
+ return wrap
diff --git a/gi/overrides/keysyms.py b/gi/overrides/keysyms.py
index 35ee8eb..07ce277 100644
--- a/gi/overrides/keysyms.py
+++ b/gi/overrides/keysyms.py
@@ -15,1485 +15,39 @@
# 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 Street, Fifth Floor, Boston, MA 02110-1301
-# USA
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
-VoidSymbol = 0xFFFFFF
-BackSpace = 0xFF08
-Tab = 0xFF09
-Linefeed = 0xFF0A
-Clear = 0xFF0B
-Return = 0xFF0D
-Pause = 0xFF13
-Scroll_Lock = 0xFF14
-Sys_Req = 0xFF15
-Escape = 0xFF1B
-Delete = 0xFFFF
-Multi_key = 0xFF20
-Codeinput = 0xFF37
-SingleCandidate = 0xFF3C
-MultipleCandidate = 0xFF3D
-PreviousCandidate = 0xFF3E
-Kanji = 0xFF21
-Muhenkan = 0xFF22
-Henkan_Mode = 0xFF23
-Henkan = 0xFF23
-Romaji = 0xFF24
-Hiragana = 0xFF25
-Katakana = 0xFF26
-Hiragana_Katakana = 0xFF27
-Zenkaku = 0xFF28
-Hankaku = 0xFF29
-Zenkaku_Hankaku = 0xFF2A
-Touroku = 0xFF2B
-Massyo = 0xFF2C
-Kana_Lock = 0xFF2D
-Kana_Shift = 0xFF2E
-Eisu_Shift = 0xFF2F
-Eisu_toggle = 0xFF30
-Kanji_Bangou = 0xFF37
-Zen_Koho = 0xFF3D
-Mae_Koho = 0xFF3E
-Home = 0xFF50
-Left = 0xFF51
-Up = 0xFF52
-Right = 0xFF53
-Down = 0xFF54
-Prior = 0xFF55
-Page_Up = 0xFF55
-Next = 0xFF56
-Page_Down = 0xFF56
-End = 0xFF57
-Begin = 0xFF58
-Select = 0xFF60
-Print = 0xFF61
-Execute = 0xFF62
-Insert = 0xFF63
-Undo = 0xFF65
-Redo = 0xFF66
-Menu = 0xFF67
-Find = 0xFF68
-Cancel = 0xFF69
-Help = 0xFF6A
-Break = 0xFF6B
-Mode_switch = 0xFF7E
-script_switch = 0xFF7E
-Num_Lock = 0xFF7F
-KP_Space = 0xFF80
-KP_Tab = 0xFF89
-KP_Enter = 0xFF8D
-KP_F1 = 0xFF91
-KP_F2 = 0xFF92
-KP_F3 = 0xFF93
-KP_F4 = 0xFF94
-KP_Home = 0xFF95
-KP_Left = 0xFF96
-KP_Up = 0xFF97
-KP_Right = 0xFF98
-KP_Down = 0xFF99
-KP_Prior = 0xFF9A
-KP_Page_Up = 0xFF9A
-KP_Next = 0xFF9B
-KP_Page_Down = 0xFF9B
-KP_End = 0xFF9C
-KP_Begin = 0xFF9D
-KP_Insert = 0xFF9E
-KP_Delete = 0xFF9F
-KP_Equal = 0xFFBD
-KP_Multiply = 0xFFAA
-KP_Add = 0xFFAB
-KP_Separator = 0xFFAC
-KP_Subtract = 0xFFAD
-KP_Decimal = 0xFFAE
-KP_Divide = 0xFFAF
-KP_0 = 0xFFB0
-KP_1 = 0xFFB1
-KP_2 = 0xFFB2
-KP_3 = 0xFFB3
-KP_4 = 0xFFB4
-KP_5 = 0xFFB5
-KP_6 = 0xFFB6
-KP_7 = 0xFFB7
-KP_8 = 0xFFB8
-KP_9 = 0xFFB9
-F1 = 0xFFBE
-F2 = 0xFFBF
-F3 = 0xFFC0
-F4 = 0xFFC1
-F5 = 0xFFC2
-F6 = 0xFFC3
-F7 = 0xFFC4
-F8 = 0xFFC5
-F9 = 0xFFC6
-F10 = 0xFFC7
-F11 = 0xFFC8
-L1 = 0xFFC8
-F12 = 0xFFC9
-L2 = 0xFFC9
-F13 = 0xFFCA
-L3 = 0xFFCA
-F14 = 0xFFCB
-L4 = 0xFFCB
-F15 = 0xFFCC
-L5 = 0xFFCC
-F16 = 0xFFCD
-L6 = 0xFFCD
-F17 = 0xFFCE
-L7 = 0xFFCE
-F18 = 0xFFCF
-L8 = 0xFFCF
-F19 = 0xFFD0
-L9 = 0xFFD0
-F20 = 0xFFD1
-L10 = 0xFFD1
-F21 = 0xFFD2
-R1 = 0xFFD2
-F22 = 0xFFD3
-R2 = 0xFFD3
-F23 = 0xFFD4
-R3 = 0xFFD4
-F24 = 0xFFD5
-R4 = 0xFFD5
-F25 = 0xFFD6
-R5 = 0xFFD6
-F26 = 0xFFD7
-R6 = 0xFFD7
-F27 = 0xFFD8
-R7 = 0xFFD8
-F28 = 0xFFD9
-R8 = 0xFFD9
-F29 = 0xFFDA
-R9 = 0xFFDA
-F30 = 0xFFDB
-R10 = 0xFFDB
-F31 = 0xFFDC
-R11 = 0xFFDC
-F32 = 0xFFDD
-R12 = 0xFFDD
-F33 = 0xFFDE
-R13 = 0xFFDE
-F34 = 0xFFDF
-R14 = 0xFFDF
-F35 = 0xFFE0
-R15 = 0xFFE0
-Shift_L = 0xFFE1
-Shift_R = 0xFFE2
-Control_L = 0xFFE3
-Control_R = 0xFFE4
-Caps_Lock = 0xFFE5
-Shift_Lock = 0xFFE6
-Meta_L = 0xFFE7
-Meta_R = 0xFFE8
-Alt_L = 0xFFE9
-Alt_R = 0xFFEA
-Super_L = 0xFFEB
-Super_R = 0xFFEC
-Hyper_L = 0xFFED
-Hyper_R = 0xFFEE
-ISO_Lock = 0xFE01
-ISO_Level2_Latch = 0xFE02
-ISO_Level3_Shift = 0xFE03
-ISO_Level3_Latch = 0xFE04
-ISO_Level3_Lock = 0xFE05
-ISO_Group_Shift = 0xFF7E
-ISO_Group_Latch = 0xFE06
-ISO_Group_Lock = 0xFE07
-ISO_Next_Group = 0xFE08
-ISO_Next_Group_Lock = 0xFE09
-ISO_Prev_Group = 0xFE0A
-ISO_Prev_Group_Lock = 0xFE0B
-ISO_First_Group = 0xFE0C
-ISO_First_Group_Lock = 0xFE0D
-ISO_Last_Group = 0xFE0E
-ISO_Last_Group_Lock = 0xFE0F
-ISO_Left_Tab = 0xFE20
-ISO_Move_Line_Up = 0xFE21
-ISO_Move_Line_Down = 0xFE22
-ISO_Partial_Line_Up = 0xFE23
-ISO_Partial_Line_Down = 0xFE24
-ISO_Partial_Space_Left = 0xFE25
-ISO_Partial_Space_Right = 0xFE26
-ISO_Set_Margin_Left = 0xFE27
-ISO_Set_Margin_Right = 0xFE28
-ISO_Release_Margin_Left = 0xFE29
-ISO_Release_Margin_Right = 0xFE2A
-ISO_Release_Both_Margins = 0xFE2B
-ISO_Fast_Cursor_Left = 0xFE2C
-ISO_Fast_Cursor_Right = 0xFE2D
-ISO_Fast_Cursor_Up = 0xFE2E
-ISO_Fast_Cursor_Down = 0xFE2F
-ISO_Continuous_Underline = 0xFE30
-ISO_Discontinuous_Underline = 0xFE31
-ISO_Emphasize = 0xFE32
-ISO_Center_Object = 0xFE33
-ISO_Enter = 0xFE34
-dead_grave = 0xFE50
-dead_acute = 0xFE51
-dead_circumflex = 0xFE52
-dead_tilde = 0xFE53
-dead_macron = 0xFE54
-dead_breve = 0xFE55
-dead_abovedot = 0xFE56
-dead_diaeresis = 0xFE57
-dead_abovering = 0xFE58
-dead_doubleacute = 0xFE59
-dead_caron = 0xFE5A
-dead_cedilla = 0xFE5B
-dead_ogonek = 0xFE5C
-dead_iota = 0xFE5D
-dead_voiced_sound = 0xFE5E
-dead_semivoiced_sound = 0xFE5F
-dead_belowdot = 0xFE60
-First_Virtual_Screen = 0xFED0
-Prev_Virtual_Screen = 0xFED1
-Next_Virtual_Screen = 0xFED2
-Last_Virtual_Screen = 0xFED4
-Terminate_Server = 0xFED5
-AccessX_Enable = 0xFE70
-AccessX_Feedback_Enable = 0xFE71
-RepeatKeys_Enable = 0xFE72
-SlowKeys_Enable = 0xFE73
-BounceKeys_Enable = 0xFE74
-StickyKeys_Enable = 0xFE75
-MouseKeys_Enable = 0xFE76
-MouseKeys_Accel_Enable = 0xFE77
-Overlay1_Enable = 0xFE78
-Overlay2_Enable = 0xFE79
-AudibleBell_Enable = 0xFE7A
-Pointer_Left = 0xFEE0
-Pointer_Right = 0xFEE1
-Pointer_Up = 0xFEE2
-Pointer_Down = 0xFEE3
-Pointer_UpLeft = 0xFEE4
-Pointer_UpRight = 0xFEE5
-Pointer_DownLeft = 0xFEE6
-Pointer_DownRight = 0xFEE7
-Pointer_Button_Dflt = 0xFEE8
-Pointer_Button1 = 0xFEE9
-Pointer_Button2 = 0xFEEA
-Pointer_Button3 = 0xFEEB
-Pointer_Button4 = 0xFEEC
-Pointer_Button5 = 0xFEED
-Pointer_DblClick_Dflt = 0xFEEE
-Pointer_DblClick1 = 0xFEEF
-Pointer_DblClick2 = 0xFEF0
-Pointer_DblClick3 = 0xFEF1
-Pointer_DblClick4 = 0xFEF2
-Pointer_DblClick5 = 0xFEF3
-Pointer_Drag_Dflt = 0xFEF4
-Pointer_Drag1 = 0xFEF5
-Pointer_Drag2 = 0xFEF6
-Pointer_Drag3 = 0xFEF7
-Pointer_Drag4 = 0xFEF8
-Pointer_Drag5 = 0xFEFD
-Pointer_EnableKeys = 0xFEF9
-Pointer_Accelerate = 0xFEFA
-Pointer_DfltBtnNext = 0xFEFB
-Pointer_DfltBtnPrev = 0xFEFC
-_3270_Duplicate = 0xFD01
-_3270_FieldMark = 0xFD02
-_3270_Right2 = 0xFD03
-_3270_Left2 = 0xFD04
-_3270_BackTab = 0xFD05
-_3270_EraseEOF = 0xFD06
-_3270_EraseInput = 0xFD07
-_3270_Reset = 0xFD08
-_3270_Quit = 0xFD09
-_3270_PA1 = 0xFD0A
-_3270_PA2 = 0xFD0B
-_3270_PA3 = 0xFD0C
-_3270_Test = 0xFD0D
-_3270_Attn = 0xFD0E
-_3270_CursorBlink = 0xFD0F
-_3270_AltCursor = 0xFD10
-_3270_KeyClick = 0xFD11
-_3270_Jump = 0xFD12
-_3270_Ident = 0xFD13
-_3270_Rule = 0xFD14
-_3270_Copy = 0xFD15
-_3270_Play = 0xFD16
-_3270_Setup = 0xFD17
-_3270_Record = 0xFD18
-_3270_ChangeScreen = 0xFD19
-_3270_DeleteWord = 0xFD1A
-_3270_ExSelect = 0xFD1B
-_3270_CursorSelect = 0xFD1C
-_3270_PrintScreen = 0xFD1D
-_3270_Enter = 0xFD1E
-space = 0x020
-exclam = 0x021
-quotedbl = 0x022
-numbersign = 0x023
-dollar = 0x024
-percent = 0x025
-ampersand = 0x026
-apostrophe = 0x027
-quoteright = 0x027
-parenleft = 0x028
-parenright = 0x029
-asterisk = 0x02a
-plus = 0x02b
-comma = 0x02c
-minus = 0x02d
-period = 0x02e
-slash = 0x02f
-_0 = 0x030
-_1 = 0x031
-_2 = 0x032
-_3 = 0x033
-_4 = 0x034
-_5 = 0x035
-_6 = 0x036
-_7 = 0x037
-_8 = 0x038
-_9 = 0x039
-colon = 0x03a
-semicolon = 0x03b
-less = 0x03c
-equal = 0x03d
-greater = 0x03e
-question = 0x03f
-at = 0x040
-A = 0x041
-B = 0x042
-C = 0x043
-D = 0x044
-E = 0x045
-F = 0x046
-G = 0x047
-H = 0x048
-I = 0x049
-J = 0x04a
-K = 0x04b
-L = 0x04c
-M = 0x04d
-N = 0x04e
-O = 0x04f
-P = 0x050
-Q = 0x051
-R = 0x052
-S = 0x053
-T = 0x054
-U = 0x055
-V = 0x056
-W = 0x057
-X = 0x058
-Y = 0x059
-Z = 0x05a
-bracketleft = 0x05b
-backslash = 0x05c
-bracketright = 0x05d
-asciicircum = 0x05e
-underscore = 0x05f
-grave = 0x060
-quoteleft = 0x060
-a = 0x061
-b = 0x062
-c = 0x063
-d = 0x064
-e = 0x065
-f = 0x066
-g = 0x067
-h = 0x068
-i = 0x069
-j = 0x06a
-k = 0x06b
-l = 0x06c
-m = 0x06d
-n = 0x06e
-o = 0x06f
-p = 0x070
-q = 0x071
-r = 0x072
-s = 0x073
-t = 0x074
-u = 0x075
-v = 0x076
-w = 0x077
-x = 0x078
-y = 0x079
-z = 0x07a
-braceleft = 0x07b
-bar = 0x07c
-braceright = 0x07d
-asciitilde = 0x07e
-nobreakspace = 0x0a0
-exclamdown = 0x0a1
-cent = 0x0a2
-sterling = 0x0a3
-currency = 0x0a4
-yen = 0x0a5
-brokenbar = 0x0a6
-section = 0x0a7
-diaeresis = 0x0a8
-copyright = 0x0a9
-ordfeminine = 0x0aa
-guillemotleft = 0x0ab
-notsign = 0x0ac
-hyphen = 0x0ad
-registered = 0x0ae
-macron = 0x0af
-degree = 0x0b0
-plusminus = 0x0b1
-twosuperior = 0x0b2
-threesuperior = 0x0b3
-acute = 0x0b4
-mu = 0x0b5
-paragraph = 0x0b6
-periodcentered = 0x0b7
-cedilla = 0x0b8
-onesuperior = 0x0b9
-masculine = 0x0ba
-guillemotright = 0x0bb
-onequarter = 0x0bc
-onehalf = 0x0bd
-threequarters = 0x0be
-questiondown = 0x0bf
-Agrave = 0x0c0
-Aacute = 0x0c1
-Acircumflex = 0x0c2
-Atilde = 0x0c3
-Adiaeresis = 0x0c4
-Aring = 0x0c5
-AE = 0x0c6
-Ccedilla = 0x0c7
-Egrave = 0x0c8
-Eacute = 0x0c9
-Ecircumflex = 0x0ca
-Ediaeresis = 0x0cb
-Igrave = 0x0cc
-Iacute = 0x0cd
-Icircumflex = 0x0ce
-Idiaeresis = 0x0cf
-ETH = 0x0d0
-Eth = 0x0d0
-Ntilde = 0x0d1
-Ograve = 0x0d2
-Oacute = 0x0d3
-Ocircumflex = 0x0d4
-Otilde = 0x0d5
-Odiaeresis = 0x0d6
-multiply = 0x0d7
-Ooblique = 0x0d8
-Ugrave = 0x0d9
-Uacute = 0x0da
-Ucircumflex = 0x0db
-Udiaeresis = 0x0dc
-Yacute = 0x0dd
-THORN = 0x0de
-Thorn = 0x0de
-ssharp = 0x0df
-agrave = 0x0e0
-aacute = 0x0e1
-acircumflex = 0x0e2
-atilde = 0x0e3
-adiaeresis = 0x0e4
-aring = 0x0e5
-ae = 0x0e6
-ccedilla = 0x0e7
-egrave = 0x0e8
-eacute = 0x0e9
-ecircumflex = 0x0ea
-ediaeresis = 0x0eb
-igrave = 0x0ec
-iacute = 0x0ed
-icircumflex = 0x0ee
-idiaeresis = 0x0ef
-eth = 0x0f0
-ntilde = 0x0f1
-ograve = 0x0f2
-oacute = 0x0f3
-ocircumflex = 0x0f4
-otilde = 0x0f5
-odiaeresis = 0x0f6
-division = 0x0f7
-oslash = 0x0f8
-ugrave = 0x0f9
-uacute = 0x0fa
-ucircumflex = 0x0fb
-udiaeresis = 0x0fc
-yacute = 0x0fd
-thorn = 0x0fe
-ydiaeresis = 0x0ff
-Aogonek = 0x1a1
-breve = 0x1a2
-Lstroke = 0x1a3
-Lcaron = 0x1a5
-Sacute = 0x1a6
-Scaron = 0x1a9
-Scedilla = 0x1aa
-Tcaron = 0x1ab
-Zacute = 0x1ac
-Zcaron = 0x1ae
-Zabovedot = 0x1af
-aogonek = 0x1b1
-ogonek = 0x1b2
-lstroke = 0x1b3
-lcaron = 0x1b5
-sacute = 0x1b6
-caron = 0x1b7
-scaron = 0x1b9
-scedilla = 0x1ba
-tcaron = 0x1bb
-zacute = 0x1bc
-doubleacute = 0x1bd
-zcaron = 0x1be
-zabovedot = 0x1bf
-Racute = 0x1c0
-Abreve = 0x1c3
-Lacute = 0x1c5
-Cacute = 0x1c6
-Ccaron = 0x1c8
-Eogonek = 0x1ca
-Ecaron = 0x1cc
-Dcaron = 0x1cf
-Dstroke = 0x1d0
-Nacute = 0x1d1
-Ncaron = 0x1d2
-Odoubleacute = 0x1d5
-Rcaron = 0x1d8
-Uring = 0x1d9
-Udoubleacute = 0x1db
-Tcedilla = 0x1de
-racute = 0x1e0
-abreve = 0x1e3
-lacute = 0x1e5
-cacute = 0x1e6
-ccaron = 0x1e8
-eogonek = 0x1ea
-ecaron = 0x1ec
-dcaron = 0x1ef
-dstroke = 0x1f0
-nacute = 0x1f1
-ncaron = 0x1f2
-odoubleacute = 0x1f5
-udoubleacute = 0x1fb
-rcaron = 0x1f8
-uring = 0x1f9
-tcedilla = 0x1fe
-abovedot = 0x1ff
-Hstroke = 0x2a1
-Hcircumflex = 0x2a6
-Iabovedot = 0x2a9
-Gbreve = 0x2ab
-Jcircumflex = 0x2ac
-hstroke = 0x2b1
-hcircumflex = 0x2b6
-idotless = 0x2b9
-gbreve = 0x2bb
-jcircumflex = 0x2bc
-Cabovedot = 0x2c5
-Ccircumflex = 0x2c6
-Gabovedot = 0x2d5
-Gcircumflex = 0x2d8
-Ubreve = 0x2dd
-Scircumflex = 0x2de
-cabovedot = 0x2e5
-ccircumflex = 0x2e6
-gabovedot = 0x2f5
-gcircumflex = 0x2f8
-ubreve = 0x2fd
-scircumflex = 0x2fe
-kra = 0x3a2
-kappa = 0x3a2
-Rcedilla = 0x3a3
-Itilde = 0x3a5
-Lcedilla = 0x3a6
-Emacron = 0x3aa
-Gcedilla = 0x3ab
-Tslash = 0x3ac
-rcedilla = 0x3b3
-itilde = 0x3b5
-lcedilla = 0x3b6
-emacron = 0x3ba
-gcedilla = 0x3bb
-tslash = 0x3bc
-ENG = 0x3bd
-eng = 0x3bf
-Amacron = 0x3c0
-Iogonek = 0x3c7
-Eabovedot = 0x3cc
-Imacron = 0x3cf
-Ncedilla = 0x3d1
-Omacron = 0x3d2
-Kcedilla = 0x3d3
-Uogonek = 0x3d9
-Utilde = 0x3dd
-Umacron = 0x3de
-amacron = 0x3e0
-iogonek = 0x3e7
-eabovedot = 0x3ec
-imacron = 0x3ef
-ncedilla = 0x3f1
-omacron = 0x3f2
-kcedilla = 0x3f3
-uogonek = 0x3f9
-utilde = 0x3fd
-umacron = 0x3fe
-OE = 0x13bc
-oe = 0x13bd
-Ydiaeresis = 0x13be
-overline = 0x47e
-kana_fullstop = 0x4a1
-kana_openingbracket = 0x4a2
-kana_closingbracket = 0x4a3
-kana_comma = 0x4a4
-kana_conjunctive = 0x4a5
-kana_middledot = 0x4a5
-kana_WO = 0x4a6
-kana_a = 0x4a7
-kana_i = 0x4a8
-kana_u = 0x4a9
-kana_e = 0x4aa
-kana_o = 0x4ab
-kana_ya = 0x4ac
-kana_yu = 0x4ad
-kana_yo = 0x4ae
-kana_tsu = 0x4af
-kana_tu = 0x4af
-prolongedsound = 0x4b0
-kana_A = 0x4b1
-kana_I = 0x4b2
-kana_U = 0x4b3
-kana_E = 0x4b4
-kana_O = 0x4b5
-kana_KA = 0x4b6
-kana_KI = 0x4b7
-kana_KU = 0x4b8
-kana_KE = 0x4b9
-kana_KO = 0x4ba
-kana_SA = 0x4bb
-kana_SHI = 0x4bc
-kana_SU = 0x4bd
-kana_SE = 0x4be
-kana_SO = 0x4bf
-kana_TA = 0x4c0
-kana_CHI = 0x4c1
-kana_TI = 0x4c1
-kana_TSU = 0x4c2
-kana_TU = 0x4c2
-kana_TE = 0x4c3
-kana_TO = 0x4c4
-kana_NA = 0x4c5
-kana_NI = 0x4c6
-kana_NU = 0x4c7
-kana_NE = 0x4c8
-kana_NO = 0x4c9
-kana_HA = 0x4ca
-kana_HI = 0x4cb
-kana_FU = 0x4cc
-kana_HU = 0x4cc
-kana_HE = 0x4cd
-kana_HO = 0x4ce
-kana_MA = 0x4cf
-kana_MI = 0x4d0
-kana_MU = 0x4d1
-kana_ME = 0x4d2
-kana_MO = 0x4d3
-kana_YA = 0x4d4
-kana_YU = 0x4d5
-kana_YO = 0x4d6
-kana_RA = 0x4d7
-kana_RI = 0x4d8
-kana_RU = 0x4d9
-kana_RE = 0x4da
-kana_RO = 0x4db
-kana_WA = 0x4dc
-kana_N = 0x4dd
-voicedsound = 0x4de
-semivoicedsound = 0x4df
-kana_switch = 0xFF7E
-Arabic_comma = 0x5ac
-Arabic_semicolon = 0x5bb
-Arabic_question_mark = 0x5bf
-Arabic_hamza = 0x5c1
-Arabic_maddaonalef = 0x5c2
-Arabic_hamzaonalef = 0x5c3
-Arabic_hamzaonwaw = 0x5c4
-Arabic_hamzaunderalef = 0x5c5
-Arabic_hamzaonyeh = 0x5c6
-Arabic_alef = 0x5c7
-Arabic_beh = 0x5c8
-Arabic_tehmarbuta = 0x5c9
-Arabic_teh = 0x5ca
-Arabic_theh = 0x5cb
-Arabic_jeem = 0x5cc
-Arabic_hah = 0x5cd
-Arabic_khah = 0x5ce
-Arabic_dal = 0x5cf
-Arabic_thal = 0x5d0
-Arabic_ra = 0x5d1
-Arabic_zain = 0x5d2
-Arabic_seen = 0x5d3
-Arabic_sheen = 0x5d4
-Arabic_sad = 0x5d5
-Arabic_dad = 0x5d6
-Arabic_tah = 0x5d7
-Arabic_zah = 0x5d8
-Arabic_ain = 0x5d9
-Arabic_ghain = 0x5da
-Arabic_tatweel = 0x5e0
-Arabic_feh = 0x5e1
-Arabic_qaf = 0x5e2
-Arabic_kaf = 0x5e3
-Arabic_lam = 0x5e4
-Arabic_meem = 0x5e5
-Arabic_noon = 0x5e6
-Arabic_ha = 0x5e7
-Arabic_heh = 0x5e7
-Arabic_waw = 0x5e8
-Arabic_alefmaksura = 0x5e9
-Arabic_yeh = 0x5ea
-Arabic_fathatan = 0x5eb
-Arabic_dammatan = 0x5ec
-Arabic_kasratan = 0x5ed
-Arabic_fatha = 0x5ee
-Arabic_damma = 0x5ef
-Arabic_kasra = 0x5f0
-Arabic_shadda = 0x5f1
-Arabic_sukun = 0x5f2
-Arabic_switch = 0xFF7E
-Serbian_dje = 0x6a1
-Macedonia_gje = 0x6a2
-Cyrillic_io = 0x6a3
-Ukrainian_ie = 0x6a4
-Ukranian_je = 0x6a4
-Macedonia_dse = 0x6a5
-Ukrainian_i = 0x6a6
-Ukranian_i = 0x6a6
-Ukrainian_yi = 0x6a7
-Ukranian_yi = 0x6a7
-Cyrillic_je = 0x6a8
-Serbian_je = 0x6a8
-Cyrillic_lje = 0x6a9
-Serbian_lje = 0x6a9
-Cyrillic_nje = 0x6aa
-Serbian_nje = 0x6aa
-Serbian_tshe = 0x6ab
-Macedonia_kje = 0x6ac
-Ukrainian_ghe_with_upturn = 0x6ad
-Byelorussian_shortu = 0x6ae
-Cyrillic_dzhe = 0x6af
-Serbian_dze = 0x6af
-numerosign = 0x6b0
-Serbian_DJE = 0x6b1
-Macedonia_GJE = 0x6b2
-Cyrillic_IO = 0x6b3
-Ukrainian_IE = 0x6b4
-Ukranian_JE = 0x6b4
-Macedonia_DSE = 0x6b5
-Ukrainian_I = 0x6b6
-Ukranian_I = 0x6b6
-Ukrainian_YI = 0x6b7
-Ukranian_YI = 0x6b7
-Cyrillic_JE = 0x6b8
-Serbian_JE = 0x6b8
-Cyrillic_LJE = 0x6b9
-Serbian_LJE = 0x6b9
-Cyrillic_NJE = 0x6ba
-Serbian_NJE = 0x6ba
-Serbian_TSHE = 0x6bb
-Macedonia_KJE = 0x6bc
-Ukrainian_GHE_WITH_UPTURN = 0x6bd
-Byelorussian_SHORTU = 0x6be
-Cyrillic_DZHE = 0x6bf
-Serbian_DZE = 0x6bf
-Cyrillic_yu = 0x6c0
-Cyrillic_a = 0x6c1
-Cyrillic_be = 0x6c2
-Cyrillic_tse = 0x6c3
-Cyrillic_de = 0x6c4
-Cyrillic_ie = 0x6c5
-Cyrillic_ef = 0x6c6
-Cyrillic_ghe = 0x6c7
-Cyrillic_ha = 0x6c8
-Cyrillic_i = 0x6c9
-Cyrillic_shorti = 0x6ca
-Cyrillic_ka = 0x6cb
-Cyrillic_el = 0x6cc
-Cyrillic_em = 0x6cd
-Cyrillic_en = 0x6ce
-Cyrillic_o = 0x6cf
-Cyrillic_pe = 0x6d0
-Cyrillic_ya = 0x6d1
-Cyrillic_er = 0x6d2
-Cyrillic_es = 0x6d3
-Cyrillic_te = 0x6d4
-Cyrillic_u = 0x6d5
-Cyrillic_zhe = 0x6d6
-Cyrillic_ve = 0x6d7
-Cyrillic_softsign = 0x6d8
-Cyrillic_yeru = 0x6d9
-Cyrillic_ze = 0x6da
-Cyrillic_sha = 0x6db
-Cyrillic_e = 0x6dc
-Cyrillic_shcha = 0x6dd
-Cyrillic_che = 0x6de
-Cyrillic_hardsign = 0x6df
-Cyrillic_YU = 0x6e0
-Cyrillic_A = 0x6e1
-Cyrillic_BE = 0x6e2
-Cyrillic_TSE = 0x6e3
-Cyrillic_DE = 0x6e4
-Cyrillic_IE = 0x6e5
-Cyrillic_EF = 0x6e6
-Cyrillic_GHE = 0x6e7
-Cyrillic_HA = 0x6e8
-Cyrillic_I = 0x6e9
-Cyrillic_SHORTI = 0x6ea
-Cyrillic_KA = 0x6eb
-Cyrillic_EL = 0x6ec
-Cyrillic_EM = 0x6ed
-Cyrillic_EN = 0x6ee
-Cyrillic_O = 0x6ef
-Cyrillic_PE = 0x6f0
-Cyrillic_YA = 0x6f1
-Cyrillic_ER = 0x6f2
-Cyrillic_ES = 0x6f3
-Cyrillic_TE = 0x6f4
-Cyrillic_U = 0x6f5
-Cyrillic_ZHE = 0x6f6
-Cyrillic_VE = 0x6f7
-Cyrillic_SOFTSIGN = 0x6f8
-Cyrillic_YERU = 0x6f9
-Cyrillic_ZE = 0x6fa
-Cyrillic_SHA = 0x6fb
-Cyrillic_E = 0x6fc
-Cyrillic_SHCHA = 0x6fd
-Cyrillic_CHE = 0x6fe
-Cyrillic_HARDSIGN = 0x6ff
-Greek_ALPHAaccent = 0x7a1
-Greek_EPSILONaccent = 0x7a2
-Greek_ETAaccent = 0x7a3
-Greek_IOTAaccent = 0x7a4
-Greek_IOTAdiaeresis = 0x7a5
-Greek_OMICRONaccent = 0x7a7
-Greek_UPSILONaccent = 0x7a8
-Greek_UPSILONdieresis = 0x7a9
-Greek_OMEGAaccent = 0x7ab
-Greek_accentdieresis = 0x7ae
-Greek_horizbar = 0x7af
-Greek_alphaaccent = 0x7b1
-Greek_epsilonaccent = 0x7b2
-Greek_etaaccent = 0x7b3
-Greek_iotaaccent = 0x7b4
-Greek_iotadieresis = 0x7b5
-Greek_iotaaccentdieresis = 0x7b6
-Greek_omicronaccent = 0x7b7
-Greek_upsilonaccent = 0x7b8
-Greek_upsilondieresis = 0x7b9
-Greek_upsilonaccentdieresis = 0x7ba
-Greek_omegaaccent = 0x7bb
-Greek_ALPHA = 0x7c1
-Greek_BETA = 0x7c2
-Greek_GAMMA = 0x7c3
-Greek_DELTA = 0x7c4
-Greek_EPSILON = 0x7c5
-Greek_ZETA = 0x7c6
-Greek_ETA = 0x7c7
-Greek_THETA = 0x7c8
-Greek_IOTA = 0x7c9
-Greek_KAPPA = 0x7ca
-Greek_LAMDA = 0x7cb
-Greek_LAMBDA = 0x7cb
-Greek_MU = 0x7cc
-Greek_NU = 0x7cd
-Greek_XI = 0x7ce
-Greek_OMICRON = 0x7cf
-Greek_PI = 0x7d0
-Greek_RHO = 0x7d1
-Greek_SIGMA = 0x7d2
-Greek_TAU = 0x7d4
-Greek_UPSILON = 0x7d5
-Greek_PHI = 0x7d6
-Greek_CHI = 0x7d7
-Greek_PSI = 0x7d8
-Greek_OMEGA = 0x7d9
-Greek_alpha = 0x7e1
-Greek_beta = 0x7e2
-Greek_gamma = 0x7e3
-Greek_delta = 0x7e4
-Greek_epsilon = 0x7e5
-Greek_zeta = 0x7e6
-Greek_eta = 0x7e7
-Greek_theta = 0x7e8
-Greek_iota = 0x7e9
-Greek_kappa = 0x7ea
-Greek_lamda = 0x7eb
-Greek_lambda = 0x7eb
-Greek_mu = 0x7ec
-Greek_nu = 0x7ed
-Greek_xi = 0x7ee
-Greek_omicron = 0x7ef
-Greek_pi = 0x7f0
-Greek_rho = 0x7f1
-Greek_sigma = 0x7f2
-Greek_finalsmallsigma = 0x7f3
-Greek_tau = 0x7f4
-Greek_upsilon = 0x7f5
-Greek_phi = 0x7f6
-Greek_chi = 0x7f7
-Greek_psi = 0x7f8
-Greek_omega = 0x7f9
-Greek_switch = 0xFF7E
-leftradical = 0x8a1
-topleftradical = 0x8a2
-horizconnector = 0x8a3
-topintegral = 0x8a4
-botintegral = 0x8a5
-vertconnector = 0x8a6
-topleftsqbracket = 0x8a7
-botleftsqbracket = 0x8a8
-toprightsqbracket = 0x8a9
-botrightsqbracket = 0x8aa
-topleftparens = 0x8ab
-botleftparens = 0x8ac
-toprightparens = 0x8ad
-botrightparens = 0x8ae
-leftmiddlecurlybrace = 0x8af
-rightmiddlecurlybrace = 0x8b0
-topleftsummation = 0x8b1
-botleftsummation = 0x8b2
-topvertsummationconnector = 0x8b3
-botvertsummationconnector = 0x8b4
-toprightsummation = 0x8b5
-botrightsummation = 0x8b6
-rightmiddlesummation = 0x8b7
-lessthanequal = 0x8bc
-notequal = 0x8bd
-greaterthanequal = 0x8be
-integral = 0x8bf
-therefore = 0x8c0
-variation = 0x8c1
-infinity = 0x8c2
-nabla = 0x8c5
-approximate = 0x8c8
-similarequal = 0x8c9
-ifonlyif = 0x8cd
-implies = 0x8ce
-identical = 0x8cf
-radical = 0x8d6
-includedin = 0x8da
-includes = 0x8db
-intersection = 0x8dc
-union = 0x8dd
-logicaland = 0x8de
-logicalor = 0x8df
-partialderivative = 0x8ef
-function = 0x8f6
-leftarrow = 0x8fb
-uparrow = 0x8fc
-rightarrow = 0x8fd
-downarrow = 0x8fe
-blank = 0x9df
-soliddiamond = 0x9e0
-checkerboard = 0x9e1
-ht = 0x9e2
-ff = 0x9e3
-cr = 0x9e4
-lf = 0x9e5
-nl = 0x9e8
-vt = 0x9e9
-lowrightcorner = 0x9ea
-uprightcorner = 0x9eb
-upleftcorner = 0x9ec
-lowleftcorner = 0x9ed
-crossinglines = 0x9ee
-horizlinescan1 = 0x9ef
-horizlinescan3 = 0x9f0
-horizlinescan5 = 0x9f1
-horizlinescan7 = 0x9f2
-horizlinescan9 = 0x9f3
-leftt = 0x9f4
-rightt = 0x9f5
-bott = 0x9f6
-topt = 0x9f7
-vertbar = 0x9f8
-emspace = 0xaa1
-enspace = 0xaa2
-em3space = 0xaa3
-em4space = 0xaa4
-digitspace = 0xaa5
-punctspace = 0xaa6
-thinspace = 0xaa7
-hairspace = 0xaa8
-emdash = 0xaa9
-endash = 0xaaa
-signifblank = 0xaac
-ellipsis = 0xaae
-doubbaselinedot = 0xaaf
-onethird = 0xab0
-twothirds = 0xab1
-onefifth = 0xab2
-twofifths = 0xab3
-threefifths = 0xab4
-fourfifths = 0xab5
-onesixth = 0xab6
-fivesixths = 0xab7
-careof = 0xab8
-figdash = 0xabb
-leftanglebracket = 0xabc
-decimalpoint = 0xabd
-rightanglebracket = 0xabe
-marker = 0xabf
-oneeighth = 0xac3
-threeeighths = 0xac4
-fiveeighths = 0xac5
-seveneighths = 0xac6
-trademark = 0xac9
-signaturemark = 0xaca
-trademarkincircle = 0xacb
-leftopentriangle = 0xacc
-rightopentriangle = 0xacd
-emopencircle = 0xace
-emopenrectangle = 0xacf
-leftsinglequotemark = 0xad0
-rightsinglequotemark = 0xad1
-leftdoublequotemark = 0xad2
-rightdoublequotemark = 0xad3
-prescription = 0xad4
-minutes = 0xad6
-seconds = 0xad7
-latincross = 0xad9
-hexagram = 0xada
-filledrectbullet = 0xadb
-filledlefttribullet = 0xadc
-filledrighttribullet = 0xadd
-emfilledcircle = 0xade
-emfilledrect = 0xadf
-enopencircbullet = 0xae0
-enopensquarebullet = 0xae1
-openrectbullet = 0xae2
-opentribulletup = 0xae3
-opentribulletdown = 0xae4
-openstar = 0xae5
-enfilledcircbullet = 0xae6
-enfilledsqbullet = 0xae7
-filledtribulletup = 0xae8
-filledtribulletdown = 0xae9
-leftpointer = 0xaea
-rightpointer = 0xaeb
-club = 0xaec
-diamond = 0xaed
-heart = 0xaee
-maltesecross = 0xaf0
-dagger = 0xaf1
-doubledagger = 0xaf2
-checkmark = 0xaf3
-ballotcross = 0xaf4
-musicalsharp = 0xaf5
-musicalflat = 0xaf6
-malesymbol = 0xaf7
-femalesymbol = 0xaf8
-telephone = 0xaf9
-telephonerecorder = 0xafa
-phonographcopyright = 0xafb
-caret = 0xafc
-singlelowquotemark = 0xafd
-doublelowquotemark = 0xafe
-cursor = 0xaff
-leftcaret = 0xba3
-rightcaret = 0xba6
-downcaret = 0xba8
-upcaret = 0xba9
-overbar = 0xbc0
-downtack = 0xbc2
-upshoe = 0xbc3
-downstile = 0xbc4
-underbar = 0xbc6
-jot = 0xbca
-quad = 0xbcc
-uptack = 0xbce
-circle = 0xbcf
-upstile = 0xbd3
-downshoe = 0xbd6
-rightshoe = 0xbd8
-leftshoe = 0xbda
-lefttack = 0xbdc
-righttack = 0xbfc
-hebrew_doublelowline = 0xcdf
-hebrew_aleph = 0xce0
-hebrew_bet = 0xce1
-hebrew_beth = 0xce1
-hebrew_gimel = 0xce2
-hebrew_gimmel = 0xce2
-hebrew_dalet = 0xce3
-hebrew_daleth = 0xce3
-hebrew_he = 0xce4
-hebrew_waw = 0xce5
-hebrew_zain = 0xce6
-hebrew_zayin = 0xce6
-hebrew_chet = 0xce7
-hebrew_het = 0xce7
-hebrew_tet = 0xce8
-hebrew_teth = 0xce8
-hebrew_yod = 0xce9
-hebrew_finalkaph = 0xcea
-hebrew_kaph = 0xceb
-hebrew_lamed = 0xcec
-hebrew_finalmem = 0xced
-hebrew_mem = 0xcee
-hebrew_finalnun = 0xcef
-hebrew_nun = 0xcf0
-hebrew_samech = 0xcf1
-hebrew_samekh = 0xcf1
-hebrew_ayin = 0xcf2
-hebrew_finalpe = 0xcf3
-hebrew_pe = 0xcf4
-hebrew_finalzade = 0xcf5
-hebrew_finalzadi = 0xcf5
-hebrew_zade = 0xcf6
-hebrew_zadi = 0xcf6
-hebrew_qoph = 0xcf7
-hebrew_kuf = 0xcf7
-hebrew_resh = 0xcf8
-hebrew_shin = 0xcf9
-hebrew_taw = 0xcfa
-hebrew_taf = 0xcfa
-Hebrew_switch = 0xFF7E
-Thai_kokai = 0xda1
-Thai_khokhai = 0xda2
-Thai_khokhuat = 0xda3
-Thai_khokhwai = 0xda4
-Thai_khokhon = 0xda5
-Thai_khorakhang = 0xda6
-Thai_ngongu = 0xda7
-Thai_chochan = 0xda8
-Thai_choching = 0xda9
-Thai_chochang = 0xdaa
-Thai_soso = 0xdab
-Thai_chochoe = 0xdac
-Thai_yoying = 0xdad
-Thai_dochada = 0xdae
-Thai_topatak = 0xdaf
-Thai_thothan = 0xdb0
-Thai_thonangmontho = 0xdb1
-Thai_thophuthao = 0xdb2
-Thai_nonen = 0xdb3
-Thai_dodek = 0xdb4
-Thai_totao = 0xdb5
-Thai_thothung = 0xdb6
-Thai_thothahan = 0xdb7
-Thai_thothong = 0xdb8
-Thai_nonu = 0xdb9
-Thai_bobaimai = 0xdba
-Thai_popla = 0xdbb
-Thai_phophung = 0xdbc
-Thai_fofa = 0xdbd
-Thai_phophan = 0xdbe
-Thai_fofan = 0xdbf
-Thai_phosamphao = 0xdc0
-Thai_moma = 0xdc1
-Thai_yoyak = 0xdc2
-Thai_rorua = 0xdc3
-Thai_ru = 0xdc4
-Thai_loling = 0xdc5
-Thai_lu = 0xdc6
-Thai_wowaen = 0xdc7
-Thai_sosala = 0xdc8
-Thai_sorusi = 0xdc9
-Thai_sosua = 0xdca
-Thai_hohip = 0xdcb
-Thai_lochula = 0xdcc
-Thai_oang = 0xdcd
-Thai_honokhuk = 0xdce
-Thai_paiyannoi = 0xdcf
-Thai_saraa = 0xdd0
-Thai_maihanakat = 0xdd1
-Thai_saraaa = 0xdd2
-Thai_saraam = 0xdd3
-Thai_sarai = 0xdd4
-Thai_saraii = 0xdd5
-Thai_saraue = 0xdd6
-Thai_sarauee = 0xdd7
-Thai_sarau = 0xdd8
-Thai_sarauu = 0xdd9
-Thai_phinthu = 0xdda
-Thai_maihanakat_maitho = 0xdde
-Thai_baht = 0xddf
-Thai_sarae = 0xde0
-Thai_saraae = 0xde1
-Thai_sarao = 0xde2
-Thai_saraaimaimuan = 0xde3
-Thai_saraaimaimalai = 0xde4
-Thai_lakkhangyao = 0xde5
-Thai_maiyamok = 0xde6
-Thai_maitaikhu = 0xde7
-Thai_maiek = 0xde8
-Thai_maitho = 0xde9
-Thai_maitri = 0xdea
-Thai_maichattawa = 0xdeb
-Thai_thanthakhat = 0xdec
-Thai_nikhahit = 0xded
-Thai_leksun = 0xdf0
-Thai_leknung = 0xdf1
-Thai_leksong = 0xdf2
-Thai_leksam = 0xdf3
-Thai_leksi = 0xdf4
-Thai_lekha = 0xdf5
-Thai_lekhok = 0xdf6
-Thai_lekchet = 0xdf7
-Thai_lekpaet = 0xdf8
-Thai_lekkao = 0xdf9
-Hangul = 0xff31
-Hangul_Start = 0xff32
-Hangul_End = 0xff33
-Hangul_Hanja = 0xff34
-Hangul_Jamo = 0xff35
-Hangul_Romaja = 0xff36
-Hangul_Codeinput = 0xff37
-Hangul_Jeonja = 0xff38
-Hangul_Banja = 0xff39
-Hangul_PreHanja = 0xff3a
-Hangul_PostHanja = 0xff3b
-Hangul_SingleCandidate = 0xff3c
-Hangul_MultipleCandidate = 0xff3d
-Hangul_PreviousCandidate = 0xff3e
-Hangul_Special = 0xff3f
-Hangul_switch = 0xFF7E
-Hangul_Kiyeog = 0xea1
-Hangul_SsangKiyeog = 0xea2
-Hangul_KiyeogSios = 0xea3
-Hangul_Nieun = 0xea4
-Hangul_NieunJieuj = 0xea5
-Hangul_NieunHieuh = 0xea6
-Hangul_Dikeud = 0xea7
-Hangul_SsangDikeud = 0xea8
-Hangul_Rieul = 0xea9
-Hangul_RieulKiyeog = 0xeaa
-Hangul_RieulMieum = 0xeab
-Hangul_RieulPieub = 0xeac
-Hangul_RieulSios = 0xead
-Hangul_RieulTieut = 0xeae
-Hangul_RieulPhieuf = 0xeaf
-Hangul_RieulHieuh = 0xeb0
-Hangul_Mieum = 0xeb1
-Hangul_Pieub = 0xeb2
-Hangul_SsangPieub = 0xeb3
-Hangul_PieubSios = 0xeb4
-Hangul_Sios = 0xeb5
-Hangul_SsangSios = 0xeb6
-Hangul_Ieung = 0xeb7
-Hangul_Jieuj = 0xeb8
-Hangul_SsangJieuj = 0xeb9
-Hangul_Cieuc = 0xeba
-Hangul_Khieuq = 0xebb
-Hangul_Tieut = 0xebc
-Hangul_Phieuf = 0xebd
-Hangul_Hieuh = 0xebe
-Hangul_A = 0xebf
-Hangul_AE = 0xec0
-Hangul_YA = 0xec1
-Hangul_YAE = 0xec2
-Hangul_EO = 0xec3
-Hangul_E = 0xec4
-Hangul_YEO = 0xec5
-Hangul_YE = 0xec6
-Hangul_O = 0xec7
-Hangul_WA = 0xec8
-Hangul_WAE = 0xec9
-Hangul_OE = 0xeca
-Hangul_YO = 0xecb
-Hangul_U = 0xecc
-Hangul_WEO = 0xecd
-Hangul_WE = 0xece
-Hangul_WI = 0xecf
-Hangul_YU = 0xed0
-Hangul_EU = 0xed1
-Hangul_YI = 0xed2
-Hangul_I = 0xed3
-Hangul_J_Kiyeog = 0xed4
-Hangul_J_SsangKiyeog = 0xed5
-Hangul_J_KiyeogSios = 0xed6
-Hangul_J_Nieun = 0xed7
-Hangul_J_NieunJieuj = 0xed8
-Hangul_J_NieunHieuh = 0xed9
-Hangul_J_Dikeud = 0xeda
-Hangul_J_Rieul = 0xedb
-Hangul_J_RieulKiyeog = 0xedc
-Hangul_J_RieulMieum = 0xedd
-Hangul_J_RieulPieub = 0xede
-Hangul_J_RieulSios = 0xedf
-Hangul_J_RieulTieut = 0xee0
-Hangul_J_RieulPhieuf = 0xee1
-Hangul_J_RieulHieuh = 0xee2
-Hangul_J_Mieum = 0xee3
-Hangul_J_Pieub = 0xee4
-Hangul_J_PieubSios = 0xee5
-Hangul_J_Sios = 0xee6
-Hangul_J_SsangSios = 0xee7
-Hangul_J_Ieung = 0xee8
-Hangul_J_Jieuj = 0xee9
-Hangul_J_Cieuc = 0xeea
-Hangul_J_Khieuq = 0xeeb
-Hangul_J_Tieut = 0xeec
-Hangul_J_Phieuf = 0xeed
-Hangul_J_Hieuh = 0xeee
-Hangul_RieulYeorinHieuh = 0xeef
-Hangul_SunkyeongeumMieum = 0xef0
-Hangul_SunkyeongeumPieub = 0xef1
-Hangul_PanSios = 0xef2
-Hangul_KkogjiDalrinIeung = 0xef3
-Hangul_SunkyeongeumPhieuf = 0xef4
-Hangul_YeorinHieuh = 0xef5
-Hangul_AraeA = 0xef6
-Hangul_AraeAE = 0xef7
-Hangul_J_PanSios = 0xef8
-Hangul_J_KkogjiDalrinIeung = 0xef9
-Hangul_J_YeorinHieuh = 0xefa
-Korean_Won = 0xeff
+import sys
+import warnings
+
+from ..module import get_introspection_module
+
+Gdk = get_introspection_module('Gdk')
+
+warnings.warn('keysyms has been deprecated. Please use Gdk.KEY_<name> instead.',
+ RuntimeWarning)
+
+_modname = globals()['__name__']
+_keysyms = sys.modules[_modname]
+
+for name in dir(Gdk):
+ if name.startswith('KEY_'):
+ target = name[4:]
+ if target[0] in '0123456789':
+ target = '_' + target
+ value = getattr(Gdk, name)
+ setattr(_keysyms, target, value)
+
+
+# Not found in Gdk but left for compatibility.
Armenian_eternity = 0x14a1
Armenian_section_sign = 0x14a2
-Armenian_full_stop = 0x14a3
-Armenian_verjaket = 0x14a3
-Armenian_parenright = 0x14a4
Armenian_parenleft = 0x14a5
Armenian_guillemotright = 0x14a6
Armenian_guillemotleft = 0x14a7
Armenian_em_dash = 0x14a8
Armenian_dot = 0x14a9
Armenian_mijaket = 0x14a9
-Armenian_separation_mark = 0x14aa
-Armenian_but = 0x14aa
Armenian_comma = 0x14ab
Armenian_en_dash = 0x14ac
-Armenian_hyphen = 0x14ad
-Armenian_yentamna = 0x14ad
Armenian_ellipsis = 0x14ae
-Armenian_exclam = 0x14af
-Armenian_amanak = 0x14af
-Armenian_accent = 0x14b0
-Armenian_shesht = 0x14b0
-Armenian_question = 0x14b1
-Armenian_paruyk = 0x14b1
-Armenian_AYB = 0x14b2
-Armenian_ayb = 0x14b3
-Armenian_BEN = 0x14b4
-Armenian_ben = 0x14b5
-Armenian_GIM = 0x14b6
-Armenian_gim = 0x14b7
-Armenian_DA = 0x14b8
-Armenian_da = 0x14b9
-Armenian_YECH = 0x14ba
-Armenian_yech = 0x14bb
-Armenian_ZA = 0x14bc
-Armenian_za = 0x14bd
-Armenian_E = 0x14be
-Armenian_e = 0x14bf
-Armenian_AT = 0x14c0
-Armenian_at = 0x14c1
-Armenian_TO = 0x14c2
-Armenian_to = 0x14c3
-Armenian_ZHE = 0x14c4
-Armenian_zhe = 0x14c5
-Armenian_INI = 0x14c6
-Armenian_ini = 0x14c7
-Armenian_LYUN = 0x14c8
-Armenian_lyun = 0x14c9
-Armenian_KHE = 0x14ca
-Armenian_khe = 0x14cb
-Armenian_TSA = 0x14cc
-Armenian_tsa = 0x14cd
-Armenian_KEN = 0x14ce
-Armenian_ken = 0x14cf
-Armenian_HO = 0x14d0
-Armenian_ho = 0x14d1
-Armenian_DZA = 0x14d2
-Armenian_dza = 0x14d3
-Armenian_GHAT = 0x14d4
-Armenian_ghat = 0x14d5
-Armenian_TCHE = 0x14d6
-Armenian_tche = 0x14d7
-Armenian_MEN = 0x14d8
-Armenian_men = 0x14d9
-Armenian_HI = 0x14da
-Armenian_hi = 0x14db
-Armenian_NU = 0x14dc
-Armenian_nu = 0x14dd
-Armenian_SHA = 0x14de
-Armenian_sha = 0x14df
-Armenian_VO = 0x14e0
-Armenian_vo = 0x14e1
-Armenian_CHA = 0x14e2
-Armenian_cha = 0x14e3
-Armenian_PE = 0x14e4
-Armenian_pe = 0x14e5
-Armenian_JE = 0x14e6
-Armenian_je = 0x14e7
-Armenian_RA = 0x14e8
-Armenian_ra = 0x14e9
-Armenian_SE = 0x14ea
-Armenian_se = 0x14eb
-Armenian_VEV = 0x14ec
-Armenian_vev = 0x14ed
-Armenian_TYUN = 0x14ee
-Armenian_tyun = 0x14ef
-Armenian_RE = 0x14f0
-Armenian_re = 0x14f1
-Armenian_TSO = 0x14f2
-Armenian_tso = 0x14f3
-Armenian_VYUN = 0x14f4
-Armenian_vyun = 0x14f5
-Armenian_PYUR = 0x14f6
-Armenian_pyur = 0x14f7
-Armenian_KE = 0x14f8
-Armenian_ke = 0x14f9
-Armenian_O = 0x14fa
-Armenian_o = 0x14fb
-Armenian_FE = 0x14fc
-Armenian_fe = 0x14fd
-Armenian_apostrophe = 0x14fe
-Armenian_ligature_ew = 0x14ff
-Georgian_an = 0x15d0
-Georgian_ban = 0x15d1
-Georgian_gan = 0x15d2
-Georgian_don = 0x15d3
-Georgian_en = 0x15d4
-Georgian_vin = 0x15d5
-Georgian_zen = 0x15d6
-Georgian_tan = 0x15d7
-Georgian_in = 0x15d8
-Georgian_kan = 0x15d9
-Georgian_las = 0x15da
-Georgian_man = 0x15db
-Georgian_nar = 0x15dc
-Georgian_on = 0x15dd
-Georgian_par = 0x15de
-Georgian_zhar = 0x15df
-Georgian_rae = 0x15e0
-Georgian_san = 0x15e1
-Georgian_tar = 0x15e2
-Georgian_un = 0x15e3
-Georgian_phar = 0x15e4
-Georgian_khar = 0x15e5
-Georgian_ghan = 0x15e6
-Georgian_qar = 0x15e7
-Georgian_shin = 0x15e8
-Georgian_chin = 0x15e9
-Georgian_can = 0x15ea
-Georgian_jil = 0x15eb
-Georgian_cil = 0x15ec
-Georgian_char = 0x15ed
-Georgian_xan = 0x15ee
-Georgian_jhan = 0x15ef
-Georgian_hae = 0x15f0
-Georgian_he = 0x15f1
-Georgian_hie = 0x15f2
-Georgian_we = 0x15f3
-Georgian_har = 0x15f4
-Georgian_hoe = 0x15f5
-Georgian_fi = 0x15f6
-EcuSign = 0x20a0
-ColonSign = 0x20a1
-CruzeiroSign = 0x20a2
-FFrancSign = 0x20a3
-LiraSign = 0x20a4
-MillSign = 0x20a5
-NairaSign = 0x20a6
-PesetaSign = 0x20a7
-RupeeSign = 0x20a8
-WonSign = 0x20a9
-NewSheqelSign = 0x20aa
-DongSign = 0x20ab
-EuroSign = 0x20ac
diff --git a/gi/overrides/meson.build b/gi/overrides/meson.build
new file mode 100644
index 0000000..6ff073f
--- /dev/null
+++ b/gi/overrides/meson.build
@@ -0,0 +1,15 @@
+python_sources = [
+ 'GLib.py',
+ 'Gtk.py',
+ 'Gdk.py',
+ 'GdkPixbuf.py',
+ 'GObject.py',
+ 'Gio.py',
+ 'GIMarshallingTests.py',
+ 'Pango.py',
+ 'keysyms.py',
+ '__init__.py']
+
+python.install_sources(python_sources,
+ subdir : join_paths('gi', 'overrides')
+)
diff --git a/gi/_gobject/pygboxed.c b/gi/pygboxed.c
index 541e77b..595f815 100644
--- a/gi/_gobject/pygboxed.c
+++ b/gi/pygboxed.c
@@ -15,78 +15,95 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
-#include <pyglib.h>
-#include "pygobject-private.h"
-#include "pygboxed.h"
+#include <Python.h>
+#include <glib-object.h>
-#include "pygi.h"
+#include "pygboxed.h"
+#include "pygi-type.h"
+#include "pygi-type.h"
+#include "pygi-util.h"
GQuark pygboxed_type_key;
-GQuark pygboxed_marshal_key;
-PYGLIB_DEFINE_TYPE("gobject.GBoxed", PyGBoxed_Type, PyGBoxed);
+PYGI_DEFINE_TYPE("gobject.GBoxed", PyGBoxed_Type, PyGBoxed);
static void
-pyg_boxed_dealloc(PyGBoxed *self)
+gboxed_dealloc(PyGBoxed *self)
{
- if (self->free_on_dealloc && self->boxed) {
- PyGILState_STATE state = pyglib_gil_state_ensure();
- g_boxed_free(self->gtype, self->boxed);
- pyglib_gil_state_release(state);
+ if (self->free_on_dealloc && pyg_boxed_get_ptr (self)) {
+ PyGILState_STATE state = PyGILState_Ensure();
+ g_boxed_free (self->gtype, pyg_boxed_get_ptr (self));
+ PyGILState_Release(state);
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject*
-pyg_boxed_richcompare(PyObject *self, PyObject *other, int op)
+gboxed_richcompare(PyObject *self, PyObject *other, int op)
{
if (Py_TYPE(self) == Py_TYPE(other) &&
PyObject_IsInstance(self, (PyObject*)&PyGBoxed_Type))
- return _pyglib_generic_ptr_richcompare(((PyGBoxed*)self)->boxed,
- ((PyGBoxed*)other)->boxed,
- op);
+ return pyg_ptr_richcompare (pyg_boxed_get_ptr (self),
+ pyg_boxed_get_ptr (other),
+ op);
else {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
}
-
-static long
-pyg_boxed_hash(PyGBoxed *self)
+static Py_hash_t
+gboxed_hash(PyGBoxed *self)
{
- return (long)self->boxed;
+ return (Py_hash_t)(gintptr)(pyg_boxed_get_ptr (self));
}
static PyObject *
-pyg_boxed_repr(PyGBoxed *self)
+gboxed_repr(PyGBoxed *boxed)
{
- gchar buf[128];
+ PyObject *module, *repr, *self = (PyObject *)boxed;
+ gchar *module_str, *namespace;
+
+ module = PyObject_GetAttrString (self, "__module__");
+ if (module == NULL)
+ return NULL;
+
+ if (!PyUnicode_Check (module)) {
+ Py_DECREF (module);
+ return NULL;
+ }
+
+ module_str = PyUnicode_AsUTF8 (module);
+ namespace = g_strrstr (module_str, ".");
+ if (namespace == NULL) {
+ namespace = module_str;
+ } else {
+ namespace += 1;
+ }
- g_snprintf(buf, sizeof(buf), "<%s at 0x%lx>", g_type_name(self->gtype),
- (long)self->boxed);
- return PYGLIB_PyUnicode_FromString(buf);
+ repr = PyUnicode_FromFormat ("<%s.%s object at %p (%s at %p)>",
+ namespace, Py_TYPE (self)->tp_name,
+ self, g_type_name (boxed->gtype),
+ pyg_boxed_get_ptr (boxed));
+ Py_DECREF (module);
+ return repr;
}
static int
-pyg_boxed_init(PyGBoxed *self, PyObject *args, PyObject *kwargs)
+gboxed_init(PyGBoxed *self, PyObject *args, PyObject *kwargs)
{
gchar buf[512];
if (!PyArg_ParseTuple(args, ":GBoxed.__init__"))
return -1;
- self->boxed = NULL;
+ pyg_boxed_set_ptr (self, NULL);
self->gtype = 0;
self->free_on_dealloc = FALSE;
@@ -97,27 +114,25 @@ pyg_boxed_init(PyGBoxed *self, PyObject *args, PyObject *kwargs)
}
static void
-pyg_boxed_free(PyObject *op)
+gboxed_free(PyObject *op)
{
PyObject_FREE(op);
}
static PyObject *
-pyg_boxed_copy(PyGBoxed *self)
+gboxed_copy(PyGBoxed *self)
{
- return pyg_boxed_new (self->gtype, self->boxed, TRUE, TRUE);
+ return pygi_gboxed_new (self->gtype, pyg_boxed_get_ptr (self), TRUE, TRUE);
}
-
-
static PyMethodDef pygboxed_methods[] = {
- { "copy", (PyCFunction) pyg_boxed_copy, METH_NOARGS },
+ { "copy", (PyCFunction) gboxed_copy, METH_NOARGS },
{ NULL, NULL, 0 }
};
/**
- * pyg_register_boxed:
+ * pygi_register_gboxed:
* @dict: the module dictionary to store the wrapper class.
* @class_name: the Python name for the wrapper class.
* @boxed_type: the GType of the boxed type being wrapped.
@@ -128,8 +143,8 @@ static PyMethodDef pygboxed_methods[] = {
* will be stored in the provided module dictionary.
*/
void
-pyg_register_boxed(PyObject *dict, const gchar *class_name,
- GType boxed_type, PyTypeObject *type)
+pygi_register_gboxed (PyObject *dict, const gchar *class_name,
+ GType boxed_type, PyTypeObject *type)
{
PyObject *o;
@@ -137,9 +152,10 @@ pyg_register_boxed(PyObject *dict, const gchar *class_name,
g_return_if_fail(class_name != NULL);
g_return_if_fail(boxed_type != 0);
- if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_boxed_dealloc;
+ if (!type->tp_dealloc) type->tp_dealloc = (destructor)gboxed_dealloc;
- Py_TYPE(type) = &PyType_Type;
+ Py_SET_TYPE(type, &PyType_Type);
+ g_assert (Py_TYPE (&PyGBoxed_Type) != NULL);
type->tp_base = &PyGBoxed_Type;
if (PyType_Ready(type) < 0) {
@@ -157,7 +173,7 @@ pyg_register_boxed(PyObject *dict, const gchar *class_name,
}
/**
- * pyg_boxed_new:
+ * pygi_gboxed_new:
* @boxed_type: the GType of the boxed value.
* @boxed: the boxed value.
* @copy_boxed: whether the new boxed wrapper should hold a copy of the value.
@@ -169,11 +185,11 @@ pyg_register_boxed(PyObject *dict, const gchar *class_name,
* wrapper will be freed when the wrapper is deallocated. If
* @copy_boxed is True, then @own_ref must also be True.
*
- * Returns: the boxed wrapper.
+ * Returns: the boxed wrapper or %NULL and sets an exception.
*/
PyObject *
-pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed,
- gboolean own_ref)
+pygi_gboxed_new (GType boxed_type, gpointer boxed, gboolean copy_boxed,
+ gboolean own_ref)
{
PyGILState_STATE state;
PyGBoxed *self;
@@ -182,11 +198,11 @@ pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed,
g_return_val_if_fail(boxed_type != 0, NULL);
g_return_val_if_fail(!copy_boxed || (copy_boxed && own_ref), NULL);
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
if (!boxed) {
Py_INCREF(Py_None);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return Py_None;
}
@@ -198,38 +214,58 @@ pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed,
if (!tp)
tp = (PyTypeObject *)&PyGBoxed_Type; /* fallback */
+ if (!PyType_IsSubtype (tp, &PyGBoxed_Type)) {
+ PyErr_Format (PyExc_RuntimeError, "%s isn't a GBoxed", tp->tp_name);
+ PyGILState_Release (state);
+ return NULL;
+ }
+
self = (PyGBoxed *)tp->tp_alloc(tp, 0);
if (self == NULL) {
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return NULL;
}
if (copy_boxed)
boxed = g_boxed_copy(boxed_type, boxed);
- self->boxed = boxed;
+ pyg_boxed_set_ptr (self, boxed);
self->gtype = boxed_type;
self->free_on_dealloc = own_ref;
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return (PyObject *)self;
}
-void
-pygobject_boxed_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_gboxed_register_types(PyObject *d)
{
+ PyObject *pygtype;
+
pygboxed_type_key = g_quark_from_static_string("PyGBoxed::class");
- pygboxed_marshal_key = g_quark_from_static_string("PyGBoxed::marshal");
- PyGBoxed_Type.tp_dealloc = (destructor)pyg_boxed_dealloc;
- PyGBoxed_Type.tp_richcompare = pyg_boxed_richcompare;
- PyGBoxed_Type.tp_repr = (reprfunc)pyg_boxed_repr;
+ PyGBoxed_Type.tp_dealloc = (destructor)gboxed_dealloc;
+ PyGBoxed_Type.tp_richcompare = gboxed_richcompare;
+ PyGBoxed_Type.tp_repr = (reprfunc)gboxed_repr;
PyGBoxed_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
PyGBoxed_Type.tp_methods = pygboxed_methods;
- PyGBoxed_Type.tp_init = (initproc)pyg_boxed_init;
- PyGBoxed_Type.tp_free = (freefunc)pyg_boxed_free;
- PyGBoxed_Type.tp_hash = (hashfunc)pyg_boxed_hash;
-
- PYGOBJECT_REGISTER_GTYPE(d, PyGBoxed_Type, "GBoxed", G_TYPE_BOXED);
+ PyGBoxed_Type.tp_init = (initproc)gboxed_init;
+ PyGBoxed_Type.tp_free = (freefunc)gboxed_free;
+ PyGBoxed_Type.tp_hash = (hashfunc)gboxed_hash;
+ PyGBoxed_Type.tp_alloc = PyType_GenericAlloc;
+ PyGBoxed_Type.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyGBoxed_Type))
+ return -1;
+
+ pygtype = pyg_type_wrapper_new (G_TYPE_POINTER);
+ PyDict_SetItemString (PyGBoxed_Type.tp_dict, "__gtype__", pygtype);
+ Py_DECREF (pygtype);
+
+ PyDict_SetItemString(d, "GBoxed", (PyObject *)&PyGBoxed_Type);
+
+ return 0;
}
diff --git a/gi/_gobject/pygboxed.h b/gi/pygboxed.h
index 8433b9d..c1b80bf 100644
--- a/gi/_gobject/pygboxed.h
+++ b/gi/pygboxed.h
@@ -14,14 +14,21 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGOBJECT_BOXED_H__
#define __PYGOBJECT_BOXED_H__
-void pygobject_boxed_register_types(PyObject *d);
+extern GQuark pygboxed_type_key;
+
+extern PyTypeObject PyGBoxed_Type;
+
+void pygi_register_gboxed (PyObject *dict, const gchar *class_name,
+ GType boxed_type, PyTypeObject *type);
+PyObject * pygi_gboxed_new (GType boxed_type, gpointer boxed,
+ gboolean copy_boxed, gboolean own_ref);
+
+int pygi_gboxed_register_types(PyObject *d);
#endif /* __PYGOBJECT_BOXED_H__ */
diff --git a/gi/_gobject/pygenum.c b/gi/pygenum.c
index 89e3a06..37495e8 100644
--- a/gi/_gobject/pygenum.c
+++ b/gi/pygenum.c
@@ -16,31 +16,28 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <pyglib.h>
-#include "pygobject-private.h"
-#include "pygi.h"
+#include <config.h>
+#include "pygi-type.h"
+#include "pygi-util.h"
+#include "pygi-type.h"
+#include "pygi-basictype.h"
#include "pygenum.h"
+#include "pygboxed.h"
GQuark pygenum_class_key;
-PYGLIB_DEFINE_TYPE("gobject.GEnum", PyGEnum_Type, PyGEnum);
+PYGI_DEFINE_TYPE("gobject.GEnum", PyGEnum_Type, PyGEnum);
static PyObject *
pyg_enum_val_new(PyObject* subclass, GType gtype, PyObject *intval)
{
PyObject *args, *item;
args = Py_BuildValue("(O)", intval);
- item = (&PYGLIB_PyLong_Type)->tp_new((PyTypeObject*)subclass, args, NULL);
+ item = (&PyLong_Type)->tp_new((PyTypeObject*)subclass, args, NULL);
Py_DECREF(args);
if (!item)
return NULL;
@@ -54,7 +51,7 @@ pyg_enum_richcompare(PyGEnum *self, PyObject *other, int op)
{
static char warning[256];
- if (!PYGLIB_PyLong_Check(other)) {
+ if (!PyLong_Check (other)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
@@ -72,29 +69,50 @@ pyg_enum_richcompare(PyGEnum *self, PyObject *other, int op)
static PyObject *
pyg_enum_repr(PyGEnum *self)
{
- GEnumClass *enum_class;
- const char *value;
- guint index;
- static char tmp[256];
- long l;
+ PyObject *module;
+ GEnumClass *enum_class;
+ const char *value;
+ guint index;
+ char *namespace, *module_str;
+ static char tmp[256];
+ long l;
+
+ module = PyObject_GetAttrString ((PyObject *)self, "__module__");
+ if (module == NULL)
+ return NULL;
- enum_class = g_type_class_ref(self->gtype);
- g_assert(G_IS_ENUM_CLASS(enum_class));
+ if (!PyUnicode_Check (module)) {
+ Py_DECREF (module);
+ return NULL;
+ }
- l = PYGLIB_PyLong_AS_LONG(self);
- for (index = 0; index < enum_class->n_values; index++)
- if (l == enum_class->values[index].value)
- break;
+ enum_class = g_type_class_ref(self->gtype);
+ g_assert(G_IS_ENUM_CLASS(enum_class));
- value = enum_class->values[index].value_name;
- if (value)
- sprintf(tmp, "<enum %s of type %s>", value, g_type_name(self->gtype));
- else
- sprintf(tmp, "<enum %ld of type %s>", PYGLIB_PyLong_AS_LONG(self), g_type_name(self->gtype));
+ l = PyLong_AS_LONG ((PyObject*)self);
+ for (index = 0; index < enum_class->n_values; index++)
+ if (l == enum_class->values[index].value)
+ break;
- g_type_class_unref(enum_class);
+ module_str = PyUnicode_AsUTF8 (module);
+ namespace = g_strrstr (module_str, ".");
+ if (namespace == NULL) {
+ namespace = module_str;
+ } else {
+ namespace += 1;
+ }
- return PYGLIB_PyUnicode_FromString(tmp);
+ value = enum_class->values[index].value_name;
+ if (value)
+ sprintf(tmp, "<enum %s of type %s.%s>", value,
+ namespace, Py_TYPE (self)->tp_name);
+ else
+ sprintf(tmp, "<enum %ld of type %s.%s>", PyLong_AS_LONG ((PyObject*)self),
+ namespace, Py_TYPE (self)->tp_name);
+ Py_DECREF (module);
+ g_type_class_unref(enum_class);
+
+ return PyUnicode_FromString (tmp);
}
static PyObject *
@@ -143,7 +161,7 @@ pyg_enum_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
* values might not have been that good", but we need to keep
* backward compatibility.
*/
- if (!PyDict_Check(values) || PyDict_Size(values) > eclass->n_values) {
+ if (!PyDict_Check(values) || (gsize)PyDict_Size(values) > eclass->n_values) {
PyErr_SetString(PyExc_TypeError, "__enum_values__ badly formed");
Py_DECREF(values);
g_type_class_unref(eclass);
@@ -152,7 +170,7 @@ pyg_enum_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
g_type_class_unref(eclass);
- intvalue = PYGLIB_PyLong_FromLong(value);
+ intvalue = PyLong_FromLong(value);
ret = PyDict_GetItem(values, intvalue);
Py_DECREF(intvalue);
Py_DECREF(values);
@@ -182,11 +200,11 @@ pyg_enum_from_gtype (GType gtype, int value)
if (!pyclass)
pyclass = pyg_enum_add(NULL, g_type_name(gtype), NULL, gtype);
if (!pyclass)
- return PYGLIB_PyLong_FromLong(value);
+ return PyLong_FromLong(value);
values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
"__enum_values__");
- intvalue = PYGLIB_PyLong_FromLong(value);
+ intvalue = PyLong_FromLong(value);
retval = PyDict_GetItem(values, intvalue);
if (retval) {
Py_INCREF(retval);
@@ -213,7 +231,7 @@ pyg_enum_add (PyObject * module,
PyGILState_STATE state;
PyObject *instance_dict, *stub, *values, *o;
GEnumClass *eclass;
- int i;
+ guint i;
g_return_val_if_fail(typename != NULL, NULL);
if (!g_type_is_a (gtype, G_TYPE_ENUM)) {
@@ -222,7 +240,7 @@ pyg_enum_add (PyObject * module,
return NULL;
}
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
/* Create a new type derived from GEnum. This is the same as:
* >>> stub = type(typename, (GEnum,), {})
@@ -234,17 +252,16 @@ pyg_enum_add (PyObject * module,
Py_DECREF(instance_dict);
if (!stub) {
PyErr_SetString(PyExc_RuntimeError, "can't create const");
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return NULL;
}
((PyTypeObject *)stub)->tp_flags &= ~Py_TPFLAGS_BASETYPE;
- ((PyTypeObject *)stub)->tp_new = pyg_enum_new;
if (module)
PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
"__module__",
- PYGLIB_PyUnicode_FromString(PyModule_GetName(module)));
+ PyUnicode_FromString (PyModule_GetName(module)));
g_type_set_qdata(gtype, pygenum_class_key, stub);
@@ -265,7 +282,7 @@ pyg_enum_add (PyObject * module,
for (i = 0; i < eclass->n_values; i++) {
PyObject *item, *intval;
- intval = PYGLIB_PyLong_FromLong(eclass->values[i].value);
+ intval = PyLong_FromLong(eclass->values[i].value);
item = pyg_enum_val_new(stub, gtype, intval);
PyDict_SetItem(values, intval, item);
Py_DECREF(intval);
@@ -287,7 +304,7 @@ pyg_enum_add (PyObject * module,
g_type_class_unref(eclass);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return stub;
}
@@ -297,7 +314,7 @@ pyg_enum_reduce(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, ":GEnum.__reduce__"))
return NULL;
- return Py_BuildValue("(O(i)O)", Py_TYPE(self), PYGLIB_PyLong_AsLong(self),
+ return Py_BuildValue("(O(i)O)", Py_TYPE(self), PyLong_AsLong (self),
PyObject_GetAttrString(self, "__dict__"));
}
@@ -307,13 +324,17 @@ pyg_enum_get_value_name(PyGEnum *self, void *closure)
GEnumClass *enum_class;
GEnumValue *enum_value;
PyObject *retval;
+ gint intvalue;
+
+ if (!pygi_gint_from_py ((PyObject*) self, &intvalue))
+ return NULL;
enum_class = g_type_class_ref(self->gtype);
g_assert(G_IS_ENUM_CLASS(enum_class));
- enum_value = g_enum_get_value(enum_class, PYGLIB_PyLong_AS_LONG(self));
+ enum_value = g_enum_get_value(enum_class, intvalue);
- retval = PYGLIB_PyUnicode_FromString(enum_value->value_name);
+ retval = pygi_utf8_to_py (enum_value->value_name);
g_type_class_unref(enum_class);
return retval;
@@ -325,13 +346,18 @@ pyg_enum_get_value_nick(PyGEnum *self, void *closure)
GEnumClass *enum_class;
GEnumValue *enum_value;
PyObject *retval;
+ gint intvalue;
+
+ if (!pygi_gint_from_py ((PyObject*) self, &intvalue))
+ return NULL;
enum_class = g_type_class_ref(self->gtype);
g_assert(G_IS_ENUM_CLASS(enum_class));
- enum_value = g_enum_get_value(enum_class, PYGLIB_PyLong_AS_LONG(self));
+ enum_value = g_enum_get_value(enum_class, intvalue);
+
+ retval = pygi_utf8_to_py (enum_value->value_nick);
- retval = PYGLIB_PyUnicode_FromString(enum_value->value_nick);
g_type_class_unref(enum_class);
return retval;
@@ -349,23 +375,34 @@ static PyGetSetDef pyg_enum_getsets[] = {
{ NULL, 0, 0 }
};
-void
-pygobject_enum_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_enum_register_types(PyObject *d)
{
+ PyObject *pygtype;
+
pygenum_class_key = g_quark_from_static_string("PyGEnum::class");
- PyGEnum_Type.tp_base = &PYGLIB_PyLong_Type;
-#if PY_VERSION_HEX < 0x03000000
+ PyGEnum_Type.tp_base = &PyLong_Type;
PyGEnum_Type.tp_new = pyg_enum_new;
-#else
- PyGEnum_Type.tp_new = PyLong_Type.tp_new;
PyGEnum_Type.tp_hash = PyLong_Type.tp_hash;
-#endif
PyGEnum_Type.tp_repr = (reprfunc)pyg_enum_repr;
PyGEnum_Type.tp_str = (reprfunc)pyg_enum_repr;
PyGEnum_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
PyGEnum_Type.tp_richcompare = (richcmpfunc)pyg_enum_richcompare;
PyGEnum_Type.tp_methods = pyg_enum_methods;
PyGEnum_Type.tp_getset = pyg_enum_getsets;
- PYGOBJECT_REGISTER_GTYPE(d, PyGEnum_Type, "GEnum", G_TYPE_ENUM);
+ PyGEnum_Type.tp_alloc = PyType_GenericAlloc;
+ if (PyType_Ready(&PyGEnum_Type))
+ return -1;
+
+ pygtype = pyg_type_wrapper_new (G_TYPE_ENUM);
+ PyDict_SetItemString (PyGEnum_Type.tp_dict, "__gtype__", pygtype);
+ Py_DECREF (pygtype);
+
+ PyDict_SetItemString(d, "GEnum", (PyObject *)&PyGEnum_Type);
+
+ return 0;
}
diff --git a/gi/pygenum.h b/gi/pygenum.h
new file mode 100644
index 0000000..5b46d35
--- /dev/null
+++ b/gi/pygenum.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * 2004-2008 Johan Dahlin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGOBJECT_ENUM_H__
+#define __PYGOBJECT_ENUM_H__
+
+extern GQuark pygenum_class_key;
+
+#define PyGEnum_Check(x) (PyObject_IsInstance((PyObject *)x, (PyObject *)&PyGEnum_Type) && g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_ENUM))
+
+typedef struct {
+ PyLongObject parent;
+ int zero_pad; /* must always be 0 */
+ GType gtype;
+} PyGEnum;
+
+extern PyTypeObject PyGEnum_Type;
+
+PyObject * pyg_enum_add (PyObject * module,
+ const char * type_name,
+ const char * strip_prefix,
+ GType gtype);
+
+PyObject * pyg_enum_from_gtype (GType gtype,
+ int value);
+
+gint pyg_enum_get_value (GType enum_type, PyObject *obj, gint *val);
+
+int pygi_enum_register_types(PyObject *d);
+
+#endif /* __PYGOBJECT_ENUM_H__ */
diff --git a/gi/_gobject/pygflags.c b/gi/pygflags.c
index bdeaae7..df1280f 100644
--- a/gi/_gobject/pygflags.c
+++ b/gi/pygflags.c
@@ -16,24 +16,20 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
-#include <pyglib.h>
-#include "pygobject-private.h"
+#include "pygi-type.h"
+#include "pygi-util.h"
+#include "pygi-type.h"
#include "pygflags.h"
-
-#include "pygi.h"
+#include "pygboxed.h"
GQuark pygflags_class_key;
-PYGLIB_DEFINE_TYPE("gobject.GFlags", PyGFlags_Type, PyGFlags);
+PYGI_DEFINE_TYPE("gobject.GFlags", PyGFlags_Type, PyGFlags);
static PyObject *
pyg_flags_val_new(PyObject* subclass, GType gtype, PyObject *intval)
@@ -41,7 +37,7 @@ pyg_flags_val_new(PyObject* subclass, GType gtype, PyObject *intval)
PyObject *args, *item;
args = Py_BuildValue("(O)", intval);
g_assert(PyObject_IsSubclass(subclass, (PyObject*) &PyGFlags_Type));
- item = PYGLIB_PyLong_Type.tp_new((PyTypeObject*)subclass, args, NULL);
+ item = PyLong_Type.tp_new((PyTypeObject*)subclass, args, NULL);
Py_DECREF(args);
if (!item)
return NULL;
@@ -55,7 +51,7 @@ pyg_flags_richcompare(PyGFlags *self, PyObject *other, int op)
{
static char warning[256];
- if (!PYGLIB_PyLong_Check(other)) {
+ if (!PyLong_Check (other)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
@@ -75,7 +71,7 @@ generate_repr(GType gtype, guint value)
{
GFlagsClass *flags_class;
char *retval = NULL, *tmp;
- int i;
+ guint i;
flags_class = g_type_class_ref(gtype);
g_assert(G_IS_FLAGS_CLASS(flags_class));
@@ -106,20 +102,42 @@ generate_repr(GType gtype, guint value)
static PyObject *
pyg_flags_repr(PyGFlags *self)
{
- char *tmp, *retval;
- PyObject *pyretval;
+ char *tmp, *retval, *module_str, *namespace;
+ PyObject *pyretval, *module;
+
+ tmp = generate_repr(self->gtype, (guint)PyLong_AsUnsignedLongMask ((PyObject*)self));
+
+ module = PyObject_GetAttrString ((PyObject *)self, "__module__");
+ if (module == NULL) {
+ g_free (tmp);
+ return NULL;
+ }
- tmp = generate_repr(self->gtype, PYGLIB_PyLong_AsUnsignedLong(self));
+ if (!PyUnicode_Check (module)) {
+ g_free (tmp);
+ Py_DECREF (module);
+ return NULL;
+ }
+
+ module_str = PyUnicode_AsUTF8 (module);
+ namespace = g_strrstr (module_str, ".");
+ if (namespace == NULL) {
+ namespace = module_str;
+ } else {
+ namespace += 1;
+ }
if (tmp)
- retval = g_strdup_printf("<flags %s of type %s>", tmp,
- g_type_name(self->gtype));
+ retval = g_strdup_printf("<flags %s of type %s.%s>", tmp,
+ namespace, Py_TYPE (self)->tp_name);
else
- retval = g_strdup_printf("<flags %ld of type %s>", PYGLIB_PyLong_AsUnsignedLong(self),
- g_type_name(self->gtype));
+ retval = g_strdup_printf("<flags %ld of type %s.%s>",
+ PyLong_AsUnsignedLongMask ((PyObject*)self),
+ namespace, Py_TYPE (self)->tp_name);
g_free(tmp);
+ Py_DECREF (module);
- pyretval = PYGLIB_PyUnicode_FromString(retval);
+ pyretval = PyUnicode_FromString (retval);
g_free(retval);
return pyretval;
@@ -168,7 +186,7 @@ pyg_flags_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
g_type_class_unref(eclass);
- pyint = PYGLIB_PyLong_FromUnsignedLong(value);
+ pyint = PyLong_FromUnsignedLong (value);
ret = PyDict_GetItem(values, pyint);
if (!ret) {
PyErr_Clear();
@@ -191,7 +209,7 @@ pyg_flags_from_gtype (GType gtype, guint value)
PyObject *pyclass, *values, *retval, *pyint;
if (PyErr_Occurred())
- return PYGLIB_PyLong_FromUnsignedLong(0);
+ return PyLong_FromUnsignedLong (0);
g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
@@ -206,11 +224,11 @@ pyg_flags_from_gtype (GType gtype, guint value)
if (!pyclass)
pyclass = pyg_flags_add(NULL, g_type_name(gtype), NULL, gtype);
if (!pyclass)
- return PYGLIB_PyLong_FromUnsignedLong(value);
+ return PyLong_FromUnsignedLong (value);
values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
"__flags_values__");
- pyint = PYGLIB_PyLong_FromUnsignedLong(value);
+ pyint = PyLong_FromUnsignedLong (value);
retval = PyDict_GetItem(values, pyint);
if (!retval) {
PyErr_Clear();
@@ -238,7 +256,7 @@ pyg_flags_add (PyObject * module,
PyGILState_STATE state;
PyObject *instance_dict, *stub, *values, *o;
GFlagsClass *eclass;
- int i;
+ guint i;
g_return_val_if_fail(typename != NULL, NULL);
if (!g_type_is_a(gtype, G_TYPE_FLAGS)) {
@@ -247,7 +265,7 @@ pyg_flags_add (PyObject * module,
return NULL;
}
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
/* Create a new type derived from GFlags. This is the same as:
* >>> stub = type(typename, (GFlags,), {})
@@ -259,17 +277,16 @@ pyg_flags_add (PyObject * module,
Py_DECREF(instance_dict);
if (!stub) {
PyErr_SetString(PyExc_RuntimeError, "can't create GFlags subtype");
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return NULL;
}
((PyTypeObject *)stub)->tp_flags &= ~Py_TPFLAGS_BASETYPE;
- ((PyTypeObject *)stub)->tp_new = pyg_flags_new;
if (module) {
PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
"__module__",
- PYGLIB_PyUnicode_FromString(PyModule_GetName(module)));
+ PyUnicode_FromString (PyModule_GetName(module)));
/* Add it to the module name space */
PyModule_AddObject(module, (char*)typename, stub);
@@ -288,7 +305,7 @@ pyg_flags_add (PyObject * module,
for (i = 0; i < eclass->n_values; i++) {
PyObject *item, *intval;
- intval = PYGLIB_PyLong_FromUnsignedLong(eclass->values[i].value);
+ intval = PyLong_FromUnsignedLong (eclass->values[i].value);
g_assert(PyErr_Occurred() == NULL);
item = pyg_flags_val_new(stub, gtype, intval);
PyDict_SetItem(values, intval, item);
@@ -311,7 +328,7 @@ pyg_flags_add (PyObject * module,
g_type_class_unref(eclass);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return stub;
}
@@ -320,32 +337,32 @@ static PyObject *
pyg_flags_and(PyGFlags *a, PyGFlags *b)
{
if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
- return PYGLIB_PyLong_Type.tp_as_number->nb_and((PyObject*)a,
+ return PyLong_Type.tp_as_number->nb_and((PyObject*)a,
(PyObject*)b);
return pyg_flags_from_gtype(a->gtype,
- PYGLIB_PyLong_AsUnsignedLong(a) & PYGLIB_PyLong_AsUnsignedLong(b));
+ (guint)(PyLong_AsUnsignedLongMask ((PyObject*)a) & PyLong_AsUnsignedLongMask ((PyObject*)b)));
}
static PyObject *
pyg_flags_or(PyGFlags *a, PyGFlags *b)
{
if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
- return PYGLIB_PyLong_Type.tp_as_number->nb_or((PyObject*)a,
+ return PyLong_Type.tp_as_number->nb_or((PyObject*)a,
(PyObject*)b);
- return pyg_flags_from_gtype(a->gtype, PYGLIB_PyLong_AsUnsignedLong(a) | PYGLIB_PyLong_AsUnsignedLong(b));
+ return pyg_flags_from_gtype(a->gtype, (guint)(PyLong_AsUnsignedLongMask ((PyObject*)a) | PyLong_AsUnsignedLongMask ((PyObject*)b)));
}
static PyObject *
pyg_flags_xor(PyGFlags *a, PyGFlags *b)
{
if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
- return PYGLIB_PyLong_Type.tp_as_number->nb_xor((PyObject*)a,
+ return PyLong_Type.tp_as_number->nb_xor((PyObject*)a,
(PyObject*)b);
return pyg_flags_from_gtype(a->gtype,
- PYGLIB_PyLong_AsUnsignedLong(a) ^ PYGLIB_PyLong_AsUnsignedLong(b));
+ (guint)(PyLong_AsUnsignedLongMask ((PyObject*)a) ^ PyLong_AsUnsignedLongMask ((PyObject*)b)));
}
@@ -368,9 +385,9 @@ pyg_flags_get_first_value_name(PyGFlags *self, void *closure)
flags_class = g_type_class_ref(self->gtype);
g_assert(G_IS_FLAGS_CLASS(flags_class));
- flags_value = g_flags_get_first_value(flags_class, PYGLIB_PyLong_AsUnsignedLong(self));
+ flags_value = g_flags_get_first_value(flags_class, (guint)PyLong_AsUnsignedLongMask ((PyObject*)self));
if (flags_value)
- retval = PYGLIB_PyUnicode_FromString(flags_value->value_name);
+ retval = PyUnicode_FromString (flags_value->value_name);
else {
retval = Py_None;
Py_INCREF(Py_None);
@@ -390,9 +407,9 @@ pyg_flags_get_first_value_nick(PyGFlags *self, void *closure)
flags_class = g_type_class_ref(self->gtype);
g_assert(G_IS_FLAGS_CLASS(flags_class));
- flags_value = g_flags_get_first_value(flags_class, PYGLIB_PyLong_AsUnsignedLong(self));
+ flags_value = g_flags_get_first_value(flags_class, (guint)PyLong_AsUnsignedLongMask ((PyObject*)self));
if (flags_value)
- retval = PYGLIB_PyUnicode_FromString(flags_value->value_nick);
+ retval = PyUnicode_FromString (flags_value->value_nick);
else {
retval = Py_None;
Py_INCREF(Py_None);
@@ -407,15 +424,21 @@ pyg_flags_get_value_names(PyGFlags *self, void *closure)
{
GFlagsClass *flags_class;
PyObject *retval;
- int i;
+ guint i;
flags_class = g_type_class_ref(self->gtype);
g_assert(G_IS_FLAGS_CLASS(flags_class));
retval = PyList_New(0);
- for (i = 0; i < flags_class->n_values; i++)
- if ((PYGLIB_PyLong_AsUnsignedLong(self) & flags_class->values[i].value) == flags_class->values[i].value)
- PyList_Append(retval, PYGLIB_PyUnicode_FromString(flags_class->values[i].value_name));
+ for (i = 0; i < flags_class->n_values; i++) {
+ PyObject *value_name;
+
+ if ((PyLong_AsUnsignedLongMask ((PyObject*)self) & flags_class->values[i].value) == flags_class->values[i].value) {
+ value_name = PyUnicode_FromString (flags_class->values[i].value_name);
+ PyList_Append (retval, value_name);
+ Py_DECREF (value_name);
+ }
+ }
g_type_class_unref(flags_class);
@@ -427,15 +450,15 @@ pyg_flags_get_value_nicks(PyGFlags *self, void *closure)
{
GFlagsClass *flags_class;
PyObject *retval;
- int i;
+ guint i;
flags_class = g_type_class_ref(self->gtype);
g_assert(G_IS_FLAGS_CLASS(flags_class));
retval = PyList_New(0);
for (i = 0; i < flags_class->n_values; i++)
- if ((PYGLIB_PyLong_AsUnsignedLong(self) & flags_class->values[i].value) == flags_class->values[i].value) {
- PyObject *py_nick = PYGLIB_PyUnicode_FromString(flags_class->values[i].value_nick);
+ if ((PyLong_AsUnsignedLongMask ((PyObject*)self) & flags_class->values[i].value) == flags_class->values[i].value) {
+ PyObject *py_nick = PyUnicode_FromString (flags_class->values[i].value_nick);
PyList_Append(retval, py_nick);
Py_DECREF (py_nick);
}
@@ -459,9 +482,6 @@ static PyNumberMethods pyg_flags_as_number = {
(binaryfunc)pyg_flags_warn, /* nb_multiply */
(binaryfunc)pyg_flags_warn, /* nb_divide */
(binaryfunc)pyg_flags_warn, /* nb_remainder */
-#if PY_VERSION_HEX < 0x03000000
- (binaryfunc)pyg_flags_warn, /* nb_divmod */
-#endif
(ternaryfunc)pyg_flags_warn, /* nb_power */
0, /* nb_negative */
0, /* nb_positive */
@@ -475,23 +495,34 @@ static PyNumberMethods pyg_flags_as_number = {
(binaryfunc)pyg_flags_or, /* nb_or */
};
-void
-pygobject_flags_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_flags_register_types(PyObject *d)
{
+ PyObject *pygtype;
+
pygflags_class_key = g_quark_from_static_string("PyGFlags::class");
- PyGFlags_Type.tp_base = &PYGLIB_PyLong_Type;
-#if PY_VERSION_HEX < 0x03000000
+ PyGFlags_Type.tp_base = &PyLong_Type;
PyGFlags_Type.tp_new = pyg_flags_new;
-#else
- PyGFlags_Type.tp_new = PyLong_Type.tp_new;
- PyGFlags_Type.tp_hash = PyLong_Type.tp_hash;
-#endif
+ PyGFlags_Type.tp_hash = PyLong_Type.tp_hash;
PyGFlags_Type.tp_repr = (reprfunc)pyg_flags_repr;
PyGFlags_Type.tp_as_number = &pyg_flags_as_number;
PyGFlags_Type.tp_str = (reprfunc)pyg_flags_repr;
PyGFlags_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
PyGFlags_Type.tp_richcompare = (richcmpfunc)pyg_flags_richcompare;
PyGFlags_Type.tp_getset = pyg_flags_getsets;
- PYGOBJECT_REGISTER_GTYPE(d, PyGFlags_Type, "GFlags", G_TYPE_FLAGS);
+ PyGFlags_Type.tp_alloc = PyType_GenericAlloc;
+ if (PyType_Ready(&PyGFlags_Type))
+ return -1;
+
+ pygtype = pyg_type_wrapper_new (G_TYPE_FLAGS);
+ PyDict_SetItemString (PyGFlags_Type.tp_dict, "__gtype__", pygtype);
+ Py_DECREF (pygtype);
+
+ PyDict_SetItemString(d, "GFlags", (PyObject *)&PyGFlags_Type);
+
+ return 0;
}
diff --git a/gi/pygflags.h b/gi/pygflags.h
new file mode 100644
index 0000000..7cff7f2
--- /dev/null
+++ b/gi/pygflags.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * 2004-2008 Johan Dahlin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGOBJECT_FLAGS_H__
+#define __PYGOBJECT_FLAGS_H__
+
+extern GQuark pygflags_class_key;
+
+typedef struct {
+ PyLongObject parent;
+ int zero_pad; /* must always be 0 */
+ GType gtype;
+} PyGFlags;
+
+extern PyTypeObject PyGFlags_Type;
+
+#define PyGFlags_Check(x) (PyObject_IsInstance((PyObject *)x, (PyObject *)&PyGFlags_Type) && g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_FLAGS))
+
+extern PyObject * pyg_flags_add (PyObject * module,
+ const char * type_name,
+ const char * strip_prefix,
+ GType gtype);
+extern PyObject * pyg_flags_from_gtype (GType gtype,
+ guint value);
+
+gint pyg_flags_get_value (GType flag_type, PyObject *obj, guint *val);
+
+int pygi_flags_register_types(PyObject *d);
+
+#endif /* __PYGOBJECT_FLAGS_H__ */
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 7d8a837..c5c5bea 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -16,29 +16,35 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include <Python.h>
#include <string.h>
#include <time.h>
-#include <datetime.h>
-#include <pygobject.h>
-#include <pyglib-python-compat.h>
-#include <pyglib.h>
+#include "pygobject-internal.h"
-#include "pygi-marshal-from-py.h"
-#include "pygi-marshal-to-py.h"
+#include <pygenum.h>
+#include <pygflags.h>
+#include "pygi-argument.h"
+#include "pygi-info.h"
+#include "pygi-value.h"
+#include "pygi-basictype.h"
+#include "pygi-object.h"
+#include "pygi-struct-marshal.h"
+#include "pygi-error.h"
+#include "pygi-foreign.h"
+#include "pygi-type.h"
+#include "pygi-util.h"
-static gboolean
-gi_argument_to_gssize (GIArgument *arg_in,
- GITypeTag type_tag,
- gssize *gssize_out)
+
+gboolean
+pygi_argument_to_gssize (GIArgument *arg_in,
+ GITypeTag type_tag,
+ gssize *gssize_out)
{
switch (type_tag) {
case GI_TYPE_TAG_INT8:
@@ -60,10 +66,22 @@ gi_argument_to_gssize (GIArgument *arg_in,
*gssize_out = arg_in->v_uint32;
return TRUE;
case GI_TYPE_TAG_INT64:
- *gssize_out = arg_in->v_int64;
+ if (arg_in->v_int64 > G_MAXSSIZE || arg_in->v_int64 < G_MINSSIZE) {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to gssize",
+ g_type_tag_to_string(type_tag));
+ return FALSE;
+ }
+ *gssize_out = (gssize)arg_in->v_int64;
return TRUE;
case GI_TYPE_TAG_UINT64:
- *gssize_out = arg_in->v_uint64;
+ if (arg_in->v_uint64 > G_MAXSSIZE) {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to gssize",
+ g_type_tag_to_string(type_tag));
+ return FALSE;
+ }
+ *gssize_out = (gssize)arg_in->v_uint64;
return TRUE;
default:
PyErr_Format (PyExc_TypeError,
@@ -73,32 +91,59 @@ gi_argument_to_gssize (GIArgument *arg_in,
}
}
+static GITypeTag
+_pygi_get_storage_type (GITypeInfo *type_info)
+{
+ GITypeTag type_tag = g_type_info_get_tag (type_info);
+
+ if (type_tag == GI_TYPE_TAG_INTERFACE) {
+ GIBaseInfo *interface = g_type_info_get_interface (type_info);
+ switch (g_base_info_get_type (interface)) {
+ case GI_INFO_TYPE_ENUM:
+ case GI_INFO_TYPE_FLAGS:
+ type_tag = g_enum_info_get_storage_type ((GIEnumInfo *)interface);
+ break;
+ default:
+ /* FIXME: we might have something to do for other types */
+ break;
+ }
+ g_base_info_unref (interface);
+ }
+ return type_tag;
+}
+
void
_pygi_hash_pointer_to_arg (GIArgument *arg,
- GITypeTag type_tag)
+ GITypeInfo *type_info)
{
+ GITypeTag type_tag = _pygi_get_storage_type (type_info);
+
switch (type_tag) {
case GI_TYPE_TAG_INT8:
- arg->v_int8 = GPOINTER_TO_INT (arg->v_pointer);
+ arg->v_int8 = (gint8)GPOINTER_TO_INT (arg->v_pointer);
break;
case GI_TYPE_TAG_INT16:
- arg->v_int16 = GPOINTER_TO_INT (arg->v_pointer);
+ arg->v_int16 = (gint16)GPOINTER_TO_INT (arg->v_pointer);
break;
case GI_TYPE_TAG_INT32:
- arg->v_int32 = GPOINTER_TO_INT (arg->v_pointer);
+ arg->v_int32 = (gint32)GPOINTER_TO_INT (arg->v_pointer);
break;
case GI_TYPE_TAG_UINT8:
- arg->v_uint8 = GPOINTER_TO_UINT (arg->v_pointer);
+ arg->v_uint8 = (guint8)GPOINTER_TO_UINT (arg->v_pointer);
break;
case GI_TYPE_TAG_UINT16:
- arg->v_uint16 = GPOINTER_TO_UINT (arg->v_pointer);
+ arg->v_uint16 = (guint16)GPOINTER_TO_UINT (arg->v_pointer);
break;
case GI_TYPE_TAG_UINT32:
- arg->v_uint32 = GPOINTER_TO_UINT (arg->v_pointer);
+ arg->v_uint32 = (guint32)GPOINTER_TO_UINT (arg->v_pointer);
+ break;
+ case GI_TYPE_TAG_GTYPE:
+ arg->v_size = GPOINTER_TO_SIZE (arg->v_pointer);
break;
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_INTERFACE:
+ case GI_TYPE_TAG_ARRAY:
break;
default:
g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag));
@@ -107,8 +152,10 @@ _pygi_hash_pointer_to_arg (GIArgument *arg,
gpointer
_pygi_arg_to_hash_pointer (const GIArgument *arg,
- GITypeTag type_tag)
+ GITypeInfo *type_info)
{
+ GITypeTag type_tag = _pygi_get_storage_type (type_info);
+
switch (type_tag) {
case GI_TYPE_TAG_INT8:
return GINT_TO_POINTER (arg->v_int8);
@@ -122,9 +169,12 @@ _pygi_arg_to_hash_pointer (const GIArgument *arg,
return GINT_TO_POINTER (arg->v_int32);
case GI_TYPE_TAG_UINT32:
return GINT_TO_POINTER (arg->v_uint32);
+ case GI_TYPE_TAG_GTYPE:
+ return GSIZE_TO_POINTER (arg->v_size);
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_INTERFACE:
+ case GI_TYPE_TAG_ARRAY:
return arg->v_pointer;
default:
g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag));
@@ -132,642 +182,49 @@ _pygi_arg_to_hash_pointer (const GIArgument *arg,
}
}
-static void
-_pygi_g_type_tag_py_bounds (GITypeTag type_tag,
- PyObject **lower,
- PyObject **upper)
-{
- switch (type_tag) {
- case GI_TYPE_TAG_INT8:
- *lower = PYGLIB_PyLong_FromLong (-128);
- *upper = PYGLIB_PyLong_FromLong (127);
- break;
- case GI_TYPE_TAG_UINT8:
- *upper = PYGLIB_PyLong_FromLong (255);
- *lower = PYGLIB_PyLong_FromLong (0);
- break;
- case GI_TYPE_TAG_INT16:
- *lower = PYGLIB_PyLong_FromLong (-32768);
- *upper = PYGLIB_PyLong_FromLong (32767);
- break;
- case GI_TYPE_TAG_UINT16:
- *upper = PYGLIB_PyLong_FromLong (65535);
- *lower = PYGLIB_PyLong_FromLong (0);
- break;
- case GI_TYPE_TAG_INT32:
- *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 = PYGLIB_PyLong_FromLong (0);
- break;
- case GI_TYPE_TAG_INT64:
- /* Note: On 32-bit archs, these numbers don't fit in a long. */
- *lower = PyLong_FromLongLong (G_MININT64);
- *upper = PyLong_FromLongLong (G_MAXINT64);
- break;
- case GI_TYPE_TAG_UINT64:
- *upper = PyLong_FromUnsignedLongLong (G_MAXUINT64);
- *lower = PYGLIB_PyLong_FromLong (0);
- break;
- case GI_TYPE_TAG_FLOAT:
- *upper = PyFloat_FromDouble (G_MAXFLOAT);
- *lower = PyFloat_FromDouble (-G_MAXFLOAT);
- break;
- case GI_TYPE_TAG_DOUBLE:
- *upper = PyFloat_FromDouble (G_MAXDOUBLE);
- *lower = PyFloat_FromDouble (-G_MAXDOUBLE);
- break;
- default:
- PyErr_SetString (PyExc_TypeError, "Non-numeric type tag");
- *lower = *upper = NULL;
- return;
- }
-}
-
-gint
-_pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
- gboolean is_instance,
- PyObject *object)
-{
- gint retval;
-
- GType g_type;
- PyObject *py_type;
- gchar *type_name_expected = NULL;
- GIInfoType interface_type;
-
- interface_type = g_base_info_get_type (info);
- if ( (interface_type == GI_INFO_TYPE_STRUCT) &&
- (g_struct_info_is_foreign ( (GIStructInfo*) info))) {
- /* TODO: Could we check is the correct foreign type? */
- return 1;
- }
-
- g_type = g_registered_type_info_get_g_type (info);
- if (g_type != G_TYPE_NONE) {
- py_type = _pygi_type_get_from_g_type (g_type);
- } else {
- py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info);
- }
-
- if (py_type == NULL) {
- return 0;
- }
-
- g_assert (PyType_Check (py_type));
-
- if (is_instance) {
- retval = PyObject_IsInstance (object, py_type);
- if (!retval) {
- type_name_expected = _pygi_g_base_info_get_fullname (
- (GIBaseInfo *) info);
- }
- } else {
- if (!PyObject_Type (py_type)) {
- type_name_expected = "type";
- retval = 0;
- } else if (!PyType_IsSubtype ( (PyTypeObject *) object,
- (PyTypeObject *) py_type)) {
- type_name_expected = _pygi_g_base_info_get_fullname (
- (GIBaseInfo *) info);
- retval = 0;
- } else {
- retval = 1;
- }
- }
-
- Py_DECREF (py_type);
-
- if (!retval) {
- PyTypeObject *object_type;
- if (type_name_expected == NULL) {
- return -1;
- }
-
- object_type = (PyTypeObject *) PyObject_Type (object);
- if (object_type == NULL) {
- return -1;
- }
-
- PyErr_Format (PyExc_TypeError, "Must be %s, not %s",
- type_name_expected, object_type->tp_name);
-
- g_free (type_name_expected);
- }
-
- return retval;
-}
-
-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);
- g_base_info_unref (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_CLOSURE)) {
- if (!(PyCallable_Check (object) ||
- pyg_type_from_object_strict (object, FALSE) == G_TYPE_CLOSURE)) {
- PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- } else if (g_type_is_a (type, G_TYPE_VALUE)) {
- /* we can't check g_values because we don't have
- * enough context so just pass them through */
- break;
- }
-
- /* Fallback. */
- }
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_INTERFACE:
- case GI_INFO_TYPE_OBJECT:
- retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object);
- break;
- case GI_INFO_TYPE_UNION:
-
-
- retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object);
-
- /* If not the same type then check to see if the object's type
- * is the same as one of the union's members
- */
- if (retval == 0) {
- gint i;
- gint n_fields;
-
- n_fields = g_union_info_get_n_fields ( (GIUnionInfo *) info);
-
- for (i = 0; i < n_fields; i++) {
- gint member_retval;
- GIFieldInfo *field_info;
- GITypeInfo *field_type_info;
-
- field_info =
- g_union_info_get_field ( (GIUnionInfo *) info, i);
- field_type_info = g_field_info_get_type (field_info);
-
- member_retval = _pygi_g_type_info_check_object(
- field_type_info,
- object,
- TRUE);
-
- g_base_info_unref ( ( GIBaseInfo *) field_type_info);
- g_base_info_unref ( ( GIBaseInfo *) field_info);
-
- if (member_retval == 1) {
- retval = member_retval;
- break;
- }
- }
- }
-
- break;
- default:
- g_assert_not_reached();
- }
-
- return retval;
-}
-
-gint
-_pygi_g_type_info_check_object (GITypeInfo *type_info,
- PyObject *object,
- gboolean allow_none)
+/**
+ * _pygi_argument_array_length_marshal:
+ * @length_arg_index: Index of length argument in the callables args list.
+ * @user_data1: (type Array(GValue)): Array of GValue arguments to retrieve length
+ * @user_data2: (type GICallableInfo): Callable info to get the argument from.
+ *
+ * Generic marshalling policy for array length arguments in callables.
+ *
+ * Returns: The length of the array or -1 on failure.
+ */
+gssize
+_pygi_argument_array_length_marshal (gsize length_arg_index,
+ void *user_data1,
+ void *user_data2)
{
- GITypeTag type_tag;
- gint retval = 1;
-
- if (allow_none && object == Py_None) {
- return retval;
- }
-
- type_tag = g_type_info_get_tag (type_info);
-
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- /* No check; VOID means undefined type */
- break;
- case GI_TYPE_TAG_BOOLEAN:
- /* No check; every Python object has a truth value. */
- break;
- case GI_TYPE_TAG_UINT8:
- case GI_TYPE_TAG_INT8:
- /* (U)INT8 types can be characters */
- if (PYGLIB_PyBytes_Check(object)) {
- if (PYGLIB_PyBytes_Size(object) != 1) {
- PyErr_Format (PyExc_TypeError, "Must be a single character");
- retval = 0;
- break;
- }
-
- break;
- }
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_INT64:
- case GI_TYPE_TAG_UINT64:
- case GI_TYPE_TAG_FLOAT:
- case GI_TYPE_TAG_DOUBLE:
- {
- PyObject *number, *lower, *upper;
-
- if (!PyNumber_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be number, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- if (type_tag == GI_TYPE_TAG_FLOAT || type_tag == GI_TYPE_TAG_DOUBLE) {
- number = PyNumber_Float (object);
- } else {
- number = PYGLIB_PyNumber_Long (object);
- }
-
- _pygi_g_type_tag_py_bounds (type_tag, &lower, &upper);
-
- if (lower == NULL || upper == NULL || number == NULL) {
- retval = -1;
- goto check_number_release;
- }
-
- /* Check bounds */
- if (PyObject_RichCompareBool (lower, number, Py_GT)
- || PyObject_RichCompareBool (upper, number, Py_LT)) {
- PyObject *lower_str;
- PyObject *upper_str;
-
- if (PyErr_Occurred()) {
- retval = -1;
- goto check_number_release;
- }
-
- lower_str = PyObject_Str (lower);
- upper_str = PyObject_Str (upper);
- if (lower_str == NULL || upper_str == NULL) {
- retval = -1;
- 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;
- PyObject *upper_pybytes_obj;
-
- lower_pybytes_obj = PyUnicode_AsUTF8String (lower_str);
- if (!lower_pybytes_obj) {
- goto utf8_fail;
- }
-
- 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:
- Py_XDECREF (lower_str);
- Py_XDECREF (upper_str);
- }
-
-check_number_release:
- Py_XDECREF (number);
- Py_XDECREF (lower);
- Py_XDECREF (upper);
- break;
- }
- case GI_TYPE_TAG_GTYPE:
- {
- if (pyg_type_from_object (object) == 0) {
- PyErr_Format (PyExc_TypeError, "Must be gobject.GType, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- }
- case GI_TYPE_TAG_UNICHAR:
- {
- Py_ssize_t size;
- if (PyUnicode_Check (object)) {
- size = PyUnicode_GET_SIZE (object);
-#if PY_VERSION_HEX < 0x03000000
- } else if (PyString_Check (object)) {
- PyObject *pyuni = PyUnicode_FromEncodedObject (object, "UTF-8", "strict");
- size = PyUnicode_GET_SIZE (pyuni);
- Py_DECREF(pyuni);
-#endif
- } else {
- PyErr_Format (PyExc_TypeError, "Must be string, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- if (size != 1) {
- PyErr_Format (PyExc_TypeError, "Must be a one character string, not %" G_GINT64_FORMAT " characters",
- (gint64)size);
- retval = 0;
- break;
- }
-
- break;
- }
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- if (!PYGLIB_PyBaseString_Check (object) ) {
- PyErr_Format (PyExc_TypeError, "Must be string, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- case GI_TYPE_TAG_ARRAY:
- {
- gssize fixed_size;
- Py_ssize_t length;
- GITypeInfo *item_type_info;
- Py_ssize_t i;
-
- if (!PySequence_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- length = PySequence_Length (object);
- if (length < 0) {
- retval = -1;
- break;
- }
-
- fixed_size = g_type_info_get_array_fixed_size (type_info);
- if (fixed_size >= 0 && length != fixed_size) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- fixed_size, length);
- retval = 0;
- break;
- }
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (item_type_info != NULL);
-
- /* FIXME: This is insain. We really should only check the first
- * object and perhaps have a debugging mode. Large arrays
- * will cause apps to slow to a crawl.
- */
- for (i = 0; i < length; i++) {
- PyObject *item;
-
- item = PySequence_GetItem (object, i);
- if (item == NULL) {
- retval = -1;
- break;
- }
-
- retval = _pygi_g_type_info_check_object (item_type_info, item, TRUE);
-
- Py_DECREF (item);
-
- if (retval < 0) {
- break;
- }
- if (!retval) {
- _PyGI_ERROR_PREFIX ("Item %zd: ", i);
- break;
- }
- }
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
-
- break;
- }
- case GI_TYPE_TAG_INTERFACE:
- {
- GIBaseInfo *info;
-
- info = g_type_info_get_interface (type_info);
- g_assert (info != NULL);
-
- retval = _pygi_g_type_interface_check_object(info, object);
-
- g_base_info_unref (info);
- break;
- }
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- {
- Py_ssize_t length;
- GITypeInfo *item_type_info;
- Py_ssize_t i;
-
- if (!PySequence_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- length = PySequence_Length (object);
- if (length < 0) {
- retval = -1;
- break;
- }
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (item_type_info != NULL);
-
- for (i = 0; i < length; i++) {
- PyObject *item;
-
- item = PySequence_GetItem (object, i);
- if (item == NULL) {
- retval = -1;
- break;
- }
-
- retval = _pygi_g_type_info_check_object (item_type_info, item, TRUE);
-
- Py_DECREF (item);
-
- if (retval < 0) {
- break;
- }
- if (!retval) {
- _PyGI_ERROR_PREFIX ("Item %zd: ", i);
- break;
- }
- }
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
- break;
- }
- case GI_TYPE_TAG_GHASH:
- {
- Py_ssize_t length;
- PyObject *keys;
- PyObject *values;
- GITypeInfo *key_type_info;
- GITypeInfo *value_type_info;
- Py_ssize_t i;
-
- keys = PyMapping_Keys (object);
- if (keys == NULL) {
- PyErr_Format (PyExc_TypeError, "Must be mapping, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- length = PyMapping_Length (object);
- if (length < 0) {
- Py_DECREF (keys);
- retval = -1;
- break;
- }
-
- values = PyMapping_Values (object);
- if (values == NULL) {
- retval = -1;
- Py_DECREF (keys);
- break;
- }
-
- key_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (key_type_info != NULL);
-
- value_type_info = g_type_info_get_param_type (type_info, 1);
- g_assert (value_type_info != NULL);
-
- for (i = 0; i < length; i++) {
- PyObject *key;
- PyObject *value;
-
- key = PyList_GET_ITEM (keys, i);
- value = PyList_GET_ITEM (values, i);
-
- retval = _pygi_g_type_info_check_object (key_type_info, key, TRUE);
- if (retval < 0) {
- break;
- }
- if (!retval) {
- _PyGI_ERROR_PREFIX ("Key %zd :", i);
- break;
- }
-
- retval = _pygi_g_type_info_check_object (value_type_info, value, TRUE);
- if (retval < 0) {
- break;
- }
- if (!retval) {
- _PyGI_ERROR_PREFIX ("Value %zd :", i);
- break;
- }
- }
-
- g_base_info_unref ( (GIBaseInfo *) key_type_info);
- g_base_info_unref ( (GIBaseInfo *) value_type_info);
- Py_DECREF (values);
- Py_DECREF (keys);
- break;
- }
- case GI_TYPE_TAG_ERROR:
- PyErr_SetString (PyExc_NotImplementedError, "Error marshalling is not supported yet");
- /* TODO */
- break;
+ GIArgInfo length_arg_info;
+ GITypeInfo length_type_info;
+ GIArgument length_arg;
+ gssize array_len = -1;
+ GValue *values = (GValue *)user_data1;
+ GICallableInfo *callable_info = (GICallableInfo *)user_data2;
+
+ g_callable_info_load_arg (callable_info, (gint)length_arg_index, &length_arg_info);
+ g_arg_info_load_type (&length_arg_info, &length_type_info);
+
+ length_arg = _pygi_argument_from_g_value (&(values[length_arg_index]),
+ &length_type_info);
+ if (!pygi_argument_to_gssize (&length_arg,
+ g_type_info_get_tag (&length_type_info),
+ &array_len)) {
+ return -1;
}
- return retval;
+ return array_len;
}
/**
* _pygi_argument_to_array
* @arg: The argument to convert
- * @args: Arguments to method invocation, possibly contaning the array length.
- * Set to %NULL if this is not for a method call or @args_values is
- * specified.
- * @args_values: GValue Arguments to method invocation, possibly contaning the
- * array length. Set to %NULL if this is not for a method call or
- * @args is specified.
- * @callable_info: Info on the callable, if this a method call; otherwise %NULL
+ * @array_length_policy: Closure for marshalling the array length argument when needed.
+ * @user_data1: Generic user data passed to the array_length_policy.
+ * @user_data2: Generic user data passed to the array_length_policy.
* @type_info: The type info for @arg
* @out_free_array: A return location for a gboolean that indicates whether
* or not the wrapped GArray should be freed
@@ -784,9 +241,9 @@ check_number_release:
*/
GArray *
_pygi_argument_to_array (GIArgument *arg,
- GIArgument *args[],
- const GValue *args_values,
- GICallableInfo *callable_info,
+ PyGIArgArrayLengthPolicy array_length_policy,
+ void *user_data1,
+ void *user_data2,
GITypeInfo *type_info,
gboolean *out_free_array)
{
@@ -812,52 +269,46 @@ _pygi_argument_to_array (GIArgument *arg,
g_base_info_unref ( (GIBaseInfo *) item_type_info);
if (is_zero_terminated) {
- length = g_strv_length (arg->v_pointer);
+ if (item_size == sizeof(gpointer))
+ length = g_strv_length ((gchar **)arg->v_pointer);
+ else if (item_size == 1)
+ length = strlen ((gchar*)arg->v_pointer);
+ else if (item_size == sizeof(int))
+ for (length = 0; *(((int*)arg->v_pointer) + length); length++);
+ else if (item_size == sizeof(short))
+ for (length = 0; *(((short*)arg->v_pointer) + length); length++);
+ else
+ g_assert_not_reached ();
} else {
length = g_type_info_get_array_fixed_size (type_info);
if (length < 0) {
gint length_arg_pos;
- GIArgInfo length_arg_info;
- GITypeInfo length_type_info;
- if (G_UNLIKELY (args == NULL && args_values == NULL)) {
+ if (G_UNLIKELY (array_length_policy == NULL)) {
g_critical ("Unable to determine array length for %p",
arg->v_pointer);
- g_array = g_array_new (is_zero_terminated, FALSE, item_size);
+ g_array = g_array_new (is_zero_terminated, FALSE, (guint)item_size);
*out_free_array = TRUE;
return g_array;
}
length_arg_pos = g_type_info_get_array_length (type_info);
g_assert (length_arg_pos >= 0);
- g_assert (callable_info);
- g_callable_info_load_arg (callable_info, length_arg_pos, &length_arg_info);
- g_arg_info_load_type (&length_arg_info, &length_type_info);
-
- if (args != NULL) {
- if (!gi_argument_to_gssize (args[length_arg_pos],
- g_type_info_get_tag (&length_type_info),
- &length))
- return NULL;
- } else {
- /* get it from args_values */
- GIArgument length_arg = _pygi_argument_from_g_value (&(args_values[length_arg_pos]),
- &length_type_info);
- if (!gi_argument_to_gssize (&length_arg,
- g_type_info_get_tag (&length_type_info),
- &length))
- return NULL;
+
+ length = array_length_policy (length_arg_pos, user_data1, user_data2);
+ if (length < 0) {
+ return NULL;
}
}
}
g_assert (length >= 0);
- g_array = g_array_new (is_zero_terminated, FALSE, item_size);
+ g_array = g_array_new (is_zero_terminated, FALSE, (guint)item_size);
g_free (g_array->data);
g_array->data = arg->v_pointer;
- g_array->len = length;
+ g_array->len = (guint)length;
*out_free_array = TRUE;
break;
case GI_ARRAY_TYPE_ARRAY:
@@ -894,25 +345,21 @@ _pygi_argument_from_object (PyObject *object,
{
GIArgument arg;
GITypeTag type_tag;
+ gpointer cleanup_data = NULL;
memset(&arg, 0, sizeof(GIArgument));
type_tag = g_type_info_get_tag (type_info);
- if (_pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer) ||
- PyErr_Occurred()) {
- return arg;
- }
-
switch (type_tag) {
case GI_TYPE_TAG_ARRAY:
{
- Py_ssize_t length;
+ Py_ssize_t py_length;
+ guint length, i;
gboolean is_zero_terminated;
GITypeInfo *item_type_info;
gsize item_size;
GArray *array;
GITransfer item_transfer;
- Py_ssize_t i;
if (object == Py_None) {
arg.v_pointer = NULL;
@@ -921,18 +368,17 @@ _pygi_argument_from_object (PyObject *object,
/* Note, strings are sequences, but we cannot accept them here */
if (!PySequence_Check (object) ||
-#if PY_VERSION_HEX < 0x03000000
- PyString_Check (object) ||
-#endif
PyUnicode_Check (object)) {
PyErr_SetString (PyExc_TypeError, "expected sequence");
break;
}
- length = PySequence_Length (object);
- if (length < 0) {
+ py_length = PySequence_Length (object);
+ if (py_length < 0)
+ break;
+
+ if (!pygi_guint_from_pyssize (py_length, &length))
break;
- }
is_zero_terminated = g_type_info_is_zero_terminated (type_info);
item_type_info = g_type_info_get_param_type (type_info, 0);
@@ -943,7 +389,7 @@ _pygi_argument_from_object (PyObject *object,
else
item_size = sizeof (GIArgument);
- array = g_array_sized_new (is_zero_terminated, FALSE, item_size, length);
+ array = g_array_sized_new (is_zero_terminated, FALSE, (guint)item_size, length);
if (array == NULL) {
g_base_info_unref ( (GIBaseInfo *) item_type_info);
PyErr_NoMemory();
@@ -951,9 +397,9 @@ _pygi_argument_from_object (PyObject *object,
}
if (g_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8 &&
- PYGLIB_PyBytes_Check(object)) {
+ PyBytes_Check (object)) {
- memcpy(array->data, PYGLIB_PyBytes_AsString(object), length);
+ memcpy(array->data, PyBytes_AsString (object), length);
array->len = length;
goto array_success;
}
@@ -987,7 +433,7 @@ array_item_error:
GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
array = NULL;
- _PyGI_ERROR_PREFIX ("Item %zd: ", i);
+ _PyGI_ERROR_PREFIX ("Item %u: ", i);
break;
}
@@ -1016,9 +462,11 @@ array_success:
{
GType g_type;
PyObject *py_type;
+ gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) &&
+ (g_struct_info_is_foreign ((GIStructInfo *) info));
g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
- py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info);
+ py_type = pygi_type_import_by_gi_info ( (GIBaseInfo *) info);
/* Note for G_TYPE_VALUE g_type:
* This will currently leak the GValue that is allocated and
@@ -1027,40 +475,44 @@ array_success:
* Further re-factoring is needed to fix this leak.
* See: https://bugzilla.gnome.org/show_bug.cgi?id=693405
*/
- _pygi_marshal_from_py_interface_struct (object,
- &arg,
- NULL, /*arg_name*/
- info, /*interface_info*/
- type_info,
- g_type,
- py_type,
- transfer,
- FALSE, /*copy_reference*/
- g_struct_info_is_foreign (info));
+ pygi_arg_struct_from_py_marshal (object,
+ &arg,
+ NULL, /*arg_name*/
+ info, /*interface_info*/
+ g_type,
+ py_type,
+ transfer,
+ FALSE, /*copy_reference*/
+ is_foreign,
+ g_type_info_is_pointer (type_info));
Py_DECREF (py_type);
break;
}
case GI_INFO_TYPE_ENUM:
- case GI_INFO_TYPE_FLAGS:
{
- PyObject *int_;
+ GType g_type;
- int_ = PYGLIB_PyNumber_Long (object);
- if (int_ == NULL) {
+ g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
+ if (pyg_enum_get_value(g_type, object, &arg.v_int) < 0)
break;
- }
- arg.v_int = PYGLIB_PyLong_AsLong (int_);
+ break;
+ }
+ case GI_INFO_TYPE_FLAGS:
+ {
+ GType g_type;
- Py_DECREF (int_);
+ g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
+ if (pyg_flags_get_value(g_type, object, &arg.v_uint) < 0)
+ break;
break;
}
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_OBJECT:
/* An error within this call will result in a NULL arg */
- _pygi_marshal_from_py_gobject_out_arg (object, &arg, transfer);
+ pygi_arg_gobject_out_arg_from_py (object, &arg, transfer);
break;
default:
@@ -1218,7 +670,7 @@ list_item_error:
}
g_hash_table_insert (hash_table, key.v_pointer,
- _pygi_arg_to_hash_pointer (&value, g_type_info_get_tag (value_type_info)));
+ _pygi_arg_to_hash_pointer (&value, value_type_info));
continue;
hash_table_item_error:
@@ -1245,7 +697,9 @@ hash_table_release:
/* TODO */
break;
default:
- g_assert_not_reached ();
+ /* Ignores cleanup data for now. */
+ pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer, &cleanup_data);
+ break;
}
return arg;
@@ -1272,9 +726,6 @@ _pygi_argument_to_object (GIArgument *arg,
PyObject *object = NULL;
type_tag = g_type_info_get_tag (type_info);
- object = _pygi_marshal_to_py_basic_type (arg, type_tag, transfer);
- if (object)
- return object;
switch (type_tag) {
case GI_TYPE_TAG_VOID:
@@ -1314,7 +765,7 @@ _pygi_argument_to_object (GIArgument *arg,
if (item_type_tag == GI_TYPE_TAG_UINT8) {
/* Return as a byte array */
- object = PYGLIB_PyBytes_FromStringAndSize (array->data, array->len);
+ object = PyBytes_FromStringAndSize (array->data, array->len);
} else {
object = PyList_New (array->len);
if (object == NULL) {
@@ -1362,21 +813,23 @@ _pygi_argument_to_object (GIArgument *arg,
{
PyObject *py_type;
GType g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
+ gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) &&
+ (g_struct_info_is_foreign ((GIStructInfo *) info));
/* Special case variant and none to force loading from py module. */
if (g_type == G_TYPE_VARIANT || g_type == G_TYPE_NONE) {
- py_type = _pygi_type_import_by_gi_info (info);
+ py_type = pygi_type_import_by_gi_info (info);
} else {
- py_type = _pygi_type_get_from_g_type (g_type);
+ py_type = pygi_type_get_from_g_type (g_type);
}
- object = _pygi_marshal_to_py_interface_struct (arg,
- info, /*interface_info*/
- g_type,
- py_type,
- transfer,
- FALSE, /*is_allocated*/
- g_struct_info_is_foreign (info));
+ object = pygi_arg_struct_to_py_marshal (arg,
+ info, /*interface_info*/
+ g_type,
+ py_type,
+ transfer,
+ FALSE, /*is_allocated*/
+ is_foreign);
Py_XDECREF (py_type);
break;
@@ -1390,14 +843,14 @@ _pygi_argument_to_object (GIArgument *arg,
if (type == G_TYPE_NONE) {
/* An enum with a GType of None is an enum without GType */
- PyObject *py_type = _pygi_type_import_by_gi_info (info);
+ PyObject *py_type = pygi_type_import_by_gi_info (info);
PyObject *py_args = NULL;
if (!py_type)
return NULL;
py_args = PyTuple_New (1);
- if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (arg->v_int)) != 0) {
+ if (PyTuple_SetItem (py_args, 0, pygi_gint_to_py (arg->v_int)) != 0) {
Py_DECREF (py_args);
Py_DECREF (py_type);
return NULL;
@@ -1418,26 +871,7 @@ _pygi_argument_to_object (GIArgument *arg,
}
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_OBJECT:
- /* HACK:
- * The following hack is to work around GTK+ sending signals which
- * contain floating widgets in them. This assumes control of how
- * references are added by the PyGObject wrapper and avoids the sink
- * behavior by explicitly passing GI_TRANSFER_EVERYTHING as the transfer
- * mode and then re-forcing the object as floating afterwards.
- *
- * This can be deleted once the following ticket is fixed:
- * https://bugzilla.gnome.org/show_bug.cgi?id=693400
- */
- if (arg->v_pointer &&
- !G_IS_PARAM_SPEC (arg->v_pointer) &&
- transfer == GI_TRANSFER_NOTHING &&
- g_object_is_floating (arg->v_pointer)) {
- g_object_ref (arg->v_pointer);
- object = _pygi_marshal_to_py_object (arg, GI_TRANSFER_EVERYTHING);
- g_object_force_floating (arg->v_pointer);
- } else {
- object = _pygi_marshal_to_py_object (arg, transfer);
- }
+ object = pygi_arg_gobject_to_py_called_from_c (arg, transfer);
break;
default:
@@ -1529,7 +963,7 @@ _pygi_argument_to_object (GIArgument *arg,
break;
}
- _pygi_hash_pointer_to_arg (&value, g_type_info_get_tag (value_type_info));
+ _pygi_hash_pointer_to_arg (&value, value_type_info);
py_value = _pygi_argument_to_object (&value, value_type_info, item_transfer);
if (py_value == NULL) {
Py_DECREF (py_key);
@@ -1556,12 +990,12 @@ _pygi_argument_to_object (GIArgument *arg,
GError *error = (GError *) arg->v_pointer;
if (error != NULL && transfer == GI_TRANSFER_NOTHING) {
/* If we have not been transferred the ownership we must copy
- * the error, because pyglib_error_check() is going to free it.
+ * the error, because pygi_error_check() is going to free it.
*/
error = g_error_copy (error);
}
- if (pyglib_error_check (&error)) {
+ if (pygi_error_check (&error)) {
PyObject *err_type;
PyObject *err_value;
PyObject *err_trace;
@@ -1578,138 +1012,13 @@ _pygi_argument_to_object (GIArgument *arg,
}
default:
{
- g_assert_not_reached();
+ object = pygi_marshal_to_py_basic_type (arg, type_tag, transfer);
}
}
return object;
}
-
-GIArgument
-_pygi_argument_from_g_value(const GValue *value,
- GITypeInfo *type_info)
-{
- GIArgument arg = { 0, };
-
- GITypeTag type_tag = g_type_info_get_tag (type_info);
-
- /* For the long handling: long can be equivalent to
- int32 or int64, depending on the architecture, but
- gi doesn't tell us (and same for ulong)
- */
- 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:
- if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
- arg.v_int = g_value_get_long (value);
- else
- arg.v_int = g_value_get_int (value);
- break;
- case GI_TYPE_TAG_INT64:
- if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
- arg.v_int64 = g_value_get_long (value);
- else
- arg.v_int64 = g_value_get_int64 (value);
- break;
- case GI_TYPE_TAG_UINT8:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_UINT32:
- if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
- arg.v_uint = g_value_get_ulong (value);
- else
- arg.v_uint = g_value_get_uint (value);
- break;
- case GI_TYPE_TAG_UINT64:
- if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
- arg.v_uint64 = g_value_get_ulong (value);
- else
- arg.v_uint64 = g_value_get_uint64 (value);
- break;
- case GI_TYPE_TAG_UNICHAR:
- arg.v_uint32 = g_value_get_schar (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_long = g_value_get_gtype (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_GLIST:
- case GI_TYPE_TAG_GSLIST:
- arg.v_pointer = g_value_get_pointer (value);
- break;
- case GI_TYPE_TAG_ARRAY:
- case GI_TYPE_TAG_GHASH:
- if (G_VALUE_HOLDS_BOXED (value))
- arg.v_pointer = g_value_get_boxed (value);
- else
- /* e. g. GSettings::change-event */
- arg.v_pointer = g_value_get_pointer (value);
- break;
- case GI_TYPE_TAG_INTERFACE:
- {
- GIBaseInfo *info;
- GIInfoType info_type;
-
- info = g_type_info_get_interface (type_info);
- info_type = g_base_info_get_type (info);
-
- g_base_info_unref (info);
-
- switch (info_type) {
- case GI_INFO_TYPE_FLAGS:
- arg.v_uint = g_value_get_flags (value);
- break;
- case GI_INFO_TYPE_ENUM:
- arg.v_int = g_value_get_enum (value);
- break;
- case GI_INFO_TYPE_INTERFACE:
- case GI_INFO_TYPE_OBJECT:
- if (G_VALUE_HOLDS_PARAM (value))
- arg.v_pointer = g_value_get_param (value);
- else
- 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_VALUE_HOLDS(value, G_TYPE_BOXED)) {
- arg.v_pointer = g_value_get_boxed (value);
- } else if (G_VALUE_HOLDS(value, G_TYPE_VARIANT)) {
- arg.v_pointer = g_value_get_variant (value);
- } else {
- arg.v_pointer = g_value_get_pointer (value);
- }
- break;
- default:
- g_warning("Converting of type '%s' is not implemented", g_info_type_to_string(info_type));
- g_assert_not_reached();
- }
- break;
- }
- case GI_TYPE_TAG_ERROR:
- arg.v_pointer = g_value_get_boxed (value);
- break;
- case GI_TYPE_TAG_VOID:
- arg.v_pointer = g_value_get_pointer (value);
- break;
- }
-
- return arg;
-}
-
void
_pygi_argument_release (GIArgument *arg,
GITypeInfo *type_info,
@@ -1770,9 +1079,9 @@ _pygi_argument_release (GIArgument *arg,
/* Free the items */
for (i = 0; i < array->len; i++) {
- GIArgument *item;
- item = &_g_array_index (array, GIArgument, i);
- _pygi_argument_release (item, item_type_info, item_transfer, direction);
+ GIArgument item;
+ memcpy (&item, array->data + (g_array_get_element_size (array) * i), sizeof (GIArgument));
+ _pygi_argument_release (&item, item_type_info, item_transfer, direction);
}
g_base_info_unref ( (GIBaseInfo *) item_type_info);
@@ -1827,7 +1136,8 @@ _pygi_argument_release (GIArgument *arg,
if (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) {
g_closure_unref (arg->v_pointer);
}
- } else if (g_struct_info_is_foreign ( (GIStructInfo*) info)) {
+ } else if (info_type == GI_INFO_TYPE_STRUCT &&
+ g_struct_info_is_foreign ((GIStructInfo*) info)) {
if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) {
pygi_struct_foreign_release (info, arg->v_pointer);
}
@@ -1972,13 +1282,8 @@ _pygi_argument_release (GIArgument *arg,
g_slice_free (GError *, arg->v_pointer);
break;
}
+ default:
+ break;
}
}
-void
-_pygi_argument_init (void)
-{
- PyDateTime_IMPORT;
- _pygobject_import();
-}
-
diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h
index ed88214..2e889dd 100644
--- a/gi/pygi-argument.h
+++ b/gi/pygi-argument.h
@@ -14,9 +14,7 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_ARGUMENT_H__
@@ -30,28 +28,24 @@ G_BEGIN_DECLS
/* Private */
-gpointer _pygi_arg_to_hash_pointer (const GIArgument *arg,
- GITypeTag type_tag);
-
-void _pygi_hash_pointer_to_arg (GIArgument *arg,
- GITypeTag type_tag);
-
-gint _pygi_g_type_interface_check_object (GIBaseInfo *info,
- PyObject *object);
+typedef gssize (*PyGIArgArrayLengthPolicy) (gsize item_index,
+ void *user_data1,
+ void *user_data2);
-gint _pygi_g_type_info_check_object (GITypeInfo *type_info,
- PyObject *object,
- gboolean allow_none);
+gssize _pygi_argument_array_length_marshal (gsize length_arg_index,
+ void *user_data1,
+ void *user_data2);
-gint _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
- gboolean is_instance,
- PyObject *object);
+gpointer _pygi_arg_to_hash_pointer (const GIArgument *arg,
+ GITypeInfo *type_info);
+void _pygi_hash_pointer_to_arg (GIArgument *arg,
+ GITypeInfo *type_info);
GArray* _pygi_argument_to_array (GIArgument *arg,
- GIArgument *args[],
- const GValue *args_values,
- GICallableInfo *callable_info,
+ PyGIArgArrayLengthPolicy array_length_policy,
+ void *user_data1,
+ void *user_data2,
GITypeInfo *type_info,
gboolean *out_free_array);
@@ -63,15 +57,14 @@ PyObject* _pygi_argument_to_object (GIArgument *arg,
GITypeInfo *type_info,
GITransfer transfer);
-GIArgument _pygi_argument_from_g_value(const GValue *value,
- GITypeInfo *type_info);
-
void _pygi_argument_release (GIArgument *arg,
GITypeInfo *type_info,
GITransfer transfer,
GIDirection direction);
-void _pygi_argument_init (void);
+gboolean pygi_argument_to_gssize (GIArgument *arg_in,
+ GITypeTag type_tag,
+ gssize *gssize_out);
G_END_DECLS
diff --git a/gi/pygi-array.c b/gi/pygi-array.c
new file mode 100644
index 0000000..d5b817f
--- /dev/null
+++ b/gi/pygi-array.c
@@ -0,0 +1,978 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include <glib.h>
+
+#include "pygi-array.h"
+#include "pygi-info.h"
+#include "pygi-marshal-cleanup.h"
+#include "pygi-basictype.h"
+#include "pygi-util.h"
+
+/* Needed for _pygi_marshal_cleanup_from_py_interface_struct_gvalue hack */
+#include "pygi-struct-marshal.h"
+
+/*
+ * GArray to Python
+ */
+
+static gboolean
+gi_argument_from_py_ssize_t (GIArgument *arg_out,
+ Py_ssize_t size_in,
+ GITypeTag type_tag)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_VOID:
+ case GI_TYPE_TAG_BOOLEAN:
+ goto unhandled_type;
+
+ case GI_TYPE_TAG_INT8:
+ if (size_in >= G_MININT8 && size_in <= G_MAXINT8) {
+ arg_out->v_int8 = (gint8)size_in;
+ return TRUE;
+ } else {
+ goto overflow;
+ }
+
+ case GI_TYPE_TAG_UINT8:
+ if (size_in >= 0 && size_in <= G_MAXUINT8) {
+ arg_out->v_uint8 = (guint8)size_in;
+ return TRUE;
+ } else {
+ goto overflow;
+ }
+
+ case GI_TYPE_TAG_INT16:
+ if (size_in >= G_MININT16 && size_in <= G_MAXINT16) {
+ arg_out->v_int16 = (gint16)size_in;
+ return TRUE;
+ } else {
+ goto overflow;
+ }
+
+ case GI_TYPE_TAG_UINT16:
+ if (size_in >= 0 && size_in <= G_MAXUINT16) {
+ arg_out->v_uint16 = (guint16)size_in;
+ return TRUE;
+ } else {
+ goto overflow;
+ }
+
+ /* Ranges assume two's complement */
+ case GI_TYPE_TAG_INT32:
+ if (size_in >= G_MININT32 && size_in <= G_MAXINT32) {
+ arg_out->v_int32 = (gint32)size_in;
+ return TRUE;
+ } else {
+ goto overflow;
+ }
+
+ case GI_TYPE_TAG_UINT32:
+ if (size_in >= 0 && (gsize)size_in <= G_MAXUINT32) {
+ arg_out->v_uint32 = (guint32)size_in;
+ return TRUE;
+ } else {
+ goto overflow;
+ }
+
+ case GI_TYPE_TAG_INT64:
+ arg_out->v_int64 = size_in;
+ return TRUE;
+
+ case GI_TYPE_TAG_UINT64:
+ if (size_in >= 0) {
+ arg_out->v_uint64 = size_in;
+ return TRUE;
+ } else {
+ goto overflow;
+ }
+
+ case GI_TYPE_TAG_FLOAT:
+ case GI_TYPE_TAG_DOUBLE:
+ case GI_TYPE_TAG_GTYPE:
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ case GI_TYPE_TAG_ARRAY:
+ case GI_TYPE_TAG_INTERFACE:
+ case GI_TYPE_TAG_GLIST:
+ case GI_TYPE_TAG_GSLIST:
+ case GI_TYPE_TAG_GHASH:
+ case GI_TYPE_TAG_ERROR:
+ case GI_TYPE_TAG_UNICHAR:
+ default:
+ goto unhandled_type;
+ }
+
+ overflow:
+ PyErr_Format (PyExc_OverflowError,
+ "Unable to marshal C Py_ssize_t %zd to %s",
+ size_in,
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+
+ unhandled_type:
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal C Py_ssize_t %zd to %s",
+ size_in,
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+}
+
+static gboolean
+gi_argument_to_gsize (GIArgument *arg_in,
+ gsize *gsize_out,
+ GITypeTag type_tag)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_INT8:
+ *gsize_out = arg_in->v_int8;
+ return TRUE;
+ case GI_TYPE_TAG_UINT8:
+ *gsize_out = arg_in->v_uint8;
+ return TRUE;
+ case GI_TYPE_TAG_INT16:
+ *gsize_out = arg_in->v_int16;
+ return TRUE;
+ case GI_TYPE_TAG_UINT16:
+ *gsize_out = arg_in->v_uint16;
+ return TRUE;
+ case GI_TYPE_TAG_INT32:
+ *gsize_out = arg_in->v_int32;
+ return TRUE;
+ case GI_TYPE_TAG_UINT32:
+ *gsize_out = arg_in->v_uint32;
+ return TRUE;
+ case GI_TYPE_TAG_INT64:
+ if (arg_in->v_uint64 > G_MAXSIZE) {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to gsize",
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+ }
+ *gsize_out = (gsize)arg_in->v_int64;
+ return TRUE;
+ case GI_TYPE_TAG_UINT64:
+ if (arg_in->v_uint64 > G_MAXSIZE) {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to gsize",
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+ }
+ *gsize_out = (gsize)arg_in->v_uint64;
+ return TRUE;
+ default:
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to gsize",
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+ }
+}
+
+static gboolean
+_pygi_marshal_from_py_array (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyGIMarshalFromPyFunc from_py_marshaller;
+ guint i = 0;
+ gsize success_count = 0;
+ Py_ssize_t py_length;
+ guint length;
+ guint item_size;
+ gboolean is_ptr_array;
+ GArray *array_ = NULL;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
+ GITransfer cleanup_transfer = arg_cache->transfer;
+
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+
+ if (!PySequence_Check (py_arg)) {
+ PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ py_length = PySequence_Length (py_arg);
+ if (py_length < 0)
+ return FALSE;
+
+ if (!pygi_guint_from_pyssize (py_length, &length))
+ return FALSE;
+
+ if (array_cache->fixed_size >= 0 &&
+ (guint)array_cache->fixed_size != length) {
+ PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %u",
+ array_cache->fixed_size, length);
+
+ return FALSE;
+ }
+
+ item_size = (guint)array_cache->item_size;
+ is_ptr_array = (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
+ if (is_ptr_array) {
+ array_ = (GArray *)g_ptr_array_sized_new (length);
+ } else {
+ array_ = g_array_sized_new (array_cache->is_zero_terminated,
+ TRUE,
+ item_size,
+ length);
+ }
+
+ if (array_ == NULL) {
+ PyErr_NoMemory ();
+ return FALSE;
+ }
+
+ if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8 &&
+ PyBytes_Check (py_arg)) {
+ gchar *data = PyBytes_AsString (py_arg);
+
+ /* Avoid making a copy if the data
+ * is not transferred to the C function
+ * and cannot not be modified by it.
+ */
+ if (array_cache->array_type == GI_ARRAY_TYPE_C &&
+ arg_cache->transfer == GI_TRANSFER_NOTHING &&
+ !array_cache->is_zero_terminated) {
+ g_free (array_->data);
+ array_->data = data;
+ cleanup_transfer = GI_TRANSFER_EVERYTHING;
+ } else {
+ memcpy (array_->data, data, length);
+ }
+ array_->len = length;
+ if (array_cache->is_zero_terminated) {
+ /* If array_ has been created with zero_termination, space for the
+ * terminator is properly allocated, so we're not off-by-one here. */
+ array_->data[length] = '\0';
+ }
+ goto array_success;
+ }
+
+ from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
+ for (i = 0, success_count = 0; i < length; i++) {
+ GIArgument item = {0};
+ gpointer item_cleanup_data = NULL;
+ PyObject *py_item = PySequence_GetItem (py_arg, i);
+ if (py_item == NULL)
+ goto err;
+
+ if (!from_py_marshaller ( state,
+ callable_cache,
+ sequence_cache->item_cache,
+ py_item,
+ &item,
+ &item_cleanup_data)) {
+ Py_DECREF (py_item);
+ goto err;
+ }
+ Py_DECREF (py_item);
+
+ if (item_cleanup_data != NULL && item_cleanup_data != item.v_pointer) {
+ /* We only support one level of data discrepancy between an items
+ * data and its cleanup data. This is because we only track a single
+ * extra cleanup data pointer per-argument and cannot track the entire
+ * array of items differing data and cleanup_data.
+ * For example, this would fail if trying to marshal an array of
+ * callback closures marked with SCOPE call type where the cleanup data
+ * is different from the items v_pointer, likewise an array of arrays.
+ */
+ PyErr_SetString(PyExc_RuntimeError, "Cannot cleanup item data for array due to "
+ "the items data its cleanup data being different.");
+ goto err;
+ }
+
+ /* FIXME: it is much more efficent to have seperate marshaller
+ * for ptr arrays than doing the evaluation
+ * and casting each loop iteration
+ */
+ if (is_ptr_array) {
+ g_ptr_array_add((GPtrArray *)array_, item.v_pointer);
+ } else if (sequence_cache->item_cache->is_pointer) {
+ /* if the item is a pointer, simply copy the pointer */
+ g_assert (item_size == sizeof (item.v_pointer));
+ g_array_insert_val (array_, i, item);
+ } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
+ /* Special case handling of flat arrays of gvalue/boxed/struct */
+ PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *) sequence_cache->item_cache;
+ GIBaseInfo *base_info = (GIBaseInfo *) item_iface_cache->interface_info;
+ GIInfoType info_type = g_base_info_get_type (base_info);
+
+ switch (info_type) {
+ case GI_INFO_TYPE_UNION:
+ case GI_INFO_TYPE_STRUCT:
+ {
+ PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache;
+ PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup;
+
+ if (g_type_is_a (item_iface_cache->g_type, G_TYPE_VALUE)) {
+ /* Special case GValue flat arrays to properly init and copy the contents. */
+ GValue* dest = (GValue*)(void*)(array_->data + (i * item_size));
+ if (item.v_pointer != NULL) {
+ memset (dest, 0, item_size);
+ g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
+ g_value_copy ((GValue*) item.v_pointer, dest);
+ }
+ /* Manually increment the length because we are manually setting the memory. */
+ array_->len++;
+
+ } else {
+ /* Handles flat arrays of boxed or struct types. */
+ g_array_insert_vals (array_, i, item.v_pointer, 1);
+ }
+
+ /* Cleanup any memory left by the per-item marshaler because
+ * _pygi_marshal_cleanup_from_py_array will not know about this
+ * due to "item" being a temporarily marshaled value done on the stack.
+ */
+ if (from_py_cleanup)
+ from_py_cleanup (state, item_arg_cache, py_item, item_cleanup_data, TRUE);
+
+ break;
+ }
+ default:
+ g_array_insert_val (array_, i, item);
+ }
+ } else {
+ /* default value copy of a simple type */
+ g_array_insert_val (array_, i, item);
+ }
+
+ success_count++;
+ }
+ goto array_success;
+
+err:
+ if (sequence_cache->item_cache->from_py_cleanup != NULL) {
+ gsize j;
+ PyGIMarshalCleanupFunc cleanup_func =
+ sequence_cache->item_cache->from_py_cleanup;
+
+ /* Only attempt per item cleanup on pointer items */
+ if (sequence_cache->item_cache->is_pointer) {
+ for(j = 0; j < success_count; j++) {
+ PyObject *py_seq_item = PySequence_GetItem (py_arg, j);
+ cleanup_func (state,
+ sequence_cache->item_cache,
+ py_seq_item,
+ is_ptr_array ?
+ g_ptr_array_index ((GPtrArray *)array_, j) :
+ g_array_index (array_, gpointer, j),
+ TRUE);
+ Py_DECREF (py_seq_item);
+ }
+ }
+ }
+
+ if (is_ptr_array)
+ g_ptr_array_free ( ( GPtrArray *)array_, TRUE);
+ else
+ g_array_free (array_, TRUE);
+ _PyGI_ERROR_PREFIX ("Item %u: ", i);
+ return FALSE;
+
+array_success:
+ if (array_cache->len_arg_index >= 0) {
+ /* we have an child arg to handle */
+ PyGIArgCache *child_cache =
+ _pygi_callable_cache_get_arg (callable_cache, (guint)array_cache->len_arg_index);
+
+ if (!gi_argument_from_py_ssize_t (&state->args[child_cache->c_arg_index].arg_value,
+ length,
+ child_cache->type_tag)) {
+ goto err;
+ }
+ }
+
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
+ /* In the case of GI_ARRAY_C, we give the data directly as the argument
+ * but keep the array_ wrapper as cleanup data so we don't have to find
+ * it's length again.
+ */
+ arg->v_pointer = array_->data;
+
+ if (cleanup_transfer == GI_TRANSFER_EVERYTHING) {
+ g_array_free (array_, FALSE);
+ *cleanup_data = NULL;
+ } else {
+ *cleanup_data = array_;
+ }
+ } else {
+ arg->v_pointer = array_;
+
+ if (cleanup_transfer == GI_TRANSFER_NOTHING) {
+ /* Free everything in cleanup. */
+ *cleanup_data = array_;
+ } else if (cleanup_transfer == GI_TRANSFER_CONTAINER) {
+ /* Make a shallow copy so we can free the elements later in cleanup
+ * because it is possible invoke will free the list before our cleanup. */
+ *cleanup_data = is_ptr_array ?
+ (gpointer)g_ptr_array_ref ((GPtrArray *)array_) :
+ (gpointer)g_array_ref (array_);
+ } else { /* GI_TRANSFER_EVERYTHING */
+ /* No cleanup, everything is given to the callee. */
+ *cleanup_data = NULL;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+_pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (was_processed) {
+ GArray *array_ = NULL;
+ GPtrArray *ptr_array_ = NULL;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
+
+ if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ ptr_array_ = (GPtrArray *) data;
+ } else {
+ array_ = (GArray *) data;
+ }
+
+ /* clean up items first */
+ if (sequence_cache->item_cache->from_py_cleanup != NULL) {
+ gsize i;
+ guint len;
+ PyGIMarshalCleanupFunc cleanup_func =
+ sequence_cache->item_cache->from_py_cleanup;
+
+ g_assert (array_ || ptr_array_);
+ len = (array_ != NULL) ? array_->len : ptr_array_->len;
+
+ for (i = 0; i < len; i++) {
+ gpointer item;
+ PyObject *py_item = NULL;
+
+ /* case 1: GPtrArray */
+ if (ptr_array_ != NULL)
+ item = g_ptr_array_index (ptr_array_, i);
+ /* case 2: C array or GArray with object pointers */
+ else if (sequence_cache->item_cache->is_pointer)
+ item = g_array_index (array_, gpointer, i);
+ /* case 3: C array or GArray with simple types or structs */
+ else {
+ item = array_->data + i * array_cache->item_size;
+ /* special-case hack: GValue array items do not get slice
+ * allocated in _pygi_marshal_from_py_array(), so we must
+ * not try to deallocate it as a slice and thus
+ * short-circuit cleanup_func. */
+ if (cleanup_func == pygi_arg_gvalue_from_py_cleanup) {
+ g_value_unset ((GValue*) item);
+ continue;
+ }
+ }
+
+ py_item = PySequence_GetItem (py_arg, i);
+ cleanup_func (state, sequence_cache->item_cache, py_item, item, TRUE);
+ Py_XDECREF (py_item);
+ }
+ }
+
+ /* Only free the array when we didn't transfer ownership */
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
+ /* always free the GArray wrapper created in from_py marshaling and
+ * passed back as cleanup_data
+ */
+ g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
+ } else {
+ if (array_ != NULL)
+ g_array_unref (array_);
+ else
+ g_ptr_array_unref (ptr_array_);
+ }
+ }
+}
+
+/*
+ * GArray from Python
+ */
+static PyObject *
+_pygi_marshal_to_py_array (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ GArray *array_;
+ PyObject *py_obj = NULL;
+ PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
+ guint processed_items = 0;
+
+ /* GArrays make it easier to iterate over arrays
+ * with different element sizes but requires that
+ * we allocate a GArray if the argument was a C array
+ */
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
+ gsize len;
+ if (array_cache->fixed_size >= 0) {
+ g_assert(arg->v_pointer != NULL);
+ len = array_cache->fixed_size;
+ } else if (array_cache->is_zero_terminated) {
+ if (arg->v_pointer == NULL) {
+ len = 0;
+ } else if (array_cache->item_size == 1) {
+ len = strlen (arg->v_pointer);
+ } else if (array_cache->item_size == sizeof(gpointer)) {
+ len = g_strv_length ((gchar **)arg->v_pointer);
+ } else if (array_cache->item_size == sizeof(int)) {
+ for (len = 0; *(((int*)arg->v_pointer) + len); len++);
+ } else if (array_cache->item_size == sizeof(short)) {
+ for (len = 0; *(((short*)arg->v_pointer) + len); len++);
+ } else {
+ g_assert_not_reached ();
+ }
+ } else {
+ GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value;
+ PyGIArgCache *sub_cache = _pygi_callable_cache_get_arg (callable_cache,
+ (guint)array_cache->len_arg_index);
+
+ if (!gi_argument_to_gsize (len_arg, &len, sub_cache->type_tag)) {
+ return NULL;
+ }
+ }
+
+ array_ = g_array_new (FALSE,
+ FALSE,
+ (guint)array_cache->item_size);
+ if (array_ == NULL) {
+ PyErr_NoMemory ();
+
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && arg->v_pointer != NULL)
+ g_free (arg->v_pointer);
+
+ return NULL;
+ }
+
+ if (array_->data != NULL)
+ g_free (array_->data);
+ array_->data = arg->v_pointer;
+ array_->len = (guint)len;
+ } else {
+ array_ = arg->v_pointer;
+ }
+
+ if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
+ if (arg->v_pointer == NULL) {
+ py_obj = PyBytes_FromString ("");
+ } else {
+ py_obj = PyBytes_FromStringAndSize (array_->data, array_->len);
+ }
+ } else {
+ if (arg->v_pointer == NULL) {
+ py_obj = PyList_New (0);
+ } else {
+ guint i;
+
+ gsize item_size;
+ PyGIMarshalToPyFunc item_to_py_marshaller;
+ PyGIArgCache *item_arg_cache;
+ GPtrArray *item_cleanups;
+
+ py_obj = PyList_New (array_->len);
+ if (py_obj == NULL)
+ goto err;
+
+ item_cleanups = g_ptr_array_sized_new (array_->len);
+ *cleanup_data = item_cleanups;
+
+ item_arg_cache = seq_cache->item_cache;
+ item_to_py_marshaller = item_arg_cache->to_py_marshaller;
+
+ item_size = g_array_get_element_size (array_);
+
+ for (i = 0; i < array_->len; i++) {
+ GIArgument item_arg = {0};
+ PyObject *py_item;
+ gpointer item_cleanup_data = NULL;
+
+ /* If we are receiving an array of pointers, simply assign the pointer
+ * and move on, letting the per-item marshaler deal with the
+ * various transfer modes and ref counts (e.g. g_variant_ref_sink).
+ */
+ if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
+
+ } else if (item_arg_cache->is_pointer) {
+ item_arg.v_pointer = g_array_index (array_, gpointer, i);
+
+ } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *) item_arg_cache;
+
+ /* FIXME: This probably doesn't work with boxed types or gvalues.
+ * See fx. _pygi_marshal_from_py_array() */
+ switch (g_base_info_get_type (iface_cache->interface_info)) {
+ case GI_INFO_TYPE_STRUCT:
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING &&
+ !g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
+ /* array elements are structs */
+ gpointer *_struct = g_malloc (item_size);
+ memcpy (_struct, array_->data + i * item_size,
+ item_size);
+ item_arg.v_pointer = _struct;
+ } else {
+ item_arg.v_pointer = array_->data + i * item_size;
+ }
+ break;
+ case GI_INFO_TYPE_ENUM:
+ memcpy (&item_arg, array_->data + i * item_size, item_size);
+ break;
+ default:
+ item_arg.v_pointer = g_array_index (array_, gpointer, i);
+ break;
+ }
+ } else {
+ memcpy (&item_arg, array_->data + i * item_size, item_size);
+ }
+
+ py_item = item_to_py_marshaller ( state,
+ callable_cache,
+ item_arg_cache,
+ &item_arg,
+ &item_cleanup_data);
+
+ g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
+
+ if (py_item == NULL) {
+ Py_CLEAR (py_obj);
+
+ if (array_cache->array_type == GI_ARRAY_TYPE_C)
+ g_array_unref (array_);
+
+ g_ptr_array_unref (item_cleanups);
+
+ goto err;
+ }
+ PyList_SET_ITEM (py_obj, i, py_item);
+ processed_items++;
+ }
+ }
+ }
+
+ if (array_cache->array_type == GI_ARRAY_TYPE_C)
+ g_array_free (array_, FALSE);
+
+ return py_obj;
+
+err:
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
+ g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING);
+ } else {
+ /* clean up unprocessed items */
+ if (seq_cache->item_cache->to_py_cleanup != NULL) {
+ guint j;
+ PyGIMarshalToPyCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup;
+ for (j = processed_items; j < array_->len; j++) {
+ cleanup_func (state,
+ seq_cache->item_cache,
+ NULL,
+ g_array_index (array_, gpointer, j),
+ FALSE);
+ }
+ }
+
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
+ g_array_free (array_, TRUE);
+ }
+
+ return NULL;
+}
+
+static GArray*
+_wrap_c_array (PyGIInvokeState *state,
+ PyGIArgGArray *array_cache,
+ gpointer data)
+{
+ GArray *array_;
+ gsize len = 0;
+
+ if (array_cache->fixed_size >= 0) {
+ len = array_cache->fixed_size;
+ } else if (array_cache->is_zero_terminated) {
+ if (array_cache->item_size == sizeof(gpointer))
+ len = g_strv_length ((gchar **)data);
+ else if (array_cache->item_size == 1)
+ len = strlen ((gchar*)data);
+ else if (array_cache->item_size == sizeof(int))
+ for (len = 0; *(((int*)data) + len); len++);
+ else if (array_cache->item_size == sizeof(short))
+ for (len = 0; *(((short*)data) + len); len++);
+ else
+ g_assert_not_reached ();
+ } else if (array_cache->len_arg_index >= 0) {
+ GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value;
+ len = len_arg->v_long;
+ }
+
+ array_ = g_array_new (FALSE,
+ FALSE,
+ (guint)array_cache->item_size);
+
+ if (array_ == NULL)
+ return NULL;
+
+ g_free (array_->data);
+ array_->data = data;
+ array_->len = (guint)len;
+
+ return array_;
+}
+
+static void
+_pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer cleanup_data,
+ gpointer data,
+ gboolean was_processed)
+{
+ GArray *array_ = NULL;
+ GPtrArray *ptr_array_ = NULL;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
+ gboolean free_array = FALSE;
+ gboolean free_array_full = TRUE;
+
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
+ arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+ free_array = TRUE;
+ }
+
+ /* If this isn't a garray create one to help process variable sized
+ array elements */
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
+ array_ = _wrap_c_array (state, array_cache, data);
+
+ if (array_ == NULL)
+ return;
+
+ free_array = TRUE;
+ free_array_full = arg_cache->transfer != GI_TRANSFER_NOTHING;
+ } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ ptr_array_ = (GPtrArray *) data;
+ } else {
+ array_ = (GArray *) data;
+ }
+
+ if (sequence_cache->item_cache->to_py_cleanup != NULL) {
+ GPtrArray *item_cleanups = (GPtrArray *) cleanup_data;
+ gsize i;
+ guint len;
+ PyGIMarshalToPyCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
+
+ g_assert (array_ || ptr_array_);
+ len = (array_ != NULL) ? array_->len : ptr_array_->len;
+
+ for (i = 0; i < len; i++) {
+ cleanup_func (state,
+ sequence_cache->item_cache,
+ g_ptr_array_index(item_cleanups, i),
+ (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
+ was_processed);
+ }
+ }
+
+ if (cleanup_data)
+ g_ptr_array_unref ((GPtrArray *) cleanup_data);
+
+ if (free_array) {
+ if (array_ != NULL)
+ g_array_free (array_, free_array_full);
+ else
+ g_ptr_array_free (ptr_array_, free_array_full);
+ }
+}
+
+static void
+_array_cache_free_func (PyGIArgGArray *cache)
+{
+ if (cache != NULL) {
+ pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
+ g_slice_free (PyGIArgGArray, cache);
+ }
+}
+
+PyGIArgCache*
+pygi_arg_garray_len_arg_setup (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ PyGICallableCache *callable_cache,
+ PyGIDirection direction,
+ gssize arg_index,
+ gssize *py_arg_index)
+{
+ PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
+
+ /* attempt len_arg_index setup for the first time */
+ if (seq_cache->len_arg_index < 0) {
+ seq_cache->len_arg_index = g_type_info_get_array_length (type_info);
+
+ /* offset by self arg for methods and vfuncs */
+ if (seq_cache->len_arg_index >= 0 && callable_cache != NULL) {
+ seq_cache->len_arg_index += callable_cache->args_offset;
+ }
+ }
+
+ if (seq_cache->len_arg_index >= 0) {
+ PyGIArgCache *child_cache = NULL;
+
+ child_cache = _pygi_callable_cache_get_arg (callable_cache,
+ (guint)seq_cache->len_arg_index);
+ if (child_cache == NULL) {
+ child_cache = pygi_arg_cache_alloc ();
+ } else {
+ /* If the "length" arg cache already exists (the length comes before
+ * the array in the argument list), remove it from the to_py_args list
+ * because it does not belong in "to python" return tuple. The length
+ * will implicitly be a part of the returned Python list.
+ */
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ callable_cache->to_py_args =
+ g_slist_remove (callable_cache->to_py_args, child_cache);
+ }
+
+ /* This is a case where the arg cache already exists and has been
+ * setup by another array argument sharing the same length argument.
+ * See: gi_marshalling_tests_multi_array_key_value_in
+ */
+ if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
+ return child_cache;
+ }
+
+ /* There is a length argument for this array, so increment the number
+ * of "to python" child arguments when applicable.
+ */
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ callable_cache->n_to_py_child_args++;
+
+ child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+ child_cache->direction = direction;
+ child_cache->to_py_marshaller = pygi_marshal_to_py_basic_type_cache_adapter;
+ child_cache->from_py_marshaller = pygi_marshal_from_py_basic_type_cache_adapter;
+ child_cache->py_arg_index = -1;
+
+ /* ugly edge case code:
+ *
+ * When the length comes before the array parameter we need to update
+ * indexes of arguments after the index argument.
+ */
+ if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
+ guint i;
+ (*py_arg_index) -= 1;
+ callable_cache->n_py_args -= 1;
+
+ for (i = (guint)seq_cache->len_arg_index + 1;
+ (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) {
+ PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
+ if (update_cache == NULL)
+ break;
+
+ update_cache->py_arg_index -= 1;
+ }
+ }
+
+ _pygi_callable_cache_set_arg (callable_cache, (guint)seq_cache->len_arg_index, child_cache);
+ return child_cache;
+ }
+
+ return NULL;
+}
+
+static gboolean
+pygi_arg_garray_setup (PyGIArgGArray *sc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
+{
+ GITypeInfo *item_type_info;
+ PyGIArgCache *arg_cache = (PyGIArgCache *)sc;
+
+ if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache)) {
+ return FALSE;
+ }
+
+ ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
+ sc->array_type = g_type_info_get_array_type (type_info);
+ sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
+ sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
+ sc->len_arg_index = -1; /* setup by pygi_arg_garray_len_arg_setup */
+
+ item_type_info = g_type_info_get_param_type (type_info, 0);
+ sc->item_size = _pygi_g_type_info_size (item_type_info);
+ g_base_info_unref ( (GIBaseInfo *)item_type_info);
+
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
+ }
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_garray_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
+{
+ PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
+ if (array_cache == NULL)
+ return NULL;
+
+ if (!pygi_arg_garray_setup (array_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache)) {
+ pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
+ return NULL;
+ }
+
+ return (PyGIArgCache *)array_cache;
+}
diff --git a/gi/pygi-array.h b/gi/pygi-array.h
new file mode 100644
index 0000000..718c7cd
--- /dev/null
+++ b/gi/pygi-array.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_ARRAY_H__
+#define __PYGI_ARRAY_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+PyGIArgCache *pygi_arg_garray_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache);
+
+PyGIArgCache *pygi_arg_garray_len_arg_setup (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ PyGICallableCache *callable_cache,
+ PyGIDirection direction,
+ gssize arg_index,
+ gssize *py_arg_index);
+
+G_END_DECLS
+
+#endif /*__PYGI_ARRAY_H__*/
diff --git a/gi/pygi-basictype.c b/gi/pygi-basictype.c
new file mode 100644
index 0000000..82f8a85
--- /dev/null
+++ b/gi/pygi-basictype.c
@@ -0,0 +1,1338 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+
+#include "pygi-type.h"
+#include "pygi-basictype.h"
+#include "pygi-argument.h"
+#include "pygi-util.h"
+
+#if defined(G_OS_WIN32)
+#include <float.h>
+static gboolean
+pygi_isfinite (gdouble value) {
+ return _finite (value);
+}
+#else
+#include <math.h>
+static gboolean
+pygi_isfinite (gdouble value) {
+ return isfinite (value);
+}
+#endif
+
+static gboolean
+pygi_gpointer_from_py (PyObject *py_arg, gpointer *result)
+{
+ void* temp;
+
+ if (py_arg == Py_None) {
+ *result = NULL;
+ return TRUE;
+ } else if (PyCapsule_CheckExact (py_arg)) {
+ temp = PyCapsule_GetPointer (py_arg, NULL);
+ if (temp == NULL)
+ return FALSE;
+ *result = temp;
+ return TRUE;
+ } else if (PyLong_Check(py_arg)) {
+ temp = PyLong_AsVoidPtr (py_arg);
+ if (PyErr_Occurred ())
+ return FALSE;
+ *result = temp;
+ return TRUE;
+ } else {
+ PyErr_SetString(PyExc_ValueError,
+ "Pointer arguments are restricted to integers, capsules, and None. "
+ "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599");
+ return FALSE;
+ }
+}
+
+static gboolean
+marshal_from_py_void (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ g_warn_if_fail (arg_cache->transfer == GI_TRANSFER_NOTHING);
+
+ if (pygi_gpointer_from_py (py_arg, &(arg->v_pointer))) {
+ *cleanup_data = arg->v_pointer;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+PyObject *
+pygi_gsize_to_py (gsize value)
+{
+ return PyLong_FromSize_t (value);
+}
+
+PyObject *
+pygi_gssize_to_py (gssize value)
+{
+ return PyLong_FromSsize_t (value);
+}
+
+static PyObject *
+base_float_checks (PyObject *object)
+{
+ if (!PyNumber_Check (object)) {
+ PyErr_Format (PyExc_TypeError, "Must be number, not %s",
+ Py_TYPE (object)->tp_name);
+ return NULL;
+ }
+
+ return PyNumber_Float (object);
+}
+
+gboolean
+pygi_gdouble_from_py (PyObject *py_arg, gdouble *result)
+{
+ PyObject *py_float;
+ gdouble temp;
+
+ py_float = base_float_checks (py_arg);
+ if (py_float == NULL)
+ return FALSE;
+
+ temp = PyFloat_AsDouble (py_float);
+ Py_DECREF (py_float);
+
+ if (PyErr_Occurred ())
+ return FALSE;
+
+ *result = temp;
+
+ return TRUE;
+}
+
+PyObject *
+pygi_gdouble_to_py (gdouble value)
+{
+ return PyFloat_FromDouble (value);
+}
+
+gboolean
+pygi_gfloat_from_py (PyObject *py_arg, gfloat *result)
+{
+ gdouble double_;
+ PyObject *py_float;
+
+ py_float = base_float_checks (py_arg);
+ if (py_float == NULL)
+ return FALSE;
+
+ double_ = PyFloat_AsDouble (py_float);
+ if (PyErr_Occurred ()) {
+ Py_DECREF (py_float);
+ return FALSE;
+ }
+
+ if (pygi_isfinite (double_) && (double_ < -G_MAXFLOAT || double_ > G_MAXFLOAT)) {
+ PyObject *min, *max;
+
+ min = pygi_gfloat_to_py (-G_MAXFLOAT);
+ max = pygi_gfloat_to_py (G_MAXFLOAT);
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %S to %S",
+ py_float, min, max);
+ Py_DECREF (min);
+ Py_DECREF (max);
+ Py_DECREF (py_float);
+ return FALSE;
+ }
+
+ Py_DECREF (py_float);
+ *result = (gfloat)double_;
+
+ return TRUE;
+}
+
+PyObject *
+pygi_gfloat_to_py (gfloat value)
+{
+ return PyFloat_FromDouble (value);
+}
+
+gboolean
+pygi_gunichar_from_py (PyObject *py_arg, gunichar *result)
+{
+ Py_ssize_t size;
+ gchar *string_;
+
+ if (py_arg == Py_None) {
+ *result = 0;
+ return FALSE;
+ }
+
+ if (PyUnicode_Check (py_arg)) {
+ PyObject *py_bytes;
+
+ size = PyUnicode_GET_LENGTH (py_arg);
+ py_bytes = PyUnicode_AsUTF8String (py_arg);
+ if (!py_bytes)
+ return FALSE;
+
+ string_ = g_strdup(PyBytes_AsString (py_bytes));
+ Py_DECREF (py_bytes);
+ } else {
+ PyErr_Format (PyExc_TypeError, "Must be string, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ if (size != 1) {
+ PyErr_Format (PyExc_TypeError, "Must be a one character string, not %lld characters",
+ (long long) size);
+ g_free (string_);
+ return FALSE;
+ }
+
+ *result = g_utf8_get_char (string_);
+ g_free (string_);
+
+ return TRUE;
+}
+
+static PyObject *
+pygi_gunichar_to_py (gunichar value)
+{
+ PyObject *py_obj = NULL;
+
+ /* Preserve the bidirectional mapping between 0 and "" */
+ if (value == 0) {
+ py_obj = PyUnicode_FromString ("");
+ } else if (g_unichar_validate (value)) {
+ gchar utf8[6];
+ gint bytes;
+
+ bytes = g_unichar_to_utf8 (value, utf8);
+ py_obj = PyUnicode_FromStringAndSize ((char*)utf8, bytes);
+ } else {
+ /* TODO: Convert the error to an exception. */
+ PyErr_Format (PyExc_TypeError,
+ "Invalid unicode codepoint %" G_GUINT32_FORMAT,
+ value);
+ }
+
+ return py_obj;
+}
+
+static gboolean
+pygi_gtype_from_py (PyObject *py_arg, GType *type)
+{
+ GType temp = pyg_type_from_object (py_arg);
+
+ if (temp == 0) {
+ if (!PyErr_Occurred ()) {
+ PyErr_SetString (PyExc_ValueError, "Invalid GType");
+ return FALSE;
+ }
+ PyErr_Format (PyExc_TypeError, "Must be GObject.GType, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ *type = temp;
+
+ return TRUE;
+}
+
+gboolean
+pygi_utf8_from_py (PyObject *py_arg, gchar **result)
+{
+ gchar *string_;
+
+ if (py_arg == Py_None) {
+ *result = NULL;
+ return TRUE;
+ }
+
+ if (PyUnicode_Check (py_arg)) {
+ PyObject *pystr_obj = PyUnicode_AsUTF8String (py_arg);
+ if (!pystr_obj)
+ return FALSE;
+
+ string_ = g_strdup (PyBytes_AsString (pystr_obj));
+ Py_DECREF (pystr_obj);
+ }
+ else {
+ PyErr_Format (PyExc_TypeError, "Must be string, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ *result = string_;
+ return TRUE;
+}
+
+G_GNUC_UNUSED
+static gboolean
+filename_from_py_unix (PyObject *py_arg, gchar **result)
+{
+ gchar *filename;
+
+ if (py_arg == Py_None) {
+ *result = NULL;
+ return TRUE;
+ }
+
+ if (PyBytes_Check (py_arg)) {
+ char *buffer;
+
+ if (PyBytes_AsStringAndSize (py_arg, &buffer, NULL) == -1)
+ return FALSE;
+
+ filename = g_strdup (buffer);
+ } else if (PyUnicode_Check (py_arg)) {
+ PyObject *bytes;
+ char *buffer;
+
+ bytes = PyUnicode_EncodeFSDefault (py_arg);
+
+ if (!bytes)
+ return FALSE;
+
+ if (PyBytes_AsStringAndSize (bytes, &buffer, NULL) == -1) {
+ Py_DECREF (bytes);
+ return FALSE;
+ }
+
+ filename = g_strdup (buffer);
+ Py_DECREF (bytes);
+ } else {
+ PyErr_Format (PyExc_TypeError, "Must be bytes, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ *result = filename;
+ return TRUE;
+}
+
+G_GNUC_UNUSED
+static gboolean
+filename_from_py_win32 (PyObject *py_arg, gchar **result)
+{
+ gchar *filename;
+
+ if (py_arg == Py_None) {
+ *result = NULL;
+ return TRUE;
+ }
+
+ if (PyBytes_Check (py_arg)) {
+ PyObject *uni_arg;
+ gboolean temp_result;
+ char *buffer;
+
+ if (PyBytes_AsStringAndSize (py_arg, &buffer, NULL) == -1)
+ return FALSE;
+
+ uni_arg = PyUnicode_DecodeFSDefault (buffer);
+ if (!uni_arg)
+ return FALSE;
+ temp_result = filename_from_py_win32 (uni_arg, result);
+ Py_DECREF (uni_arg);
+ return temp_result;
+ } else if (PyUnicode_Check (py_arg)) {
+ PyObject *bytes, *temp_uni;
+ char *buffer;
+
+ /* The roundtrip merges lone surrogates, so we get the same output as
+ * with Py 2. Requires 3.4+ because of https://bugs.python.org/issue27971
+ * Separated lone surrogates can occur when concatenating two paths.
+ */
+ bytes = PyUnicode_AsEncodedString (py_arg, "utf-16-le", "surrogatepass");
+ if (!bytes)
+ return FALSE;
+ temp_uni = PyUnicode_FromEncodedObject (bytes, "utf-16-le", "surrogatepass");
+ Py_DECREF (bytes);
+ if (!temp_uni)
+ return FALSE;
+ /* glib uses utf-8, so encode to that and allow surrogates so we can
+ * represent all possible path values
+ */
+ bytes = PyUnicode_AsEncodedString (temp_uni, "utf-8", "surrogatepass");
+ Py_DECREF (temp_uni);
+ if (!bytes)
+ return FALSE;
+
+ if (PyBytes_AsStringAndSize (bytes, &buffer, NULL) == -1) {
+ Py_DECREF (bytes);
+ return FALSE;
+ }
+
+ filename = g_strdup (buffer);
+ Py_DECREF (bytes);
+ } else {
+ PyErr_Format (PyExc_TypeError, "Must be str, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ *result = filename;
+ return TRUE;
+}
+
+static gboolean
+pygi_filename_from_py (PyObject *py_arg, gchar **result)
+{
+#ifdef G_OS_WIN32
+ return filename_from_py_win32 (py_arg, result);
+#else
+ return filename_from_py_unix (py_arg, result);
+#endif
+}
+
+static PyObject *
+base_number_checks (PyObject *object)
+{
+ PyObject *number;
+
+ if (!PyNumber_Check (object)) {
+ PyErr_Format (PyExc_TypeError, "Must be number, not %s",
+ Py_TYPE (object)->tp_name);
+ return NULL;
+ }
+
+ number = PyNumber_Long (object);
+
+ if (number == NULL) {
+ PyErr_SetString (PyExc_TypeError, "expected int argument");
+ return NULL;
+ }
+
+ return number;
+}
+
+gboolean
+pygi_gboolean_from_py (PyObject *object, gboolean *result)
+{
+ int value = PyObject_IsTrue (object);
+ if (value == -1)
+ return FALSE;
+ *result = (gboolean)value;
+ return TRUE;
+}
+
+PyObject *
+pygi_gboolean_to_py (gboolean value)
+{
+ return PyBool_FromLong (value);
+}
+
+/* A super set of pygi_gint8_from_py (also handles unicode) */
+gboolean
+pygi_gschar_from_py (PyObject *object, gint8 *result)
+{
+ if (PyUnicode_Check (object)) {
+ gunichar uni;
+ PyObject *temp;
+ gboolean status;
+
+ if (!pygi_gunichar_from_py (object, &uni))
+ return FALSE;
+
+ temp = pygi_guint32_to_py (uni);
+ status = pygi_gint8_from_py (temp, result);
+ Py_DECREF (temp);
+ return status;
+ } else {
+ /* pygi_gint8_from_py handles numbers and bytes */
+ return pygi_gint8_from_py (object, result);
+ }
+
+ return FALSE;
+}
+
+/* A super set of pygi_guint8_from_py (also handles unicode) */
+gboolean
+pygi_guchar_from_py (PyObject *object, guchar *result)
+{
+ if (PyUnicode_Check (object)) {
+ gunichar uni;
+ PyObject *temp;
+ gboolean status;
+ gint8 codepoint;
+
+ if (!pygi_gunichar_from_py (object, &uni))
+ return FALSE;
+
+ temp = pygi_guint32_to_py (uni);
+ status = pygi_gint8_from_py (temp, &codepoint);
+ Py_DECREF (temp);
+ if (status)
+ *result = (guchar)codepoint;
+ return status;
+ } else {
+ /* pygi_guint8_from_py handles numbers and bytes */
+ return pygi_guint8_from_py (object, result);
+ }
+}
+
+gboolean
+pygi_gint_from_py (PyObject *object, gint *result)
+{
+ long long_value;
+ PyObject *number;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLong (number);
+ if (PyErr_Occurred ()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value < G_MININT || long_value > G_MAXINT) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (gint)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %d to %d",
+ number, (int)G_MININT, (int)G_MAXINT);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+PyObject *
+pygi_gint_to_py (gint value)
+{
+ return PyLong_FromLong (value);
+}
+
+gboolean
+pygi_guint_from_py (PyObject *object, guint *result)
+{
+ unsigned long long_value;
+ PyObject *number;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsUnsignedLong (number);
+ if (PyErr_Occurred ()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value > G_MAXUINT) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (gint)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %lu",
+ number, (long)0, (unsigned long)G_MAXUINT);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+PyObject *
+pygi_guint_to_py (guint value)
+{
+#if (G_MAXUINT <= LONG_MAX)
+ return PyLong_FromLong ((long) value);
+#else
+ if (value <= LONG_MAX)
+ return PyLong_FromLong ((long) value);
+ return PyLong_FromUnsignedLong (value);
+#endif
+}
+
+gboolean
+pygi_glong_from_py (PyObject *object, glong *result)
+{
+ long long_value;
+ PyObject *number;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLong (number);
+ if (long_value == -1 && PyErr_Occurred ()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ }
+
+ Py_DECREF (number);
+ *result = (glong)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %ld",
+ number, (long)G_MINLONG, (long)G_MAXLONG);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+PyObject *
+pygi_glong_to_py (glong value)
+{
+ return PyLong_FromLong (value);
+}
+
+gboolean
+pygi_gulong_from_py (PyObject *object, gulong *result)
+{
+ unsigned long long_value;
+ PyObject *number;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsUnsignedLong (number);
+ if (PyErr_Occurred ()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ }
+
+ Py_DECREF (number);
+ *result = (gulong)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %lu",
+ number, (long)0, (unsigned long)G_MAXULONG);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+PyObject *
+pygi_gulong_to_py (gulong value)
+{
+ if (value <= LONG_MAX)
+ return PyLong_FromLong ((long) value);
+ else
+ return PyLong_FromUnsignedLong (value);
+}
+
+gboolean
+pygi_gint8_from_py (PyObject *object, gint8 *result)
+{
+ long long_value;
+ PyObject *number;
+
+ if (PyBytes_Check (object)) {
+ if (PyBytes_Size (object) != 1) {
+ PyErr_Format (PyExc_TypeError, "Must be a single character");
+ return FALSE;
+ }
+
+ *result = (gint8)(PyBytes_AsString (object)[0]);
+ return TRUE;
+ }
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLong (number);
+ if (long_value == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value < G_MININT8 || long_value > G_MAXINT8) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (gint8)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %ld",
+ number, (long)G_MININT8, (long)G_MAXINT8);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+PyObject *
+pygi_gint8_to_py (gint8 value)
+{
+ return PyLong_FromLong (value);
+}
+
+gboolean
+pygi_guint8_from_py (PyObject *object, guint8 *result)
+{
+ long long_value;
+ PyObject *number;
+
+ if (PyBytes_Check (object)) {
+ if (PyBytes_Size (object) != 1) {
+ PyErr_Format (PyExc_TypeError, "Must be a single character");
+ return FALSE;
+ }
+
+ *result = (guint8)(PyBytes_AsString (object)[0]);
+ return TRUE;
+ }
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLong (number);
+ if (long_value == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value < 0 || long_value > G_MAXUINT8) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (guint8)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %ld",
+ number, (long)0, (long)G_MAXUINT8);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+PyObject *
+pygi_guint8_to_py (guint8 value)
+{
+ return PyLong_FromLong (value);
+}
+
+static gboolean
+pygi_gint16_from_py (PyObject *object, gint16 *result)
+{
+ long long_value;
+ PyObject *number;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLong (number);
+ if (long_value == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value < G_MININT16 || long_value > G_MAXINT16) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (gint16)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %ld",
+ number, (long)G_MININT16, (long)G_MAXINT16);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+static PyObject *
+pygi_gint16_to_py (gint16 value)
+{
+ return PyLong_FromLong (value);
+}
+
+static gboolean
+pygi_guint16_from_py (PyObject *object, guint16 *result)
+{
+ long long_value;
+ PyObject *number;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLong (number);
+ if (long_value == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value < 0 || long_value > G_MAXUINT16) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (guint16)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %ld",
+ number, (long)0, (long)G_MAXUINT16);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+static PyObject *
+pygi_guint16_to_py (guint16 value)
+{
+ return PyLong_FromLong (value);
+}
+
+static gboolean
+pygi_gint32_from_py (PyObject *object, gint32 *result)
+{
+ long long_value;
+ PyObject *number;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLong (number);
+ if (long_value == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value < G_MININT32 || long_value > G_MAXINT32) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (gint32)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %ld",
+ number, (long)G_MININT32, (long)G_MAXINT32);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+static PyObject *
+pygi_gint32_to_py (gint32 value)
+{
+ return PyLong_FromLong (value);
+}
+
+static gboolean
+pygi_guint32_from_py (PyObject *object, guint32 *result)
+{
+ long long long_value;
+ PyObject *number;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLongLong (number);
+ if (PyErr_Occurred ()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value < 0 || long_value > G_MAXUINT32) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (guint32)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %lu",
+ number, (long)0, (unsigned long)G_MAXUINT32);
+ Py_DECREF (number);
+ return FALSE;
+}
+
+PyObject *
+pygi_guint32_to_py (guint32 value)
+{
+#if (G_MAXUINT <= LONG_MAX)
+ return PyLong_FromLong (value);
+#else
+ if (value <= LONG_MAX)
+ return PyLong_FromLong((long) value);
+ else
+ return PyLong_FromLongLong (value);
+#endif
+}
+
+gboolean
+pygi_gint64_from_py (PyObject *object, gint64 *result)
+{
+ long long long_value;
+ PyObject *number, *min, *max;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsLongLong (number);
+ if (PyErr_Occurred ()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value < G_MININT64 || long_value > G_MAXINT64) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (gint64)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ min = pygi_gint64_to_py (G_MININT64);
+ max = pygi_gint64_to_py (G_MAXINT64);
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %S to %S",
+ number, min, max);
+ Py_DECREF (number);
+ Py_DECREF (min);
+ Py_DECREF (max);
+ return FALSE;
+}
+
+PyObject *
+pygi_gint64_to_py (gint64 value)
+{
+ if (LONG_MIN <= value && value <= LONG_MAX)
+ return PyLong_FromLong((long) value);
+ else
+ return PyLong_FromLongLong (value);
+}
+
+gboolean
+pygi_guint64_from_py (PyObject *object, guint64 *result)
+{
+ unsigned long long long_value;
+ PyObject *number, *max;
+
+ number = base_number_checks (object);
+ if (number == NULL)
+ return FALSE;
+
+ long_value = PyLong_AsUnsignedLongLong (number);
+ if (PyErr_Occurred ()) {
+ if (PyErr_ExceptionMatches (PyExc_OverflowError))
+ goto overflow;
+ Py_DECREF (number);
+ return FALSE;
+ } else if (long_value > G_MAXUINT64) {
+ goto overflow;
+ }
+
+ Py_DECREF (number);
+ *result = (guint64)long_value;
+ return TRUE;
+
+overflow:
+ PyErr_Clear ();
+ max = pygi_guint64_to_py (G_MAXUINT64);
+ PyErr_Format (
+ PyExc_OverflowError, "%S not in range %ld to %S",
+ number, (long)0, max);
+ Py_DECREF (number);
+ Py_DECREF (max);
+ return FALSE;
+}
+
+PyObject *
+pygi_guint64_to_py (guint64 value)
+{
+ if (value <= LONG_MAX)
+ return PyLong_FromLong((long) value);
+ else
+ return PyLong_FromUnsignedLongLong (value);
+}
+
+gboolean
+pygi_marshal_from_py_basic_type (PyObject *object, /* in */
+ GIArgument *arg, /* out */
+ GITypeTag type_tag,
+ GITransfer transfer,
+ gpointer *cleanup_data /* out */)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_VOID:
+ g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
+ if (pygi_gpointer_from_py (object, &(arg->v_pointer))) {
+ *cleanup_data = arg->v_pointer;
+ return TRUE;
+ }
+ return FALSE;
+
+ case GI_TYPE_TAG_INT8:
+ return pygi_gint8_from_py (object, &(arg->v_int8));
+
+ case GI_TYPE_TAG_UINT8:
+ return pygi_guint8_from_py (object, &(arg->v_uint8));
+
+ case GI_TYPE_TAG_INT16:
+ return pygi_gint16_from_py (object, &(arg->v_int16));
+
+ case GI_TYPE_TAG_UINT16:
+ return pygi_guint16_from_py (object, &(arg->v_uint16));
+
+ case GI_TYPE_TAG_INT32:
+ return pygi_gint32_from_py (object, &(arg->v_int32));
+
+ case GI_TYPE_TAG_UINT32:
+ return pygi_guint32_from_py (object, &(arg->v_uint32));
+
+ case GI_TYPE_TAG_INT64:
+ return pygi_gint64_from_py (object, &(arg->v_int64));
+
+ case GI_TYPE_TAG_UINT64:
+ return pygi_guint64_from_py (object, &(arg->v_uint64));
+
+ case GI_TYPE_TAG_BOOLEAN:
+ return pygi_gboolean_from_py (object, &(arg->v_boolean));
+
+ case GI_TYPE_TAG_FLOAT:
+ return pygi_gfloat_from_py (object, &(arg->v_float));
+
+ case GI_TYPE_TAG_DOUBLE:
+ return pygi_gdouble_from_py (object, &(arg->v_double));
+
+ case GI_TYPE_TAG_GTYPE:
+ return pygi_gtype_from_py (object, &(arg->v_size));
+
+ case GI_TYPE_TAG_UNICHAR:
+ return pygi_gunichar_from_py (object, &(arg->v_uint32));
+
+ case GI_TYPE_TAG_UTF8:
+ if (pygi_utf8_from_py (object, &(arg->v_string))) {
+ *cleanup_data = arg->v_string;
+ return TRUE;
+ }
+ return FALSE;
+
+ case GI_TYPE_TAG_FILENAME:
+ if (pygi_filename_from_py (object, &(arg->v_string))) {
+ *cleanup_data = arg->v_string;
+ return TRUE;
+ }
+ return FALSE;
+
+ default:
+ PyErr_Format (PyExc_TypeError, "Type tag %d not supported",
+ type_tag);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+pygi_marshal_from_py_basic_type_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ return pygi_marshal_from_py_basic_type (py_arg,
+ arg,
+ arg_cache->type_tag,
+ arg_cache->transfer,
+ cleanup_data);
+}
+
+static void
+marshal_cleanup_from_py_utf8 (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ /* We strdup strings so free unless ownership is transferred to C. */
+ if (was_processed && arg_cache->transfer == GI_TRANSFER_NOTHING)
+ g_free (data);
+}
+
+static PyObject *
+marshal_to_py_void (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ if (arg_cache->is_pointer) {
+ return PyLong_FromVoidPtr (arg->v_pointer);
+ }
+ Py_RETURN_NONE;
+}
+
+PyObject *
+pygi_utf8_to_py (gchar *value)
+{
+ if (value == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ return PyUnicode_FromString (value);
+}
+
+PyObject *
+pygi_filename_to_py (gchar *value)
+{
+ PyObject *py_obj;
+
+ if (value == NULL) {
+ Py_RETURN_NONE;
+ }
+
+#ifdef G_OS_WIN32
+ py_obj = PyUnicode_DecodeUTF8 (value, strlen(value),
+ "surrogatepass");
+#else
+ py_obj = PyUnicode_DecodeFSDefault (value);
+#endif
+
+ return py_obj;
+}
+
+/**
+ * pygi_marshal_to_py_basic_type:
+ * @arg: The argument to convert to an object.
+ * @type_tag: Type tag for @arg
+ * @transfer: Transfer annotation
+ *
+ * Convert the given argument to a Python object. This function
+ * is restricted to simple types that only require the GITypeTag
+ * and GITransfer. For a more complete conversion routine, use:
+ * _pygi_argument_to_object.
+ *
+ * Returns: A PyObject representing @arg or NULL if it cannot convert
+ * the argument.
+ */
+PyObject *
+pygi_marshal_to_py_basic_type (GIArgument *arg,
+ GITypeTag type_tag,
+ GITransfer transfer)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_BOOLEAN:
+ return pygi_gboolean_to_py (arg->v_boolean);
+
+ case GI_TYPE_TAG_INT8:
+ return pygi_gint8_to_py (arg->v_int8);
+
+ case GI_TYPE_TAG_UINT8:
+ return pygi_guint8_to_py (arg->v_uint8);
+
+ case GI_TYPE_TAG_INT16:
+ return pygi_gint16_to_py (arg->v_int16);
+
+ case GI_TYPE_TAG_UINT16:
+ return pygi_guint16_to_py (arg->v_uint16);
+
+ case GI_TYPE_TAG_INT32:
+ return pygi_gint32_to_py (arg->v_int32);
+
+ case GI_TYPE_TAG_UINT32:
+ return pygi_guint32_to_py (arg->v_uint32);
+
+ case GI_TYPE_TAG_INT64:
+ return pygi_gint64_to_py (arg->v_int64);
+
+ case GI_TYPE_TAG_UINT64:
+ return pygi_guint64_to_py (arg->v_uint64);
+
+ case GI_TYPE_TAG_FLOAT:
+ return pygi_gfloat_to_py (arg->v_float);
+
+ case GI_TYPE_TAG_DOUBLE:
+ return pygi_gdouble_to_py (arg->v_double);
+
+ case GI_TYPE_TAG_GTYPE:
+ return pyg_type_wrapper_new ( (GType) arg->v_size);
+
+ case GI_TYPE_TAG_UNICHAR:
+ return pygi_gunichar_to_py (arg->v_uint32);
+
+ case GI_TYPE_TAG_UTF8:
+ return pygi_utf8_to_py (arg->v_string);
+
+ case GI_TYPE_TAG_FILENAME:
+ return pygi_filename_to_py (arg->v_string);
+
+ default:
+ PyErr_Format (PyExc_TypeError, "Type tag %d not supported",
+ type_tag);
+ return NULL;
+ }
+}
+
+PyObject *
+pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ return pygi_marshal_to_py_basic_type (arg,
+ arg_cache->type_tag,
+ arg_cache->transfer);
+}
+
+static void
+marshal_cleanup_to_py_utf8 (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer cleanup_data,
+ gpointer data,
+ gboolean was_processed)
+{
+ /* Python copies the string so we need to free it
+ if the interface is transfering ownership,
+ whether or not it has been processed yet */
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
+ g_free (data);
+}
+
+static gboolean
+arg_basic_type_setup_from_info (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ GITypeTag type_tag = g_type_info_get_tag (type_info);
+
+ if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction))
+ return FALSE;
+
+ switch (type_tag) {
+ case GI_TYPE_TAG_VOID:
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ arg_cache->from_py_marshaller = marshal_from_py_void;
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ arg_cache->to_py_marshaller = marshal_to_py_void;
+
+ break;
+ case GI_TYPE_TAG_BOOLEAN:
+ arg_cache->allow_none = TRUE;
+ /* fall through */
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ case GI_TYPE_TAG_FLOAT:
+ case GI_TYPE_TAG_DOUBLE:
+ case GI_TYPE_TAG_UNICHAR:
+ case GI_TYPE_TAG_GTYPE:
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ arg_cache->from_py_marshaller = pygi_marshal_from_py_basic_type_cache_adapter;
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ arg_cache->to_py_marshaller = pygi_marshal_to_py_basic_type_cache_adapter;
+
+ break;
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ arg_cache->from_py_marshaller = pygi_marshal_from_py_basic_type_cache_adapter;
+ arg_cache->from_py_cleanup = marshal_cleanup_from_py_utf8;
+ }
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ arg_cache->to_py_marshaller = pygi_marshal_to_py_basic_type_cache_adapter;
+ arg_cache->to_py_cleanup = marshal_cleanup_to_py_utf8;
+ }
+
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_basic_type_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ gboolean res = FALSE;
+ PyGIArgCache *arg_cache = pygi_arg_cache_alloc ();
+
+ res = arg_basic_type_setup_from_info (arg_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction);
+ if (res) {
+ return arg_cache;
+ } else {
+ pygi_arg_cache_free (arg_cache);
+ return NULL;
+ }
+}
diff --git a/gi/pygi-basictype.h b/gi/pygi-basictype.h
new file mode 100644
index 0000000..04d520a
--- /dev/null
+++ b/gi/pygi-basictype.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_ARG_BASICTYPE_H__
+#define __PYGI_ARG_BASICTYPE_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+gboolean pygi_marshal_from_py_basic_type (PyObject *object, /* in */
+ GIArgument *arg, /* out */
+ GITypeTag type_tag,
+ GITransfer transfer,
+ gpointer *cleanup_data);
+gboolean pygi_marshal_from_py_basic_type_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data);
+
+PyObject *pygi_marshal_to_py_basic_type (GIArgument *arg, /* in */
+ GITypeTag type_tag,
+ GITransfer transfer);
+PyObject *pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data);
+
+PyGIArgCache *pygi_arg_basic_type_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction);
+
+PyObject *pygi_gint64_to_py (gint64 value);
+PyObject *pygi_guint64_to_py (guint64 value);
+PyObject *pygi_gfloat_to_py (gfloat value);
+PyObject *pygi_gdouble_to_py (gdouble value);
+PyObject *pygi_gboolean_to_py (gboolean value);
+PyObject *pygi_gint8_to_py (gint8 value);
+PyObject *pygi_guint8_to_py (guint8 value);
+PyObject *pygi_utf8_to_py (gchar *value);
+PyObject *pygi_gint_to_py (gint value);
+PyObject *pygi_glong_to_py (glong value);
+PyObject *pygi_guint_to_py (guint value);
+PyObject *pygi_gulong_to_py (gulong value);
+PyObject *pygi_filename_to_py (gchar *value);
+PyObject *pygi_gsize_to_py (gsize value);
+PyObject *pygi_gssize_to_py (gssize value);
+PyObject *pygi_guint32_to_py (guint32 value);
+
+gboolean pygi_gboolean_from_py (PyObject *object, gboolean *result);
+gboolean pygi_gint64_from_py (PyObject *object, gint64 *result);
+gboolean pygi_guint64_from_py (PyObject *object, guint64 *result);
+gboolean pygi_gfloat_from_py (PyObject *py_arg, gfloat *result);
+gboolean pygi_gdouble_from_py (PyObject *py_arg, gdouble *result);
+gboolean pygi_utf8_from_py (PyObject *py_arg, gchar **result);
+gboolean pygi_glong_from_py (PyObject *object, glong *result);
+gboolean pygi_gulong_from_py (PyObject *object, gulong *result);
+gboolean pygi_gint_from_py (PyObject *object, gint *result);
+gboolean pygi_guint_from_py (PyObject *object, guint *result);
+gboolean pygi_gunichar_from_py (PyObject *py_arg, gunichar *result);
+gboolean pygi_gint8_from_py (PyObject *object, gint8 *result);
+gboolean pygi_gschar_from_py (PyObject *object, gint8 *result);
+gboolean pygi_guint8_from_py (PyObject *object, guint8 *result);
+gboolean pygi_guchar_from_py (PyObject *object, guchar *result);
+
+G_END_DECLS
+
+#endif /*__PYGI_ARG_BASICTYPE_H__*/
diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c
index 5bf2c19..9deb62a 100644
--- a/gi/pygi-boxed.c
+++ b/gi/pygi-boxed.c
@@ -16,38 +16,66 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include "pygi-boxed.h"
+#include "pygi-info.h"
+#include "pygboxed.h"
+#include "pygi-type.h"
+#include "pygi-basictype.h"
+#include "pygi-util.h"
-#include <pygobject.h>
#include <girepository.h>
-#include <pyglib-python-compat.h>
+
+struct _PyGIBoxed {
+ PyGBoxed base;
+ gboolean slice_allocated;
+ gsize size;
+};
static void
-_boxed_dealloc (PyGIBoxed *self)
+boxed_clear (PyGIBoxed *self)
{
- GType g_type;
+ gpointer boxed = pyg_boxed_get_ptr (self);
+ GType g_type = ((PyGBoxed *)self)->gtype;
- if ( ( (PyGBoxed *) self)->free_on_dealloc) {
+ if ( ( (PyGBoxed *) self)->free_on_dealloc && boxed != NULL) {
if (self->slice_allocated) {
- g_slice_free1 (self->size, ( (PyGBoxed *) self)->boxed);
+ if (g_type && g_type_is_a (g_type, G_TYPE_VALUE))
+ g_value_unset (boxed);
+ g_slice_free1 (self->size, boxed);
+ self->slice_allocated = FALSE;
+ self->size = 0;
} else {
- g_type = pyg_type_from_object ( (PyObject *) self);
- g_boxed_free (g_type, ( (PyGBoxed *) self)->boxed);
+ g_boxed_free (g_type, boxed);
}
}
+ pyg_boxed_set_ptr (self, NULL);
+}
- Py_TYPE( (PyGObject *) self)->tp_free ( (PyObject *) self);
+static PyObject *
+boxed_clear_wrapper (PyGIBoxed *self)
+{
+ boxed_clear (self);
+
+ Py_RETURN_NONE;
+}
+
+
+static void
+boxed_dealloc (PyGIBoxed *self)
+{
+ boxed_clear (self);
+
+ Py_TYPE (self)->tp_free ((PyObject *)self);
}
void *
-_pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
+pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
{
- gsize size;
+ gpointer boxed = NULL;
+ gsize size = 0;
switch (g_base_info_get_type (info)) {
case GI_INFO_TYPE_UNION:
@@ -64,28 +92,33 @@ _pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
return NULL;
}
+ if (size == 0) {
+ PyErr_Format (PyExc_TypeError,
+ "boxed cannot be created directly; try using a constructor, see: help(%s.%s)",
+ g_base_info_get_namespace (info),
+ g_base_info_get_name (info));
+ return NULL;
+ }
+
if( size_out != NULL)
*size_out = size;
- return g_slice_alloc0 (size);
+ boxed = g_slice_alloc0 (size);
+ if (boxed == NULL)
+ PyErr_NoMemory();
+ return boxed;
}
static PyObject *
-_boxed_new (PyTypeObject *type,
+boxed_new (PyTypeObject *type,
PyObject *args,
PyObject *kwargs)
{
- static char *kwlist[] = { NULL };
-
GIBaseInfo *info;
gsize size = 0;
gpointer boxed;
PyGIBoxed *self = NULL;
- if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) {
- return NULL;
- }
-
info = _pygi_object_get_gi_info ( (PyObject *) type, &PyGIBaseInfo_Type);
if (info == NULL) {
if (PyErr_ExceptionMatches (PyExc_AttributeError)) {
@@ -94,13 +127,12 @@ _boxed_new (PyTypeObject *type,
return NULL;
}
- boxed = _pygi_boxed_alloc (info, &size);
+ boxed = pygi_boxed_alloc (info, &size);
if (boxed == NULL) {
- PyErr_NoMemory();
goto out;
}
- self = (PyGIBoxed *) _pygi_boxed_new (type, boxed, TRUE, size);
+ self = (PyGIBoxed *) pygi_boxed_new (type, boxed, TRUE, size);
if (self == NULL) {
g_slice_free1 (size, boxed);
goto out;
@@ -116,21 +148,30 @@ out:
}
static int
-_boxed_init (PyObject *self,
+boxed_init (PyObject *self,
PyObject *args,
PyObject *kwargs)
{
+ static char *kwlist[] = { NULL };
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) {
+ PyErr_Clear ();
+ PyErr_Warn (PyExc_DeprecationWarning,
+ "Passing arguments to gi.types.Boxed.__init__() is deprecated. "
+ "All arguments passed will be ignored.");
+ }
+
/* Don't call PyGBoxed's init, which raises an exception. */
return 0;
}
-PYGLIB_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed);
+PYGI_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed);
PyObject *
-_pygi_boxed_new (PyTypeObject *type,
- gpointer boxed,
- gboolean free_on_dealloc,
- gsize allocated_slice)
+pygi_boxed_new (PyTypeObject *type,
+ gpointer boxed,
+ gboolean free_on_dealloc,
+ gsize allocated_slice)
{
PyGIBoxed *self;
@@ -149,8 +190,8 @@ _pygi_boxed_new (PyTypeObject *type,
}
( (PyGBoxed *) self)->gtype = pyg_type_from_object ( (PyObject *) type);
- ( (PyGBoxed *) self)->boxed = boxed;
( (PyGBoxed *) self)->free_on_dealloc = free_on_dealloc;
+ pyg_boxed_set_ptr (self, boxed);
if (allocated_slice > 0) {
self->size = allocated_slice;
self->slice_allocated = TRUE;
@@ -162,30 +203,57 @@ _pygi_boxed_new (PyTypeObject *type,
return (PyObject *) self;
}
-static PyObject *
-_pygi_boxed_get_free_on_dealloc(PyGIBoxed *self, void *closure)
+/**
+ * pygi_boxed_copy_in_place:
+ *
+ * Replace the boxed pointer held by this wrapper with a boxed copy
+ * freeing the previously held pointer (when free_on_dealloc is TRUE).
+ * This can be used in cases where Python is passed a reference which
+ * it does not own and the wrapper is held by the Python program
+ * longer than the duration of a callback it was passed to.
+ */
+void
+pygi_boxed_copy_in_place (PyGIBoxed *self)
{
- return PyBool_FromLong( ((PyGBoxed *)self)->free_on_dealloc );
+ PyGBoxed *pygboxed = (PyGBoxed *)self;
+ gpointer ptr = pyg_boxed_get_ptr (self);
+ gpointer copy = NULL;
+
+ if (ptr)
+ copy = g_boxed_copy (pygboxed->gtype, ptr);
+
+ boxed_clear (self);
+ pyg_boxed_set_ptr (pygboxed, copy);
+ pygboxed->free_on_dealloc = TRUE;
}
-static PyGetSetDef pygi_boxed_getsets[] = {
- { "_free_on_dealloc", (getter)_pygi_boxed_get_free_on_dealloc, (setter)0 },
- { NULL, 0, 0 }
+static PyMethodDef boxed_methods[] = {
+ { "_clear_boxed", (PyCFunction)boxed_clear_wrapper, METH_NOARGS },
+ { NULL, NULL, 0 }
};
-void
-_pygi_boxed_register_types (PyObject *m)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_boxed_register_types (PyObject *m)
{
- Py_TYPE(&PyGIBoxed_Type) = &PyType_Type;
+ Py_SET_TYPE(&PyGIBoxed_Type, &PyType_Type);
+ g_assert (Py_TYPE (&PyGBoxed_Type) != NULL);
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_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);
- PyGIBoxed_Type.tp_getset = pygi_boxed_getsets;
+ PyGIBoxed_Type.tp_methods = boxed_methods;
- if (PyType_Ready (&PyGIBoxed_Type))
- return;
- if (PyModule_AddObject (m, "Boxed", (PyObject *) &PyGIBoxed_Type))
- return;
+ if (PyType_Ready (&PyGIBoxed_Type) < 0)
+ return -1;
+ Py_INCREF ((PyObject *) &PyGIBoxed_Type);
+ if (PyModule_AddObject (m, "Boxed", (PyObject *) &PyGIBoxed_Type) < 0) {
+ Py_DECREF ((PyObject *) &PyGIBoxed_Type);
+ return -1;
+ }
+
+ return 0;
}
diff --git a/gi/pygi-boxed.h b/gi/pygi-boxed.h
index 38ac928..18c4448 100644
--- a/gi/pygi-boxed.h
+++ b/gi/pygi-boxed.h
@@ -14,29 +14,32 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_BOXED_H__
#define __PYGI_BOXED_H__
#include <Python.h>
+#include <girepository.h>
+#include "pygobject-internal.h"
G_BEGIN_DECLS
+typedef struct _PyGIBoxed PyGIBoxed;
+
extern PyTypeObject PyGIBoxed_Type;
-PyObject * _pygi_boxed_new (PyTypeObject *type,
- gpointer boxed,
- gboolean free_on_dealloc,
- gsize allocated_slice);
+PyObject * pygi_boxed_new (PyTypeObject *type,
+ gpointer boxed,
+ gboolean free_on_dealloc,
+ gsize allocated_slice);
+
+void * pygi_boxed_alloc (GIBaseInfo *info, gsize *size);
-void * _pygi_boxed_alloc (GIBaseInfo *info,
- gsize *size);
+void pygi_boxed_copy_in_place (PyGIBoxed *self);
-void _pygi_boxed_register_types (PyObject *m);
+int pygi_boxed_register_types (PyObject *m);
G_END_DECLS
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 2f807f8..c6630de 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -2,6 +2,7 @@
* vim: tabstop=4 shiftwidth=4 expandtab
*
* Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -14,37 +15,99 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <Python.h>
+#include <girepository.h>
+
+#include "pygi-type.h"
#include "pygi-info.h"
#include "pygi-cache.h"
-#include "pygi-marshal-to-py.h"
-#include "pygi-marshal-from-py.h"
#include "pygi-marshal-cleanup.h"
#include "pygi-type.h"
-#include <girepository.h>
+#include "pygi-hashtable.h"
+#include "pygi-basictype.h"
+#include "pygi-list.h"
+#include "pygi-array.h"
+#include "pygi-closure.h"
+#include "pygi-error.h"
+#include "pygi-object.h"
+#include "pygi-struct-marshal.h"
+#include "pygi-enum-marshal.h"
+#include "pygi-resulttuple.h"
+#include "pygi-invoke.h"
+
+
+/* _arg_info_default_value
+ * info:
+ * arg: (out): GIArgument to fill in with default value.
+ *
+ * This is currently a place holder API which only supports "allow-none" pointer args.
+ * Once defaults are part of the GI API, we can replace this with: g_arg_info_default_value
+ * https://bugzilla.gnome.org/show_bug.cgi?id=558620
+ *
+ * Returns: TRUE if the given argument supports a default value and was filled in.
+ */
+static gboolean
+_arg_info_default_value (GIArgInfo *info, GIArgument *arg)
+{
+ if (g_arg_info_may_be_null (info)) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+ return FALSE;
+}
-PyGIArgCache * _arg_cache_new (GITypeInfo *type_info,
- PyGICallableCache *callable_cache,
- GIArgInfo *arg_info,
- GITransfer transfer,
- PyGIDirection direction,
- gssize c_arg_index,
- gssize py_arg_index);
-
-PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
- PyGICallableCache *callable_cache,
- GIArgInfo *arg_info,
- GITransfer transfer,
- PyGIDirection direction,
- gssize c_arg_index,
- gssize py_arg_index);
-/* cleanup */
-static void
-_pygi_arg_cache_free (PyGIArgCache *cache)
+/* pygi_arg_base_setup:
+ * arg_cache: argument cache to initialize
+ * type_info: source for type related attributes to cache
+ * arg_info: (allow-none): source for argument related attributes to cache
+ * transfer: transfer mode to store in the argument cache
+ * direction: marshaling direction to store in the cache
+ *
+ * Initializer for PyGIArgCache
+ *
+ * Returns: TRUE on success and FALSE on failure
+ */
+gboolean
+pygi_arg_base_setup (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ arg_cache->direction = direction;
+ arg_cache->transfer = transfer;
+ arg_cache->py_arg_index = -1;
+ arg_cache->c_arg_index = -1;
+
+ if (type_info != NULL) {
+ arg_cache->is_pointer = g_type_info_is_pointer (type_info);
+ arg_cache->type_tag = g_type_info_get_tag (type_info);
+ g_base_info_ref ( (GIBaseInfo *) type_info);
+ arg_cache->type_info = type_info;
+ }
+
+ if (arg_info != NULL) {
+ if (!arg_cache->has_default) {
+ /* It is possible has_default was set somewhere else */
+ arg_cache->has_default = _arg_info_default_value (arg_info,
+ &arg_cache->default_value);
+ }
+ arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
+ arg_cache->allow_none = g_arg_info_may_be_null (arg_info);
+
+ if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE || arg_cache->type_tag == GI_TYPE_TAG_ARRAY)
+ arg_cache->is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
+ else
+ arg_cache->is_caller_allocates = FALSE;
+ }
+ return TRUE;
+}
+
+void
+pygi_arg_cache_free (PyGIArgCache *cache)
{
if (cache == NULL)
return;
@@ -57,6 +120,8 @@ _pygi_arg_cache_free (PyGIArgCache *cache)
g_slice_free (PyGIArgCache, cache);
}
+/* PyGIInterfaceCache */
+
static void
_interface_cache_free_func (PyGIInterfaceCache *cache)
{
@@ -70,1136 +135,1050 @@ _interface_cache_free_func (PyGIInterfaceCache *cache)
}
}
-static void
-_hash_cache_free_func (PyGIHashCache *cache)
+/* pygi_arg_interface_setup:
+ * arg_cache: argument cache to initialize
+ * type_info: source for type related attributes to cache
+ * arg_info: (allow-none): source for argument related attributes to cache
+ * transfer: transfer mode to store in the argument cache
+ * direction: marshaling direction to store in the cache
+ * iface_info: interface info to cache
+ *
+ * Initializer for PyGIInterfaceCache
+ *
+ * Returns: TRUE on success and FALSE on failure
+ */
+gboolean
+pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info)
{
- if (cache != NULL) {
- _pygi_arg_cache_free (cache->key_cache);
- _pygi_arg_cache_free (cache->value_cache);
- g_slice_free (PyGIHashCache, cache);
+ if (!pygi_arg_base_setup ((PyGIArgCache *)iface_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction)) {
+ return FALSE;
}
-}
-static void
-_sequence_cache_free_func (PyGISequenceCache *cache)
-{
- if (cache != NULL) {
- _pygi_arg_cache_free (cache->item_cache);
- g_slice_free (PyGISequenceCache, cache);
- }
-}
+ ( (PyGIArgCache *)iface_cache)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
-static void
-_callback_cache_free_func (PyGICallbackCache *cache)
-{
- if (cache != NULL) {
- if (cache->interface_info != NULL)
- g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
+ g_base_info_ref ( (GIBaseInfo *)iface_info);
+ iface_cache->interface_info = iface_info;
+ iface_cache->arg_cache.type_tag = GI_TYPE_TAG_INTERFACE;
+ iface_cache->type_name = _pygi_g_base_info_get_fullname (iface_info);
+ iface_cache->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
+ iface_cache->py_type = pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
- g_slice_free (PyGICallbackCache, cache);
+ if (iface_cache->py_type == NULL) {
+ return FALSE;
}
+
+ return TRUE;
}
-void
-_pygi_callable_cache_free (PyGICallableCache *cache)
+PyGIArgCache *
+pygi_arg_interface_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info)
{
- gssize i;
-
- if (cache == NULL)
- return;
-
- g_slist_free (cache->to_py_args);
- g_slist_free (cache->arg_name_list);
- g_hash_table_destroy (cache->arg_name_hash);
+ PyGIInterfaceCache *ic;
- for (i = 0; i < cache->n_args; i++) {
- PyGIArgCache *tmp = cache->args_cache[i];
- _pygi_arg_cache_free (tmp);
+ ic = g_slice_new0 (PyGIInterfaceCache);
+ if (!pygi_arg_interface_setup (ic,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info)) {
+ pygi_arg_cache_free ((PyGIArgCache *)ic);
+ return NULL;
}
- if (cache->return_cache != NULL)
- _pygi_arg_cache_free (cache->return_cache);
- g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
- g_slice_free (PyGICallableCache, cache);
+ return (PyGIArgCache *)ic;
}
-/* cache generation */
+/* PyGISequenceCache */
-static PyGIInterfaceCache *
-_interface_cache_new (GIInterfaceInfo *iface_info)
+static void
+_sequence_cache_free_func (PyGISequenceCache *cache)
{
- PyGIInterfaceCache *ic;
-
- ic = g_slice_new0 (PyGIInterfaceCache);
- ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
- ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
- ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
-
- if (ic->py_type == NULL)
- return NULL;
-
- ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
- return ic;
+ if (cache != NULL) {
+ pygi_arg_cache_free (cache->item_cache);
+ g_slice_free (PyGISequenceCache, cache);
+ }
}
-static PyGISequenceCache *
-_sequence_cache_new (GITypeInfo *type_info,
- GIDirection direction,
- GITransfer transfer,
- gssize child_offset)
+/* pygi_arg_sequence_setup:
+ * sc: sequence cache to initialize
+ * type_info: source for type related attributes to cache
+ * arg_info: (allow-none): source for argument related attributes to cache
+ * transfer: transfer mode to store in the argument cache
+ * direction: marshaling direction to store in the cache
+ * iface_info: interface info to cache
+ *
+ * Initializer for PyGISequenceCache used for holding list and array argument
+ * caches.
+ *
+ * Returns: TRUE on success and FALSE on failure
+ */
+gboolean
+pygi_arg_sequence_setup (PyGISequenceCache *sc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
{
- PyGISequenceCache *sc;
GITypeInfo *item_type_info;
GITransfer item_transfer;
- sc = g_slice_new0 (PyGISequenceCache);
- ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
-
- sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
- sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
- sc->len_arg_index = g_type_info_get_array_length (type_info);
- if (sc->len_arg_index >= 0)
- sc->len_arg_index += child_offset;
+ if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
+ type_info,
+ arg_info,
+ transfer,
+ direction)) {
+ return FALSE;
+ }
+ sc->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
item_type_info = g_type_info_get_param_type (type_info, 0);
-
item_transfer =
transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
- sc->item_cache = _arg_cache_new (item_type_info,
- NULL,
- NULL,
- item_transfer,
- direction,
- 0, 0);
+ sc->item_cache = pygi_arg_cache_new (item_type_info,
+ NULL,
+ item_transfer,
+ direction,
+ callable_cache,
+ 0, 0);
- if (sc->item_cache == NULL) {
- _pygi_arg_cache_free ( (PyGIArgCache *)sc);
- return NULL;
- }
-
- sc->item_size = _pygi_g_type_info_size (item_type_info);
g_base_info_unref ( (GIBaseInfo *)item_type_info);
- return sc;
-}
-static PyGIHashCache *
-_hash_cache_new (GITypeInfo *type_info,
- GIDirection direction,
- GITransfer transfer)
-{
- PyGIHashCache *hc;
- GITypeInfo *key_type_info;
- GITypeInfo *value_type_info;
- GITransfer item_transfer;
-
- hc = g_slice_new0 (PyGIHashCache);
- ( (PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
- key_type_info = g_type_info_get_param_type (type_info, 0);
- value_type_info = g_type_info_get_param_type (type_info, 1);
-
- item_transfer =
- transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
-
- hc->key_cache = _arg_cache_new (key_type_info,
- NULL,
- NULL,
- item_transfer,
- direction,
- 0, 0);
-
- if (hc->key_cache == NULL) {
- _pygi_arg_cache_free ( (PyGIArgCache *)hc);
- return NULL;
- }
-
- hc->value_cache = _arg_cache_new (value_type_info,
- NULL,
- NULL,
- item_transfer,
- direction,
- 0, 0);
-
- if (hc->value_cache == NULL) {
- _pygi_arg_cache_free ( (PyGIArgCache *)hc);
- return NULL;
+ if (sc->item_cache == NULL) {
+ return FALSE;
}
- g_base_info_unref( (GIBaseInfo *)key_type_info);
- g_base_info_unref( (GIBaseInfo *)value_type_info);
-
- return hc;
+ return TRUE;
}
-static PyGICallbackCache *
-_callback_cache_new (GIArgInfo *arg_info,
- GIInterfaceInfo *iface_info,
- gssize child_offset)
+PyGIArgCache *
+pygi_arg_cache_alloc (void)
{
- PyGICallbackCache *cc;
-
- cc = g_slice_new0 (PyGICallbackCache);
- ( (PyGIArgCache *)cc)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;
-
- cc->user_data_index = g_arg_info_get_closure (arg_info);
- if (cc->user_data_index != -1)
- cc->user_data_index += child_offset;
- cc->destroy_notify_index = g_arg_info_get_destroy (arg_info);
- if (cc->destroy_notify_index != -1)
- cc->destroy_notify_index += child_offset;
- cc->scope = g_arg_info_get_scope (arg_info);
- g_base_info_ref( (GIBaseInfo *)iface_info);
- cc->interface_info = iface_info;
- return cc;
+ return g_slice_new0 (PyGIArgCache);
}
static PyGIArgCache *
-_arg_cache_alloc (void)
+_arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
{
- return g_slice_new0 (PyGIArgCache);
-}
+ GIInfoType info_type;
-static void
-_arg_cache_from_py_basic_type_setup (PyGIArgCache *arg_cache)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
-}
+ info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);
-static void
-_arg_cache_to_py_basic_type_setup (PyGIArgCache *arg_cache)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
-}
+ switch (info_type) {
+ case GI_INFO_TYPE_CALLBACK:
+ return pygi_arg_callback_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info,
+ callable_cache);
+ case GI_INFO_TYPE_OBJECT:
+ case GI_INFO_TYPE_INTERFACE:
+ return pygi_arg_gobject_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info,
+ callable_cache);
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_UNION:
+ return pygi_arg_struct_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ case GI_INFO_TYPE_ENUM:
+ return pygi_arg_enum_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ case GI_INFO_TYPE_FLAGS:
+ return pygi_arg_flags_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ default:
+ g_assert_not_reached ();
+ }
-static void
-_arg_cache_from_py_void_setup (PyGIArgCache *arg_cache)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_void;
+ return NULL;
}
-static void
-_arg_cache_to_py_void_setup (PyGIArgCache *arg_cache)
+PyGIArgCache *
+pygi_arg_cache_new (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache,
+ gssize c_arg_index,
+ gssize py_arg_index)
{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_void;
-}
+ PyGIArgCache *arg_cache = NULL;
+ GITypeTag type_tag;
-static void
-_arg_cache_from_py_utf8_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_utf8;
-}
+ type_tag = g_type_info_get_tag (type_info);
-static void
-_arg_cache_to_py_utf8_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
- arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
-}
+ switch (type_tag) {
+ case GI_TYPE_TAG_VOID:
+ case GI_TYPE_TAG_BOOLEAN:
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ case GI_TYPE_TAG_FLOAT:
+ case GI_TYPE_TAG_DOUBLE:
+ case GI_TYPE_TAG_UNICHAR:
+ case GI_TYPE_TAG_GTYPE:
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ arg_cache = pygi_arg_basic_type_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction);
+ break;
-static gboolean
-_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
- PyGICallableCache *callable_cache,
- GITypeInfo *type_info,
- GITransfer transfer,
- PyGIDirection direction,
- gssize arg_index)
-{
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
- seq_cache->array_type = g_type_info_get_array_type (type_info);
+ case GI_TYPE_TAG_ARRAY:
+ {
+ arg_cache = pygi_arg_garray_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache);
+ if (arg_cache == NULL)
+ return NULL;
+
+ pygi_arg_garray_len_arg_setup (arg_cache,
+ type_info,
+ callable_cache,
+ direction,
+ c_arg_index,
+ &py_arg_index);
+ }
+ break;
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
+ case GI_TYPE_TAG_GLIST:
+ arg_cache = pygi_arg_glist_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache);
+ break;
- if (seq_cache->len_arg_index >= 0) {
- PyGIArgCache *child_cache =
- callable_cache->args_cache[seq_cache->len_arg_index];
+ case GI_TYPE_TAG_GSLIST:
+ arg_cache = pygi_arg_gslist_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache);
+ break;
- if (child_cache == NULL) {
- child_cache = _arg_cache_alloc ();
- } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
- child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
- return TRUE;
- }
+ case GI_TYPE_TAG_GHASH:
+ arg_cache = pygi_arg_hash_table_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache);
+ break;
- if (seq_cache->len_arg_index < arg_index)
- child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE;
- else
- child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
+ arg_cache = _arg_cache_new_for_interface (interface_info,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache);
- child_cache->direction = direction;
- child_cache->to_py_marshaller = NULL;
- child_cache->from_py_marshaller = NULL;
+ g_base_info_unref ( (GIBaseInfo *)interface_info);
+ }
+ break;
- callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
+ case GI_TYPE_TAG_ERROR:
+ arg_cache = pygi_arg_gerror_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction);
+ break;
+ default:
+ break;
}
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
-
- return TRUE;
-}
-
-static gboolean
-_arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
- PyGICallableCache *callable_cache,
- GITypeInfo *type_info,
- GITransfer transfer,
- PyGIDirection direction,
- gssize arg_index)
-{
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
- arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
-
- seq_cache->array_type = g_type_info_get_array_type (type_info);
-
- if (seq_cache->len_arg_index >= 0) {
- PyGIArgCache *child_cache = callable_cache->args_cache[seq_cache->len_arg_index];
- if (seq_cache->len_arg_index < arg_index)
- callable_cache->n_to_py_child_args++;
-
- if (child_cache != NULL) {
- callable_cache->to_py_args =
- g_slist_remove (callable_cache->to_py_args, child_cache);
-
- if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
- child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE)
- return TRUE;
- } else {
- child_cache = _arg_cache_alloc ();
- }
-
- child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
- child_cache->direction = direction;
- child_cache->to_py_marshaller = NULL;
- child_cache->from_py_marshaller = NULL;
-
- callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
+ if (arg_cache != NULL) {
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
}
- return TRUE;
+ return arg_cache;
}
-static void
-_arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
-}
+/* PyGICallableCache */
-static void
-_arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
+static PyGIDirection
+_pygi_get_direction (PyGICallableCache *callable_cache, GIDirection gi_direction)
{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
- arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
+ /* For vfuncs and callbacks our marshalling directions are reversed */
+ if (gi_direction == GI_DIRECTION_INOUT) {
+ return PYGI_DIRECTION_BIDIRECTIONAL;
+ } else if (gi_direction == GI_DIRECTION_IN) {
+ if (callable_cache->calling_context != PYGI_CALLING_CONTEXT_IS_FROM_PY)
+ return PYGI_DIRECTION_TO_PYTHON;
+ return PYGI_DIRECTION_FROM_PYTHON;
+ } else {
+ if (callable_cache->calling_context != PYGI_CALLING_CONTEXT_IS_FROM_PY)
+ return PYGI_DIRECTION_FROM_PYTHON;
+ return PYGI_DIRECTION_TO_PYTHON;
+ }
}
-static void
-_arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
+/* Generate the cache for the callable's arguments */
+static gboolean
+_callable_cache_generate_args_cache_real (PyGICallableCache *callable_cache,
+ GICallableInfo *callable_info)
{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
-}
+ gint i;
+ guint arg_index;
+ GITypeInfo *return_info;
+ GITransfer return_transfer;
+ PyGIArgCache *return_cache;
+ PyGIDirection return_direction;
+ gssize last_explicit_arg_index;
+ PyObject *tuple_names;
+ GSList *arg_cache_item;
+ PyTypeObject* resulttuple_type;
-static void
-_arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
- arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
-}
+ /* Return arguments are always considered out */
+ return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
-static void
-_arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash;
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash;
-}
+ /* cache the return arg */
+ return_info =
+ g_callable_info_get_return_type (callable_info);
+ return_transfer =
+ g_callable_info_get_caller_owns (callable_info);
+ return_cache =
+ pygi_arg_cache_new (return_info,
+ NULL,
+ return_transfer,
+ return_direction,
+ callable_cache,
+ -1,
+ -1);
+ if (return_cache == NULL)
+ return FALSE;
-static void
-_arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash;
- arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash;
-}
+ return_cache->is_skipped = g_callable_info_skip_return (callable_info);
+ callable_cache->return_cache = return_cache;
+ g_base_info_unref (return_info);
-static void
-_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
- arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
-}
+ callable_cache->user_data_index = -1;
-static void
-_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
- arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
-}
+ for (i = 0, arg_index = (guint)callable_cache->args_offset;
+ arg_index < _pygi_callable_cache_args_len (callable_cache);
+ i++, arg_index++) {
+ PyGIArgCache *arg_cache = NULL;
+ GIArgInfo *arg_info;
+ PyGIDirection direction;
-static void
-_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
-}
+ arg_info = g_callable_info_get_arg (callable_info, i);
-static void
-_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
-}
+ /* This only happens when dealing with callbacks */
+ if (g_arg_info_get_closure (arg_info) == i) {
+ callable_cache->user_data_index = i;
-static void
-_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
- GIInterfaceInfo *iface_info,
- GITransfer transfer)
-{
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
-
- if (iface_cache->g_type == G_TYPE_VALUE)
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
- else if (iface_cache->is_foreign)
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
-}
+ arg_cache = pygi_arg_cache_alloc ();
+ _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
-static void
-_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
- GIInterfaceInfo *iface_info,
- GITransfer transfer)
-{
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
+ direction = _pygi_get_direction (callable_cache, GI_DIRECTION_IN);
+ arg_cache->direction = direction;
+ arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
+ arg_cache->c_arg_index = i;
+ arg_cache->is_pointer = TRUE;
- if (iface_cache->is_foreign)
- arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
-}
+ } else {
+ GITypeInfo *type_info;
+
+ direction = _pygi_get_direction (callable_cache,
+ g_arg_info_get_direction (arg_info));
+ type_info = g_arg_info_get_type (arg_info);
+
+ /* must be an child arg filled in by its owner
+ * and continue
+ * fill in it's c_arg_index, add to the in count
+ */
+ arg_cache = _pygi_callable_cache_get_arg (callable_cache, arg_index);
+ if (arg_cache != NULL) {
+ /* ensure c_arg_index always aligns with callable_cache->args_cache
+ * and all of the various PyGIInvokeState arrays. */
+ arg_cache->c_arg_index = arg_index;
+
+ if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) {
+ arg_cache->py_arg_index = callable_cache->n_py_args;
+ callable_cache->n_py_args++;
+ }
-static void
-_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
-}
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ callable_cache->n_to_py_args++;
+ }
-static void
-_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object_cache_adapter;
- arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
-}
+ arg_cache->type_tag = g_type_info_get_tag (type_info);
-static void
-_arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
- PyGICallableCache *callable_cache)
-{
- PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
- if (callback_cache->user_data_index >= 0) {
- PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
- user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
- user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
- callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
- }
+ } else {
+ GITransfer transfer;
+ gssize py_arg_index = -1;
- if (callback_cache->destroy_notify_index >= 0) {
- PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
- destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
- destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
- callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
- }
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
-}
+ transfer = g_arg_info_get_ownership_transfer (arg_info);
-static void
-_arg_cache_to_py_interface_callback_setup (void)
-{
- PyErr_Format(PyExc_NotImplementedError,
- "Callback returns are not supported");
-}
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ py_arg_index = callable_cache->n_py_args;
+ callable_cache->n_py_args++;
+ }
-static void
-_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
-}
+ arg_cache =
+ pygi_arg_cache_new (type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache,
+ arg_index,
+ py_arg_index);
+
+ if (arg_cache == NULL) {
+ g_base_info_unref( (GIBaseInfo *)type_info);
+ g_base_info_unref( (GIBaseInfo *)arg_info);
+ return FALSE;
+ }
-static void
-_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
-}
-static void
-_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
-}
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ callable_cache->n_to_py_args++;
-static void
-_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
-}
+ callable_cache->to_py_args =
+ g_slist_append (callable_cache->to_py_args, arg_cache);
+ }
-PyGIArgCache *
-_arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
- PyGICallableCache *callable_cache,
- GIArgInfo *arg_info,
- GITransfer transfer,
- PyGIDirection direction,
- gssize c_arg_index,
- gssize py_arg_index)
-{
- PyGIInterfaceCache *iface_cache = NULL;
- PyGIArgCache *arg_cache = NULL;
- gssize child_offset = 0;
- GIInfoType info_type;
+ _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
+ }
- if (callable_cache != NULL)
- child_offset =
- (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
- callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
+ g_base_info_unref (type_info);
+ }
- info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);
+ /* Ensure arguments always have a name when available */
+ arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
- /* Callbacks are special cased */
- if (info_type != GI_INFO_TYPE_CALLBACK) {
- iface_cache = _interface_cache_new (iface_info);
+ g_base_info_unref ( (GIBaseInfo *)arg_info);
- arg_cache = (PyGIArgCache *)iface_cache;
- if (arg_cache == NULL)
- return NULL;
}
- switch (info_type) {
- case GI_INFO_TYPE_UNION:
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
-
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
-
- break;
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_STRUCT:
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_interface_struct_setup (arg_cache,
- iface_info,
- transfer);
-
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_interface_struct_setup (arg_cache,
- iface_info,
- transfer);
- break;
- case GI_INFO_TYPE_OBJECT:
- case GI_INFO_TYPE_INTERFACE:
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
-
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
-
- break;
- case GI_INFO_TYPE_CALLBACK:
- {
- PyGICallbackCache *callback_cache;
+ if (callable_cache->arg_name_hash == NULL) {
+ callable_cache->arg_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ } else {
+ g_hash_table_remove_all (callable_cache->arg_name_hash);
+ }
+ callable_cache->n_py_required_args = 0;
+ callable_cache->user_data_varargs_index = -1;
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
- _arg_cache_to_py_interface_callback_setup ();
- return NULL;
- }
+ last_explicit_arg_index = -1;
- callback_cache =
- _callback_cache_new (arg_info,
- iface_info,
- child_offset);
+ /* Reverse loop through all the arguments to setup arg_name_list/hash
+ * and find the number of required arguments */
+ for (i=(_pygi_callable_cache_args_len (callable_cache))-1; i >= 0; i--) {
+ PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache, i);
- arg_cache = (PyGIArgCache *)callback_cache;
- if (arg_cache == NULL)
- return NULL;
+ if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
+ arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
+ arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache);
+ /* Setup arg_name_list and arg_name_hash */
+ gpointer arg_name = (gpointer)arg_cache->arg_name;
+ callable_cache->arg_name_list = g_slist_prepend (callable_cache->arg_name_list,
+ arg_name);
+ if (arg_name != NULL) {
+ g_hash_table_insert (callable_cache->arg_name_hash,
+ arg_name,
+ GINT_TO_POINTER(i));
+ }
- break;
+ /* The first tail argument without a default will force all the preceding
+ * argument defaults off. This limits support of default args to the
+ * tail of an args list.
+ */
+ if (callable_cache->n_py_required_args > 0) {
+ arg_cache->has_default = FALSE;
+ callable_cache->n_py_required_args += 1;
+ } else if (!arg_cache->has_default) {
+ callable_cache->n_py_required_args += 1;
}
- case GI_INFO_TYPE_ENUM:
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
+ if (last_explicit_arg_index == -1) {
+ last_explicit_arg_index = i;
- break;
- case GI_INFO_TYPE_FLAGS:
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
+ /* If the last "from python" argument in the args list is a child
+ * with pyarg (currently only callback user_data). Set it to eat
+ * variable args in the callable cache.
+ */
+ if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG)
+ callable_cache->user_data_varargs_index = i;
+ }
+ }
+ }
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
+ if (!return_cache->is_skipped && return_cache->type_tag != GI_TYPE_TAG_VOID) {
+ callable_cache->has_return = TRUE;
+ }
- break;
- default:
- g_assert_not_reached ();
+ tuple_names = PyList_New (0);
+ if (callable_cache->has_return) {
+ PyList_Append (tuple_names, Py_None);
}
- if (arg_cache != NULL) {
- arg_cache->direction = direction;
- arg_cache->transfer = transfer;
- arg_cache->type_tag = GI_TYPE_TAG_INTERFACE;
- arg_cache->py_arg_index = py_arg_index;
- arg_cache->c_arg_index = c_arg_index;
+ arg_cache_item = callable_cache->to_py_args;
+ while (arg_cache_item) {
+ const gchar *arg_name = ((PyGIArgCache *)arg_cache_item->data)->arg_name;
+ PyObject *arg_string = PyUnicode_FromString (arg_name);
+ PyList_Append (tuple_names, arg_string);
+ Py_DECREF (arg_string);
+ arg_cache_item = arg_cache_item->next;
+ }
- if (iface_cache != NULL) {
- g_base_info_ref ( (GIBaseInfo *)iface_info);
- iface_cache->interface_info = iface_info;
+ /* No need to create a tuple type if there aren't multiple values */
+ if (PyList_Size (tuple_names) > 1) {
+ resulttuple_type = pygi_resulttuple_new_type (tuple_names);
+ if (resulttuple_type == NULL) {
+ Py_DECREF (tuple_names);
+ return FALSE;
+ } else {
+ callable_cache->resulttuple_type = resulttuple_type;
}
}
+ Py_DECREF (tuple_names);
- return arg_cache;
+ return TRUE;
}
-PyGIArgCache *
-_arg_cache_new (GITypeInfo *type_info,
- PyGICallableCache *callable_cache,
- GIArgInfo *arg_info,
- GITransfer transfer,
- PyGIDirection direction,
- gssize c_arg_index,
- gssize py_arg_index)
+static void
+_callable_cache_deinit_real (PyGICallableCache *cache)
{
- PyGIArgCache *arg_cache = NULL;
- gssize child_offset = 0;
- GITypeTag type_tag;
+ g_clear_pointer (&cache->to_py_args, g_slist_free);
+ g_clear_pointer (&cache->arg_name_list, g_slist_free);
+ g_clear_pointer (&cache->arg_name_hash, g_hash_table_unref);
+ g_clear_pointer (&cache->args_cache, g_ptr_array_unref);
+ Py_CLEAR (cache->resulttuple_type);
- type_tag = g_type_info_get_tag (type_info);
+ g_clear_pointer (&cache->return_cache, pygi_arg_cache_free);
+}
- if (callable_cache != NULL)
- child_offset =
- (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
- callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
+static gboolean
+_callable_cache_init (PyGICallableCache *cache,
+ GICallableInfo *callable_info)
+{
+ gint n_args;
+ GIBaseInfo *container;
+
+ if (cache->deinit == NULL)
+ cache->deinit = _callable_cache_deinit_real;
+
+ if (cache->generate_args_cache == NULL)
+ cache->generate_args_cache = _callable_cache_generate_args_cache_real;
+
+ cache->name = g_base_info_get_name ((GIBaseInfo *) callable_info);
+ cache->namespace = g_base_info_get_namespace ((GIBaseInfo *) callable_info);
+ container = g_base_info_get_container ((GIBaseInfo *) callable_info);
+ cache->container_name = NULL;
+ /* https://bugzilla.gnome.org/show_bug.cgi?id=709456 */
+ if (container != NULL && g_base_info_get_type (container) != GI_INFO_TYPE_TYPE) {
+ cache->container_name = g_base_info_get_name (container);
+ }
+ cache->throws = g_callable_info_can_throw_gerror ((GIBaseInfo *) callable_info);
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- arg_cache = _arg_cache_alloc ();
- if (arg_cache == NULL)
- break;
+ if (g_base_info_is_deprecated (callable_info)) {
+ const gchar *deprecated = g_base_info_get_attribute (callable_info, "deprecated");
+ gchar *warning;
+ gchar *full_name = pygi_callable_cache_get_full_name (cache);
+ if (deprecated != NULL)
+ warning = g_strdup_printf ("%s is deprecated: %s",
+ full_name,
+ deprecated);
+ else
+ warning = g_strdup_printf ("%s is deprecated",
+ full_name);
+ g_free (full_name);
+ PyErr_WarnEx (PyExc_DeprecationWarning, warning, 0);
+ g_free (warning);
+ }
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_void_setup (arg_cache);
+ n_args = (gint)cache->args_offset + g_callable_info_get_n_args (callable_info);
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_void_setup (arg_cache);
+ if (n_args >= 0) {
+ cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) pygi_arg_cache_free);
+ g_ptr_array_set_size (cache->args_cache, n_args);
+ }
- break;
- case GI_TYPE_TAG_BOOLEAN:
- case GI_TYPE_TAG_INT8:
- case GI_TYPE_TAG_UINT8:
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_INT64:
- case GI_TYPE_TAG_UINT64:
- case GI_TYPE_TAG_FLOAT:
- case GI_TYPE_TAG_DOUBLE:
- case GI_TYPE_TAG_UNICHAR:
- case GI_TYPE_TAG_GTYPE:
- arg_cache = _arg_cache_alloc ();
- if (arg_cache == NULL)
- break;
+ if (!cache->generate_args_cache (cache, callable_info)) {
+ _callable_cache_deinit_real (cache);
+ return FALSE;
+ }
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_basic_type_setup (arg_cache);
+ return TRUE;
+}
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_basic_type_setup (arg_cache);
+gchar *
+pygi_callable_cache_get_full_name (PyGICallableCache *cache)
+{
+ if (cache->container_name != NULL) {
+ return g_strjoin (".",
+ cache->namespace,
+ cache->container_name,
+ cache->name,
+ NULL);
+ } else {
+ return g_strjoin (".",
+ cache->namespace,
+ cache->name,
+ NULL);
+ }
+}
- break;
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- arg_cache = _arg_cache_alloc ();
- if (arg_cache == NULL)
- break;
+void
+pygi_callable_cache_free (PyGICallableCache *cache)
+{
+ cache->deinit (cache);
+ g_free (cache);
+}
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_utf8_setup (arg_cache, transfer);
+/* PyGIFunctionCache */
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_utf8_setup (arg_cache, transfer);
+static PyObject *
+_function_cache_invoke_real (PyGIFunctionCache *function_cache,
+ PyGIInvokeState *state,
+ PyObject *py_args,
+ PyObject *py_kwargs)
+{
+ return pygi_invoke_c_callable (function_cache, state,
+ py_args, py_kwargs);
+}
- break;
- case GI_TYPE_TAG_ARRAY:
- {
- PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+static void
+_function_cache_deinit_real (PyGICallableCache *callable_cache)
+{
+ g_function_invoker_destroy (&((PyGIFunctionCache *) callable_cache)->invoker);
- arg_cache = (PyGIArgCache *)seq_cache;
- if (arg_cache == NULL)
- break;
+ _callable_cache_deinit_real (callable_cache);
+}
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_array_setup (arg_cache,
- callable_cache,
- type_info,
- transfer,
- direction,
- c_arg_index);
+static gboolean
+_function_cache_init (PyGIFunctionCache *function_cache,
+ GICallableInfo *callable_info)
+{
+ PyGICallableCache *callable_cache = (PyGICallableCache *) function_cache;
+ GIFunctionInvoker *invoker = &function_cache->invoker;
+ GError *error = NULL;
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_array_setup (arg_cache,
- callable_cache,
- type_info,
- transfer,
- direction,
- c_arg_index);
-
- /* ugly edge case code:
- *
- * length can come before the array parameter which means we
- * need to update indexes if this happens
- */
- if (seq_cache->len_arg_index > -1 &&
- callable_cache->args_cache[seq_cache->len_arg_index]->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
- gssize i;
- PyGIArgCache *child_cache =
- callable_cache->args_cache[seq_cache->len_arg_index];
-
- child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
- py_arg_index -= 1;
- callable_cache->n_py_args -= 1;
-
- for (i = seq_cache->len_arg_index + 1;
- i < callable_cache->n_args;
- i++) {
- PyGIArgCache *update_cache = callable_cache->args_cache[i];
- if (update_cache == NULL)
- break;
-
- update_cache->py_arg_index -= 1;
- }
- }
-
- break;
- }
- case GI_TYPE_TAG_GLIST:
- {
- PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+ callable_cache->calling_context = PYGI_CALLING_CONTEXT_IS_FROM_PY;
- arg_cache = (PyGIArgCache *)seq_cache;
- if (arg_cache == NULL)
- break;
+ if (callable_cache->deinit == NULL)
+ callable_cache->deinit = _function_cache_deinit_real;
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_glist_setup (arg_cache, transfer);
+ if (function_cache->invoke == NULL)
+ function_cache->invoke = _function_cache_invoke_real;
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_glist_setup (arg_cache, transfer);
+ if (!_callable_cache_init (callable_cache, callable_info))
+ return FALSE;
+ /* Set by PyGICCallbackCache and PyGIVFuncCache */
+ if (invoker->native_address == NULL) {
+ if (g_function_info_prep_invoker ((GIFunctionInfo *) callable_info,
+ invoker,
+ &error)) {
+ return TRUE;
+ }
+ } else {
+ if (g_function_invoker_new_for_address (invoker->native_address,
+ (GIFunctionInfo *) callable_info,
+ invoker,
+ &error)) {
+ return TRUE;
+ }
+ }
- break;
- }
- case GI_TYPE_TAG_GSLIST:
- {
- PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+ if (!pygi_error_check (&error)) {
+ PyErr_Format (PyExc_RuntimeError,
+ "unknown error creating invoker for %s",
+ g_base_info_get_name ((GIBaseInfo *) callable_info));
+ }
- arg_cache = (PyGIArgCache *)seq_cache;
- if (arg_cache == NULL)
- break;
+ _callable_cache_deinit_real (callable_cache);
+ return FALSE;
+}
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_gslist_setup (arg_cache, transfer);
+PyGIFunctionCache *
+pygi_function_cache_new (GICallableInfo *info)
+{
+ PyGIFunctionCache *function_cache;
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_gslist_setup (arg_cache, transfer);
+ function_cache = g_new0 (PyGIFunctionCache, 1);
- break;
- }
- case GI_TYPE_TAG_GHASH:
- arg_cache =
- (PyGIArgCache *)_hash_cache_new (type_info,
- direction,
- transfer);
+ if (!_function_cache_init (function_cache, info)) {
+ g_free (function_cache);
+ return NULL;
+ }
- if (arg_cache == NULL)
- break;
+ return function_cache;
+}
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_ghash_setup (arg_cache);
+PyObject *
+pygi_function_cache_invoke (PyGIFunctionCache *function_cache,
+ PyObject *py_args,
+ PyObject *py_kwargs)
+{
+ PyGIInvokeState state = { 0, };
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
- _arg_cache_to_py_ghash_setup (arg_cache);
- }
+ return function_cache->invoke (function_cache, &state,
+ py_args, py_kwargs);
+}
- break;
- case GI_TYPE_TAG_INTERFACE:
- {
- GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
- arg_cache = _arg_cache_new_for_interface (interface_info,
- callable_cache,
- arg_info,
- transfer,
- direction,
- c_arg_index,
- py_arg_index);
+/* PyGICCallbackCache */
- g_base_info_unref ( (GIBaseInfo *)interface_info);
- break;
- }
- case GI_TYPE_TAG_ERROR:
- arg_cache = _arg_cache_alloc ();
- if (arg_cache == NULL)
- break;
+PyGIFunctionCache *
+pygi_ccallback_cache_new (GICallableInfo *info,
+ GCallback function_ptr)
+{
+ PyGICCallbackCache *ccallback_cache;
+ PyGIFunctionCache *function_cache;
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_from_py_gerror_setup (arg_cache);
+ ccallback_cache = g_new0 (PyGICCallbackCache, 1);
+ function_cache = (PyGIFunctionCache *) ccallback_cache;
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
- _arg_cache_to_py_gerror_setup (arg_cache);
+ function_cache->invoker.native_address = function_ptr;
- break;
- }
+ if (!_function_cache_init (function_cache, info)) {
+ g_free (ccallback_cache);
+ return NULL;
+ }
- if (arg_cache != NULL) {
- arg_cache->direction = direction;
- arg_cache->transfer = transfer;
- arg_cache->type_tag = type_tag;
- arg_cache->py_arg_index = py_arg_index;
- arg_cache->c_arg_index = c_arg_index;
- arg_cache->is_pointer = g_type_info_is_pointer (type_info);
- g_base_info_ref ( (GIBaseInfo *) type_info);
- arg_cache->type_info = type_info;
- }
+ return function_cache;
+}
- return arg_cache;
+PyObject *
+pygi_ccallback_cache_invoke (PyGICCallbackCache *ccallback_cache,
+ PyObject *py_args,
+ PyObject *py_kwargs,
+ gpointer user_data)
+{
+ PyGIFunctionCache *function_cache = (PyGIFunctionCache *) ccallback_cache;
+ PyGIInvokeState state = { 0, };
+
+ state.user_data = user_data;
+
+ return function_cache->invoke (function_cache, &state,
+ py_args, py_kwargs);
}
-static void
-_arg_name_list_generate (PyGICallableCache *callable_cache)
+/* PyGIConstructorCache */
+
+static PyObject *
+_constructor_cache_invoke_real (PyGIFunctionCache *function_cache,
+ PyGIInvokeState *state,
+ PyObject *py_args,
+ PyObject *py_kwargs)
{
- GSList * arg_name_list = NULL;
- int i;
+ PyGICallableCache *cache = (PyGICallableCache *) function_cache;
+ PyObject *constructor_class;
+ PyObject *ret;
+
+ constructor_class = PyTuple_GetItem (py_args, 0);
+ if (constructor_class == NULL) {
+ gchar *full_name = pygi_callable_cache_get_full_name (cache);
+ PyErr_Clear ();
+ PyErr_Format (PyExc_TypeError,
+ "Constructors require the class to be passed in as an argument, "
+ "No arguments passed to the %s constructor.",
+ full_name);
+ g_free (full_name);
- if (callable_cache->arg_name_hash == NULL) {
- callable_cache->arg_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
- } else {
- g_hash_table_remove_all (callable_cache->arg_name_hash);
+ return FALSE;
}
- for (i=0; i < callable_cache->n_args; i++) {
- PyGIArgCache *arg_cache = NULL;
+ py_args = PyTuple_GetSlice (py_args, 1, PyTuple_Size (py_args));
+ ret = _function_cache_invoke_real (function_cache, state,
+ py_args, py_kwargs);
+ Py_DECREF (py_args);
- arg_cache = callable_cache->args_cache[i];
+ if (ret == NULL || cache->return_cache->is_skipped)
+ return ret;
- if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
- arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
- (arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON ||
- arg_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL)) {
-
- gpointer arg_name = (gpointer)arg_cache->arg_name;
+ if (ret != Py_None) {
+ if (!PyTuple_Check (ret))
+ return ret;
- arg_name_list = g_slist_prepend (arg_name_list, arg_name);
- if (arg_name != NULL) {
- g_hash_table_insert (callable_cache->arg_name_hash, arg_name, arg_name);
- }
- }
+ if (PyTuple_GET_ITEM (ret, 0) != Py_None)
+ return ret;
}
- callable_cache->arg_name_list = g_slist_reverse (arg_name_list);
+ PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
+
+ Py_DECREF (ret);
+ return NULL;
}
-/* Generate the cache for the callable's arguments */
-static gboolean
-_args_cache_generate (GICallableInfo *callable_info,
- PyGICallableCache *callable_cache)
+PyGIFunctionCache *
+pygi_constructor_cache_new (GICallableInfo *info)
{
- gssize arg_index = 0;
- gssize i;
- GITypeInfo *return_info;
- GITransfer return_transfer;
- PyGIArgCache *return_cache;
- PyGIDirection return_direction;
-
- /* determine if we are marshalling the return to or from python */
- if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
- return_direction = PYGI_DIRECTION_FROM_PYTHON;
- else
- return_direction = PYGI_DIRECTION_TO_PYTHON;
+ PyGIConstructorCache *constructor_cache;
+ PyGIFunctionCache *function_cache;
- /* cache the return arg */
- return_info =
- g_callable_info_get_return_type (callable_info);
- return_transfer =
- g_callable_info_get_caller_owns (callable_info);
- return_cache =
- _arg_cache_new (return_info,
- callable_cache,
- NULL,
- return_transfer,
- return_direction,
- -1,
- -1);
- if (return_cache == NULL)
- return FALSE;
+ constructor_cache = g_new0 (PyGIConstructorCache, 1);
+ function_cache = (PyGIFunctionCache *) constructor_cache;
- return_cache->is_skipped = g_callable_info_skip_return (callable_info);
- callable_cache->return_cache = return_cache;
- g_base_info_unref (return_info);
+ function_cache->invoke = _constructor_cache_invoke_real;
- /* first arg is the instance */
- if (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
- callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
- GIInterfaceInfo *interface_info;
- PyGIArgCache *instance_cache;
- PyGIDirection instance_direction;
+ if (!_function_cache_init (function_cache, info)) {
+ g_free (constructor_cache);
+ return NULL;
+ }
- instance_direction = PYGI_DIRECTION_FROM_PYTHON;
+ return function_cache;
+}
+/* PyGIFunctionWithInstanceCache */
- interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
+static gboolean
+_function_with_instance_cache_generate_args_cache_real (PyGICallableCache *callable_cache,
+ GICallableInfo *callable_info)
+{
+ GIInterfaceInfo *interface_info;
+ PyGIArgCache *instance_cache;
+ GITransfer transfer;
- instance_cache =
- _arg_cache_new_for_interface (interface_info,
- callable_cache,
- NULL,
- GI_TRANSFER_NOTHING,
- instance_direction,
- arg_index,
- 0);
+ interface_info = g_base_info_get_container ((GIBaseInfo *) callable_info);
+ transfer = g_callable_info_get_instance_ownership_transfer (callable_info);
- /* FIXME: marshal interfaces from_py */
- instance_cache->from_py_marshaller = _pygi_marshal_from_py_interface_instance;
- g_base_info_unref ( (GIBaseInfo *)interface_info);
+ instance_cache =
+ _arg_cache_new_for_interface (interface_info,
+ NULL,
+ NULL,
+ transfer,
+ PYGI_DIRECTION_FROM_PYTHON,
+ callable_cache);
- if (instance_cache == NULL)
- return FALSE;
+ if (instance_cache == NULL)
+ return FALSE;
- callable_cache->args_cache[arg_index] = instance_cache;
+ /* Because we are not supplied a GITypeInfo for instance arguments,
+ * assume some defaults. */
+ instance_cache->is_pointer = TRUE;
+ instance_cache->py_arg_index = 0;
+ instance_cache->c_arg_index = 0;
- arg_index++;
- callable_cache->n_from_py_args++;
- callable_cache->n_py_args++;
- }
+ _pygi_callable_cache_set_arg (callable_cache, 0, instance_cache);
+ callable_cache->n_py_args++;
- for (i=0; arg_index < callable_cache->n_args; arg_index++, i++) {
- PyGIArgCache *arg_cache = NULL;
- GIArgInfo *arg_info;
- GITypeInfo *type_info;
- GIDirection gi_direction;
- PyGIDirection direction;
- GITransfer transfer;
- GITypeTag type_tag;
- gboolean is_caller_allocates = FALSE;
- gssize py_arg_index = -1;
+ return _callable_cache_generate_args_cache_real (callable_cache,
+ callable_info);
+}
- arg_info = g_callable_info_get_arg (callable_info, i);
+static gboolean
+_function_with_instance_cache_init (PyGIFunctionWithInstanceCache *fwi_cache,
+ GICallableInfo *info)
+{
+ PyGICallableCache *callable_cache = (PyGICallableCache *) fwi_cache;
- if (g_arg_info_get_closure (arg_info) == i) {
+ callable_cache->args_offset += 1;
+ callable_cache->generate_args_cache = _function_with_instance_cache_generate_args_cache_real;
- arg_cache = _arg_cache_alloc ();
- callable_cache->args_cache[arg_index] = arg_cache;
+ return _function_cache_init ((PyGIFunctionCache *) fwi_cache, info);
+}
- arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
- arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
- arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
- arg_cache->c_arg_index = i;
+/* PyGIMethodCache */
- callable_cache->n_from_py_args++;
+PyGIFunctionCache *
+pygi_method_cache_new (GICallableInfo *info)
+{
+ PyGIMethodCache *method_cache;
+ PyGIFunctionWithInstanceCache *fwi_cache;
- g_base_info_unref ( (GIBaseInfo *)arg_info);
+ method_cache = g_new0 (PyGIMethodCache, 1);
+ fwi_cache = (PyGIFunctionWithInstanceCache *) method_cache;
- continue;
- }
+ if (!_function_with_instance_cache_init (fwi_cache, info)) {
+ g_free (method_cache);
+ return NULL;
+ }
- /* For vfuncs and callbacks our marshalling directions
- are reversed */
- gi_direction = g_arg_info_get_direction (arg_info);
- if (gi_direction == GI_DIRECTION_INOUT) {
- direction = PYGI_DIRECTION_BIDIRECTIONAL;
- } else if (gi_direction == GI_DIRECTION_IN) {
- direction = PYGI_DIRECTION_FROM_PYTHON;
- if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
- direction = PYGI_DIRECTION_TO_PYTHON;
- } else {
- direction = PYGI_DIRECTION_TO_PYTHON;
- if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
- direction = PYGI_DIRECTION_FROM_PYTHON;
- }
+ return (PyGIFunctionCache *) method_cache;
+}
- transfer = g_arg_info_get_ownership_transfer (arg_info);
- type_info = g_arg_info_get_type (arg_info);
- type_tag = g_type_info_get_tag (type_info);
-
- if (type_tag == GI_TYPE_TAG_INTERFACE || type_tag == GI_TYPE_TAG_ARRAY)
- is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
-
- /* must be an child arg filled in by its owner
- * and continue
- * fill in it's c_arg_index, add to the in count
- */
- if (callable_cache->args_cache[arg_index] != NULL) {
- arg_cache = callable_cache->args_cache[arg_index];
- if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) {
- arg_cache->py_arg_index = callable_cache->n_py_args;
- callable_cache->n_py_args++;
- }
+/* PyGIVFuncCache */
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
- arg_cache->c_arg_index = callable_cache->n_from_py_args;
- callable_cache->n_from_py_args++;
- }
+static PyObject *
+_vfunc_cache_invoke_real (PyGIFunctionCache *function_cache,
+ PyGIInvokeState *state,
+ PyObject *py_args,
+ PyObject *py_kwargs)
+{
+ PyGIVFuncCache *vfunc_cache = (PyGIVFuncCache *) function_cache;
+ PyObject *py_gtype;
+ GType implementor_gtype;
+ GError *error = NULL;
+ PyObject *ret;
+
+ py_gtype = PyTuple_GetItem (py_args, 0);
+ if (py_gtype == NULL) {
+ PyErr_SetString (PyExc_TypeError,
+ "need the GType of the implementor class");
+ return FALSE;
+ }
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
- callable_cache->n_to_py_args++;
- callable_cache->n_to_py_child_args++;
- }
+ implementor_gtype = pyg_type_from_object (py_gtype);
+ if (implementor_gtype == G_TYPE_INVALID)
+ return FALSE;
- arg_cache->type_tag = g_type_info_get_tag (type_info);
+ /* vfunc addresses are pulled into the state at call time and cannot be
+ * cached because the call site can specify a different portion of the
+ * class hierarchy. e.g. Object.do_func vs. SubObject.do_func might
+ * retrieve a different vfunc address but GI gives us the same vfunc info.
+ */
+ state->function_ptr = g_vfunc_info_get_address ((GIVFuncInfo *) vfunc_cache->info,
+ implementor_gtype,
+ &error);
+ if (pygi_error_check (&error)) {
+ return FALSE;
+ }
- g_base_info_unref (type_info);
- g_base_info_unref ( (GIBaseInfo *)arg_info);
- continue;
- }
+ py_args = PyTuple_GetSlice (py_args, 1, PyTuple_Size (py_args));
+ ret = _function_cache_invoke_real (function_cache, state,
+ py_args, py_kwargs);
+ Py_DECREF (py_args);
- if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
- py_arg_index = callable_cache->n_py_args;
- callable_cache->n_from_py_args++;
- callable_cache->n_py_args++;
- }
+ return ret;
+}
- arg_cache =
- _arg_cache_new (type_info,
- callable_cache,
- arg_info,
- transfer,
- direction,
- arg_index,
- py_arg_index);
+static void
+_vfunc_cache_deinit_real (PyGICallableCache *callable_cache)
+{
+ g_base_info_unref (((PyGIVFuncCache *) callable_cache)->info);
- if (arg_cache == NULL)
- goto arg_err;
+ _function_cache_deinit_real (callable_cache);
+}
- arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
- arg_cache->allow_none = g_arg_info_may_be_null(arg_info);
- arg_cache->is_caller_allocates = is_caller_allocates;
+PyGIFunctionCache *
+pygi_vfunc_cache_new (GICallableInfo *info)
+{
+ PyGIVFuncCache *vfunc_cache;
+ PyGIFunctionCache *function_cache;
+ PyGIFunctionWithInstanceCache *fwi_cache;
- if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
- callable_cache->n_to_py_args++;
+ vfunc_cache = g_new0 (PyGIVFuncCache, 1);
+ function_cache = (PyGIFunctionCache *) vfunc_cache;
+ fwi_cache = (PyGIFunctionWithInstanceCache *) vfunc_cache;
- if (arg_cache == NULL)
- goto arg_err;
+ ((PyGICallableCache *) vfunc_cache)->deinit = _vfunc_cache_deinit_real;
- callable_cache->to_py_args =
- g_slist_append (callable_cache->to_py_args, arg_cache);
- }
+ /* This must be non-NULL for _function_cache_init() to create the
+ * invoker, the real address will be set in _vfunc_cache_invoke_real().
+ */
+ function_cache->invoker.native_address = (gpointer) 0xdeadbeef;
- callable_cache->args_cache[arg_index] = arg_cache;
- g_base_info_unref( (GIBaseInfo *)type_info);
- g_base_info_unref( (GIBaseInfo *)arg_info);
+ function_cache->invoke = _vfunc_cache_invoke_real;
- continue;
-arg_err:
- g_base_info_unref( (GIBaseInfo *)type_info);
- g_base_info_unref( (GIBaseInfo *)arg_info);
- return FALSE;
+ if (!_function_with_instance_cache_init (fwi_cache, info)) {
+ g_free (vfunc_cache);
+ return NULL;
}
- _arg_name_list_generate (callable_cache);
+ /* Required by _vfunc_cache_invoke_real() */
+ vfunc_cache->info = g_base_info_ref ((GIBaseInfo *) info);
- return TRUE;
+ return function_cache;
}
-PyGICallableCache *
-_pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
-{
- PyGICallableCache *cache;
- GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
+/* PyGIClosureCache */
- cache = g_slice_new0 (PyGICallableCache);
+PyGIClosureCache *
+pygi_closure_cache_new (GICallableInfo *info)
+{
+ gssize i;
+ PyGIClosureCache *closure_cache;
+ PyGICallableCache *callable_cache;
- if (cache == NULL)
- return NULL;
+ closure_cache = g_new0 (PyGIClosureCache, 1);
+ callable_cache = (PyGICallableCache *) closure_cache;
- cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);
+ callable_cache->calling_context = PYGI_CALLING_CONTEXT_IS_FROM_C;
- if (g_base_info_is_deprecated (callable_info)) {
- const gchar *deprecated = g_base_info_get_attribute (callable_info, "deprecated");
- gchar *warning;
- if (deprecated != NULL)
- warning = g_strdup_printf ("%s.%s is deprecated: %s",
- g_base_info_get_namespace (callable_info), cache->name,
- deprecated);
- else
- warning = g_strdup_printf ("%s.%s is deprecated",
- g_base_info_get_namespace (callable_info), cache->name);
- PyErr_WarnEx(PyExc_DeprecationWarning, warning, 0);
- g_free (warning);
+ if (!_callable_cache_init (callable_cache, info)) {
+ g_free (closure_cache);
+ return NULL;
}
- if (type == GI_INFO_TYPE_FUNCTION) {
- GIFunctionInfoFlags flags;
+ /* For backwards compatibility closures include the array's length.
+ *
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=652115
+ */
+ for (i = 0; (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) {
+ PyGIArgCache *arg_cache;
+ PyGIArgGArray *garray_cache;
+ PyGIArgCache *len_arg_cache;
+
+ arg_cache = g_ptr_array_index (callable_cache->args_cache, i);
+ if (arg_cache->type_tag != GI_TYPE_TAG_ARRAY)
+ continue;
- flags = g_function_info_get_flags ( (GIFunctionInfo *)callable_info);
+ garray_cache = (PyGIArgGArray *) arg_cache;
+ if (garray_cache->len_arg_index == -1)
+ continue;
- if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
- cache->function_type = PYGI_FUNCTION_TYPE_CONSTRUCTOR;
- else if (flags & GI_FUNCTION_IS_METHOD)
- cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
- } else if (type == GI_INFO_TYPE_VFUNC) {
- cache->function_type = PYGI_FUNCTION_TYPE_VFUNC;
- } else if (type == GI_INFO_TYPE_CALLBACK) {
- if (is_ccallback)
- cache->function_type = PYGI_FUNCTION_TYPE_CCALLBACK;
- else
- cache->function_type = PYGI_FUNCTION_TYPE_CALLBACK;
- } else {
- cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
+ len_arg_cache = g_ptr_array_index (callable_cache->args_cache,
+ garray_cache->len_arg_index);
+ len_arg_cache->meta_type = PYGI_META_ARG_TYPE_PARENT;
}
- cache->n_args = g_callable_info_get_n_args (callable_info);
+ /* Prevent guessing multiple user data arguments.
+ * This is required because some versions of GI
+ * do not recognize user_data/data arguments correctly.
+ */
+ if (callable_cache->user_data_index == -1) {
+ for (i = 0; (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) {
+ PyGIArgCache *arg_cache;
- /* if we are a method or vfunc make sure the instance parameter is counted */
- if (cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
- cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)
- cache->n_args++;
+ arg_cache = g_ptr_array_index (callable_cache->args_cache, i);
- if (cache->n_args > 0)
- cache->args_cache = g_slice_alloc0 (cache->n_args * sizeof (PyGIArgCache *));
+ if (arg_cache->direction == PYGI_DIRECTION_TO_PYTHON &&
+ arg_cache->type_tag == GI_TYPE_TAG_VOID &&
+ arg_cache->is_pointer) {
- if (!_args_cache_generate (callable_info, cache))
- goto err;
+ callable_cache->user_data_index = i;
+ break;
+ }
+ }
+ }
- return cache;
-err:
- _pygi_callable_cache_free (cache);
- return NULL;
+ return closure_cache;
}
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 6e5e0ab..fc5a616 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -2,6 +2,7 @@
* vim: tabstop=4 shiftwidth=4 expandtab
*
* Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -14,9 +15,7 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_CACHE_H__
@@ -24,30 +23,48 @@
#include <Python.h>
#include <girepository.h>
+#include <girffi.h>
#include "pygi-invoke-state-struct.h"
G_BEGIN_DECLS
-typedef struct _PyGICallableCache PyGICallableCache;
typedef struct _PyGIArgCache PyGIArgCache;
+typedef struct _PyGICallableCache PyGICallableCache;
+typedef struct _PyGIFunctionCache PyGIFunctionCache;
+typedef struct _PyGIVFuncCache PyGIVFuncCache;
+
+typedef PyGIFunctionCache PyGICCallbackCache;
+typedef PyGIFunctionCache PyGIConstructorCache;
+typedef PyGIFunctionCache PyGIFunctionWithInstanceCache;
+typedef PyGIFunctionCache PyGIMethodCache;
+typedef PyGICallableCache PyGIClosureCache;
typedef gboolean (*PyGIMarshalFromPyFunc) (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
typedef PyObject *(*PyGIMarshalToPyFunc) (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
+ PyObject *py_arg,
gpointer data,
gboolean was_processed);
+typedef void (*PyGIMarshalToPyCleanupFunc) (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer cleanup_data,
+ gpointer data,
+ gboolean was_processed);
+
/* Argument meta types denote how we process the argument:
* - PYGI_META_ARG_TYPE_PARENT - parents may or may not have children
* but are always processed via the normal marshaller for their
@@ -56,10 +73,6 @@ typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
* - PYGI_META_ARG_TYPE_CHILD - Children without python argument are
* ignored by the marshallers and handled directly by their parents
* marshaller.
- * - PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE -Sometimes children arguments
- * come before the parent. In these cases they need to be flagged
- * so that the argument list counts must be updated for the cache to
- * be valid
* - Children with pyargs (PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) are processed
* the same as other child args but also have an index into the
* python parameters passed to the invoker
@@ -67,38 +80,29 @@ typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
typedef enum {
PYGI_META_ARG_TYPE_PARENT,
PYGI_META_ARG_TYPE_CHILD,
- PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE,
PYGI_META_ARG_TYPE_CHILD_WITH_PYARG,
PYGI_META_ARG_TYPE_CLOSURE,
} PyGIMetaArgType;
/*
- * GI determines function types via a combination of flags and info classes.
- * Since for branching purposes they are mutually exclusive, the
- * PyGIFunctionType enum consolidates them into one enumeration for ease of
- * branching and debugging.
+ * Argument direction types denotes how we marshal,
+ * e.g. to Python or from Python or both.
*/
typedef enum {
- PYGI_FUNCTION_TYPE_FUNCTION,
- PYGI_FUNCTION_TYPE_METHOD,
- PYGI_FUNCTION_TYPE_CONSTRUCTOR,
- PYGI_FUNCTION_TYPE_VFUNC,
- PYGI_FUNCTION_TYPE_CALLBACK,
- PYGI_FUNCTION_TYPE_CCALLBACK,
- } PyGIFunctionType;
+ PYGI_DIRECTION_TO_PYTHON = 1 << 0,
+ PYGI_DIRECTION_FROM_PYTHON = 1 << 1,
+ PYGI_DIRECTION_BIDIRECTIONAL = PYGI_DIRECTION_TO_PYTHON | PYGI_DIRECTION_FROM_PYTHON
+ } PyGIDirection;
/*
* In PyGI IN and OUT arguments mean different things depending on the context
- * of the callable (e.g. is it a callback that is being called from C or a
- * function that is being called from python). We don't as much care if the
- * parameter is an IN or OUT C parameter, than we do if the parameter is being
- * marshalled into Python or from Python.
+ * of the callable, e.g. is it a callback that is being called from C or a
+ * function that is being called from Python.
*/
typedef enum {
- PYGI_DIRECTION_TO_PYTHON,
- PYGI_DIRECTION_FROM_PYTHON,
- PYGI_DIRECTION_BIDIRECTIONAL
- } PyGIDirection;
+ PYGI_CALLING_CONTEXT_IS_FROM_C,
+ PYGI_CALLING_CONTEXT_IS_FROM_PY
+} PyGICallingContext;
struct _PyGIArgCache
@@ -110,6 +114,7 @@ struct _PyGIArgCache
gboolean is_caller_allocates;
gboolean is_skipped;
gboolean allow_none;
+ gboolean has_default;
PyGIDirection direction;
GITransfer transfer;
@@ -120,24 +125,32 @@ struct _PyGIArgCache
PyGIMarshalToPyFunc to_py_marshaller;
PyGIMarshalCleanupFunc from_py_cleanup;
- PyGIMarshalCleanupFunc to_py_cleanup;
+ PyGIMarshalToPyCleanupFunc to_py_cleanup;
GDestroyNotify destroy_notify;
gssize c_arg_index;
gssize py_arg_index;
+
+ /* Set when has_default is true. */
+ GIArgument default_value;
};
typedef struct _PyGISequenceCache
{
PyGIArgCache arg_cache;
+ PyGIArgCache *item_cache;
+} PyGISequenceCache;
+
+typedef struct _PyGIArgGArray
+{
+ PyGISequenceCache seq_cache;
gssize fixed_size;
gssize len_arg_index;
gboolean is_zero_terminated;
gsize item_size;
GIArrayType array_type;
- PyGIArgCache *item_cache;
-} PyGISequenceCache;
+} PyGIArgGArray;
typedef struct _PyGIInterfaceCache
{
@@ -149,48 +162,174 @@ typedef struct _PyGIInterfaceCache
gchar *type_name;
} PyGIInterfaceCache;
-typedef struct _PyGIHashCache
-{
- PyGIArgCache arg_cache;
- PyGIArgCache *key_cache;
- PyGIArgCache *value_cache;
-} PyGIHashCache;
-
-typedef struct _PyGICallbackCache
-{
- PyGIArgCache arg_cache;
- gssize user_data_index;
- gssize destroy_notify_index;
- GIScopeType scope;
- GIInterfaceInfo *interface_info;
-} PyGICallbackCache;
-
struct _PyGICallableCache
{
const gchar *name;
+ const gchar *container_name;
+ const gchar *namespace;
- PyGIFunctionType function_type;
+ PyGICallingContext calling_context;
PyGIArgCache *return_cache;
- PyGIArgCache **args_cache;
+ GPtrArray *args_cache;
GSList *to_py_args;
GSList *arg_name_list; /* for keyword arg matching */
GHashTable *arg_name_hash;
+ gboolean throws;
+
+ /* Index of user_data arg passed to a callable. */
+ gssize user_data_index;
+
+ /* Index of user_data arg that can eat variable args passed to a callable. */
+ gssize user_data_varargs_index;
- /* counts */
- gssize n_from_py_args;
+ /* Number of args already added */
+ gssize args_offset;
+
+ /* Number of out args passed to g_function_info_invoke.
+ * This is used for the length of PyGIInvokeState.out_values */
gssize n_to_py_args;
+
+ /* If the callable return value gets used */
+ gboolean has_return;
+
+ /* The type used for returning multiple values or NULL */
+ PyTypeObject* resulttuple_type;
+
+ /* Number of out args for g_function_info_invoke that will be skipped
+ * when marshaling to Python due to them being implicitly available
+ * (list/array length).
+ */
gssize n_to_py_child_args;
- gssize n_args;
+ /* Number of Python arguments expected for invoking the gi function. */
gssize n_py_args;
+
+ /* Minimum number of args required to call the callable from Python.
+ * This count does not include args with defaults. */
+ gssize n_py_required_args;
+
+ void (*deinit) (PyGICallableCache *callable_cache);
+
+ gboolean (*generate_args_cache) (PyGICallableCache *callable_cache,
+ GICallableInfo *callable_info);
+};
+
+struct _PyGIFunctionCache {
+ PyGICallableCache callable_cache;
+
+ /* An invoker with ffi_cif already setup */
+ GIFunctionInvoker invoker;
+
+ PyObject *(*invoke) (PyGIFunctionCache *function_cache,
+ PyGIInvokeState *state,
+ PyObject *py_args,
+ PyObject *py_kwargs);
+} ;
+
+struct _PyGIVFuncCache {
+ PyGIFunctionWithInstanceCache fwi_cache;
+
+ GIBaseInfo *info;
};
-void _pygi_arg_cache_clear (PyGIArgCache *cache);
-void _pygi_callable_cache_free (PyGICallableCache *cache);
-PyGICallableCache *_pygi_callable_cache_new (GICallableInfo *callable_info,
- gboolean is_ccallback);
+gboolean
+pygi_arg_base_setup (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction);
+
+gboolean
+pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info);
+
+gboolean
+pygi_arg_sequence_setup (PyGISequenceCache *sc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache);
+
+PyGIArgCache *
+pygi_arg_interface_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info);
+
+PyGIArgCache *
+pygi_arg_cache_alloc (void);
+
+PyGIArgCache *
+pygi_arg_cache_new (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache,
+ /* will be removed */
+ gssize c_arg_index,
+ gssize py_arg_index);
+
+void
+pygi_arg_cache_free (PyGIArgCache *cache);
+
+void
+pygi_callable_cache_free (PyGICallableCache *cache);
+
+gchar *
+pygi_callable_cache_get_full_name (PyGICallableCache *cache);
+
+PyGIFunctionCache *
+pygi_function_cache_new (GICallableInfo *info);
+
+PyObject *
+pygi_function_cache_invoke (PyGIFunctionCache *function_cache,
+ PyObject *py_args,
+ PyObject *py_kwargs);
+
+PyGIFunctionCache *
+pygi_ccallback_cache_new (GICallableInfo *info,
+ GCallback function_ptr);
+
+PyObject *
+pygi_ccallback_cache_invoke (PyGIFunctionCache *function_cache,
+ PyObject *py_args,
+ PyObject *py_kwargs,
+ gpointer user_data);
+
+PyGIFunctionCache *
+pygi_constructor_cache_new (GICallableInfo *info);
+
+PyGIFunctionCache *
+pygi_method_cache_new (GICallableInfo *info);
+
+PyGIFunctionCache *
+pygi_vfunc_cache_new (GICallableInfo *info);
+
+PyGIClosureCache *
+pygi_closure_cache_new (GICallableInfo *info);
+
+inline static guint
+_pygi_callable_cache_args_len (PyGICallableCache *cache) {
+ return ((cache)->args_cache)->len;
+}
+
+inline static PyGIArgCache *
+_pygi_callable_cache_get_arg (PyGICallableCache *cache, guint index) {
+ return (PyGIArgCache *) g_ptr_array_index (cache->args_cache, index);
+}
+
+inline static void
+_pygi_callable_cache_set_arg (PyGICallableCache *cache, guint index, PyGIArgCache *arg_cache) {
+ cache->args_cache->pdata[index] = arg_cache;
+}
G_END_DECLS
diff --git a/gi/pygi-ccallback.c b/gi/pygi-ccallback.c
index 82777fb..db12f49 100644
--- a/gi/pygi-ccallback.c
+++ b/gi/pygi-ccallback.c
@@ -16,16 +16,13 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include "pygi-util.h"
+#include "pygi-ccallback.h"
-#include <pygobject.h>
#include <girepository.h>
-#include <pyglib-python-compat.h>
static PyObject *
@@ -34,21 +31,20 @@ _ccallback_call(PyGICCallback *self, PyObject *args, PyObject *kwargs)
PyObject *result;
if (self->cache == NULL) {
- self->cache = _pygi_callable_cache_new (self->info, TRUE);
+ self->cache = (PyGICCallbackCache *)pygi_ccallback_cache_new (self->info,
+ self->callback);
if (self->cache == NULL)
return NULL;
}
- result = pygi_callable_info_invoke( (GIBaseInfo *) self->info,
- args,
- kwargs,
- self->cache,
- self->callback,
- self->user_data);
+ result = pygi_ccallback_cache_invoke (self->cache,
+ args,
+ kwargs,
+ self->user_data);
return result;
}
-PYGLIB_DEFINE_TYPE("gi.CCallback", PyGICCallback_Type, PyGICCallback);
+PYGI_DEFINE_TYPE("gi.CCallback", PyGICCallback_Type, PyGICCallback);
PyObject *
_pygi_ccallback_new (GCallback callback,
@@ -81,19 +77,33 @@ static void
_ccallback_dealloc (PyGICCallback *self)
{
g_base_info_unref ( (GIBaseInfo *)self->info);
+
+ if (self->cache != NULL) {
+ pygi_callable_cache_free ( (PyGICallableCache *)self->cache);
+ }
+
+ Py_TYPE (self)->tp_free ((PyObject *)self);
}
-void
-_pygi_ccallback_register_types (PyObject *m)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_ccallback_register_types (PyObject *m)
{
- Py_TYPE(&PyGICCallback_Type) = &PyType_Type;
+ Py_SET_TYPE(&PyGICCallback_Type, &PyType_Type);
PyGICCallback_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE);
PyGICCallback_Type.tp_dealloc = (destructor) _ccallback_dealloc;
PyGICCallback_Type.tp_call = (ternaryfunc) _ccallback_call;
- if (PyType_Ready (&PyGICCallback_Type))
- return;
- if (PyModule_AddObject (m, "CCallback", (PyObject *) &PyGICCallback_Type))
- return;
+ if (PyType_Ready (&PyGICCallback_Type) < 0)
+ return -1;
+ Py_INCREF ((PyObject *) &PyGICCallback_Type);
+ if (PyModule_AddObject (m, "CCallback", (PyObject *) &PyGICCallback_Type) < 0) {
+ Py_INCREF ((PyObject *) &PyGICCallback_Type);
+ return -1;
+ }
+
+ return 0;
}
diff --git a/gi/pygi-ccallback.h b/gi/pygi-ccallback.h
index c796092..7b8439d 100644
--- a/gi/pygi-ccallback.h
+++ b/gi/pygi-ccallback.h
@@ -14,18 +14,27 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_CCLOSURE_H__
#define __PYGI_CCLOSURE_H__
#include <Python.h>
+#include "pygi-cache.h"
G_BEGIN_DECLS
+typedef struct {
+ PyObject_HEAD
+ GCallback callback;
+ GIFunctionInfo *info;
+ gpointer user_data;
+ GIScopeType scope;
+ GDestroyNotify destroy_notify_func;
+ PyGICCallbackCache *cache;
+} PyGICCallback;
+
extern PyTypeObject PyGICCallback_Type;
PyObject * _pygi_ccallback_new (GCallback callback,
@@ -34,7 +43,7 @@ PyObject * _pygi_ccallback_new (GCallback callback,
GIFunctionInfo *info,
GDestroyNotify destroy_notify);
-void _pygi_ccallback_register_types (PyObject *m);
+int pygi_ccallback_register_types (PyObject *m);
G_END_DECLS
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index 2f5548a..4e19c5e 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -14,12 +14,27 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include "pygi-closure.h"
+#include "pygi-error.h"
+#include "pygi-marshal-cleanup.h"
+#include "pygi-invoke.h"
+#include "pygi-ccallback.h"
+#include "pygi-info.h"
+
+extern PyObject *_PyGIDefaultArgPlaceholder;
+
+typedef struct _PyGICallbackCache
+{
+ PyGIArgCache arg_cache;
+ gssize user_data_index;
+ gssize destroy_notify_index;
+ GIScopeType scope;
+ GIInterfaceInfo *interface_info;
+ PyGIClosureCache *closure_cache;
+} PyGICallbackCache;
/* This maintains a list of closures which can be free'd whenever
as they have been called. We will free them on the next
@@ -28,493 +43,494 @@
static GSList* async_free_list;
static void
-_pygi_closure_assign_pyobj_to_retval (gpointer retval, PyObject *object,
- GITypeInfo *type_info,
- GITransfer transfer)
+_pygi_closure_assign_pyobj_to_retval (gpointer retval,
+ GIArgument *arg,
+ PyGIArgCache *arg_cache)
{
- GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
- GITypeTag type_tag;
- if (PyErr_Occurred ())
- return;
-
- type_tag = g_type_info_get_tag (type_info);
-
if (retval == NULL)
return;
- switch (type_tag) {
+ switch (arg_cache->type_tag) {
case GI_TYPE_TAG_BOOLEAN:
- *((ffi_sarg *) retval) = arg.v_boolean;
+ *((ffi_sarg *) retval) = arg->v_boolean;
break;
case GI_TYPE_TAG_INT8:
- *((ffi_sarg *) retval) = arg.v_int8;
+ *((ffi_sarg *) retval) = arg->v_int8;
break;
case GI_TYPE_TAG_UINT8:
- *((ffi_arg *) retval) = arg.v_uint8;
+ *((ffi_arg *) retval) = arg->v_uint8;
break;
case GI_TYPE_TAG_INT16:
- *((ffi_sarg *) retval) = arg.v_int16;
+ *((ffi_sarg *) retval) = arg->v_int16;
break;
case GI_TYPE_TAG_UINT16:
- *((ffi_arg *) retval) = arg.v_uint16;
+ *((ffi_arg *) retval) = arg->v_uint16;
break;
case GI_TYPE_TAG_INT32:
- *((ffi_sarg *) retval) = arg.v_int32;
+ *((ffi_sarg *) retval) = arg->v_int32;
break;
case GI_TYPE_TAG_UINT32:
- *((ffi_arg *) retval) = arg.v_uint32;
+ *((ffi_arg *) retval) = arg->v_uint32;
break;
case GI_TYPE_TAG_INT64:
- *((ffi_sarg *) retval) = arg.v_int64;
+ *((ffi_sarg *) retval) = arg->v_int64;
break;
case GI_TYPE_TAG_UINT64:
- *((ffi_arg *) retval) = arg.v_uint64;
+ *((ffi_arg *) retval) = arg->v_uint64;
break;
case GI_TYPE_TAG_FLOAT:
- *((gfloat *) retval) = arg.v_float;
+ *((gfloat *) retval) = arg->v_float;
break;
case GI_TYPE_TAG_DOUBLE:
- *((gdouble *) retval) = arg.v_double;
+ *((gdouble *) retval) = arg->v_double;
break;
case GI_TYPE_TAG_GTYPE:
- *((ffi_arg *) retval) = arg.v_ulong;
+ *((ffi_arg *) retval) = arg->v_size;
break;
case GI_TYPE_TAG_UNICHAR:
- *((ffi_arg *) retval) = arg.v_uint32;
+ *((ffi_arg *) retval) = arg->v_uint32;
break;
case GI_TYPE_TAG_INTERFACE:
{
- GIBaseInfo* interface_info;
- GIInfoType interface_type;
+ GIBaseInfo *interface_info;
- interface_info = g_type_info_get_interface(type_info);
- interface_type = g_base_info_get_type(interface_info);
+ interface_info = ((PyGIInterfaceCache *) arg_cache)->interface_info;
- switch (interface_type) {
+ switch (g_base_info_get_type (interface_info)) {
case GI_INFO_TYPE_ENUM:
- *(ffi_sarg *) retval = arg.v_int;
+ *(ffi_sarg *) retval = arg->v_int;
break;
case GI_INFO_TYPE_FLAGS:
- *(ffi_arg *) retval = arg.v_uint;
+ *(ffi_arg *) retval = arg->v_uint;
break;
default:
- *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
+ *(ffi_arg *) retval = (ffi_arg) arg->v_pointer;
break;
}
- g_base_info_unref (interface_info);
break;
}
default:
- *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
+ *(ffi_arg *) retval = (ffi_arg) arg->v_pointer;
break;
}
}
static void
-_pygi_closure_clear_retval (GICallableInfo *callable_info, gpointer retval)
-{
- GITypeInfo return_type_info;
- GITypeTag return_type_tag;
-
- g_callable_info_load_return_type (callable_info, &return_type_info);
- return_type_tag = g_type_info_get_tag (&return_type_info);
- if (return_type_tag != GI_TYPE_TAG_VOID) {
- *((ffi_arg *) retval) = 0;
- }
-}
-
-static void
-_pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
- GITypeInfo *type_info,
- GITransfer transfer)
+_pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg,
+ GIArgument *arg,
+ PyGIArgCache *arg_cache)
{
- GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
- GITypeTag type_tag = g_type_info_get_tag (type_info);
-
if (out_arg == NULL)
return;
- switch (type_tag) {
+ switch (arg_cache->type_tag) {
case GI_TYPE_TAG_BOOLEAN:
- *((gboolean *) out_arg) = arg.v_boolean;
+ *((gboolean *) out_arg) = arg->v_boolean;
break;
case GI_TYPE_TAG_INT8:
- *((gint8 *) out_arg) = arg.v_int8;
+ *((gint8 *) out_arg) = arg->v_int8;
break;
case GI_TYPE_TAG_UINT8:
- *((guint8 *) out_arg) = arg.v_uint8;
+ *((guint8 *) out_arg) = arg->v_uint8;
break;
case GI_TYPE_TAG_INT16:
- *((gint16 *) out_arg) = arg.v_int16;
+ *((gint16 *) out_arg) = arg->v_int16;
break;
case GI_TYPE_TAG_UINT16:
- *((guint16 *) out_arg) = arg.v_uint16;
+ *((guint16 *) out_arg) = arg->v_uint16;
break;
case GI_TYPE_TAG_INT32:
- *((gint32 *) out_arg) = arg.v_int32;
+ *((gint32 *) out_arg) = arg->v_int32;
break;
case GI_TYPE_TAG_UINT32:
- *((guint32 *) out_arg) = arg.v_uint32;
+ *((guint32 *) out_arg) = arg->v_uint32;
break;
case GI_TYPE_TAG_INT64:
- *((gint64 *) out_arg) = arg.v_int64;
+ *((gint64 *) out_arg) = arg->v_int64;
break;
case GI_TYPE_TAG_UINT64:
- *((glong *) out_arg) = arg.v_uint64;
+ *((guint64 *) out_arg) = arg->v_uint64;
break;
case GI_TYPE_TAG_FLOAT:
- *((gfloat *) out_arg) = arg.v_float;
+ *((gfloat *) out_arg) = arg->v_float;
break;
case GI_TYPE_TAG_DOUBLE:
- *((gdouble *) out_arg) = arg.v_double;
+ *((gdouble *) out_arg) = arg->v_double;
break;
case GI_TYPE_TAG_GTYPE:
- *((gulong *) out_arg) = arg.v_ulong;
+ *((GType *) out_arg) = arg->v_size;
break;
case GI_TYPE_TAG_UNICHAR:
- *((guint32 *) out_arg) = arg.v_uint32;
+ *((guint32 *) out_arg) = arg->v_uint32;
break;
case GI_TYPE_TAG_INTERFACE:
{
- GIBaseInfo *interface;
- GIInfoType interface_type;
+ GIBaseInfo *interface_info;
- interface = g_type_info_get_interface (type_info);
- interface_type = g_base_info_get_type (interface);
+ interface_info = ((PyGIInterfaceCache *) arg_cache)->interface_info;
- switch (interface_type) {
+ switch (g_base_info_get_type (interface_info)) {
case GI_INFO_TYPE_ENUM:
- *(gint *) out_arg = arg.v_int;
+ *(gint *) out_arg = arg->v_int;
break;
case GI_INFO_TYPE_FLAGS:
- *(guint *) out_arg = arg.v_uint;
+ *(guint *) out_arg = arg->v_uint;
break;
case GI_INFO_TYPE_STRUCT:
- if (!g_type_info_is_pointer (type_info)) {
- if (object != Py_None) {
- gsize item_size = _pygi_g_type_info_size (type_info);
- memcpy (out_arg, arg.v_pointer, item_size);
+ if (!arg_cache->is_pointer) {
+ if (arg->v_pointer != NULL) {
+ gsize item_size = _pygi_g_type_info_size (arg_cache->type_info);
+ memcpy (out_arg, arg->v_pointer, item_size);
}
break;
}
-
- /* Fall through if pointer */
+ *((gpointer *) out_arg) = arg->v_pointer;
+ break;
default:
- *((gpointer *) out_arg) = arg.v_pointer;
+ *((gpointer *) out_arg) = arg->v_pointer;
break;
}
-
- g_base_info_unref (interface);
break;
}
default:
- *((gpointer *) out_arg) = arg.v_pointer;
+ *((gpointer *) out_arg) = arg->v_pointer;
break;
}
}
-static GIArgument *
-_pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
+static void
+_pygi_closure_convert_ffi_arguments (PyGIInvokeArgState *state,
+ PyGICallableCache *cache,
+ void **args)
{
- gint num_args, i;
- GIArgInfo arg_info;
- GITypeInfo arg_type;
- GITypeTag tag;
- GIDirection direction;
- GIArgument *g_args;
-
- num_args = g_callable_info_get_n_args (callable_info);
- g_args = g_new0 (GIArgument, num_args);
-
- for (i = 0; i < num_args; i++) {
- g_callable_info_load_arg (callable_info, i, &arg_info);
- g_arg_info_load_type (&arg_info, &arg_type);
- tag = g_type_info_get_tag (&arg_type);
- direction = g_arg_info_get_direction (&arg_info);
-
- if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
- g_args[i].v_pointer = * (gpointer *) args[i];
+ guint i;
+
+ for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
+ PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i);
+ gpointer arg_pointer;
+
+ if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
+ state[i].arg_value.v_pointer = * (gpointer *) args[i];
+
+ if (state[i].arg_value.v_pointer == NULL)
+ continue;
+
+ state[i].arg_pointer.v_pointer = state[i].arg_value.v_pointer;
+ arg_pointer = state[i].arg_value.v_pointer;
} else {
- switch (tag) {
- case GI_TYPE_TAG_BOOLEAN:
- g_args[i].v_boolean = * (gboolean *) args[i];
- break;
- case GI_TYPE_TAG_INT8:
- g_args[i].v_int8 = * (gint8 *) args[i];
- break;
- case GI_TYPE_TAG_UINT8:
- g_args[i].v_uint8 = * (guint8 *) args[i];
- break;
- case GI_TYPE_TAG_INT16:
- g_args[i].v_int16 = * (gint16 *) args[i];
- break;
- case GI_TYPE_TAG_UINT16:
- g_args[i].v_uint16 = * (guint16 *) args[i];
- break;
- case GI_TYPE_TAG_INT32:
- g_args[i].v_int32 = * (gint32 *) args[i];
- break;
- case GI_TYPE_TAG_UINT32:
- g_args[i].v_uint32 = * (guint32 *) args[i];
- break;
- case GI_TYPE_TAG_INT64:
- g_args[i].v_int64 = * (glong *) args[i];
- break;
- case GI_TYPE_TAG_UINT64:
- g_args[i].v_uint64 = * (glong *) args[i];
- break;
- case GI_TYPE_TAG_FLOAT:
- g_args[i].v_float = * (gfloat *) args[i];
- break;
- case GI_TYPE_TAG_DOUBLE:
- g_args[i].v_double = * (gdouble *) args[i];
- break;
- case GI_TYPE_TAG_UTF8:
- g_args[i].v_string = * (gchar **) args[i];
- break;
- case GI_TYPE_TAG_INTERFACE:
- {
- GIBaseInfo *interface;
- GIInfoType interface_type;
-
- interface = g_type_info_get_interface (&arg_type);
- interface_type = g_base_info_get_type (interface);
-
- if (interface_type == GI_INFO_TYPE_OBJECT ||
- interface_type == GI_INFO_TYPE_INTERFACE) {
- g_args[i].v_pointer = * (gpointer *) args[i];
- g_base_info_unref (interface);
- break;
- } else if (interface_type == GI_INFO_TYPE_ENUM ||
- interface_type == GI_INFO_TYPE_FLAGS) {
- g_args[i].v_uint = * (guint *) args[i];
- g_base_info_unref (interface);
- break;
- } else if (interface_type == GI_INFO_TYPE_STRUCT ||
- interface_type == GI_INFO_TYPE_CALLBACK) {
- g_args[i].v_pointer = * (gpointer *) args[i];
- g_base_info_unref (interface);
- break;
- }
+ arg_pointer = args[i];
+ }
+
+ switch (arg_cache->type_tag) {
+ case GI_TYPE_TAG_BOOLEAN:
+ state[i].arg_value.v_boolean = * (gboolean *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_INT8:
+ state[i].arg_value.v_int8 = * (gint8 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_UINT8:
+ state[i].arg_value.v_uint8 = * (guint8 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_INT16:
+ state[i].arg_value.v_int16 = * (gint16 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_UINT16:
+ state[i].arg_value.v_uint16 = * (guint16 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_INT32:
+ state[i].arg_value.v_int32 = * (gint32 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_UINT32:
+ state[i].arg_value.v_uint32 = * (guint32 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_INT64:
+ state[i].arg_value.v_int64 = * (gint64 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_UINT64:
+ state[i].arg_value.v_uint64 = * (guint64 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ state[i].arg_value.v_float = * (gfloat *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ state[i].arg_value.v_double = * (gdouble *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_UTF8:
+ state[i].arg_value.v_string = * (gchar **) arg_pointer;
+ break;
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIBaseInfo *interface;
+ GIInfoType interface_type;
+
+ interface = ((PyGIInterfaceCache *) arg_cache)->interface_info;
+ interface_type = g_base_info_get_type (interface);
- g_base_info_unref (interface);
+ if (interface_type == GI_INFO_TYPE_ENUM) {
+ state[i].arg_value.v_int = * (gint *) arg_pointer;
+ } else if (interface_type == GI_INFO_TYPE_FLAGS) {
+ state[i].arg_value.v_uint = * (guint *) arg_pointer;
+ } else {
+ state[i].arg_value.v_pointer = * (gpointer *) arg_pointer;
}
- case GI_TYPE_TAG_ERROR:
- case GI_TYPE_TAG_GHASH:
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- case GI_TYPE_TAG_ARRAY:
- case GI_TYPE_TAG_VOID:
- g_args[i].v_pointer = * (gpointer *) args[i];
- break;
- default:
- g_warning ("Unhandled type tag %s", g_type_tag_to_string (tag));
- g_args[i].v_pointer = 0;
+ break;
}
+ case GI_TYPE_TAG_UNICHAR:
+ state[i].arg_value.v_uint32 = * (guint32 *) arg_pointer;
+ break;
+ case GI_TYPE_TAG_ERROR:
+ case GI_TYPE_TAG_GHASH:
+ case GI_TYPE_TAG_GLIST:
+ case GI_TYPE_TAG_GSLIST:
+ case GI_TYPE_TAG_ARRAY:
+ case GI_TYPE_TAG_VOID:
+ state[i].arg_value.v_pointer = * (gpointer *) arg_pointer;
+ break;
+ default:
+ g_warning ("Unhandled type tag %s",
+ g_type_tag_to_string (arg_cache->type_tag));
+ state[i].arg_value.v_pointer = 0;
}
}
- return g_args;
+
+ if (cache->throws) {
+ gssize error_index = _pygi_callable_cache_args_len (cache);
+
+ state[error_index].arg_value.v_pointer = * (gpointer *) args[error_index];
+ }
}
static gboolean
-_pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
- void *user_data, PyObject **py_args,
- GIArgument **out_args)
+_invoke_state_init_from_cache (PyGIInvokeState *state,
+ PyGIClosureCache *closure_cache,
+ void **args)
{
- int n_args = g_callable_info_get_n_args (callable_info);
- int n_in_args = 0;
- int n_out_args = 0;
- int i;
- int user_data_arg = -1;
- int destroy_notify_arg = -1;
-
- GIArgument *g_args = NULL;
-
- *py_args = NULL;
- *py_args = PyTuple_New (n_args);
- if (*py_args == NULL)
- goto error;
-
- *out_args = NULL;
- *out_args = g_new0 (GIArgument, n_args);
- g_args = _pygi_closure_convert_ffi_arguments (callable_info, args);
-
- for (i = 0; i < n_args; i++) {
- GIArgInfo arg_info;
- GIDirection direction;
-
- /* Special case callbacks and skip over userdata and Destroy Notify */
- if (i == user_data_arg || i == destroy_notify_arg)
- continue;
-
- g_callable_info_load_arg (callable_info, i, &arg_info);
- direction = g_arg_info_get_direction (&arg_info);
-
- if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
- GITypeInfo arg_type;
- GITypeTag arg_tag;
- GITransfer transfer;
- PyObject *value;
- GIArgument *arg;
- gboolean free_array;
+ PyGICallableCache *cache = (PyGICallableCache *) closure_cache;
+
+ state->n_args = _pygi_callable_cache_args_len (cache);
+ state->n_py_in_args = state->n_args;
+
+ /* Increment after setting the number of Python input args */
+ if (cache->throws) {
+ state->n_args++;
+ }
+
+ state->py_in_args = PyTuple_New (state->n_py_in_args);
+ if (state->py_in_args == NULL) {
+ PyErr_NoMemory ();
+ return FALSE;
+ }
+
+ state->args = NULL;
+ state->error = NULL;
+
+ if (!_pygi_invoke_arg_state_init (state)) {
+ return FALSE;
+ }
+
+ state->ffi_args = NULL;
+
+ _pygi_closure_convert_ffi_arguments (state->args, cache, args);
+ return TRUE;
+}
+
+static void
+_invoke_state_clear (PyGIInvokeState *state)
+{
+ _pygi_invoke_arg_state_free (state);
+ Py_XDECREF (state->py_in_args);
+}
+
+static gboolean
+_pygi_closure_convert_arguments (PyGIInvokeState *state,
+ PyGIClosureCache *closure_cache)
+{
+ PyGICallableCache *cache = (PyGICallableCache *) closure_cache;
+ gssize n_in_args = 0;
+ gssize i;
- g_arg_info_load_type (&arg_info, &arg_type);
- arg_tag = g_type_info_get_tag (&arg_type);
- transfer = g_arg_info_get_ownership_transfer (&arg_info);
- free_array = FALSE;
+ for (i = 0; (gsize)i < _pygi_callable_cache_args_len (cache); i++) {
+ PyGIArgCache *arg_cache;
- if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID &&
- g_type_info_is_pointer (&arg_type)) {
+ arg_cache = g_ptr_array_index (cache->args_cache, i);
+
+ if (arg_cache->direction & PYGI_DIRECTION_TO_PYTHON) {
+ PyObject *value;
- if (user_data == NULL) {
+ if (cache->user_data_index == i) {
+ if (state->user_data == NULL) {
+ /* user_data can be NULL for connect functions which don't accept
+ * user_data or as the default for user_data in the middle of function
+ * arguments.
+ */
Py_INCREF (Py_None);
value = Py_None;
} else {
- value = user_data;
- Py_INCREF (value);
+ /* Extend the callbacks args with user_data as variable args. */
+ gssize j, user_data_len;
+ PyObject *py_user_data = state->user_data;
+
+ if (!PyTuple_Check (py_user_data)) {
+ PyErr_SetString (PyExc_TypeError, "expected tuple for callback user_data");
+ return FALSE;
+ }
+
+ user_data_len = PyTuple_Size (py_user_data);
+ _PyTuple_Resize (&state->py_in_args,
+ state->n_py_in_args + user_data_len - 1);
+
+ for (j = 0; j < user_data_len; j++, n_in_args++) {
+ value = PyTuple_GetItem (py_user_data, j);
+ Py_INCREF (value);
+ PyTuple_SET_ITEM (state->py_in_args, n_in_args, value);
+ }
+ /* We can assume user_data args are never going to be inout,
+ * so just continue here.
+ */
+ continue;
}
- } else if (direction == GI_DIRECTION_IN &&
- arg_tag == GI_TYPE_TAG_INTERFACE) {
- /* Handle callbacks as a special case */
- GIBaseInfo *info;
- GIInfoType info_type;
-
- info = g_type_info_get_interface (&arg_type);
- info_type = g_base_info_get_type (info);
-
- arg = (GIArgument*) &g_args[i];
-
- if (info_type == GI_INFO_TYPE_CALLBACK) {
- gpointer user_data = NULL;
- GDestroyNotify destroy_notify = NULL;
- GIScopeType scope = g_arg_info_get_scope(&arg_info);
-
- user_data_arg = g_arg_info_get_closure(&arg_info);
- destroy_notify_arg = g_arg_info_get_destroy(&arg_info);
-
- if (user_data_arg != -1)
- user_data = g_args[user_data_arg].v_pointer;
-
- if (destroy_notify_arg != -1)
- user_data = (GDestroyNotify) g_args[destroy_notify_arg].v_pointer;
-
- value = _pygi_ccallback_new(arg->v_pointer,
- user_data,
- scope,
- (GIFunctionInfo *) info,
- destroy_notify);
- } else
- value = _pygi_argument_to_object (arg, &arg_type, transfer);
-
- g_base_info_unref (info);
- if (value == NULL)
- goto error;
+ } else if (arg_cache->meta_type != PYGI_META_ARG_TYPE_PARENT) {
+ continue;
} else {
- if (direction == GI_DIRECTION_IN)
- arg = (GIArgument*) &g_args[i];
- else
- arg = (GIArgument*) g_args[i].v_pointer;
-
- if (g_type_info_get_tag (&arg_type) == GI_TYPE_TAG_ARRAY)
- arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args, NULL,
- callable_info, &arg_type, &free_array);
-
- value = _pygi_argument_to_object (arg, &arg_type, transfer);
-
- if (free_array)
- g_array_free (arg->v_pointer, FALSE);
-
- if (value == NULL)
- goto error;
+ gpointer cleanup_data = NULL;
+
+ value = arg_cache->to_py_marshaller (state,
+ cache,
+ arg_cache,
+ &state->args[i].arg_value,
+ &cleanup_data);
+ state->args[i].to_py_arg_cleanup_data = cleanup_data;
+
+ if (value == NULL) {
+ pygi_marshal_cleanup_args_to_py_parameter_fail (state,
+ cache,
+ i);
+ return FALSE;
+ }
}
- PyTuple_SET_ITEM (*py_args, n_in_args, value);
- n_in_args++;
- }
- if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
- (*out_args) [n_out_args] = g_args[i];
- n_out_args++;
+ PyTuple_SET_ITEM (state->py_in_args, n_in_args, value);
+ n_in_args++;
}
-
}
- if (_PyTuple_Resize (py_args, n_in_args) == -1)
- goto error;
+ if (_PyTuple_Resize (&state->py_in_args, n_in_args) == -1)
+ return FALSE;
- g_free (g_args);
return TRUE;
-
-error:
- Py_CLEAR (*py_args);
- g_free (*out_args);
- *out_args = NULL;
- g_free (g_args);
-
- return FALSE;
}
-static void
-_pygi_closure_set_out_arguments (GICallableInfo *callable_info,
- PyObject *py_retval, GIArgument *out_args,
+static gboolean
+_pygi_closure_set_out_arguments (PyGIInvokeState *state,
+ PyGICallableCache *cache,
+ PyObject *py_retval,
void *resp)
{
- int n_args, i, i_py_retval, i_out_args;
- GITypeInfo return_type_info;
- GITypeTag return_type_tag;
-
- i_py_retval = 0;
- g_callable_info_load_return_type (callable_info, &return_type_info);
- return_type_tag = g_type_info_get_tag (&return_type_info);
- if (return_type_tag != GI_TYPE_TAG_VOID) {
- GITransfer transfer = g_callable_info_get_caller_owns (callable_info);
+ gssize i;
+ gssize i_py_retval = 0;
+ gboolean success;
+
+ if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) {
+ PyObject *item = py_retval;
+
if (PyTuple_Check (py_retval)) {
- PyObject *item = PyTuple_GET_ITEM (py_retval, 0);
- _pygi_closure_assign_pyobj_to_retval (resp, item,
- &return_type_info, transfer);
- } else {
- _pygi_closure_assign_pyobj_to_retval (resp, py_retval,
- &return_type_info, transfer);
+ item = PyTuple_GET_ITEM (py_retval, 0);
+ }
+
+ success = cache->return_cache->from_py_marshaller (state,
+ cache,
+ cache->return_cache,
+ item,
+ &state->return_arg,
+ &state->args[0].arg_cleanup_data);
+
+ if (!success) {
+ pygi_marshal_cleanup_args_return_fail (state,
+ cache);
+ return FALSE;
}
+
+ _pygi_closure_assign_pyobj_to_retval (resp, &state->return_arg,
+ cache->return_cache);
i_py_retval++;
}
- i_out_args = 0;
- n_args = g_callable_info_get_n_args (callable_info);
- for (i = 0; i < n_args; i++) {
- GIArgInfo arg_info;
- GITypeInfo type_info;
- GIDirection direction;
- g_callable_info_load_arg (callable_info, i, &arg_info);
- g_arg_info_load_type (&arg_info, &type_info);
- direction = g_arg_info_get_direction (&arg_info);
-
- if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
- GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info);
-
- if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ERROR) {
- /* TODO: check if an exception has been set and convert it to a GError */
- out_args[i_out_args].v_pointer = NULL;
- i_out_args++;
+ for (i = 0; (gsize)i < _pygi_callable_cache_args_len (cache); i++) {
+ PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i);
+
+ if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
+ PyObject *item = py_retval;
+
+ if (arg_cache->type_tag == GI_TYPE_TAG_ERROR) {
+ * (GError **) state->args[i].arg_pointer.v_pointer = NULL;
continue;
}
if (PyTuple_Check (py_retval)) {
- PyObject *item = PyTuple_GET_ITEM (py_retval, i_py_retval);
- _pygi_closure_assign_pyobj_to_out_argument (
- out_args[i_out_args].v_pointer, item, &type_info, transfer);
- } else if (i_py_retval == 0) {
- _pygi_closure_assign_pyobj_to_out_argument (
- out_args[i_out_args].v_pointer, py_retval, &type_info,
- transfer);
- } else
- g_assert_not_reached();
-
- i_out_args++;
+ item = PyTuple_GET_ITEM (py_retval, i_py_retval);
+ } else if (i_py_retval != 0) {
+ pygi_marshal_cleanup_args_to_py_parameter_fail (state,
+ cache,
+ i_py_retval);
+ return FALSE;
+ }
+
+ success = arg_cache->from_py_marshaller (state,
+ cache,
+ arg_cache,
+ item,
+ &state->args[i].arg_value,
+ &state->args[i_py_retval].arg_cleanup_data);
+
+ if (!success) {
+ pygi_marshal_cleanup_args_to_py_parameter_fail (state,
+ cache,
+ i_py_retval);
+ return FALSE;
+ }
+
+ _pygi_closure_assign_pyobj_to_out_argument (state->args[i].arg_pointer.v_pointer,
+ &state->args[i].arg_value, arg_cache);
+
i_py_retval++;
}
}
+
+ return TRUE;
+}
+
+static void
+_pygi_closure_clear_retvals (PyGIInvokeState *state,
+ PyGICallableCache *cache,
+ gpointer resp)
+{
+ gsize i;
+ GIArgument arg = { 0, };
+
+ if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) {
+ _pygi_closure_assign_pyobj_to_retval (resp, &arg,
+ cache->return_cache);
+ }
+
+ for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
+ PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i);
+
+ if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
+ _pygi_closure_assign_pyobj_to_out_argument (state->args[i].arg_pointer.v_pointer,
+ &arg, arg_cache);
+ }
+ }
+
+ if (cache->throws) {
+ gssize error_index = state->n_args - 1;
+ GError **error = (GError **) state->args[error_index].arg_value.v_pointer;
+
+ if (error != NULL) {
+ pygi_gerror_exception_check (error);
+ }
+ }
}
static void
@@ -534,43 +550,56 @@ _pygi_closure_handle (ffi_cif *cif,
void **args,
void *data)
{
- PyGILState_STATE state;
+ PyGILState_STATE py_state;
PyGICClosure *closure = data;
PyObject *retval;
- PyObject *py_args;
- GIArgument *out_args = NULL;
+ gboolean success;
+ PyGIInvokeState state = { 0, };
+
+ /* Ignore closures when Python is not initialized. This can happen in cases
+ * where calling Python implemented vfuncs can happen at shutdown time.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=722562 */
+ if (!Py_IsInitialized()) {
+ return;
+ }
/* Lock the GIL as we are coming into this code without the lock and we
may be executing python code */
- state = PyGILState_Ensure();
+ py_state = PyGILState_Ensure ();
+
+ if (closure->cache == NULL)
+ goto end;
+
+ state.user_data = closure->user_data;
- if (!_pygi_closure_convert_arguments ( (GICallableInfo *) closure->info, args,
- closure->user_data,
- &py_args, &out_args)) {
- if (PyErr_Occurred ())
- PyErr_Print();
+ _invoke_state_init_from_cache (&state, closure->cache, args);
+
+ if (!_pygi_closure_convert_arguments (&state, closure->cache)) {
+ _pygi_closure_clear_retvals (&state, closure->cache, result);
goto end;
}
- retval = PyObject_CallObject ( (PyObject *) closure->function, py_args);
- Py_DECREF (py_args);
+ retval = PyObject_CallObject ( (PyObject *) closure->function, state.py_in_args);
if (retval == NULL) {
- _pygi_closure_clear_retval (closure->info, result);
- PyErr_Print();
+ _pygi_closure_clear_retvals (&state, closure->cache, result);
goto end;
}
- _pygi_closure_set_out_arguments (closure->info, retval, out_args, result);
- if (PyErr_Occurred ()) {
- _pygi_closure_clear_retval (closure->info, result);
- PyErr_Print();
+ pygi_marshal_cleanup_args_to_py_marshal_success (&state, closure->cache);
+ success = _pygi_closure_set_out_arguments (&state, closure->cache, retval, result);
+
+ if (!success) {
+ pygi_marshal_cleanup_args_from_py_marshal_success (&state, closure->cache);
+ _pygi_closure_clear_retvals (&state, closure->cache, result);
}
Py_DECREF (retval);
end:
- g_free (out_args);
+
+ if (PyErr_Occurred ())
+ PyErr_Print ();
/* Now that the closure has finished we can make a decision about how
to free it. Scope call gets free'd at the end of wrap_g_function_info_invoke.
@@ -591,23 +620,31 @@ end:
async_free_list = g_slist_prepend (async_free_list, closure);
break;
default:
- g_error ("Invalid scope reached inside %s. Possibly a bad annotation?",
- g_base_info_get_name (closure->info));
+ /* Handle new scopes added by gobject-introspection */
+ g_critical ("Unknown scope reached inside %s. Please file an issue "
+ "at https://gitlab.gnome.org/GNOME/pygobject/issues/new",
+ g_base_info_get_name (closure->info));
}
- PyGILState_Release (state);
+ _invoke_state_clear (&state);
+ PyGILState_Release (py_state);
}
-void _pygi_invoke_closure_free (gpointer data)
+void _pygi_invoke_closure_free (PyGICClosure* invoke_closure)
{
- PyGICClosure* invoke_closure = (PyGICClosure *) data;
-
+#if GI_CHECK_VERSION (1, 72, 0)
+ g_callable_info_destroy_closure (invoke_closure->info,
+ invoke_closure->closure);
+#else
g_callable_info_free_closure (invoke_closure->info,
invoke_closure->closure);
+#endif
if (invoke_closure->info)
g_base_info_unref ( (GIBaseInfo*) invoke_closure->info);
+ invoke_closure->cache = NULL;
+
_pygi_invoke_closure_clear_py_data(invoke_closure);
g_slice_free (PyGICClosure, invoke_closure);
@@ -616,9 +653,10 @@ void _pygi_invoke_closure_free (gpointer data)
PyGICClosure*
_pygi_make_native_closure (GICallableInfo* info,
+ PyGIClosureCache *cache,
GIScopeType scope,
PyObject *py_function,
- gpointer py_user_data)
+ PyObject *py_user_data)
{
PyGICClosure *closure;
ffi_closure *fficlosure;
@@ -631,14 +669,22 @@ _pygi_make_native_closure (GICallableInfo* info,
closure = g_slice_new0 (PyGICClosure);
closure->info = (GICallableInfo *) g_base_info_ref ( (GIBaseInfo *) info);
closure->function = py_function;
- closure->user_data = py_user_data ? py_user_data : Py_None;
+ closure->user_data = py_user_data;
+ closure->cache = cache;
Py_INCREF (py_function);
- Py_INCREF (closure->user_data);
+ Py_XINCREF (closure->user_data);
+#if GI_CHECK_VERSION (1, 72, 0)
+ fficlosure =
+ g_callable_info_create_closure (info, &closure->cif, _pygi_closure_handle,
+ closure);
+#else
fficlosure =
g_callable_info_prepare_closure (info, &closure->cif, _pygi_closure_handle,
closure);
+#endif
+
closure->closure = fficlosure;
/* Give the closure the information it needs to determine when
@@ -647,3 +693,285 @@ _pygi_make_native_closure (GICallableInfo* info,
return closure;
}
+
+/* _pygi_destroy_notify_dummy:
+ *
+ * Dummy method used in the occasion when a method has a GDestroyNotify
+ * argument without user data.
+ */
+static void
+_pygi_destroy_notify_dummy (gpointer data) {
+}
+
+static gboolean
+_pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ GICallableInfo *callable_info;
+ PyGICClosure *closure;
+ PyGIArgCache *user_data_cache = NULL;
+ PyGIArgCache *destroy_cache = NULL;
+ PyGICallbackCache *callback_cache;
+ PyObject *py_user_data = NULL;
+
+ callback_cache = (PyGICallbackCache *)arg_cache;
+
+ if (callback_cache->user_data_index > 0) {
+ user_data_cache = _pygi_callable_cache_get_arg (callable_cache, (guint)callback_cache->user_data_index);
+ if (user_data_cache->py_arg_index < state->n_py_in_args) {
+ /* py_user_data is a borrowed reference. */
+ py_user_data = PyTuple_GetItem (state->py_in_args, user_data_cache->py_arg_index);
+ if (!py_user_data)
+ return FALSE;
+ /* NULL out user_data if it was not supplied and the default arg placeholder
+ * was used instead.
+ */
+ if (py_user_data == _PyGIDefaultArgPlaceholder) {
+ py_user_data = NULL;
+ } else if (callable_cache->user_data_varargs_index < 0) {
+ /* For non-variable length user data, place the user data in a
+ * single item tuple which is concatenated to the callbacks arguments.
+ * This allows callback input arg marshaling to always expect a
+ * tuple for user data. Note the
+ */
+ py_user_data = Py_BuildValue("(O)", py_user_data, NULL);
+ } else {
+ /* increment the ref borrowed from PyTuple_GetItem above */
+ Py_INCREF (py_user_data);
+ }
+ }
+ }
+
+ if (py_arg == Py_None) {
+ return TRUE;
+ }
+
+ if (!PyCallable_Check (py_arg)) {
+ PyErr_Format (PyExc_TypeError,
+ "Callback needs to be a function or method not %s",
+ Py_TYPE (py_arg)->tp_name);
+
+ return FALSE;
+ }
+
+ callable_info = (GICallableInfo *)callback_cache->interface_info;
+
+ closure = _pygi_make_native_closure (
+ callable_info, callback_cache->closure_cache, callback_cache->scope,
+ py_arg, py_user_data);
+
+#if GI_CHECK_VERSION (1, 72, 0)
+ if (closure->closure != NULL)
+ arg->v_pointer = g_callable_info_get_closure_native_address (callable_info, closure->closure);
+ else
+ arg->v_pointer = NULL;
+#else
+ arg->v_pointer = closure->closure;
+#endif
+
+ /* always decref the user data as _pygi_make_native_closure adds its own ref */
+ Py_XDECREF (py_user_data);
+
+ /* The PyGICClosure instance is used as user data passed into the C function.
+ * The return trip to python will marshal this back and pull the python user data out.
+ */
+ if (user_data_cache != NULL) {
+ state->args[user_data_cache->c_arg_index].arg_value.v_pointer = closure;
+ }
+
+ /* Setup a GDestroyNotify callback if this method supports it along with
+ * a user data field. The user data field is a requirement in order
+ * free resources and ref counts associated with this arguments closure.
+ * In case a user data field is not available, show a warning giving
+ * explicit information and setup a dummy notification to avoid a crash
+ * later on in _pygi_destroy_notify_callback_closure.
+ */
+ if (callback_cache->destroy_notify_index > 0) {
+ destroy_cache = _pygi_callable_cache_get_arg (callable_cache, (guint)callback_cache->destroy_notify_index);
+ }
+
+ if (destroy_cache) {
+ if (user_data_cache != NULL) {
+ state->args[destroy_cache->c_arg_index].arg_value.v_pointer = _pygi_invoke_closure_free;
+ } else {
+ char *full_name = pygi_callable_cache_get_full_name (callable_cache);
+ gchar *msg = g_strdup_printf("Callables passed to %s will leak references because "
+ "the method does not support a user_data argument. "
+ "See: https://bugzilla.gnome.org/show_bug.cgi?id=685598",
+ full_name);
+ g_free (full_name);
+ if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 2)) {
+ g_free(msg);
+ _pygi_invoke_closure_free(closure);
+ return FALSE;
+ }
+ g_free(msg);
+ state->args[destroy_cache->c_arg_index].arg_value.v_pointer = _pygi_destroy_notify_dummy;
+ }
+ }
+
+ /* Use the PyGIClosure as data passed to cleanup for GI_SCOPE_TYPE_CALL. */
+ *cleanup_data = closure;
+
+ return TRUE;
+}
+
+static PyObject *
+_pygi_marshal_to_py_interface_callback (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *arg_cleanup_data)
+{
+ PyGICallbackCache *callback_cache = (PyGICallbackCache *) arg_cache;
+ gssize user_data_index;
+ gssize destroy_notify_index;
+ gpointer user_data = NULL;
+ GDestroyNotify destroy_notify = NULL;
+
+ user_data_index = callback_cache->user_data_index;
+ destroy_notify_index = callback_cache->destroy_notify_index;
+
+ if (user_data_index != -1)
+ user_data = state->args[user_data_index].arg_value.v_pointer;
+
+ if (destroy_notify_index != -1)
+ destroy_notify = state->args[destroy_notify_index].arg_value.v_pointer;
+
+ return _pygi_ccallback_new (arg->v_pointer,
+ user_data,
+ callback_cache->scope,
+ (GIFunctionInfo *) callback_cache->interface_info,
+ destroy_notify);
+}
+
+static void
+_callback_cache_free_func (PyGICallbackCache *cache)
+{
+ if (cache != NULL) {
+ if (cache->interface_info != NULL)
+ g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
+
+ if (cache->closure_cache != NULL) {
+ pygi_callable_cache_free ((PyGICallableCache *) cache->closure_cache);
+ cache->closure_cache = NULL;
+ }
+
+ g_slice_free (PyGICallbackCache, cache);
+ }
+}
+
+static void
+_pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
+
+ if (was_processed && callback_cache->scope == GI_SCOPE_TYPE_CALL) {
+ _pygi_invoke_closure_free (data);
+ }
+}
+
+static gboolean
+pygi_arg_callback_setup_from_info (PyGICallbackCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info,
+ PyGICallableCache *callable_cache)
+{
+ PyGIArgCache *cache = (PyGIArgCache *)arg_cache;
+ gssize child_offset = 0;
+
+ if (!pygi_arg_base_setup ((PyGIArgCache *)arg_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction)) {
+ return FALSE;
+ }
+
+ if (callable_cache != NULL)
+ child_offset = callable_cache->args_offset;
+
+ ( (PyGIArgCache *)arg_cache)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;
+
+ arg_cache->user_data_index = g_arg_info_get_closure (arg_info);
+ if (arg_cache->user_data_index != -1)
+ arg_cache->user_data_index += child_offset;
+
+ arg_cache->destroy_notify_index = g_arg_info_get_destroy (arg_info);
+ if (arg_cache->destroy_notify_index != -1)
+ arg_cache->destroy_notify_index += child_offset;
+
+ if (arg_cache->user_data_index >= 0) {
+ PyGIArgCache *user_data_arg_cache = pygi_arg_cache_alloc ();
+ user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
+ user_data_arg_cache->direction = direction;
+ user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
+ _pygi_callable_cache_set_arg (callable_cache, (guint)arg_cache->user_data_index,
+ user_data_arg_cache);
+ }
+
+ if (arg_cache->destroy_notify_index >= 0) {
+ PyGIArgCache *destroy_arg_cache = pygi_arg_cache_alloc ();
+ destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+ destroy_arg_cache->direction = direction;
+ _pygi_callable_cache_set_arg (callable_cache, (guint)arg_cache->destroy_notify_index,
+ destroy_arg_cache);
+ }
+
+ arg_cache->scope = g_arg_info_get_scope (arg_info);
+ g_base_info_ref( (GIBaseInfo *)iface_info);
+ arg_cache->interface_info = iface_info;
+
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ arg_cache->closure_cache = pygi_closure_cache_new (arg_cache->interface_info);
+ cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
+ cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
+ }
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ cache->to_py_marshaller = _pygi_marshal_to_py_interface_callback;
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_callback_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info,
+ PyGICallableCache *callable_cache)
+{
+ gboolean res = FALSE;
+ PyGICallbackCache *callback_cache;
+
+ callback_cache = g_slice_new0 (PyGICallbackCache);
+ if (callback_cache == NULL)
+ return NULL;
+
+ res = pygi_arg_callback_setup_from_info (callback_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info,
+ callable_cache);
+ if (res) {
+ return (PyGIArgCache *)callback_cache;
+ } else {
+ pygi_arg_cache_free ((PyGIArgCache *)callback_cache);
+ return NULL;
+ }
+}
diff --git a/gi/pygi-closure.h b/gi/pygi-closure.h
index 6f98339..8a52b86 100644
--- a/gi/pygi-closure.h
+++ b/gi/pygi-closure.h
@@ -12,9 +12,7 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_CLOSURE_H__
@@ -24,6 +22,8 @@
#include <girffi.h>
#include <ffi.h>
+#include "pygi-cache.h"
+
G_BEGIN_DECLS
@@ -40,17 +40,27 @@ typedef struct _PyGICClosure
GIScopeType scope;
PyObject* user_data;
+
+ PyGIClosureCache *cache;
} PyGICClosure;
void _pygi_closure_handle (ffi_cif *cif, void *result, void
**args, void *userdata);
-void _pygi_invoke_closure_free (gpointer user_data);
+void _pygi_invoke_closure_free (PyGICClosure* invoke_closure);
PyGICClosure* _pygi_make_native_closure (GICallableInfo* info,
+ PyGIClosureCache *cache,
GIScopeType scope,
PyObject *function,
- gpointer user_data);
+ PyObject *user_data);
+
+PyGIArgCache *pygi_arg_callback_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info,
+ PyGICallableCache *callable_cache);
G_END_DECLS
diff --git a/gi/pygi-enum-marshal.c b/gi/pygi-enum-marshal.c
new file mode 100644
index 0000000..15a489d
--- /dev/null
+++ b/gi/pygi-enum-marshal.c
@@ -0,0 +1,407 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include <glib.h>
+
+#include "pygi-enum-marshal.h"
+#include "pygi-type.h"
+#include "pygenum.h"
+#include "pygflags.h"
+
+static gboolean
+gi_argument_from_c_long (GIArgument *arg_out,
+ long c_long_in,
+ GITypeTag type_tag)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_INT8:
+ arg_out->v_int8 = (gint8)c_long_in;
+ return TRUE;
+ case GI_TYPE_TAG_UINT8:
+ arg_out->v_uint8 = (guint8)c_long_in;
+ return TRUE;
+ case GI_TYPE_TAG_INT16:
+ arg_out->v_int16 = (gint16)c_long_in;
+ return TRUE;
+ case GI_TYPE_TAG_UINT16:
+ arg_out->v_uint16 = (guint16)c_long_in;
+ return TRUE;
+ case GI_TYPE_TAG_INT32:
+ arg_out->v_int32 = (gint32)c_long_in;
+ return TRUE;
+ case GI_TYPE_TAG_UINT32:
+ arg_out->v_uint32 = (guint32)c_long_in;
+ return TRUE;
+ case GI_TYPE_TAG_INT64:
+ arg_out->v_int64 = (gint64)c_long_in;
+ return TRUE;
+ case GI_TYPE_TAG_UINT64:
+ arg_out->v_uint64 = (guint64)c_long_in;
+ return TRUE;
+ default:
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal C long %ld to %s",
+ c_long_in,
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+ }
+}
+
+static gboolean
+gi_argument_to_c_long (GIArgument *arg_in,
+ long *c_long_out,
+ GITypeTag type_tag)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_INT8:
+ *c_long_out = arg_in->v_int8;
+ return TRUE;
+ case GI_TYPE_TAG_UINT8:
+ *c_long_out = arg_in->v_uint8;
+ return TRUE;
+ case GI_TYPE_TAG_INT16:
+ *c_long_out = arg_in->v_int16;
+ return TRUE;
+ case GI_TYPE_TAG_UINT16:
+ *c_long_out = arg_in->v_uint16;
+ return TRUE;
+ case GI_TYPE_TAG_INT32:
+ *c_long_out = arg_in->v_int32;
+ return TRUE;
+ case GI_TYPE_TAG_UINT32:
+ *c_long_out = arg_in->v_uint32;
+ return TRUE;
+ case GI_TYPE_TAG_INT64:
+ if (arg_in->v_int64 > G_MAXLONG || arg_in->v_int64 < G_MINLONG) {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to C long",
+ g_type_tag_to_string(type_tag));
+ return FALSE;
+ }
+ *c_long_out = (glong)arg_in->v_int64;
+ return TRUE;
+ case GI_TYPE_TAG_UINT64:
+ if (arg_in->v_uint64 > G_MAXLONG) {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to C long",
+ g_type_tag_to_string(type_tag));
+ return FALSE;
+ }
+ *c_long_out = (glong)arg_in->v_uint64;
+ return TRUE;
+ default:
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to C long",
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+ }
+}
+
+static gboolean
+_pygi_marshal_from_py_interface_enum (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyObject *py_long;
+ long c_long;
+ gint is_instance;
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ GIBaseInfo *interface = NULL;
+
+ is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
+
+ py_long = PyNumber_Long (py_arg);
+ if (py_long == NULL) {
+ PyErr_Clear();
+ goto err;
+ }
+
+ c_long = PyLong_AsLong (py_long);
+ Py_DECREF (py_long);
+
+ /* Write c_long into arg */
+ interface = g_type_info_get_interface (arg_cache->type_info);
+ assert(g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
+ if (!gi_argument_from_c_long(arg,
+ c_long,
+ g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
+ g_assert_not_reached();
+ g_base_info_unref (interface);
+ return FALSE;
+ }
+
+ /* If this is not an instance of the Enum type that we want
+ * we need to check if the value is equivilant to one of the
+ * Enum's memebers */
+ if (!is_instance) {
+ int i;
+ gboolean is_found = FALSE;
+
+ for (i = 0; i < g_enum_info_get_n_values (iface_cache->interface_info); i++) {
+ GIValueInfo *value_info =
+ g_enum_info_get_value (iface_cache->interface_info, i);
+ gint64 enum_value = g_value_info_get_value (value_info);
+ g_base_info_unref ( (GIBaseInfo *)value_info);
+ if (c_long == enum_value) {
+ is_found = TRUE;
+ break;
+ }
+ }
+
+ if (!is_found)
+ goto err;
+ }
+
+ g_base_info_unref (interface);
+ return TRUE;
+
+err:
+ if (interface)
+ g_base_info_unref (interface);
+ PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
+ iface_cache->type_name, Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+}
+
+static gboolean
+_pygi_marshal_from_py_interface_flags (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyObject *py_long;
+ unsigned long c_ulong;
+ gint is_instance;
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ GIBaseInfo *interface;
+
+ is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
+
+ py_long = PyNumber_Long (py_arg);
+ if (py_long == NULL) {
+ PyErr_Clear ();
+ goto err;
+ }
+
+ c_ulong = PyLong_AsUnsignedLongMask (py_long);
+ Py_DECREF (py_long);
+
+ /* only 0 or argument of type Flag is allowed */
+ if (!is_instance && c_ulong != 0)
+ goto err;
+
+ /* Write c_long into arg */
+ interface = g_type_info_get_interface (arg_cache->type_info);
+ g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
+ if (!gi_argument_from_c_long(arg, c_ulong,
+ g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
+ g_base_info_unref (interface);
+ return FALSE;
+ }
+
+ g_base_info_unref (interface);
+ return TRUE;
+
+err:
+ PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
+ iface_cache->type_name, Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+
+}
+
+static PyObject *
+_pygi_marshal_to_py_interface_enum (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyObject *py_obj = NULL;
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ GIBaseInfo *interface;
+ long c_long;
+
+ interface = g_type_info_get_interface (arg_cache->type_info);
+ g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
+
+ if (!gi_argument_to_c_long(arg, &c_long,
+ g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
+ return NULL;
+ }
+
+ if (iface_cache->g_type == G_TYPE_NONE) {
+ py_obj = PyObject_CallFunction (iface_cache->py_type, "l", c_long);
+ } else {
+ py_obj = pyg_enum_from_gtype (iface_cache->g_type, (gint)c_long);
+ }
+ g_base_info_unref (interface);
+ return py_obj;
+}
+
+static PyObject *
+_pygi_marshal_to_py_interface_flags (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyObject *py_obj = NULL;
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ GIBaseInfo *interface;
+ long c_long;
+
+ interface = g_type_info_get_interface (arg_cache->type_info);
+ g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
+
+ if (!gi_argument_to_c_long(arg, &c_long,
+ g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
+ g_base_info_unref (interface);
+ return NULL;
+ }
+
+ g_base_info_unref (interface);
+ if (iface_cache->g_type == G_TYPE_NONE) {
+ /* An enum with a GType of None is an enum without GType */
+
+ PyObject *py_type = pygi_type_import_by_gi_info (iface_cache->interface_info);
+ PyObject *py_args = NULL;
+
+ if (!py_type)
+ return NULL;
+
+ py_args = PyTuple_New (1);
+ if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (c_long)) != 0) {
+ Py_DECREF (py_args);
+ Py_DECREF (py_type);
+ return NULL;
+ }
+
+ py_obj = PyObject_CallFunction (py_type, "l", c_long);
+
+ Py_DECREF (py_args);
+ Py_DECREF (py_type);
+ } else {
+ py_obj = pyg_flags_from_gtype (iface_cache->g_type, (guint)c_long);
+ }
+
+ return py_obj;
+}
+
+static gboolean
+pygi_arg_enum_setup_from_info (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
+
+ return TRUE;
+}
+
+
+PyGIArgCache *
+pygi_arg_enum_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info)
+{
+ gboolean res = FALSE;
+ PyGIArgCache *cache = NULL;
+
+ cache = pygi_arg_interface_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ if (cache == NULL)
+ return NULL;
+
+ res = pygi_arg_enum_setup_from_info (cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction);
+ if (res) {
+ return cache;
+ } else {
+ pygi_arg_cache_free (cache);
+ return NULL;
+ }
+}
+
+static gboolean
+pygi_arg_flags_setup_from_info (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
+
+ return TRUE;
+}
+
+
+PyGIArgCache *
+pygi_arg_flags_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info)
+{
+ gboolean res = FALSE;
+ PyGIArgCache *cache = NULL;
+
+ cache = pygi_arg_interface_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ if (cache == NULL)
+ return NULL;
+
+ res = pygi_arg_flags_setup_from_info (cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction);
+ if (res) {
+ return cache;
+ } else {
+ pygi_arg_cache_free (cache);
+ return NULL;
+ }
+}
diff --git a/gi/pygi-enum-marshal.h b/gi/pygi-enum-marshal.h
new file mode 100644
index 0000000..2fdcbc4
--- /dev/null
+++ b/gi/pygi-enum-marshal.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_ENUM_MARSHAL_H__
+#define __PYGI_ENUM_MARSHAL_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+PyGIArgCache *pygi_arg_enum_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info);
+
+PyGIArgCache *pygi_arg_flags_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info);
+
+G_END_DECLS
+
+#endif /*__PYGI_ENUM_MARSHAL_H__*/
diff --git a/gi/pygi-error.c b/gi/pygi-error.c
new file mode 100644
index 0000000..de6b7c1
--- /dev/null
+++ b/gi/pygi-error.c
@@ -0,0 +1,374 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 1998-2003 James Henstridge
+ * 2004-2008 Johan Dahlin
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include "pygi-error.h"
+#include "pygi-type.h"
+#include "pygi-util.h"
+#include "pygi-basictype.h"
+
+
+PyObject *PyGError = NULL;
+
+/**
+ * pygi_error_marshal_to_py:
+ * @error: a pointer to the GError.
+ *
+ * Checks to see if @error has been set. If @error has been set, then a
+ * GLib.GError Python exception object is returned (but not raised).
+ * If not error is set returns Py_None.
+ *
+ * Returns: a GLib.GError Python exception object, or Py_None,
+ * or NULL and sets an error if creating the exception object fails.
+ */
+PyObject *
+pygi_error_marshal_to_py (GError **error)
+{
+ PyGILState_STATE state;
+ PyObject *exc_type;
+ PyObject *exc_instance;
+ const char *domain = NULL;
+
+ g_return_val_if_fail(error != NULL, NULL);
+
+ if (*error == NULL)
+ Py_RETURN_NONE;
+
+ state = PyGILState_Ensure();
+
+ exc_type = PyGError;
+
+ if ((*error)->domain) {
+ domain = g_quark_to_string ((*error)->domain);
+ }
+
+ exc_instance = PyObject_CallFunction (exc_type, "ssi",
+ (*error)->message,
+ domain,
+ (*error)->code);
+
+ PyGILState_Release(state);
+
+ return exc_instance;
+}
+
+/**
+ * pygi_error_check:
+ * @error: a pointer to the GError.
+ *
+ * Checks to see if the GError has been set. If the error has been
+ * set, then the glib.GError Python exception will be raised, and
+ * the GError cleared.
+ *
+ * Returns: True if an error was set.
+ */
+gboolean
+pygi_error_check (GError **error)
+{
+ PyGILState_STATE state;
+ PyObject *exc_instance;
+
+ g_return_val_if_fail(error != NULL, FALSE);
+ if (*error == NULL)
+ return FALSE;
+
+ state = PyGILState_Ensure();
+
+ exc_instance = pygi_error_marshal_to_py (error);
+ if (exc_instance != NULL) {
+ PyErr_SetObject(PyGError, exc_instance);
+ Py_DECREF(exc_instance);
+ } else {
+ PyErr_Print ();
+ PyErr_SetString (PyExc_RuntimeError, "Converting the GError failed");
+ }
+ g_clear_error(error);
+
+ PyGILState_Release(state);
+
+ return TRUE;
+}
+
+/**
+ * pygi_error_marshal_from_py:
+ * @pyerr: A Python exception instance.
+ * @error: a standard GLib GError ** output parameter
+ *
+ * Converts from a Python implemented GError into a GError.
+ *
+ * Returns: TRUE if the conversion was successful, otherwise a Python exception
+ * is set and FALSE is returned.
+ */
+gboolean
+pygi_error_marshal_from_py (PyObject *pyerr, GError **error)
+{
+ gint code;
+ gchar *message = NULL;
+ gchar *domain = NULL;
+ gboolean res = FALSE;
+ PyObject *py_message = NULL,
+ *py_domain = NULL,
+ *py_code = NULL;
+
+ if (PyObject_IsInstance (pyerr, PyGError) != 1) {
+ PyErr_Format (PyExc_TypeError, "Must be GLib.Error, not %s",
+ Py_TYPE (pyerr)->tp_name);
+ return FALSE;
+ }
+
+ py_message = PyObject_GetAttrString (pyerr, "message");
+ if (!py_message) {
+ PyErr_SetString (PyExc_ValueError,
+ "GLib.Error instances must have a 'message' string attribute");
+ goto cleanup;
+ }
+
+ if (!pygi_utf8_from_py (py_message, &message))
+ goto cleanup;
+
+ py_domain = PyObject_GetAttrString (pyerr, "domain");
+ if (!py_domain) {
+ PyErr_SetString (PyExc_ValueError,
+ "GLib.Error instances must have a 'domain' string attribute");
+ goto cleanup;
+ }
+
+ if (!pygi_utf8_from_py (py_domain, &domain))
+ goto cleanup;
+
+ py_code = PyObject_GetAttrString (pyerr, "code");
+ if (!py_code) {
+ PyErr_SetString (PyExc_ValueError,
+ "GLib.Error instances must have a 'code' int attribute");
+ goto cleanup;
+ }
+
+ if (!pygi_gint_from_py (py_code, &code))
+ goto cleanup;
+
+ res = TRUE;
+ g_set_error_literal (error,
+ g_quark_from_string (domain),
+ code,
+ message);
+
+cleanup:
+ g_free (message);
+ g_free (domain);
+ Py_XDECREF (py_message);
+ Py_XDECREF (py_code);
+ Py_XDECREF (py_domain);
+ return res;
+}
+
+/**
+ * pygi_gerror_exception_check:
+ * @error: a standard GLib GError ** output parameter
+ *
+ * Checks to see if a GError exception has been raised, and if so
+ * translates the python exception to a standard GLib GError. If the
+ * raised exception is not a GError then PyErr_Print() is called.
+ *
+ * Returns: 0 if no exception has been raised, -1 if it is a
+ * valid glib.GError, -2 otherwise.
+ */
+gboolean
+pygi_gerror_exception_check (GError **error)
+{
+ int res = -1;
+ PyObject *type, *value, *traceback;
+ PyErr_Fetch(&type, &value, &traceback);
+ if (type == NULL)
+ return 0;
+ PyErr_NormalizeException(&type, &value, &traceback);
+ if (value == NULL) {
+ PyErr_Restore(type, value, traceback);
+ PyErr_Print();
+ return -2;
+ }
+ if (!value ||
+ !PyErr_GivenExceptionMatches(type,
+ (PyObject *) PyGError)) {
+ PyErr_Restore(type, value, traceback);
+ PyErr_Print();
+ return -2;
+ }
+ Py_DECREF(type);
+ Py_XDECREF(traceback);
+
+ if (!pygi_error_marshal_from_py (value, error)) {
+ PyErr_Print();
+ res = -2;
+ }
+
+ Py_DECREF(value);
+ return res;
+
+}
+
+static gboolean
+_pygi_marshal_from_py_gerror (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ GError *error = NULL;
+ if (pygi_error_marshal_from_py (py_arg, &error)) {
+ arg->v_pointer = error;
+ *cleanup_data = error;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+static void
+_pygi_marshal_from_py_gerror_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (was_processed) {
+ g_error_free ((GError *)data);
+ }
+}
+
+static PyObject *
+_pygi_marshal_to_py_gerror (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ GError *error = arg->v_pointer;
+ PyObject *py_obj = NULL;
+
+ py_obj = pygi_error_marshal_to_py (&error);
+
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) {
+ g_error_free (error);
+ }
+
+ return py_obj;
+}
+
+static gboolean
+pygi_arg_gerror_setup_from_info (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction)) {
+ return FALSE;
+ }
+
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
+
+ /* Assign cleanup function if we manage memory after call completion. */
+ if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+ arg_cache->from_py_cleanup = _pygi_marshal_from_py_gerror_cleanup;
+ }
+ }
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
+ arg_cache->meta_type = PYGI_META_ARG_TYPE_PARENT;
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_gerror_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ gboolean res = FALSE;
+ PyGIArgCache *arg_cache;
+
+ arg_cache = pygi_arg_cache_alloc ();
+
+ res = pygi_arg_gerror_setup_from_info (arg_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction);
+ if (res) {
+ return arg_cache;
+ } else {
+ pygi_arg_cache_free (arg_cache);
+ return NULL;
+ }
+}
+
+static PyObject *
+pygerror_from_gvalue (const GValue *value)
+{
+ GError *gerror = (GError *) g_value_get_boxed (value);
+ PyObject *pyerr = pygi_error_marshal_to_py (&gerror);
+ return pyerr;
+}
+
+static int
+pygerror_to_gvalue (GValue *value, PyObject *pyerror)
+{
+ GError *gerror = NULL;
+
+ if (pygi_error_marshal_from_py (pyerror, &gerror)) {
+ g_value_take_boxed (value, gerror);
+ return 0;
+ }
+
+ return -1;
+}
+
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_error_register_types (PyObject *module)
+{
+ PyObject *error_module = PyImport_ImportModule ("gi._error");
+ if (!error_module) {
+ return -1;
+ }
+
+ /* Stash a reference to the Python implemented gi._error.GError. */
+ PyGError = PyObject_GetAttrString (error_module, "GError");
+ Py_DECREF (error_module);
+ if (PyGError == NULL)
+ return -1;
+
+ pyg_register_gtype_custom (G_TYPE_ERROR,
+ pygerror_from_gvalue,
+ pygerror_to_gvalue);
+
+ return 0;
+}
+
diff --git a/gi/pygi-error.h b/gi/pygi-error.h
new file mode 100644
index 0000000..3e6c414
--- /dev/null
+++ b/gi/pygi-error.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 1998-2003 James Henstridge
+ * 2004-2008 Johan Dahlin
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_ERROR_H__
+#define __PYGI_ERROR_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+extern PyObject *PyGError;
+
+gboolean pygi_error_check (GError **error);
+
+PyObject* pygi_error_marshal_to_py (GError **error);
+
+gboolean pygi_error_marshal_from_py (PyObject *pyerr,
+ GError **error);
+
+gboolean pygi_gerror_exception_check (GError **error);
+
+PyGIArgCache* pygi_arg_gerror_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction);
+
+int pygi_error_register_types (PyObject *module);
+
+G_END_DECLS
+
+#endif /*__PYGI_ERROR_H__*/
diff --git a/gi/pygi-foreign-api.h b/gi/pygi-foreign-api.h
new file mode 100644
index 0000000..9367518
--- /dev/null
+++ b/gi/pygi-foreign-api.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_FOREIGN_API_H__
+#define __PYGI_FOREIGN_API_H__
+
+#include <girepository.h>
+#include <pygobject.h>
+
+typedef PyObject * (*PyGIArgOverrideToGIArgumentFunc) (PyObject *value,
+ GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ GIArgument *arg);
+typedef PyObject * (*PyGIArgOverrideFromGIArgumentFunc) (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data);
+typedef PyObject * (*PyGIArgOverrideReleaseFunc) (GITypeInfo *type_info,
+ gpointer struct_);
+
+
+struct PyGI_API {
+ void (*register_foreign_struct) (const char* namespace_,
+ const char* name,
+ PyGIArgOverrideToGIArgumentFunc to_func,
+ PyGIArgOverrideFromGIArgumentFunc from_func,
+ PyGIArgOverrideReleaseFunc release_func);
+};
+
+
+#ifndef _INSIDE_PYGOBJECT_
+
+static struct PyGI_API *PyGI_API = NULL;
+
+static int
+_pygi_import (void)
+{
+ if (PyGI_API != NULL) {
+ return 1;
+ }
+ PyGI_API = (struct PyGI_API*) PyCapsule_Import("gi._API", FALSE);
+ if (PyGI_API == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static inline PyObject *
+pygi_register_foreign_struct (const char* namespace_,
+ const char* name,
+ PyGIArgOverrideToGIArgumentFunc to_func,
+ PyGIArgOverrideFromGIArgumentFunc from_func,
+ PyGIArgOverrideReleaseFunc release_func)
+{
+ if (_pygi_import() < 0) {
+ return NULL;
+ }
+ PyGI_API->register_foreign_struct(namespace_,
+ name,
+ to_func,
+ from_func,
+ release_func);
+ Py_RETURN_NONE;
+}
+
+#endif /* _INSIDE_PYGOBJECT_ */
+
+#endif /* __PYGI_FOREIGN_API_H__ */
diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c
index 3fe6a39..aa01157 100644
--- a/gi/pygi-foreign-cairo.c
+++ b/gi/pygi-foreign-cairo.c
@@ -21,20 +21,21 @@
* IN THE SOFTWARE.
*/
-#include <cairo.h>
#include <Python.h>
+#include <cairo.h>
+#include <py3cairo.h>
-#if PY_VERSION_HEX < 0x03000000
-#include <pycairo.h>
-static Pycairo_CAPI_t *Pycairo_CAPI;
-#else
-#include <pycairo/py3cairo.h>
-#endif
-
+#include <cairo-gobject.h>
-#include "pygi-foreign.h"
+/* Limit includes from PyGI to APIs which do not have link dependencies
+ * (pygobject.h and pygi-foreign-api.h) since _gi_cairo is built as a separate
+ * shared library that interacts with PyGI through a PyCapsule API at runtime.
+ */
+#include <pygi-foreign-api.h>
-#include <pyglib-python-compat.h>
+/*
+ * cairo_t marshaling
+ */
static PyObject *
cairo_context_to_arg (PyObject *value,
@@ -44,27 +45,37 @@ cairo_context_to_arg (PyObject *value,
{
cairo_t *cr;
- g_assert (transfer == GI_TRANSFER_NOTHING);
+ if (!PyObject_TypeCheck (value, &PycairoContext_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Context");
+ return NULL;
+ }
cr = PycairoContext_GET (value);
if (!cr) {
return NULL;
}
+ if (transfer != GI_TRANSFER_NOTHING)
+ cr = cairo_reference (cr);
+
arg->v_pointer = cr;
Py_RETURN_NONE;
}
static PyObject *
-cairo_context_from_arg (GIInterfaceInfo *interface_info, gpointer data)
+cairo_context_from_arg (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data)
{
cairo_t *context = (cairo_t*) data;
- cairo_reference (context);
+ if (transfer == GI_TRANSFER_NOTHING)
+ cairo_reference (context);
return PycairoContext_FromContext (context, &PycairoContext_Type, NULL);
}
+
static PyObject *
cairo_context_release (GIBaseInfo *base_info,
gpointer struct_)
@@ -73,6 +84,43 @@ cairo_context_release (GIBaseInfo *base_info,
Py_RETURN_NONE;
}
+static int
+cairo_context_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_t *cr;
+
+ if (!PyObject_TypeCheck (obj, &PycairoContext_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Context");
+ return -1;
+ }
+
+ cr = PycairoContext_GET (obj);
+ if (!cr) {
+ return -1;
+ }
+
+ /* PycairoContext_GET returns a borrowed reference, use set_boxed
+ * to add new ref to the context which will be managed by the GValue. */
+ g_value_set_boxed (value, cr);
+ return 0;
+}
+
+static PyObject *
+cairo_context_from_gvalue (const GValue *value)
+{
+ /* PycairoContext_FromContext steals a ref, so we dup it out of the GValue. */
+ cairo_t *cr = g_value_dup_boxed (value);
+ if (!cr) {
+ Py_RETURN_NONE;
+ }
+
+ return PycairoContext_FromContext (cr, &PycairoContext_Type, NULL);
+}
+
+
+/*
+ * cairo_surface_t marshaling
+ */
static PyObject *
cairo_surface_to_arg (PyObject *value,
@@ -82,7 +130,10 @@ cairo_surface_to_arg (PyObject *value,
{
cairo_surface_t *surface;
- g_assert (transfer == GI_TRANSFER_NOTHING);
+ if (!PyObject_TypeCheck (value, &PycairoSurface_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Surface");
+ return NULL;
+ }
surface = ( (PycairoSurface*) value)->surface;
if (!surface) {
@@ -90,16 +141,22 @@ cairo_surface_to_arg (PyObject *value,
return NULL;
}
+ if (transfer != GI_TRANSFER_NOTHING)
+ surface = cairo_surface_reference (surface);
+
arg->v_pointer = surface;
Py_RETURN_NONE;
}
static PyObject *
-cairo_surface_from_arg (GIInterfaceInfo *interface_info, gpointer data)
+cairo_surface_from_arg (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data)
{
cairo_surface_t *surface = (cairo_surface_t*) data;
- cairo_surface_reference (surface);
+ if (transfer == GI_TRANSFER_NOTHING)
+ cairo_surface_reference (surface);
return PycairoSurface_FromSurface (surface, NULL);
}
@@ -112,6 +169,59 @@ cairo_surface_release (GIBaseInfo *base_info,
Py_RETURN_NONE;
}
+static int
+cairo_surface_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_surface_t *surface;
+
+ if (!PyObject_TypeCheck (obj, &PycairoSurface_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Surface");
+ return -1;
+ }
+
+ surface = ((PycairoSurface*) obj)->surface;
+ if (!surface) {
+ return -1;
+ }
+
+ /* surface is a borrowed reference, use set_boxed
+ * to add new ref to the context which will be managed by the GValue. */
+ g_value_set_boxed (value, surface);
+ return 0;
+}
+
+static PyObject *
+cairo_surface_from_gvalue (const GValue *value)
+{
+ /* PycairoSurface_FromSurface steals a ref, so we dup it out of the GValue. */
+ cairo_surface_t *surface = g_value_dup_boxed (value);
+ if (!surface) {
+ Py_RETURN_NONE;
+ }
+
+ return PycairoSurface_FromSurface (surface, NULL);
+}
+
+
+/*
+ * cairo_path_t marshaling
+ */
+
+static cairo_path_t *
+_cairo_path_copy (cairo_path_t *path) {
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ cairo_path_t *copy;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
+ cr = cairo_create (surface);
+ cairo_append_path (cr, path);
+ copy = cairo_copy_path (cr);
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+
+ return copy;
+}
static PyObject *
cairo_path_to_arg (PyObject *value,
@@ -121,7 +231,10 @@ cairo_path_to_arg (PyObject *value,
{
cairo_path_t *path;
- g_assert (transfer == GI_TRANSFER_NOTHING);
+ if (!PyObject_TypeCheck (value, &PycairoPath_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Path");
+ return NULL;
+ }
path = ( (PycairoPath*) value)->path;
if (!path) {
@@ -129,15 +242,25 @@ cairo_path_to_arg (PyObject *value,
return NULL;
}
+ if (transfer != GI_TRANSFER_NOTHING)
+ path = _cairo_path_copy (path);
+
arg->v_pointer = path;
Py_RETURN_NONE;
}
static PyObject *
-cairo_path_from_arg (GIInterfaceInfo *interface_info, gpointer data)
+cairo_path_from_arg (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data)
{
cairo_path_t *path = (cairo_path_t*) data;
+ if (transfer == GI_TRANSFER_NOTHING) {
+ PyErr_SetString(PyExc_TypeError, "Unsupported annotation (transfer none) for cairo.Path return");
+ return NULL;
+ }
+
return PycairoPath_FromPath (path);
}
@@ -149,6 +272,46 @@ cairo_path_release (GIBaseInfo *base_info,
Py_RETURN_NONE;
}
+
+/*
+ * cairo_font_face_t marshaling
+ */
+
+static int
+cairo_font_face_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_font_face_t *font_face;
+
+ if (!PyObject_TypeCheck (obj, &PycairoFontFace_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.FontFace");
+ return -1;
+ }
+
+ font_face = ((PycairoFontFace*) obj)->font_face;
+ if (!font_face) {
+ return -1;
+ }
+
+ g_value_set_boxed (value, font_face);
+ return 0;
+}
+
+static PyObject *
+cairo_font_face_from_gvalue (const GValue *value)
+{
+ cairo_font_face_t *font_face = g_value_dup_boxed (value);
+ if (!font_face) {
+ Py_RETURN_NONE;
+ }
+
+ return PycairoFontFace_FromFontFace (font_face);
+}
+
+
+/*
+ * cairo_font_options_t marshaling
+ */
+
static PyObject *
cairo_font_options_to_arg (PyObject *value,
GIInterfaceInfo *interface_info,
@@ -157,7 +320,10 @@ cairo_font_options_to_arg (PyObject *value,
{
cairo_font_options_t *font_options;
- g_assert (transfer == GI_TRANSFER_NOTHING);
+ if (!PyObject_TypeCheck (value, &PycairoFontOptions_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.FontOptions");
+ return NULL;
+ }
font_options = ( (PycairoFontOptions*) value)->font_options;
if (!font_options) {
@@ -165,16 +331,24 @@ cairo_font_options_to_arg (PyObject *value,
return NULL;
}
+ if (transfer != GI_TRANSFER_NOTHING)
+ font_options = cairo_font_options_copy (font_options);
+
arg->v_pointer = font_options;
Py_RETURN_NONE;
}
static PyObject *
-cairo_font_options_from_arg (GIInterfaceInfo *interface_info, gpointer data)
+cairo_font_options_from_arg (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data)
{
cairo_font_options_t *font_options = (cairo_font_options_t*) data;
- return PycairoFontOptions_FromFontOptions (cairo_font_options_copy (font_options));
+ if (transfer == GI_TRANSFER_NOTHING)
+ font_options = cairo_font_options_copy (font_options);
+
+ return PycairoFontOptions_FromFontOptions (font_options);
}
static PyObject *
@@ -185,17 +359,297 @@ cairo_font_options_release (GIBaseInfo *base_info,
Py_RETURN_NONE;
}
-static PyMethodDef _gi_cairo_functions[] = { {0,} };
-PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo")
+
+/*
+ * scaled_font_t marshaling
+ */
+
+static int
+cairo_scaled_font_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_scaled_font_t *scaled_font;
+
+ if (!PyObject_TypeCheck (obj, &PycairoScaledFont_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.ScaledFont");
+ return -1;
+ }
+
+ scaled_font = ((PycairoScaledFont*) obj)->scaled_font;
+ if (!scaled_font) {
+ return -1;
+ }
+
+ /* scaled_font is a borrowed reference, use set_boxed
+ * to add new ref to the context which will be managed by the GValue. */
+ g_value_set_boxed (value, scaled_font);
+ return 0;
+}
+
+static PyObject *
+cairo_scaled_font_from_gvalue (const GValue *value)
+{
+ /* PycairoScaledFont_FromScaledFont steals a ref, so we dup it out of the GValue. */
+ cairo_scaled_font_t *scaled_font = g_value_dup_boxed (value);
+ if (!scaled_font) {
+ Py_RETURN_NONE;
+ }
+
+ return PycairoScaledFont_FromScaledFont (scaled_font);
+}
+
+
+/*
+ * cairo_pattern_t marshaling
+ */
+
+static PyObject *
+cairo_pattern_to_arg (PyObject *value,
+ GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ GIArgument *arg)
+{
+ cairo_pattern_t *pattern;
+
+ if (!PyObject_TypeCheck (value, &PycairoPattern_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Pattern");
+ return NULL;
+ }
+
+ pattern = ((PycairoPattern*) value)->pattern;
+ if (!pattern) {
+ PyErr_SetString (PyExc_ValueError, "Pattern instance wrapping a NULL pattern");
+ return NULL;
+ }
+
+ if (transfer != GI_TRANSFER_NOTHING)
+ pattern = cairo_pattern_reference (pattern);
+
+ arg->v_pointer = pattern;
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+cairo_pattern_from_arg (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data)
+{
+ cairo_pattern_t *pattern = (cairo_pattern_t*) data;
+
+ if (transfer == GI_TRANSFER_NOTHING)
+ pattern = cairo_pattern_reference (pattern);
+
+ return PycairoPattern_FromPattern (pattern, NULL);
+}
+
+static PyObject *
+cairo_pattern_release (GIBaseInfo *base_info,
+ gpointer struct_)
+{
+ cairo_pattern_destroy ( (cairo_pattern_t*) struct_);
+ Py_RETURN_NONE;
+}
+
+static int
+cairo_pattern_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_pattern_t *pattern;
+
+ if (!PyObject_TypeCheck (obj, &PycairoPattern_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Pattern");
+ return -1;
+ }
+
+ pattern = ((PycairoPattern*) obj)->pattern;
+ if (!pattern) {
+ return -1;
+ }
+
+ /* pattern is a borrowed reference, use set_boxed
+ * to add new ref to the context which will be managed by the GValue. */
+ g_value_set_boxed (value, pattern);
+ return 0;
+}
+
+static PyObject *
+cairo_pattern_from_gvalue (const GValue *value)
{
-#if PY_VERSION_HEX < 0x03000000
- Pycairo_IMPORT;
+ /* PycairoPattern_FromPattern steals a ref, so we dup it out of the GValue. */
+ cairo_pattern_t *pattern = g_value_dup_boxed (value);
+ if (!pattern) {
+ Py_RETURN_NONE;
+ }
+
+ return PycairoPattern_FromPattern (pattern, NULL);
+}
+
+static PyObject *
+cairo_region_to_arg (PyObject *value,
+ GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ GIArgument *arg)
+{
+ cairo_region_t *region;
+
+ if (!PyObject_TypeCheck (value, &PycairoRegion_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Region");
+ return NULL;
+ }
+
+ region = ( (PycairoRegion*) value)->region;
+ if (!region) {
+ PyErr_SetString (PyExc_ValueError, "Region instance wrapping a NULL region");
+ return NULL;
+ }
+
+ if (transfer != GI_TRANSFER_NOTHING)
+ region = cairo_region_copy (region);
+
+ arg->v_pointer = region;
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+cairo_region_from_arg (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data)
+{
+ cairo_region_t *region = (cairo_region_t*) data;
+
+ if (transfer == GI_TRANSFER_NOTHING)
+ cairo_region_reference (region);
+
+ return PycairoRegion_FromRegion (region);
+}
+
+static PyObject *
+cairo_region_release (GIBaseInfo *base_info,
+ gpointer struct_)
+{
+ cairo_region_destroy ( (cairo_region_t*) struct_);
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+cairo_matrix_from_arg (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ gpointer data)
+{
+ cairo_matrix_t *matrix = (cairo_matrix_t*) data;
+
+ if (transfer != GI_TRANSFER_NOTHING) {
+ PyErr_SetString(PyExc_TypeError, "Unsupported annotation (transfer full) for cairo.Matrix");
+ return NULL;
+ }
+
+ if (matrix == NULL) {
+ /* NULL in case of caller-allocates */
+ cairo_matrix_t temp = {0};
+ return PycairoMatrix_FromMatrix (&temp);
+ }
+
+ return PycairoMatrix_FromMatrix (matrix);
+}
+
+static PyObject *
+cairo_matrix_to_arg (PyObject *value,
+ GIInterfaceInfo *interface_info,
+ GITransfer transfer,
+ GIArgument *arg)
+{
+ cairo_matrix_t *matrix;
+
+ if (!PyObject_TypeCheck (value, &PycairoMatrix_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Matrix");
+ return NULL;
+ }
+
+ matrix = &(( (PycairoMatrix*) value)->matrix);
+
+ arg->v_pointer = matrix;
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+cairo_matrix_release (GIBaseInfo *base_info,
+ gpointer struct_)
+{
+ Py_RETURN_NONE;
+}
+
+static int
+cairo_matrix_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_matrix_t *matrix;
+
+ if (!PyObject_TypeCheck (obj, &PycairoMatrix_Type)) {
+ PyErr_SetString (PyExc_TypeError, "Expected cairo.Matrix");
+ return -1;
+ }
+
+ matrix = &(( (PycairoMatrix*) obj)->matrix);
+ if (!matrix) {
+ return -1;
+ }
+
+ g_value_set_boxed (value, matrix);
+ return 0;
+}
+
+static PyObject *
+cairo_matrix_from_gvalue (const GValue *value)
+{
+ cairo_matrix_t *matrix = g_value_get_boxed(value);
+ if (!matrix) {
+ Py_RETURN_NONE;
+ }
+
+ return PycairoMatrix_FromMatrix (matrix);
+}
+
+#ifdef __GNUC__
+#define PYGI_MODINIT_FUNC __attribute__((visibility("default"))) PyMODINIT_FUNC
#else
- import_cairo();
+#define PYGI_MODINIT_FUNC PyMODINIT_FUNC
#endif
+static PyMethodDef _gi_cairo_functions[] = { {0,} };
+
+static struct PyModuleDef __gi_cairomodule = {
+ PyModuleDef_HEAD_INIT,
+ "_gi_cairo",
+ NULL,
+ -1,
+ _gi_cairo_functions,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PYGI_MODINIT_FUNC PyInit__gi_cairo (void);
+
+PYGI_MODINIT_FUNC PyInit__gi_cairo (void)
+{
+ PyObject *module;
+ module = PyModule_Create (&__gi_cairomodule);
+
+ PyObject *gobject_mod;
+
+ import_cairo();
+
if (Pycairo_CAPI == NULL)
- return PYGLIB_MODULE_ERROR_RETURN;
+ return NULL;
+
+ gobject_mod = pygobject_init (3, 13, 2);
+ if (gobject_mod == NULL)
+ return NULL;
+ Py_DECREF (gobject_mod);
+
+ pygi_register_foreign_struct ("cairo",
+ "Matrix",
+ cairo_matrix_to_arg,
+ cairo_matrix_from_arg,
+ cairo_matrix_release);
pygi_register_foreign_struct ("cairo",
"Context",
@@ -220,5 +674,42 @@ PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo")
cairo_font_options_to_arg,
cairo_font_options_from_arg,
cairo_font_options_release);
-}
-PYGLIB_MODULE_END;
+
+ pygi_register_foreign_struct ("cairo",
+ "Pattern",
+ cairo_pattern_to_arg,
+ cairo_pattern_from_arg,
+ cairo_pattern_release);
+
+ pygi_register_foreign_struct ("cairo",
+ "Region",
+ cairo_region_to_arg,
+ cairo_region_from_arg,
+ cairo_region_release);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_MATRIX,
+ cairo_matrix_from_gvalue,
+ cairo_matrix_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_CONTEXT,
+ cairo_context_from_gvalue,
+ cairo_context_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_SURFACE,
+ cairo_surface_from_gvalue,
+ cairo_surface_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_FONT_FACE,
+ cairo_font_face_from_gvalue,
+ cairo_font_face_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_SCALED_FONT,
+ cairo_scaled_font_from_gvalue,
+ cairo_scaled_font_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_PATTERN,
+ cairo_pattern_from_gvalue,
+ cairo_pattern_to_gvalue);
+
+ return module;
+} \ No newline at end of file
diff --git a/gi/pygi-foreign.c b/gi/pygi-foreign.c
index 7537399..80a19f7 100644
--- a/gi/pygi-foreign.c
+++ b/gi/pygi-foreign.c
@@ -22,11 +22,9 @@
* IN THE SOFTWARE.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
-#include "pygobject.h"
+#include "pygobject-internal.h"
#include "pygi-foreign.h"
#include <girepository.h>
@@ -50,7 +48,7 @@ init_foreign_structs (void)
static PyGIForeignStruct *
do_lookup (const gchar *namespace, const gchar *name)
{
- gint i;
+ guint i;
for (i = 0; i < foreign_structs->len; i++) {
PyGIForeignStruct *foreign_struct = \
g_ptr_array_index (foreign_structs, i);
@@ -63,24 +61,24 @@ do_lookup (const gchar *namespace, const gchar *name)
return NULL;
}
+static PyObject *
+pygi_struct_foreign_load_module (const char *namespace)
+{
+ gchar *module_name = g_strconcat ("gi._gi_", namespace, NULL);
+ PyObject *module = PyImport_ImportModule (module_name);
+ g_free (module_name);
+ return module;
+}
+
static PyGIForeignStruct *
-pygi_struct_foreign_lookup (GIBaseInfo *base_info)
+pygi_struct_foreign_lookup_by_name (const char *namespace, const char *name)
{
PyGIForeignStruct *result;
- const gchar *namespace = g_base_info_get_namespace (base_info);
- const gchar *name = g_base_info_get_name (base_info);
-
- if (foreign_structs == NULL) {
- init_foreign_structs ();
- }
result = do_lookup (namespace, name);
if (result == NULL) {
- gchar *module_name = g_strconcat ("gi._gi_", namespace, NULL);
- PyObject *module = PyImport_ImportModule (module_name);
-
- g_free (module_name);
+ PyObject *module = pygi_struct_foreign_load_module (namespace);
if (module == NULL)
PyErr_Clear ();
@@ -92,7 +90,7 @@ pygi_struct_foreign_lookup (GIBaseInfo *base_info)
if (result == NULL) {
PyErr_Format (PyExc_TypeError,
- "Couldn't find conversion for foreign struct '%s.%s'",
+ "Couldn't find foreign struct converter for '%s.%s'",
namespace,
name);
}
@@ -100,6 +98,15 @@ pygi_struct_foreign_lookup (GIBaseInfo *base_info)
return result;
}
+static PyGIForeignStruct *
+pygi_struct_foreign_lookup (GIBaseInfo *base_info)
+{
+ const gchar *namespace = g_base_info_get_namespace (base_info);
+ const gchar *name = g_base_info_get_name (base_info);
+
+ return pygi_struct_foreign_lookup_by_name (namespace, name);
+}
+
PyObject *
pygi_struct_foreign_convert_to_g_argument (PyObject *value,
GIInterfaceInfo *interface_info,
@@ -123,6 +130,7 @@ pygi_struct_foreign_convert_to_g_argument (PyObject *value,
PyObject *
pygi_struct_foreign_convert_from_g_argument (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
GIArgument *arg)
{
GIBaseInfo *base_info = (GIBaseInfo *) interface_info;
@@ -131,7 +139,7 @@ pygi_struct_foreign_convert_from_g_argument (GIInterfaceInfo *interface_info,
if (foreign_struct == NULL)
return NULL;
- return foreign_struct->from_func (interface_info, arg);
+ return foreign_struct->from_func (interface_info, transfer, arg);
}
PyObject *
@@ -150,11 +158,11 @@ pygi_struct_foreign_release (GIBaseInfo *base_info,
}
void
-pygi_register_foreign_struct_real (const char* namespace_,
- const char* name,
- PyGIArgOverrideToGIArgumentFunc to_func,
- PyGIArgOverrideFromGIArgumentFunc from_func,
- PyGIArgOverrideReleaseFunc release_func)
+pygi_register_foreign_struct (const char* namespace_,
+ const char* name,
+ PyGIArgOverrideToGIArgumentFunc to_func,
+ PyGIArgOverrideFromGIArgumentFunc from_func,
+ PyGIArgOverrideReleaseFunc release_func)
{
PyGIForeignStruct *new_struct = g_slice_new (PyGIForeignStruct);
new_struct->namespace = namespace_;
@@ -165,3 +173,63 @@ pygi_register_foreign_struct_real (const char* namespace_,
g_ptr_array_add (foreign_structs, new_struct);
}
+
+PyObject *
+pygi_require_foreign (PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "namespace", "symbol", NULL };
+ const char *namespace = NULL;
+ const char *symbol = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+ "s|z:require_foreign",
+ kwlist, &namespace, &symbol)) {
+ return NULL;
+ }
+
+ if (symbol) {
+ PyGIForeignStruct *foreign;
+ foreign = pygi_struct_foreign_lookup_by_name (namespace, symbol);
+ if (foreign == NULL) {
+ return NULL;
+ }
+ } else {
+ PyObject *module = pygi_struct_foreign_load_module (namespace);
+ if (module) {
+ Py_DECREF (module);
+ } else {
+ return NULL;
+ }
+ }
+
+ Py_RETURN_NONE;
+}
+
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_foreign_init (void)
+{
+ if (foreign_structs == NULL) {
+ init_foreign_structs ();
+ }
+
+ return 0;
+}
+
+
+PyObject *pygi_register_foreign (PyObject *self, PyObject *args)
+{
+ /* We need to try loading the foreign modules upfront so the GType
+ * converters are registered:
+ * https://gitlab.gnome.org/GNOME/pygobject/issues/260
+ */
+ PyObject *mod = pygi_struct_foreign_load_module ("cairo");
+ if (mod == NULL)
+ PyErr_Clear ();
+ else
+ Py_DECREF (mod);
+
+ Py_RETURN_NONE;
+}
diff --git a/gi/pygi-foreign.h b/gi/pygi-foreign.h
index dd5f896..d4c50dd 100644
--- a/gi/pygi-foreign.h
+++ b/gi/pygi-foreign.h
@@ -26,23 +26,30 @@
#define __PYGI_FOREIGN_H__
#include <Python.h>
-#include <girepository.h>
-
-#include "pygi.h"
+#include "pygi-foreign-api.h"
PyObject *pygi_struct_foreign_convert_to_g_argument (PyObject *value,
GIInterfaceInfo *interface_info,
GITransfer transfer,
GIArgument *arg);
PyObject *pygi_struct_foreign_convert_from_g_argument (GIInterfaceInfo *interface_info,
+ GITransfer transfer,
GIArgument *arg);
PyObject *pygi_struct_foreign_release (GITypeInfo *type_info,
gpointer struct_);
-void pygi_register_foreign_struct_real (const char* namespace_,
- const char* name,
- PyGIArgOverrideToGIArgumentFunc to_func,
- PyGIArgOverrideFromGIArgumentFunc from_func,
- PyGIArgOverrideReleaseFunc release_func);
+void pygi_register_foreign_struct (const char* namespace_,
+ const char* name,
+ PyGIArgOverrideToGIArgumentFunc to_func,
+ PyGIArgOverrideFromGIArgumentFunc from_func,
+ PyGIArgOverrideReleaseFunc release_func);
+
+PyObject *pygi_require_foreign (PyObject *self,
+ PyObject *args,
+ PyObject *kwargs);
+
+int pygi_foreign_init (void);
+
+PyObject *pygi_register_foreign (PyObject *self, PyObject *args);
#endif /* __PYGI_FOREIGN_H__ */
diff --git a/gi/pygi-hashtable.c b/gi/pygi-hashtable.c
new file mode 100644
index 0000000..26d5f61
--- /dev/null
+++ b/gi/pygi-hashtable.c
@@ -0,0 +1,420 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include "pygi-hashtable.h"
+#include "pygi-argument.h"
+#include "pygi-util.h"
+
+typedef struct _PyGIHashCache
+{
+ PyGIArgCache arg_cache;
+ PyGIArgCache *key_cache;
+ PyGIArgCache *value_cache;
+} PyGIHashCache;
+
+
+static void
+_hash_cache_free_func (PyGIHashCache *cache)
+{
+ if (cache != NULL) {
+ pygi_arg_cache_free (cache->key_cache);
+ pygi_arg_cache_free (cache->value_cache);
+ g_slice_free (PyGIHashCache, cache);
+ }
+}
+
+static gboolean
+_pygi_marshal_from_py_ghash (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyGIMarshalFromPyFunc key_from_py_marshaller;
+ PyGIMarshalFromPyFunc value_from_py_marshaller;
+
+ int i;
+ Py_ssize_t length;
+ PyObject *py_keys, *py_values;
+
+ GHashFunc hash_func;
+ GEqualFunc equal_func;
+
+ GHashTable *hash_ = NULL;
+ PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+
+ py_keys = PyMapping_Keys (py_arg);
+ if (py_keys == NULL) {
+ PyErr_Format (PyExc_TypeError, "Must be mapping, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ length = PyMapping_Length (py_arg);
+ if (length < 0) {
+ Py_DECREF (py_keys);
+ return FALSE;
+ }
+
+ py_values = PyMapping_Values (py_arg);
+ if (py_values == NULL) {
+ Py_DECREF (py_keys);
+ return FALSE;
+ }
+
+ key_from_py_marshaller = hash_cache->key_cache->from_py_marshaller;
+ value_from_py_marshaller = hash_cache->value_cache->from_py_marshaller;
+
+ switch (hash_cache->key_cache->type_tag) {
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ hash_func = g_str_hash;
+ equal_func = g_str_equal;
+ break;
+ default:
+ hash_func = NULL;
+ equal_func = NULL;
+ }
+
+ hash_ = g_hash_table_new (hash_func, equal_func);
+ if (hash_ == NULL) {
+ PyErr_NoMemory ();
+ Py_DECREF (py_keys);
+ Py_DECREF (py_values);
+ return FALSE;
+ }
+
+ for (i = 0; i < length; i++) {
+ GIArgument key, value;
+ gpointer key_cleanup_data = NULL;
+ gpointer value_cleanup_data = NULL;
+ PyObject *py_key = PyList_GET_ITEM (py_keys, i);
+ PyObject *py_value = PyList_GET_ITEM (py_values, i);
+ if (py_key == NULL || py_value == NULL)
+ goto err;
+
+ if (!key_from_py_marshaller ( state,
+ callable_cache,
+ hash_cache->key_cache,
+ py_key,
+ &key,
+ &key_cleanup_data))
+ goto err;
+
+ if (!value_from_py_marshaller ( state,
+ callable_cache,
+ hash_cache->value_cache,
+ py_value,
+ &value,
+ &value_cleanup_data))
+ goto err;
+
+ g_hash_table_insert (hash_,
+ _pygi_arg_to_hash_pointer (&key, hash_cache->key_cache->type_info),
+ _pygi_arg_to_hash_pointer (&value, hash_cache->value_cache->type_info));
+ continue;
+err:
+ /* FIXME: cleanup hash keys and values */
+ Py_DECREF (py_keys);
+ Py_DECREF (py_values);
+ g_hash_table_unref (hash_);
+ _PyGI_ERROR_PREFIX ("Item %i: ", i);
+ return FALSE;
+ }
+
+ arg->v_pointer = hash_;
+
+ if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+ /* Free everything in cleanup. */
+ *cleanup_data = arg->v_pointer;
+ } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+ /* Make a shallow copy so we can free the elements later in cleanup
+ * because it is possible invoke will free the list before our cleanup. */
+ *cleanup_data = g_hash_table_ref (arg->v_pointer);
+ } else { /* GI_TRANSFER_EVERYTHING */
+ /* No cleanup, everything is given to the callee.
+ * Note that the keys and values will leak for transfer everything because
+ * we do not use g_hash_table_new_full and set key/value_destroy_func. */
+ *cleanup_data = NULL;
+ }
+
+ return TRUE;
+}
+
+static void
+_pygi_marshal_cleanup_from_py_ghash (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (data == NULL)
+ return;
+
+ if (was_processed) {
+ GHashTable *hash_;
+ PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
+
+ hash_ = (GHashTable *)data;
+
+ /* clean up keys and values first */
+ if (hash_cache->key_cache->from_py_cleanup != NULL ||
+ hash_cache->value_cache->from_py_cleanup != NULL) {
+ GHashTableIter hiter;
+ gpointer key;
+ gpointer value;
+
+ PyGIMarshalCleanupFunc key_cleanup_func =
+ hash_cache->key_cache->from_py_cleanup;
+ PyGIMarshalCleanupFunc value_cleanup_func =
+ hash_cache->value_cache->from_py_cleanup;
+
+ g_hash_table_iter_init (&hiter, hash_);
+ while (g_hash_table_iter_next (&hiter, &key, &value)) {
+ if (key != NULL && key_cleanup_func != NULL)
+ key_cleanup_func (state,
+ hash_cache->key_cache,
+ NULL,
+ key,
+ TRUE);
+ if (value != NULL && value_cleanup_func != NULL)
+ value_cleanup_func (state,
+ hash_cache->value_cache,
+ NULL,
+ value,
+ TRUE);
+ }
+ }
+
+ g_hash_table_unref (hash_);
+ }
+}
+
+static PyObject *
+_pygi_marshal_to_py_ghash (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ GHashTable *hash_;
+ GHashTableIter hash_table_iter;
+
+ PyGIMarshalToPyFunc key_to_py_marshaller;
+ PyGIMarshalToPyFunc value_to_py_marshaller;
+
+ PyGIArgCache *key_arg_cache;
+ PyGIArgCache *value_arg_cache;
+ PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
+
+ GIArgument key_arg;
+ GIArgument value_arg;
+
+ PyObject *py_obj = NULL;
+
+ hash_ = arg->v_pointer;
+
+ if (hash_ == NULL) {
+ py_obj = Py_None;
+ Py_INCREF (py_obj);
+ return py_obj;
+ }
+
+ py_obj = PyDict_New ();
+ if (py_obj == NULL)
+ return NULL;
+
+ key_arg_cache = hash_cache->key_cache;
+ key_to_py_marshaller = key_arg_cache->to_py_marshaller;
+
+ value_arg_cache = hash_cache->value_cache;
+ value_to_py_marshaller = value_arg_cache->to_py_marshaller;
+
+ g_hash_table_iter_init (&hash_table_iter, hash_);
+ while (g_hash_table_iter_next (&hash_table_iter,
+ &key_arg.v_pointer,
+ &value_arg.v_pointer)) {
+ gpointer key_cleanup_data = NULL;
+ gpointer value_cleanup_data = NULL;
+ PyObject *py_key;
+ PyObject *py_value;
+ int retval;
+
+
+ _pygi_hash_pointer_to_arg (&key_arg, hash_cache->key_cache->type_info);
+ py_key = key_to_py_marshaller ( state,
+ callable_cache,
+ key_arg_cache,
+ &key_arg,
+ &key_cleanup_data);
+
+ if (py_key == NULL) {
+ Py_CLEAR (py_obj);
+ return NULL;
+ }
+
+ _pygi_hash_pointer_to_arg (&value_arg, hash_cache->value_cache->type_info);
+ py_value = value_to_py_marshaller ( state,
+ callable_cache,
+ value_arg_cache,
+ &value_arg,
+ &value_cleanup_data);
+
+ if (py_value == NULL) {
+ Py_CLEAR (py_obj);
+ Py_DECREF(py_key);
+ return NULL;
+ }
+
+ retval = PyDict_SetItem (py_obj, py_key, py_value);
+
+ Py_DECREF (py_key);
+ Py_DECREF (py_value);
+
+ if (retval < 0) {
+ Py_CLEAR (py_obj);
+ return NULL;
+ }
+ }
+
+ return py_obj;
+}
+
+static void
+_pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer cleanup_data,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (data == NULL)
+ return;
+
+ /* assume hashtable has boxed key and value */
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER)
+ g_hash_table_unref ( (GHashTable *)data);
+}
+
+static void
+_arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash;
+}
+
+static void
+_arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash;
+}
+
+static gboolean
+pygi_arg_hash_table_setup_from_info (PyGIHashCache *hc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
+{
+ GITypeInfo *key_type_info;
+ GITypeInfo *value_type_info;
+ GITransfer item_transfer;
+
+ if (!pygi_arg_base_setup ((PyGIArgCache *)hc, type_info, arg_info, transfer, direction))
+ return FALSE;
+
+ ( (PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
+ key_type_info = g_type_info_get_param_type (type_info, 0);
+ value_type_info = g_type_info_get_param_type (type_info, 1);
+
+ item_transfer =
+ transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
+
+ hc->key_cache = pygi_arg_cache_new (key_type_info,
+ NULL,
+ item_transfer,
+ direction,
+ callable_cache,
+ 0, 0);
+
+ if (hc->key_cache == NULL) {
+ return FALSE;
+ }
+
+ hc->value_cache = pygi_arg_cache_new (value_type_info,
+ NULL,
+ item_transfer,
+ direction,
+ callable_cache,
+ 0, 0);
+
+ if (hc->value_cache == NULL) {
+ return FALSE;
+ }
+
+ g_base_info_unref( (GIBaseInfo *)key_type_info);
+ g_base_info_unref( (GIBaseInfo *)value_type_info);
+
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ _arg_cache_from_py_ghash_setup ((PyGIArgCache *)hc);
+ }
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ _arg_cache_to_py_ghash_setup ((PyGIArgCache *)hc);
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_hash_table_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
+{
+ gboolean res = FALSE;
+ PyGIHashCache *hc = NULL;
+
+ hc = g_slice_new0 (PyGIHashCache);
+ if (hc == NULL)
+ return NULL;
+
+ res = pygi_arg_hash_table_setup_from_info (hc,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache);
+ if (res) {
+ return (PyGIArgCache *)hc;
+ } else {
+ pygi_arg_cache_free ((PyGIArgCache *)hc);
+ return NULL;
+ }
+}
diff --git a/gi/pygi-hashtable.h b/gi/pygi-hashtable.h
new file mode 100644
index 0000000..74cd04f
--- /dev/null
+++ b/gi/pygi-hashtable.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_HASHTABLE_H__
+#define __PYGI_HASHTABLE_H__
+
+#include "pygi-cache.h"
+#include <girepository.h>
+
+G_BEGIN_DECLS
+
+PyGIArgCache *pygi_arg_hash_table_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache);
+
+G_END_DECLS
+
+#endif /*__PYGI_HASHTABLE_H__*/
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 7164ff9..08c76db 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -2,6 +2,7 @@
* vim: tabstop=4 shiftwidth=4 expandtab
*
* Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org>
+ * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
*
* pygi-info.c: GI.*Info wrappers.
*
@@ -16,17 +17,17 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include "pygi-info.h"
#include "pygi-cache.h"
-
-#include <pygobject.h>
-#include <pyglib-python-compat.h>
-
+#include "pygi-invoke.h"
+#include "pygi-type.h"
+#include "pygi-argument.h"
+#include "pygi-util.h"
+#include "pygi-basictype.h"
+#include "pygi-type.h"
/* _generate_doc_string
*
@@ -53,9 +54,119 @@ _generate_doc_string(PyGIBaseInfo *self)
return PyObject_CallFunctionObjArgs (_py_generate_doc_string, self, NULL);
}
+static PyObject *
+_get_info_string (PyGIBaseInfo *self,
+ const gchar* (*get_info_string)(GIBaseInfo*))
+{
+ const gchar *value = get_info_string ((GIBaseInfo*)self->info);
+ if (value == NULL) {
+ Py_RETURN_NONE;
+ }
+ return pygi_utf8_to_py (value);
+}
+
+static PyObject *
+_get_child_info (PyGIBaseInfo *self,
+ GIBaseInfo* (*get_child_info)(GIBaseInfo*))
+{
+ GIBaseInfo *info;
+ PyObject *py_info;
+
+ info = get_child_info ((GIBaseInfo*)self->info);
+ if (info == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ py_info = _pygi_info_new (info);
+ g_base_info_unref (info);
+ return py_info;
+}
+
+
+static PyObject *
+_get_child_info_by_name (PyGIBaseInfo *self, PyObject *py_name,
+ GIBaseInfo* (*get_child_info_by_name)(GIBaseInfo*, const gchar*))
+{
+ GIBaseInfo *info;
+ PyObject *py_info;
+ char *name;
+
+ if (!pygi_utf8_from_py (py_name, &name))
+ return NULL;
+
+ info = get_child_info_by_name ((GIObjectInfo*)self->info, name);
+ g_free (name);
+ if (info == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ py_info = _pygi_info_new (info);
+ g_base_info_unref (info);
+ return py_info;
+}
+
+
+/* _make_infos_tuple
+ *
+ * Build a tuple from the common API pattern in GI of having a
+ * function which returns a count and an indexed GIBaseInfo
+ * in the range of 0 to count;
+ */
+static PyObject *
+_make_infos_tuple (PyGIBaseInfo *self,
+ gint (*get_n_infos)(GIBaseInfo*),
+ GIBaseInfo* (*get_info)(GIBaseInfo*, gint))
+{
+ gint n_infos;
+ PyObject *infos;
+ gint i;
+
+ n_infos = get_n_infos ( (GIBaseInfo *) self->info);
+
+ infos = PyTuple_New (n_infos);
+ if (infos == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < n_infos; i++) {
+ GIBaseInfo *info;
+ PyObject *py_info;
+
+ info = (GIBaseInfo *) get_info (self->info, i);
+ g_assert (info != NULL);
+
+ py_info = _pygi_info_new (info);
+
+ g_base_info_unref (info);
+
+ if (py_info == NULL) {
+ Py_CLEAR (infos);
+ break;
+ }
+
+ PyTuple_SET_ITEM (infos, i, py_info);
+ }
+
+ return infos;
+}
+
/* BaseInfo */
+/* We need to be careful about calling g_base_info_get_name because
+ * calling it with a GI_INFO_TYPE_TYPE will crash.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=709456
+ */
+static const char *
+_safe_base_info_get_name (GIBaseInfo *info)
+{
+ if (g_base_info_get_type (info) == GI_INFO_TYPE_TYPE) {
+ return "type_type_instance";
+ } else {
+ return g_base_info_get_name (info);
+ }
+}
+
static void
_base_info_dealloc (PyGIBaseInfo *self)
{
@@ -64,40 +175,56 @@ _base_info_dealloc (PyGIBaseInfo *self)
g_base_info_unref (self->info);
- _pygi_callable_cache_free(self->cache);
+ if (self->cache != NULL)
+ pygi_callable_cache_free ( (PyGICallableCache *) self->cache);
- Py_TYPE( (PyObject *) self)->tp_free ( (PyObject *) self);
+ Py_TYPE (self)->tp_free ((PyObject *)self);
}
static PyObject *
_base_info_repr (PyGIBaseInfo *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);
+
+ return PyUnicode_FromFormat ("%s(%s)",
+ Py_TYPE( (PyObject *) self)->tp_name,
+ _safe_base_info_get_name (self->info));
}
static PyObject *
-_base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op)
+_wrap_g_base_info_equal (PyGIBaseInfo *self, PyObject *other)
{
- PyObject *res;
GIBaseInfo *other_info;
- if (!PyObject_TypeCheck(other, &PyGIBaseInfo_Type)) {
- Py_INCREF(Py_NotImplemented);
+ if (!PyObject_TypeCheck (other, &PyGIBaseInfo_Type)) {
+ Py_INCREF (Py_NotImplemented);
return Py_NotImplemented;
}
other_info = ((PyGIBaseInfo *)other)->info;
+ if (g_base_info_equal (self->info, other_info)) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+static PyObject *
+_base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op)
+{
+ PyObject *res;
switch (op) {
case Py_EQ:
- res = g_base_info_equal (self->info, other_info) ? Py_True : Py_False;
- break;
+ return _wrap_g_base_info_equal (self, other);
case Py_NE:
- res = g_base_info_equal (self->info, other_info) ? Py_False : Py_True;
- break;
+ res = _wrap_g_base_info_equal (self, other);
+ if (res == Py_True) {
+ Py_DECREF (res);
+ Py_RETURN_FALSE;
+ } else {
+ Py_DECREF (res);
+ Py_RETURN_TRUE;
+ }
default:
res = Py_NotImplemented;
break;
@@ -106,21 +233,14 @@ _base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op)
return res;
}
-PYGLIB_DEFINE_TYPE("gi.BaseInfo", PyGIBaseInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE("gi.BaseInfo", PyGIBaseInfo_Type, PyGIBaseInfo);
gboolean
_pygi_is_python_keyword (const gchar *name)
{
/* It may be better to use keyword.iskeyword(); keep in sync with
* python -c 'import keyword; print(keyword.kwlist)' */
-#if PY_VERSION_HEX < 0x03000000
- /* Python 2.x */
- static const gchar* keywords[] = {"and", "as", "assert", "break", "class",
- "continue", "def", "del", "elif", "else", "except", "exec", "finally",
- "for", "from", "global", "if", "import", "in", "is", "lambda", "not",
- "or", "pass", "print", "raise", "return", "try", "while", "with",
- "yield", NULL};
-#elif PY_VERSION_HEX < 0x04000000
+#if PY_VERSION_HEX < 0x04000000
/* Python 3.x; note that we explicitly keep "print"; it is not a keyword
* any more, but we do not want to break API between Python versions */
static const gchar* keywords[] = {"False", "None", "True", "and", "as",
@@ -145,38 +265,73 @@ _pygi_is_python_keyword (const gchar *name)
}
static PyObject *
+_wrap_g_base_info_get_type (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (g_base_info_get_type (self->info));
+}
+
+static PyObject *
_wrap_g_base_info_get_name (PyGIBaseInfo *self)
{
const gchar *name;
- name = g_base_info_get_name (self->info);
+ name = _safe_base_info_get_name (self->info);
/* escape keywords */
if (_pygi_is_python_keyword (name)) {
gchar *escaped = g_strconcat (name, "_", NULL);
- PyObject *obj = PYGLIB_PyUnicode_FromString (escaped);
+ PyObject *obj = pygi_utf8_to_py (escaped);
g_free (escaped);
return obj;
}
- return PYGLIB_PyUnicode_FromString (name);
+ return pygi_utf8_to_py (name);
}
static PyObject *
_wrap_g_base_info_get_name_unescaped (PyGIBaseInfo *self)
{
- return PYGLIB_PyUnicode_FromString (g_base_info_get_name (self->info));
+ return _get_info_string (self, _safe_base_info_get_name);
}
static PyObject *
_wrap_g_base_info_get_namespace (PyGIBaseInfo *self)
{
- return PYGLIB_PyUnicode_FromString (g_base_info_get_namespace (self->info));
+ return _get_info_string (self, g_base_info_get_namespace);
+}
+
+static PyObject *
+_wrap_g_base_info_is_deprecated (PyGIBaseInfo *self)
+{
+ if (g_base_info_is_deprecated (self->info))
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+_wrap_g_base_info_get_attribute (PyGIBaseInfo *self, PyObject *arg)
+{
+ char *name;
+ const char *value;
+
+ if (!pygi_utf8_from_py (arg, &name))
+ return NULL;
+
+ value = g_base_info_get_attribute (self->info, name);
+ g_free (name);
+ if (value == NULL) {
+ Py_RETURN_NONE;
+ }
+ return pygi_utf8_to_py (value);
}
static PyObject *
_wrap_g_base_info_get_container (PyGIBaseInfo *self)
{
+ /* Note: don't use _get_child_info because g_base_info_get_container
+ * is marked as [transfer none] and therefore returns a borrowed ref.
+ */
GIBaseInfo *info;
info = g_base_info_get_container (self->info);
@@ -190,10 +345,14 @@ _wrap_g_base_info_get_container (PyGIBaseInfo *self)
static PyMethodDef _PyGIBaseInfo_methods[] = {
+ { "get_type", (PyCFunction) _wrap_g_base_info_get_type, METH_NOARGS },
{ "get_name", (PyCFunction) _wrap_g_base_info_get_name, METH_NOARGS },
{ "get_name_unescaped", (PyCFunction) _wrap_g_base_info_get_name_unescaped, METH_NOARGS },
{ "get_namespace", (PyCFunction) _wrap_g_base_info_get_namespace, METH_NOARGS },
+ { "is_deprecated", (PyCFunction) _wrap_g_base_info_is_deprecated, METH_NOARGS },
+ { "get_attribute", (PyCFunction) _wrap_g_base_info_get_attribute, METH_O },
{ "get_container", (PyCFunction) _wrap_g_base_info_get_container, METH_NOARGS },
+ { "equal", (PyCFunction) _wrap_g_base_info_equal, METH_O },
{ NULL, NULL, 0 }
};
@@ -209,13 +368,13 @@ _base_info_getattro(PyGIBaseInfo *self, PyObject *name)
static PyObject *docstr;
if (docstr == NULL) {
- docstr= PYGLIB_PyUnicode_InternFromString("__doc__");
+ docstr= PyUnicode_InternFromString ("__doc__");
if (docstr == NULL)
return NULL;
}
Py_INCREF (name);
- PYGLIB_PyUnicode_InternInPlace (&name);
+ PyUnicode_InternInPlace (&name);
if (name == docstr) {
result = _generate_doc_string (self);
@@ -236,8 +395,8 @@ _base_info_attr_name(PyGIBaseInfo *self, void *closure)
static PyObject *
_base_info_attr_module(PyGIBaseInfo *self, void *closure)
{
- return PYGLIB_PyUnicode_FromFormat ("gi.repository.%s",
- g_base_info_get_namespace (self->info));
+ return PyUnicode_FromFormat ("gi.repository.%s",
+ g_base_info_get_namespace (self->info));
}
static PyGetSetDef _base_info_getsets[] = {
@@ -267,10 +426,8 @@ _pygi_info_new (GIBaseInfo *info)
type = &PyGICallbackInfo_Type;
break;
case GI_INFO_TYPE_STRUCT:
- type = &PyGIStructInfo_Type;
- break;
case GI_INFO_TYPE_BOXED:
- type = &PyGIBoxedInfo_Type;
+ type = &PyGIStructInfo_Type;
break;
case GI_INFO_TYPE_ENUM:
case GI_INFO_TYPE_FLAGS:
@@ -342,7 +499,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_TYPE(&py_info)->tp_name);
+ type->tp_name, Py_TYPE(py_info)->tp_name);
goto out;
}
@@ -357,44 +514,7 @@ out:
/* CallableInfo */
-PYGLIB_DEFINE_TYPE ("gi.CallableInfo", PyGICallableInfo_Type, PyGICallableInfo);
-
-static PyObject *
-_wrap_g_callable_info_get_arguments (PyGIBaseInfo *self)
-{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- n_infos = g_callable_info_get_n_args ( (GICallableInfo *) self->info);
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- info = (GIBaseInfo *) g_callable_info_get_arg ( (GICallableInfo *) self->info, i);
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
-
- PyTuple_SET_ITEM (infos, i, py_info);
- }
-
- return infos;
-}
-
+PYGI_DEFINE_TYPE ("gi.CallableInfo", PyGICallableInfo_Type, PyGICallableInfo);
/* _callable_info_call:
*
@@ -440,6 +560,33 @@ _callable_info_call (PyGICallableInfo *self, PyObject *args, PyObject *kwargs)
}
}
+static PyObject *
+_callable_info_repr (PyGICallableInfo *self)
+{
+ PyObject *bound_repr_o = NULL;
+ const char *bound_repr = "None";
+ PyObject *res = NULL;
+
+ if (self->py_bound_arg) {
+ bound_repr_o = PyObject_Repr(self->py_bound_arg);
+ if (bound_repr_o == NULL)
+ goto out;
+
+ bound_repr = PyUnicode_AsUTF8(bound_repr_o);
+ if (bound_repr == NULL)
+ goto out;
+ }
+
+ res = PyUnicode_FromFormat ("%s(%s, bound=%s)",
+ Py_TYPE( (PyObject *) self)->tp_name,
+ _safe_base_info_get_name (self->base.info),
+ bound_repr);
+
+out:
+ Py_XDECREF(bound_repr_o);
+
+ return res;
+}
/* _function_info_call:
*
@@ -472,17 +619,12 @@ _function_info_call (PyGICallableInfo *self, PyObject *args, PyObject *kwargs)
py_str_name = tmp;
}
-#if PY_VERSION_HEX < 0x03000000
- str_name = PyString_AsString (py_str_name);
-#else
str_name = PyBytes_AsString (py_str_name);
-#endif
-
- if (strcmp (str_name, g_base_info_get_name (container_info))) {
+ if (strcmp (str_name, _safe_base_info_get_name (container_info))) {
PyErr_Format (PyExc_TypeError,
"%s constructor cannot be used to create instances of "
"a subclass %s",
- g_base_info_get_name (container_info),
+ _safe_base_info_get_name (container_info),
str_name);
Py_DECREF (py_str_name);
return NULL;
@@ -572,132 +714,224 @@ _callable_info_dealloc (PyGICallableInfo *self)
PyGIBaseInfo_Type.tp_dealloc ((PyObject *) self);
}
+static PyObject *
+_wrap_g_callable_info_get_arguments (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_callable_info_get_n_args, g_callable_info_get_arg);
+}
+
+static PyObject *
+_wrap_g_callable_info_get_return_type (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_callable_info_get_return_type);
+}
+
+static PyObject *
+_wrap_g_callable_info_get_caller_owns (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (
+ g_callable_info_get_caller_owns (self->info) );
+}
+
+static PyObject *
+_wrap_g_callable_info_may_return_null (PyGIBaseInfo *self)
+{
+ return pygi_gboolean_to_py (
+ g_callable_info_may_return_null (self->info) );
+}
+
+static PyObject *
+_wrap_g_callable_info_skip_return (PyGIBaseInfo *self)
+{
+ return pygi_gboolean_to_py (g_callable_info_skip_return (self->info));
+}
+
+static PyObject *
+_wrap_g_callable_info_get_return_attribute (PyGIBaseInfo *self, PyObject *py_name)
+{
+ gchar *name;
+ const gchar *attr;
+
+ if (!pygi_utf8_from_py (py_name, &name))
+ return NULL;
+
+ attr = g_callable_info_get_return_attribute (self->info, name);
+ if (attr) {
+ g_free (name);
+ return pygi_utf8_to_py (attr);
+ } else {
+ PyErr_Format(PyExc_AttributeError, "return attribute %s not found", name);
+ g_free (name);
+ return NULL;
+ }
+}
+
+static PyObject *
+_wrap_g_callable_info_can_throw_gerror (PyGIBaseInfo *self)
+{
+ if (g_callable_info_can_throw_gerror (self->info))
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
static PyMethodDef _PyGICallableInfo_methods[] = {
{ "invoke", (PyCFunction) _wrap_g_callable_info_invoke, METH_VARARGS | METH_KEYWORDS },
{ "get_arguments", (PyCFunction) _wrap_g_callable_info_get_arguments, METH_NOARGS },
+ { "get_return_type", (PyCFunction) _wrap_g_callable_info_get_return_type, METH_NOARGS },
+ { "get_caller_owns", (PyCFunction) _wrap_g_callable_info_get_caller_owns, METH_NOARGS },
+ { "may_return_null", (PyCFunction) _wrap_g_callable_info_may_return_null, METH_NOARGS },
+ { "skip_return", (PyCFunction) _wrap_g_callable_info_skip_return, METH_NOARGS },
+ { "get_return_attribute", (PyCFunction) _wrap_g_callable_info_get_return_attribute, METH_O },
+ { "can_throw_gerror", (PyCFunction) _wrap_g_callable_info_can_throw_gerror, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* CallbackInfo */
-PYGLIB_DEFINE_TYPE ("gi.CallbackInfo", PyGICallbackInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.CallbackInfo", PyGICallbackInfo_Type, PyGICallableInfo);
static PyMethodDef _PyGICallbackInfo_methods[] = {
{ NULL, NULL, 0 }
};
-/* BoxedInfo */
-PYGLIB_DEFINE_TYPE ("gi.BoxedInfo", PyGIBoxedInfo_Type, PyGIBaseInfo);
-
-static PyMethodDef _PyGIBoxedInfo_methods[] = {
- { NULL, NULL, 0 }
-};
-
/* ErrorDomainInfo */
-PYGLIB_DEFINE_TYPE ("gi.ErrorDomainInfo", PyGIErrorDomainInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.ErrorDomainInfo", PyGIErrorDomainInfo_Type, PyGIBaseInfo);
static PyMethodDef _PyGIErrorDomainInfo_methods[] = {
{ NULL, NULL, 0 }
};
/* SignalInfo */
-PYGLIB_DEFINE_TYPE ("gi.SignalInfo", PyGISignalInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.SignalInfo", PyGISignalInfo_Type, PyGICallableInfo);
+
+static PyObject *
+_wrap_g_signal_info_get_flags (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (
+ g_signal_info_get_flags ((GISignalInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_signal_info_get_class_closure (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_signal_info_get_class_closure);
+}
+
+static PyObject *
+_wrap_g_signal_info_true_stops_emit (PyGIBaseInfo *self)
+{
+ return pygi_gboolean_to_py (
+ g_signal_info_true_stops_emit ((GISignalInfo *)self->info) );
+}
static PyMethodDef _PyGISignalInfo_methods[] = {
+ { "get_flags", (PyCFunction) _wrap_g_signal_info_get_flags, METH_NOARGS },
+ { "get_class_closure", (PyCFunction) _wrap_g_signal_info_get_class_closure, METH_NOARGS },
+ { "true_stops_emit", (PyCFunction) _wrap_g_signal_info_true_stops_emit, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* PropertyInfo */
-PYGLIB_DEFINE_TYPE ("gi.PropertyInfo", PyGIPropertyInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.PropertyInfo", PyGIPropertyInfo_Type, PyGIBaseInfo);
+
+static PyObject *
+_wrap_g_property_info_get_flags (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (
+ g_property_info_get_flags ((GIPropertyInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_property_info_get_type (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_property_info_get_type);
+}
+
+static PyObject *
+_wrap_g_property_info_get_ownership_transfer (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (
+ g_property_info_get_ownership_transfer ((GIPropertyInfo *)self->info) );
+}
static PyMethodDef _PyGIPropertyInfo_methods[] = {
+ { "get_flags", (PyCFunction) _wrap_g_property_info_get_flags, METH_NOARGS },
+ { "get_type", (PyCFunction) _wrap_g_property_info_get_type, METH_NOARGS },
+ { "get_ownership_transfer", (PyCFunction) _wrap_g_property_info_get_ownership_transfer, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* ArgInfo */
-PYGLIB_DEFINE_TYPE ("gi.ArgInfo", PyGIArgInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.ArgInfo", PyGIArgInfo_Type, PyGIBaseInfo);
static PyObject *
_wrap_g_arg_info_get_direction (PyGIBaseInfo *self)
{
- return PyLong_FromLong (
+ return pygi_guint_to_py (
g_arg_info_get_direction ((GIArgInfo*)self->info) );
}
static PyObject *
_wrap_g_arg_info_is_caller_allocates (PyGIBaseInfo *self)
{
- return PyBool_FromLong (
+ return pygi_gboolean_to_py (
g_arg_info_is_caller_allocates ((GIArgInfo*)self->info) );
}
static PyObject *
_wrap_g_arg_info_is_return_value (PyGIBaseInfo *self)
{
- return PyBool_FromLong (
+ return pygi_gboolean_to_py (
g_arg_info_is_return_value ((GIArgInfo*)self->info) );
}
static PyObject *
_wrap_g_arg_info_is_optional (PyGIBaseInfo *self)
{
- return PyBool_FromLong (
+ return pygi_gboolean_to_py (
g_arg_info_is_optional ((GIArgInfo*)self->info) );
}
static PyObject *
_wrap_g_arg_info_may_be_null (PyGIBaseInfo *self)
{
- return PyBool_FromLong (
+ return pygi_gboolean_to_py (
g_arg_info_may_be_null ((GIArgInfo*)self->info) );
}
-/* _g_arg_get_pytype_hint
- *
- * Returns new value reference to a string hinting at the python type
- * which can be used for the given gi argument info.
- */
static PyObject *
-_g_arg_get_pytype_hint (PyGIBaseInfo *self)
+_wrap_g_arg_info_get_ownership_transfer (PyGIBaseInfo *self)
{
- GIArgInfo *arg_info = (GIArgInfo*)self->info;
- GITypeInfo type_info;
- GITypeTag type_tag;
- PyObject *py_type;
+ return pygi_guint_to_py (
+ g_arg_info_get_ownership_transfer ((GIArgInfo *)self->info) );
+}
- g_arg_info_load_type(arg_info, &type_info);
- type_tag = g_type_info_get_tag(&type_info);
+static PyObject *
+_wrap_g_arg_info_get_scope (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (
+ g_arg_info_get_scope ((GIArgInfo *)self->info) );
+}
- /* First attempt getting a python type object. */
- py_type = _pygi_get_py_type_hint(type_tag);
- if (py_type != Py_None && PyObject_HasAttrString(py_type, "__name__")) {
- PyObject *name = PyObject_GetAttrString(py_type, "__name__");
- Py_DecRef(py_type);
- return name;
- } else {
- Py_DecRef(py_type);
- if (type_tag == GI_TYPE_TAG_INTERFACE) {
- const char *info_name;
- PyObject *py_string;
- GIBaseInfo *iface = g_type_info_get_interface(&type_info);
- gchar *name;
-
- info_name = g_base_info_get_name (iface);
- if (info_name == NULL) {
- g_base_info_unref (iface);
- return PYGLIB_PyUnicode_FromString(g_type_tag_to_string(type_tag));
- }
-
- name = g_strdup_printf("%s.%s",
- g_base_info_get_namespace(iface),
- info_name);
- g_base_info_unref(iface);
- py_string = PYGLIB_PyUnicode_FromString(name);
- g_free(name);
- return py_string;
- }
- return PYGLIB_PyUnicode_FromString(g_type_tag_to_string(type_tag));
- }
+static PyObject *
+_wrap_g_arg_info_get_closure (PyGIBaseInfo *self)
+{
+ return pygi_gint_to_py (
+ g_arg_info_get_closure ((GIArgInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_arg_info_get_destroy (PyGIBaseInfo *self)
+{
+ return pygi_gint_to_py (
+ g_arg_info_get_destroy ((GIArgInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_arg_info_get_type (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_arg_info_get_type);
}
static PyMethodDef _PyGIArgInfo_methods[] = {
@@ -706,21 +940,103 @@ static PyMethodDef _PyGIArgInfo_methods[] = {
{ "is_return_value", (PyCFunction) _wrap_g_arg_info_is_return_value, METH_NOARGS },
{ "is_optional", (PyCFunction) _wrap_g_arg_info_is_optional, METH_NOARGS },
{ "may_be_null", (PyCFunction) _wrap_g_arg_info_may_be_null, METH_NOARGS },
- { "get_pytype_hint", (PyCFunction) _g_arg_get_pytype_hint, METH_NOARGS },
+ { "get_ownership_transfer", (PyCFunction) _wrap_g_arg_info_get_ownership_transfer, METH_NOARGS },
+ { "get_scope", (PyCFunction) _wrap_g_arg_info_get_scope, METH_NOARGS },
+ { "get_closure", (PyCFunction) _wrap_g_arg_info_get_closure, METH_NOARGS },
+ { "get_destroy", (PyCFunction) _wrap_g_arg_info_get_destroy, METH_NOARGS },
+ { "get_type", (PyCFunction) _wrap_g_arg_info_get_type, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* TypeInfo */
-PYGLIB_DEFINE_TYPE ("gi.TypeInfo", PyGITypeInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.TypeInfo", PyGITypeInfo_Type, PyGIBaseInfo);
+
+static PyObject *
+_wrap_g_type_info_is_pointer (PyGIBaseInfo *self)
+{
+ return pygi_gboolean_to_py (g_type_info_is_pointer (self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_get_tag (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (g_type_info_get_tag (self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_get_tag_as_string (PyGIBaseInfo *self)
+{
+ GITypeTag tag = g_type_info_get_tag (self->info);
+ return pygi_utf8_to_py (g_type_tag_to_string(tag));
+}
+
+static PyObject *
+_wrap_g_type_info_get_param_type (PyGIBaseInfo *self, PyObject *py_n)
+{
+ GIBaseInfo *info;
+ PyObject *py_info;
+ gint n;
+
+ if (!pygi_gint_from_py (py_n, &n))
+ return NULL;
+
+ info = (GIBaseInfo *) g_type_info_get_param_type ( (GITypeInfo *) self->info, n);
+ if (info == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ py_info = _pygi_info_new (info);
+ g_base_info_unref (info);
+ return py_info;
+}
+
+static PyObject *
+_wrap_g_type_info_get_interface (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_type_info_get_interface);
+}
+
+static PyObject *
+_wrap_g_type_info_get_array_length (PyGIBaseInfo *self)
+{
+ return pygi_gint_to_py (g_type_info_get_array_length (self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_get_array_fixed_size (PyGIBaseInfo *self)
+{
+ return pygi_gint_to_py (g_type_info_get_array_fixed_size (self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_is_zero_terminated (PyGIBaseInfo *self)
+{
+ return pygi_gboolean_to_py (g_type_info_is_zero_terminated (self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_get_array_type (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (g_type_info_get_array_type (self->info));
+}
static PyMethodDef _PyGITypeInfo_methods[] = {
+ { "is_pointer", (PyCFunction) _wrap_g_type_info_is_pointer, METH_NOARGS },
+ { "get_tag", (PyCFunction) _wrap_g_type_info_get_tag, METH_NOARGS },
+ { "get_tag_as_string", (PyCFunction) _wrap_g_type_info_get_tag_as_string, METH_NOARGS },
+ { "get_param_type", (PyCFunction) _wrap_g_type_info_get_param_type, METH_O },
+ { "get_interface", (PyCFunction) _wrap_g_type_info_get_interface, METH_NOARGS },
+ { "get_array_length", (PyCFunction) _wrap_g_type_info_get_array_length, METH_NOARGS },
+ { "get_array_fixed_size", (PyCFunction) _wrap_g_type_info_get_array_fixed_size, METH_NOARGS },
+ { "is_zero_terminated", (PyCFunction) _wrap_g_type_info_is_zero_terminated, METH_NOARGS },
+ { "get_array_type", (PyCFunction) _wrap_g_type_info_get_array_type, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* FunctionInfo */
-PYGLIB_DEFINE_TYPE ("gi.FunctionInfo", PyGIFunctionInfo_Type, PyGICallableInfo);
+PYGI_DEFINE_TYPE ("gi.FunctionInfo", PyGIFunctionInfo_Type, PyGICallableInfo);
static PyObject *
_wrap_g_function_info_is_constructor (PyGIBaseInfo *self)
@@ -731,7 +1047,7 @@ _wrap_g_function_info_is_constructor (PyGIBaseInfo *self)
flags = g_function_info_get_flags ( (GIFunctionInfo*) self->info);
is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR;
- return PyBool_FromLong (is_constructor);
+ return pygi_gboolean_to_py (is_constructor);
}
static PyObject *
@@ -743,7 +1059,7 @@ _wrap_g_function_info_is_method (PyGIBaseInfo *self)
flags = g_function_info_get_flags ( (GIFunctionInfo*) self->info);
is_method = flags & GI_FUNCTION_IS_METHOD;
- return PyBool_FromLong (is_method);
+ return pygi_gboolean_to_py (is_method);
}
gsize
@@ -796,6 +1112,8 @@ _pygi_g_type_tag_size (GITypeTag type_tag)
"Unable to know the size (assuming %s is not a pointer)",
g_type_tag_to_string (type_tag));
break;
+ default:
+ break;
}
return size;
@@ -854,10 +1172,10 @@ _pygi_g_type_info_size (GITypeInfo *type_info)
if (g_type_info_is_pointer (type_info)) {
size = sizeof (gpointer);
} else {
- GITypeTag type_tag;
+ GITypeTag enum_type_tag;
- type_tag = g_enum_info_get_storage_type ( (GIEnumInfo *) info);
- size = _pygi_g_type_tag_size (type_tag);
+ enum_type_tag = g_enum_info_get_storage_type ( (GIEnumInfo *) info);
+ size = _pygi_g_type_tag_size (enum_type_tag);
}
break;
case GI_INFO_TYPE_BOXED:
@@ -895,19 +1213,61 @@ _pygi_g_type_info_size (GITypeInfo *type_info)
case GI_TYPE_TAG_ERROR:
size = sizeof (gpointer);
break;
+ default:
+ break;
}
return size;
}
+static PyObject *
+_wrap_g_function_info_get_symbol (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_function_info_get_symbol);
+}
+
+static PyObject *
+_wrap_g_function_info_get_flags (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (g_function_info_get_flags (self->info));
+}
+
+static PyObject *
+_wrap_g_function_info_get_property (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_function_info_get_property);
+}
+
+static PyObject *
+_wrap_g_function_info_get_vfunc (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_function_info_get_vfunc);
+}
+
static PyMethodDef _PyGIFunctionInfo_methods[] = {
{ "is_constructor", (PyCFunction) _wrap_g_function_info_is_constructor, METH_NOARGS },
{ "is_method", (PyCFunction) _wrap_g_function_info_is_method, METH_NOARGS },
+ { "get_symbol", (PyCFunction) _wrap_g_function_info_get_symbol, METH_NOARGS },
+ { "get_flags", (PyCFunction) _wrap_g_function_info_get_flags, METH_NOARGS },
+ { "get_property", (PyCFunction) _wrap_g_function_info_get_property, METH_NOARGS },
+ { "get_vfunc", (PyCFunction) _wrap_g_function_info_get_vfunc, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* RegisteredTypeInfo */
-PYGLIB_DEFINE_TYPE ("gi.RegisteredTypeInfo", PyGIRegisteredTypeInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.RegisteredTypeInfo", PyGIRegisteredTypeInfo_Type, PyGIBaseInfo);
+
+static PyObject *
+_wrap_g_registered_type_info_get_type_name (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_registered_type_info_get_type_name);
+}
+
+static PyObject *
+_wrap_g_registered_type_info_get_type_init (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_registered_type_info_get_type_init);
+}
static PyObject *
_wrap_g_registered_type_info_get_g_type (PyGIBaseInfo *self)
@@ -920,245 +1280,73 @@ _wrap_g_registered_type_info_get_g_type (PyGIBaseInfo *self)
}
static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = {
+ { "get_type_name", (PyCFunction) _wrap_g_registered_type_info_get_type_name, METH_NOARGS },
+ { "get_type_init", (PyCFunction) _wrap_g_registered_type_info_get_type_init, METH_NOARGS },
{ "get_g_type", (PyCFunction) _wrap_g_registered_type_info_get_g_type, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* GIStructInfo */
-PYGLIB_DEFINE_TYPE ("StructInfo", PyGIStructInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("StructInfo", PyGIStructInfo_Type, PyGIBaseInfo);
static PyObject *
-_get_fields (PyGIBaseInfo *self, GIInfoType info_type)
+_wrap_g_struct_info_get_fields (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- switch (info_type) {
- case GI_INFO_TYPE_STRUCT:
- n_infos = g_struct_info_get_n_fields ( (GIStructInfo *) self->info);
- break;
- case GI_INFO_TYPE_OBJECT:
- n_infos = g_object_info_get_n_fields ( (GIObjectInfo *) self->info);
- break;
- default:
- g_assert_not_reached();
- }
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- switch (info_type) {
- case GI_INFO_TYPE_STRUCT:
- info = (GIBaseInfo *) g_struct_info_get_field ( (GIStructInfo *) self->info, i);
- break;
- case GI_INFO_TYPE_OBJECT:
- info = (GIBaseInfo *) g_object_info_get_field ( (GIObjectInfo *) self->info, i);
- break;
- default:
- g_assert_not_reached();
- }
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
-
- PyTuple_SET_ITEM (infos, i, py_info);
- }
-
- return infos;
+ return _make_infos_tuple (self, g_struct_info_get_n_fields, g_struct_info_get_field);
}
static PyObject *
-_get_methods (PyGIBaseInfo *self, GIInfoType info_type)
+_wrap_g_struct_info_get_methods (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- switch (info_type) {
- case GI_INFO_TYPE_STRUCT:
- n_infos = g_struct_info_get_n_methods ( (GIStructInfo *) self->info);
- break;
- case GI_INFO_TYPE_OBJECT:
- n_infos = g_object_info_get_n_methods ( (GIObjectInfo *) self->info);
- break;
- default:
- g_assert_not_reached();
- }
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- switch (info_type) {
- case GI_INFO_TYPE_STRUCT:
- info = (GIBaseInfo *) g_struct_info_get_method ( (GIStructInfo *) self->info, i);
- break;
- case GI_INFO_TYPE_OBJECT:
- info = (GIBaseInfo *) g_object_info_get_method ( (GIObjectInfo *) self->info, i);
- break;
- default:
- g_assert_not_reached();
- }
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
-
- PyTuple_SET_ITEM (infos, i, py_info);
- }
-
- return infos;
+ return _make_infos_tuple (self, g_struct_info_get_n_methods, g_struct_info_get_method);
}
static PyObject *
-_get_constants (PyGIBaseInfo *self, GIInfoType info_type)
+_wrap_g_struct_info_get_size (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- switch (info_type) {
- case GI_INFO_TYPE_INTERFACE:
- n_infos = g_interface_info_get_n_constants ( (GIInterfaceInfo *) self->info);
- break;
- case GI_INFO_TYPE_OBJECT:
- n_infos = g_object_info_get_n_constants ( (GIObjectInfo *) self->info);
- break;
- default:
- g_assert_not_reached();
- }
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- switch (info_type) {
- case GI_INFO_TYPE_INTERFACE:
- info = (GIBaseInfo *) g_interface_info_get_constant ( (GIInterfaceInfo *) self->info, i);
- break;
- case GI_INFO_TYPE_OBJECT:
- info = (GIBaseInfo *) g_object_info_get_constant ( (GIObjectInfo *) self->info, i);
- break;
- default:
- g_assert_not_reached();
- }
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
-
- PyTuple_SET_ITEM (infos, i, py_info);
- }
-
- return infos;
+ return pygi_gsize_to_py (g_struct_info_get_size (self->info));
}
static PyObject *
-_get_vfuncs (PyGIBaseInfo *self, GIInfoType info_type)
+_wrap_g_struct_info_get_alignment (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- switch (info_type) {
- case GI_INFO_TYPE_INTERFACE:
- n_infos = g_interface_info_get_n_vfuncs ( (GIInterfaceInfo *) self->info);
- break;
- case GI_INFO_TYPE_OBJECT:
- n_infos = g_object_info_get_n_vfuncs ( (GIObjectInfo *) self->info);
- break;
- default:
- g_assert_not_reached();
- }
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- switch (info_type) {
- case GI_INFO_TYPE_INTERFACE:
- info = (GIBaseInfo *) g_interface_info_get_vfunc ( (GIInterfaceInfo *) self->info, i);
- break;
- case GI_INFO_TYPE_OBJECT:
- info = (GIBaseInfo *) g_object_info_get_vfunc ( (GIObjectInfo *) self->info, i);
- break;
- default:
- g_assert_not_reached();
- }
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
+ return pygi_gsize_to_py (g_struct_info_get_alignment (self->info));
+}
- PyTuple_SET_ITEM (infos, i, py_info);
- }
+static PyObject *
+_wrap_g_struct_info_is_gtype_struct (PyGIBaseInfo *self)
+{
+ return pygi_gboolean_to_py (g_struct_info_is_gtype_struct (self->info));
+}
- return infos;
+static PyObject *
+_wrap_g_struct_info_is_foreign (PyGIBaseInfo *self)
+{
+ return pygi_gboolean_to_py (g_struct_info_is_foreign (self->info));
}
static PyObject *
-_wrap_g_struct_info_get_fields (PyGIBaseInfo *self)
+_wrap_g_struct_info_find_method (PyGIBaseInfo *self, PyObject *py_name)
{
- return _get_fields (self, GI_INFO_TYPE_STRUCT);
+ return _get_child_info_by_name (self, py_name, g_struct_info_find_method);
}
static PyObject *
-_wrap_g_struct_info_get_methods (PyGIBaseInfo *self)
+_wrap_g_struct_info_find_field (PyGIBaseInfo *self, PyObject *py_name)
{
- return _get_methods (self, GI_INFO_TYPE_STRUCT);
+ return _get_child_info_by_name (self, py_name, g_struct_info_find_field);
}
static PyMethodDef _PyGIStructInfo_methods[] = {
{ "get_fields", (PyCFunction) _wrap_g_struct_info_get_fields, METH_NOARGS },
+ { "find_field", (PyCFunction) _wrap_g_struct_info_find_field, METH_O },
{ "get_methods", (PyCFunction) _wrap_g_struct_info_get_methods, METH_NOARGS },
+ { "find_method", (PyCFunction) _wrap_g_struct_info_find_method, METH_O },
+ { "get_size", (PyCFunction) _wrap_g_struct_info_get_size, METH_NOARGS },
+ { "get_alignment", (PyCFunction) _wrap_g_struct_info_get_alignment, METH_NOARGS },
+ { "is_gtype_struct", (PyCFunction) _wrap_g_struct_info_is_gtype_struct, METH_NOARGS },
+ { "is_foreign", (PyCFunction) _wrap_g_struct_info_is_foreign, METH_NOARGS },
{ NULL, NULL, 0 }
};
@@ -1166,8 +1354,8 @@ gboolean
pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
{
gboolean is_simple;
- gsize n_field_infos;
- gsize i;
+ gint n_field_infos;
+ gint i;
is_simple = TRUE;
@@ -1263,6 +1451,9 @@ pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
g_base_info_unref (info);
break;
}
+ default:
+ g_assert_not_reached();
+ break;
}
g_base_info_unref ( (GIBaseInfo *) field_type_info);
@@ -1274,42 +1465,12 @@ pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
/* EnumInfo */
-PYGLIB_DEFINE_TYPE ("gi.EnumInfo", PyGIEnumInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.EnumInfo", PyGIEnumInfo_Type, PyGIBaseInfo);
static PyObject *
_wrap_g_enum_info_get_values (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- n_infos = g_enum_info_get_n_values ( (GIEnumInfo *) self->info);
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- info = (GIBaseInfo *) g_enum_info_get_value ( (GIEnumInfo *) self->info, i);
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
-
- PyTuple_SET_ITEM (infos, i, py_info);
- }
-
- return infos;
+ return _make_infos_tuple (self, g_enum_info_get_n_values, g_enum_info_get_value);
}
static PyObject *
@@ -1326,195 +1487,254 @@ _wrap_g_enum_info_is_flags (PyGIBaseInfo *self)
}
}
+static PyObject *
+_wrap_g_enum_info_get_methods (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_enum_info_get_n_methods, g_enum_info_get_method);
+}
+
+static PyObject *
+_wrap_g_enum_info_get_storage_type (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (g_enum_info_get_storage_type ((GIBaseInfo *) self->info));
+}
+
static PyMethodDef _PyGIEnumInfo_methods[] = {
{ "get_values", (PyCFunction) _wrap_g_enum_info_get_values, METH_NOARGS },
{ "is_flags", (PyCFunction) _wrap_g_enum_info_is_flags, METH_NOARGS },
+ { "get_methods", (PyCFunction) _wrap_g_enum_info_get_methods, METH_NOARGS },
+ { "get_storage_type", (PyCFunction) _wrap_g_enum_info_get_storage_type, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* ObjectInfo */
-PYGLIB_DEFINE_TYPE ("ObjectInfo", PyGIObjectInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("ObjectInfo", PyGIObjectInfo_Type, PyGIBaseInfo);
static PyObject *
_wrap_g_object_info_get_parent (PyGIBaseInfo *self)
{
- GIBaseInfo *info;
- PyObject *py_info;
-
- info = (GIBaseInfo *) g_object_info_get_parent ( (GIObjectInfo*) self->info);
-
- if (info == NULL) {
- Py_RETURN_NONE;
- }
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- return py_info;
+ return _get_child_info (self, g_object_info_get_parent);
}
static PyObject *
_wrap_g_object_info_get_methods (PyGIBaseInfo *self)
{
- return _get_methods (self, GI_INFO_TYPE_OBJECT);
+ return _make_infos_tuple (self, g_object_info_get_n_methods, g_object_info_get_method);
}
static PyObject *
-_wrap_g_object_info_get_fields (PyGIBaseInfo *self)
+_wrap_g_object_info_find_method (PyGIBaseInfo *self, PyObject *py_name)
{
- return _get_fields (self, GI_INFO_TYPE_OBJECT);
+ return _get_child_info_by_name (self, py_name, g_object_info_find_method);
}
static PyObject *
-_wrap_g_object_info_get_interfaces (PyGIBaseInfo *self)
+_wrap_g_object_info_get_fields (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- n_infos = g_object_info_get_n_interfaces ( (GIObjectInfo *) self->info);
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- info = (GIBaseInfo *) g_object_info_get_interface ( (GIObjectInfo *) self->info, i);
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
+ return _make_infos_tuple (self, g_object_info_get_n_fields, g_object_info_get_field);
+}
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
+static PyObject *
+_wrap_g_object_info_get_properties (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_object_info_get_n_properties, g_object_info_get_property);
+}
- PyTuple_SET_ITEM (infos, i, py_info);
- }
+static PyObject *
+_wrap_g_object_info_get_signals (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_object_info_get_n_signals, g_object_info_get_signal);
+}
- return infos;
+static PyObject *
+_wrap_g_object_info_get_interfaces (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_object_info_get_n_interfaces, g_object_info_get_interface);
}
static PyObject *
_wrap_g_object_info_get_constants (PyGIBaseInfo *self)
{
- return _get_constants (self, GI_INFO_TYPE_OBJECT);
+ return _make_infos_tuple (self, g_object_info_get_n_constants, g_object_info_get_constant);
}
static PyObject *
_wrap_g_object_info_get_vfuncs (PyGIBaseInfo *self)
{
- return _get_vfuncs (self, GI_INFO_TYPE_OBJECT);
+ return _make_infos_tuple (self, g_object_info_get_n_vfuncs, g_object_info_get_vfunc);
}
static PyObject *
_wrap_g_object_info_get_abstract (PyGIBaseInfo *self)
{
gboolean is_abstract = g_object_info_get_abstract ( (GIObjectInfo*) self->info);
- return PyBool_FromLong (is_abstract);
+ return pygi_gboolean_to_py (is_abstract);
+}
+
+static PyObject *
+_wrap_g_object_info_get_type_name (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_object_info_get_type_name);
+}
+
+static PyObject *
+_wrap_g_object_info_get_type_init (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_object_info_get_type_init);
+}
+
+static PyObject *
+_wrap_g_object_info_get_fundamental (PyGIBaseInfo *self)
+{
+ return pygi_gboolean_to_py (g_object_info_get_fundamental ( (GIObjectInfo*) self->info));
}
static PyObject *
_wrap_g_object_info_get_class_struct (PyGIBaseInfo *self)
{
- GIBaseInfo *info;
+ return _get_child_info (self, g_object_info_get_class_struct);
+}
- info = g_object_info_get_class_struct ((GIObjectInfo*)self->info);
+static PyObject *
+_wrap_g_object_info_find_vfunc (PyGIBaseInfo *self, PyObject *py_name)
+{
+ return _get_child_info_by_name (self, py_name, g_object_info_find_vfunc);
+}
- if (info == NULL) {
- Py_RETURN_NONE;
- }
+static PyObject *
+_wrap_g_object_info_get_unref_function (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_object_info_get_unref_function);
+}
- return _pygi_info_new (info);
+static PyObject *
+_wrap_g_object_info_get_ref_function (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_object_info_get_ref_function);
+}
+
+static PyObject *
+_wrap_g_object_info_get_set_value_function (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_object_info_get_set_value_function);
+}
+
+static PyObject *
+_wrap_g_object_info_get_get_value_function (PyGIBaseInfo *self)
+{
+ return _get_info_string (self, g_object_info_get_get_value_function);
}
static PyMethodDef _PyGIObjectInfo_methods[] = {
{ "get_parent", (PyCFunction) _wrap_g_object_info_get_parent, METH_NOARGS },
{ "get_methods", (PyCFunction) _wrap_g_object_info_get_methods, METH_NOARGS },
+ { "find_method", (PyCFunction) _wrap_g_object_info_find_method, METH_O },
{ "get_fields", (PyCFunction) _wrap_g_object_info_get_fields, METH_NOARGS },
+ { "get_properties", (PyCFunction) _wrap_g_object_info_get_properties, METH_NOARGS },
+ { "get_signals", (PyCFunction) _wrap_g_object_info_get_signals, METH_NOARGS },
{ "get_interfaces", (PyCFunction) _wrap_g_object_info_get_interfaces, METH_NOARGS },
{ "get_constants", (PyCFunction) _wrap_g_object_info_get_constants, METH_NOARGS },
{ "get_vfuncs", (PyCFunction) _wrap_g_object_info_get_vfuncs, METH_NOARGS },
+ { "find_vfunc", (PyCFunction) _wrap_g_object_info_find_vfunc, METH_O },
{ "get_abstract", (PyCFunction) _wrap_g_object_info_get_abstract, METH_NOARGS },
+ { "get_type_name", (PyCFunction) _wrap_g_object_info_get_type_name, METH_NOARGS },
+ { "get_type_init", (PyCFunction) _wrap_g_object_info_get_type_init, METH_NOARGS },
+ { "get_fundamental", (PyCFunction) _wrap_g_object_info_get_fundamental, METH_NOARGS },
{ "get_class_struct", (PyCFunction) _wrap_g_object_info_get_class_struct, METH_NOARGS },
+ { "get_unref_function", (PyCFunction) _wrap_g_object_info_get_unref_function, METH_NOARGS },
+ { "get_ref_function", (PyCFunction) _wrap_g_object_info_get_ref_function, METH_NOARGS },
+ { "get_set_value_function", (PyCFunction) _wrap_g_object_info_get_set_value_function, METH_NOARGS },
+ { "get_get_value_function", (PyCFunction) _wrap_g_object_info_get_get_value_function, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* GIInterfaceInfo */
-PYGLIB_DEFINE_TYPE ("InterfaceInfo", PyGIInterfaceInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("InterfaceInfo", PyGIInterfaceInfo_Type, PyGIBaseInfo);
static PyObject *
_wrap_g_interface_info_get_methods (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- n_infos = g_interface_info_get_n_methods ( (GIInterfaceInfo *) self->info);
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
+ return _make_infos_tuple (self, g_interface_info_get_n_methods, g_interface_info_get_method);
+}
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
+static PyObject *
+_wrap_g_interface_info_find_method (PyGIBaseInfo *self, PyObject *py_name)
+{
+ return _get_child_info_by_name (self, py_name, g_interface_info_find_method);
+}
- info = (GIBaseInfo *) g_interface_info_get_method ( (GIInterfaceInfo *) self->info, i);
- g_assert (info != NULL);
+static PyObject *
+_wrap_g_interface_info_get_constants (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_interface_info_get_n_constants, g_interface_info_get_constant);
+}
- py_info = _pygi_info_new (info);
+static PyObject *
+_wrap_g_interface_info_get_vfuncs (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_interface_info_get_n_vfuncs, g_interface_info_get_vfunc);
+}
- g_base_info_unref (info);
+static PyObject *
+_wrap_g_interface_info_find_vfunc (PyGIBaseInfo *self, PyObject *py_name)
+{
+ return _get_child_info_by_name (self, py_name, g_interface_info_find_vfunc);
+}
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
+static PyObject *
+_wrap_g_interface_info_get_prerequisites (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_interface_info_get_n_prerequisites, g_interface_info_get_prerequisite);
+}
- PyTuple_SET_ITEM (infos, i, py_info);
- }
+static PyObject *
+_wrap_g_interface_info_get_properties (PyGIBaseInfo *self)
+{
+ return _make_infos_tuple (self, g_interface_info_get_n_properties, g_interface_info_get_property);
+}
- return infos;
+static PyObject *
+_wrap_g_interface_info_get_iface_struct (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_interface_info_get_iface_struct);
}
static PyObject *
-_wrap_g_interface_info_get_constants (PyGIBaseInfo *self)
+_wrap_g_interface_info_get_signals (PyGIBaseInfo *self)
{
- return _get_constants (self, GI_INFO_TYPE_INTERFACE);
+ return _make_infos_tuple (self, g_interface_info_get_n_signals, g_interface_info_get_signal);
}
static PyObject *
-_wrap_g_interface_info_get_vfuncs (PyGIBaseInfo *self)
+_wrap_g_interface_info_find_signal (PyGIBaseInfo *self, PyObject *py_name)
{
- return _get_vfuncs (self, GI_INFO_TYPE_INTERFACE);
+ return _get_child_info_by_name (self, py_name, g_interface_info_find_signal);
}
static PyMethodDef _PyGIInterfaceInfo_methods[] = {
+ { "get_prerequisites", (PyCFunction) _wrap_g_interface_info_get_prerequisites, METH_NOARGS },
+ { "get_properties", (PyCFunction) _wrap_g_interface_info_get_properties, METH_NOARGS },
{ "get_methods", (PyCFunction) _wrap_g_interface_info_get_methods, METH_NOARGS },
- { "get_constants", (PyCFunction) _wrap_g_interface_info_get_constants, METH_NOARGS },
+ { "find_method", (PyCFunction) _wrap_g_interface_info_find_method, METH_O },
+ { "get_signals", (PyCFunction) _wrap_g_interface_info_get_signals, METH_NOARGS },
+ { "find_signal", (PyCFunction) _wrap_g_interface_info_find_signal, METH_O },
{ "get_vfuncs", (PyCFunction) _wrap_g_interface_info_get_vfuncs, METH_NOARGS },
+ { "get_constants", (PyCFunction) _wrap_g_interface_info_get_constants, METH_NOARGS },
+ { "get_iface_struct", (PyCFunction) _wrap_g_interface_info_get_iface_struct, METH_NOARGS },
+ { "find_vfunc", (PyCFunction) _wrap_g_interface_info_find_vfunc, METH_O },
{ NULL, NULL, 0 }
};
/* GIConstantInfo */
-PYGLIB_DEFINE_TYPE ("gi.ConstantInfo", PyGIConstantInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.ConstantInfo", PyGIConstantInfo_Type, PyGIBaseInfo);
static PyObject *
_wrap_g_constant_info_get_value (PyGIBaseInfo *self)
{
GITypeInfo *type_info;
- GIArgument value;
+ GIArgument value = {0};
PyObject *py_value;
gboolean free_array = FALSE;
@@ -1548,16 +1768,16 @@ static PyMethodDef _PyGIConstantInfo_methods[] = {
};
/* GIValueInfo */
-PYGLIB_DEFINE_TYPE ("gi.ValueInfo", PyGIValueInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.ValueInfo", PyGIValueInfo_Type, PyGIBaseInfo);
static PyObject *
_wrap_g_value_info_get_value (PyGIBaseInfo *self)
{
- glong value;
+ gint64 value;
value = g_value_info_get_value ( (GIValueInfo *) self->info);
- return PYGLIB_PyLong_FromLong (value);
+ return pygi_gint64_to_py (value);
}
@@ -1568,7 +1788,119 @@ static PyMethodDef _PyGIValueInfo_methods[] = {
/* GIFieldInfo */
-PYGLIB_DEFINE_TYPE ("gi.FieldInfo", PyGIFieldInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.FieldInfo", PyGIFieldInfo_Type, PyGIBaseInfo);
+
+static gssize
+_struct_field_array_length_marshal (gsize length_index,
+ void *container_ptr,
+ void *struct_data_ptr)
+{
+ gssize array_len = -1;
+ GIFieldInfo *array_len_field = NULL;
+ GIArgument arg = {0};
+ GIBaseInfo *container_info = (GIBaseInfo *)container_ptr;
+
+ switch (g_base_info_get_type (container_info)) {
+ case GI_INFO_TYPE_UNION:
+ array_len_field = g_union_info_get_field ((GIUnionInfo *)container_info, (gint)length_index);
+ break;
+ case GI_INFO_TYPE_STRUCT:
+ array_len_field = g_struct_info_get_field ((GIStructInfo *)container_info, (gint)length_index);
+ break;
+ case GI_INFO_TYPE_OBJECT:
+ array_len_field = g_object_info_get_field ((GIObjectInfo *)container_info, (gint)length_index);
+ break;
+ default:
+ /* Other types don't have fields. */
+ g_assert_not_reached();
+ }
+
+ if (array_len_field == NULL) {
+ return -1;
+ }
+
+ if (g_field_info_get_field (array_len_field, struct_data_ptr, &arg)) {
+ GITypeInfo *array_len_type_info;
+
+ array_len_type_info = g_field_info_get_type (array_len_field);
+ if (array_len_type_info == NULL) {
+ goto out;
+ }
+
+ if (!pygi_argument_to_gssize (&arg,
+ g_type_info_get_tag (array_len_type_info),
+ &array_len)) {
+ array_len = -1;
+ }
+
+ g_base_info_unref (array_len_type_info);
+ }
+
+out:
+ g_base_info_unref (array_len_field);
+ return array_len;
+}
+
+static gint
+_pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
+ PyObject *object)
+{
+ gint retval;
+
+ GType g_type;
+ PyObject *py_type;
+ gchar *type_name_expected = NULL;
+ GIInfoType interface_type;
+
+ interface_type = g_base_info_get_type (info);
+ if ( (interface_type == GI_INFO_TYPE_STRUCT) &&
+ (g_struct_info_is_foreign ( (GIStructInfo*) info))) {
+ /* TODO: Could we check is the correct foreign type? */
+ return 1;
+ }
+
+ g_type = g_registered_type_info_get_g_type (info);
+ if (g_type != G_TYPE_NONE) {
+ py_type = pygi_type_get_from_g_type (g_type);
+ } else {
+ py_type = pygi_type_import_by_gi_info ( (GIBaseInfo *) info);
+ }
+
+ if (py_type == NULL) {
+ return 0;
+ }
+
+ g_assert (PyType_Check (py_type));
+
+ retval = PyObject_IsInstance (object, py_type);
+ if (!retval) {
+ type_name_expected = _pygi_g_base_info_get_fullname (
+ (GIBaseInfo *) info);
+ }
+
+ Py_DECREF (py_type);
+
+ if (!retval) {
+ PyTypeObject *object_type;
+
+ if (type_name_expected == NULL) {
+ return -1;
+ }
+
+ object_type = (PyTypeObject *) PyObject_Type (object);
+ if (object_type == NULL) {
+ g_free (type_name_expected);
+ return -1;
+ }
+
+ PyErr_Format (PyExc_TypeError, "Must be %s, not %s",
+ type_name_expected, object_type->tp_name);
+
+ g_free (type_name_expected);
+ }
+
+ return retval;
+}
static PyObject *
_wrap_g_field_info_get_value (PyGIBaseInfo *self,
@@ -1593,7 +1925,7 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self,
g_assert (container_info != NULL);
/* Check the instance. */
- if (!_pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) container_info, TRUE, instance)) {
+ if (!_pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) container_info, instance)) {
_PyGI_ERROR_PREFIX ("argument 1: ");
return NULL;
}
@@ -1659,8 +1991,12 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self,
}
if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) {
- value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL, NULL,
- field_type_info, &free_array);
+ value.v_pointer = _pygi_argument_to_array (&value,
+ _struct_field_array_length_marshal,
+ container_info,
+ pointer,
+ field_type_info,
+ &free_array);
}
argument_to_object:
@@ -1697,7 +2033,7 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self,
g_assert (container_info != NULL);
/* Check the instance. */
- if (!_pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) container_info, TRUE, instance)) {
+ if (!_pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) container_info, instance)) {
_PyGI_ERROR_PREFIX ("argument 1: ");
return NULL;
}
@@ -1719,21 +2055,6 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self,
field_type_info = g_field_info_get_type ( (GIFieldInfo *) self->info);
- /* Check the value. */
- {
- gboolean retval;
-
- retval = _pygi_g_type_info_check_object (field_type_info, py_value, TRUE);
- if (retval < 0) {
- goto out;
- }
-
- if (!retval) {
- _PyGI_ERROR_PREFIX ("argument 2: ");
- goto out;
- }
- }
-
/* Set the field's value. */
/* A few types are not handled by g_field_info_set_field, so do it here. */
if (!g_type_info_is_pointer (field_type_info)
@@ -1779,7 +2100,7 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self,
size = g_struct_info_get_size ( (GIStructInfo *) info);
g_assert (size > 0);
- g_memmove ((char*) pointer + offset, value.v_pointer, size);
+ memmove ((char*) pointer + offset, value.v_pointer, size);
g_base_info_unref (info);
@@ -1828,122 +2149,116 @@ out:
return retval;
}
+static PyObject *
+_wrap_g_field_info_get_flags (PyGIBaseInfo *self)
+{
+ return pygi_guint_to_py (g_field_info_get_flags (self->info));
+}
+
+static PyObject *
+_wrap_g_field_info_get_size (PyGIBaseInfo *self)
+{
+ return pygi_gint_to_py (g_field_info_get_size (self->info));
+}
+
+static PyObject *
+_wrap_g_field_info_get_offset (PyGIBaseInfo *self)
+{
+ return pygi_gint_to_py (g_field_info_get_offset (self->info));
+}
+
+static PyObject *
+_wrap_g_field_info_get_type (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_field_info_get_type);
+}
+
static PyMethodDef _PyGIFieldInfo_methods[] = {
{ "get_value", (PyCFunction) _wrap_g_field_info_get_value, METH_VARARGS },
{ "set_value", (PyCFunction) _wrap_g_field_info_set_value, METH_VARARGS },
+ { "get_flags", (PyCFunction) _wrap_g_field_info_get_flags, METH_VARARGS },
+ { "get_size", (PyCFunction) _wrap_g_field_info_get_size, METH_VARARGS },
+ { "get_offset", (PyCFunction) _wrap_g_field_info_get_offset, METH_VARARGS },
+ { "get_type", (PyCFunction) _wrap_g_field_info_get_type, METH_VARARGS },
{ NULL, NULL, 0 }
};
/* GIUnresolvedInfo */
-PYGLIB_DEFINE_TYPE ("gi.UnresolvedInfo", PyGIUnresolvedInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.UnresolvedInfo", PyGIUnresolvedInfo_Type, PyGIBaseInfo);
static PyMethodDef _PyGIUnresolvedInfo_methods[] = {
{ NULL, NULL, 0 }
};
/* GIVFuncInfo */
-PYGLIB_DEFINE_TYPE ("gi.VFuncInfo", PyGIVFuncInfo_Type, PyGICallableInfo);
+PYGI_DEFINE_TYPE ("gi.VFuncInfo", PyGIVFuncInfo_Type, PyGICallableInfo);
static PyObject *
-_wrap_g_vfunc_info_get_invoker (PyGIBaseInfo *self)
+_wrap_g_vfunc_info_get_flags (PyGIBaseInfo *self)
{
- PyObject *result = Py_None;
- GIBaseInfo *info;
+ return pygi_guint_to_py (g_vfunc_info_get_flags ((GIVFuncInfo *) self->info));
+}
- info = (GIBaseInfo *) g_vfunc_info_get_invoker ( (GIVFuncInfo *) self->info );
- if (info)
- result = _pygi_info_new(info);
- else
- Py_INCREF(Py_None);
+static PyObject *
+_wrap_g_vfunc_info_get_offset (PyGIBaseInfo *self)
+{
+ return pygi_gint_to_py (g_vfunc_info_get_offset ((GIVFuncInfo *) self->info));
+}
- return result;
+static PyObject *
+_wrap_g_vfunc_info_get_signal (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_vfunc_info_get_signal);
+}
+
+static PyObject *
+_wrap_g_vfunc_info_get_invoker (PyGIBaseInfo *self)
+{
+ return _get_child_info (self, g_vfunc_info_get_invoker);
}
static PyMethodDef _PyGIVFuncInfo_methods[] = {
+ { "get_flags", (PyCFunction) _wrap_g_vfunc_info_get_flags, METH_NOARGS },
+ { "get_offset", (PyCFunction) _wrap_g_vfunc_info_get_offset, METH_NOARGS },
+ { "get_signal", (PyCFunction) _wrap_g_vfunc_info_get_signal, METH_NOARGS },
{ "get_invoker", (PyCFunction) _wrap_g_vfunc_info_get_invoker, METH_NOARGS },
{ NULL, NULL, 0 }
};
/* GIUnionInfo */
-PYGLIB_DEFINE_TYPE ("gi.UnionInfo", PyGIUnionInfo_Type, PyGIBaseInfo);
+PYGI_DEFINE_TYPE ("gi.UnionInfo", PyGIUnionInfo_Type, PyGIBaseInfo);
static PyObject *
_wrap_g_union_info_get_fields (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- n_infos = g_union_info_get_n_fields ( (GIUnionInfo *) self->info);
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- info = (GIBaseInfo *) g_union_info_get_field ( (GIUnionInfo *) self->info, i);
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
-
- PyTuple_SET_ITEM (infos, i, py_info);
- }
-
- return infos;
+ return _make_infos_tuple (self, g_union_info_get_n_fields, g_union_info_get_field);
}
static PyObject *
_wrap_g_union_info_get_methods (PyGIBaseInfo *self)
{
- gssize n_infos;
- PyObject *infos;
- gssize i;
-
- n_infos = g_union_info_get_n_methods ( (GIUnionInfo *) self->info);
-
- infos = PyTuple_New (n_infos);
- if (infos == NULL) {
- return NULL;
- }
-
- for (i = 0; i < n_infos; i++) {
- GIBaseInfo *info;
- PyObject *py_info;
-
- info = (GIBaseInfo *) g_union_info_get_method ( (GIUnionInfo *) self->info, i);
- g_assert (info != NULL);
-
- py_info = _pygi_info_new (info);
-
- g_base_info_unref (info);
-
- if (py_info == NULL) {
- Py_CLEAR (infos);
- break;
- }
+ return _make_infos_tuple (self, g_union_info_get_n_methods, g_union_info_get_method);
+}
- PyTuple_SET_ITEM (infos, i, py_info);
- }
+static PyObject *
+_wrap_g_union_info_get_size (PyGIBaseInfo *self)
+{
+ return pygi_gsize_to_py (g_union_info_get_size (self->info));
+}
- return infos;
+static PyObject *
+_wrap_g_union_info_get_alignment (PyGIBaseInfo *self)
+{
+ return pygi_gsize_to_py (g_union_info_get_alignment (self->info));
}
static PyMethodDef _PyGIUnionInfo_methods[] = {
{ "get_fields", (PyCFunction) _wrap_g_union_info_get_fields, METH_NOARGS },
{ "get_methods", (PyCFunction) _wrap_g_union_info_get_methods, METH_NOARGS },
+ { "get_size", (PyCFunction) _wrap_g_union_info_get_size, METH_NOARGS },
+ { "get_alignment", (PyCFunction) _wrap_g_union_info_get_alignment, METH_NOARGS },
{ NULL, NULL, 0 }
};
@@ -1959,12 +2274,12 @@ _pygi_g_base_info_get_fullname (GIBaseInfo *info)
if (container_info != NULL) {
fullname = g_strdup_printf ("%s.%s.%s",
g_base_info_get_namespace (container_info),
- g_base_info_get_name (container_info),
- g_base_info_get_name (info));
+ _safe_base_info_get_name (container_info),
+ _safe_base_info_get_name (info));
} else {
fullname = g_strdup_printf ("%s.%s",
g_base_info_get_namespace (info),
- g_base_info_get_name (info));
+ _safe_base_info_get_name (info));
}
if (fullname == NULL) {
@@ -1974,21 +2289,28 @@ _pygi_g_base_info_get_fullname (GIBaseInfo *info)
return fullname;
}
-void
-_pygi_info_register_types (PyObject *m)
+
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_info_register_types (PyObject *m)
{
#define _PyGI_REGISTER_TYPE(m, type, cname, base) \
- Py_TYPE(&type) = &PyType_Type; \
+ Py_SET_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, #cname, (PyObject *)&type)) \
- return
+ if (PyType_Ready(&type) < 0) \
+ return -1; \
+ Py_INCREF ((PyObject *)&type); \
+ if (PyModule_AddObject(m, #cname, (PyObject *)&type) < 0) { \
+ Py_DECREF ((PyObject *)&type); \
+ return -1; \
+ };
- Py_TYPE(&PyGIBaseInfo_Type) = &PyType_Type;
+ Py_SET_TYPE(&PyGIBaseInfo_Type, &PyType_Type);
PyGIBaseInfo_Type.tp_dealloc = (destructor) _base_info_dealloc;
PyGIBaseInfo_Type.tp_repr = (reprfunc) _base_info_repr;
@@ -1999,36 +2321,44 @@ _pygi_info_register_types (PyObject *m)
PyGIBaseInfo_Type.tp_getset = _base_info_getsets;
PyGIBaseInfo_Type.tp_getattro = (getattrofunc) _base_info_getattro;
- if (PyType_Ready(&PyGIBaseInfo_Type))
- return;
- if (PyModule_AddObject(m, "BaseInfo", (PyObject *)&PyGIBaseInfo_Type))
- return;
-
- if (PyModule_AddObject(m, "DIRECTION_IN", PyLong_FromLong(GI_DIRECTION_IN)))
- return;
- if (PyModule_AddObject(m, "DIRECTION_OUT", PyLong_FromLong(GI_DIRECTION_OUT)))
- return;
- if (PyModule_AddObject(m, "DIRECTION_INOUT", PyLong_FromLong(GI_DIRECTION_INOUT)))
- return;
+ if (PyType_Ready(&PyGIBaseInfo_Type) < 0)
+ return -1;
+ Py_INCREF ((PyObject *)&PyGIBaseInfo_Type);
+ if (PyModule_AddObject(m, "BaseInfo", (PyObject *)&PyGIBaseInfo_Type) < 0) {
+ Py_DECREF ((PyObject *)&PyGIBaseInfo_Type);
+ return -1;
+ }
- _PyGI_REGISTER_TYPE (m, PyGICallableInfo_Type, CallableInfo,
- PyGIBaseInfo_Type);
PyGICallableInfo_Type.tp_call = (ternaryfunc) _callable_info_call;
+ PyGICallableInfo_Type.tp_repr = (reprfunc) _callable_info_repr;
PyGICallableInfo_Type.tp_dealloc = (destructor) _callable_info_dealloc;
+ _PyGI_REGISTER_TYPE (m, PyGICallableInfo_Type, CallableInfo,
+ PyGIBaseInfo_Type);
+ // FIXME: this is to work around a pylint issue
+ // https://gitlab.gnome.org/GNOME/pygobject/issues/217
+#ifndef PYPY_VERSION
_PyGI_REGISTER_TYPE (m, PyGIFunctionInfo_Type, FunctionInfo,
PyGICallableInfo_Type);
+#endif
PyGIFunctionInfo_Type.tp_call = (ternaryfunc) _function_info_call;
PyGIFunctionInfo_Type.tp_descr_get = (descrgetfunc) _function_info_descr_get;
+#ifdef PYPY_VERSION
+ _PyGI_REGISTER_TYPE (m, PyGIFunctionInfo_Type, FunctionInfo,
+ PyGICallableInfo_Type);
+#endif
+ PyGIVFuncInfo_Type.tp_descr_get = (descrgetfunc) _vfunc_info_descr_get;
_PyGI_REGISTER_TYPE (m, PyGIVFuncInfo_Type, VFuncInfo,
PyGICallableInfo_Type);
- PyGIVFuncInfo_Type.tp_descr_get = (descrgetfunc) _vfunc_info_descr_get;
+
+ _PyGI_REGISTER_TYPE (m, PyGISignalInfo_Type, SignalInfo,
+ PyGICallableInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIUnresolvedInfo_Type, UnresolvedInfo,
PyGIBaseInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGICallbackInfo_Type, CallbackInfo,
- PyGIBaseInfo_Type);
+ PyGICallableInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIRegisteredTypeInfo_Type, RegisteredTypeInfo,
PyGIBaseInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIStructInfo_Type, StructInfo,
@@ -2047,12 +2377,8 @@ _pygi_info_register_types (PyObject *m)
PyGIBaseInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIUnionInfo_Type, UnionInfo,
PyGIRegisteredTypeInfo_Type);
- _PyGI_REGISTER_TYPE (m, PyGIBoxedInfo_Type, BoxedInfo,
- PyGIBaseInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIErrorDomainInfo_Type, ErrorDomainInfo,
PyGIBaseInfo_Type);
- _PyGI_REGISTER_TYPE (m, PyGISignalInfo_Type, SignalInfo,
- PyGIBaseInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIPropertyInfo_Type, PropertyInfo,
PyGIBaseInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIArgInfo_Type, ArgInfo,
@@ -2060,6 +2386,148 @@ _pygi_info_register_types (PyObject *m)
_PyGI_REGISTER_TYPE (m, PyGITypeInfo_Type, TypeInfo,
PyGIBaseInfo_Type);
-
#undef _PyGI_REGISTER_TYPE
+
+#define _PyGI_ENUM_BEGIN(name) \
+ { \
+ const char *__enum_name = #name; \
+ PyObject *__enum_value = NULL; \
+ PyObject *__new_enum_cls = NULL; \
+ PyObject *__enum_instance_dict = PyDict_New(); \
+ PyObject *__module_name = PyObject_GetAttrString (m, "__name__"); \
+ PyDict_SetItemString (__enum_instance_dict, "__module__", __module_name); \
+ Py_DECREF (__module_name);
+
+#define _PyGI_ENUM_ADD_VALUE(prefix, name) \
+ __enum_value = pygi_guint_to_py (prefix##_##name); \
+ if (PyDict_SetItemString(__enum_instance_dict, #name, __enum_value) < 0) { \
+ Py_DECREF (__enum_instance_dict); \
+ Py_DECREF (__enum_value); \
+ return -1; \
+ } \
+ Py_DECREF (__enum_value);
+
+#define _PyGI_ENUM_END \
+ __new_enum_cls = PyObject_CallFunction ((PyObject *)&PyType_Type, "s(O)O", \
+ __enum_name, (PyObject *)&PyType_Type, \
+ __enum_instance_dict); \
+ Py_DECREF (__enum_instance_dict); \
+ PyModule_AddObject (m, __enum_name, __new_enum_cls); /* steals ref */ \
+ }
+
+
+ /* GIDirection */
+ _PyGI_ENUM_BEGIN (Direction)
+ _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, IN)
+ _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, OUT)
+ _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, INOUT)
+ _PyGI_ENUM_END
+
+
+ /* GITransfer */
+ _PyGI_ENUM_BEGIN (Transfer)
+ _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, NOTHING)
+ _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, CONTAINER)
+ _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, EVERYTHING)
+ _PyGI_ENUM_END
+
+ /* GIArrayType */
+ _PyGI_ENUM_BEGIN (ArrayType)
+ _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, C)
+ _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, ARRAY)
+ _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, PTR_ARRAY)
+ _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, BYTE_ARRAY)
+ _PyGI_ENUM_END
+
+ /* GIScopeType */
+ _PyGI_ENUM_BEGIN (ScopeType)
+ _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, INVALID)
+ _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, CALL)
+ _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, ASYNC)
+ _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, NOTIFIED)
+ _PyGI_ENUM_END
+
+ /* GIVFuncInfoFlags */
+ _PyGI_ENUM_BEGIN (VFuncInfoFlags)
+ _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, CHAIN_UP)
+ _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, OVERRIDE)
+ _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, NOT_OVERRIDE)
+ _PyGI_ENUM_END
+
+ /* GIFieldInfoFlags */
+ _PyGI_ENUM_BEGIN (FieldInfoFlags)
+ _PyGI_ENUM_ADD_VALUE (GI_FIELD, IS_READABLE)
+ _PyGI_ENUM_ADD_VALUE (GI_FIELD, IS_WRITABLE)
+ _PyGI_ENUM_END
+
+ /* GIFunctionInfoFlags */
+ _PyGI_ENUM_BEGIN (FunctionInfoFlags)
+ _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_METHOD)
+ _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_CONSTRUCTOR)
+ _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_GETTER)
+ _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_SETTER)
+ _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, WRAPS_VFUNC)
+ _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, THROWS)
+ _PyGI_ENUM_END
+
+ /* GITypeTag */
+ _PyGI_ENUM_BEGIN (TypeTag)
+ /* Basic types */
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, VOID)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, BOOLEAN)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT8)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT8)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT16)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT16)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT32)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT32)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT64)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT64)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, FLOAT)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, DOUBLE)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GTYPE)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UTF8)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, FILENAME)
+
+ /* Non-basic types; compare with G_TYPE_TAG_IS_BASIC */
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, ARRAY)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INTERFACE)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GLIST)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GSLIST)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GHASH)
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, ERROR)
+
+ /* Another basic type */
+ _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UNICHAR)
+ _PyGI_ENUM_END
+
+ /* GIInfoType */
+ _PyGI_ENUM_BEGIN (InfoType)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, INVALID)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, FUNCTION)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, CALLBACK)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, STRUCT)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, BOXED)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, ENUM)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, FLAGS)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, OBJECT)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, INTERFACE)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, CONSTANT)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, INVALID_0)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, UNION)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, VALUE)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, SIGNAL)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, VFUNC)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, PROPERTY)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, FIELD)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, ARG)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, TYPE)
+ _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, UNRESOLVED)
+ _PyGI_ENUM_END
+
+#undef _PyGI_ENUM_BEGIN
+#undef _PyGI_ENUM_ADD_VALUE
+#undef _PyGI_ENUM_END
+
+ return 0;
}
diff --git a/gi/pygi-info.h b/gi/pygi-info.h
index d550d8d..12ef491 100644
--- a/gi/pygi-info.h
+++ b/gi/pygi-info.h
@@ -14,9 +14,7 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_INFO_H__
@@ -25,9 +23,31 @@
#include <Python.h>
#include <girepository.h>
+#include "pygi-cache.h"
G_BEGIN_DECLS
+typedef struct {
+ PyObject_HEAD
+ GIBaseInfo *info;
+ PyObject *inst_weakreflist;
+ PyGICallableCache *cache;
+} PyGIBaseInfo;
+
+typedef struct {
+ PyGIBaseInfo base;
+
+ /* Reference the unbound version of this struct.
+ * We use this for the actual call to invoke because it manages the cache.
+ */
+ struct PyGICallableInfo *py_unbound_info;
+
+ /* Holds bound argument for instance, class, and vfunc methods. */
+ PyObject *py_bound_arg;
+
+} PyGICallableInfo;
+
+
gboolean pygi_g_struct_info_is_simple (GIStructInfo *struct_info);
@@ -66,7 +86,7 @@ gchar* _pygi_g_base_info_get_fullname (GIBaseInfo *info);
gsize _pygi_g_type_tag_size (GITypeTag type_tag);
gsize _pygi_g_type_info_size (GITypeInfo *type_info);
-void _pygi_info_register_types (PyObject *m);
+int pygi_info_register_types (PyObject *m);
gboolean _pygi_is_python_keyword (const gchar *name);
diff --git a/gi/pygi-invoke-state-struct.h b/gi/pygi-invoke-state-struct.h
index 1d9e49c..dbf4e66 100644
--- a/gi/pygi-invoke-state-struct.h
+++ b/gi/pygi-invoke-state-struct.h
@@ -7,42 +7,60 @@
G_BEGIN_DECLS
+typedef struct _PyGIInvokeArgState
+{
+ /* Holds memory for the C value of arguments marshaled "to" or "from" Python. */
+ GIArgument arg_value;
+
+ /* Holds pointers to values in arg_values or a caller allocated chunk of
+ * memory via arg_pointer.v_pointer.
+ */
+ GIArgument arg_pointer;
+
+ /* Holds from_py marshaler cleanup data. */
+ gpointer arg_cleanup_data;
+
+ /* Holds to_py marshaler cleanup data. */
+ gpointer to_py_arg_cleanup_data;
+} PyGIInvokeArgState;
+
+
typedef struct _PyGIInvokeState
{
PyObject *py_in_args;
gssize n_py_in_args;
- gssize current_arg;
-
- GType implementor_gtype;
-
- GIArgument **args;
- GIArgument *in_args;
-
- /* Generic array allocated to the same length as args
- * for use as extra per-arg state data. */
- gpointer *args_data;
-
- /* Out args and out values
- * In order to pass a parameter and get something back out in C
- * we need to pass a pointer to the value, e.g.
- * int *out_integer;
- *
- * so while out_args == out_integer, out_value == *out_integer
- * or in other words out_args = &out_values
- *
- * We do all of our processing on out_values but we pass out_args to
- * the actual function.
+
+ /* Number of arguments the ffi wrapped C function takes. Used as the exact
+ * count for argument related arrays held in this struct.
+ */
+ gssize n_args;
+
+ /* List of arguments passed to ffi. Elements can point directly to values held in
+ * arg_values for "in/from Python" or indirectly via arg_pointers for
+ * "out/inout/to Python". In the latter case, the args[x].arg_pointer.v_pointer
+ * member points to memory for the value storage.
*/
- GIArgument *out_args;
- GIArgument *out_values;
+ GIArgument **ffi_args;
+
+ /* Array of size n_args containing per argument state */
+ PyGIInvokeArgState *args;
+ /* Memory to receive the result of the C ffi function call. */
GIArgument return_arg;
+ gpointer to_py_return_arg_cleanup_data;
+ /* A GError exception which is indirectly bound into the last position of
+ * the "args" array if the callable caches "throws" member is set.
+ */
GError *error;
gboolean failed;
gpointer user_data;
+
+ /* Function pointer to call with ffi. */
+ gpointer function_ptr;
+
} PyGIInvokeState;
G_END_DECLS
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 17cd278..7b822e4 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -17,87 +17,20 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <pyglib.h>
#include "pygi-invoke.h"
#include "pygi-marshal-cleanup.h"
+#include "pygi-error.h"
+#include "pygi-resulttuple.h"
+#include "pygi-foreign.h"
+#include "pygi-boxed.h"
-static inline gboolean
-_invoke_callable (PyGIInvokeState *state,
- PyGICallableCache *cache,
- GICallableInfo *callable_info,
- GCallback function_ptr)
-{
- GError *error;
- gint retval;
-
- error = NULL;
-
- Py_BEGIN_ALLOW_THREADS;
-
- /* FIXME: use this for now but we can streamline the calls */
- if (cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)
- retval = g_vfunc_info_invoke ( callable_info,
- state->implementor_gtype,
- state->in_args,
- cache->n_from_py_args,
- state->out_args,
- cache->n_to_py_args,
- &state->return_arg,
- &error);
- else if (g_base_info_get_type (callable_info) == GI_INFO_TYPE_CALLBACK)
- retval = g_callable_info_invoke (callable_info,
- function_ptr,
- state->in_args,
- cache->n_from_py_args,
- state->out_args,
- cache->n_to_py_args,
- &state->return_arg,
- FALSE,
- FALSE,
- &error);
- else
- retval = g_function_info_invoke ( callable_info,
- state->in_args,
- cache->n_from_py_args,
- state->out_args,
- cache->n_to_py_args,
- &state->return_arg,
- &error);
- Py_END_ALLOW_THREADS;
-
- if (!retval) {
- g_assert (error != NULL);
- pyglib_error_check (&error);
-
- /* It is unclear if the error occured before or after the C
- * function was invoked so for now assume success
- * We eventually should marshal directly to FFI so we no longer
- * have to use the reference implementation
- */
- pygi_marshal_cleanup_args_from_py_marshal_success (state, cache);
-
- return FALSE;
- }
-
- if (state->error != NULL) {
- if (pyglib_error_check (&(state->error))) {
- /* even though we errored out, the call itself was successful,
- so we assume the call processed all of the parameters */
- pygi_marshal_cleanup_args_from_py_marshal_success (state, cache);
- return FALSE;
- }
- }
-
- return TRUE;
-}
+extern PyObject *_PyGIDefaultArgPlaceholder;
static gboolean
-_check_for_unexpected_kwargs (const gchar *function_name,
+_check_for_unexpected_kwargs (PyGICallableCache *cache,
GHashTable *arg_name_hash,
PyObject *py_kwargs)
{
@@ -107,12 +40,6 @@ _check_for_unexpected_kwargs (const gchar *function_name,
while (PyDict_Next (py_kwargs, &dict_iter_pos, &dict_key, &dict_value)) {
PyObject *key;
-#if PY_VERSION_HEX < 0x03000000
- if (PyString_Check (dict_key)) {
- Py_INCREF (dict_key);
- key = dict_key;
- } else
-#endif
{
key = PyUnicode_AsUTF8String (dict_key);
if (key == NULL) {
@@ -120,12 +47,18 @@ _check_for_unexpected_kwargs (const gchar *function_name,
}
}
- if (g_hash_table_lookup (arg_name_hash, PyBytes_AsString(key)) == NULL) {
+ /* Use extended lookup because it returns whether or not the key actually
+ * exists in the hash table. g_hash_table_lookup returns NULL for keys not
+ * found which maps to index 0 for our hash lookup.
+ */
+ if (!g_hash_table_lookup_extended (arg_name_hash, PyBytes_AsString(key), NULL, NULL)) {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
PyErr_Format (PyExc_TypeError,
"%.200s() got an unexpected keyword argument '%.400s'",
- function_name,
+ full_name,
PyBytes_AsString (key));
Py_DECREF (key);
+ g_free (full_name);
return FALSE;
}
@@ -149,9 +82,8 @@ _py_args_combine_and_check_length (PyGICallableCache *cache,
{
PyObject *combined_py_args = NULL;
Py_ssize_t n_py_args, n_py_kwargs, i;
- guint n_expected_args;
+ gssize n_expected_args = cache->n_py_args;
GSList *l;
- const gchar *function_name = cache->name;
n_py_args = PyTuple_GET_SIZE (py_args);
if (py_kwargs == NULL)
@@ -160,24 +92,34 @@ _py_args_combine_and_check_length (PyGICallableCache *cache,
n_py_kwargs = PyDict_Size (py_kwargs);
/* Fast path, we already have the exact number of args and not kwargs. */
- n_expected_args = g_slist_length (cache->arg_name_list);
- if (n_py_kwargs == 0 && n_py_args == n_expected_args) {
+ if (n_py_kwargs == 0 && n_py_args == n_expected_args && cache->user_data_varargs_index < 0) {
Py_INCREF (py_args);
return py_args;
}
- if (n_expected_args < n_py_args) {
+ if (cache->user_data_varargs_index < 0 && n_expected_args < n_py_args) {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
PyErr_Format (PyExc_TypeError,
- "%.200s() takes exactly %d %sargument%s (%zd given)",
- function_name,
+ "%.200s() takes exactly %zd %sargument%s (%zd given)",
+ full_name,
n_expected_args,
n_py_kwargs > 0 ? "non-keyword " : "",
n_expected_args == 1 ? "" : "s",
n_py_args);
+ g_free (full_name);
return NULL;
}
- if (n_py_kwargs > 0 && !_check_for_unexpected_kwargs (function_name,
+ if (cache->user_data_varargs_index >= 0 && n_py_kwargs > 0 && n_expected_args < n_py_args) {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
+ PyErr_Format (PyExc_TypeError,
+ "%.200s() cannot use variable user data arguments with keyword arguments",
+ full_name);
+ g_free (full_name);
+ return NULL;
+ }
+
+ if (n_py_kwargs > 0 && !_check_for_unexpected_kwargs (cache,
cache->arg_name_hash,
py_kwargs)) {
return NULL;
@@ -187,46 +129,84 @@ _py_args_combine_and_check_length (PyGICallableCache *cache,
* when they are combined into a single tuple */
combined_py_args = PyTuple_New (n_expected_args);
- for (i = 0; i < n_py_args; i++) {
- PyObject *item = PyTuple_GET_ITEM (py_args, i);
- Py_INCREF (item);
- PyTuple_SET_ITEM (combined_py_args, i, item);
- }
-
for (i = 0, l = cache->arg_name_list; i < n_expected_args && l; i++, l = l->next) {
- PyObject *py_arg_item, *kw_arg_item = NULL;
+ PyObject *py_arg_item = NULL;
+ PyObject *kw_arg_item = NULL;
const gchar *arg_name = l->data;
+ int arg_cache_index = -1;
+ gboolean is_varargs_user_data = FALSE;
+
+ if (arg_name != NULL)
+ arg_cache_index = GPOINTER_TO_INT (g_hash_table_lookup (cache->arg_name_hash, arg_name));
+
+ is_varargs_user_data = cache->user_data_varargs_index >= 0 &&
+ arg_cache_index == cache->user_data_varargs_index;
if (n_py_kwargs > 0 && arg_name != NULL) {
/* NULL means this argument has no keyword name */
/* ex. the first argument to a method or constructor */
kw_arg_item = PyDict_GetItemString (py_kwargs, arg_name);
}
- py_arg_item = PyTuple_GET_ITEM (combined_py_args, i);
- if (kw_arg_item != NULL && py_arg_item == NULL) {
- Py_INCREF (kw_arg_item);
- PyTuple_SET_ITEM (combined_py_args, i, kw_arg_item);
+ /* use a bounded retrieval of the original input */
+ if (i < n_py_args)
+ py_arg_item = PyTuple_GET_ITEM (py_args, i);
+
+ if (kw_arg_item == NULL && py_arg_item != NULL) {
+ if (is_varargs_user_data) {
+ /* For tail end user_data varargs, pull a slice off and we are done. */
+ PyObject *user_data = PyTuple_GetSlice (py_args, i, PY_SSIZE_T_MAX);
+ PyTuple_SET_ITEM (combined_py_args, i, user_data);
+ return combined_py_args;
+ } else {
+ Py_INCREF (py_arg_item);
+ PyTuple_SET_ITEM (combined_py_args, i, py_arg_item);
+ }
+ } else if (kw_arg_item != NULL && py_arg_item == NULL) {
+ if (is_varargs_user_data) {
+ /* Special case where user_data is passed as a keyword argument (user_data=foo)
+ * Wrap the value in a tuple to represent variable args for marshaling later on.
+ */
+ PyObject *user_data = Py_BuildValue("(O)", kw_arg_item, NULL);
+ PyTuple_SET_ITEM (combined_py_args, i, user_data);
+ } else {
+ Py_INCREF (kw_arg_item);
+ PyTuple_SET_ITEM (combined_py_args, i, kw_arg_item);
+ }
} else if (kw_arg_item == NULL && py_arg_item == NULL) {
- PyErr_Format (PyExc_TypeError,
- "%.200s() takes exactly %d %sargument%s (%zd given)",
- function_name,
- n_expected_args,
- n_py_kwargs > 0 ? "non-keyword " : "",
- n_expected_args == 1 ? "" : "s",
- n_py_args);
-
- Py_DECREF (combined_py_args);
- return NULL;
-
+ if (is_varargs_user_data) {
+ /* For varargs user_data, pass an empty tuple when nothing is given. */
+ PyTuple_SET_ITEM (combined_py_args, i, PyTuple_New (0));
+ } else if (arg_cache_index >= 0 && _pygi_callable_cache_get_arg (cache, arg_cache_index)->has_default) {
+ /* If the argument supports a default, use a place holder in the
+ * argument tuple, this will be checked later during marshaling.
+ */
+ Py_INCREF (_PyGIDefaultArgPlaceholder);
+ PyTuple_SET_ITEM (combined_py_args, i, _PyGIDefaultArgPlaceholder);
+ } else {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
+ PyErr_Format (PyExc_TypeError,
+ "%.200s() takes exactly %zd %sargument%s (%zd given)",
+ full_name,
+ n_expected_args,
+ n_py_kwargs > 0 ? "non-keyword " : "",
+ n_expected_args == 1 ? "" : "s",
+ n_py_args);
+ g_free (full_name);
+
+ Py_DECREF (combined_py_args);
+ return NULL;
+ }
} else if (kw_arg_item != NULL && py_arg_item != NULL) {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
PyErr_Format (PyExc_TypeError,
"%.200s() got multiple values for keyword argument '%.200s'",
- function_name,
+ full_name,
arg_name);
Py_DECREF (combined_py_args);
+ g_free (full_name);
return NULL;
}
}
@@ -234,209 +214,230 @@ _py_args_combine_and_check_length (PyGICallableCache *cache,
return combined_py_args;
}
-static inline gboolean
-_invoke_state_init_from_callable_cache (PyGIInvokeState *state,
- PyGICallableCache *cache,
- PyObject *py_args,
- PyObject *kwargs)
-{
- PyObject *combined_args = NULL;
- state->implementor_gtype = 0;
-
- /* TODO: We don't use the class parameter sent in by the structure
- * so we remove it from the py_args tuple but we can keep it
- * around if we want to call actual gobject constructors
- * in the future instead of calling g_object_new
- */
- if (cache->function_type == PYGI_FUNCTION_TYPE_CONSTRUCTOR) {
- PyObject *constructor_class;
- constructor_class = PyTuple_GetItem (py_args, 0);
-
- if (constructor_class == NULL) {
- PyErr_Clear ();
- PyErr_Format (PyExc_TypeError,
- "Constructors require the class to be passed in as an argument, "
- "No arguments passed to the %s constructor.",
- cache->name);
-
- return FALSE;
- }
- } else if (cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
- PyObject *py_gtype;
- py_gtype = PyTuple_GetItem (py_args, 0);
- if (py_gtype == NULL) {
- PyErr_SetString (PyExc_TypeError,
- "need the GType of the implementor class");
- return FALSE;
- }
+/* To reduce calls to g_slice_*() we (1) allocate all the memory depended on
+ * the argument count in one go and (2) keep one version per argument count
+ * around for faster reuse.
+ */
- state->implementor_gtype = pyg_type_from_object (py_gtype);
+#define PyGI_INVOKE_ARG_STATE_SIZE(n) (n * (sizeof (PyGIInvokeArgState) + sizeof (GIArgument *)))
+#define PyGI_INVOKE_ARG_STATE_N_MAX 10
+static gpointer free_arg_state[PyGI_INVOKE_ARG_STATE_N_MAX];
- if (state->implementor_gtype == 0)
- return FALSE;
- }
+/**
+ * _pygi_invoke_arg_state_init:
+ * Sets PyGIInvokeState.args and PyGIInvokeState.ffi_args.
+ * On error returns FALSE and sets an exception.
+ */
+gboolean
+_pygi_invoke_arg_state_init (PyGIInvokeState *state) {
- if (cache->function_type == PYGI_FUNCTION_TYPE_CONSTRUCTOR ||
- cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
+ gpointer mem;
- /* we could optimize this by using offsets instead of modifying the tuple but it makes the
- * code more error prone and confusing so don't do that unless profiling shows
- * significant gain
- */
- combined_args = PyTuple_GetSlice (py_args, 1, PyTuple_Size (py_args));
+ if (state->n_args < PyGI_INVOKE_ARG_STATE_N_MAX && (mem = free_arg_state[state->n_args]) != NULL) {
+ free_arg_state[state->n_args] = NULL;
+ memset (mem, 0, PyGI_INVOKE_ARG_STATE_SIZE (state->n_args));
} else {
- combined_args = py_args;
- Py_INCREF (combined_args);
+ mem = g_slice_alloc0 (PyGI_INVOKE_ARG_STATE_SIZE (state->n_args));
}
- state->py_in_args = _py_args_combine_and_check_length (cache,
- combined_args,
- kwargs);
- Py_DECREF (combined_args);
-
- if (state->py_in_args == NULL) {
+ if (mem == NULL && state->n_args != 0) {
+ PyErr_NoMemory();
return FALSE;
}
- state->n_py_in_args = PyTuple_Size (state->py_in_args);
- state->args = g_slice_alloc0 (cache->n_args * sizeof (GIArgument *));
- if (state->args == NULL && cache->n_args != 0) {
- PyErr_NoMemory();
- return FALSE;
+ if (mem != NULL) {
+ state->args = mem;
+ state->ffi_args = (gpointer)((gchar *)mem + state->n_args * sizeof (PyGIInvokeArgState));
}
- state->args_data = g_slice_alloc0 (cache->n_args * sizeof (gpointer));
- if (state->args_data == NULL && cache->n_args != 0) {
- PyErr_NoMemory();
- return FALSE;
+ return TRUE;
+}
+
+/**
+ * _pygi_invoke_arg_state_free:
+ * Frees PyGIInvokeState.args and PyGIInvokeState.ffi_args
+ */
+void
+_pygi_invoke_arg_state_free(PyGIInvokeState *state) {
+ if (state->n_args < PyGI_INVOKE_ARG_STATE_N_MAX && free_arg_state[state->n_args] == NULL) {
+ free_arg_state[state->n_args] = state->args;
+ return;
}
- state->in_args = g_slice_alloc0 (cache->n_from_py_args * sizeof(GIArgument));
- if (state->in_args == NULL && cache->n_from_py_args != 0) {
- PyErr_NoMemory ();
- return FALSE;
+ g_slice_free1 (PyGI_INVOKE_ARG_STATE_SIZE (state->n_args), state->args);
+}
+
+static gboolean
+_invoke_state_init_from_cache (PyGIInvokeState *state,
+ PyGIFunctionCache *function_cache,
+ PyObject *py_args,
+ PyObject *kwargs)
+{
+ PyGICallableCache *cache = (PyGICallableCache *) function_cache;
+
+ state->n_args = _pygi_callable_cache_args_len (cache);
+
+ if (cache->throws) {
+ state->n_args++;
}
- state->out_values = g_slice_alloc0 (cache->n_to_py_args * sizeof(GIArgument));
- if (state->out_values == NULL && cache->n_to_py_args != 0) {
- PyErr_NoMemory ();
+ /* Copy the function pointer to the state for the normal case. For vfuncs,
+ * this has already been filled out based on the implementor's GType.
+ */
+ if (state->function_ptr == NULL)
+ state->function_ptr = function_cache->invoker.native_address;
+
+ state->py_in_args = _py_args_combine_and_check_length (cache,
+ py_args,
+ kwargs);
+
+ if (state->py_in_args == NULL) {
return FALSE;
}
+ state->n_py_in_args = PyTuple_Size (state->py_in_args);
- state->out_args = g_slice_alloc0 (cache->n_to_py_args * sizeof(GIArgument));
- if (state->out_args == NULL && cache->n_to_py_args != 0) {
- PyErr_NoMemory ();
+ if (!_pygi_invoke_arg_state_init (state)) {
return FALSE;
}
state->error = NULL;
+ if (cache->throws) {
+ gssize error_index = state->n_args - 1;
+ /* The ffi argument for GError needs to be a triple pointer. */
+ state->args[error_index].arg_pointer.v_pointer = &state->error;
+ state->ffi_args[error_index] = &(state->args[error_index].arg_pointer);
+ }
+
return TRUE;
}
-static inline void
-_invoke_state_clear (PyGIInvokeState *state, PyGICallableCache *cache)
+static void
+_invoke_state_clear (PyGIInvokeState *state, PyGIFunctionCache *function_cache)
{
- g_slice_free1 (cache->n_args * sizeof(GIArgument *), state->args);
- g_slice_free1 (cache->n_args * sizeof(gpointer), state->args_data);
- g_slice_free1 (cache->n_from_py_args * sizeof(GIArgument), state->in_args);
- g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_args);
- g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_values);
-
+ _pygi_invoke_arg_state_free (state);
Py_XDECREF (state->py_in_args);
}
-static gboolean _caller_alloc (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gssize arg_count,
- gssize out_count)
+static gboolean
+_caller_alloc (PyGIArgCache *arg_cache, GIArgument *arg)
{
if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- state->out_args[out_count].v_pointer = NULL;
- state->args[arg_count] = &state->out_args[out_count];
+ arg->v_pointer = NULL;
if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
- state->args[arg_count]->v_pointer =
- _pygi_boxed_alloc (iface_cache->interface_info, NULL);
+ arg->v_pointer =
+ pygi_boxed_alloc (iface_cache->interface_info, NULL);
} else if (iface_cache->g_type == G_TYPE_VALUE) {
- state->args[arg_count]->v_pointer = g_slice_new0 (GValue);
+ arg->v_pointer = g_slice_new0 (GValue);
} else if (iface_cache->is_foreign) {
PyObject *foreign_struct =
pygi_struct_foreign_convert_from_g_argument (
iface_cache->interface_info,
+ GI_TRANSFER_NOTHING,
NULL);
pygi_struct_foreign_convert_to_g_argument (foreign_struct,
iface_cache->interface_info,
GI_TRANSFER_EVERYTHING,
- state->args[arg_count]);
+ arg);
} else {
gssize size = g_struct_info_get_size(
(GIStructInfo *)iface_cache->interface_info);
- state->args[arg_count]->v_pointer = g_malloc0 (size);
+ arg->v_pointer = g_malloc0 (size);
}
} else if (arg_cache->type_tag == GI_TYPE_TAG_ARRAY) {
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
- state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, seq_cache->item_size);
- state->args[arg_count] = &state->out_args[out_count];
+ arg->v_pointer = g_array_new (TRUE, TRUE, (guint)array_cache->item_size);
} else {
return FALSE;
}
- if (state->args[arg_count]->v_pointer == NULL)
+ if (arg->v_pointer == NULL)
return FALSE;
return TRUE;
}
-static inline gboolean
-_invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
+/* pygi_invoke_marshal_in_args:
+ *
+ * Fills out the state struct argument lists. arg_values will always hold
+ * actual values marshaled either to or from Python and C. arg_pointers will
+ * hold pointers (via v_pointer) to auxilary value storage. This will normally
+ * point to values stored in arg_values. In the case of caller allocated
+ * out args, arg_pointers[x].v_pointer will point to newly allocated memory.
+ * arg_pointers inserts a level of pointer indirection between arg_values
+ * and the argument list ffi receives when dealing with non-caller allocated
+ * out arguments.
+ *
+ * For example:
+ * [[
+ * void callee (int *i, int j) { *i = 50 - j; }
+ * void caller () {
+ * int i = 0;
+ * callee (&i, 8);
+ * }
+ *
+ * args[0] == &arg_pointers[0];
+ * arg_pointers[0].v_pointer == &arg_values[0];
+ * arg_values[0].v_int == 42;
+ *
+ * args[1] == &arg_values[1];
+ * arg_values[1].v_int == 8;
+ * ]]
+ *
+ */
+static gboolean
+_invoke_marshal_in_args (PyGIInvokeState *state, PyGIFunctionCache *function_cache)
{
- gssize i, in_count, out_count;
- in_count = 0;
- out_count = 0;
+ PyGICallableCache *cache = (PyGICallableCache *) function_cache;
+ gssize i;
if (state->n_py_in_args > cache->n_py_args) {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
PyErr_Format (PyExc_TypeError,
"%s() takes exactly %zd argument(s) (%zd given)",
- cache->name,
+ full_name,
cache->n_py_args,
state->n_py_in_args);
+ g_free (full_name);
return FALSE;
}
- for (i = 0; i < cache->n_args; i++) {
- GIArgument *c_arg;
- PyGIArgCache *arg_cache = cache->args_cache[i];
+ for (i = 0; (gsize)i < _pygi_callable_cache_args_len (cache); i++) {
+ GIArgument *c_arg = &state->args[i].arg_value;
+ PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i);
PyObject *py_arg = NULL;
switch (arg_cache->direction) {
case PYGI_DIRECTION_FROM_PYTHON:
- state->args[i] = &(state->in_args[in_count]);
- in_count++;
+ /* The ffi argument points directly at memory in arg_values. */
+ state->ffi_args[i] = c_arg;
if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CLOSURE) {
- state->args[i]->v_pointer = state->user_data;
+ state->ffi_args[i]->v_pointer = state->user_data;
continue;
} else if (arg_cache->meta_type != PYGI_META_ARG_TYPE_PARENT)
continue;
if (arg_cache->py_arg_index >= state->n_py_in_args) {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
PyErr_Format (PyExc_TypeError,
"%s() takes exactly %zd argument(s) (%zd given)",
- cache->name,
+ full_name,
cache->n_py_args,
state->n_py_in_args);
+ g_free (full_name);
/* clean up all of the args we have already marshalled,
* since invoke will not be called
*/
pygi_marshal_cleanup_args_from_py_parameter_fail (state,
cache,
- i - 1);
+ i);
return FALSE;
}
@@ -446,23 +447,18 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
break;
case PYGI_DIRECTION_BIDIRECTIONAL:
- /* this will be filled in if it is an child value */
- if (state->in_args[in_count].v_pointer != NULL)
- state->out_values[out_count] = state->in_args[in_count];
-
- state->in_args[in_count].v_pointer = &state->out_values[out_count];
- in_count++;
-
if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD) {
if (arg_cache->py_arg_index >= state->n_py_in_args) {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
PyErr_Format (PyExc_TypeError,
"%s() takes exactly %zd argument(s) (%zd given)",
- cache->name,
+ full_name,
cache->n_py_args,
state->n_py_in_args);
+ g_free (full_name);
pygi_marshal_cleanup_args_from_py_parameter_fail (state,
cache,
- i - 1);
+ i);
return FALSE;
}
@@ -470,28 +466,56 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
PyTuple_GET_ITEM (state->py_in_args,
arg_cache->py_arg_index);
}
+ /* Fall through */
+
case PYGI_DIRECTION_TO_PYTHON:
+ /* arg_pointers always stores a pointer to the data to be marshaled "to python"
+ * even in cases where arg_pointers is not being used as indirection between
+ * ffi and arg_values. This gives a guarantee that out argument marshaling
+ * (_invoke_marshal_out_args) can always rely on arg_pointers pointing to
+ * the correct chunk of memory to marshal.
+ */
+ state->args[i].arg_pointer.v_pointer = c_arg;
+
if (arg_cache->is_caller_allocates) {
- if (!_caller_alloc (state, arg_cache, i, out_count)) {
+ /* In the case of caller allocated out args, we don't use
+ * an extra level of indirection and state->args will point
+ * directly at the data to be marshaled. However, as noted
+ * above, arg_pointers will also point to this caller allocated
+ * chunk of memory used by out argument marshaling.
+ */
+ state->ffi_args[i] = c_arg;
+
+ if (!_caller_alloc (arg_cache, c_arg)) {
+ char *full_name = pygi_callable_cache_get_full_name (cache);
PyErr_Format (PyExc_TypeError,
"Could not caller allocate argument %zd of callable %s",
- i, cache->name);
+ i, full_name);
+ g_free (full_name);
pygi_marshal_cleanup_args_from_py_parameter_fail (state,
cache,
- i - 1);
+ i);
return FALSE;
}
} else {
- state->out_args[out_count].v_pointer = &state->out_values[out_count];
- state->args[i] = &state->out_values[out_count];
+ /* Non-caller allocated out args will use arg_pointers as an
+ * extra level of indirection */
+ state->ffi_args[i] = &state->args[i].arg_pointer;
}
- out_count++;
+
+ break;
+ default:
+ g_assert_not_reached();
break;
}
- c_arg = state->args[i];
- if (arg_cache->from_py_marshaller != NULL) {
+ if (py_arg == _PyGIDefaultArgPlaceholder) {
+ *c_arg = arg_cache->default_value;
+ } else if (arg_cache->from_py_marshaller != NULL &&
+ arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD) {
gboolean success;
+ gpointer cleanup_data = NULL;
+
if (!arg_cache->allow_none && py_arg == Py_None) {
PyErr_Format (PyExc_TypeError,
"Argument %zd does not allow None as a value",
@@ -499,18 +523,21 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
pygi_marshal_cleanup_args_from_py_parameter_fail (state,
cache,
- i - 1);
+ i);
return FALSE;
}
success = arg_cache->from_py_marshaller (state,
- cache,
- arg_cache,
- py_arg,
- c_arg);
+ cache,
+ arg_cache,
+ py_arg,
+ c_arg,
+ &cleanup_data);
+ state->args[i].arg_cleanup_data = cleanup_data;
+
if (!success) {
pygi_marshal_cleanup_args_from_py_parameter_fail (state,
cache,
- i - 1);
+ i);
return FALSE;
}
@@ -521,57 +548,44 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
return TRUE;
}
-static inline PyObject *
-_invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
+static PyObject *
+_invoke_marshal_out_args (PyGIInvokeState *state, PyGIFunctionCache *function_cache)
{
+ PyGICallableCache *cache = (PyGICallableCache *) function_cache;
PyObject *py_out = NULL;
PyObject *py_return = NULL;
- gssize total_out_args = cache->n_to_py_args;
- gboolean has_return = FALSE;
+ gssize n_out_args = cache->n_to_py_args - cache->n_to_py_child_args;
if (cache->return_cache) {
if (!cache->return_cache->is_skipped) {
- if (cache->function_type == PYGI_FUNCTION_TYPE_CONSTRUCTOR) {
- if (state->return_arg.v_pointer == NULL) {
- PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
- pygi_marshal_cleanup_args_return_fail (state,
- cache);
- return NULL;
- }
- }
-
+ gpointer cleanup_data = NULL;
py_return = cache->return_cache->to_py_marshaller ( state,
cache,
cache->return_cache,
- &state->return_arg);
+ &state->return_arg,
+ &cleanup_data);
+ state->to_py_return_arg_cleanup_data = cleanup_data;
if (py_return == NULL) {
pygi_marshal_cleanup_args_return_fail (state,
cache);
return NULL;
}
-
-
- if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) {
- total_out_args++;
- has_return = TRUE;
- }
} else {
if (cache->return_cache->transfer == GI_TRANSFER_EVERYTHING) {
- PyGIMarshalCleanupFunc to_py_cleanup =
+ PyGIMarshalToPyCleanupFunc to_py_cleanup =
cache->return_cache->to_py_cleanup;
if (to_py_cleanup != NULL)
to_py_cleanup ( state,
cache->return_cache,
+ NULL,
&state->return_arg,
FALSE);
}
}
}
- total_out_args -= cache->n_to_py_child_args;
-
- if (cache->n_to_py_args - cache->n_to_py_child_args == 0) {
+ if (n_out_args == 0) {
if (cache->return_cache->is_skipped && state->error == NULL) {
/* we skip the return value and have no (out) arguments to return,
* so py_return should be NULL. But we must not return NULL,
@@ -583,13 +597,16 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
}
py_out = py_return;
- } else if (total_out_args == 1) {
+ } else if (!cache->has_return && n_out_args == 1) {
/* if we get here there is one out arg an no return */
PyGIArgCache *arg_cache = (PyGIArgCache *)cache->to_py_args->data;
+ gpointer cleanup_data = NULL;
py_out = arg_cache->to_py_marshaller (state,
cache,
arg_cache,
- state->args[arg_cache->c_arg_index]);
+ state->args[arg_cache->c_arg_index].arg_pointer.v_pointer,
+ &cleanup_data);
+ state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data = cleanup_data;
if (py_out == NULL) {
pygi_marshal_cleanup_args_to_py_parameter_fail (state,
cache,
@@ -598,26 +615,39 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
}
} else {
+ /* return a tuple */
gssize py_arg_index = 0;
GSList *cache_item = cache->to_py_args;
- /* return a tuple */
- py_out = PyTuple_New (total_out_args);
- if (has_return) {
+ gssize tuple_len = cache->has_return + n_out_args;
+
+ py_out = pygi_resulttuple_new (cache->resulttuple_type, tuple_len);
+
+ if (py_out == NULL) {
+ pygi_marshal_cleanup_args_to_py_parameter_fail (state,
+ cache,
+ py_arg_index);
+ return NULL;
+ }
+
+ if (cache->has_return) {
PyTuple_SET_ITEM (py_out, py_arg_index, py_return);
py_arg_index++;
}
- for(; py_arg_index < total_out_args; py_arg_index++) {
+ for (; py_arg_index < tuple_len; py_arg_index++) {
PyGIArgCache *arg_cache = (PyGIArgCache *)cache_item->data;
+ gpointer cleanup_data = NULL;
PyObject *py_obj = arg_cache->to_py_marshaller (state,
cache,
arg_cache,
- state->args[arg_cache->c_arg_index]);
+ state->args[arg_cache->c_arg_index].arg_pointer.v_pointer,
+ &cleanup_data);
+ state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data = cleanup_data;
if (py_obj == NULL) {
- if (has_return)
+ if (cache->has_return)
py_arg_index--;
-
+
pygi_marshal_cleanup_args_to_py_parameter_fail (state,
cache,
py_arg_index);
@@ -633,44 +663,103 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
}
PyObject *
-pygi_callable_info_invoke (GIBaseInfo *info, PyObject *py_args,
- PyObject *kwargs, PyGICallableCache *cache,
- GCallback function_ptr, gpointer user_data)
+pygi_invoke_c_callable (PyGIFunctionCache *function_cache,
+ PyGIInvokeState *state,
+ PyObject *py_args,
+ PyObject *py_kwargs)
{
- PyGIInvokeState state = { 0, };
+ PyGICallableCache *cache = (PyGICallableCache *) function_cache;
+ GIFFIReturnValue ffi_return_value = {0};
PyObject *ret = NULL;
- if (!_invoke_state_init_from_callable_cache (&state, cache, py_args, kwargs))
- goto err;
+ if (!_invoke_state_init_from_cache (state, function_cache,
+ py_args, py_kwargs))
+ goto err;
- if (cache->function_type == PYGI_FUNCTION_TYPE_CCALLBACK)
- state.user_data = user_data;
+ if (!_invoke_marshal_in_args (state, function_cache))
+ goto err;
- if (!_invoke_marshal_in_args (&state, cache))
- goto err;
+ Py_BEGIN_ALLOW_THREADS;
- if (!_invoke_callable (&state, cache, info, function_ptr))
- goto err;
+ ffi_call (&function_cache->invoker.cif,
+ state->function_ptr,
+ (void *) &ffi_return_value,
+ (void **) state->ffi_args);
- pygi_marshal_cleanup_args_from_py_marshal_success (&state, cache);
+ Py_END_ALLOW_THREADS;
+
+ /* If the callable throws, the address of state->error will be bound into
+ * the state->args as the last value. When the callee sets an error using
+ * the state->args passed, it will have the side effect of setting
+ * state->error allowing for easy checking here.
+ */
+ if (state->error != NULL) {
+ if (pygi_error_check (&state->error)) {
+ /* even though we errored out, the call itself was successful,
+ so we assume the call processed all of the parameters */
+ pygi_marshal_cleanup_args_from_py_marshal_success (state, cache);
+ goto err;
+ }
+ }
+
+ if (cache->return_cache) {
+ gi_type_info_extract_ffi_return_value (cache->return_cache->type_info,
+ &ffi_return_value,
+ &state->return_arg);
+ }
+
+ ret = _invoke_marshal_out_args (state, function_cache);
+ pygi_marshal_cleanup_args_from_py_marshal_success (state, cache);
+
+ if (ret != NULL)
+ pygi_marshal_cleanup_args_to_py_marshal_success (state, cache);
- ret = _invoke_marshal_out_args (&state, cache);
- if (ret)
- pygi_marshal_cleanup_args_to_py_marshal_success (&state, cache);
err:
- _invoke_state_clear (&state, cache);
+ _invoke_state_clear (state, function_cache);
return ret;
}
PyObject *
+pygi_callable_info_invoke (GIBaseInfo *info, PyObject *py_args,
+ PyObject *kwargs, PyGICallableCache *cache,
+ gpointer user_data)
+{
+ return pygi_function_cache_invoke ((PyGIFunctionCache *) cache,
+ py_args, kwargs);
+}
+
+PyObject *
_wrap_g_callable_info_invoke (PyGIBaseInfo *self, PyObject *py_args,
PyObject *kwargs)
{
if (self->cache == NULL) {
- self->cache = _pygi_callable_cache_new (self->info, FALSE);
+ PyGIFunctionCache *function_cache;
+ GIInfoType type = g_base_info_get_type (self->info);
+
+ if (type == GI_INFO_TYPE_FUNCTION) {
+ GIFunctionInfoFlags flags;
+
+ flags = g_function_info_get_flags ( (GIFunctionInfo *)self->info);
+
+ if (flags & GI_FUNCTION_IS_CONSTRUCTOR) {
+ function_cache = pygi_constructor_cache_new (self->info);
+ } else if (flags & GI_FUNCTION_IS_METHOD) {
+ function_cache = pygi_method_cache_new (self->info);
+ } else {
+ function_cache = pygi_function_cache_new (self->info);
+ }
+ } else if (type == GI_INFO_TYPE_VFUNC) {
+ function_cache = pygi_vfunc_cache_new (self->info);
+ } else if (type == GI_INFO_TYPE_CALLBACK) {
+ g_error ("Cannot invoke callback types");
+ } else {
+ function_cache = pygi_method_cache_new (self->info);
+ }
+
+ self->cache = (PyGICallableCache *)function_cache;
if (self->cache == NULL)
return NULL;
}
- return pygi_callable_info_invoke (self->info, py_args, kwargs, self->cache, NULL, NULL);
+ return pygi_callable_info_invoke (self->info, py_args, kwargs, self->cache, NULL);
}
diff --git a/gi/pygi-invoke.h b/gi/pygi-invoke.h
index 051bc8d..aa51f3f 100644
--- a/gi/pygi-invoke.h
+++ b/gi/pygi-invoke.h
@@ -14,9 +14,7 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_INVOKE_H__
@@ -26,16 +24,24 @@
#include <girepository.h>
-#include "pygi-private.h"
+#include "pygi-info.h"
#include "pygi-invoke-state-struct.h"
+
G_BEGIN_DECLS
+PyObject *pygi_invoke_c_callable (PyGIFunctionCache *function_cache,
+ PyGIInvokeState *state,
+ PyObject *py_args, PyObject *py_kwargs);
PyObject *pygi_callable_info_invoke (GIBaseInfo *info, PyObject *py_args,
PyObject *kwargs, PyGICallableCache *cache,
- GCallback function_ptr, gpointer user_data);
+ gpointer user_data);
PyObject *_wrap_g_callable_info_invoke (PyGIBaseInfo *self, PyObject *py_args,
PyObject *kwargs);
+gboolean _pygi_invoke_arg_state_init (PyGIInvokeState *state);
+
+void _pygi_invoke_arg_state_free (PyGIInvokeState *state);
+
G_END_DECLS
#endif /* __PYGI_INVOKE_H__ */
diff --git a/gi/pygi-list.c b/gi/pygi-list.c
new file mode 100644
index 0000000..712c372
--- /dev/null
+++ b/gi/pygi-list.c
@@ -0,0 +1,500 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include "pygi-list.h"
+#include "pygi-argument.h"
+#include "pygi-util.h"
+
+typedef PyGISequenceCache PyGIArgGList;
+
+/*
+ * GList and GSList from Python
+ */
+static gboolean
+_pygi_marshal_from_py_glist (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyGIMarshalFromPyFunc from_py_marshaller;
+ int i;
+ Py_ssize_t length;
+ GList *list_ = NULL;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+
+ if (!PySequence_Check (py_arg)) {
+ PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ length = PySequence_Length (py_arg);
+ if (length < 0)
+ return FALSE;
+
+ from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
+ for (i = 0; i < length; i++) {
+ GIArgument item = {0};
+ gpointer item_cleanup_data = NULL;
+ PyObject *py_item = PySequence_GetItem (py_arg, i);
+ if (py_item == NULL)
+ goto err;
+
+ if (!from_py_marshaller ( state,
+ callable_cache,
+ sequence_cache->item_cache,
+ py_item,
+ &item,
+ &item_cleanup_data))
+ goto err;
+
+ Py_DECREF (py_item);
+ list_ = g_list_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_info));
+ continue;
+err:
+ /* FIXME: clean up list
+ if (sequence_cache->item_cache->from_py_cleanup != NULL) {
+ PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
+ }
+ */
+ Py_XDECREF (py_item);
+ g_list_free (list_);
+ _PyGI_ERROR_PREFIX ("Item %i: ", i);
+ return FALSE;
+ }
+
+ arg->v_pointer = g_list_reverse (list_);
+
+ if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+ /* Free everything in cleanup. */
+ *cleanup_data = arg->v_pointer;
+ } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+ /* Make a shallow copy so we can free the elements later in cleanup
+ * because it is possible invoke will free the list before our cleanup. */
+ *cleanup_data = g_list_copy (arg->v_pointer);
+ } else { /* GI_TRANSFER_EVERYTHING */
+ /* No cleanup, everything is given to the callee. */
+ *cleanup_data = NULL;
+ }
+ return TRUE;
+}
+
+
+static gboolean
+_pygi_marshal_from_py_gslist (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyGIMarshalFromPyFunc from_py_marshaller;
+ int i;
+ Py_ssize_t length;
+ GSList *list_ = NULL;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+
+ if (!PySequence_Check (py_arg)) {
+ PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ length = PySequence_Length (py_arg);
+ if (length < 0)
+ return FALSE;
+
+ from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
+ for (i = 0; i < length; i++) {
+ GIArgument item = {0};
+ gpointer item_cleanup_data = NULL;
+ PyObject *py_item = PySequence_GetItem (py_arg, i);
+ if (py_item == NULL)
+ goto err;
+
+ if (!from_py_marshaller ( state,
+ callable_cache,
+ sequence_cache->item_cache,
+ py_item,
+ &item,
+ &item_cleanup_data))
+ goto err;
+
+ Py_DECREF (py_item);
+ list_ = g_slist_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_info));
+ continue;
+err:
+ /* FIXME: Clean up list
+ if (sequence_cache->item_cache->from_py_cleanup != NULL) {
+ PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
+ }
+ */
+
+ Py_XDECREF (py_item);
+ g_slist_free (list_);
+ _PyGI_ERROR_PREFIX ("Item %i: ", i);
+ return FALSE;
+ }
+
+ arg->v_pointer = g_slist_reverse (list_);
+
+ if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+ /* Free everything in cleanup. */
+ *cleanup_data = arg->v_pointer;
+ } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+ /* Make a shallow copy so we can free the elements later in cleanup
+ * because it is possible invoke will free the list before our cleanup. */
+ *cleanup_data = g_slist_copy (arg->v_pointer);
+ } else { /* GI_TRANSFER_EVERYTHING */
+ /* No cleanup, everything is given to the callee. */
+ *cleanup_data = NULL;
+ }
+
+ return TRUE;
+}
+
+static void
+_pygi_marshal_cleanup_from_py_glist (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (was_processed) {
+ GSList *list_;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+
+ list_ = (GSList *)data;
+
+ /* clean up items first */
+ if (sequence_cache->item_cache->from_py_cleanup != NULL) {
+ PyGIMarshalCleanupFunc cleanup_func =
+ sequence_cache->item_cache->from_py_cleanup;
+ GSList *node = list_;
+ gsize i = 0;
+ while (node != NULL) {
+ PyObject *py_item = PySequence_GetItem (py_arg, i);
+ cleanup_func (state,
+ sequence_cache->item_cache,
+ py_item,
+ node->data,
+ TRUE);
+ Py_XDECREF (py_item);
+ node = node->next;
+ i++;
+ }
+ }
+
+ if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) {
+ g_list_free ( (GList *)list_);
+ } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) {
+ g_slist_free (list_);
+ } else {
+ g_assert_not_reached();
+ }
+ }
+}
+
+
+/*
+ * GList and GSList to Python
+ */
+static PyObject *
+_pygi_marshal_to_py_glist (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ GList *list_;
+ guint length;
+ guint i;
+ GPtrArray *item_cleanups;
+
+ PyGIMarshalToPyFunc item_to_py_marshaller;
+ PyGIArgCache *item_arg_cache;
+ PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+
+ PyObject *py_obj = NULL;
+
+ list_ = arg->v_pointer;
+ length = g_list_length (list_);
+
+ py_obj = PyList_New (length);
+ if (py_obj == NULL)
+ return NULL;
+
+ item_cleanups = g_ptr_array_sized_new (length);
+ *cleanup_data = item_cleanups;
+
+ item_arg_cache = seq_cache->item_cache;
+ item_to_py_marshaller = item_arg_cache->to_py_marshaller;
+
+ for (i = 0; list_ != NULL; list_ = g_list_next (list_), i++) {
+ GIArgument item_arg;
+ PyObject *py_item;
+ gpointer item_cleanup_data = NULL;
+
+ item_arg.v_pointer = list_->data;
+ _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_info);
+ py_item = item_to_py_marshaller (state,
+ callable_cache,
+ item_arg_cache,
+ &item_arg,
+ &item_cleanup_data);
+
+ g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
+
+ if (py_item == NULL) {
+ Py_CLEAR (py_obj);
+ _PyGI_ERROR_PREFIX ("Item %u: ", i);
+ g_ptr_array_unref (item_cleanups);
+ return NULL;
+ }
+
+ PyList_SET_ITEM (py_obj, i, py_item);
+ }
+
+ return py_obj;
+}
+
+static PyObject *
+_pygi_marshal_to_py_gslist (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ GSList *list_;
+ guint length;
+ guint i;
+ GPtrArray *item_cleanups;
+
+ PyGIMarshalToPyFunc item_to_py_marshaller;
+ PyGIArgCache *item_arg_cache;
+ PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+
+ PyObject *py_obj = NULL;
+
+ list_ = arg->v_pointer;
+ length = g_slist_length (list_);
+
+ py_obj = PyList_New (length);
+ if (py_obj == NULL)
+ return NULL;
+
+ item_cleanups = g_ptr_array_sized_new (length);
+ *cleanup_data = item_cleanups;
+
+ item_arg_cache = seq_cache->item_cache;
+ item_to_py_marshaller = item_arg_cache->to_py_marshaller;
+
+ for (i = 0; list_ != NULL; list_ = g_slist_next (list_), i++) {
+ GIArgument item_arg;
+ PyObject *py_item;
+ gpointer item_cleanup_data = NULL;
+
+ item_arg.v_pointer = list_->data;
+ _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_info);
+ py_item = item_to_py_marshaller (state,
+ callable_cache,
+ item_arg_cache,
+ &item_arg,
+ &item_cleanup_data);
+
+ g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
+ if (py_item == NULL) {
+ Py_CLEAR (py_obj);
+ _PyGI_ERROR_PREFIX ("Item %u: ", i);
+ g_ptr_array_unref (item_cleanups);
+ return NULL;
+ }
+
+ PyList_SET_ITEM (py_obj, i, py_item);
+ }
+
+ return py_obj;
+}
+
+static void
+_pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer cleanup_data,
+ gpointer data,
+ gboolean was_processed)
+{
+ GPtrArray *item_cleanups = (GPtrArray *) cleanup_data;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ GSList *list_ = (GSList *)data;
+
+ if (sequence_cache->item_cache->to_py_cleanup != NULL) {
+ PyGIMarshalToPyCleanupFunc cleanup_func =
+ sequence_cache->item_cache->to_py_cleanup;
+ GSList *node = list_;
+ guint i = 0;
+
+ while (node != NULL) {
+ cleanup_func (state,
+ sequence_cache->item_cache,
+ g_ptr_array_index(item_cleanups, i),
+ node->data,
+ was_processed);
+ node = node->next;
+ i++;
+ }
+ }
+
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
+ arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+
+ if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) {
+ g_list_free ( (GList *)list_);
+ } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) {
+ g_slist_free (list_);
+ } else {
+ g_assert_not_reached();
+ }
+ }
+
+ g_ptr_array_unref (item_cleanups);
+}
+
+static void
+_arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
+}
+
+static void
+_arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
+}
+
+static void
+_arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
+}
+
+static void
+_arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
+}
+
+
+/*
+ * GList/GSList Interface
+ */
+
+static gboolean
+pygi_arg_glist_setup_from_info (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
+{
+ GITypeTag type_tag = g_type_info_get_tag (type_info);
+
+ if (!pygi_arg_sequence_setup ((PyGISequenceCache *)arg_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache))
+ return FALSE;
+
+ switch (type_tag) {
+ case GI_TYPE_TAG_GLIST:
+ {
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ _arg_cache_from_py_glist_setup (arg_cache, transfer);
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ _arg_cache_to_py_glist_setup (arg_cache, transfer);
+ break;
+ }
+ case GI_TYPE_TAG_GSLIST:
+ {
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ _arg_cache_from_py_gslist_setup (arg_cache, transfer);
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ _arg_cache_to_py_gslist_setup (arg_cache, transfer);
+
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_glist_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
+{
+ gboolean res = FALSE;
+
+ PyGIArgCache *arg_cache = (PyGIArgCache *) g_slice_new0 (PyGIArgGList);
+ if (arg_cache == NULL)
+ return NULL;
+
+ res = pygi_arg_glist_setup_from_info (arg_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache);
+ if (res) {
+ return arg_cache;
+ } else {
+ pygi_arg_cache_free (arg_cache);
+ return NULL;
+ }
+}
diff --git a/gi/pygi-list.h b/gi/pygi-list.h
new file mode 100644
index 0000000..f22e024
--- /dev/null
+++ b/gi/pygi-list.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_LIST_H__
+#define __PYGI_LIST_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+PyGIArgCache *pygi_arg_glist_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache);
+
+/* Internally dispatches GList and GSList */
+#define pygi_arg_gslist_new_from_info pygi_arg_glist_new_from_info
+
+G_END_DECLS
+
+#endif /*__PYGI_LIST_H__*/
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index d7d1b63..98fbe47 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -14,31 +14,33 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-
- #include "pygi-marshal-cleanup.h"
- #include <glib.h>
+
+#include "pygi-marshal-cleanup.h"
+#include "pygi-foreign.h"
+#include <glib.h>
+
static inline void
_cleanup_caller_allocates (PyGIInvokeState *state,
PyGIArgCache *cache,
+ PyObject *py_obj,
gpointer data,
gboolean was_processed)
{
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)cache;
- if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
+ /* check GValue first because GValue is also a boxed sub-type */
+ if (g_type_is_a (iface_cache->g_type, G_TYPE_VALUE)) {
+ if (was_processed)
+ g_value_unset (data);
+ g_slice_free (GValue, data);
+ } else if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
gsize size;
if (was_processed)
return; /* will be cleaned up at deallocation */
size = g_struct_info_get_size (iface_cache->interface_info);
g_slice_free1 (size, data);
- } else if (iface_cache->g_type == G_TYPE_VALUE) {
- if (was_processed)
- g_value_unset (data);
- g_slice_free (GValue, data);
} else if (iface_cache->is_foreign) {
if (was_processed)
return; /* will be cleaned up at deallocation */
@@ -90,24 +92,34 @@ void
pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState *state,
PyGICallableCache *cache)
{
- gssize i;
+ guint i;
+ PyObject *error_type, *error_value, *error_traceback;
+ gboolean have_error = !!PyErr_Occurred ();
- /* For in success, call cleanup for all GI_DIRECTION_IN values only. */
- for (i = 0; i < cache->n_args; i++) {
- PyGIArgCache *arg_cache = cache->args_cache[i];
- PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
+ if (have_error)
+ PyErr_Fetch (&error_type, &error_value, &error_traceback);
- if (cleanup_func &&
- arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON &&
- state->args[i]->v_pointer != NULL)
- cleanup_func (state, arg_cache, state->args[i]->v_pointer, TRUE);
-
- if (cleanup_func &&
- arg_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL &&
- state->args_data[i] != NULL) {
- cleanup_func (state, arg_cache, state->args_data[i], TRUE);
+ for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
+ PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
+ PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
+ gpointer cleanup_data = state->args[i].arg_cleanup_data;
+
+ /* Only cleanup using args_cleanup_data when available.
+ * It is the responsibility of the various "from_py" marshalers to return
+ * cleanup_data which is then passed into their respective cleanup function.
+ * PyGIInvokeState.args_cleanup_data stores this data (via _invoke_marshal_in_args)
+ * for the duration of the invoke up until this point.
+ */
+ if (cleanup_func && cleanup_data != NULL && arg_cache->py_arg_index >= 0 &&
+ arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
+ PyObject *py_arg = PyTuple_GET_ITEM (state->py_in_args, arg_cache->py_arg_index);
+ cleanup_func (state, arg_cache, py_arg, cleanup_data, TRUE);
+ state->args[i].arg_cleanup_data = NULL;
}
}
+
+ if (have_error)
+ PyErr_Restore (error_type, error_value, error_traceback);
}
void
@@ -115,12 +127,20 @@ pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState *state,
PyGICallableCache *cache)
{
GSList *cache_item;
+ guint i = 0;
+ PyObject *error_type, *error_value, *error_traceback;
+ gboolean have_error = !!PyErr_Occurred ();
+
+ if (have_error)
+ PyErr_Fetch (&error_type, &error_value, &error_traceback);
+
/* clean up the return if available */
if (cache->return_cache != NULL) {
- PyGIMarshalCleanupFunc cleanup_func = cache->return_cache->to_py_cleanup;
+ PyGIMarshalToPyCleanupFunc cleanup_func = cache->return_cache->to_py_cleanup;
if (cleanup_func && state->return_arg.v_pointer != NULL)
cleanup_func (state,
cache->return_cache,
+ state->to_py_return_arg_cleanup_data,
state->return_arg.v_pointer,
TRUE);
}
@@ -129,23 +149,29 @@ pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState *state,
cache_item = cache->to_py_args;
while (cache_item) {
PyGIArgCache *arg_cache = (PyGIArgCache *) cache_item->data;
- PyGIMarshalCleanupFunc cleanup_func = arg_cache->to_py_cleanup;
- gpointer data = state->args[arg_cache->c_arg_index]->v_pointer;
+ PyGIMarshalToPyCleanupFunc cleanup_func = arg_cache->to_py_cleanup;
+ gpointer data = state->args[arg_cache->c_arg_index].arg_value.v_pointer;
if (cleanup_func != NULL && data != NULL)
cleanup_func (state,
arg_cache,
+ state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data,
data,
TRUE);
else if (arg_cache->is_caller_allocates && data != NULL) {
_cleanup_caller_allocates (state,
arg_cache,
+ state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data,
data,
TRUE);
}
+ i++;
cache_item = cache_item->next;
}
+
+ if (have_error)
+ PyErr_Restore (error_type, error_value, error_traceback);
}
void
@@ -153,30 +179,46 @@ pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState *state,
PyGICallableCache *cache,
gssize failed_arg_index)
{
- gssize i;
+ guint i;
+ PyObject *error_type, *error_value, *error_traceback;
+ gboolean have_error = !!PyErr_Occurred ();
+
+ if (have_error)
+ PyErr_Fetch (&error_type, &error_value, &error_traceback);
state->failed = TRUE;
- for (i = 0; i < cache->n_args && i <= failed_arg_index; i++) {
- PyGIArgCache *arg_cache = cache->args_cache[i];
+ for (i = 0; i < _pygi_callable_cache_args_len (cache) && i <= (guint)failed_arg_index; i++) {
+ PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
- gpointer data = state->args[i]->v_pointer;
+ gpointer cleanup_data = state->args[i].arg_cleanup_data;
+ PyObject *py_arg = NULL;
- if (cleanup_func &&
- arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON &&
- data != NULL) {
+ if (arg_cache->py_arg_index < 0) {
+ continue;
+ }
+ py_arg = PyTuple_GET_ITEM (state->py_in_args, arg_cache->py_arg_index);
+
+ if (cleanup_func && cleanup_data != NULL &&
+ arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON) {
cleanup_func (state,
arg_cache,
- data,
- i < failed_arg_index);
+ py_arg,
+ cleanup_data,
+ i < (guint)failed_arg_index);
- } else if (arg_cache->is_caller_allocates && data != NULL) {
+ } else if (arg_cache->is_caller_allocates && cleanup_data != NULL) {
_cleanup_caller_allocates (state,
arg_cache,
- data,
+ py_arg,
+ cleanup_data,
FALSE);
}
+ state->args[i].arg_cleanup_data = NULL;
}
+
+ if (have_error)
+ PyErr_Restore (error_type, error_value, error_traceback);
}
void
@@ -193,406 +235,3 @@ pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state,
{
state->failed = TRUE;
}
-
-void
-_pygi_marshal_cleanup_from_py_utf8 (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- /* We strdup strings so always free if we have processed this
- parameter for input */
- if (was_processed)
- g_free (data);
-}
-
-void
-_pygi_marshal_cleanup_to_py_utf8 (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- /* Python copies the string so we need to free it
- if the interface is transfering ownership,
- whether or not it has been processed yet */
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- g_free (data);
-}
-
-void
-_pygi_marshal_cleanup_from_py_interface_object (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- /* If we processed the parameter but fail before invoking the method,
- we need to remove the ref we added */
- if (was_processed && state->failed && data != NULL &&
- arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- g_object_unref (G_OBJECT(data));
-}
-
-void
-_pygi_marshal_cleanup_to_py_interface_object (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- /* If we error out and the object is not marshalled into a PyGObject
- we must take care of removing the ref */
- if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- g_object_unref (G_OBJECT(data));
-}
-
-
-void
-_pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
- if (was_processed && callback_cache->scope == GI_SCOPE_TYPE_CALL) {
- _pygi_invoke_closure_free (state->args_data[arg_cache->c_arg_index]);
- state->args_data[arg_cache->c_arg_index] = NULL;
- }
-}
-
-void
-_pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- if (was_processed) {
- PyObject *py_arg = PyTuple_GET_ITEM (state->py_in_args,
- arg_cache->py_arg_index);
- GType py_object_type =
- pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
-
- if (py_object_type != G_TYPE_VALUE) {
- g_value_unset ((GValue *) data);
- g_slice_free (GValue, data);
- }
- }
-}
-
-void
-_pygi_marshal_cleanup_from_py_interface_struct_foreign (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- if (state->failed && was_processed)
- pygi_struct_foreign_release (
- ( (PyGIInterfaceCache *)arg_cache)->interface_info,
- data);
-}
-
-void
-_pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- pygi_struct_foreign_release (
- ( (PyGIInterfaceCache *)arg_cache)->interface_info,
- data);
-}
-
-static GArray*
-_wrap_c_array (PyGIInvokeState *state,
- PyGISequenceCache *sequence_cache,
- gpointer data)
-{
- GArray *array_;
- gsize len = 0;
-
- if (sequence_cache->fixed_size >= 0) {
- len = sequence_cache->fixed_size;
- } else if (sequence_cache->is_zero_terminated) {
- len = g_strv_length ((gchar **)data);
- } else if (sequence_cache->len_arg_index >= 0) {
- GIArgument *len_arg = state->args[sequence_cache->len_arg_index];
- len = len_arg->v_long;
- }
-
- array_ = g_array_new (FALSE,
- FALSE,
- sequence_cache->item_size);
-
- if (array_ == NULL)
- return NULL;
-
- g_free (array_->data);
- array_->data = data;
- array_->len = len;
-
- return array_;
-}
-
-void
-_pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- if (was_processed) {
- GArray *array_ = NULL;
- GPtrArray *ptr_array_ = NULL;
- PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
-
- /* If this isn't a garray create one to help process variable sized
- array elements */
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- array_ = _wrap_c_array (state, sequence_cache, data);
-
- if (array_ == NULL)
- return;
-
- } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
- ptr_array_ = (GPtrArray *) data;
- } else {
- array_ = (GArray *) data;
- }
-
- /* clean up items first */
- if (sequence_cache->item_cache->from_py_cleanup != NULL) {
- gsize i;
- guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
- PyGIMarshalCleanupFunc cleanup_func =
- sequence_cache->item_cache->from_py_cleanup;
-
- for (i = 0; i < len; i++) {
- gpointer item;
-
- /* case 1: GPtrArray */
- if (ptr_array_ != NULL)
- item = g_ptr_array_index (ptr_array_, i);
- /* case 2: C array or GArray with object pointers */
- else if (sequence_cache->item_cache->is_pointer)
- item = g_array_index (array_, gpointer, i);
- /* case 3: C array or GArray with simple types or structs */
- else {
- item = array_->data + i * sequence_cache->item_size;
- /* special-case hack: GValue array items do not get slice
- * allocated in _pygi_marshal_from_py_array(), so we must
- * not try to deallocate it as a slice and thus
- * short-circuit cleanup_func. */
- if (cleanup_func == _pygi_marshal_cleanup_from_py_interface_struct_gvalue) {
- g_value_unset ((GValue*) item);
- continue;
- }
- }
-
- cleanup_func (state, sequence_cache->item_cache, item, TRUE);
- }
- }
-
- /* Only free the array when we didn't transfer ownership */
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
- } else if (state->failed ||
- arg_cache->transfer == GI_TRANSFER_NOTHING) {
- if (array_ != NULL)
- g_array_free (array_, TRUE);
- else
- g_ptr_array_free (ptr_array_, TRUE);
- }
- }
-}
-
-void
-_pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
- arg_cache->transfer == GI_TRANSFER_CONTAINER) {
- GArray *array_ = NULL;
- GPtrArray *ptr_array_ = NULL;
- PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
-
- /* If this isn't a garray create one to help process variable sized
- array elements */
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- array_ = _wrap_c_array (state, sequence_cache, data);
-
- if (array_ == NULL)
- return;
-
- } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
- ptr_array_ = (GPtrArray *) data;
- } else {
- array_ = (GArray *) data;
- }
-
- if (sequence_cache->item_cache->to_py_cleanup != NULL) {
- gsize i;
- guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
-
- PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
- for (i = 0; i < len; i++) {
- cleanup_func (state,
- sequence_cache->item_cache,
- (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
- was_processed);
- }
- }
-
- if (array_ != NULL)
- g_array_free (array_, TRUE);
- else
- g_ptr_array_free (ptr_array_, TRUE);
- }
-}
-
-void
-_pygi_marshal_cleanup_from_py_glist (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- if (was_processed) {
- GSList *list_;
- PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
-
- list_ = (GSList *)data;
-
- /* clean up items first */
- if (sequence_cache->item_cache->from_py_cleanup != NULL) {
- PyGIMarshalCleanupFunc cleanup_func =
- sequence_cache->item_cache->from_py_cleanup;
- GSList *node = list_;
- while (node != NULL) {
- cleanup_func (state,
- sequence_cache->item_cache,
- node->data,
- TRUE);
- node = node->next;
- }
- }
-
- if (state->failed ||
- arg_cache->transfer == GI_TRANSFER_NOTHING ||
- arg_cache->transfer == GI_TRANSFER_CONTAINER) {
- switch (arg_cache->type_tag) {
- case GI_TYPE_TAG_GLIST:
- g_list_free ( (GList *)list_);
- break;
- case GI_TYPE_TAG_GSLIST:
- g_slist_free (list_);
- break;
- default:
- g_assert_not_reached();
- }
- }
- }
-}
-
-void
-_pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
-
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
- arg_cache->transfer == GI_TRANSFER_CONTAINER) {
- GSList *list_ = (GSList *)data;
-
- if (sequence_cache->item_cache->to_py_cleanup != NULL) {
- PyGIMarshalCleanupFunc cleanup_func =
- sequence_cache->item_cache->to_py_cleanup;
- GSList *node = list_;
-
- while (node != NULL) {
- cleanup_func (state,
- sequence_cache->item_cache,
- node->data,
- was_processed);
- node = node->next;
- }
- }
-
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
- switch (arg_cache->type_tag) {
- case GI_TYPE_TAG_GLIST:
- g_list_free ( (GList *)list_);
- break;
- case GI_TYPE_TAG_GSLIST:
- g_slist_free (list_);
- break;
- default:
- g_assert_not_reached();
- }
- }
- }
-}
-
-void
-_pygi_marshal_cleanup_from_py_ghash (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- if (data == NULL)
- return;
-
- if (was_processed) {
- GHashTable *hash_;
- PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
-
- hash_ = (GHashTable *)data;
-
- /* clean up keys and values first */
- if (hash_cache->key_cache->from_py_cleanup != NULL ||
- hash_cache->value_cache->from_py_cleanup != NULL) {
- GHashTableIter hiter;
- gpointer key;
- gpointer value;
-
- PyGIMarshalCleanupFunc key_cleanup_func =
- hash_cache->key_cache->from_py_cleanup;
- PyGIMarshalCleanupFunc value_cleanup_func =
- hash_cache->value_cache->from_py_cleanup;
-
- g_hash_table_iter_init (&hiter, hash_);
- while (g_hash_table_iter_next (&hiter, &key, &value)) {
- if (key != NULL && key_cleanup_func != NULL)
- key_cleanup_func (state,
- hash_cache->key_cache,
- key,
- TRUE);
- if (value != NULL && value_cleanup_func != NULL)
- value_cleanup_func (state,
- hash_cache->value_cache,
- value,
- TRUE);
- }
- }
-
- if (state->failed ||
- arg_cache->transfer == GI_TRANSFER_NOTHING ||
- arg_cache->transfer == GI_TRANSFER_CONTAINER)
- g_hash_table_destroy (hash_);
-
- }
-}
-
-void
-_pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed)
-{
- if (data == NULL)
- return;
-
- /* assume hashtable has boxed key and value */
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- g_hash_table_destroy ( (GHashTable *)data);
-}
diff --git a/gi/pygi-marshal-cleanup.h b/gi/pygi-marshal-cleanup.h
index 234e49c..18ba007 100644
--- a/gi/pygi-marshal-cleanup.h
+++ b/gi/pygi-marshal-cleanup.h
@@ -14,15 +14,15 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_MARSHAL_CLEANUP_H__
#define __PYGI_MARSHAL_CLEANUP_H__
-#include "pygi-private.h"
+#include "pygi-struct.h"
+#include "pygi-invoke-state-struct.h"
+#include "pygi-cache.h"
G_BEGIN_DECLS
@@ -39,63 +39,6 @@ void pygi_marshal_cleanup_args_return_fail (PyGIInvokeState *state,
void pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state,
PyGICallableCache *cache,
gssize failed_to_py_arg_index);
-
-void _pygi_marshal_cleanup_from_py_utf8 (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_to_py_utf8 (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_from_py_interface_struct_foreign (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_from_py_interface_object (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_to_py_interface_object (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_from_py_glist (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_from_py_ghash (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- gpointer data,
- gboolean was_processed);
G_END_DECLS
#endif /* __PYGI_MARSHAL_CLEANUP_H__ */
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
deleted file mode 100644
index 57b4126..0000000
--- a/gi/pygi-marshal-from-py.c
+++ /dev/null
@@ -1,1870 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- *
- * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>, Red Hat, Inc.
- *
- * pygi-marshal-from-py.c: Functions to convert PyObjects to C types.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#include "pygi-private.h"
-
-#include <string.h>
-#include <time.h>
-#include <pygobject.h>
-#include <pyglib-python-compat.h>
-
-#include "pygi-cache.h"
-#include "pygi-marshal-cleanup.h"
-#include "pygi-marshal-from-py.h"
-
-#ifdef _WIN32
-#ifdef _MSC_VER
-#include <math.h>
-
-#ifndef NAN
-static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
-#define NAN (*(const float *) __nan)
-#endif
-
-#ifndef INFINITY
-#define INFINITY HUGE_VAL
-#endif
-
-#endif
-#endif
-
-static gboolean
-gi_argument_from_py_ssize_t (GIArgument *arg_out,
- Py_ssize_t size_in,
- GITypeTag type_tag)
-{
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- case GI_TYPE_TAG_BOOLEAN:
- goto unhandled_type;
-
- case GI_TYPE_TAG_INT8:
- if (size_in >= G_MININT8 && size_in <= G_MAXINT8) {
- arg_out->v_int8 = size_in;
- return TRUE;
- } else {
- goto overflow;
- }
-
- case GI_TYPE_TAG_UINT8:
- if (size_in >= 0 && size_in <= G_MAXUINT8) {
- arg_out->v_uint8 = size_in;
- return TRUE;
- } else {
- goto overflow;
- }
-
- case GI_TYPE_TAG_INT16:
- if (size_in >= G_MININT16 && size_in <= G_MAXINT16) {
- arg_out->v_int16 = size_in;
- return TRUE;
- } else {
- goto overflow;
- }
-
- case GI_TYPE_TAG_UINT16:
- if (size_in >= 0 && size_in <= G_MAXUINT16) {
- arg_out->v_uint16 = size_in;
- return TRUE;
- } else {
- goto overflow;
- }
-
- /* Ranges assume two's complement */
- case GI_TYPE_TAG_INT32:
- if (size_in >= G_MININT32 && size_in <= G_MAXINT32) {
- arg_out->v_int32 = size_in;
- return TRUE;
- } else {
- goto overflow;
- }
-
- case GI_TYPE_TAG_UINT32:
- if (size_in >= 0 && size_in <= G_MAXUINT32) {
- arg_out->v_uint32 = size_in;
- return TRUE;
- } else {
- goto overflow;
- }
-
- case GI_TYPE_TAG_INT64:
- arg_out->v_int64 = size_in;
- return TRUE;
-
- case GI_TYPE_TAG_UINT64:
- if (size_in >= 0) {
- arg_out->v_uint64 = size_in;
- return TRUE;
- } else {
- goto overflow;
- }
-
- case GI_TYPE_TAG_FLOAT:
- case GI_TYPE_TAG_DOUBLE:
- case GI_TYPE_TAG_GTYPE:
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- case GI_TYPE_TAG_ARRAY:
- case GI_TYPE_TAG_INTERFACE:
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- case GI_TYPE_TAG_GHASH:
- case GI_TYPE_TAG_ERROR:
- case GI_TYPE_TAG_UNICHAR:
- default:
- goto unhandled_type;
- }
-
- overflow:
- PyErr_Format (PyExc_OverflowError,
- "Unable to marshal C Py_ssize_t %zd to %s",
- size_in,
- g_type_tag_to_string (type_tag));
- return FALSE;
-
- unhandled_type:
- PyErr_Format (PyExc_TypeError,
- "Unable to marshal C Py_ssize_t %zd to %s",
- size_in,
- g_type_tag_to_string (type_tag));
- return FALSE;
-}
-
-static gboolean
-gi_argument_from_c_long (GIArgument *arg_out,
- long c_long_in,
- GITypeTag type_tag)
-{
- switch (type_tag) {
- case GI_TYPE_TAG_INT8:
- arg_out->v_int8 = c_long_in;
- return TRUE;
- case GI_TYPE_TAG_UINT8:
- arg_out->v_uint8 = c_long_in;
- return TRUE;
- case GI_TYPE_TAG_INT16:
- arg_out->v_int16 = c_long_in;
- return TRUE;
- case GI_TYPE_TAG_UINT16:
- arg_out->v_uint16 = c_long_in;
- return TRUE;
- case GI_TYPE_TAG_INT32:
- arg_out->v_int32 = c_long_in;
- return TRUE;
- case GI_TYPE_TAG_UINT32:
- arg_out->v_uint32 = c_long_in;
- return TRUE;
- case GI_TYPE_TAG_INT64:
- arg_out->v_int64 = c_long_in;
- return TRUE;
- case GI_TYPE_TAG_UINT64:
- arg_out->v_uint64 = c_long_in;
- return TRUE;
- default:
- PyErr_Format (PyExc_TypeError,
- "Unable to marshal C long %ld to %s",
- c_long_in,
- g_type_tag_to_string (type_tag));
- return FALSE;
- }
-}
-
-/*
- * _is_union_member - check to see if the py_arg is actually a member of the
- * expected C union
- */
-static gboolean
-_is_union_member (GIInterfaceInfo *interface_info, PyObject *py_arg) {
- gint i;
- gint n_fields;
- GIUnionInfo *union_info;
- GIInfoType info_type;
- gboolean is_member = FALSE;
-
- info_type = g_base_info_get_type (interface_info);
-
- if (info_type != GI_INFO_TYPE_UNION)
- return FALSE;
-
- union_info = (GIUnionInfo *) interface_info;
- n_fields = g_union_info_get_n_fields (union_info);
-
- for (i = 0; i < n_fields; i++) {
- GIFieldInfo *field_info;
- GITypeInfo *field_type_info;
-
- field_info = g_union_info_get_field (union_info, i);
- field_type_info = g_field_info_get_type (field_info);
-
- /* we can only check if the members are interfaces */
- if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) {
- GIInterfaceInfo *field_iface_info;
- PyObject *py_type;
-
- field_iface_info = g_type_info_get_interface (field_type_info);
- py_type = _pygi_type_import_by_gi_info ((GIBaseInfo *) field_iface_info);
-
- if (py_type != NULL && PyObject_IsInstance (py_arg, py_type)) {
- is_member = TRUE;
- }
-
- Py_XDECREF (py_type);
- g_base_info_unref ( ( GIBaseInfo *) field_iface_info);
- }
-
- g_base_info_unref ( ( GIBaseInfo *) field_type_info);
- g_base_info_unref ( ( GIBaseInfo *) field_info);
-
- if (is_member)
- break;
- }
-
- return is_member;
-}
-
-gboolean
-_pygi_marshal_from_py_void (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- g_warn_if_fail (arg_cache->transfer == GI_TRANSFER_NOTHING);
-
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- } else if (PYGLIB_CPointer_Check(py_arg)) {
- arg->v_pointer = PYGLIB_CPointer_GetPointer (py_arg, NULL);
- } else {
- /* NOTE: This will change to only allow integers and the deprecation
- * warning will become a runtime exception. Using the following:
- * arg->v_pointer = PyLong_AsVoidPtr (py_arg);
- * See: https://bugzilla.gnome.org/show_bug.cgi?id=688081
- */
-
- if (!PYGLIB_PyLong_Check(py_arg) && !PyLong_Check(py_arg)) {
- if (PyErr_WarnEx(PyGIDeprecationWarning,
- "Pointer arguments will be restricted to integers, capsules, and None. "
- "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599",
- 1))
- return FALSE;
- }
- arg->v_pointer = py_arg;
- }
-
- return TRUE;
-}
-
-static gboolean
-check_valid_double (double x, double min, double max)
-{
- char buf[100];
-
- if ((x < min || x > max) && x != INFINITY && x != -INFINITY && x != NAN) {
- if (PyErr_Occurred())
- PyErr_Clear ();
-
- /* we need this as PyErr_Format() does not support float types */
- snprintf (buf, sizeof (buf), "%g not in range %g to %g", x, min, max);
- PyErr_SetString (PyExc_OverflowError, buf);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-_pygi_py_arg_to_double (PyObject *py_arg, double *double_)
-{
- PyObject *py_float;
-
- if (!PyNumber_Check (py_arg)) {
- PyErr_Format (PyExc_TypeError, "Must be number, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- py_float = PyNumber_Float (py_arg);
- if (!py_float)
- return FALSE;
-
- *double_ = PyFloat_AsDouble (py_float);
- Py_DECREF (py_float);
-
-
- return TRUE;
-}
-
-static gboolean
-_pygi_marshal_from_py_float (PyObject *py_arg,
- GIArgument *arg)
-{
- double double_;
-
- if (!_pygi_py_arg_to_double (py_arg, &double_))
- return FALSE;
-
- if (PyErr_Occurred () || !check_valid_double (double_, -G_MAXFLOAT, G_MAXFLOAT))
- return FALSE;
-
- arg->v_float = double_;
- return TRUE;
-}
-
-static gboolean
-_pygi_marshal_from_py_double (PyObject *py_arg,
- GIArgument *arg)
-{
- double double_;
-
- if (!_pygi_py_arg_to_double (py_arg, &double_))
- return FALSE;
-
- if (PyErr_Occurred () || !check_valid_double (double_, -G_MAXDOUBLE, G_MAXDOUBLE))
- return FALSE;
-
- arg->v_double = double_;
- return TRUE;
-}
-
-static gboolean
-_pygi_marshal_from_py_unichar (PyObject *py_arg,
- GIArgument *arg)
-{
- Py_ssize_t size;
- gchar *string_;
-
- if (py_arg == Py_None) {
- arg->v_uint32 = 0;
- return FALSE;
- }
-
- if (PyUnicode_Check (py_arg)) {
- PyObject *py_bytes;
-
- size = PyUnicode_GET_SIZE (py_arg);
- py_bytes = PyUnicode_AsUTF8String (py_arg);
- if (!py_bytes)
- return FALSE;
-
- string_ = g_strdup(PYGLIB_PyBytes_AsString (py_bytes));
- Py_DECREF (py_bytes);
-
-#if PY_VERSION_HEX < 0x03000000
- } else if (PyString_Check (py_arg)) {
- PyObject *pyuni = PyUnicode_FromEncodedObject (py_arg, "UTF-8", "strict");
- if (!pyuni)
- return FALSE;
-
- size = PyUnicode_GET_SIZE (pyuni);
- string_ = g_strdup (PyString_AsString(py_arg));
- Py_DECREF (pyuni);
-#endif
- } else {
- PyErr_Format (PyExc_TypeError, "Must be string, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- if (size != 1) {
- PyErr_Format (PyExc_TypeError, "Must be a one character string, not %lld characters",
- (long long) size);
- g_free (string_);
- return FALSE;
- }
-
- arg->v_uint32 = g_utf8_get_char (string_);
- g_free (string_);
-
- return TRUE;
-}
-
-static gboolean
-_pygi_marshal_from_py_gtype (PyObject *py_arg,
- GIArgument *arg)
-{
- long type_ = pyg_type_from_object (py_arg);
-
- if (type_ == 0) {
- PyErr_Format (PyExc_TypeError, "Must be gobject.GType, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- arg->v_long = type_;
- return TRUE;
-}
-
-static gboolean
-_pygi_marshal_from_py_utf8 (PyObject *py_arg,
- GIArgument *arg)
-{
- gchar *string_;
-
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- return TRUE;
- }
-
- if (PyUnicode_Check (py_arg)) {
- PyObject *pystr_obj = PyUnicode_AsUTF8String (py_arg);
- if (!pystr_obj)
- return FALSE;
-
- string_ = g_strdup (PYGLIB_PyBytes_AsString (pystr_obj));
- Py_DECREF (pystr_obj);
- }
-#if PY_VERSION_HEX < 0x03000000
- else if (PyString_Check (py_arg)) {
- string_ = g_strdup (PyString_AsString (py_arg));
- }
-#endif
- else {
- PyErr_Format (PyExc_TypeError, "Must be string, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- arg->v_string = string_;
- return TRUE;
-}
-
-static gboolean
-_pygi_marshal_from_py_filename (PyObject *py_arg,
- GIArgument *arg)
-{
- gchar *string_;
- GError *error = NULL;
-
- if (PyUnicode_Check (py_arg)) {
- PyObject *pystr_obj = PyUnicode_AsUTF8String (py_arg);
- if (!pystr_obj)
- return FALSE;
-
- string_ = g_strdup (PYGLIB_PyBytes_AsString (pystr_obj));
- Py_DECREF (pystr_obj);
- }
-#if PY_VERSION_HEX < 0x03000000
- else if (PyString_Check (py_arg)) {
- string_ = g_strdup (PyString_AsString (py_arg));
- }
-#endif
- else {
- PyErr_Format (PyExc_TypeError, "Must be string, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- 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);
- g_error_free (error);
- /* TODO: Convert the error to an exception. */
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-_pygi_marshal_from_py_long (PyObject *object, /* in */
- GIArgument *arg, /* out */
- GITypeTag type_tag,
- GITransfer transfer)
-{
- PyObject *number;
-
- if (!PyNumber_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be number, not %s",
- object->ob_type->tp_name);
- return FALSE;
- }
-
-#if PY_MAJOR_VERSION < 3
- {
- PyObject *tmp = PyNumber_Int (object);
- if (tmp) {
- number = PyNumber_Long (tmp);
- Py_DECREF (tmp);
- } else {
- number = PyNumber_Long (object);
- }
- }
-#else
- number = PyNumber_Long (object);
-#endif
-
- if (number == NULL) {
- PyErr_SetString (PyExc_TypeError, "expected int argument");
- return FALSE;
- }
-
- switch (type_tag) {
- case GI_TYPE_TAG_INT8:
- {
- long long_value = PyLong_AsLong (number);
- if (PyErr_Occurred()) {
- break;
- } else if (long_value < G_MININT8 || long_value > G_MAXINT8) {
- PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
- long_value, (long)G_MININT8, (long)G_MAXINT8);
- } else {
- arg->v_int8 = long_value;
- }
- break;
- }
-
- case GI_TYPE_TAG_UINT8:
- {
- long long_value = PyLong_AsLong (number);
- if (PyErr_Occurred()) {
- break;
- } else if (long_value < 0 || long_value > G_MAXUINT8) {
- PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
- long_value, (long)0, (long)G_MAXUINT8);
- } else {
- arg->v_uint8 = long_value;
- }
- break;
- }
-
- case GI_TYPE_TAG_INT16:
- {
- long long_value = PyLong_AsLong (number);
- if (PyErr_Occurred()) {
- break;
- } else if (long_value < G_MININT16 || long_value > G_MAXINT16) {
- PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
- long_value, (long)G_MININT16, (long)G_MAXINT16);
- } else {
- arg->v_int16 = long_value;
- }
- break;
- }
-
- case GI_TYPE_TAG_UINT16:
- {
- long long_value = PyLong_AsLong (number);
- if (PyErr_Occurred()) {
- break;
- } else if (long_value < 0 || long_value > G_MAXUINT16) {
- PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
- long_value, (long)0, (long)G_MAXUINT16);
- } else {
- arg->v_uint16 = long_value;
- }
- break;
- }
-
- case GI_TYPE_TAG_INT32:
- {
- long long_value = PyLong_AsLong (number);
- if (PyErr_Occurred()) {
- break;
- } else if (long_value < G_MININT32 || long_value > G_MAXINT32) {
- PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
- long_value, (long)G_MININT32, (long)G_MAXINT32);
- } else {
- arg->v_int32 = long_value;
- }
- break;
- }
-
- case GI_TYPE_TAG_UINT32:
- {
- PY_LONG_LONG long_value = PyLong_AsLongLong (number);
- if (PyErr_Occurred()) {
- break;
- } else if (long_value < 0 || long_value > G_MAXUINT32) {
- PyErr_Format (PyExc_OverflowError, "%lld not in range %ld to %lu",
- long_value, (long)0, (unsigned long)G_MAXUINT32);
- } else {
- arg->v_uint32 = long_value;
- }
- break;
- }
-
- case GI_TYPE_TAG_INT64:
- {
- /* Rely on Python overflow error and convert to ValueError for 64 bit values */
- arg->v_int64 = PyLong_AsLongLong (number);
- break;
- }
-
- case GI_TYPE_TAG_UINT64:
- {
- /* Rely on Python overflow error and convert to ValueError for 64 bit values */
- arg->v_uint64 = PyLong_AsUnsignedLongLong (number);
- break;
- }
-
- default:
- g_assert_not_reached ();
- }
-
- Py_DECREF (number);
-
- if (PyErr_Occurred())
- return FALSE;
- return TRUE;
-}
-
-gboolean
-_pygi_marshal_from_py_basic_type (PyObject *object, /* in */
- GIArgument *arg, /* out */
- GITypeTag type_tag,
- GITransfer transfer)
-{
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
- if (object == Py_None) {
- arg->v_pointer = NULL;
- } else if (!PYGLIB_PyLong_Check(object) && !PyLong_Check(object)) {
- PyErr_SetString(PyExc_TypeError,
- "Pointer assignment is restricted to integer values. "
- "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599");
- } else {
- arg->v_pointer = PyLong_AsVoidPtr (object);
- }
- break;
- case GI_TYPE_TAG_INT8:
- case GI_TYPE_TAG_UINT8:
- if (PYGLIB_PyBytes_Check (object)) {
- if (PYGLIB_PyBytes_Size (object) != 1) {
- PyErr_Format (PyExc_TypeError, "Must be a single character");
- return FALSE;
- }
- if (type_tag == GI_TYPE_TAG_INT8) {
- arg->v_int8 = (gint8)(PYGLIB_PyBytes_AsString (object)[0]);
- } else {
- arg->v_uint8 = (guint8)(PYGLIB_PyBytes_AsString (object)[0]);
- }
- } else {
- return _pygi_marshal_from_py_long (object, arg, type_tag, transfer);
- }
- break;
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_INT64:
- case GI_TYPE_TAG_UINT64:
- return _pygi_marshal_from_py_long (object, arg, type_tag, transfer);
-
- case GI_TYPE_TAG_BOOLEAN:
- arg->v_boolean = PyObject_IsTrue (object);
- break;
-
- case GI_TYPE_TAG_FLOAT:
- return _pygi_marshal_from_py_float (object, arg);
-
- case GI_TYPE_TAG_DOUBLE:
- return _pygi_marshal_from_py_double (object, arg);
-
- case GI_TYPE_TAG_GTYPE:
- return _pygi_marshal_from_py_gtype (object, arg);
-
- case GI_TYPE_TAG_UNICHAR:
- return _pygi_marshal_from_py_unichar (object, arg);
-
- case GI_TYPE_TAG_UTF8:
- return _pygi_marshal_from_py_utf8 (object, arg);
-
- case GI_TYPE_TAG_FILENAME:
- return _pygi_marshal_from_py_filename (object, arg);
-
- default:
- return FALSE;
- }
-
- if (PyErr_Occurred())
- return FALSE;
-
- return TRUE;
-}
-
-gboolean
-_pygi_marshal_from_py_basic_type_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- return _pygi_marshal_from_py_basic_type (py_arg,
- arg,
- arg_cache->type_tag,
- arg_cache->transfer);
-}
-
-gboolean
-_pygi_marshal_from_py_array (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyGIMarshalFromPyFunc from_py_marshaller;
- int i = 0;
- Py_ssize_t length;
- gssize item_size;
- gboolean is_ptr_array;
- GArray *array_ = NULL;
- PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
-
-
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- return TRUE;
- }
-
- if (!PySequence_Check (py_arg)) {
- PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- length = PySequence_Length (py_arg);
- if (length < 0)
- return FALSE;
-
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
-
- return FALSE;
- }
-
- item_size = sequence_cache->item_size;
- is_ptr_array = (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
- if (is_ptr_array) {
- array_ = (GArray *)g_ptr_array_new ();
- } else {
- array_ = g_array_sized_new (sequence_cache->is_zero_terminated,
- FALSE,
- item_size,
- length);
- }
-
- if (array_ == NULL) {
- PyErr_NoMemory ();
- return FALSE;
- }
-
- if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8 &&
- PYGLIB_PyBytes_Check (py_arg)) {
- memcpy(array_->data, PYGLIB_PyBytes_AsString (py_arg), length);
- array_->len = length;
- if (sequence_cache->is_zero_terminated) {
- /* If array_ has been created with zero_termination, space for the
- * terminator is properly allocated, so we're not off-by-one here. */
- array_->data[length] = '\0';
- }
- goto array_success;
- }
-
- from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
- for (i = 0; i < length; i++) {
- GIArgument item;
- PyObject *py_item = PySequence_GetItem (py_arg, i);
- if (py_item == NULL)
- goto err;
-
- if (!from_py_marshaller ( state,
- callable_cache,
- sequence_cache->item_cache,
- py_item,
- &item))
- goto err;
-
- /* FIXME: it is much more efficent to have seperate marshaller
- * for ptr arrays than doing the evaluation
- * and casting each loop iteration
- */
- if (is_ptr_array) {
- g_ptr_array_add((GPtrArray *)array_, item.v_pointer);
- } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
- PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *) sequence_cache->item_cache;
- GIBaseInfo *base_info = (GIBaseInfo *) item_iface_cache->interface_info;
- GIInfoType info_type = g_base_info_get_type (base_info);
-
- switch (info_type) {
- case GI_INFO_TYPE_UNION:
- case GI_INFO_TYPE_STRUCT:
- {
- PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache;
- PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup;
- gboolean is_boxed = g_type_is_a (item_iface_cache->g_type, G_TYPE_BOXED);
- gboolean is_gvalue = item_iface_cache->g_type == G_TYPE_VALUE;
- gboolean is_gvariant = item_iface_cache->g_type == G_TYPE_VARIANT;
-
- if (is_gvariant) {
- /* Item size will always be that of a pointer,
- * since GVariants are opaque hence always passed by ref */
- g_assert (item_size == sizeof (item.v_pointer));
- g_array_insert_val (array_, i, item.v_pointer);
- } else if (is_gvalue) {
- GValue* dest = (GValue*) (array_->data + (i * item_size));
- memset (dest, 0, item_size);
- if (item.v_pointer != NULL) {
- g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
- g_value_copy ((GValue*) item.v_pointer, dest);
- }
- /* we free the original copy already, the new one is a plain struct
- * in an array. _pygi_marshal_cleanup_from_py_array() does not free it again */
- if (from_py_cleanup)
- from_py_cleanup (state, item_arg_cache, item.v_pointer, TRUE);
- } else if (!is_boxed) {
- /* HACK: Gdk.Atom is merely an integer wrapped in a pointer,
- * so we must not dereference it; just copy the pointer
- * value, and don't attempt to free it. TODO: find out
- * if there are other data types with similar behaviour
- * and generalize. */
- if (g_strcmp0 (item_iface_cache->type_name, "Gdk.Atom") == 0) {
- g_assert (item_size == sizeof (item.v_pointer));
- memcpy (array_->data + (i * item_size), &item.v_pointer, item_size);
- } else {
- memcpy (array_->data + (i * item_size), item.v_pointer, item_size);
-
- if (from_py_cleanup)
- from_py_cleanup (state, item_arg_cache, item.v_pointer, TRUE);
- }
- } else if (is_boxed && !item_iface_cache->arg_cache.is_pointer) {
- /* The array elements are not expected to be pointers, but the
- * elements obtained are boxed pointers themselves, so insert
- * the pointed to data.
- */
- g_array_insert_vals (array_, i, item.v_pointer, 1);
- } else {
- g_array_insert_val (array_, i, item);
- }
- break;
- }
- default:
- g_array_insert_val (array_, i, item);
- }
- } else {
- g_array_insert_val (array_, i, item);
- }
- continue;
-err:
- if (sequence_cache->item_cache->from_py_cleanup != NULL) {
- gsize j;
- PyGIMarshalCleanupFunc cleanup_func =
- sequence_cache->item_cache->from_py_cleanup;
-
- for(j = 0; j < i; j++) {
- cleanup_func (state,
- sequence_cache->item_cache,
- g_array_index (array_, gpointer, j),
- TRUE);
- }
- }
-
- if (is_ptr_array)
- g_ptr_array_free ( ( GPtrArray *)array_, TRUE);
- else
- g_array_free (array_, TRUE);
- _PyGI_ERROR_PREFIX ("Item %i: ", i);
- return FALSE;
- }
-
-array_success:
- if (sequence_cache->len_arg_index >= 0) {
- /* we have an child arg to handle */
- PyGIArgCache *child_cache =
- callable_cache->args_cache[sequence_cache->len_arg_index];
-
- if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) {
- gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer;
- /* if we are not setup yet just set the in arg */
- if (len_arg == NULL) {
- if (!gi_argument_from_py_ssize_t (&state->in_args[child_cache->c_arg_index],
- length,
- child_cache->type_tag)) {
- goto err;
- }
- } else {
- *len_arg = length;
- }
- } else {
- if (!gi_argument_from_py_ssize_t (&state->in_args[child_cache->c_arg_index],
- length,
- child_cache->type_tag)) {
- goto err;
- }
- }
- }
-
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- arg->v_pointer = array_->data;
- g_array_free (array_, FALSE);
- /* remember the originally allocated array in args_data, as args and
- * in_args get changed for (inout) arguments */
- if (arg_cache->transfer == GI_TRANSFER_NOTHING)
- state->args_data[arg_cache->c_arg_index] = arg->v_pointer;
- } else {
- arg->v_pointer = array_;
- }
-
- return TRUE;
-}
-
-gboolean
-_pygi_marshal_from_py_glist (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyGIMarshalFromPyFunc from_py_marshaller;
- int i;
- Py_ssize_t length;
- GList *list_ = NULL;
- PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
-
-
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- return TRUE;
- }
-
- if (!PySequence_Check (py_arg)) {
- PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- length = PySequence_Length (py_arg);
- if (length < 0)
- return FALSE;
-
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
-
- return FALSE;
- }
-
- from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
- for (i = 0; i < length; i++) {
- GIArgument item;
- PyObject *py_item = PySequence_GetItem (py_arg, i);
- if (py_item == NULL)
- goto err;
-
- if (!from_py_marshaller ( state,
- callable_cache,
- sequence_cache->item_cache,
- py_item,
- &item))
- goto err;
-
- list_ = g_list_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_tag));
- continue;
-err:
- /* FIXME: clean up list
- if (sequence_cache->item_cache->from_py_cleanup != NULL) {
- PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
- }
- */
- g_list_free (list_);
- _PyGI_ERROR_PREFIX ("Item %i: ", i);
- return FALSE;
- }
-
- arg->v_pointer = g_list_reverse (list_);
- return TRUE;
-}
-
-gboolean
-_pygi_marshal_from_py_gslist (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyGIMarshalFromPyFunc from_py_marshaller;
- int i;
- Py_ssize_t length;
- GSList *list_ = NULL;
- PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
-
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- return TRUE;
- }
-
- if (!PySequence_Check (py_arg)) {
- PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- length = PySequence_Length (py_arg);
- if (length < 0)
- return FALSE;
-
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
-
- return FALSE;
- }
-
- from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
- for (i = 0; i < length; i++) {
- GIArgument item;
- PyObject *py_item = PySequence_GetItem (py_arg, i);
- if (py_item == NULL)
- goto err;
-
- if (!from_py_marshaller ( state,
- callable_cache,
- sequence_cache->item_cache,
- py_item,
- &item))
- goto err;
-
- list_ = g_slist_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_tag));
- continue;
-err:
- /* FIXME: Clean up list
- if (sequence_cache->item_cache->from_py_cleanup != NULL) {
- PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
- }
- */
-
- g_slist_free (list_);
- _PyGI_ERROR_PREFIX ("Item %i: ", i);
- return FALSE;
- }
-
- arg->v_pointer = g_slist_reverse (list_);
- return TRUE;
-}
-
-gboolean
-_pygi_marshal_from_py_ghash (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyGIMarshalFromPyFunc key_from_py_marshaller;
- PyGIMarshalFromPyFunc value_from_py_marshaller;
-
- int i;
- Py_ssize_t length;
- PyObject *py_keys, *py_values;
-
- GHashFunc hash_func;
- GEqualFunc equal_func;
-
- GHashTable *hash_ = NULL;
- PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
-
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- return TRUE;
- }
-
- py_keys = PyMapping_Keys (py_arg);
- if (py_keys == NULL) {
- PyErr_Format (PyExc_TypeError, "Must be mapping, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- length = PyMapping_Length (py_arg);
- if (length < 0) {
- Py_DECREF (py_keys);
- return FALSE;
- }
-
- py_values = PyMapping_Values (py_arg);
- if (py_values == NULL) {
- Py_DECREF (py_keys);
- return FALSE;
- }
-
- key_from_py_marshaller = hash_cache->key_cache->from_py_marshaller;
- value_from_py_marshaller = hash_cache->value_cache->from_py_marshaller;
-
- switch (hash_cache->key_cache->type_tag) {
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- hash_func = g_str_hash;
- equal_func = g_str_equal;
- break;
- default:
- hash_func = NULL;
- equal_func = NULL;
- }
-
- hash_ = g_hash_table_new (hash_func, equal_func);
- if (hash_ == NULL) {
- PyErr_NoMemory ();
- Py_DECREF (py_keys);
- Py_DECREF (py_values);
- return FALSE;
- }
-
- for (i = 0; i < length; i++) {
- GIArgument key, value;
- PyObject *py_key = PyList_GET_ITEM (py_keys, i);
- PyObject *py_value = PyList_GET_ITEM (py_values, i);
- if (py_key == NULL || py_value == NULL)
- goto err;
-
- if (!key_from_py_marshaller ( state,
- callable_cache,
- hash_cache->key_cache,
- py_key,
- &key))
- goto err;
-
- if (!value_from_py_marshaller ( state,
- callable_cache,
- hash_cache->value_cache,
- py_value,
- &value))
- goto err;
-
- g_hash_table_insert (hash_,
- _pygi_arg_to_hash_pointer (&key, hash_cache->key_cache->type_tag),
- _pygi_arg_to_hash_pointer (&value, hash_cache->value_cache->type_tag));
- continue;
-err:
- /* FIXME: cleanup hash keys and values */
- Py_XDECREF (py_key);
- Py_XDECREF (py_value);
- Py_DECREF (py_keys);
- Py_DECREF (py_values);
- g_hash_table_unref (hash_);
- _PyGI_ERROR_PREFIX ("Item %i: ", i);
- return FALSE;
- }
-
- arg->v_pointer = hash_;
- return TRUE;
-}
-
-gboolean
-_pygi_marshal_from_py_gerror (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for GErrors is not implemented");
- return FALSE;
-}
-
-/* _pygi_destroy_notify_dummy:
- *
- * Dummy method used in the occasion when a method has a GDestroyNotify
- * argument without user data.
- */
-static void
-_pygi_destroy_notify_dummy (gpointer data) {
-}
-
-static PyGICClosure *global_destroy_notify;
-
-static void
-_pygi_destroy_notify_callback_closure (ffi_cif *cif,
- void *result,
- void **args,
- void *data)
-{
- PyGICClosure *info = * (void**) (args[0]);
-
- g_assert (info);
-
- _pygi_invoke_closure_free (info);
-}
-
-/* _pygi_destroy_notify_create:
- *
- * Method used in the occasion when a method has a GDestroyNotify
- * argument with user data.
- */
-static PyGICClosure*
-_pygi_destroy_notify_create (void)
-{
- if (!global_destroy_notify) {
-
- PyGICClosure *destroy_notify = g_slice_new0 (PyGICClosure);
- GIBaseInfo* glib_destroy_notify;
-
- g_assert (destroy_notify);
-
- glib_destroy_notify = g_irepository_find_by_name (NULL, "GLib", "DestroyNotify");
- g_assert (glib_destroy_notify != NULL);
- g_assert (g_base_info_get_type (glib_destroy_notify) == GI_INFO_TYPE_CALLBACK);
-
- destroy_notify->closure = g_callable_info_prepare_closure ( (GICallableInfo*) glib_destroy_notify,
- &destroy_notify->cif,
- _pygi_destroy_notify_callback_closure,
- NULL);
-
- global_destroy_notify = destroy_notify;
- }
-
- return global_destroy_notify;
-}
-
-gboolean
-_pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- GICallableInfo *callable_info;
- PyGICClosure *closure;
- PyGIArgCache *user_data_cache = NULL;
- PyGIArgCache *destroy_cache = NULL;
- PyGICallbackCache *callback_cache;
- PyObject *py_user_data = NULL;
-
- callback_cache = (PyGICallbackCache *)arg_cache;
-
- if (callback_cache->user_data_index > 0) {
- user_data_cache = callable_cache->args_cache[callback_cache->user_data_index];
- if (user_data_cache->py_arg_index < state->n_py_in_args) {
- /* py_user_data is a borrowed reference. */
- py_user_data = PyTuple_GetItem (state->py_in_args, user_data_cache->py_arg_index);
- if (!py_user_data)
- return FALSE;
- }
- }
-
- if (py_arg == Py_None && !(py_user_data == Py_None || py_user_data == NULL)) {
- PyErr_Format (PyExc_TypeError,
- "When passing None for a callback userdata must also be None");
-
- return FALSE;
- }
-
- if (py_arg == Py_None) {
- return TRUE;
- }
-
- if (!PyCallable_Check (py_arg)) {
- PyErr_Format (PyExc_TypeError,
- "Callback needs to be a function or method not %s",
- py_arg->ob_type->tp_name);
-
- return FALSE;
- }
-
- callable_info = (GICallableInfo *)callback_cache->interface_info;
-
- closure = _pygi_make_native_closure (callable_info, callback_cache->scope, py_arg, py_user_data);
- arg->v_pointer = closure->closure;
-
- /* The PyGICClosure instance is used as user data passed into the C function.
- * The return trip to python will marshal this back and pull the python user data out.
- */
- if (user_data_cache != NULL) {
- state->in_args[user_data_cache->c_arg_index].v_pointer = closure;
- }
-
- /* Setup a GDestroyNotify callback if this method supports it along with
- * a user data field. The user data field is a requirement in order
- * free resources and ref counts associated with this arguments closure.
- * In case a user data field is not available, show a warning giving
- * explicit information and setup a dummy notification to avoid a crash
- * later on in _pygi_destroy_notify_callback_closure.
- */
- if (callback_cache->destroy_notify_index > 0) {
- destroy_cache = callable_cache->args_cache[callback_cache->destroy_notify_index];
- }
-
- if (destroy_cache) {
- if (user_data_cache != NULL) {
- PyGICClosure *destroy_notify = _pygi_destroy_notify_create ();
- state->in_args[destroy_cache->c_arg_index].v_pointer = destroy_notify->closure;
- } else {
- gchar *msg = g_strdup_printf("Callables passed to %s will leak references because "
- "the method does not support a user_data argument. "
- "See: https://bugzilla.gnome.org/show_bug.cgi?id=685598",
- callable_cache->name);
- if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 2)) {
- g_free(msg);
- _pygi_invoke_closure_free(closure);
- return FALSE;
- }
- g_free(msg);
- state->in_args[destroy_cache->c_arg_index].v_pointer = _pygi_destroy_notify_dummy;
- }
- }
-
- /* Store the PyGIClosure as extra args data so _pygi_marshal_cleanup_from_py_interface_callback
- * can clean it up later for GI_SCOPE_TYPE_CALL based closures.
- */
- state->args_data[arg_cache->c_arg_index] = closure;
-
- return TRUE;
-}
-
-gboolean
-_pygi_marshal_from_py_interface_enum (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyObject *py_long;
- long c_long;
- gint is_instance;
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- GIBaseInfo *interface = NULL;
-
- is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
-
- py_long = PYGLIB_PyNumber_Long (py_arg);
- if (py_long == NULL) {
- PyErr_Clear();
- goto err;
- }
-
- c_long = PYGLIB_PyLong_AsLong (py_long);
- Py_DECREF (py_long);
-
- /* Write c_long into arg */
- interface = g_type_info_get_interface (arg_cache->type_info);
- assert(g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
- if (!gi_argument_from_c_long(arg,
- c_long,
- g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
- g_assert_not_reached();
- g_base_info_unref (interface);
- return FALSE;
- }
-
- /* If this is not an instance of the Enum type that we want
- * we need to check if the value is equivilant to one of the
- * Enum's memebers */
- if (!is_instance) {
- int i;
- gboolean is_found = FALSE;
-
- for (i = 0; i < g_enum_info_get_n_values (iface_cache->interface_info); i++) {
- GIValueInfo *value_info =
- g_enum_info_get_value (iface_cache->interface_info, i);
- glong enum_value = g_value_info_get_value (value_info);
- g_base_info_unref ( (GIBaseInfo *)value_info);
- if (c_long == enum_value) {
- is_found = TRUE;
- break;
- }
- }
-
- if (!is_found)
- goto err;
- }
-
- g_base_info_unref (interface);
- return TRUE;
-
-err:
- if (interface)
- g_base_info_unref (interface);
- PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
- iface_cache->type_name, py_arg->ob_type->tp_name);
- return FALSE;
-}
-
-gboolean
-_pygi_marshal_from_py_interface_flags (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyObject *py_long;
- long c_long;
- gint is_instance;
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- GIBaseInfo *interface;
-
- is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
-
- py_long = PYGLIB_PyNumber_Long (py_arg);
- if (py_long == NULL) {
- PyErr_Clear ();
- goto err;
- }
-
- c_long = PYGLIB_PyLong_AsLong (py_long);
- Py_DECREF (py_long);
-
- /* only 0 or argument of type Flag is allowed */
- if (!is_instance && c_long != 0)
- goto err;
-
- /* Write c_long into arg */
- interface = g_type_info_get_interface (arg_cache->type_info);
- g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
- if (!gi_argument_from_c_long(arg, c_long,
- g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
- g_base_info_unref (interface);
- return FALSE;
- }
-
- g_base_info_unref (interface);
- return TRUE;
-
-err:
- PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
- iface_cache->type_name, py_arg->ob_type->tp_name);
- return FALSE;
-
-}
-
-gboolean
-_pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
-
- return _pygi_marshal_from_py_interface_struct (py_arg,
- arg,
- arg_cache->arg_name,
- iface_cache->interface_info,
- arg_cache->type_info,
- iface_cache->g_type,
- iface_cache->py_type,
- arg_cache->transfer,
- TRUE, /*copy_reference*/
- iface_cache->is_foreign);
-}
-
-gboolean
-_pygi_marshal_from_py_interface_boxed (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return FALSE;
-}
-
-gboolean
-_pygi_marshal_from_py_interface_object (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- return TRUE;
- }
-
- if (!PyObject_IsInstance (py_arg, ( (PyGIInterfaceCache *)arg_cache)->py_type)) {
- PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
-
- PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
- arg_cache->arg_name ? arg_cache->arg_name : "self",
- ( (PyGIInterfaceCache *)arg_cache)->type_name,
- module ? PYGLIB_PyUnicode_AsString(module) : "",
- module ? "." : "",
- py_arg->ob_type->tp_name);
- if (module)
- Py_DECREF (module);
- return FALSE;
- }
-
- return _pygi_marshal_from_py_gobject (py_arg, arg, arg_cache->transfer);
-}
-
-gboolean
-_pygi_marshal_from_py_interface_union (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- PyErr_Format(PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return FALSE;
-}
-
-gboolean _pygi_marshal_from_py_interface_instance (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg)
-{
- GIInfoType info_type;
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
-
- info_type = g_base_info_get_type (iface_cache->interface_info);
- switch (info_type) {
- case GI_INFO_TYPE_UNION:
- case GI_INFO_TYPE_STRUCT:
- {
- GType type = iface_cache->g_type;
-
- if (!PyObject_IsInstance (py_arg, iface_cache->py_type)) {
- /* wait, we might be a member of a union so manually check */
- if (!_is_union_member (iface_cache->interface_info, py_arg)) {
- if (!PyErr_Occurred()) {
- PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
- PyErr_Format (PyExc_TypeError,
- "argument %s: Expected a %s, but got %s%s%s",
- arg_cache->arg_name ? arg_cache->arg_name : "self",
- iface_cache->type_name,
- module ? PYGLIB_PyUnicode_AsString(module) : "",
- module ? "." : "",
- py_arg->ob_type->tp_name);
- if (module)
- Py_DECREF (module);
- }
- return FALSE;
- }
- }
-
- if (g_type_is_a (type, G_TYPE_BOXED)) {
- arg->v_pointer = pyg_boxed_get (py_arg, void);
- } else if (g_type_is_a (type, G_TYPE_POINTER) ||
- g_type_is_a (type, G_TYPE_VARIANT) ||
- type == G_TYPE_NONE) {
- arg->v_pointer = pyg_pointer_get (py_arg, void);
- } else {
- PyErr_Format (PyExc_TypeError, "unable to convert an instance of '%s'", g_type_name (type));
- return FALSE;
- }
-
- break;
- }
- case GI_INFO_TYPE_OBJECT:
- case GI_INFO_TYPE_INTERFACE:
- arg->v_pointer = pygobject_get (py_arg);
- if (arg->v_pointer != NULL) {
- GType obj_type = G_OBJECT_TYPE (( GObject *)arg->v_pointer);
- GType expected_type = iface_cache->g_type;
-
- if (!g_type_is_a (obj_type, expected_type)) {
- PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
- PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
- arg_cache->arg_name ? arg_cache->arg_name : "self",
- iface_cache->type_name,
- module ? PYGLIB_PyUnicode_AsString(module) : "",
- module ? "." : "",
- py_arg->ob_type->tp_name);
- if (module)
- Py_DECREF (module);
- return FALSE;
- }
- }
- break;
- default:
- /* Other types don't have methods. */
- g_assert_not_reached ();
- }
-
- return TRUE;
-}
-
-/* _pygi_marshal_from_py_gobject:
- * py_arg: (in):
- * arg: (out):
- */
-gboolean
-_pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
- GIArgument *arg, /*out*/
- GITransfer transfer) {
- GObject *gobj;
-
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- return TRUE;
- }
-
- if (!pygobject_check (py_arg, &PyGObject_Type)) {
- PyObject *repr = PyObject_Repr (py_arg);
- PyErr_Format(PyExc_TypeError, "expected GObject but got %s",
- PYGLIB_PyUnicode_AsString (repr));
- Py_DECREF (repr);
- return FALSE;
- }
-
- gobj = pygobject_get (py_arg);
- if (transfer == GI_TRANSFER_EVERYTHING) {
- /* For transfer everything, add a new ref that the callee will take ownership of.
- * Pythons existing ref to the GObject will be managed with the PyGObject wrapper.
- */
- g_object_ref (gobj);
- }
-
- arg->v_pointer = gobj;
- return TRUE;
-}
-
-/* _pygi_marshal_from_py_gobject_out_arg:
- * py_arg: (in):
- * arg: (out):
- *
- * A specialization for marshaling Python GObjects used for out/return values
- * from a Python implemented vfuncs, signals, or an assignment to a GObject property.
- */
-gboolean
-_pygi_marshal_from_py_gobject_out_arg (PyObject *py_arg, /*in*/
- GIArgument *arg, /*out*/
- GITransfer transfer) {
- GObject *gobj;
- if (!_pygi_marshal_from_py_gobject (py_arg, arg, transfer)) {
- return FALSE;
- }
-
- /* HACK: At this point the basic marshaling of the GObject was successful
- * but we add some special case hacks for vfunc returns due to buggy APIs:
- * https://bugzilla.gnome.org/show_bug.cgi?id=693393
- */
- gobj = arg->v_pointer;
- if (py_arg->ob_refcnt == 1 && gobj->ref_count == 1) {
- /* If both object ref counts are only 1 at this point (the reference held
- * in a return tuple), we assume the GObject will be free'd before reaching
- * its target and become invalid. So instead of getting invalid object errors
- * we add a new GObject ref.
- */
- g_object_ref (gobj);
-
- if (((PyGObject *)py_arg)->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING) {
- /*
- * We want to re-float instances that were floating and the Python
- * wrapper assumed ownership. With the additional caveat that there
- * are not any strong references beyond the return tuple.
- */
- g_object_force_floating (gobj);
-
- } else {
- PyObject *repr = PyObject_Repr (py_arg);
- gchar *msg = g_strdup_printf ("Expecting to marshal a borrowed reference for %s, "
- "but nothing in Python is holding a reference to this object. "
- "See: https://bugzilla.gnome.org/show_bug.cgi?id=687522",
- PYGLIB_PyUnicode_AsString(repr));
- Py_DECREF (repr);
- if (PyErr_WarnEx (PyExc_RuntimeWarning, msg, 2)) {
- g_free (msg);
- return FALSE;
- }
- g_free (msg);
- }
- }
-
- return TRUE;
-}
-
-/* _pygi_marshal_from_py_gvalue:
- * py_arg: (in):
- * arg: (out):
- * transfer:
- * copy_reference: TRUE if arg should use the pointer reference held by py_arg
- * when it is already holding a GValue vs. copying the value.
- */
-gboolean
-_pygi_marshal_from_py_gvalue (PyObject *py_arg,
- GIArgument *arg,
- GITransfer transfer,
- gboolean copy_reference) {
- GValue *value;
- GType object_type;
-
- object_type = pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
- if (object_type == G_TYPE_INVALID) {
- PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
- return FALSE;
- }
-
- /* if already a gvalue, use that, else marshal into gvalue */
- if (object_type == G_TYPE_VALUE) {
- GValue *source_value = pyg_boxed_get (py_arg, GValue);
- if (copy_reference) {
- value = source_value;
- } else {
- value = g_slice_new0 (GValue);
- g_value_init (value, G_VALUE_TYPE (source_value));
- g_value_copy (source_value, value);
- }
- } else {
- value = g_slice_new0 (GValue);
- g_value_init (value, object_type);
- if (pyg_value_from_pyobject (value, py_arg) < 0) {
- g_slice_free (GValue, value);
- PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
- return FALSE;
- }
- }
-
- arg->v_pointer = value;
- return TRUE;
-}
-
-/* _pygi_marshal_from_py_gclosure:
- * py_arg: (in):
- * arg: (out):
- */
-gboolean
-_pygi_marshal_from_py_gclosure(PyObject *py_arg,
- GIArgument *arg)
-{
- GClosure *closure;
- GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE);
-
- if ( !(PyCallable_Check(py_arg) ||
- g_type_is_a (object_gtype, G_TYPE_CLOSURE))) {
- PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- if (g_type_is_a (object_gtype, G_TYPE_CLOSURE))
- closure = (GClosure *)pyg_boxed_get (py_arg, void);
- else
- closure = pyg_closure_new (py_arg, NULL, NULL);
-
- if (closure == NULL) {
- PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
- return FALSE;
- }
-
- arg->v_pointer = closure;
- return TRUE;
-}
-
-gboolean
-_pygi_marshal_from_py_interface_struct (PyObject *py_arg,
- GIArgument *arg,
- const gchar *arg_name,
- GIBaseInfo *interface_info,
- GITypeInfo *type_info,
- GType g_type,
- PyObject *py_type,
- GITransfer transfer,
- gboolean copy_reference,
- gboolean is_foreign)
-{
- gboolean is_union = FALSE;
-
- if (py_arg == Py_None) {
- arg->v_pointer = NULL;
- return TRUE;
- }
-
- /* FIXME: handle this large if statement in the cache
- * and set the correct marshaller
- */
-
- if (g_type_is_a (g_type, G_TYPE_CLOSURE)) {
- return _pygi_marshal_from_py_gclosure (py_arg, arg);
- } else if (g_type_is_a (g_type, G_TYPE_VALUE)) {
- return _pygi_marshal_from_py_gvalue(py_arg,
- arg,
- transfer,
- copy_reference);
- } else if (is_foreign) {
- PyObject *success;
- success = pygi_struct_foreign_convert_to_g_argument (py_arg,
- interface_info,
- transfer,
- arg);
-
- return (success == Py_None);
- } else if (!PyObject_IsInstance (py_arg, py_type)) {
- /* first check to see if this is a member of the expected union */
- is_union = _is_union_member (interface_info, py_arg);
- if (!is_union) {
- goto type_error;
- }
- }
-
- if (g_type_is_a (g_type, G_TYPE_BOXED)) {
- /* Additionally use pyg_type_from_object to pull the stashed __gtype__
- * attribute off of the input argument for type checking. This is needed
- * to work around type discrepancies in cases with aliased (typedef) types.
- * e.g. GtkAllocation, GdkRectangle.
- * See: https://bugzilla.gnomethere are .org/show_bug.cgi?id=707140
- */
- if (is_union || pyg_boxed_check (py_arg, g_type) ||
- g_type_is_a (pyg_type_from_object (py_arg), g_type)) {
- arg->v_pointer = pyg_boxed_get (py_arg, void);
- if (transfer == GI_TRANSFER_EVERYTHING) {
- arg->v_pointer = g_boxed_copy (g_type, arg->v_pointer);
- }
- } else {
- goto type_error;
- }
-
- } else if (g_type_is_a (g_type, G_TYPE_POINTER) ||
- g_type_is_a (g_type, G_TYPE_VARIANT) ||
- g_type == G_TYPE_NONE) {
- g_warn_if_fail (g_type_is_a (g_type, G_TYPE_VARIANT) || !g_type_info_is_pointer (type_info) || transfer == GI_TRANSFER_NOTHING);
-
- if (g_type_is_a (g_type, G_TYPE_VARIANT) &&
- pyg_type_from_object (py_arg) != G_TYPE_VARIANT) {
- PyErr_SetString (PyExc_TypeError, "expected GLib.Variant");
- return FALSE;
- }
- arg->v_pointer = pyg_pointer_get (py_arg, void);
-
- } else {
- PyErr_Format (PyExc_NotImplementedError,
- "structure type '%s' is not supported yet",
- g_type_name(g_type));
- return FALSE;
- }
- return TRUE;
-
-type_error:
- {
- gchar *type_name = _pygi_g_base_info_get_fullname (interface_info);
- PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
-
- PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
- arg_name ? arg_name : "self",
- type_name,
- module ? PYGLIB_PyUnicode_AsString(module) : "",
- module ? "." : "",
- py_arg->ob_type->tp_name);
- if (module)
- Py_DECREF (module);
- g_free (type_name);
- return FALSE;
- }
-}
diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h
deleted file mode 100644
index 9f56a6f..0000000
--- a/gi/pygi-marshal-from-py.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- *
- * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>, Red Hat, Inc.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGI_MARSHAL_from_py_PY_H__
-#define __PYGI_MARSHAL_from_py_PY_H__
-
-#include <Python.h>
-
-#include <girepository.h>
-
-#include "pygi-private.h"
-
-G_BEGIN_DECLS
-
-gboolean _pygi_marshal_from_py_ssize_t (PyGIArgCache *arg_cache,
- Py_ssize_t size,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_void (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_array (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_glist (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_ghash (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_gerror (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_enum (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_flags (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_interface(PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_boxed (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_object (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_union (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-gboolean _pygi_marshal_from_py_interface_instance (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-
-/* Simplified marshalers shared between vfunc/closure and direct function calls. */
-gboolean _pygi_marshal_from_py_basic_type (PyObject *object, /* in */
- GIArgument *arg, /* out */
- GITypeTag type_tag,
- GITransfer transfer);
-gboolean _pygi_marshal_from_py_basic_type_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg);
-
-gboolean _pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
- GIArgument *arg, /*out*/
- GITransfer transfer);
-gboolean _pygi_marshal_from_py_gobject_out_arg (PyObject *py_arg, /*in*/
- GIArgument *arg, /*out*/
- GITransfer transfer);
-
-gboolean _pygi_marshal_from_py_gvalue (PyObject *py_arg, /*in*/
- GIArgument *arg, /*out*/
- GITransfer transfer,
- gboolean is_allocated);
-
-gboolean _pygi_marshal_from_py_gclosure(PyObject *py_arg, /*in*/
- GIArgument *arg); /*out*/
-
-gboolean _pygi_marshal_from_py_interface_struct (PyObject *py_arg,
- GIArgument *arg,
- const gchar *arg_name,
- GIBaseInfo *interface_info,
- GITypeInfo *type_info,
- GType g_type,
- PyObject *py_type,
- GITransfer transfer,
- gboolean is_allocated,
- gboolean is_foreign);
-
-G_END_DECLS
-
-#endif /* __PYGI_MARSHAL_from_py_PY__ */
diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c
deleted file mode 100644
index 7c260f7..0000000
--- a/gi/pygi-marshal-to-py.c
+++ /dev/null
@@ -1,891 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- *
- * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>, Red Hat, Inc.
- *
- * pygi-marshal-from-py.c: functions for converting C types to PyObject
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#include "pygi-private.h"
-
-#include <string.h>
-#include <time.h>
-
-#include <pyglib.h>
-#include <pygobject.h>
-#include <pyglib-python-compat.h>
-
-#include "pygi-cache.h"
-#include "pygi-marshal-cleanup.h"
-#include "pygi-marshal-to-py.h"
-#include "pygi-argument.h"
-
-static gboolean
-gi_argument_to_c_long (GIArgument *arg_in,
- long *c_long_out,
- GITypeTag type_tag)
-{
- switch (type_tag) {
- case GI_TYPE_TAG_INT8:
- *c_long_out = arg_in->v_int8;
- return TRUE;
- case GI_TYPE_TAG_UINT8:
- *c_long_out = arg_in->v_uint8;
- return TRUE;
- case GI_TYPE_TAG_INT16:
- *c_long_out = arg_in->v_int16;
- return TRUE;
- case GI_TYPE_TAG_UINT16:
- *c_long_out = arg_in->v_uint16;
- return TRUE;
- case GI_TYPE_TAG_INT32:
- *c_long_out = arg_in->v_int32;
- return TRUE;
- case GI_TYPE_TAG_UINT32:
- *c_long_out = arg_in->v_uint32;
- return TRUE;
- case GI_TYPE_TAG_INT64:
- *c_long_out = arg_in->v_int64;
- return TRUE;
- case GI_TYPE_TAG_UINT64:
- *c_long_out = arg_in->v_uint64;
- return TRUE;
- default:
- PyErr_Format (PyExc_TypeError,
- "Unable to marshal %s to C long",
- g_type_tag_to_string (type_tag));
- return FALSE;
- }
-}
-
-static gboolean
-gi_argument_to_gsize (GIArgument *arg_in,
- gsize *gsize_out,
- GITypeTag type_tag)
-{
- switch (type_tag) {
- case GI_TYPE_TAG_INT8:
- *gsize_out = arg_in->v_int8;
- return TRUE;
- case GI_TYPE_TAG_UINT8:
- *gsize_out = arg_in->v_uint8;
- return TRUE;
- case GI_TYPE_TAG_INT16:
- *gsize_out = arg_in->v_int16;
- return TRUE;
- case GI_TYPE_TAG_UINT16:
- *gsize_out = arg_in->v_uint16;
- return TRUE;
- case GI_TYPE_TAG_INT32:
- *gsize_out = arg_in->v_int32;
- return TRUE;
- case GI_TYPE_TAG_UINT32:
- *gsize_out = arg_in->v_uint32;
- return TRUE;
- case GI_TYPE_TAG_INT64:
- *gsize_out = arg_in->v_int64;
- return TRUE;
- case GI_TYPE_TAG_UINT64:
- *gsize_out = arg_in->v_uint64;
- return TRUE;
- default:
- PyErr_Format (PyExc_TypeError,
- "Unable to marshal %s to gsize",
- g_type_tag_to_string (type_tag));
- return FALSE;
- }
-}
-
-PyObject *
-_pygi_marshal_to_py_void (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
- if (arg_cache->is_pointer) {
- /* NOTE: This will change to interpret pointers as integer values
- * by using the following:
- * py_obj = PyLong_FromVoidPtr (arg->v_pointer);
- * See: https://bugzilla.gnome.org/show_bug.cgi?id=688081
- */
- py_obj = arg->v_pointer;
- } else {
- py_obj = Py_None;
- }
-
- Py_XINCREF (py_obj);
- return py_obj;
-}
-
-static PyObject *
-_pygi_marshal_to_py_unichar (GIArgument *arg)
-{
- PyObject *py_obj = NULL;
-
- /* Preserve the bidirectional mapping between 0 and "" */
- if (arg->v_uint32 == 0) {
- py_obj = PYGLIB_PyUnicode_FromString ("");
- } else if (g_unichar_validate (arg->v_uint32)) {
- gchar utf8[6];
- gint bytes;
-
- bytes = g_unichar_to_utf8 (arg->v_uint32, utf8);
- py_obj = PYGLIB_PyUnicode_FromStringAndSize ((char*)utf8, bytes);
- } else {
- /* TODO: Convert the error to an exception. */
- PyErr_Format (PyExc_TypeError,
- "Invalid unicode codepoint %" G_GUINT32_FORMAT,
- arg->v_uint32);
- }
-
- return py_obj;
-}
-
-static PyObject *
-_pygi_marshal_to_py_utf8 (GIArgument *arg)
-{
- PyObject *py_obj = NULL;
- if (arg->v_string == NULL) {
- Py_RETURN_NONE;
- }
-
- py_obj = PYGLIB_PyUnicode_FromString (arg->v_string);
- return py_obj;
-}
-
-static PyObject *
-_pygi_marshal_to_py_filename (GIArgument *arg)
-{
- gchar *string = NULL;
- PyObject *py_obj = NULL;
- GError *error = NULL;
-
- if (arg->v_string == NULL) {
- Py_RETURN_NONE;
- }
-
- string = g_filename_to_utf8 (arg->v_string, -1, NULL, NULL, &error);
- if (string == NULL) {
- PyErr_SetString (PyExc_Exception, error->message);
- /* TODO: Convert the error to an exception. */
- return NULL;
- }
-
- py_obj = PYGLIB_PyUnicode_FromString (string);
- g_free (string);
-
- return py_obj;
-}
-
-
-/**
- * _pygi_marshal_to_py_basic_type:
- * @arg: The argument to convert to an object.
- * @type_tag: Type tag for @arg
- * @transfer: Transfer annotation
- *
- * Convert the given argument to a Python object. This function
- * is restricted to simple types that only require the GITypeTag
- * and GITransfer. For a more complete conversion routine, use:
- * _pygi_argument_to_object.
- *
- * Returns: A PyObject representing @arg or NULL if it cannot convert
- * the argument.
- */
-PyObject *
-_pygi_marshal_to_py_basic_type (GIArgument *arg,
- GITypeTag type_tag,
- GITransfer transfer)
-{
- switch (type_tag) {
- case GI_TYPE_TAG_BOOLEAN:
- return PyBool_FromLong (arg->v_boolean);
-
- case GI_TYPE_TAG_INT8:
- return PYGLIB_PyLong_FromLong (arg->v_int8);
-
- case GI_TYPE_TAG_UINT8:
- return PYGLIB_PyLong_FromLong (arg->v_uint8);
-
- case GI_TYPE_TAG_INT16:
- return PYGLIB_PyLong_FromLong (arg->v_int16);
-
- case GI_TYPE_TAG_UINT16:
- return PYGLIB_PyLong_FromLong (arg->v_uint16);
-
- case GI_TYPE_TAG_INT32:
- return PYGLIB_PyLong_FromLong (arg->v_int32);
-
- case GI_TYPE_TAG_UINT32:
- return PyLong_FromLongLong (arg->v_uint32);
-
- case GI_TYPE_TAG_INT64:
- return PyLong_FromLongLong (arg->v_int64);
-
- case GI_TYPE_TAG_UINT64:
- return PyLong_FromUnsignedLongLong (arg->v_uint64);
-
- case GI_TYPE_TAG_FLOAT:
- return PyFloat_FromDouble (arg->v_float);
-
- case GI_TYPE_TAG_DOUBLE:
- return PyFloat_FromDouble (arg->v_double);
-
- case GI_TYPE_TAG_GTYPE:
- return pyg_type_wrapper_new ( (GType) arg->v_long);
-
- case GI_TYPE_TAG_UNICHAR:
- return _pygi_marshal_to_py_unichar (arg);
-
- case GI_TYPE_TAG_UTF8:
- return _pygi_marshal_to_py_utf8 (arg);
-
- case GI_TYPE_TAG_FILENAME:
- return _pygi_marshal_to_py_filename (arg);
-
- default:
- return NULL;
- }
- return NULL;
-}
-
-PyObject *
-_pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- return _pygi_marshal_to_py_basic_type (arg,
- arg_cache->type_tag,
- arg_cache->transfer);
-}
-
-PyObject *
-_pygi_marshal_to_py_array (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- GArray *array_;
- PyObject *py_obj = NULL;
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
- gsize processed_items = 0;
-
- /* GArrays make it easier to iterate over arrays
- * with different element sizes but requires that
- * we allocate a GArray if the argument was a C array
- */
- if (seq_cache->array_type == GI_ARRAY_TYPE_C) {
- gsize len;
- if (seq_cache->fixed_size >= 0) {
- g_assert(arg->v_pointer != NULL);
- len = seq_cache->fixed_size;
- } else if (seq_cache->is_zero_terminated) {
- if (arg->v_pointer == NULL) {
- len = 0;
- } else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
- len = strlen (arg->v_pointer);
- } else {
- len = g_strv_length ((gchar **)arg->v_pointer);
- }
- } else {
- GIArgument *len_arg = state->args[seq_cache->len_arg_index];
-
- if (!gi_argument_to_gsize (len_arg,
- &len,
- callable_cache->args_cache[seq_cache->len_arg_index]->type_tag)) {
- return NULL;
- }
- }
-
- array_ = g_array_new (FALSE,
- FALSE,
- seq_cache->item_size);
- if (array_ == NULL) {
- PyErr_NoMemory ();
-
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && arg->v_pointer != NULL)
- g_free (arg->v_pointer);
-
- return NULL;
- }
-
- if (array_->data != NULL)
- g_free (array_->data);
- array_->data = arg->v_pointer;
- array_->len = len;
- } else {
- array_ = arg->v_pointer;
- }
-
- if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
- if (arg->v_pointer == NULL) {
- py_obj = PYGLIB_PyBytes_FromString ("");
- } else {
- py_obj = PYGLIB_PyBytes_FromStringAndSize (array_->data, array_->len);
- }
- } else {
- if (arg->v_pointer == NULL) {
- py_obj = PyList_New (0);
- } else {
- int i;
-
- gsize item_size;
- PyGIMarshalToPyFunc item_to_py_marshaller;
- PyGIArgCache *item_arg_cache;
-
- py_obj = PyList_New (array_->len);
- if (py_obj == NULL)
- goto err;
-
-
- item_arg_cache = seq_cache->item_cache;
- item_to_py_marshaller = item_arg_cache->to_py_marshaller;
-
- item_size = g_array_get_element_size (array_);
-
- for (i = 0; i < array_->len; i++) {
- GIArgument item_arg;
- PyObject *py_item;
-
- if (seq_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
- item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
- } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *) item_arg_cache;
- gboolean is_gvariant = iface_cache->g_type == G_TYPE_VARIANT;
-
- // FIXME: This probably doesn't work with boxed types or gvalues. See fx. _pygi_marshal_from_py_array()
- switch (g_base_info_get_type (iface_cache->interface_info)) {
- case GI_INFO_TYPE_STRUCT:
- if (is_gvariant) {
- g_assert (item_size == sizeof (gpointer));
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- item_arg.v_pointer = g_variant_ref_sink (g_array_index (array_, gpointer, i));
- else
- item_arg.v_pointer = g_array_index (array_, gpointer, i);
- } else if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && !item_arg_cache->is_pointer &&
- !g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
- /* array elements are structs */
- gpointer *_struct = g_malloc (item_size);
- memcpy (_struct, array_->data + i * item_size,
- item_size);
- item_arg.v_pointer = _struct;
- } else if (item_arg_cache->is_pointer)
- /* array elements are pointers to values */
- item_arg.v_pointer = g_array_index (array_, gpointer, i);
- else
- item_arg.v_pointer = array_->data + i * item_size;
- break;
- default:
- item_arg.v_pointer = g_array_index (array_, gpointer, i);
- break;
- }
- } else {
- memcpy (&item_arg, array_->data + i * item_size, item_size);
- }
-
- py_item = item_to_py_marshaller ( state,
- callable_cache,
- item_arg_cache,
- &item_arg);
-
- if (py_item == NULL) {
- Py_CLEAR (py_obj);
-
- if (seq_cache->array_type == GI_ARRAY_TYPE_C)
- g_array_unref (array_);
-
- goto err;
- }
- PyList_SET_ITEM (py_obj, i, py_item);
- processed_items++;
- }
- }
- }
-
- if (seq_cache->array_type == GI_ARRAY_TYPE_C)
- g_array_free (array_, FALSE);
-
- return py_obj;
-
-err:
- if (seq_cache->array_type == GI_ARRAY_TYPE_C) {
- g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING);
- } else {
- /* clean up unprocessed items */
- if (seq_cache->item_cache->to_py_cleanup != NULL) {
- int j;
- PyGIMarshalCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup;
- for (j = processed_items; j < array_->len; j++) {
- cleanup_func (state,
- seq_cache->item_cache,
- g_array_index (array_, gpointer, j),
- FALSE);
- }
- }
-
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- g_array_free (array_, TRUE);
- }
-
- return NULL;
-}
-
-PyObject *
-_pygi_marshal_to_py_glist (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- GList *list_;
- gsize length;
- gsize i;
-
- PyGIMarshalToPyFunc item_to_py_marshaller;
- PyGIArgCache *item_arg_cache;
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
-
- PyObject *py_obj = NULL;
-
- list_ = arg->v_pointer;
- length = g_list_length (list_);
-
- py_obj = PyList_New (length);
- if (py_obj == NULL)
- return NULL;
-
- item_arg_cache = seq_cache->item_cache;
- item_to_py_marshaller = item_arg_cache->to_py_marshaller;
-
- for (i = 0; list_ != NULL; list_ = g_list_next (list_), i++) {
- GIArgument item_arg;
- PyObject *py_item;
-
- item_arg.v_pointer = list_->data;
- _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_tag);
- py_item = item_to_py_marshaller (state,
- callable_cache,
- item_arg_cache,
- &item_arg);
-
- if (py_item == NULL) {
- Py_CLEAR (py_obj);
- _PyGI_ERROR_PREFIX ("Item %zu: ", i);
- return NULL;
- }
-
- PyList_SET_ITEM (py_obj, i, py_item);
- }
-
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_gslist (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- GSList *list_;
- gsize length;
- gsize i;
-
- PyGIMarshalToPyFunc item_to_py_marshaller;
- PyGIArgCache *item_arg_cache;
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
-
- PyObject *py_obj = NULL;
-
- list_ = arg->v_pointer;
- length = g_slist_length (list_);
-
- py_obj = PyList_New (length);
- if (py_obj == NULL)
- return NULL;
-
- item_arg_cache = seq_cache->item_cache;
- item_to_py_marshaller = item_arg_cache->to_py_marshaller;
-
- for (i = 0; list_ != NULL; list_ = g_slist_next (list_), i++) {
- GIArgument item_arg;
- PyObject *py_item;
-
- item_arg.v_pointer = list_->data;
- _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_tag);
- py_item = item_to_py_marshaller (state,
- callable_cache,
- item_arg_cache,
- &item_arg);
-
- if (py_item == NULL) {
- Py_CLEAR (py_obj);
- _PyGI_ERROR_PREFIX ("Item %zu: ", i);
- return NULL;
- }
-
- PyList_SET_ITEM (py_obj, i, py_item);
- }
-
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_ghash (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- GHashTable *hash_;
- GHashTableIter hash_table_iter;
-
- PyGIMarshalToPyFunc key_to_py_marshaller;
- PyGIMarshalToPyFunc value_to_py_marshaller;
-
- PyGIArgCache *key_arg_cache;
- PyGIArgCache *value_arg_cache;
- PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
-
- GIArgument key_arg;
- GIArgument value_arg;
-
- PyObject *py_obj = NULL;
-
- hash_ = arg->v_pointer;
-
- if (hash_ == NULL) {
- py_obj = Py_None;
- Py_INCREF (py_obj);
- return py_obj;
- }
-
- py_obj = PyDict_New ();
- if (py_obj == NULL)
- return NULL;
-
- key_arg_cache = hash_cache->key_cache;
- key_to_py_marshaller = key_arg_cache->to_py_marshaller;
-
- value_arg_cache = hash_cache->value_cache;
- value_to_py_marshaller = value_arg_cache->to_py_marshaller;
-
- g_hash_table_iter_init (&hash_table_iter, hash_);
- while (g_hash_table_iter_next (&hash_table_iter,
- &key_arg.v_pointer,
- &value_arg.v_pointer)) {
- PyObject *py_key;
- PyObject *py_value;
- int retval;
-
-
- _pygi_hash_pointer_to_arg (&key_arg, hash_cache->key_cache->type_tag);
- py_key = key_to_py_marshaller ( state,
- callable_cache,
- key_arg_cache,
- &key_arg);
-
- if (py_key == NULL) {
- Py_CLEAR (py_obj);
- return NULL;
- }
-
- _pygi_hash_pointer_to_arg (&value_arg, hash_cache->value_cache->type_tag);
- py_value = value_to_py_marshaller ( state,
- callable_cache,
- value_arg_cache,
- &value_arg);
-
- if (py_value == NULL) {
- Py_CLEAR (py_obj);
- Py_DECREF(py_key);
- return NULL;
- }
-
- retval = PyDict_SetItem (py_obj, py_key, py_value);
-
- Py_DECREF (py_key);
- Py_DECREF (py_value);
-
- if (retval < 0) {
- Py_CLEAR (py_obj);
- return NULL;
- }
- }
-
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_gerror (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- GError *error = arg->v_pointer;
- PyObject *py_obj = NULL;
-
- py_obj = pyglib_error_marshal(&error);
-
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) {
- g_error_free (error);
- }
-
- if (py_obj != NULL) {
- return py_obj;
- } else {
- Py_RETURN_NONE;
- }
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_callback (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
-
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling a callback to PyObject is not supported");
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_enum (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- GIBaseInfo *interface;
- long c_long;
-
- interface = g_type_info_get_interface (arg_cache->type_info);
- g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
-
- if (!gi_argument_to_c_long(arg, &c_long,
- g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
- return NULL;
- }
-
- if (iface_cache->g_type == G_TYPE_NONE) {
- py_obj = PyObject_CallFunction (iface_cache->py_type, "l", c_long);
- } else {
- py_obj = pyg_enum_from_gtype (iface_cache->g_type, c_long);
- }
- g_base_info_unref (interface);
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_flags (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- GIBaseInfo *interface;
- long c_long;
-
- interface = g_type_info_get_interface (arg_cache->type_info);
- g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
-
- if (!gi_argument_to_c_long(arg, &c_long,
- g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
- g_base_info_unref (interface);
- return NULL;
- }
-
- g_base_info_unref (interface);
- if (iface_cache->g_type == G_TYPE_NONE) {
- /* An enum with a GType of None is an enum without GType */
-
- PyObject *py_type = _pygi_type_import_by_gi_info (iface_cache->interface_info);
- PyObject *py_args = NULL;
-
- if (!py_type)
- return NULL;
-
- py_args = PyTuple_New (1);
- if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (c_long)) != 0) {
- Py_DECREF (py_args);
- Py_DECREF (py_type);
- return NULL;
- }
-
- py_obj = PyObject_CallFunction (py_type, "l", c_long);
-
- Py_DECREF (py_args);
- Py_DECREF (py_type);
- } else {
- py_obj = pyg_flags_from_gtype (iface_cache->g_type, c_long);
- }
-
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_struct_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
-
- return _pygi_marshal_to_py_interface_struct (arg,
- iface_cache->interface_info,
- iface_cache->g_type,
- iface_cache->py_type,
- arg_cache->transfer,
- arg_cache->is_caller_allocates,
- iface_cache->is_foreign);
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_interface (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
-
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_boxed (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
-
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_object_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- return _pygi_marshal_to_py_object(arg, arg_cache->transfer);
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_union (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
-
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_object (GIArgument *arg, GITransfer transfer) {
- PyObject *pyobj;
-
- if (arg->v_pointer == NULL) {
- pyobj = Py_None;
- Py_INCREF (pyobj);
-
- } else if (G_IS_PARAM_SPEC(arg->v_pointer)) {
- pyobj = pyg_param_spec_new (arg->v_pointer);
- if (transfer == GI_TRANSFER_EVERYTHING)
- g_param_spec_unref (arg->v_pointer);
-
- } else {
- pyobj = pygobject_new_full (arg->v_pointer,
- /*steal=*/ transfer == GI_TRANSFER_EVERYTHING,
- /*type=*/ NULL);
- }
-
- return pyobj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_struct (GIArgument *arg,
- GIInterfaceInfo *interface_info,
- GType g_type,
- PyObject *py_type,
- GITransfer transfer,
- gboolean is_allocated,
- gboolean is_foreign)
-{
- PyObject *py_obj = NULL;
-
- if (arg->v_pointer == NULL) {
- Py_RETURN_NONE;
- }
-
- if (g_type_is_a (g_type, G_TYPE_VALUE)) {
- py_obj = pyg_value_as_pyobject (arg->v_pointer, FALSE);
- } else if (is_foreign) {
- py_obj = pygi_struct_foreign_convert_from_g_argument (interface_info,
- arg->v_pointer);
- } else if (g_type_is_a (g_type, G_TYPE_BOXED)) {
- if (py_type) {
- py_obj = _pygi_boxed_new ((PyTypeObject *) py_type,
- arg->v_pointer,
- transfer == GI_TRANSFER_EVERYTHING || is_allocated,
- is_allocated ?
- g_struct_info_get_size(interface_info) : 0);
- }
- } else if (g_type_is_a (g_type, G_TYPE_POINTER)) {
- if (py_type == NULL ||
- !PyType_IsSubtype ((PyTypeObject *) py_type, &PyGIStruct_Type)) {
- g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
- py_obj = pyg_pointer_new (g_type, arg->v_pointer);
- } else {
- py_obj = _pygi_struct_new ( (PyTypeObject *) py_type,
- arg->v_pointer,
- transfer == GI_TRANSFER_EVERYTHING);
- }
- } else if (g_type_is_a (g_type, G_TYPE_VARIANT)) {
- /* Note we do not use transfer for the structs free_on_dealloc because
- * GLib.Variant overrides __del__ to call "g_variant_unref". */
- if (py_type) {
- g_variant_ref_sink (arg->v_pointer);
- py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
- arg->v_pointer,
- FALSE);
- }
- } else if (g_type == G_TYPE_NONE) {
- if (py_type) {
- py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
- arg->v_pointer,
- transfer == GI_TRANSFER_EVERYTHING);
- }
- } else {
- PyErr_Format (PyExc_NotImplementedError,
- "structure type '%s' is not supported yet",
- g_type_name (g_type));
- }
-
- return py_obj;
-}
diff --git a/gi/pygi-marshal-to-py.h b/gi/pygi-marshal-to-py.h
deleted file mode 100644
index 1378630..0000000
--- a/gi/pygi-marshal-to-py.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- *
- * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>, Red Hat, Inc.
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGI_MARSHAL_TO_PY_H__
-#define __PYGI_MARSHAL_TO_PY_H__
-
-PyObject *_pygi_marshal_to_py_basic_type (GIArgument *arg,
- GITypeTag type_tag,
- GITransfer transfer);
-PyObject *_pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_void (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_array (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_glist (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_gslist (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_ghash (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_gerror (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_callback(PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_enum (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_flags (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_struct_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_interface(PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_boxed (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_object_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_union (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-
-/* Simplified marshalers shared between vfunc/closure and direct function calls. */
-
-PyObject *_pygi_marshal_to_py_object (GIArgument *arg,
- GITransfer transfer);
-
-PyObject *_pygi_marshal_to_py_interface_struct (GIArgument *arg,
- GIInterfaceInfo *interface_info,
- GType g_type,
- PyObject *py_type,
- GITransfer transfer,
- gboolean is_allocated,
- gboolean is_foreign);
-
-G_END_DECLS
-
-#endif /* __PYGI_MARSHAL_TO_PY_H__ */
diff --git a/gi/pygi-object.c b/gi/pygi-object.c
new file mode 100644
index 0000000..c97d2df
--- /dev/null
+++ b/gi/pygi-object.c
@@ -0,0 +1,381 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include <glib.h>
+
+#include "pygi-object.h"
+#include "pygobject-object.h"
+#include "pygparamspec.h"
+
+/*
+ * GObject from Python
+ */
+
+typedef gboolean (*PyGIObjectMarshalFromPyFunc) (PyObject *py_arg,
+ GIArgument *arg,
+ GITransfer transfer);
+
+/* _pygi_marshal_from_py_gobject:
+ * py_arg: (in):
+ * arg: (out):
+ */
+static gboolean
+_pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
+ GIArgument *arg, /*out*/
+ GITransfer transfer) {
+ GObject *gobj;
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+
+ if (!pygobject_check (py_arg, &PyGObject_Type)) {
+ PyObject *repr = PyObject_Repr (py_arg);
+ PyErr_Format(PyExc_TypeError, "expected GObject but got %s",
+ PyUnicode_AsUTF8 (repr));
+ Py_DECREF (repr);
+ return FALSE;
+ }
+
+ gobj = pygobject_get (py_arg);
+ if (gobj == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "object at %p of type %s is not initialized",
+ py_arg, Py_TYPE(py_arg)->tp_name);
+ return FALSE;
+ }
+
+ if (transfer == GI_TRANSFER_EVERYTHING) {
+ /* For transfer everything, add a new ref that the callee will take ownership of.
+ * Pythons existing ref to the GObject will be managed with the PyGObject wrapper.
+ */
+ g_object_ref (gobj);
+ }
+
+ arg->v_pointer = gobj;
+ return TRUE;
+}
+
+/* pygi_arg_gobject_out_arg_from_py:
+ * py_arg: (in):
+ * arg: (out):
+ *
+ * A specialization for marshaling Python GObjects used for out/return values
+ * from a Python implemented vfuncs, signals, or an assignment to a GObject property.
+ */
+gboolean
+pygi_arg_gobject_out_arg_from_py (PyObject *py_arg, /*in*/
+ GIArgument *arg, /*out*/
+ GITransfer transfer) {
+ GObject *gobj;
+ if (!_pygi_marshal_from_py_gobject (py_arg, arg, transfer)) {
+ return FALSE;
+ }
+
+ /* HACK: At this point the basic marshaling of the GObject was successful
+ * but we add some special case hacks for vfunc returns due to buggy APIs:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=693393
+ */
+ gobj = arg->v_pointer;
+ if (Py_REFCNT (py_arg) == 1 && gobj->ref_count == 1) {
+ /* If both object ref counts are only 1 at this point (the reference held
+ * in a return tuple), we assume the GObject will be free'd before reaching
+ * its target and become invalid. So instead of getting invalid object errors
+ * we add a new GObject ref.
+ */
+ g_object_ref (gobj);
+
+ if (((PyGObject *)py_arg)->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING) {
+ /*
+ * We want to re-float instances that were floating and the Python
+ * wrapper assumed ownership. With the additional caveat that there
+ * are not any strong references beyond the return tuple.
+ */
+ g_object_force_floating (gobj);
+
+ } else {
+ PyObject *repr = PyObject_Repr (py_arg);
+ gchar *msg = g_strdup_printf ("Expecting to marshal a borrowed reference for %s, "
+ "but nothing in Python is holding a reference to this object. "
+ "See: https://bugzilla.gnome.org/show_bug.cgi?id=687522",
+ PyUnicode_AsUTF8 (repr));
+ Py_DECREF (repr);
+ if (PyErr_WarnEx (PyExc_RuntimeWarning, msg, 2)) {
+ g_free (msg);
+ return FALSE;
+ }
+ g_free (msg);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_interface_object (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data,
+ PyGIObjectMarshalFromPyFunc func)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+
+ if (PyObject_IsInstance (py_arg, iface_cache->py_type) ||
+ (pygobject_check (py_arg, &PyGObject_Type) &&
+ g_type_is_a (G_OBJECT_TYPE (pygobject_get (py_arg)), iface_cache->g_type))) {
+
+ gboolean res;
+ res = func (py_arg, arg, arg_cache->transfer);
+ *cleanup_data = arg->v_pointer;
+ return res;
+
+ } else {
+ PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
+
+ PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
+ arg_cache->arg_name ? arg_cache->arg_name : "self",
+ ( (PyGIInterfaceCache *)arg_cache)->type_name,
+ module ? PyUnicode_AsUTF8 (module) : "",
+ module ? "." : "",
+ Py_TYPE (py_arg)->tp_name);
+ if (module)
+ Py_DECREF (module);
+ return FALSE;
+ }
+}
+
+static gboolean
+_pygi_marshal_from_py_called_from_c_interface_object (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ return _pygi_marshal_from_py_interface_object (state,
+ callable_cache,
+ arg_cache,
+ py_arg,
+ arg,
+ cleanup_data,
+ pygi_arg_gobject_out_arg_from_py);
+}
+
+static gboolean
+_pygi_marshal_from_py_called_from_py_interface_object (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ return _pygi_marshal_from_py_interface_object (state,
+ callable_cache,
+ arg_cache,
+ py_arg,
+ arg,
+ cleanup_data,
+ _pygi_marshal_from_py_gobject);
+}
+
+static void
+_pygi_marshal_cleanup_from_py_interface_object (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ /* If we processed the parameter but fail before invoking the method,
+ we need to remove the ref we added */
+ if (was_processed && state->failed && data != NULL &&
+ arg_cache->transfer == GI_TRANSFER_EVERYTHING)
+ g_object_unref (G_OBJECT(data));
+}
+
+
+/*
+ * GObject to Python
+ */
+
+PyObject *
+pygi_arg_gobject_to_py (GIArgument *arg, GITransfer transfer) {
+ PyObject *pyobj;
+
+ if (arg->v_pointer == NULL) {
+ pyobj = Py_None;
+ Py_INCREF (pyobj);
+
+ } else if (G_IS_PARAM_SPEC(arg->v_pointer)) {
+ pyobj = pyg_param_spec_new (arg->v_pointer);
+ if (transfer == GI_TRANSFER_EVERYTHING)
+ g_param_spec_unref (arg->v_pointer);
+
+ } else if (G_IS_OBJECT(arg->v_pointer)) {
+ pyobj = pygobject_new_full (arg->v_pointer,
+ /*steal=*/ transfer == GI_TRANSFER_EVERYTHING,
+ /*type=*/ NULL);
+ } else {
+ PyErr_Format(PyExc_TypeError,
+ "No means to translate argument or return value for '%s'",
+ g_type_name_from_instance(arg->v_pointer));
+ return NULL;
+ }
+
+ return pyobj;
+}
+
+PyObject *
+pygi_arg_gobject_to_py_called_from_c (GIArgument *arg,
+ GITransfer transfer)
+{
+ PyObject *object;
+
+ /* HACK:
+ * The following hack is to work around GTK sending signals which
+ * contain floating widgets in them. This assumes control of how
+ * references are added by the PyGObject wrapper and avoids the sink
+ * behavior by explicitly passing GI_TRANSFER_EVERYTHING as the transfer
+ * mode and then re-forcing the object as floating afterwards.
+ *
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=693400
+ */
+ if (arg->v_pointer != NULL &&
+ transfer == GI_TRANSFER_NOTHING &&
+ G_IS_OBJECT (arg->v_pointer) &&
+ g_object_is_floating (arg->v_pointer)) {
+
+ g_object_ref (arg->v_pointer);
+ object = pygi_arg_gobject_to_py (arg, GI_TRANSFER_EVERYTHING);
+ g_object_force_floating (arg->v_pointer);
+ } else {
+ object = pygi_arg_gobject_to_py (arg, transfer);
+ }
+
+ return object;
+}
+
+static PyObject *
+_pygi_marshal_to_py_called_from_c_interface_object_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ return pygi_arg_gobject_to_py_called_from_c (arg, arg_cache->transfer);
+}
+
+static PyObject *
+_pygi_marshal_to_py_called_from_py_interface_object_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ return pygi_arg_gobject_to_py (arg, arg_cache->transfer);
+}
+
+static void
+_pygi_marshal_cleanup_to_py_interface_object (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer cleanup_data,
+ gpointer data,
+ gboolean was_processed)
+{
+ /* If we error out and the object is not marshalled into a PyGObject
+ we must take care of removing the ref */
+ if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING)
+ g_object_unref (G_OBJECT(data));
+}
+
+static gboolean
+pygi_arg_gobject_setup_from_info (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ PyGICallableCache *callable_cache)
+{
+ /* NOTE: usage of pygi_arg_interface_new_from_info already calls
+ * pygi_arg_interface_setup so no need to do it here.
+ */
+
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ if (callable_cache->calling_context == PYGI_CALLING_CONTEXT_IS_FROM_C) {
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_called_from_c_interface_object;
+ } else {
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_called_from_py_interface_object;
+ }
+
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
+ }
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ if (callable_cache->calling_context == PYGI_CALLING_CONTEXT_IS_FROM_C) {
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_called_from_c_interface_object_cache_adapter;
+ } else {
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_called_from_py_interface_object_cache_adapter;
+ }
+
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_gobject_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info,
+ PyGICallableCache *callable_cache)
+{
+ gboolean res = FALSE;
+ PyGIArgCache *cache = NULL;
+
+ cache = pygi_arg_interface_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ if (cache == NULL)
+ return NULL;
+
+ res = pygi_arg_gobject_setup_from_info (cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ callable_cache);
+ if (res) {
+ return cache;
+ } else {
+ pygi_arg_cache_free (cache);
+ return NULL;
+ }
+}
diff --git a/gi/pygi-object.h b/gi/pygi-object.h
new file mode 100644
index 0000000..360bce1
--- /dev/null
+++ b/gi/pygi-object.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_OBJECT_H__
+#define __PYGI_OBJECT_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+gboolean
+pygi_arg_gobject_out_arg_from_py (PyObject *py_arg, /* in */
+ GIArgument *arg, /* out */
+ GITransfer transfer);
+
+PyObject *
+pygi_arg_gobject_to_py (GIArgument *arg,
+ GITransfer transfer);
+
+PyObject *
+pygi_arg_gobject_to_py_called_from_c (GIArgument *arg,
+ GITransfer transfer);
+
+
+PyGIArgCache *
+pygi_arg_gobject_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info,
+ PyGICallableCache *callable_cache);
+
+G_END_DECLS
+
+#endif /*__PYGI_OBJECT_H__*/
diff --git a/gi/pygi-private.h b/gi/pygi-private.h
deleted file mode 100644
index 97eced5..0000000
--- a/gi/pygi-private.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- */
-#ifndef __PYGI_PRIVATE_H__
-#define __PYGI_PRIVATE_H__
-
-#ifdef __PYGI_H__
-# error "Import pygi.h or pygi-private.h, but not both"
-#endif
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <Python.h>
-
-#include "pygi.h"
-
-#include "pygobject-external.h"
-
-#include "pygi-repository.h"
-#include "pygi-info.h"
-#include "pygi-struct.h"
-#include "pygi-boxed.h"
-#include "pygi-argument.h"
-#include "pygi-type.h"
-#include "pygi-foreign.h"
-#include "pygi-closure.h"
-#include "pygi-ccallback.h"
-#include "pygi-property.h"
-#include "pygi-signal-closure.h"
-#include "pygi-invoke.h"
-#include "pygi-cache.h"
-#include "pygi-source.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); \
- Py_DECREF(py_error_prefix); \
- } \
-} G_STMT_END
-
-#else
-
-#define _PyGI_ERROR_PREFIX(format, ...) G_STMT_START { \
- PyObject *py_error_prefix; \
- py_error_prefix = PyString_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 (PyString_Check(py_error_value)) { \
- PyString_ConcatAndDel(&py_error_prefix, py_error_value); \
- if (py_error_prefix != NULL) { \
- py_error_value = py_error_prefix; \
- } \
- } \
- PyErr_Restore(py_error_type, py_error_value, py_error_traceback); \
- } \
-} 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. */
-#define _g_array_index(a,t,i) \
- *(t *)((a)->data + g_array_get_element_size(a) * (i))
-
-
-G_END_DECLS
-
-#endif /* __PYGI_PRIVATE_H__ */
diff --git a/gi/pygi-property.c b/gi/pygi-property.c
index 3f6d038..595167b 100644
--- a/gi/pygi-property.c
+++ b/gi/pygi-property.c
@@ -21,7 +21,11 @@
* IN THE SOFTWARE.
*/
-#include "pygi-private.h"
+#include "pygi-property.h"
+#include "pygi-value.h"
+#include "pygi-argument.h"
+#include "pygparamspec.h"
+#include "pygi-type.h"
#include <girepository.h>
@@ -29,7 +33,7 @@ static GIPropertyInfo *
lookup_property_from_object_info (GIObjectInfo *info, const gchar *attr_name)
{
gssize n_infos;
- gssize i;
+ gint i;
n_infos = g_object_info_get_n_properties (info);
for (i = 0; i < n_infos; i++) {
@@ -53,7 +57,7 @@ lookup_property_from_interface_info (GIInterfaceInfo *info,
const gchar *attr_name)
{
gssize n_infos;
- gssize i;
+ gint i;
n_infos = g_interface_info_get_n_properties (info);
for (i = 0; i < n_infos; i++) {
@@ -95,185 +99,115 @@ _pygi_lookup_property_from_g_type (GType g_type, const gchar *attr_name)
return ret;
}
-static inline gpointer
-g_value_get_or_dup_boxed (const GValue *value, GITransfer transfer)
+PyObject *
+pygi_call_do_get_property (PyObject *instance, GParamSpec *pspec)
{
- if (transfer == GI_TRANSFER_EVERYTHING)
- return g_value_dup_boxed (value);
- else
- return g_value_get_boxed (value);
+ PyObject *py_pspec;
+ PyObject *retval;
+
+ py_pspec = pyg_param_spec_new (pspec);
+ retval = PyObject_CallMethod (instance, "do_get_property", "O", py_pspec);
+ Py_DECREF (py_pspec);
+ return retval;
}
PyObject *
-pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
+pygi_get_property_value (PyGObject *instance, GParamSpec *pspec)
{
GIPropertyInfo *property_info = NULL;
GValue value = { 0, };
- GIArgument arg = { 0, };
PyObject *py_value = NULL;
- GITypeInfo *type_info = NULL;
- GITransfer transfer;
- GITypeTag type_tag;
+ GType fundamental;
+ gboolean handled;
- /* The owner_type of the pspec gives us the exact type that introduced the
- * property, even if it is a parent class of the instance in question. */
- property_info = _pygi_lookup_property_from_g_type (pspec->owner_type, pspec->name);
+ if (!(pspec->flags & G_PARAM_READABLE)) {
+ PyErr_Format(PyExc_TypeError, "property %s is not readable",
+ g_param_spec_get_name (pspec));
+ return NULL;
+ }
- if (property_info == NULL)
- goto out;
+ /* Fast path which calls the Python getter implementation directly.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=723872 */
+ if (pyg_gtype_is_custom (pspec->owner_type)) {
+ return pygi_call_do_get_property ((PyObject *)instance, pspec);
+ }
+ Py_BEGIN_ALLOW_THREADS;
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
g_object_get_property (instance->obj, pspec->name, &value);
+ fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (&value));
+ Py_END_ALLOW_THREADS;
- type_info = g_property_info_get_type (property_info);
- transfer = g_property_info_get_ownership_transfer (property_info);
- 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:
- arg.v_int8 = g_value_get_schar (&value);
- break;
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_INT32:
- if (G_VALUE_HOLDS_LONG (&value))
- arg.v_long = g_value_get_long (&value);
- else
- arg.v_int = g_value_get_int (&value);
- break;
- case GI_TYPE_TAG_INT64:
- if (G_VALUE_HOLDS_LONG (&value))
- arg.v_long = g_value_get_long (&value);
- else
- arg.v_int64 = g_value_get_int64 (&value);
- break;
- case GI_TYPE_TAG_UINT8:
- arg.v_uint8 = g_value_get_uchar (&value);
- break;
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_UINT32:
- if (G_VALUE_HOLDS_ULONG (&value))
- arg.v_ulong = g_value_get_ulong (&value);
- else
- arg.v_uint = g_value_get_uint (&value);
- break;
- case GI_TYPE_TAG_UINT64:
- if (G_VALUE_HOLDS_ULONG (&value))
- arg.v_ulong = g_value_get_ulong (&value);
- else
- arg.v_uint64 = g_value_get_uint64 (&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_gtype (&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);
+ /* Fast path basic types which don't need GI type info. */
+ py_value = pygi_value_to_py_basic_type (&value, fundamental, &handled);
+ if (handled) {
+ goto out;
+ }
- g_base_info_unref (info);
+ /* Attempt to marshal through GI.
+ * The owner_type of the pspec gives us the exact type that introduced the
+ * property, even if it is a parent class of the instance in question. */
+ property_info = _pygi_lookup_property_from_g_type (pspec->owner_type, pspec->name);
+ if (property_info) {
+ GITypeInfo *type_info = NULL;
+ gboolean free_array = FALSE;
+ GIArgument arg = { 0, };
+ GITransfer transfer = GI_TRANSFER_NOTHING;
+
+ type_info = g_property_info_get_type (property_info);
+ arg = _pygi_argument_from_g_value (&value, type_info);
+
+ /* Arrays are special cased, see note in _pygi_argument_to_array. */
+ if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) {
+ arg.v_pointer = _pygi_argument_to_array (&arg, NULL, NULL, NULL,
+ type_info, &free_array);
+ } else if (g_type_is_a (pspec->value_type, G_TYPE_BOXED)) {
+ arg.v_pointer = g_value_dup_boxed (&value);
+ transfer = GI_TRANSFER_EVERYTHING;
+ }
- switch (info_type) {
- case GI_INFO_TYPE_ENUM:
- arg.v_int = 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:
+ py_value = _pygi_argument_to_object (&arg, type_info, transfer);
- if (g_type_is_a (type, G_TYPE_BOXED)) {
- arg.v_pointer = g_value_dup_boxed (&value);
- } else if (g_type_is_a (type, G_TYPE_POINTER)) {
- arg.v_pointer = g_value_get_pointer (&value);
- } else if (g_type_is_a (type, G_TYPE_VARIANT)) {
- arg.v_pointer = g_value_get_variant (&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_or_dup_boxed (&value, transfer);
- break;
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- if (G_VALUE_HOLDS_BOXED(&value))
- arg.v_pointer = g_value_get_or_dup_boxed (&value, transfer);
- else
- arg.v_pointer = g_value_get_pointer (&value);
- break;
- case GI_TYPE_TAG_ARRAY:
- {
- gchar** strings;
- GArray *arg_items;
- int i;
-
- strings = g_value_get_or_dup_boxed (&value, transfer);
- if (strings == NULL)
- arg.v_pointer = NULL;
- else {
- arg_items = g_array_sized_new (TRUE, TRUE, sizeof (GIArgument), g_strv_length (strings));
- g_array_set_size (arg_items, g_strv_length (strings));
- for (i = 0; strings[i] != NULL; ++i) {
- g_array_index (arg_items, GIArgument, i).v_string = strings[i];
- }
- arg.v_pointer = arg_items;
- }
- break;
+ if (free_array) {
+ g_array_free (arg.v_pointer, FALSE);
}
- 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;
+
+ g_base_info_unref (type_info);
+ g_base_info_unref (property_info);
}
- py_value = _pygi_argument_to_object (&arg, type_info, transfer);
- g_value_unset (&value);
+ /* Fallback to GValue marshalling. */
+ if (py_value == NULL) {
+ py_value = pyg_param_gvalue_as_pyobject (&value, TRUE, pspec);
+ }
out:
- if (property_info != NULL)
- g_base_info_unref (property_info);
- if (type_info != NULL)
- g_base_info_unref (type_info);
-
+ g_value_unset (&value);
return py_value;
}
+PyObject *
+pygi_get_property_value_by_name (PyGObject *self, gchar *param_name)
+{
+ GParamSpec *pspec;
+
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS(self->obj),
+ param_name);
+ if (!pspec) {
+ PyErr_Format (PyExc_TypeError,
+ "object of type `%s' does not have property `%s'",
+ g_type_name (G_OBJECT_TYPE (self->obj)), param_name);
+ return NULL;
+ }
+
+ return pygi_get_property_value (self, pspec);
+}
+
gint
-pygi_set_property_value_real (PyGObject *instance,
- GParamSpec *pspec,
- PyObject *py_value)
+pygi_set_property_value (PyGObject *instance,
+ GParamSpec *pspec,
+ PyObject *py_value)
{
GIPropertyInfo *property_info = NULL;
GITypeInfo *type_info = NULL;
@@ -302,7 +236,7 @@ pygi_set_property_value_real (PyGObject *instance,
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
- // FIXME: Lots of types still unhandled
+ /* FIXME: Lots of types still unhandled */
type_tag = g_type_info_get_tag (type_info);
switch (type_tag) {
case GI_TYPE_TAG_INTERFACE:
@@ -321,6 +255,9 @@ pygi_set_property_value_real (PyGObject *instance,
case GI_INFO_TYPE_ENUM:
g_value_set_enum (&value, arg.v_int);
break;
+ case GI_INFO_TYPE_FLAGS:
+ g_value_set_flags (&value, arg.v_uint);
+ break;
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_OBJECT:
g_value_set_object (&value, arg.v_pointer);
@@ -411,7 +348,7 @@ pygi_set_property_value_real (PyGObject *instance,
*/
GArray *arg_items = (GArray*) arg.v_pointer;
gchar** strings;
- int i;
+ guint i;
if (arg_items == NULL)
goto out;
diff --git a/gi/pygi-property.h b/gi/pygi-property.h
index 875d21e..d641b01 100644
--- a/gi/pygi-property.h
+++ b/gi/pygi-property.h
@@ -27,13 +27,22 @@
#include <Python.h>
#include <girepository.h>
-#include "pygi.h"
+#include "pygobject-internal.h"
-PyObject *pygi_get_property_value_real (PyGObject *instance,
- GParamSpec *pspec);
+PyObject *
+pygi_get_property_value (PyGObject *instance,
+ GParamSpec *pspec);
-gint pygi_set_property_value_real (PyGObject *instance,
- GParamSpec *pspec,
- PyObject *py_value);
+PyObject *
+pygi_get_property_value_by_name (PyGObject *self,
+ gchar *param_name);
+PyObject *
+pygi_call_do_get_property (PyObject *instance,
+ GParamSpec *pspec);
+
+gint
+pygi_set_property_value (PyGObject *instance,
+ GParamSpec *pspec,
+ PyObject *py_value);
#endif /* __PYGI_PROPERTY_H__ */
diff --git a/gi/pygi-repository.c b/gi/pygi-repository.c
index d7c65f5..07fdc8f 100644
--- a/gi/pygi-repository.c
+++ b/gi/pygi-repository.c
@@ -16,18 +16,17 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
-
-#include <pyglib-python-compat.h>
+#include "pygi-repository.h"
+#include "pygi-info.h"
+#include "pygi-basictype.h"
+#include "pygi-util.h"
PyObject *PyGIRepositoryError;
-PYGLIB_DEFINE_TYPE("gi.Repository", PyGIRepository_Type, PyGIRepository);
+PYGI_DEFINE_TYPE("gi.Repository", PyGIRepository_Type, PyGIRepository);
static PyObject *
_wrap_g_irepository_enumerate_versions (PyGIRepository *self,
@@ -48,7 +47,7 @@ _wrap_g_irepository_enumerate_versions (PyGIRepository *self,
ret = PyList_New(0);
for (item = versions; item; item = item->next) {
char *version = item->data;
- PyObject *py_version = PYGLIB_PyUnicode_FromString (version);
+ PyObject *py_version = pygi_utf8_to_py (version);
PyList_Append(ret, py_version);
Py_DECREF(py_version);
g_free (version);
@@ -110,6 +109,24 @@ _wrap_g_irepository_require (PyGIRepository *self,
}
static PyObject *
+_wrap_g_irepository_is_registered (PyGIRepository *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "namespace", "version", NULL };
+ const char *namespace_;
+ const char *version = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|z:Repository.is_registered",
+ kwlist, &namespace_, &version)) {
+ return NULL;
+ }
+
+ return pygi_gboolean_to_py (g_irepository_is_registered (self->repository,
+ namespace_, version));
+}
+
+static PyObject *
_wrap_g_irepository_find_by_name (PyGIRepository *self,
PyObject *args,
PyObject *kwargs)
@@ -164,7 +181,7 @@ _wrap_g_irepository_get_infos (PyGIRepository *self,
const char *namespace_;
gssize n_infos;
PyObject *infos;
- gssize i;
+ gint i;
if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.get_infos",
kwlist, &namespace_)) {
@@ -221,7 +238,7 @@ _wrap_g_irepository_get_typelib_path (PyGIRepository *self,
return NULL;
}
- return PYGLIB_PyBytes_FromString (typelib_path);
+ return pygi_filename_to_py (typelib_path);
}
static PyObject *
@@ -244,7 +261,7 @@ _wrap_g_irepository_get_version (PyGIRepository *self,
return NULL;
}
- return PYGLIB_PyUnicode_FromString (version);
+ return pygi_utf8_to_py (version);
}
static PyObject *
@@ -258,7 +275,7 @@ _wrap_g_irepository_get_loaded_namespaces (PyGIRepository *self)
py_namespaces = PyList_New (0);
for (i = 0; namespaces[i] != NULL; i++) {
- PyObject *py_namespace = PYGLIB_PyUnicode_FromString (namespaces[i]);
+ PyObject *py_namespace = pygi_utf8_to_py (namespaces[i]);
PyList_Append (py_namespaces, py_namespace);
Py_DECREF(py_namespace);
g_free (namespaces[i]);
@@ -269,6 +286,74 @@ _wrap_g_irepository_get_loaded_namespaces (PyGIRepository *self)
return py_namespaces;
}
+static PyObject *
+_wrap_g_irepository_get_dependencies (PyGIRepository *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "namespace", NULL };
+ const char *namespace_;
+ char **namespaces;
+ PyObject *py_namespaces;
+ gssize i;
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+ "s:Repository.get_dependencies", kwlist, &namespace_)) {
+ return NULL;
+ }
+
+ py_namespaces = PyList_New (0);
+ /* Returns NULL in case of no dependencies */
+ namespaces = g_irepository_get_dependencies (self->repository, namespace_);
+ if (namespaces == NULL) {
+ return py_namespaces;
+ }
+
+ for (i = 0; namespaces[i] != NULL; i++) {
+ PyObject *py_namespace = pygi_utf8_to_py (namespaces[i]);
+ PyList_Append (py_namespaces, py_namespace);
+ Py_DECREF(py_namespace);
+ }
+
+ g_strfreev (namespaces);
+
+ return py_namespaces;
+}
+
+
+static PyObject *
+_wrap_g_irepository_get_immediate_dependencies (PyGIRepository *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "namespace", NULL };
+ const char *namespace_;
+ char **namespaces;
+ PyObject *py_namespaces;
+ gssize i;
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+ "s:Repository.get_immediate_dependencies",
+ kwlist, &namespace_)) {
+ return NULL;
+ }
+
+ py_namespaces = PyList_New (0);
+ namespaces = g_irepository_get_immediate_dependencies (self->repository,
+ namespace_);
+
+ for (i = 0; namespaces[i] != NULL; i++) {
+ PyObject *py_namespace = pygi_utf8_to_py (namespaces[i]);
+ PyList_Append (py_namespaces, py_namespace);
+ Py_DECREF (py_namespace);
+ }
+
+ g_strfreev (namespaces);
+
+ return py_namespaces;
+}
+
+
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 },
@@ -278,28 +363,41 @@ static PyMethodDef _PyGIRepository_methods[] = {
{ "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 },
{ "get_loaded_namespaces", (PyCFunction) _wrap_g_irepository_get_loaded_namespaces, METH_NOARGS },
+ { "get_dependencies", (PyCFunction) _wrap_g_irepository_get_dependencies, METH_VARARGS | METH_KEYWORDS },
+ { "get_immediate_dependencies", (PyCFunction) _wrap_g_irepository_get_immediate_dependencies, METH_VARARGS | METH_KEYWORDS },
+ { "is_registered", (PyCFunction) _wrap_g_irepository_is_registered, METH_VARARGS | METH_KEYWORDS },
{ NULL, NULL, 0 }
};
-void
-_pygi_repository_register_types (PyObject *m)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_repository_register_types (PyObject *m)
{
- Py_TYPE(&PyGIRepository_Type) = &PyType_Type;
+ Py_SET_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 (PyType_Ready (&PyGIRepository_Type) < 0)
+ return -1;
- if (PyModule_AddObject (m, "Repository", (PyObject *) &PyGIRepository_Type)) {
- return;
+ Py_INCREF ((PyObject *) &PyGIRepository_Type);
+ if (PyModule_AddObject (m, "Repository", (PyObject *) &PyGIRepository_Type) < 0) {
+ Py_DECREF ((PyObject *) &PyGIRepository_Type);
+ return -1;
}
PyGIRepositoryError = PyErr_NewException ("gi.RepositoryError", NULL, NULL);
- if (PyModule_AddObject (m, "RepositoryError", PyGIRepositoryError)) {
- return;
+ if (PyGIRepositoryError == NULL)
+ return -1;
+
+ Py_INCREF (PyGIRepositoryError);
+ if (PyModule_AddObject (m, "RepositoryError", PyGIRepositoryError) < 0) {
+ Py_DECREF (PyGIRepositoryError);
+ return -1;
}
-}
+ return 0;
+}
diff --git a/gi/pygi-repository.h b/gi/pygi-repository.h
index d8eb8cf..2207de3 100644
--- a/gi/pygi-repository.h
+++ b/gi/pygi-repository.h
@@ -14,25 +14,29 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_REPOSITORY_H__
#define __PYGI_REPOSITORY_H__
#include <Python.h>
+#include <girepository.h>
G_BEGIN_DECLS
+typedef struct {
+ PyObject_HEAD
+ GIRepository *repository;
+} PyGIRepository;
+
/* Private */
extern PyTypeObject PyGIRepository_Type;
extern PyObject *PyGIRepositoryError;
-void _pygi_repository_register_types (PyObject *m);
+int pygi_repository_register_types (PyObject *m);
G_END_DECLS
diff --git a/gi/pygi-resulttuple.c b/gi/pygi-resulttuple.c
new file mode 100644
index 0000000..93170ea
--- /dev/null
+++ b/gi/pygi-resulttuple.c
@@ -0,0 +1,368 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2015 Christoph Reiter <reiter.christoph@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include <glib.h>
+#include "pygi-resulttuple.h"
+#include "pygi-util.h"
+
+static char repr_format_key[] = "__repr_format";
+static char tuple_indices_key[] = "__tuple_indices";
+
+#define PYGI_USE_FREELIST
+
+#ifdef PYPY_VERSION
+#undef PYGI_USE_FREELIST
+#endif
+
+#ifdef PYGI_USE_FREELIST
+/* A free list similar to the one used for the CPython tuple. Difference
+ * is that zero length tuples aren't cached (as we don't need them)
+ * and that the freelist is smaller as we don't free it with the cyclic GC
+ * as CPython does. This wastes 21kB max.
+ */
+#define PyGIResultTuple_MAXSAVESIZE 10
+#define PyGIResultTuple_MAXFREELIST 100
+static PyObject *free_list[PyGIResultTuple_MAXSAVESIZE];
+static int numfree[PyGIResultTuple_MAXSAVESIZE];
+#endif
+
+PYGI_DEFINE_TYPE ("gi._gi.ResultTuple", PyGIResultTuple_Type, PyTupleObject)
+
+/**
+ * ResultTuple.__repr__() implementation.
+ * Takes the _ResultTuple.__repr_format format string and applies the tuple
+ * values to it.
+ */
+static PyObject*
+resulttuple_repr(PyObject *self) {
+ PyObject *format, *repr, *format_attr;
+
+ format_attr = PyUnicode_FromString (repr_format_key);
+ format = PyTuple_Type.tp_getattro (self, format_attr);
+ Py_DECREF (format_attr);
+ if (format == NULL)
+ return NULL;
+ repr = PyUnicode_Format (format, self);
+ Py_DECREF (format);
+ return repr;
+}
+
+/**
+ * PyGIResultTuple_Type.tp_getattro implementation.
+ * Looks up the tuple index in _ResultTuple.__tuple_indices and returns the
+ * tuple item.
+ */
+static PyObject*
+resulttuple_getattro(PyObject *self, PyObject *name) {
+ PyObject *mapping, *index, *mapping_attr, *item;
+
+ mapping_attr = PyUnicode_FromString (tuple_indices_key);
+ mapping = PyTuple_Type.tp_getattro (self, mapping_attr);
+ Py_DECREF (mapping_attr);
+ if (mapping == NULL)
+ return NULL;
+ g_assert (PyDict_Check (mapping));
+ index = PyDict_GetItem (mapping, name);
+
+ if (index != NULL) {
+ item = PyTuple_GET_ITEM (self, PyLong_AsSsize_t (index));
+ Py_INCREF (item);
+ } else {
+ item = PyTuple_Type.tp_getattro (self, name);
+ }
+ Py_DECREF (mapping);
+
+ return item;
+}
+
+/**
+ * ResultTuple.__reduce__() implementation.
+ * Always returns (tuple, tuple(self))
+ * Needed so that pickling doesn't depend on our tuple subclass and unpickling
+ * works without it. As a result unpickle will give back in a normal tuple.
+ */
+static PyObject *
+resulttuple_reduce(PyObject *self)
+{
+ PyObject *tuple = PySequence_Tuple (self);
+ if (tuple == NULL)
+ return NULL;
+ return Py_BuildValue ("(O, (N))", &PyTuple_Type, tuple);
+}
+
+/**
+ * Extends __dir__ with the extra attributes accessible through
+ * resulttuple_getattro()
+ */
+static PyObject *
+resulttuple_dir(PyObject *self)
+{
+ PyObject *mapping_attr;
+ PyObject *items = NULL;
+ PyObject *mapping = NULL;
+ PyObject *mapping_values = NULL;
+ PyObject *result = NULL;
+
+ mapping_attr = PyUnicode_FromString (tuple_indices_key);
+ mapping = PyTuple_Type.tp_getattro (self, mapping_attr);
+ Py_DECREF (mapping_attr);
+ if (mapping == NULL)
+ goto error;
+ items = PyObject_Dir ((PyObject*)Py_TYPE (self));
+ if (items == NULL)
+ goto error;
+ mapping_values = PyDict_Keys (mapping);
+ if (mapping_values == NULL)
+ goto error;
+ result = PySequence_InPlaceConcat (items, mapping_values);
+
+error:
+ Py_XDECREF (items);
+ Py_XDECREF (mapping);
+ Py_XDECREF (mapping_values);
+
+ return result;
+}
+
+/**
+ * resulttuple_new_type:
+ * @args: one list object containing tuple item names and None
+ *
+ * Exposes pygi_resulttuple_new_type() as ResultTuple._new_type()
+ * to allow creation of result types for unit tests.
+ *
+ * Returns: A new PyTypeObject which is a subclass of PyGIResultTuple_Type
+ * or %NULL in case of an error.
+ */
+static PyObject *
+resulttuple_new_type(PyObject *self, PyObject *args) {
+ PyObject *tuple_names, *new_type;
+
+ if (!PyArg_ParseTuple (args, "O:ResultTuple._new_type", &tuple_names))
+ return NULL;
+
+ if (!PyList_Check (tuple_names)) {
+ PyErr_SetString (PyExc_TypeError, "not a list");
+ return NULL;
+ }
+
+ new_type = (PyObject *)pygi_resulttuple_new_type (tuple_names);
+ return new_type;
+}
+
+static PyMethodDef resulttuple_methods[] = {
+ {"__reduce__", (PyCFunction)resulttuple_reduce, METH_NOARGS},
+ {"__dir__", (PyCFunction)resulttuple_dir, METH_NOARGS},
+ {"_new_type", (PyCFunction)resulttuple_new_type,
+ METH_VARARGS | METH_STATIC},
+ {NULL, NULL, 0},
+};
+
+/**
+ * pygi_resulttuple_new_type:
+ * @tuple_names: A python list containing str or None items.
+ *
+ * Similar to namedtuple() creates a new tuple subclass which
+ * allows to access items by name and have a pretty __repr__.
+ * Each item in the passed name list corresponds to an item with
+ * the same index in the tuple class. If the name is None the item/index
+ * is unnamed.
+ *
+ * Returns: A new PyTypeObject which is a subclass of PyGIResultTuple_Type
+ * or %NULL in case of an error.
+ */
+PyTypeObject*
+pygi_resulttuple_new_type(PyObject *tuple_names) {
+ PyTypeObject *new_type;
+ PyObject *class_dict, *format_string, *empty_format, *named_format,
+ *format_list, *sep, *index_dict, *slots, *paren_format, *new_type_args,
+ *paren_string;
+ Py_ssize_t len, i;
+
+ g_assert (PyList_Check (tuple_names));
+
+ class_dict = PyDict_New ();
+
+ /* To save some memory don't use an instance dict */
+ slots = PyTuple_New (0);
+ PyDict_SetItemString (class_dict, "__slots__", slots);
+ Py_DECREF (slots);
+
+ format_list = PyList_New (0);
+ index_dict = PyDict_New ();
+
+ empty_format = PyUnicode_FromString ("%r");
+ named_format = PyUnicode_FromString ("%s=%%r");
+ len = PyList_Size (tuple_names);
+ for (i = 0; i < len; i++) {
+ PyObject *item, *named_args, *named_build, *index;
+ item = PyList_GET_ITEM (tuple_names, i);
+ if (item == Py_None) {
+ PyList_Append (format_list, empty_format);
+ } else {
+ named_args = Py_BuildValue ("(O)", item);
+ named_build = PyUnicode_Format (named_format, named_args);
+ Py_DECREF (named_args);
+ PyList_Append (format_list, named_build);
+ Py_DECREF (named_build);
+ index = PyLong_FromSsize_t (i);
+ PyDict_SetItem (index_dict, item, index);
+ Py_DECREF (index);
+ }
+ }
+ Py_DECREF (empty_format);
+ Py_DECREF (named_format);
+
+ sep = PyUnicode_FromString (", ");
+ format_string = PyObject_CallMethod (sep, "join", "O", format_list);
+ Py_DECREF (sep);
+ Py_DECREF (format_list);
+ paren_format = PyUnicode_FromString ("(%s)");
+ paren_string = PyUnicode_Format (paren_format, format_string);
+ Py_DECREF (paren_format);
+ Py_DECREF (format_string);
+
+ PyDict_SetItemString (class_dict, repr_format_key, paren_string);
+ Py_DECREF (paren_string);
+
+ PyDict_SetItemString (class_dict, tuple_indices_key, index_dict);
+ Py_DECREF (index_dict);
+
+ new_type_args = Py_BuildValue ("s(O)O", "_ResultTuple",
+ &PyGIResultTuple_Type, class_dict);
+ new_type = (PyTypeObject *)PyType_Type.tp_new (&PyType_Type,
+ new_type_args, NULL);
+ Py_DECREF (new_type_args);
+ Py_DECREF (class_dict);
+
+ if (new_type != NULL) {
+ /* disallow subclassing as that would break the free list caching
+ * since we assume that all subclasses use PyTupleObject */
+ new_type->tp_flags &= ~Py_TPFLAGS_BASETYPE;
+ }
+
+ return new_type;
+}
+
+
+/**
+ * pygi_resulttuple_new:
+ * @subclass: A PyGIResultTuple_Type subclass which will be the type of the
+ * returned instance.
+ * @len: Length of the returned tuple
+ *
+ * Like PyTuple_New(). Return an uninitialized tuple of the given @length.
+ *
+ * Returns: An instance of @subclass or %NULL on error.
+ */
+PyObject *
+pygi_resulttuple_new(PyTypeObject *subclass, Py_ssize_t len) {
+#ifdef PYGI_USE_FREELIST
+ PyObject *self;
+ Py_ssize_t i;
+
+ /* Check the free list for a tuple object with the needed size;
+ * clear it and change the class to ours.
+ */
+ if (len > 0 && len < PyGIResultTuple_MAXSAVESIZE) {
+ self = free_list[len];
+ if (self != NULL) {
+ free_list[len] = PyTuple_GET_ITEM (self, 0);
+ numfree[len]--;
+ for (i=0; i < len; i++) {
+ PyTuple_SET_ITEM (self, i, NULL);
+ }
+ Py_SET_TYPE (self, subclass);
+ Py_INCREF (subclass);
+ _Py_NewReference (self);
+ PyObject_GC_Track (self);
+ return self;
+ }
+ }
+#endif
+
+ /* For zero length tuples and in case the free list is empty, alloc
+ * as usual.
+ */
+ return subclass->tp_alloc (subclass, len);
+}
+
+#ifdef PYGI_USE_FREELIST
+static void resulttuple_dealloc(PyObject *self) {
+ Py_ssize_t i, len;
+
+ PyObject_GC_UnTrack (self);
+ CPy_TRASHCAN_BEGIN (self, resulttuple_dealloc)
+
+ /* Free the tuple items and, if there is space, save the tuple object
+ * pointer to the front of the free list for its size. Otherwise free it.
+ */
+ len = Py_SIZE (self);
+ if (len > 0) {
+ for (i=0; i < len; i++) {
+ Py_XDECREF (PyTuple_GET_ITEM (self, i));
+ }
+
+ if (len < PyGIResultTuple_MAXSAVESIZE && numfree[len] < PyGIResultTuple_MAXFREELIST) {
+ PyTuple_SET_ITEM (self, 0, free_list[len]);
+ numfree[len]++;
+ free_list[len] = self;
+ goto done;
+ }
+ }
+
+ Py_TYPE (self)->tp_free (self);
+
+done:
+ CPy_TRASHCAN_END (self)
+}
+#endif
+
+/**
+ * pygi_resulttuple_register_types:
+ * @module: A Python modules to which ResultTuple gets added to.
+ *
+ * Initializes the ResultTuple class and adds it to the passed @module.
+ *
+ * Returns: -1 on error, 0 on success.
+ */
+int pygi_resulttuple_register_types(PyObject *module) {
+
+ PyGIResultTuple_Type.tp_base = &PyTuple_Type;
+ PyGIResultTuple_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
+ PyGIResultTuple_Type.tp_repr = (reprfunc)resulttuple_repr;
+ PyGIResultTuple_Type.tp_getattro = (getattrofunc)resulttuple_getattro;
+ PyGIResultTuple_Type.tp_methods = resulttuple_methods;
+#ifdef PYGI_USE_FREELIST
+ PyGIResultTuple_Type.tp_dealloc = (destructor)resulttuple_dealloc;
+#endif
+
+ if (PyType_Ready (&PyGIResultTuple_Type) < 0)
+ return -1;
+
+ Py_INCREF (&PyGIResultTuple_Type);
+ if (PyModule_AddObject (module, "ResultTuple",
+ (PyObject *)&PyGIResultTuple_Type) < 0) {
+ Py_DECREF (&PyGIResultTuple_Type);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/gi/_gobject/pygenum.h b/gi/pygi-resulttuple.h
index 0558831..3f63ca0 100644
--- a/gi/_gobject/pygenum.h
+++ b/gi/pygi-resulttuple.h
@@ -1,7 +1,7 @@
/* -*- Mode: C; c-basic-offset: 4 -*-
- * pygtk- Python bindings for the GTK toolkit.
- * Copyright (C) 1998-2003 James Henstridge
- * 2004-2008 Johan Dahlin
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2015 Christoph Reiter <reiter.christoph@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -14,14 +14,21 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __PYGOBJECT_ENUM_H__
-#define __PYGOBJECT_ENUM_H__
+#ifndef __PYGI_RESULTTUPLE_H__
+#define __PYGI_RESULTTUPLE_H__
+
+#include "Python.h"
+
+int
+pygi_resulttuple_register_types (PyObject *d);
+
+PyTypeObject *
+pygi_resulttuple_new_type (PyObject *tuple_names);
-void pygobject_enum_register_types(PyObject *d);
+PyObject*
+pygi_resulttuple_new (PyTypeObject *subclass, Py_ssize_t len);
-#endif /* __PYGOBJECT_ENUM_H__ */
+#endif /* __PYGI_RESULTTUPLE_H__ */
diff --git a/gi/pygi-signal-closure.c b/gi/pygi-signal-closure.c
index bcd1320..d553d76 100644
--- a/gi/pygi-signal-closure.c
+++ b/gi/pygi-signal-closure.c
@@ -13,12 +13,13 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include "pygi-signal-closure.h"
+#include "pygi-value.h"
+#include "pygi-argument.h"
+#include "pygi-boxed.h"
static GISignalInfo *
_pygi_lookup_signal_from_g_type (GType g_type,
@@ -80,11 +81,14 @@ pygi_signal_closure_marshal(GClosure *closure,
GISignalInfo *signal_info;
gint n_sig_info_args;
gint sig_info_highest_arg;
+ GSList *list_item = NULL;
+ GSList *pass_by_ref_structs = NULL;
state = PyGILState_Ensure();
signal_info = ((PyGISignalClosure *)closure)->signal_info;
n_sig_info_args = g_callable_info_get_n_args(signal_info);
+ g_assert_cmpint (n_sig_info_args, >=, 0);
/* the first argument to a signal callback is instance,
but instance is not counted in the introspection data */
sig_info_highest_arg = n_sig_info_args + 1;
@@ -107,34 +111,78 @@ pygi_signal_closure_marshal(GClosure *closure,
}
PyTuple_SetItem(params, i, item);
- } else if (i < sig_info_highest_arg) {
+ } else if (i < (guint)sig_info_highest_arg) {
GIArgInfo arg_info;
GITypeInfo type_info;
- GITransfer transfer;
+ GITypeTag type_tag;
GIArgument arg = { 0, };
PyObject *item = NULL;
gboolean free_array = FALSE;
+ gboolean pass_struct_by_ref = FALSE;
g_callable_info_load_arg(signal_info, i - 1, &arg_info);
g_arg_info_load_type(&arg_info, &type_info);
- transfer = g_arg_info_get_ownership_transfer(&arg_info);
arg = _pygi_argument_from_g_value(&param_values[i], &type_info);
-
- if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ARRAY) {
+
+ type_tag = g_type_info_get_tag (&type_info);
+ if (type_tag == GI_TYPE_TAG_ARRAY) {
/* Skip the self argument of param_values */
- arg.v_pointer = _pygi_argument_to_array (&arg, NULL, param_values + 1, signal_info,
- &type_info, &free_array);
+ arg.v_pointer = _pygi_argument_to_array (&arg,
+ _pygi_argument_array_length_marshal,
+ (void *)(param_values + 1),
+ signal_info,
+ &type_info,
+ &free_array);
+ }
+
+ /* Hack to ensure struct arguments are passed-by-reference allowing
+ * callback implementors to modify the struct values. This is needed
+ * for keeping backwards compatibility and should be removed in future
+ * versions which support signal output arguments as return values.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=735486
+ *
+ * Note the logic here must match the logic path taken in _pygi_argument_to_object.
+ */
+ if (type_tag == GI_TYPE_TAG_INTERFACE) {
+ GIBaseInfo *info = g_type_info_get_interface (&type_info);
+ GIInfoType info_type = g_base_info_get_type (info);
+
+ if (info_type == GI_INFO_TYPE_STRUCT ||
+ info_type == GI_INFO_TYPE_BOXED ||
+ info_type == GI_INFO_TYPE_UNION) {
+
+ GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
+ gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) &&
+ (g_struct_info_is_foreign ((GIStructInfo *) info));
+
+ if (!is_foreign && !g_type_is_a (gtype, G_TYPE_VALUE) &&
+ g_type_is_a (gtype, G_TYPE_BOXED)) {
+ pass_struct_by_ref = TRUE;
+ }
+ }
+
+ g_base_info_unref (info);
}
-
- item = _pygi_argument_to_object (&arg, &type_info, transfer);
-
+
+ if (pass_struct_by_ref) {
+ /* transfer everything will ensure the struct is not copied when wrapped. */
+ item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_EVERYTHING);
+ if (item && PyObject_IsInstance (item, (PyObject *) &PyGIBoxed_Type)) {
+ ((PyGBoxed *)item)->free_on_dealloc = FALSE;
+ pass_by_ref_structs = g_slist_prepend (pass_by_ref_structs, item);
+ }
+
+ } else {
+ item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_NOTHING);
+ }
+
if (free_array) {
g_array_free (arg.v_pointer, FALSE);
}
-
if (item == NULL) {
+ PyErr_Print ();
goto out;
}
PyTuple_SetItem(params, i, item);
@@ -166,18 +214,35 @@ pygi_signal_closure_marshal(GClosure *closure,
}
Py_DECREF(ret);
+ /* Run through the list of structs which have been passed by reference and
+ * check if they are being held longer than the duration of the callback
+ * execution. This is determined if the ref count is greater than 1.
+ * A single ref is held by the argument list and any more would mean the callback
+ * stored a ref somewhere else. In this case we make an internal copy of
+ * the boxed struct so Python can own the memory to it.
+ */
+ list_item = pass_by_ref_structs;
+ while (list_item) {
+ PyObject *item = list_item->data;
+ if (Py_REFCNT (item) > 1) {
+ pygi_boxed_copy_in_place ((PyGIBoxed *)item);
+ }
+ list_item = g_slist_next (list_item);
+ }
+
out:
+ g_slist_free (pass_by_ref_structs);
Py_DECREF(params);
PyGILState_Release(state);
}
GClosure *
-pygi_signal_closure_new_real (PyGObject *instance,
- GType g_type,
- const gchar *signal_name,
- PyObject *callback,
- PyObject *extra_args,
- PyObject *swap_data)
+pygi_signal_closure_new (PyGObject *instance,
+ GType g_type,
+ const gchar *signal_name,
+ PyObject *callback,
+ PyObject *extra_args,
+ PyObject *swap_data)
{
GClosure *closure = NULL;
PyGISignalClosure *pygi_closure = NULL;
diff --git a/gi/pygi-signal-closure.h b/gi/pygi-signal-closure.h
index ffdd29c..9ba8d6d 100644
--- a/gi/pygi-signal-closure.h
+++ b/gi/pygi-signal-closure.h
@@ -24,7 +24,9 @@
#ifndef __PYGI_SIGNAL_CLOSURE_H__
#define __PYGI_SIGNAL_CLOSURE_H__
-#include "pygi.h"
+#include <Python.h>
+#include <girepository.h>
+#include "pygobject-internal.h"
G_BEGIN_DECLS
@@ -35,12 +37,13 @@ typedef struct _PyGISignalClosure
GISignalInfo *signal_info;
} PyGISignalClosure;
-GClosure * pygi_signal_closure_new_real (PyGObject *instance,
- GType g_type,
- const gchar *sig_name,
- PyObject *callback,
- PyObject *extra_args,
- PyObject *swap_data);
+GClosure *
+pygi_signal_closure_new (PyGObject *instance,
+ GType g_type,
+ const gchar *sig_name,
+ PyObject *callback,
+ PyObject *extra_args,
+ PyObject *swap_data);
G_END_DECLS
diff --git a/gi/pygi-source.c b/gi/pygi-source.c
index 66bbc3c..c85386d 100644
--- a/gi/pygi-source.c
+++ b/gi/pygi-source.c
@@ -23,12 +23,11 @@
* IN THE SOFTWARE.
*/
-#define NO_IMPORT
-#include "pygobject.h"
-
-#include "pygi-private.h"
-#include "pyglib.h"
-#include "pyglib-private.h"
+#include "pygi-info.h"
+#include "pygi-boxed.h"
+#include "pygi-type.h"
+#include "pygi-basictype.h"
+#include "pygboxed.h"
#include "pygi-source.h"
typedef struct
@@ -38,7 +37,7 @@ typedef struct
} PyGRealSource;
static gboolean
-pyg_source_prepare(GSource *source, gint *timeout)
+source_prepare(GSource *source, gint *timeout)
{
PyGRealSource *pysource = (PyGRealSource *)source;
PyObject *t;
@@ -46,7 +45,7 @@ pyg_source_prepare(GSource *source, gint *timeout)
gboolean got_err = TRUE;
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
t = PyObject_CallMethod(pysource->obj, "prepare", NULL);
@@ -66,13 +65,16 @@ pyg_source_prepare(GSource *source, gint *timeout)
goto bail;
}
- ret = PyObject_IsTrue(PyTuple_GET_ITEM(t, 0));
- *timeout = PYGLIB_PyLong_AsLong(PyTuple_GET_ITEM(t, 1));
+ if (!pygi_gboolean_from_py (PyTuple_GET_ITEM(t, 0), &ret)) {
+ ret = FALSE;
+ goto bail;
+ }
- if (*timeout == -1 && PyErr_Occurred()) {
- ret = FALSE;
- goto bail;
- }
+ if (!pygi_gint_from_py (PyTuple_GET_ITEM(t, 1), timeout))
+ {
+ ret = FALSE;
+ goto bail;
+ }
got_err = FALSE;
@@ -82,20 +84,20 @@ bail:
Py_XDECREF(t);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return ret;
}
static gboolean
-pyg_source_check(GSource *source)
+source_check(GSource *source)
{
PyGRealSource *pysource = (PyGRealSource *)source;
PyObject *t;
gboolean ret;
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
t = PyObject_CallMethod(pysource->obj, "check", NULL);
@@ -107,20 +109,20 @@ pyg_source_check(GSource *source)
Py_DECREF(t);
}
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return ret;
}
static gboolean
-pyg_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
+source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
{
PyGRealSource *pysource = (PyGRealSource *)source;
PyObject *func, *args, *tuple, *t;
gboolean ret;
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
if (callback) {
tuple = user_data;
@@ -142,19 +144,19 @@ pyg_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
Py_DECREF(t);
}
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return ret;
}
static void
-pyg_source_finalize(GSource *source)
+source_finalize(GSource *source)
{
PyGRealSource *pysource = (PyGRealSource *)source;
PyObject *func, *t;
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
func = PyObject_GetAttrString(pysource->obj, "finalize");
if (func) {
@@ -166,24 +168,71 @@ pyg_source_finalize(GSource *source)
} else {
Py_DECREF(t);
}
+ } else {
+ PyErr_Clear ();
}
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
}
static GSourceFuncs pyg_source_funcs =
{
- pyg_source_prepare,
- pyg_source_check,
- pyg_source_dispatch,
- pyg_source_finalize
+ source_prepare,
+ source_check,
+ source_dispatch,
+ source_finalize
};
+/**
+ * _pyglib_destroy_notify:
+ * @user_data: a PyObject pointer.
+ *
+ * A function that can be used as a GDestroyNotify callback that will
+ * call Py_DECREF on the data.
+ */
+static void
+destroy_notify(gpointer user_data)
+{
+ PyObject *obj = (PyObject *)user_data;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+ Py_DECREF(obj);
+ PyGILState_Release(state);
+}
+
+static gboolean
+handler_marshal(gpointer user_data)
+{
+ PyObject *tuple, *ret;
+ gboolean res;
+ PyGILState_STATE state;
+
+ g_return_val_if_fail(user_data != NULL, FALSE);
+
+ state = PyGILState_Ensure();
+
+ tuple = (PyObject *)user_data;
+ ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0),
+ PyTuple_GetItem(tuple, 1));
+ if (!ret) {
+ PyErr_Print();
+ res = FALSE;
+ } else {
+ res = PyObject_IsTrue(ret);
+ Py_DECREF(ret);
+ }
+
+ PyGILState_Release(state);
+
+ return res;
+}
+
PyObject *
-pyg_source_set_callback(PyGObject *self_module, PyObject *args)
+pygi_source_set_callback (PyGObject *self_module, PyObject *args)
{
PyObject *self, *first, *callback, *cbargs = NULL, *data;
- gint len;
+ Py_ssize_t len;
len = PyTuple_Size (args);
if (len < 2) {
@@ -218,30 +267,42 @@ pyg_source_set_callback(PyGObject *self_module, PyObject *args)
return NULL;
g_source_set_callback(pyg_boxed_get (self, GSource),
- _pyglib_handler_marshal, data,
- _pyglib_destroy_notify);
+ handler_marshal, data,
+ destroy_notify);
Py_INCREF(Py_None);
return Py_None;
}
/**
- * pyg_source_new:
+ * pygi_source_new:
*
* Wrap the un-bindable g_source_new() and provide wrapper callbacks in the
* GSourceFuncs which call back to Python.
+ *
+ * Returns NULL on error and sets an exception.
*/
PyObject*
-pyg_source_new (void)
+pygi_source_new (PyObject *self, PyObject *args)
{
- PyGRealSource *source = NULL;
- PyObject *py_type;
+ PyGRealSource *source;
+ PyObject *py_type, *boxed;
- source = (PyGRealSource*) g_source_new (&pyg_source_funcs, sizeof (PyGRealSource));
+ g_assert (args == NULL);
+
+ py_type = pygi_type_import_by_name ("GLib", "Source");
+ if (!py_type)
+ return NULL;
- py_type = _pygi_type_import_by_name ("GLib", "Source");
+ source = (PyGRealSource*) g_source_new (&pyg_source_funcs, sizeof (PyGRealSource));
/* g_source_new uses malloc, not slices */
- source->obj = _pygi_boxed_new ( (PyTypeObject *) py_type, source, FALSE, 0);
+ boxed = pygi_boxed_new ( (PyTypeObject *) py_type, source, TRUE, 0);
+ Py_DECREF (py_type);
+ if (!boxed) {
+ g_source_unref ((GSource *)source);
+ return NULL;
+ }
+ source->obj = boxed;
return source->obj;
}
diff --git a/gi/pygi-source.h b/gi/pygi-source.h
index a602767..5d60c63 100644
--- a/gi/pygi-source.h
+++ b/gi/pygi-source.h
@@ -24,8 +24,8 @@
#ifndef __PYGI_SOURCE_H__
#define __PYGI_SOURCE_H__
-PyObject *pyg_source_new (void);
-PyObject *pyg_source_set_callback (PyGObject *self, PyObject *args);
+PyObject *pygi_source_new (PyObject *self, PyObject *args);
+PyObject *pygi_source_set_callback (PyGObject *self, PyObject *args);
#endif /* __PYGI_SOURCE_H__ */
diff --git a/gi/pygi-struct-marshal.c b/gi/pygi-struct-marshal.c
new file mode 100644
index 0000000..885f5d7
--- /dev/null
+++ b/gi/pygi-struct-marshal.c
@@ -0,0 +1,646 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include <glib.h>
+
+#include "pygi-struct-marshal.h"
+#include "pygi-struct.h"
+#include "pygi-foreign.h"
+#include "pygi-value.h"
+#include "pygi-type.h"
+#include "pygi-boxed.h"
+#include "pygi-info.h"
+#include "pygpointer.h"
+#include "pygboxed.h"
+#include "pygi-type.h"
+
+/*
+ * _is_union_member - check to see if the py_arg is actually a member of the
+ * expected C union
+ */
+static gboolean
+_is_union_member (GIInterfaceInfo *interface_info, PyObject *py_arg) {
+ gint i;
+ gint n_fields;
+ GIUnionInfo *union_info;
+ GIInfoType info_type;
+ gboolean is_member = FALSE;
+
+ info_type = g_base_info_get_type (interface_info);
+
+ if (info_type != GI_INFO_TYPE_UNION)
+ return FALSE;
+
+ union_info = (GIUnionInfo *) interface_info;
+ n_fields = g_union_info_get_n_fields (union_info);
+
+ for (i = 0; i < n_fields; i++) {
+ GIFieldInfo *field_info;
+ GITypeInfo *field_type_info;
+
+ field_info = g_union_info_get_field (union_info, i);
+ field_type_info = g_field_info_get_type (field_info);
+
+ /* we can only check if the members are interfaces */
+ if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) {
+ GIInterfaceInfo *field_iface_info;
+ PyObject *py_type;
+
+ field_iface_info = g_type_info_get_interface (field_type_info);
+ py_type = pygi_type_import_by_gi_info ((GIBaseInfo *) field_iface_info);
+
+ if (py_type != NULL && PyObject_IsInstance (py_arg, py_type)) {
+ is_member = TRUE;
+ }
+
+ Py_XDECREF (py_type);
+ g_base_info_unref ( ( GIBaseInfo *) field_iface_info);
+ }
+
+ g_base_info_unref ( ( GIBaseInfo *) field_type_info);
+ g_base_info_unref ( ( GIBaseInfo *) field_info);
+
+ if (is_member)
+ break;
+ }
+
+ return is_member;
+}
+
+
+/*
+ * GValue from Python
+ */
+
+/* pygi_arg_gvalue_from_py_marshal:
+ * py_arg: (in):
+ * arg: (out):
+ * transfer:
+ * copy_reference: TRUE if arg should use the pointer reference held by py_arg
+ * when it is already holding a GValue vs. copying the value.
+ */
+gboolean
+pygi_arg_gvalue_from_py_marshal (PyObject *py_arg,
+ GIArgument *arg,
+ GITransfer transfer,
+ gboolean copy_reference) {
+ GValue *value;
+ GType object_type;
+
+ object_type = pyg_type_from_object_strict ( (PyObject *) Py_TYPE (py_arg), FALSE);
+ if (object_type == G_TYPE_INVALID) {
+ PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
+ return FALSE;
+ }
+
+ /* if already a gvalue, use that, else marshal into gvalue */
+ if (object_type == G_TYPE_VALUE) {
+ GValue *source_value = pyg_boxed_get (py_arg, GValue);
+ if (copy_reference) {
+ value = source_value;
+ } else {
+ value = g_slice_new0 (GValue);
+ g_value_init (value, G_VALUE_TYPE (source_value));
+ g_value_copy (source_value, value);
+ }
+ } else {
+ value = g_slice_new0 (GValue);
+ g_value_init (value, object_type);
+ if (pyg_value_from_pyobject_with_error (value, py_arg) < 0) {
+ g_slice_free (GValue, value);
+ return FALSE;
+ }
+ }
+
+ arg->v_pointer = value;
+ return TRUE;
+}
+
+void
+pygi_arg_gvalue_from_py_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ /* Note py_arg can be NULL for hash table which is a bug. */
+ if (was_processed && py_arg != NULL) {
+ GType py_object_type =
+ pyg_type_from_object_strict ( (PyObject *) Py_TYPE (py_arg), FALSE);
+
+ /* When a GValue was not passed, it means the marshalers created a new
+ * one to pass in, clean this up.
+ */
+ if (py_object_type != G_TYPE_VALUE) {
+ g_value_unset ((GValue *) data);
+ g_slice_free (GValue, data);
+ }
+ }
+}
+
+/* pygi_arg_gclosure_from_py_marshal:
+ * py_arg: (in):
+ * arg: (out):
+ */
+static gboolean
+pygi_arg_gclosure_from_py_marshal (PyObject *py_arg,
+ GIArgument *arg,
+ GITransfer transfer)
+{
+ GClosure *closure;
+ GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE);
+
+ if ( !(PyCallable_Check(py_arg) ||
+ g_type_is_a (object_gtype, G_TYPE_CLOSURE))) {
+ PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
+ Py_TYPE (py_arg)->tp_name);
+ return FALSE;
+ }
+
+ if (g_type_is_a (object_gtype, G_TYPE_CLOSURE)) {
+ closure = (GClosure *)pyg_boxed_get (py_arg, void);
+ /* Make sure we own a ref which is held until cleanup. */
+ if (closure != NULL) {
+ g_closure_ref (closure);
+ }
+ } else {
+ PyObject *functools;
+ PyObject *partial = NULL;
+
+ functools = PyImport_ImportModule ("functools");
+ if (functools) {
+ partial = PyObject_GetAttrString (functools, "partial");
+ Py_DECREF (functools);
+ }
+
+ if (partial && PyObject_IsInstance (py_arg, partial) > 0 && PyObject_HasAttrString (py_arg, "__gtk_template__")) {
+ PyObject *partial_func;
+ PyObject *partial_args;
+ PyObject *partial_keywords;
+ PyObject *swap_data;
+
+ partial_func = PyObject_GetAttrString (py_arg, "func");
+ partial_args = PyObject_GetAttrString (py_arg, "args");
+ partial_keywords = PyObject_GetAttrString (py_arg, "keywords");
+ swap_data = PyDict_GetItemString (partial_keywords, "swap_data");
+
+ closure = pyg_closure_new (partial_func, partial_args, swap_data);
+
+ Py_DECREF (partial_func);
+ Py_DECREF (partial_args);
+ Py_DECREF (partial_keywords);
+ g_closure_ref (closure);
+ g_closure_sink (closure);
+ } else {
+ closure = pyg_closure_new (py_arg, NULL, NULL);
+ g_closure_ref (closure);
+ g_closure_sink (closure);
+ }
+
+ if (partial) {
+ Py_DECREF (partial);
+ }
+ }
+
+ if (closure == NULL) {
+ PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
+ return FALSE;
+ }
+
+ /* Add an additional ref when transfering everything to the callee. */
+ if (transfer == GI_TRANSFER_EVERYTHING) {
+ g_closure_ref (closure);
+ }
+
+ arg->v_pointer = closure;
+ return TRUE;
+}
+
+static void
+arg_gclosure_from_py_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer cleanup_data,
+ gboolean was_processed)
+{
+ if (cleanup_data != NULL) {
+ g_closure_unref (cleanup_data);
+ }
+}
+
+/* pygi_arg_struct_from_py_marshal:
+ *
+ * Dispatcher to various sub marshalers
+ */
+gboolean
+pygi_arg_struct_from_py_marshal (PyObject *py_arg,
+ GIArgument *arg,
+ const gchar *arg_name,
+ GIBaseInfo *interface_info,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean copy_reference,
+ gboolean is_foreign,
+ gboolean is_pointer)
+{
+ gboolean is_union = FALSE;
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+
+ /* FIXME: handle this large if statement in the cache
+ * and set the correct marshaller
+ */
+
+ if (g_type_is_a (g_type, G_TYPE_CLOSURE)) {
+ return pygi_arg_gclosure_from_py_marshal (py_arg, arg, transfer);
+ } else if (g_type_is_a (g_type, G_TYPE_VALUE)) {
+ return pygi_arg_gvalue_from_py_marshal(py_arg,
+ arg,
+ transfer,
+ copy_reference);
+ } else if (is_foreign) {
+ PyObject *success;
+ success = pygi_struct_foreign_convert_to_g_argument (py_arg,
+ interface_info,
+ transfer,
+ arg);
+
+ return (success == Py_None);
+ } else if (!PyObject_IsInstance (py_arg, py_type)) {
+ /* first check to see if this is a member of the expected union */
+ is_union = _is_union_member (interface_info, py_arg);
+ if (!is_union) {
+ goto type_error;
+ }
+ }
+
+ if (g_type_is_a (g_type, G_TYPE_BOXED)) {
+ /* Additionally use pyg_type_from_object to pull the stashed __gtype__
+ * attribute off of the input argument for type checking. This is needed
+ * to work around type discrepancies in cases with aliased (typedef) types.
+ * e.g. GtkAllocation, GdkRectangle.
+ * See: https://bugzilla.gnomethere are .org/show_bug.cgi?id=707140
+ */
+ if (is_union || pyg_boxed_check (py_arg, g_type) ||
+ g_type_is_a (pyg_type_from_object (py_arg), g_type)) {
+ arg->v_pointer = pyg_boxed_get (py_arg, void);
+ if (transfer == GI_TRANSFER_EVERYTHING) {
+ arg->v_pointer = g_boxed_copy (g_type, arg->v_pointer);
+ }
+ } else {
+ goto type_error;
+ }
+
+ } else if (g_type_is_a (g_type, G_TYPE_POINTER) ||
+ g_type_is_a (g_type, G_TYPE_VARIANT) ||
+ g_type == G_TYPE_NONE) {
+ g_warn_if_fail (g_type_is_a (g_type, G_TYPE_VARIANT) || !is_pointer || transfer == GI_TRANSFER_NOTHING);
+
+ if (g_type_is_a (g_type, G_TYPE_VARIANT) &&
+ pyg_type_from_object (py_arg) != G_TYPE_VARIANT) {
+ PyErr_SetString (PyExc_TypeError, "expected GLib.Variant");
+ return FALSE;
+ }
+ arg->v_pointer = pyg_pointer_get (py_arg, void);
+ if (transfer == GI_TRANSFER_EVERYTHING) {
+ g_variant_ref ((GVariant *)arg->v_pointer);
+ }
+
+ } else {
+ PyErr_Format (PyExc_NotImplementedError,
+ "structure type '%s' is not supported yet",
+ g_type_name(g_type));
+ return FALSE;
+ }
+ return TRUE;
+
+type_error:
+ {
+ gchar *type_name = _pygi_g_base_info_get_fullname (interface_info);
+ PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
+
+ PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
+ arg_name ? arg_name : "self",
+ type_name,
+ module ? PyUnicode_AsUTF8(module) : "",
+ module ? "." : "",
+ Py_TYPE (py_arg)->tp_name);
+ if (module)
+ Py_DECREF (module);
+ g_free (type_name);
+ return FALSE;
+ }
+}
+
+static gboolean
+arg_struct_from_py_marshal_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+
+ gboolean res = pygi_arg_struct_from_py_marshal (py_arg,
+ arg,
+ arg_cache->arg_name,
+ iface_cache->interface_info,
+ iface_cache->g_type,
+ iface_cache->py_type,
+ arg_cache->transfer,
+ TRUE, /*copy_reference*/
+ iface_cache->is_foreign,
+ arg_cache->is_pointer);
+
+ /* Assume struct marshaling is always a pointer and assign cleanup_data
+ * here rather than passing it further down the chain.
+ */
+ *cleanup_data = arg->v_pointer;
+ return res;
+}
+
+static void
+arg_foreign_from_py_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (state->failed && was_processed) {
+ pygi_struct_foreign_release (
+ ( (PyGIInterfaceCache *)arg_cache)->interface_info,
+ data);
+ }
+}
+
+static PyObject *
+pygi_arg_struct_to_py_marshaller (GIArgument *arg,
+ GIInterfaceInfo *interface_info,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean is_allocated,
+ gboolean is_foreign)
+{
+ PyObject *py_obj = NULL;
+
+ if (arg->v_pointer == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ if (g_type_is_a (g_type, G_TYPE_VALUE)) {
+ py_obj = pyg_value_as_pyobject (arg->v_pointer, is_allocated);
+ } else if (is_foreign) {
+ py_obj = pygi_struct_foreign_convert_from_g_argument (interface_info,
+ transfer,
+ arg->v_pointer);
+ } else if (g_type_is_a (g_type, G_TYPE_BOXED)) {
+ if (py_type) {
+ py_obj = pygi_boxed_new ((PyTypeObject *) py_type,
+ arg->v_pointer,
+ transfer == GI_TRANSFER_EVERYTHING || is_allocated,
+ is_allocated ?
+ g_struct_info_get_size(interface_info) : 0);
+ }
+ } else if (g_type_is_a (g_type, G_TYPE_POINTER)) {
+ if (py_type == NULL ||
+ !PyType_IsSubtype ((PyTypeObject *) py_type, &PyGIStruct_Type)) {
+ g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
+ py_obj = pyg_pointer_new (g_type, arg->v_pointer);
+ } else {
+ py_obj = pygi_struct_new ( (PyTypeObject *) py_type,
+ arg->v_pointer,
+ transfer == GI_TRANSFER_EVERYTHING);
+ }
+ } else if (g_type_is_a (g_type, G_TYPE_VARIANT)) {
+ /* Note: sink the variant (add a ref) only if we are not transfered ownership.
+ * GLib.Variant overrides __del__ which will then call "g_variant_unref" for
+ * cleanup in either case. */
+ if (py_type) {
+ if (transfer == GI_TRANSFER_NOTHING) {
+ g_variant_ref_sink (arg->v_pointer);
+ }
+ py_obj = pygi_struct_new ((PyTypeObject *) py_type,
+ arg->v_pointer,
+ FALSE);
+ }
+ } else if (g_type == G_TYPE_NONE) {
+ if (py_type) {
+ py_obj = pygi_struct_new ((PyTypeObject *) py_type,
+ arg->v_pointer,
+ transfer == GI_TRANSFER_EVERYTHING || is_allocated);
+ }
+ } else {
+ PyErr_Format (PyExc_NotImplementedError,
+ "structure type '%s' is not supported yet",
+ g_type_name (g_type));
+ }
+
+ return py_obj;
+}
+
+PyObject *
+pygi_arg_struct_to_py_marshal (GIArgument *arg,
+ GIInterfaceInfo *interface_info,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean is_allocated,
+ gboolean is_foreign)
+{
+ PyObject *ret = pygi_arg_struct_to_py_marshaller (arg, interface_info, g_type, py_type, transfer, is_allocated, is_foreign);
+
+ if (ret && PyObject_IsInstance (ret, (PyObject *) &PyGIBoxed_Type) && transfer == GI_TRANSFER_NOTHING)
+ pygi_boxed_copy_in_place ((PyGIBoxed *) ret);
+
+ return ret;
+};
+
+static PyObject *
+arg_struct_to_py_marshal_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ PyObject *ret;
+
+ ret = pygi_arg_struct_to_py_marshaller (arg,
+ iface_cache->interface_info,
+ iface_cache->g_type,
+ iface_cache->py_type,
+ arg_cache->transfer,
+ arg_cache->is_caller_allocates,
+ iface_cache->is_foreign);
+
+ *cleanup_data = ret;
+
+ return ret;
+}
+
+static void
+arg_foreign_to_py_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer cleanup_data,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
+ pygi_struct_foreign_release (
+ ( (PyGIInterfaceCache *)arg_cache)->interface_info,
+ data);
+ }
+}
+
+static void
+arg_boxed_to_py_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer cleanup_data,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (arg_cache->transfer == GI_TRANSFER_NOTHING)
+ pygi_boxed_copy_in_place ((PyGIBoxed *) cleanup_data);
+}
+
+static gboolean
+arg_type_class_from_py_marshal (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ GType gtype = pyg_type_from_object (py_arg);
+
+ if (G_TYPE_IS_CLASSED (gtype)) {
+ arg->v_pointer = g_type_class_ref (gtype);
+ *cleanup_data = arg->v_pointer;
+ return TRUE;
+ } else {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to retrieve a GObject type class from \"%s\".",
+ Py_TYPE(py_arg)->tp_name);
+ return FALSE;
+ }
+}
+
+static void
+arg_type_class_from_py_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (was_processed) {
+ g_type_class_unref (data);
+ }
+}
+
+static void
+arg_struct_from_py_setup (PyGIArgCache *arg_cache,
+ GIInterfaceInfo *iface_info,
+ GITransfer transfer)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+
+ if (g_struct_info_is_gtype_struct ((GIStructInfo*)iface_info)) {
+ arg_cache->from_py_marshaller = arg_type_class_from_py_marshal;
+ /* Since we always add a ref in the marshalling, only unref the
+ * GTypeClass when we don't transfer ownership. */
+ if (transfer == GI_TRANSFER_NOTHING) {
+ arg_cache->from_py_cleanup = arg_type_class_from_py_cleanup;
+ }
+
+ } else {
+ arg_cache->from_py_marshaller = arg_struct_from_py_marshal_adapter;
+
+ if (g_type_is_a (iface_cache->g_type, G_TYPE_CLOSURE)) {
+ arg_cache->from_py_cleanup = arg_gclosure_from_py_cleanup;
+
+ } else if (iface_cache->g_type == G_TYPE_VALUE) {
+ arg_cache->from_py_cleanup = pygi_arg_gvalue_from_py_cleanup;
+
+ } else if (iface_cache->is_foreign) {
+ arg_cache->from_py_cleanup = arg_foreign_from_py_cleanup;
+ }
+ }
+}
+
+static void
+arg_struct_to_py_setup (PyGIArgCache *arg_cache,
+ GIInterfaceInfo *iface_info,
+ GITransfer transfer)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+
+ if (arg_cache->to_py_marshaller == NULL) {
+ arg_cache->to_py_marshaller = arg_struct_to_py_marshal_adapter;
+ }
+
+ iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
+
+ if (iface_cache->is_foreign)
+ arg_cache->to_py_cleanup = arg_foreign_to_py_cleanup;
+ else if (!g_type_is_a (iface_cache->g_type, G_TYPE_VALUE) &&
+ iface_cache->py_type &&
+ g_type_is_a (iface_cache->g_type, G_TYPE_BOXED))
+ arg_cache->to_py_cleanup = arg_boxed_to_py_cleanup;
+}
+
+PyGIArgCache *
+pygi_arg_struct_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info)
+{
+ PyGIArgCache *cache = NULL;
+ PyGIInterfaceCache *iface_cache;
+
+ cache = pygi_arg_interface_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ if (cache == NULL)
+ return NULL;
+
+ iface_cache = (PyGIInterfaceCache *)cache;
+ iface_cache->is_foreign = (g_base_info_get_type ((GIBaseInfo *) iface_info) == GI_INFO_TYPE_STRUCT) &&
+ (g_struct_info_is_foreign ((GIStructInfo*) iface_info));
+
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ arg_struct_from_py_setup (cache, iface_info, transfer);
+ }
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ arg_struct_to_py_setup (cache, iface_info, transfer);
+ }
+
+ return cache;
+}
diff --git a/gi/pygi-struct-marshal.h b/gi/pygi-struct-marshal.h
new file mode 100644
index 0000000..b2846df
--- /dev/null
+++ b/gi/pygi-struct-marshal.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_STRUCT_MARSHAL_H__
+#define __PYGI_STRUCT_MARSHAL_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+PyGIArgCache *pygi_arg_struct_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info);
+
+
+gboolean pygi_arg_gvalue_from_py_marshal (PyObject *py_arg, /*in*/
+ GIArgument *arg, /*out*/
+ GITransfer transfer,
+ gboolean is_allocated);
+
+gboolean pygi_arg_struct_from_py_marshal (PyObject *py_arg,
+ GIArgument *arg,
+ const gchar *arg_name,
+ GIBaseInfo *interface_info,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean is_allocated,
+ gboolean is_foreign,
+ gboolean is_pointer);
+
+PyObject *pygi_arg_struct_to_py_marshal (GIArgument *arg,
+ GIInterfaceInfo *interface_info,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean is_allocated,
+ gboolean is_foreign);
+
+/* Needed for hack in pygi-arg-garray.c */
+void pygi_arg_gvalue_from_py_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed);
+
+G_END_DECLS
+
+#endif /*__PYGI_STRUCT_MARSHAL_H__*/
diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c
index 29ea38e..f6e75e3 100644
--- a/gi/pygi-struct.c
+++ b/gi/pygi-struct.c
@@ -16,39 +16,80 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include "pygi-struct.h"
+#include "pygi-foreign.h"
+#include "pygi-info.h"
+#include "pygi-type.h"
+#include "pygi-type.h"
+#include "pygpointer.h"
+#include "pygi-util.h"
-#include <pygobject.h>
#include <girepository.h>
-#include <pyglib-python-compat.h>
+
+
+static GIBaseInfo *
+struct_get_info (PyTypeObject *type)
+{
+ PyObject *py_info;
+ GIBaseInfo *info = NULL;
+
+ py_info = PyObject_GetAttrString ((PyObject *)type, "__info__");
+ if (py_info == NULL) {
+ return NULL;
+ }
+ if (!PyObject_TypeCheck (py_info, &PyGIStructInfo_Type) &&
+ !PyObject_TypeCheck (py_info, &PyGIUnionInfo_Type)) {
+ PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s or %s, not %s",
+ PyGIStructInfo_Type.tp_name,
+ PyGIUnionInfo_Type.tp_name,
+ Py_TYPE(py_info)->tp_name);
+ goto out;
+ }
+
+ info = ( (PyGIBaseInfo *) py_info)->info;
+ g_base_info_ref (info);
+
+out:
+ Py_DECREF (py_info);
+
+ return info;
+}
static void
-_struct_dealloc (PyGIStruct *self)
+struct_dealloc (PyGIStruct *self)
{
- GIBaseInfo *info = _pygi_object_get_gi_info (
- (PyObject *) self,
- &PyGIStructInfo_Type);
+ GIBaseInfo *info;
+ PyObject *error_type, *error_value, *error_traceback;
+ gboolean have_error = !!PyErr_Occurred ();
+
+ if (have_error)
+ PyErr_Fetch (&error_type, &error_value, &error_traceback);
+
+ info = struct_get_info (Py_TYPE (self));
if (info != NULL && g_struct_info_is_foreign ( (GIStructInfo *) info)) {
- pygi_struct_foreign_release (info, ( (PyGPointer *) self)->pointer);
+ pygi_struct_foreign_release (info, pyg_pointer_get_ptr (self));
} else if (self->free_on_dealloc) {
- g_free ( ( (PyGPointer *) self)->pointer);
+ g_free (pyg_pointer_get_ptr (self));
}
- g_base_info_unref (info);
+ if (info != NULL) {
+ g_base_info_unref (info);
+ }
+
+ if (have_error)
+ PyErr_Restore (error_type, error_value, error_traceback);
- Py_TYPE( (PyGPointer *) self )->tp_free ( (PyObject *) self);
+ Py_TYPE (self)->tp_free ((PyObject *)self);
}
static PyObject *
-_struct_new (PyTypeObject *type,
- PyObject *args,
- PyObject *kwargs)
+struct_new (PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwargs)
{
static char *kwlist[] = { NULL };
@@ -61,7 +102,7 @@ _struct_new (PyTypeObject *type,
return NULL;
}
- info = _pygi_object_get_gi_info ( (PyObject *) type, &PyGIStructInfo_Type);
+ info = struct_get_info ( type );
if (info == NULL) {
if (PyErr_ExceptionMatches (PyExc_AttributeError)) {
PyErr_Format (PyExc_TypeError, "missing introspection information");
@@ -72,7 +113,7 @@ _struct_new (PyTypeObject *type,
size = g_struct_info_get_size ( (GIStructInfo *) info);
if (size == 0) {
PyErr_Format (PyExc_TypeError,
- "cannot allocate disguised struct %s.%s; consider adding a constructor to the library or to the overrides",
+ "struct cannot be created directly; try using a constructor, see: help(%s.%s)",
g_base_info_get_namespace (info),
g_base_info_get_name (info));
goto out;
@@ -83,7 +124,7 @@ _struct_new (PyTypeObject *type,
goto out;
}
- self = _pygi_struct_new (type, pointer, TRUE);
+ self = pygi_struct_new (type, pointer, TRUE);
if (self == NULL) {
g_free (pointer);
}
@@ -95,7 +136,7 @@ out:
}
static int
-_struct_init (PyObject *self,
+struct_init (PyObject *self,
PyObject *args,
PyObject *kwargs)
{
@@ -103,12 +144,44 @@ _struct_init (PyObject *self,
return 0;
}
-PYGLIB_DEFINE_TYPE("gi.Struct", PyGIStruct_Type, PyGIStruct);
+PYGI_DEFINE_TYPE("gi.Struct", PyGIStruct_Type, PyGIStruct);
+
PyObject *
-_pygi_struct_new (PyTypeObject *type,
- gpointer pointer,
- gboolean free_on_dealloc)
+pygi_struct_new_from_g_type (GType g_type,
+ gpointer pointer,
+ gboolean free_on_dealloc)
+{
+ PyGIStruct *self;
+ PyTypeObject *type;
+
+ type = (PyTypeObject *)pygi_type_import_by_g_type (g_type);
+
+ if (!type)
+ type = (PyTypeObject *)&PyGIStruct_Type; /* fallback */
+
+ if (!PyType_IsSubtype (type, &PyGIStruct_Type)) {
+ PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Struct");
+ return NULL;
+ }
+
+ self = (PyGIStruct *) type->tp_alloc (type, 0);
+ if (self == NULL) {
+ return NULL;
+ }
+
+ pyg_pointer_set_ptr (self, pointer);
+ ( (PyGPointer *) self)->gtype = g_type;
+ self->free_on_dealloc = free_on_dealloc;
+
+ return (PyObject *) self;
+}
+
+
+PyObject *
+pygi_struct_new (PyTypeObject *type,
+ gpointer pointer,
+ gboolean free_on_dealloc)
{
PyGIStruct *self;
GType g_type;
@@ -125,25 +198,57 @@ _pygi_struct_new (PyTypeObject *type,
g_type = pyg_type_from_object ( (PyObject *) type);
+ pyg_pointer_set_ptr (self, pointer);
( (PyGPointer *) self)->gtype = g_type;
- ( (PyGPointer *) self)->pointer = pointer;
self->free_on_dealloc = free_on_dealloc;
return (PyObject *) self;
}
-void
-_pygi_struct_register_types (PyObject *m)
+static PyObject *
+struct_repr(PyGIStruct *self)
+{
+ PyObject* repr;
+ GIBaseInfo *info;
+ PyGPointer *pointer = (PyGPointer *)self;
+
+ info = struct_get_info (Py_TYPE (self));
+ if (info == NULL)
+ return NULL;
+
+ repr = PyUnicode_FromFormat ("<%s.%s object at %p (%s at %p)>",
+ g_base_info_get_namespace (info),
+ g_base_info_get_name (info),
+ self, g_type_name (pointer->gtype),
+ pointer->pointer);
+
+ g_base_info_unref (info);
+
+ return repr;
+}
+
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_struct_register_types (PyObject *m)
{
- Py_TYPE(&PyGIStruct_Type) = &PyType_Type;
+ Py_SET_TYPE(&PyGIStruct_Type, &PyType_Type);
+ g_assert (Py_TYPE (&PyGPointer_Type) != NULL);
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_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);
+ PyGIStruct_Type.tp_repr = (reprfunc)struct_repr;
+
+ if (PyType_Ready (&PyGIStruct_Type) < 0)
+ return -1;
+ Py_INCREF ((PyObject *) &PyGIStruct_Type);
+ if (PyModule_AddObject (m, "Struct", (PyObject *) &PyGIStruct_Type) < 0) {
+ Py_DECREF ((PyObject *) &PyGIStruct_Type);
+ return -1;
+ }
- if (PyType_Ready (&PyGIStruct_Type))
- return;
- if (PyModule_AddObject (m, "Struct", (PyObject *) &PyGIStruct_Type))
- return;
+ return 0;
}
diff --git a/gi/pygi-struct.h b/gi/pygi-struct.h
index 963d05a..27230a9 100644
--- a/gi/pygi-struct.h
+++ b/gi/pygi-struct.h
@@ -14,26 +14,35 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_STRUCT_H__
#define __PYGI_STRUCT_H__
#include <Python.h>
+#include <pygobject-internal.h>
G_BEGIN_DECLS
+typedef struct {
+ PyGPointer base;
+ gboolean free_on_dealloc;
+} PyGIStruct;
+
extern PyTypeObject PyGIStruct_Type;
PyObject *
-_pygi_struct_new (PyTypeObject *type,
- gpointer pointer,
- gboolean free_on_dealloc);
+pygi_struct_new (PyTypeObject *type,
+ gpointer pointer,
+ gboolean free_on_dealloc);
+
+PyObject *
+pygi_struct_new_from_g_type (GType g_type,
+ gpointer pointer,
+ gboolean free_on_dealloc);
-void _pygi_struct_register_types (PyObject *m);
+int pygi_struct_register_types (PyObject *m);
G_END_DECLS
diff --git a/gi/pygi-type.c b/gi/pygi-type.c
index dfaadb0..619c6a2 100644
--- a/gi/pygi-type.c
+++ b/gi/pygi-type.c
@@ -1,9 +1,6 @@
/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- *
- * Copyright (C) 2009 Simon van der Linden <svdlinden@src.gnome.org>
- *
- * pygi-type.c: helpers to lookup Python wrappers from GType and GIBaseInfo.
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,19 +13,27 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include <config.h>
-#include <pyglib-python-compat.h>
+#include "pygobject-object.h"
+#include "pygboxed.h"
+#include "pygenum.h"
+#include "pygflags.h"
+#include "pygparamspec.h"
+#include "pygi-util.h"
+#include "pygpointer.h"
+#include "pyginterface.h"
+#include "pygi-type.h"
+#include "pygi-value.h"
+#include "pygi-basictype.h"
PyObject *
-_pygi_type_import_by_name (const char *namespace_,
- const char *name)
+pygi_type_import_by_name (const char *namespace_,
+ const char *name)
{
gchar *module_name;
PyObject *py_module;
@@ -52,7 +57,7 @@ _pygi_type_import_by_name (const char *namespace_,
}
PyObject *
-pygi_type_import_by_g_type_real (GType g_type)
+pygi_type_import_by_g_type (GType g_type)
{
GIRepository *repository;
GIBaseInfo *info;
@@ -65,21 +70,21 @@ pygi_type_import_by_g_type_real (GType g_type)
return NULL;
}
- type = _pygi_type_import_by_gi_info (info);
+ type = pygi_type_import_by_gi_info (info);
g_base_info_unref (info);
return type;
}
PyObject *
-_pygi_type_import_by_gi_info (GIBaseInfo *info)
+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));
+ 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)
+pygi_type_get_from_g_type (GType g_type)
{
PyObject *py_g_type;
PyObject *py_type;
@@ -91,7 +96,7 @@ _pygi_type_get_from_g_type (GType g_type)
py_type = PyObject_GetAttrString (py_g_type, "pytype");
if (py_type == Py_None) {
- py_type = pygi_type_import_by_g_type_real (g_type);
+ py_type = pygi_type_import_by_g_type (g_type);
}
Py_DECREF (py_g_type);
@@ -99,61 +104,1279 @@ _pygi_type_get_from_g_type (GType g_type)
return py_type;
}
-/* _pygi_get_py_type_hint
+/* -------------- __gtype__ objects ---------------------------- */
+
+typedef struct {
+ PyObject_HEAD
+ GType type;
+} PyGTypeWrapper;
+
+PYGI_DEFINE_TYPE("gobject.GType", PyGTypeWrapper_Type, PyGTypeWrapper);
+
+static PyObject*
+generic_gsize_richcompare(gsize a, gsize b, int op)
+{
+ PyObject *res;
+
+ switch (op) {
+
+ case Py_EQ:
+ res = (a == b) ? Py_True : Py_False;
+ Py_INCREF(res);
+ break;
+
+ case Py_NE:
+ res = (a != b) ? Py_True : Py_False;
+ Py_INCREF(res);
+ break;
+
+
+ case Py_LT:
+ res = (a < b) ? Py_True : Py_False;
+ Py_INCREF(res);
+ break;
+
+ case Py_LE:
+ res = (a <= b) ? Py_True : Py_False;
+ Py_INCREF(res);
+ break;
+
+ case Py_GT:
+ res = (a > b) ? Py_True : Py_False;
+ Py_INCREF(res);
+ break;
+
+ case Py_GE:
+ res = (a >= b) ? Py_True : Py_False;
+ Py_INCREF(res);
+ break;
+
+ default:
+ res = Py_NotImplemented;
+ Py_INCREF(res);
+ break;
+ }
+
+ return res;
+}
+
+static PyObject*
+pyg_type_wrapper_richcompare(PyObject *self, PyObject *other, int op)
+{
+ if (Py_TYPE(self) == Py_TYPE(other) && Py_TYPE(self) == &PyGTypeWrapper_Type)
+ return generic_gsize_richcompare(((PyGTypeWrapper*)self)->type,
+ ((PyGTypeWrapper*)other)->type,
+ op);
+ else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+}
+
+static long
+pyg_type_wrapper_hash(PyGTypeWrapper *self)
+{
+ return (long)self->type;
+}
+
+static PyObject *
+pyg_type_wrapper_repr(PyGTypeWrapper *self)
+{
+ char buf[80];
+ const gchar *name = g_type_name(self->type);
+
+ g_snprintf(buf, sizeof(buf), "<GType %s (%lu)>",
+ name?name:"invalid", (unsigned long int) self->type);
+ return PyUnicode_FromString (buf);
+}
+
+static void
+pyg_type_wrapper_dealloc(PyGTypeWrapper *self)
+{
+ PyObject_DEL(self);
+}
+
+static GQuark
+_pyg_type_key(GType type) {
+ GQuark key;
+
+ if (g_type_is_a(type, G_TYPE_INTERFACE)) {
+ key = pyginterface_type_key;
+ } else if (g_type_is_a(type, G_TYPE_ENUM)) {
+ key = pygenum_class_key;
+ } else if (g_type_is_a(type, G_TYPE_FLAGS)) {
+ key = pygflags_class_key;
+ } else if (g_type_is_a(type, G_TYPE_POINTER)) {
+ key = pygpointer_class_key;
+ } else if (g_type_is_a(type, G_TYPE_BOXED)) {
+ key = pygboxed_type_key;
+ } else {
+ key = pygobject_class_key;
+ }
+
+ return key;
+}
+
+static PyObject *
+_wrap_g_type_wrapper__get_pytype(PyGTypeWrapper *self, void *closure)
+{
+ GQuark key;
+ PyObject *py_type;
+
+ key = _pyg_type_key(self->type);
+
+ py_type = g_type_get_qdata(self->type, key);
+ if (!py_type)
+ py_type = Py_None;
+
+ Py_INCREF(py_type);
+ return py_type;
+}
+
+static int
+_wrap_g_type_wrapper__set_pytype(PyGTypeWrapper *self, PyObject* value, void *closure)
+{
+ GQuark key;
+ PyObject *py_type;
+
+ key = _pyg_type_key(self->type);
+
+ py_type = g_type_get_qdata(self->type, key);
+ Py_CLEAR(py_type);
+ if (value == Py_None)
+ g_type_set_qdata(self->type, key, NULL);
+ else if (PyType_Check(value)) {
+ Py_INCREF(value);
+ g_type_set_qdata(self->type, key, value);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Value must be None or a type object");
+ return -1;
+ }
+
+ return 0;
+}
+
+static PyObject *
+_wrap_g_type_wrapper__get_name(PyGTypeWrapper *self, void *closure)
+{
+ const char *name = g_type_name(self->type);
+ return PyUnicode_FromString (name ? name : "invalid");
+}
+
+static PyObject *
+_wrap_g_type_wrapper__get_parent(PyGTypeWrapper *self, void *closure)
+{
+ return pyg_type_wrapper_new(g_type_parent(self->type));
+}
+
+static PyObject *
+_wrap_g_type_wrapper__get_fundamental(PyGTypeWrapper *self, void *closure)
+{
+ return pyg_type_wrapper_new(g_type_fundamental(self->type));
+}
+
+static PyObject *
+_wrap_g_type_wrapper__get_children(PyGTypeWrapper *self, void *closure)
+{
+ guint n_children, i;
+ GType *children;
+ PyObject *retval;
+
+ children = g_type_children(self->type, &n_children);
+
+ retval = PyList_New(n_children);
+ for (i = 0; i < n_children; i++)
+ PyList_SetItem(retval, i, pyg_type_wrapper_new(children[i]));
+ g_free(children);
+
+ return retval;
+}
+
+static PyObject *
+_wrap_g_type_wrapper__get_interfaces(PyGTypeWrapper *self, void *closure)
+{
+ guint n_interfaces, i;
+ GType *interfaces;
+ PyObject *retval;
+
+ interfaces = g_type_interfaces(self->type, &n_interfaces);
+
+ retval = PyList_New(n_interfaces);
+ for (i = 0; i < n_interfaces; i++)
+ PyList_SetItem(retval, i, pyg_type_wrapper_new(interfaces[i]));
+ g_free(interfaces);
+
+ return retval;
+}
+
+static PyObject *
+_wrap_g_type_wrapper__get_depth(PyGTypeWrapper *self, void *closure)
+{
+ return pygi_guint_to_py (g_type_depth (self->type));
+}
+
+static PyGetSetDef _PyGTypeWrapper_getsets[] = {
+ { "pytype", (getter)_wrap_g_type_wrapper__get_pytype, (setter)_wrap_g_type_wrapper__set_pytype },
+ { "name", (getter)_wrap_g_type_wrapper__get_name, (setter)0 },
+ { "fundamental", (getter)_wrap_g_type_wrapper__get_fundamental, (setter)0 },
+ { "parent", (getter)_wrap_g_type_wrapper__get_parent, (setter)0 },
+ { "children", (getter)_wrap_g_type_wrapper__get_children, (setter)0 },
+ { "interfaces", (getter)_wrap_g_type_wrapper__get_interfaces, (setter)0 },
+ { "depth", (getter)_wrap_g_type_wrapper__get_depth, (setter)0 },
+ { NULL, (getter)0, (setter)0 }
+};
+
+static PyObject*
+_wrap_g_type_is_interface(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_IS_INTERFACE (self->type));
+}
+
+static PyObject*
+_wrap_g_type_is_classed(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_IS_CLASSED (self->type));
+}
+
+static PyObject*
+_wrap_g_type_is_instantiatable(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_IS_INSTANTIATABLE(self->type));
+}
+
+static PyObject*
+_wrap_g_type_is_derivable(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_IS_DERIVABLE (self->type));
+}
+
+static PyObject*
+_wrap_g_type_is_deep_derivable(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_IS_DEEP_DERIVABLE (self->type));
+}
+
+static PyObject*
+_wrap_g_type_is_abstract(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_IS_ABSTRACT (self->type));
+}
+
+static PyObject*
+_wrap_g_type_is_value_abstract(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_IS_VALUE_ABSTRACT (self->type));
+}
+
+static PyObject*
+_wrap_g_type_is_value_type(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_IS_VALUE_TYPE (self->type));
+}
+
+static PyObject*
+_wrap_g_type_has_value_table(PyGTypeWrapper *self)
+{
+ return pygi_gboolean_to_py (G_TYPE_HAS_VALUE_TABLE (self->type));
+}
+
+static PyObject*
+_wrap_g_type_from_name(PyGTypeWrapper *_, PyObject *args)
+{
+ char *type_name;
+ GType type;
+
+ if (!PyArg_ParseTuple(args, "s:GType.from_name", &type_name))
+ return NULL;
+
+ type = g_type_from_name(type_name);
+ if (type == 0) {
+ PyErr_SetString(PyExc_RuntimeError, "unknown type name");
+ return NULL;
+ }
+
+ return pyg_type_wrapper_new(type);
+}
+
+static PyObject*
+_wrap_g_type_is_a(PyGTypeWrapper *self, PyObject *args)
+{
+ PyObject *gparent;
+ GType parent;
+
+ if (!PyArg_ParseTuple(args, "O:GType.is_a", &gparent))
+ return NULL;
+ else if ((parent = pyg_type_from_object(gparent)) == 0)
+ return NULL;
+
+ return pygi_gboolean_to_py (g_type_is_a (self->type, parent));
+}
+
+static PyMethodDef _PyGTypeWrapper_methods[] = {
+ { "is_interface", (PyCFunction)_wrap_g_type_is_interface, METH_NOARGS },
+ { "is_classed", (PyCFunction)_wrap_g_type_is_classed, METH_NOARGS },
+ { "is_instantiatable", (PyCFunction)_wrap_g_type_is_instantiatable, METH_NOARGS },
+ { "is_derivable", (PyCFunction)_wrap_g_type_is_derivable, METH_NOARGS },
+ { "is_deep_derivable", (PyCFunction)_wrap_g_type_is_deep_derivable, METH_NOARGS },
+ { "is_abstract", (PyCFunction)_wrap_g_type_is_abstract, METH_NOARGS },
+ { "is_value_abstract", (PyCFunction)_wrap_g_type_is_value_abstract, METH_NOARGS },
+ { "is_value_type", (PyCFunction)_wrap_g_type_is_value_type, METH_NOARGS },
+ { "has_value_table", (PyCFunction)_wrap_g_type_has_value_table, METH_NOARGS },
+ { "from_name", (PyCFunction)_wrap_g_type_from_name, METH_VARARGS | METH_STATIC },
+ { "is_a", (PyCFunction)_wrap_g_type_is_a, METH_VARARGS },
+ { NULL, 0, 0 }
+};
+
+static int
+pyg_type_wrapper_init(PyGTypeWrapper *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "object", NULL };
+ PyObject *py_object;
+ GType type;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O:GType.__init__",
+ kwlist, &py_object))
+ return -1;
+
+ if (!(type = pyg_type_from_object(py_object)))
+ return -1;
+
+ self->type = type;
+
+ return 0;
+}
+
+/**
+ * pyg_type_wrapper_new:
+ * type: a GType
+ *
+ * Creates a Python wrapper for a GType.
*
- * This gives a hint to what python type might be used as
- * a particular gi type.
+ * Returns: the Python wrapper.
*/
PyObject *
-_pygi_get_py_type_hint(GITypeTag type_tag)
-{
- PyObject *type = Py_None;
-
- switch (type_tag) {
- case GI_TYPE_TAG_BOOLEAN:
- type = (PyObject *) &PyBool_Type;
- break;
-
- case GI_TYPE_TAG_INT8:
- case GI_TYPE_TAG_UINT8:
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_INT64:
- case GI_TYPE_TAG_UINT64:
- type = (PyObject *) &PYGLIB_PyLong_Type;
- break;
-
- case GI_TYPE_TAG_FLOAT:
- case GI_TYPE_TAG_DOUBLE:
- type = (PyObject *) &PyFloat_Type;
- break;
-
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- case GI_TYPE_TAG_ARRAY:
- type = (PyObject *) &PyList_Type;
- break;
-
- case GI_TYPE_TAG_GHASH:
- type = (PyObject *) &PyDict_Type;
- break;
-
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- case GI_TYPE_TAG_UNICHAR:
- type = (PyObject *) &PYGLIB_PyUnicode_Type;
- break;
-
- case GI_TYPE_TAG_INTERFACE:
- case GI_TYPE_TAG_GTYPE:
- case GI_TYPE_TAG_ERROR:
- case GI_TYPE_TAG_VOID:
- break;
- }
-
- Py_INCREF(type);
- return type;
+pyg_type_wrapper_new(GType type)
+{
+ PyGTypeWrapper *self;
+
+ g_assert (Py_TYPE (&PyGTypeWrapper_Type) != NULL);
+ self = (PyGTypeWrapper *)PyObject_NEW(PyGTypeWrapper,
+ &PyGTypeWrapper_Type);
+ if (self == NULL)
+ return NULL;
+
+ self->type = type;
+ return (PyObject *)self;
+}
+
+/**
+ * pyg_type_from_object_strict:
+ * obj: a Python object
+ * strict: if set to TRUE, raises an exception if it can't perform the
+ * conversion
+ *
+ * converts a python object to a GType. If strict is set, raises an
+ * exception if it can't perform the conversion, otherwise returns
+ * PY_TYPE_OBJECT.
+ *
+ * Returns: the corresponding GType, or 0 on error.
+ */
+
+GType
+pyg_type_from_object_strict(PyObject *obj, gboolean strict)
+{
+ PyObject *gtype;
+ GType type;
+
+ /* NULL check */
+ if (!obj) {
+ PyErr_SetString(PyExc_TypeError, "can't get type from NULL object");
+ return 0;
+ }
+
+ /* map some standard types to primitive GTypes ... */
+ if (obj == Py_None)
+ return G_TYPE_NONE;
+ if (PyType_Check(obj)) {
+ PyTypeObject *tp = (PyTypeObject *)obj;
+
+ if (tp == &PyLong_Type)
+ return G_TYPE_INT;
+ else if (tp == &PyBool_Type)
+ return G_TYPE_BOOLEAN;
+ else if (tp == &PyFloat_Type)
+ return G_TYPE_DOUBLE;
+ else if (tp == &PyUnicode_Type)
+ return G_TYPE_STRING;
+ else if (tp == &PyBaseObject_Type)
+ return PY_TYPE_OBJECT;
+ }
+
+ if (Py_TYPE(obj) == &PyGTypeWrapper_Type) {
+ return ((PyGTypeWrapper *)obj)->type;
+ }
+
+ /* handle strings */
+ if (PyUnicode_Check (obj)) {
+ gchar *name = PyUnicode_AsUTF8(obj);
+
+ type = g_type_from_name(name);
+ if (type != 0) {
+ return type;
+ }
+ }
+
+ /* finally, look for a __gtype__ attribute on the object */
+ gtype = PyObject_GetAttrString(obj, "__gtype__");
+
+ if (gtype) {
+ if (Py_TYPE(gtype) == &PyGTypeWrapper_Type) {
+ type = ((PyGTypeWrapper *)gtype)->type;
+ Py_DECREF(gtype);
+ return type;
+ }
+ Py_DECREF(gtype);
+ }
+
+ PyErr_Clear();
+
+ /* Some API like those that take GValues can hold a python object as
+ * a pointer. This is potentially dangerous becuase everything is
+ * passed in as a PyObject so we can't actually type check it. Only
+ * fallback to PY_TYPE_OBJECT if strict checking is disabled
+ */
+ if (!strict)
+ return PY_TYPE_OBJECT;
+
+ PyErr_SetString(PyExc_TypeError, "could not get typecode from object");
+ return 0;
}
+/**
+ * pyg_type_from_object:
+ * obj: a Python object
+ *
+ * converts a python object to a GType. Raises an exception if it
+ * can't perform the conversion.
+ *
+ * Returns: the corresponding GType, or 0 on error.
+ */
+GType
+pyg_type_from_object(PyObject *obj)
+{
+ /* Legacy call always defaults to strict type checking */
+ return pyg_type_from_object_strict(obj, TRUE);
+}
+
+/**
+ * pyg_enum_get_value:
+ * @enum_type: the GType of the flag.
+ * @obj: a Python object representing the flag value
+ * @val: a pointer to the location to store the integer representation of the flag.
+ *
+ * Converts a Python object to the integer equivalent. The conversion
+ * will depend on the type of the Python object. If the object is an
+ * integer, it is passed through directly. If it is a string, it will
+ * be treated as a full or short enum name as defined in the GType.
+ *
+ * Returns: 0 on success or -1 on failure
+ */
+gint
+pyg_enum_get_value(GType enum_type, PyObject *obj, gint *val)
+{
+ GEnumClass *eclass = NULL;
+ gint res = -1;
+
+ g_return_val_if_fail(val != NULL, -1);
+ if (!obj) {
+ *val = 0;
+ res = 0;
+ } else if (PyLong_Check (obj)) {
+ if (!pygi_gint_from_py (obj, val))
+ res = -1;
+ else
+ res = 0;
+
+ if (PyObject_TypeCheck(obj, &PyGEnum_Type) && ((PyGEnum *) obj)->gtype != enum_type) {
+ g_warning("expected enumeration type %s, but got %s instead",
+ g_type_name(enum_type),
+ g_type_name(((PyGEnum *) obj)->gtype));
+ }
+ } else if (PyUnicode_Check (obj)) {
+ GEnumValue *info;
+ char *str = PyUnicode_AsUTF8 (obj);
+
+ if (enum_type != G_TYPE_NONE)
+ eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
+ else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string to enum because there is no GType associated to look up the value");
+ res = -1;
+ }
+ info = g_enum_get_value_by_name(eclass, str);
+ g_type_class_unref(eclass);
+
+ if (!info)
+ info = g_enum_get_value_by_nick(eclass, str);
+ if (info) {
+ *val = info->value;
+ res = 0;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string");
+ res = -1;
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError,"enum values must be strings or ints");
+ res = -1;
+ }
+ return res;
+}
+
+/**
+ * pyg_flags_get_value:
+ * @flag_type: the GType of the flag.
+ * @obj: a Python object representing the flag value
+ * @val: a pointer to the location to store the integer representation of the flag.
+ *
+ * Converts a Python object to the integer equivalent. The conversion
+ * will depend on the type of the Python object. If the object is an
+ * integer, it is passed through directly. If it is a string, it will
+ * be treated as a full or short flag name as defined in the GType.
+ * If it is a tuple, then the items are treated as strings and ORed
+ * together.
+ *
+ * Returns: 0 on success or -1 on failure
+ */
+gint
+pyg_flags_get_value(GType flag_type, PyObject *obj, guint *val)
+{
+ GFlagsClass *fclass = NULL;
+ gint res = -1;
+
+ g_return_val_if_fail(val != NULL, -1);
+ if (!obj) {
+ *val = 0;
+ res = 0;
+ } else if (PyLong_Check (obj)) {
+ if (pygi_guint_from_py (obj, val))
+ res = 0;
+ } else if (PyUnicode_Check (obj)) {
+ GFlagsValue *info;
+ char *str = PyUnicode_AsUTF8 (obj);
+
+ if (flag_type != G_TYPE_NONE)
+ fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
+ else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
+ res = -1;
+ }
+ info = g_flags_get_value_by_name(fclass, str);
+ g_type_class_unref(fclass);
+
+ if (!info)
+ info = g_flags_get_value_by_nick(fclass, str);
+ if (info) {
+ *val = info->value;
+ res = 0;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string");
+ res = -1;
+ }
+ } else if (PyTuple_Check(obj)) {
+ Py_ssize_t i, len;
+
+ len = PyTuple_Size(obj);
+ *val = 0;
+ res = 0;
+
+ if (flag_type != G_TYPE_NONE)
+ fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
+ else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
+ res = -1;
+ }
+
+ for (i = 0; i < len; i++) {
+ PyObject *item = PyTuple_GetItem(obj, i);
+ char *str = PyUnicode_AsUTF8 (item);
+ GFlagsValue *info = g_flags_get_value_by_name(fclass, str);
+
+ if (!info)
+ info = g_flags_get_value_by_nick(fclass, str);
+ if (info) {
+ *val |= info->value;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string");
+ res = -1;
+ break;
+ }
+ }
+ g_type_class_unref(fclass);
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "flag values must be strings, ints, longs, or tuples");
+ res = -1;
+ }
+ return res;
+}
+
+static GQuark pyg_type_marshal_key = 0;
+static GQuark pyg_type_marshal_helper_key = 0;
+
+typedef enum _marshal_helper_data_e marshal_helper_data_e;
+enum _marshal_helper_data_e {
+ MARSHAL_HELPER_NONE = 0,
+ MARSHAL_HELPER_RETURN_NULL,
+ MARSHAL_HELPER_IMPORT_DONE,
+};
+
+PyGTypeMarshal *
+pyg_type_lookup(GType type)
+{
+ GType ptype = type;
+ PyGTypeMarshal *tm = NULL;
+ marshal_helper_data_e marshal_helper;
+
+ if (type == G_TYPE_INVALID)
+ return NULL;
+
+ marshal_helper = GPOINTER_TO_INT (
+ g_type_get_qdata(type, pyg_type_marshal_helper_key));
+
+ /* If we called this function before with @type and nothing was found,
+ * return NULL early to not spend time in the loop below */
+ if (marshal_helper == MARSHAL_HELPER_RETURN_NULL)
+ return NULL;
+
+ /* Otherwise do recursive type lookup */
+ do {
+ if (marshal_helper == MARSHAL_HELPER_IMPORT_DONE)
+ pygi_type_import_by_g_type (ptype);
+
+ if ((tm = g_type_get_qdata(ptype, pyg_type_marshal_key)) != NULL)
+ break;
+ ptype = g_type_parent(ptype);
+ } while (ptype);
+
+ if (marshal_helper == MARSHAL_HELPER_NONE) {
+ marshal_helper = (tm == NULL) ?
+ MARSHAL_HELPER_RETURN_NULL:
+ MARSHAL_HELPER_IMPORT_DONE;
+ g_type_set_qdata(type, pyg_type_marshal_helper_key,
+ GINT_TO_POINTER(marshal_helper));
+ }
+ return tm;
+}
+
+/**
+ * pyg_register_gtype_custom:
+ * @gtype: the GType for the new type
+ * @from_func: a function to convert GValues to Python objects
+ * @to_func: a function to convert Python objects to GValues
+ *
+ * In order to handle specific conversion of gboxed types or new
+ * fundamental types, you may use this function to register conversion
+ * handlers.
+ */
+
+void
+pyg_register_gtype_custom(GType gtype,
+ fromvaluefunc from_func,
+ tovaluefunc to_func)
+{
+ PyGTypeMarshal *tm;
+
+ if (!pyg_type_marshal_key) {
+ pyg_type_marshal_key = g_quark_from_static_string("PyGType::marshal");
+ pyg_type_marshal_helper_key = g_quark_from_static_string("PyGType::marshal-helper");
+ }
+
+ tm = g_new(PyGTypeMarshal, 1);
+ tm->fromvalue = from_func;
+ tm->tovalue = to_func;
+ g_type_set_qdata(gtype, pyg_type_marshal_key, tm);
+}
+
+/* -------------- PyGClosure ----------------- */
+
+static void
+pyg_closure_invalidate(gpointer data, GClosure *closure)
+{
+ PyGClosure *pc = (PyGClosure *)closure;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+ Py_XDECREF(pc->callback);
+ Py_XDECREF(pc->extra_args);
+ Py_XDECREF(pc->swap_data);
+ PyGILState_Release(state);
+
+ pc->callback = NULL;
+ pc->extra_args = NULL;
+ pc->swap_data = NULL;
+}
+
+static void
+pyg_closure_marshal(GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ PyGILState_STATE state;
+ PyGClosure *pc = (PyGClosure *)closure;
+ PyObject *params, *ret;
+ guint i;
+
+ state = PyGILState_Ensure();
+
+ /* construct Python tuple for the parameter values */
+ params = PyTuple_New(n_param_values);
+ for (i = 0; i < n_param_values; i++) {
+ /* swap in a different initial data for connect_object() */
+ if (i == 0 && G_CCLOSURE_SWAP_DATA(closure)) {
+ g_return_if_fail(pc->swap_data != NULL);
+ Py_INCREF(pc->swap_data);
+ PyTuple_SetItem(params, 0, pc->swap_data);
+ } else {
+ PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
+
+ /* error condition */
+ if (!item) {
+ if (!PyErr_Occurred ())
+ PyErr_SetString (PyExc_TypeError,
+ "can't convert parameter to desired type");
+
+ if (pc->exception_handler)
+ pc->exception_handler (return_value, n_param_values, param_values);
+ else
+ PyErr_Print();
+
+ goto out;
+ }
+ PyTuple_SetItem(params, i, item);
+ }
+ }
+ /* params passed to function may have extra arguments */
+ if (pc->extra_args) {
+ PyObject *tuple = params;
+ params = PySequence_Concat(tuple, pc->extra_args);
+ Py_DECREF(tuple);
+ }
+ ret = PyObject_CallObject(pc->callback, params);
+ if (ret == NULL) {
+ if (pc->exception_handler)
+ pc->exception_handler(return_value, n_param_values, param_values);
+ else
+ PyErr_Print();
+ goto out;
+ }
+
+ if (G_IS_VALUE(return_value) && pyg_value_from_pyobject(return_value, ret) != 0) {
+ /* If we already have an exception set, use that, otherwise set a
+ * generic one */
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_TypeError,
+ "can't convert return value to desired type");
+
+ if (pc->exception_handler)
+ pc->exception_handler(return_value, n_param_values, param_values);
+ else
+ PyErr_Print();
+ }
+ Py_DECREF(ret);
+
+ out:
+ Py_DECREF(params);
+ PyGILState_Release(state);
+}
+
+/**
+ * pyg_closure_new:
+ * callback: a Python callable object
+ * extra_args: a tuple of extra arguments, or None/NULL.
+ * swap_data: an alternative python object to pass first.
+ *
+ * Creates a GClosure wrapping a Python callable and optionally a set
+ * of additional function arguments. This is needed to attach python
+ * handlers to signals, for instance.
+ *
+ * Returns: the new closure.
+ */
+GClosure *
+pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data)
+{
+ GClosure *closure;
+
+ g_return_val_if_fail(callback != NULL, NULL);
+ closure = g_closure_new_simple(sizeof(PyGClosure), NULL);
+ g_closure_add_invalidate_notifier(closure, NULL, pyg_closure_invalidate);
+ g_closure_set_marshal(closure, pyg_closure_marshal);
+ Py_INCREF(callback);
+ ((PyGClosure *)closure)->callback = callback;
+ if (extra_args && extra_args != Py_None) {
+ Py_INCREF(extra_args);
+ if (!PyTuple_Check(extra_args)) {
+ PyObject *tmp = PyTuple_New(1);
+ PyTuple_SetItem(tmp, 0, extra_args);
+ extra_args = tmp;
+ }
+ ((PyGClosure *)closure)->extra_args = extra_args;
+ }
+ if (swap_data) {
+ Py_INCREF(swap_data);
+ ((PyGClosure *)closure)->swap_data = swap_data;
+ closure->derivative_flag = TRUE;
+ }
+ return closure;
+}
+
+/**
+ * pyg_closure_set_exception_handler:
+ * @closure: a closure created with pyg_closure_new()
+ * @handler: the handler to call when an exception occurs or NULL for none
+ *
+ * Sets the handler to call when an exception occurs during closure invocation.
+ * The handler is responsible for providing a proper return value to the
+ * closure invocation. If @handler is %NULL, the default handler will be used.
+ * The default handler prints the exception to stderr and doesn't touch the
+ * closure's return value.
+ */
+void
+pyg_closure_set_exception_handler(GClosure *closure,
+ PyClosureExceptionHandler handler)
+{
+ PyGClosure *pygclosure;
+
+ g_return_if_fail(closure != NULL);
+
+ pygclosure = (PyGClosure *)closure;
+ pygclosure->exception_handler = handler;
+}
+/* -------------- PySignalClassClosure ----------------- */
+/* a closure used for the `class closure' of a signal. As this gets
+ * all the info from the first argument to the closure and the
+ * invocation hint, we can have a single closure that handles all
+ * class closure cases. We call a method by the name of the signal
+ * with "do_" prepended.
+ *
+ * We also remove the first argument from the * param list, as it is
+ * the instance object, which is passed * implicitly to the method
+ * object. */
+
+static void
+pyg_signal_class_closure_marshal(GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ PyGILState_STATE state;
+ GObject *object;
+ PyObject *object_wrapper;
+ GSignalInvocationHint *hint = (GSignalInvocationHint *)invocation_hint;
+ gchar *method_name, *tmp;
+ PyObject *method;
+ PyObject *params, *ret;
+ Py_ssize_t py_len;
+ guint i, len;
+
+ state = PyGILState_Ensure();
+
+ g_return_if_fail(invocation_hint != NULL);
+ /* get the object passed as the first argument to the closure */
+ object = g_value_get_object(&param_values[0]);
+ g_return_if_fail(object != NULL && G_IS_OBJECT(object));
+
+ /* get the wrapper for this object */
+ object_wrapper = pygobject_new(object);
+ g_return_if_fail(object_wrapper != NULL);
+
+ /* construct method name for this class closure */
+ method_name = g_strconcat("do_", g_signal_name(hint->signal_id), NULL);
+
+ /* convert dashes to underscores. For some reason, g_signal_name
+ * seems to convert all the underscores in the signal name to
+ dashes??? */
+ for (tmp = method_name; *tmp != '\0'; tmp++)
+ if (*tmp == '-') *tmp = '_';
+
+ method = PyObject_GetAttrString(object_wrapper, method_name);
+ g_free(method_name);
+
+ if (!method) {
+ PyErr_Clear();
+ Py_DECREF(object_wrapper);
+ PyGILState_Release(state);
+ return;
+ }
+ Py_DECREF(object_wrapper);
+
+ /* construct Python tuple for the parameter values; don't copy boxed values
+ initially because we'll check after the call to see if a copy is needed. */
+ params = PyTuple_New(n_param_values - 1);
+ for (i = 1; i < n_param_values; i++) {
+ PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
+
+ /* error condition */
+ if (!item) {
+ Py_DECREF(params);
+ PyGILState_Release(state);
+ return;
+ }
+ PyTuple_SetItem(params, i - 1, item);
+ }
+
+ ret = PyObject_CallObject(method, params);
+
+ /* Copy boxed values if others ref them, this needs to be done regardless of
+ exception status. */
+ py_len = PyTuple_Size(params);
+ len = (guint)py_len;
+ for (i = 0; i < len; i++) {
+ PyObject *item = PyTuple_GetItem(params, i);
+ if (item != NULL && PyObject_TypeCheck(item, &PyGBoxed_Type)
+ && Py_REFCNT (item) != 1) {
+ PyGBoxed* boxed_item = (PyGBoxed*)item;
+ if (!boxed_item->free_on_dealloc) {
+ gpointer boxed_ptr = pyg_boxed_get_ptr (boxed_item);
+ pyg_boxed_set_ptr (boxed_item, g_boxed_copy (boxed_item->gtype, boxed_ptr));
+ boxed_item->free_on_dealloc = TRUE;
+ }
+ }
+ }
+
+ if (ret == NULL) {
+ PyErr_Print();
+ Py_DECREF(method);
+ Py_DECREF(params);
+ PyGILState_Release(state);
+ return;
+ }
+ Py_DECREF(method);
+ Py_DECREF(params);
+ if (G_IS_VALUE(return_value))
+ pyg_value_from_pyobject(return_value, ret);
+ Py_DECREF(ret);
+ PyGILState_Release(state);
+}
+
+/**
+ * pyg_signal_class_closure_get:
+ *
+ * Returns the GClosure used for the class closure of signals. When
+ * called, it will invoke the method do_signalname (for the signal
+ * "signalname").
+ *
+ * Returns: the closure.
+ */
+GClosure *
+pyg_signal_class_closure_get(void)
+{
+ static GClosure *closure;
+
+ if (closure == NULL) {
+ closure = g_closure_new_simple(sizeof(GClosure), NULL);
+ g_closure_set_marshal(closure, pyg_signal_class_closure_marshal);
+
+ g_closure_ref(closure);
+ g_closure_sink(closure);
+ }
+ return closure;
+}
+
+/* ----- __doc__ descriptor for GObject and GInterface ----- */
+
+static void
+object_doc_dealloc(PyObject *self)
+{
+ PyObject_FREE(self);
+}
+
+/* append information about signals of a particular gtype */
+static void
+add_signal_docs(GType gtype, GString *string)
+{
+ GTypeClass *class = NULL;
+ guint *signal_ids, n_ids = 0, i;
+
+ if (G_TYPE_IS_CLASSED(gtype))
+ class = g_type_class_ref(gtype);
+ signal_ids = g_signal_list_ids(gtype, &n_ids);
+
+ if (n_ids > 0) {
+ g_string_append_printf(string, "Signals from %s:\n",
+ g_type_name(gtype));
+
+ for (i = 0; i < n_ids; i++) {
+ GSignalQuery query;
+ guint j;
+
+ g_signal_query(signal_ids[i], &query);
+
+ g_string_append(string, " ");
+ g_string_append(string, query.signal_name);
+ g_string_append(string, " (");
+ for (j = 0; j < query.n_params; j++) {
+ g_string_append(string, g_type_name(query.param_types[j]));
+ if (j != query.n_params - 1)
+ g_string_append(string, ", ");
+ }
+ g_string_append(string, ")");
+ if (query.return_type && query.return_type != G_TYPE_NONE) {
+ g_string_append(string, " -> ");
+ g_string_append(string, g_type_name(query.return_type));
+ }
+ g_string_append(string, "\n");
+ }
+ g_free(signal_ids);
+ g_string_append(string, "\n");
+ }
+ if (class)
+ g_type_class_unref(class);
+}
+
+static void
+add_property_docs(GType gtype, GString *string)
+{
+ GObjectClass *class;
+ GParamSpec **props;
+ guint n_props = 0, i;
+ gboolean has_prop = FALSE;
+ const gchar *blurb=NULL;
+
+ class = g_type_class_ref(gtype);
+ props = g_object_class_list_properties(class, &n_props);
+
+ for (i = 0; i < n_props; i++) {
+ if (props[i]->owner_type != gtype)
+ continue; /* these are from a parent type */
+
+ /* print out the heading first */
+ if (!has_prop) {
+ g_string_append_printf(string, "Properties from %s:\n",
+ g_type_name(gtype));
+ has_prop = TRUE;
+ }
+ g_string_append_printf(string, " %s -> %s: %s\n",
+ g_param_spec_get_name(props[i]),
+ g_type_name(props[i]->value_type),
+ g_param_spec_get_nick(props[i]));
+
+ /* g_string_append_printf crashes on win32 if the third
+ argument is NULL. */
+ blurb=g_param_spec_get_blurb(props[i]);
+ if (blurb)
+ g_string_append_printf(string, " %s\n",blurb);
+ }
+ g_free(props);
+ if (has_prop)
+ g_string_append(string, "\n");
+ g_type_class_unref(class);
+}
+
+static PyObject *
+object_doc_descr_get(PyObject *self, PyObject *obj, PyObject *type)
+{
+ GType gtype = 0;
+ GString *string;
+ PyObject *pystring;
+
+ if (obj && pygobject_check(obj, &PyGObject_Type)) {
+ gtype = G_OBJECT_TYPE(pygobject_get(obj));
+ if (!gtype)
+ PyErr_SetString(PyExc_RuntimeError, "could not get object type");
+ } else {
+ gtype = pyg_type_from_object(type);
+ }
+ if (!gtype)
+ return NULL;
+
+ string = g_string_new_len(NULL, 512);
+
+ if (g_type_is_a(gtype, G_TYPE_INTERFACE))
+ g_string_append_printf(string, "Interface %s\n\n", g_type_name(gtype));
+ else if (g_type_is_a(gtype, G_TYPE_OBJECT))
+ g_string_append_printf(string, "Object %s\n\n", g_type_name(gtype));
+ else
+ g_string_append_printf(string, "%s\n\n", g_type_name(gtype));
+
+ if (((PyTypeObject *) type)->tp_doc)
+ g_string_append_printf(string, "%s\n\n", ((PyTypeObject *) type)->tp_doc);
+
+ if (g_type_is_a(gtype, G_TYPE_OBJECT)) {
+ GType parent = G_TYPE_OBJECT;
+ GArray *parents = g_array_new(FALSE, FALSE, sizeof(GType));
+ int iparent;
+
+ while (parent) {
+ g_array_append_val(parents, parent);
+ parent = g_type_next_base(gtype, parent);
+ }
+
+ for (iparent = parents->len - 1; iparent >= 0; --iparent) {
+ GType *interfaces;
+ guint n_interfaces, i;
+
+ parent = g_array_index(parents, GType, iparent);
+ add_signal_docs(parent, string);
+ add_property_docs(parent, string);
+
+ /* add docs for implemented interfaces */
+ interfaces = g_type_interfaces(parent, &n_interfaces);
+ for (i = 0; i < n_interfaces; i++)
+ add_signal_docs(interfaces[i], string);
+ g_free(interfaces);
+ }
+ g_array_free(parents, TRUE);
+ }
+
+ pystring = PyUnicode_FromStringAndSize (string->str, string->len);
+ g_string_free(string, TRUE);
+ return pystring;
+}
+
+PYGI_DEFINE_TYPE("gobject.GObject.__doc__", PyGObjectDoc_Type, PyObject);
+
+/**
+ * pyg_object_descr_doc_get:
+ *
+ * Returns an object intended to be the __doc__ attribute of GObject
+ * wrappers. When read in the context of the object it will return
+ * some documentation about the signals and properties of the object.
+ *
+ * Returns: the descriptor.
+ */
+PyObject *
+pyg_object_descr_doc_get(void)
+{
+ static PyObject *doc_descr = NULL;
+
+ if (!doc_descr) {
+ Py_SET_TYPE(&PyGObjectDoc_Type, &PyType_Type);
+ if (PyType_Ready(&PyGObjectDoc_Type))
+ return NULL;
+
+ doc_descr = PyObject_NEW(PyObject, &PyGObjectDoc_Type);
+ if (doc_descr == NULL)
+ return NULL;
+ }
+ return doc_descr;
+}
+
+
+/**
+ * pyg_pyobj_to_unichar_conv:
+ *
+ * Converts PyObject value to a unichar and write result to memory
+ * pointed to by ptr. Follows the calling convention of a ParseArgs
+ * converter (O& format specifier) so it may be used to convert function
+ * arguments.
+ *
+ * Returns: 1 if the conversion succeeds and 0 otherwise. If the conversion
+ * did not succeesd, a Python exception is raised
+ */
+int pyg_pyobj_to_unichar_conv(PyObject* py_obj, void* ptr)
+{
+ if (!pygi_gunichar_from_py (py_obj, ptr))
+ return 0;
+ return 1;
+}
+
+gboolean
+pyg_gtype_is_custom(GType gtype)
+{
+ return g_type_get_qdata (gtype, pygobject_custom_key) != NULL;
+}
+
+static PyObject *
+strv_from_gvalue(const GValue *value)
+{
+ gchar **argv;
+ PyObject *py_argv;
+ gsize i;
+
+ argv = (gchar **) g_value_get_boxed (value);
+ py_argv = PyList_New (0);
+
+ for (i = 0; argv && argv[i]; i++) {
+ int res;
+ PyObject *item = pygi_utf8_to_py (argv[i]);
+ if (item == NULL) {
+ Py_DECREF (py_argv);
+ return NULL;
+ }
+ res = PyList_Append (py_argv, item);
+ Py_DECREF (item);
+ if (res == -1) {
+ Py_DECREF (py_argv);
+ return NULL;
+ }
+ }
+
+ return py_argv;
+}
+
+static int
+strv_to_gvalue(GValue *value, PyObject *obj)
+{
+ Py_ssize_t argc, i;
+ gchar **argv;
+
+ if (!(PyTuple_Check (obj) || PyList_Check (obj)))
+ return -1;
+
+ argc = PySequence_Length (obj);
+ argv = g_new (gchar *, argc + 1);
+ for (i = 0; i < argc; ++i) {
+ PyObject* item = PySequence_Fast_GET_ITEM (obj, i);
+ if (!pygi_utf8_from_py (item, &(argv[i])))
+ goto error;
+ }
+
+ argv[i] = NULL;
+ g_value_take_boxed (value, argv);
+ return 0;
+
+error:
+ for (i = i - 1; i >= 0; i--) {
+ g_free (argv[i]);
+ }
+ g_free (argv);
+ return -1;
+}
+
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_type_register_types(PyObject *d)
+{
+ PyGTypeWrapper_Type.tp_dealloc = (destructor)pyg_type_wrapper_dealloc;
+ PyGTypeWrapper_Type.tp_richcompare = pyg_type_wrapper_richcompare;
+ PyGTypeWrapper_Type.tp_repr = (reprfunc)pyg_type_wrapper_repr;
+ PyGTypeWrapper_Type.tp_hash = (hashfunc)pyg_type_wrapper_hash;
+ PyGTypeWrapper_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ PyGTypeWrapper_Type.tp_methods = _PyGTypeWrapper_methods;
+ PyGTypeWrapper_Type.tp_getset = _PyGTypeWrapper_getsets;
+ PyGTypeWrapper_Type.tp_init = (initproc)pyg_type_wrapper_init;
+ PyGTypeWrapper_Type.tp_alloc = PyType_GenericAlloc;
+ PyGTypeWrapper_Type.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyGTypeWrapper_Type))
+ return -1;
+
+ PyDict_SetItemString(d, "GType", (PyObject *)&PyGTypeWrapper_Type);
+
+ /* This type lazily registered in pyg_object_descr_doc_get */
+ PyGObjectDoc_Type.tp_dealloc = (destructor)object_doc_dealloc;
+ PyGObjectDoc_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ PyGObjectDoc_Type.tp_descr_get = (descrgetfunc)object_doc_descr_get;
+
+ pyg_register_gtype_custom (G_TYPE_STRV,
+ strv_from_gvalue,
+ strv_to_gvalue);
+
+ return 0;
+}
diff --git a/gi/pygi-type.h b/gi/pygi-type.h
index 01b5994..c7e1a45 100644
--- a/gi/pygi-type.h
+++ b/gi/pygi-type.h
@@ -1,7 +1,8 @@
/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- *
- * Copyright (C) 2009 Simon van der Linden <svdlinden@src.gnome.org>
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * 2004-2008 Johan Dahlin
+ * pyginterface.c: wrapper for the gobject library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -14,33 +15,52 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __PYGI_TYPE_H__
+#ifndef __PYGI_TYPE_H__
#define __PYGI_TYPE_H__
#include <Python.h>
+#include <glib-object.h>
+#include <girepository.h>
+#include "pygobject-internal.h"
+
+extern PyTypeObject PyGTypeWrapper_Type;
-G_BEGIN_DECLS
+typedef PyObject *(* fromvaluefunc)(const GValue *value);
+typedef int (*tovaluefunc)(GValue *value, PyObject *obj);
-/* Public */
+typedef struct {
+ fromvaluefunc fromvalue;
+ tovaluefunc tovalue;
+} PyGTypeMarshal;
-PyObject *pygi_type_import_by_g_type_real (GType g_type);
+PyGTypeMarshal *pyg_type_lookup(GType type);
+gboolean pyg_gtype_is_custom (GType gtype);
-/* Private */
+void pyg_register_gtype_custom(GType gtype,
+ fromvaluefunc from_func,
+ tovaluefunc to_func);
-PyObject *_pygi_type_import_by_name (const char *namespace_, const char *name);
+int pygi_type_register_types(PyObject *d);
-PyObject *_pygi_type_import_by_gi_info (GIBaseInfo *info);
+PyObject *pyg_object_descr_doc_get(void);
+PyObject *pyg_type_wrapper_new (GType type);
+GType pyg_type_from_object_strict (PyObject *obj, gboolean strict);
+GType pyg_type_from_object (PyObject *obj);
-PyObject *_pygi_type_get_from_g_type (GType g_type);
+int pyg_pyobj_to_unichar_conv (PyObject* py_obj, void* ptr);
-PyObject *_pygi_get_py_type_hint (GITypeTag type_tag);
+GClosure *pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data);
+GClosure *pyg_signal_class_closure_get(void);
+void pyg_closure_set_exception_handler(GClosure *closure,
+ PyClosureExceptionHandler handler);
-G_END_DECLS
+PyObject *pygi_type_import_by_g_type (GType g_type);
+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);
#endif /* __PYGI_TYPE_H__ */
diff --git a/gi/pygi-util.c b/gi/pygi-util.c
new file mode 100644
index 0000000..3a297f4
--- /dev/null
+++ b/gi/pygi-util.c
@@ -0,0 +1,126 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pygi-util.h"
+
+gboolean
+pygi_guint_from_pyssize (Py_ssize_t pyval, guint *result)
+{
+ if (pyval < 0) {
+ PyErr_SetString (PyExc_ValueError, "< 0");
+ return FALSE;
+ } else if (G_MAXUINT < PY_SSIZE_T_MAX && pyval > (Py_ssize_t)G_MAXUINT) {
+ PyErr_SetString (PyExc_ValueError, "too large");
+ return FALSE;
+ }
+ *result = (guint)pyval;
+ return TRUE;
+}
+
+PyObject *
+pyg_integer_richcompare(PyObject *v, PyObject *w, int op)
+{
+ PyObject *result;
+ gboolean t;
+
+ switch (op) {
+ case Py_EQ: t = PyLong_AS_LONG (v) == PyLong_AS_LONG (w); break;
+ case Py_NE: t = PyLong_AS_LONG (v) != PyLong_AS_LONG (w); break;
+ case Py_LE: t = PyLong_AS_LONG (v) <= PyLong_AS_LONG (w); break;
+ case Py_GE: t = PyLong_AS_LONG (v) >= PyLong_AS_LONG (w); break;
+ case Py_LT: t = PyLong_AS_LONG (v) < PyLong_AS_LONG (w); break;
+ case Py_GT: t = PyLong_AS_LONG (v) > PyLong_AS_LONG (w); break;
+ default: g_assert_not_reached();
+ }
+
+ result = t ? Py_True : Py_False;
+ Py_INCREF(result);
+ return result;
+}
+
+PyObject*
+pyg_ptr_richcompare(void* a, void *b, int op)
+{
+ PyObject *res;
+
+ switch (op) {
+ case Py_EQ:
+ res = (a == b) ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ res = (a != b) ? Py_True : Py_False;
+ break;
+ case Py_LT:
+ res = (a < b) ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ res = (a <= b) ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ res = (a > b) ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ res = (a >= b) ? Py_True : Py_False;
+ break;
+ default:
+ res = Py_NotImplemented;
+ break;
+ }
+
+ Py_INCREF(res);
+ return res;
+}
+
+/**
+ * pyg_constant_strip_prefix:
+ * @name: the constant name.
+ * @strip_prefix: the prefix to strip.
+ *
+ * Advances the pointer @name by strlen(@strip_prefix) characters. If
+ * the resulting name does not start with a letter or underscore, the
+ * @name pointer will be rewound. This is to ensure that the
+ * resulting name is a valid identifier. Hence the returned string is
+ * a pointer into the string @name.
+ *
+ * Returns: the stripped constant name.
+ */
+const gchar *
+pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix)
+{
+ size_t prefix_len, i;
+
+ prefix_len = strlen(strip_prefix);
+
+ /* Check so name starts with strip_prefix, if it doesn't:
+ * return the rest of the part which doesn't match
+ */
+ for (i = 0; i < prefix_len; i++) {
+ if (name[i] != strip_prefix[i] && name[i] != '_') {
+ return &name[i];
+ }
+ }
+
+ /* strip off prefix from value name, while keeping it a valid
+ * identifier */
+ for (i = prefix_len + 1; i > 0; i--) {
+ if (g_ascii_isalpha(name[i - 1]) || name[i - 1] == '_') {
+ return &name[i - 1];
+ }
+ }
+ return name;
+}
diff --git a/gi/pygi-util.h b/gi/pygi-util.h
new file mode 100644
index 0000000..a223730
--- /dev/null
+++ b/gi/pygi-util.h
@@ -0,0 +1,56 @@
+#ifndef __PYGI_UTIL_H__
+#define __PYGI_UTIL_H__
+
+#include <Python.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+PyObject * pyg_integer_richcompare(PyObject *v, PyObject *w, int op);
+PyObject * pyg_ptr_richcompare(void* a, void *b, int op);
+const gchar * pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix);
+
+gboolean pygi_guint_from_pyssize (Py_ssize_t pyval, guint *result);
+
+#if PY_VERSION_HEX < 0x030900A4
+# define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0)
+#endif
+
+#if PY_VERSION_HEX >= 0x03080000
+# define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_BEGIN(op, dealloc)
+# define CPy_TRASHCAN_END(op) Py_TRASHCAN_END
+#else
+# define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_SAFE_BEGIN(op)
+# define CPy_TRASHCAN_END(op) Py_TRASHCAN_SAFE_END(op)
+#endif
+
+#define PYGI_DEFINE_TYPE(typename, symbol, csymbol) \
+PyTypeObject symbol = { \
+ PyVarObject_HEAD_INIT(NULL, 0) \
+ typename, \
+ sizeof(csymbol) \
+};
+
+#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); \
+ Py_DECREF(py_error_prefix); \
+ } \
+} G_STMT_END
+
+
+G_END_DECLS
+
+#endif /* __PYGI_UTIL_H__ */
diff --git a/gi/pygi-value.c b/gi/pygi-value.c
new file mode 100644
index 0000000..e7ee1e0
--- /dev/null
+++ b/gi/pygi-value.c
@@ -0,0 +1,933 @@
+
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include "pygi-value.h"
+#include "pygi-struct.h"
+#include "pygi-basictype.h"
+#include "pygobject-object.h"
+#include "pygi-type.h"
+#include "pygenum.h"
+#include "pygpointer.h"
+#include "pygboxed.h"
+#include "pygflags.h"
+#include "pygparamspec.h"
+
+
+/* glib 2.62 has started to print warnings for these which can't be disabled selectively, so just copy them here */
+#define PYGI_TYPE_VALUE_ARRAY (g_value_array_get_type())
+#define PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), PYGI_TYPE_VALUE_ARRAY))
+#define PYGI_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), g_param_spec_types[18], GParamSpecValueArray))
+
+GIArgument
+_pygi_argument_from_g_value(const GValue *value,
+ GITypeInfo *type_info)
+{
+ GIArgument arg = { 0, };
+
+ GITypeTag type_tag = g_type_info_get_tag (type_info);
+
+ /* For the long handling: long can be equivalent to
+ int32 or int64, depending on the architecture, but
+ gi doesn't tell us (and same for ulong)
+ */
+ switch (type_tag) {
+ case GI_TYPE_TAG_BOOLEAN:
+ arg.v_boolean = g_value_get_boolean (value);
+ break;
+ case GI_TYPE_TAG_INT8:
+ arg.v_int8 = g_value_get_schar (value);
+ break;
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_INT32:
+ if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
+ arg.v_int32 = (gint32)g_value_get_long (value);
+ else
+ arg.v_int32 = (gint32)g_value_get_int (value);
+ break;
+ case GI_TYPE_TAG_INT64:
+ if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
+ arg.v_int64 = g_value_get_long (value);
+ else
+ arg.v_int64 = g_value_get_int64 (value);
+ break;
+ case GI_TYPE_TAG_UINT8:
+ arg.v_uint8 = g_value_get_uchar (value);
+ break;
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_UINT32:
+ if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
+ arg.v_uint32 = (guint32)g_value_get_ulong (value);
+ else
+ arg.v_uint32 = (guint32)g_value_get_uint (value);
+ break;
+ case GI_TYPE_TAG_UINT64:
+ if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
+ arg.v_uint64 = g_value_get_ulong (value);
+ else
+ arg.v_uint64 = g_value_get_uint64 (value);
+ break;
+ case GI_TYPE_TAG_UNICHAR:
+ arg.v_uint32 = g_value_get_schar (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_gtype (value);
+ break;
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ /* Callers are responsible for ensuring the GValue stays alive
+ * long enough for the string to be copied. */
+ arg.v_string = (char *)g_value_get_string (value);
+ break;
+ case GI_TYPE_TAG_GLIST:
+ case GI_TYPE_TAG_GSLIST:
+ case GI_TYPE_TAG_ARRAY:
+ case GI_TYPE_TAG_GHASH:
+ if (G_VALUE_HOLDS_BOXED (value))
+ arg.v_pointer = g_value_get_boxed (value);
+ else
+ /* e. g. GSettings::change-event */
+ arg.v_pointer = g_value_get_pointer (value);
+ break;
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIBaseInfo *info;
+ GIInfoType info_type;
+
+ info = g_type_info_get_interface (type_info);
+ info_type = g_base_info_get_type (info);
+
+ g_base_info_unref (info);
+
+ switch (info_type) {
+ case GI_INFO_TYPE_FLAGS:
+ arg.v_uint = g_value_get_flags (value);
+ break;
+ case GI_INFO_TYPE_ENUM:
+ arg.v_int = g_value_get_enum (value);
+ break;
+ case GI_INFO_TYPE_INTERFACE:
+ case GI_INFO_TYPE_OBJECT:
+ if (G_VALUE_HOLDS_PARAM (value))
+ arg.v_pointer = g_value_get_param (value);
+ else
+ 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_VALUE_HOLDS (value, G_TYPE_BOXED)) {
+ arg.v_pointer = g_value_get_boxed (value);
+ } else if (G_VALUE_HOLDS (value, G_TYPE_VARIANT)) {
+ arg.v_pointer = g_value_get_variant (value);
+ } else if (G_VALUE_HOLDS (value, G_TYPE_POINTER)) {
+ arg.v_pointer = g_value_get_pointer (value);
+ } else {
+ PyErr_Format (PyExc_NotImplementedError,
+ "Converting GValue's of type '%s' is not implemented.",
+ g_type_name (G_VALUE_TYPE (value)));
+ }
+ break;
+ default:
+ PyErr_Format (PyExc_NotImplementedError,
+ "Converting GValue's of type '%s' is not implemented.",
+ g_info_type_to_string (info_type));
+ break;
+ }
+ break;
+ }
+ case GI_TYPE_TAG_ERROR:
+ arg.v_pointer = g_value_get_boxed (value);
+ break;
+ case GI_TYPE_TAG_VOID:
+ arg.v_pointer = g_value_get_pointer (value);
+ break;
+ default:
+ break;
+ }
+
+ return arg;
+}
+
+
+/* Ignore g_value_array deprecations. Although they are deprecated,
+ * we still need to support the marshaling of them in PyGObject.
+ */
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+static int
+pyg_value_array_from_pyobject(GValue *value,
+ PyObject *obj,
+ const GParamSpecValueArray *pspec)
+{
+ Py_ssize_t seq_len;
+ GValueArray *value_array;
+ guint len, i;
+
+ seq_len = PySequence_Length(obj);
+ if (seq_len == -1) {
+ PyErr_Clear();
+ return -1;
+ }
+ len = (guint)seq_len;
+
+ if (pspec && pspec->fixed_n_elements > 0 && len != pspec->fixed_n_elements)
+ return -1;
+
+ value_array = g_value_array_new(len);
+
+ for (i = 0; i < len; ++i) {
+ PyObject *item = PySequence_GetItem(obj, i);
+ GType type;
+
+ if (! item) {
+ PyErr_Clear();
+ g_value_array_free(value_array);
+ return -1;
+ }
+
+ if (pspec && pspec->element_spec)
+ type = G_PARAM_SPEC_VALUE_TYPE(pspec->element_spec);
+ else if (item == Py_None)
+ type = G_TYPE_POINTER; /* store None as NULL */
+ else {
+ type = pyg_type_from_object((PyObject*)Py_TYPE(item));
+ if (! type) {
+ PyErr_Clear();
+ g_value_array_free(value_array);
+ Py_DECREF(item);
+ return -1;
+ }
+ }
+
+ if (type == G_TYPE_VALUE) {
+ const GValue * item_value = pyg_boxed_get(item, GValue);
+ g_value_array_append(value_array, item_value);
+ } else {
+ GValue item_value = { 0, };
+ int status;
+
+ g_value_init(&item_value, type);
+ status = (pspec && pspec->element_spec)
+ ? pyg_param_gvalue_from_pyobject(&item_value, item, pspec->element_spec)
+ : pyg_value_from_pyobject(&item_value, item);
+ Py_DECREF(item);
+
+ if (status == -1) {
+ g_value_array_free(value_array);
+ g_value_unset(&item_value);
+ return -1;
+ }
+ g_value_array_append(value_array, &item_value);
+ g_value_unset(&item_value);
+ }
+ }
+
+ g_value_take_boxed(value, value_array);
+ return 0;
+}
+
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+static int
+pyg_array_from_pyobject(GValue *value,
+ PyObject *obj)
+{
+ Py_ssize_t len, i;
+ GArray *array;
+
+ len = PySequence_Length(obj);
+ if (len == -1) {
+ PyErr_Clear();
+ return -1;
+ }
+
+ array = g_array_new(FALSE, TRUE, sizeof(GValue));
+
+ for (i = 0; i < len; ++i) {
+ PyObject *item = PySequence_GetItem(obj, i);
+ GType type;
+ GValue item_value = { 0, };
+ int status;
+
+ if (! item) {
+ PyErr_Clear();
+ g_array_free(array, FALSE);
+ return -1;
+ }
+
+ if (item == Py_None)
+ type = G_TYPE_POINTER; /* store None as NULL */
+ else {
+ type = pyg_type_from_object((PyObject*)Py_TYPE(item));
+ if (! type) {
+ PyErr_Clear();
+ g_array_free(array, FALSE);
+ Py_DECREF(item);
+ return -1;
+ }
+ }
+
+ g_value_init(&item_value, type);
+ status = pyg_value_from_pyobject(&item_value, item);
+ Py_DECREF(item);
+
+ if (status == -1) {
+ g_array_free(array, FALSE);
+ g_value_unset(&item_value);
+ return -1;
+ }
+
+ g_array_append_val(array, item_value);
+ }
+
+ g_value_take_boxed(value, array);
+ return 0;
+}
+
+/**
+ * pyg_value_from_pyobject_with_error:
+ * @value: the GValue object to store the converted value in.
+ * @obj: the Python object to convert.
+ *
+ * This function converts a Python object and stores the result in a
+ * GValue. The GValue must be initialised in advance with
+ * g_value_init(). If the Python object can't be converted to the
+ * type of the GValue, then an error is returned.
+ *
+ * Returns: 0 on success, -1 on error.
+ */
+int
+pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj)
+{
+ GType value_type = G_VALUE_TYPE(value);
+
+ switch (G_TYPE_FUNDAMENTAL(value_type)) {
+ case G_TYPE_INTERFACE:
+ /* we only handle interface types that have a GObject prereq */
+ if (g_type_is_a(value_type, G_TYPE_OBJECT)) {
+ if (obj == Py_None)
+ g_value_set_object(value, NULL);
+ else {
+ if (!PyObject_TypeCheck(obj, &PyGObject_Type)) {
+ PyErr_SetString(PyExc_TypeError, "GObject is required");
+ return -1;
+ }
+ if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
+ value_type)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid GObject type for assignment");
+ return -1;
+ }
+ g_value_set_object(value, pygobject_get(obj));
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Unsupported conversion");
+ return -1;
+ }
+ break;
+ case G_TYPE_CHAR:
+ {
+ gint8 temp;
+ if (pygi_gschar_from_py (obj, &temp)) {
+ g_value_set_schar (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_UCHAR:
+ {
+ guchar temp;
+ if (pygi_guchar_from_py (obj, &temp)) {
+ g_value_set_uchar (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_BOOLEAN:
+ {
+ gboolean temp;
+ if (pygi_gboolean_from_py (obj, &temp)) {
+ g_value_set_boolean (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_INT:
+ {
+ gint temp;
+ if (pygi_gint_from_py (obj, &temp)) {
+ g_value_set_int (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_UINT:
+ {
+ guint temp;
+ if (pygi_guint_from_py (obj, &temp)) {
+ g_value_set_uint (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_LONG:
+ {
+ glong temp;
+ if (pygi_glong_from_py (obj, &temp)) {
+ g_value_set_long (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_ULONG:
+ {
+ gulong temp;
+ if (pygi_gulong_from_py (obj, &temp)) {
+ g_value_set_ulong (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_INT64:
+ {
+ gint64 temp;
+ if (pygi_gint64_from_py (obj, &temp)) {
+ g_value_set_int64 (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_UINT64:
+ {
+ guint64 temp;
+ if (pygi_guint64_from_py (obj, &temp)) {
+ g_value_set_uint64 (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_ENUM:
+ {
+ gint val = 0;
+ if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
+ return -1;
+ }
+ g_value_set_enum(value, val);
+ }
+ break;
+ case G_TYPE_FLAGS:
+ {
+ guint val = 0;
+ if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
+ return -1;
+ }
+ g_value_set_flags(value, val);
+ return 0;
+ }
+ break;
+ case G_TYPE_FLOAT:
+ {
+ gfloat temp;
+ if (pygi_gfloat_from_py (obj, &temp)) {
+ g_value_set_float (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_DOUBLE:
+ {
+ gdouble temp;
+ if (pygi_gdouble_from_py (obj, &temp)) {
+ g_value_set_double (value, temp);
+ return 0;
+ } else
+ return -1;
+ }
+ case G_TYPE_STRING:
+ {
+ gchar *temp;
+ if (pygi_utf8_from_py (obj, &temp)) {
+ g_value_take_string (value, temp);
+ return 0;
+ } else {
+ /* also allows setting anything implementing __str__ */
+ PyObject* str;
+ PyErr_Clear ();
+ str = PyObject_Str (obj);
+ if (str == NULL)
+ return -1;
+ if (pygi_utf8_from_py (str, &temp)) {
+ Py_DECREF (str);
+ g_value_take_string (value, temp);
+ return 0;
+ }
+ Py_DECREF (str);
+ return -1;
+ }
+ }
+ case G_TYPE_POINTER:
+ if (obj == Py_None)
+ g_value_set_pointer(value, NULL);
+ else if (PyObject_TypeCheck(obj, &PyGPointer_Type) &&
+ G_VALUE_HOLDS(value, ((PyGPointer *)obj)->gtype))
+ g_value_set_pointer(value, pyg_pointer_get(obj, gpointer));
+ else if (PyCapsule_CheckExact (obj))
+ g_value_set_pointer(value, PyCapsule_GetPointer (obj, NULL));
+ else if (G_VALUE_HOLDS_GTYPE (value))
+ g_value_set_gtype (value, pyg_type_from_object (obj));
+ else {
+ PyErr_SetString(PyExc_TypeError, "Expected pointer");
+ return -1;
+ }
+ break;
+ case G_TYPE_BOXED: {
+ PyGTypeMarshal *bm;
+ gboolean holds_value_array;
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ holds_value_array = G_VALUE_HOLDS(value, PYGI_TYPE_VALUE_ARRAY);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ if (obj == Py_None)
+ g_value_set_boxed(value, NULL);
+ else if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
+ g_value_set_boxed(value, obj);
+ else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) &&
+ G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype))
+ g_value_set_boxed(value, pyg_boxed_get(obj, gpointer));
+ else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
+ GType type;
+ GValue *n_value;
+
+ type = pyg_type_from_object((PyObject*)Py_TYPE(obj));
+ if (G_UNLIKELY (! type)) {
+ return -1;
+ }
+ n_value = g_new0 (GValue, 1);
+ g_value_init (n_value, type);
+ g_value_take_boxed (value, n_value);
+ return pyg_value_from_pyobject_with_error (n_value, obj);
+ }
+ else if (PySequence_Check(obj) && holds_value_array)
+ return pyg_value_array_from_pyobject(value, obj, NULL);
+
+ else if (PySequence_Check(obj) &&
+ G_VALUE_HOLDS(value, G_TYPE_ARRAY))
+ return pyg_array_from_pyobject(value, obj);
+ else if (PyUnicode_Check (obj) &&
+ G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
+ GString *string;
+ char *buffer;
+ Py_ssize_t len;
+ buffer = PyUnicode_AsUTF8AndSize (obj, &len);
+ if (buffer == NULL)
+ return -1;
+ string = g_string_new_len(buffer, len);
+ g_value_set_boxed(value, string);
+ g_string_free (string, TRUE);
+ break;
+ }
+ else if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
+ return bm->tovalue(value, obj);
+ else if (PyCapsule_CheckExact (obj))
+ g_value_set_boxed(value, PyCapsule_GetPointer (obj, NULL));
+ else {
+ PyErr_SetString(PyExc_TypeError, "Expected Boxed");
+ return -1;
+ }
+ break;
+ }
+ case G_TYPE_PARAM:
+ /* we need to support both the wrapped _gi.GParamSpec and the GI
+ * GObject.ParamSpec */
+ if (G_IS_PARAM_SPEC (pygobject_get (obj)))
+ g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj)));
+ else if (pyg_param_spec_check (obj))
+ g_value_set_param(value, PyCapsule_GetPointer (obj, NULL));
+ else {
+ PyErr_SetString(PyExc_TypeError, "Expected ParamSpec");
+ return -1;
+ }
+ break;
+ case G_TYPE_OBJECT:
+ if (obj == Py_None) {
+ g_value_set_object(value, NULL);
+ } else if (PyObject_TypeCheck(obj, &PyGObject_Type) &&
+ G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
+ G_VALUE_TYPE(value))) {
+ g_value_set_object(value, pygobject_get(obj));
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Expected GObject");
+ return -1;
+ }
+ break;
+ case G_TYPE_VARIANT:
+ {
+ if (obj == Py_None)
+ g_value_set_variant(value, NULL);
+ else if (pyg_type_from_object_strict(obj, FALSE) == G_TYPE_VARIANT)
+ g_value_set_variant(value, pyg_boxed_get(obj, GVariant));
+ else {
+ PyErr_SetString(PyExc_TypeError, "Expected Variant");
+ return -1;
+ }
+ break;
+ }
+ default:
+ {
+ PyGTypeMarshal *bm;
+ if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) {
+ return bm->tovalue(value, obj);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Unknown value type");
+ return -1;
+ }
+ break;
+ }
+ }
+
+ /* If an error occurred, unset the GValue but don't clear the Python error. */
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * pyg_value_from_pyobject:
+ * @value: the GValue object to store the converted value in.
+ * @obj: the Python object to convert.
+ *
+ * Same basic function as pyg_value_from_pyobject_with_error but clears
+ * any Python errors before returning.
+ *
+ * Returns: 0 on success, -1 on error.
+ */
+int
+pyg_value_from_pyobject(GValue *value, PyObject *obj)
+{
+ int res = pyg_value_from_pyobject_with_error (value, obj);
+
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ return -1;
+ }
+ return res;
+}
+
+/**
+ * pygi_value_to_py_basic_type:
+ * @value: the GValue object.
+ * @handled: (out): TRUE if the return value is defined
+ *
+ * This function creates/returns a Python wrapper object that
+ * represents the GValue passed as an argument limited to supporting basic types
+ * like ints, bools, and strings.
+ *
+ * Returns: a PyObject representing the value.
+ */
+PyObject *
+pygi_value_to_py_basic_type (const GValue *value, GType fundamental, gboolean *handled)
+{
+ *handled = TRUE;
+ switch (fundamental) {
+ case G_TYPE_CHAR:
+ return PyLong_FromLong (g_value_get_schar (value));
+ case G_TYPE_UCHAR:
+ return PyLong_FromLong (g_value_get_uchar (value));
+ case G_TYPE_BOOLEAN:
+ return pygi_gboolean_to_py (g_value_get_boolean (value));
+ case G_TYPE_INT:
+ return pygi_gint_to_py (g_value_get_int (value));
+ case G_TYPE_UINT:
+ return pygi_guint_to_py (g_value_get_uint (value));
+ case G_TYPE_LONG:
+ return pygi_glong_to_py (g_value_get_long(value));
+ case G_TYPE_ULONG:
+ return pygi_gulong_to_py (g_value_get_ulong (value));
+ case G_TYPE_INT64:
+ return pygi_gint64_to_py (g_value_get_int64 (value));
+ case G_TYPE_UINT64:
+ return pygi_guint64_to_py (g_value_get_uint64 (value));
+ case G_TYPE_ENUM:
+ return pyg_enum_from_gtype (G_VALUE_TYPE (value),
+ g_value_get_enum (value));
+ case G_TYPE_FLAGS:
+ return pyg_flags_from_gtype (G_VALUE_TYPE (value),
+ g_value_get_flags (value));
+ case G_TYPE_FLOAT:
+ return pygi_gfloat_to_py (g_value_get_float (value));
+ case G_TYPE_DOUBLE:
+ return pygi_gdouble_to_py (g_value_get_double (value));
+ case G_TYPE_STRING:
+ return pygi_utf8_to_py (g_value_get_string (value));
+ default:
+ *handled = FALSE;
+ return NULL;
+ }
+}
+
+/**
+ * value_to_py_structured_type:
+ * @value: the GValue object.
+ * @copy_boxed: true if boxed values should be copied.
+ *
+ * This function creates/returns a Python wrapper object that
+ * represents the GValue passed as an argument.
+ *
+ * Returns: a PyObject representing the value or NULL and sets an error;
+ */
+static PyObject *
+value_to_py_structured_type (const GValue *value, GType fundamental, gboolean copy_boxed)
+{
+ const gchar *type_name;
+
+ switch (fundamental) {
+ case G_TYPE_INTERFACE:
+ if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_OBJECT))
+ return pygobject_new(g_value_get_object(value));
+ else
+ break;
+
+ case G_TYPE_POINTER:
+ if (G_VALUE_HOLDS_GTYPE (value))
+ return pyg_type_wrapper_new (g_value_get_gtype (value));
+ else
+ return pyg_pointer_new(G_VALUE_TYPE(value),
+ g_value_get_pointer(value));
+ case G_TYPE_BOXED: {
+ PyGTypeMarshal *bm;
+ gboolean holds_value_array;
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ holds_value_array = G_VALUE_HOLDS(value, PYGI_TYPE_VALUE_ARRAY);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) {
+ PyObject *ret = (PyObject *)g_value_dup_boxed(value);
+ if (ret == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return ret;
+ } else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
+ GValue *n_value = g_value_get_boxed (value);
+ return pyg_value_as_pyobject(n_value, copy_boxed);
+ } else if (holds_value_array) {
+ GValueArray *array = (GValueArray *) g_value_get_boxed(value);
+ Py_ssize_t n_values = array ? array->n_values : 0;
+ PyObject *ret = PyList_New(n_values);
+ int i;
+ for (i = 0; i < n_values; ++i)
+ PyList_SET_ITEM(ret, i, pyg_value_as_pyobject
+ (array->values + i, copy_boxed));
+ return ret;
+ } else if (G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
+ GString *string = (GString *) g_value_get_boxed(value);
+ PyObject *ret = PyUnicode_FromStringAndSize (string->str, string->len);
+ return ret;
+ }
+ bm = pyg_type_lookup(G_VALUE_TYPE(value));
+ if (bm) {
+ return bm->fromvalue(value);
+ } else {
+ if (copy_boxed)
+ return pygi_gboxed_new(G_VALUE_TYPE(value),
+ g_value_get_boxed(value), TRUE, TRUE);
+ else
+ return pygi_gboxed_new(G_VALUE_TYPE(value),
+ g_value_get_boxed(value),FALSE,FALSE);
+ }
+ }
+ case G_TYPE_PARAM:
+ return pyg_param_spec_new(g_value_get_param(value));
+ case G_TYPE_OBJECT:
+ return pygobject_new(g_value_get_object(value));
+ case G_TYPE_VARIANT:
+ {
+ GVariant *v = g_value_get_variant(value);
+ if (v == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return pygi_struct_new_from_g_type (G_TYPE_VARIANT, g_variant_ref(v), FALSE);
+ }
+ default:
+ {
+ PyGTypeMarshal *bm;
+ if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))))
+ return bm->fromvalue(value);
+ break;
+ }
+ }
+
+ type_name = g_type_name (G_VALUE_TYPE (value));
+ if (type_name == NULL) {
+ type_name = "(null)";
+ }
+ PyErr_Format (PyExc_TypeError, "unknown type %s", type_name);
+ return NULL;
+}
+
+
+/**
+ * pyg_value_as_pyobject:
+ * @value: the GValue object.
+ * @copy_boxed: true if boxed values should be copied.
+ *
+ * This function creates/returns a Python wrapper object that
+ * represents the GValue passed as an argument.
+ *
+ * Returns: a PyObject representing the value or %NULL and sets an exception.
+ */
+PyObject *
+pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed)
+{
+ PyObject *pyobj;
+ gboolean handled;
+ GType fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value));
+
+ /* HACK: special case char and uchar to return PyBytes intstead of integers
+ * in the general case. Property access will skip this by calling
+ * pygi_value_to_py_basic_type() directly.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=733893 */
+ if (fundamental == G_TYPE_CHAR) {
+ gint8 val = g_value_get_schar(value);
+ return PyUnicode_FromStringAndSize ((char *)&val, 1);
+ } else if (fundamental == G_TYPE_UCHAR) {
+ guint8 val = g_value_get_uchar(value);
+ return PyBytes_FromStringAndSize ((char *)&val, 1);
+ }
+
+ pyobj = pygi_value_to_py_basic_type (value, fundamental, &handled);
+ if (handled)
+ return pyobj;
+
+ pyobj = value_to_py_structured_type (value, fundamental, copy_boxed);
+ return pyobj;
+}
+
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+int
+pyg_param_gvalue_from_pyobject(GValue* value,
+ PyObject* py_obj,
+ const GParamSpec* pspec)
+{
+ if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
+ gunichar u;
+
+ if (!pyg_pyobj_to_unichar_conv(py_obj, &u)) {
+ PyErr_Clear();
+ return -1;
+ }
+ g_value_set_uint(value, u);
+ return 0;
+ }
+ else if (PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec))
+ return pyg_value_array_from_pyobject(value, py_obj,
+ PYGI_PARAM_SPEC_VALUE_ARRAY(pspec));
+ else {
+ return pyg_value_from_pyobject(value, py_obj);
+ }
+}
+
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+PyObject*
+pyg_param_gvalue_as_pyobject(const GValue* gvalue,
+ gboolean copy_boxed,
+ const GParamSpec* pspec)
+{
+ if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
+ gunichar u;
+ gchar *encoded;
+ PyObject *retval;
+
+ u = g_value_get_uint (gvalue);
+ encoded = g_ucs4_to_utf8 (&u, 1, NULL, NULL, NULL);
+ if (encoded == NULL) {
+ PyErr_SetString (PyExc_ValueError, "Failed to decode");
+ return NULL;
+ }
+ retval = PyUnicode_FromString (encoded);
+ g_free (encoded);
+ return retval;
+ }
+ else {
+ return pyg_value_as_pyobject(gvalue, copy_boxed);
+ }
+}
+
+PyObject *
+pyg__gvalue_get(PyObject *module, PyObject *pygvalue)
+{
+ if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
+ PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
+ return NULL;
+ }
+
+ return pyg_value_as_pyobject (pyg_boxed_get(pygvalue, GValue),
+ /*copy_boxed=*/ TRUE);
+}
+
+PyObject *
+pyg__gvalue_get_type(PyObject *module, PyObject *pygvalue)
+{
+ GValue *value;
+ GType type;
+
+ if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
+ PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
+ return NULL;
+ }
+
+ value = pyg_boxed_get (pygvalue, GValue);
+ type = G_VALUE_TYPE (value);
+ return pyg_type_wrapper_new (type);
+}
+
+PyObject *
+pyg__gvalue_set(PyObject *module, PyObject *args)
+{
+ PyObject *pygvalue;
+ PyObject *pyobject;
+
+ if (!PyArg_ParseTuple (args, "OO:_gi._gvalue_set",
+ &pygvalue, &pyobject))
+ return NULL;
+
+ if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
+ PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
+ return NULL;
+ }
+
+ if (pyg_value_from_pyobject_with_error (pyg_boxed_get (pygvalue, GValue),
+ pyobject) == -1)
+ return NULL;
+
+ Py_RETURN_NONE;
+}
diff --git a/gi/pygi-value.h b/gi/pygi-value.h
new file mode 100644
index 0000000..5778a22
--- /dev/null
+++ b/gi/pygi-value.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_VALUE_H__
+#define __PYGI_VALUE_H__
+
+#include <Python.h>
+#include <glib-object.h>
+#include <girepository.h>
+
+G_BEGIN_DECLS
+
+GIArgument _pygi_argument_from_g_value(const GValue *value,
+ GITypeInfo *type_info);
+
+int pyg_value_from_pyobject(GValue *value, PyObject *obj);
+int pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj);
+PyObject *pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed);
+int pyg_param_gvalue_from_pyobject(GValue* value,
+ PyObject* py_obj,
+ const GParamSpec* pspec);
+PyObject *pyg_param_gvalue_as_pyobject(const GValue* gvalue,
+ gboolean copy_boxed,
+ const GParamSpec* pspec);
+PyObject *pyg_strv_from_gvalue(const GValue *value);
+int pyg_strv_to_gvalue(GValue *value, PyObject *obj);
+
+PyObject *pygi_value_to_py_basic_type (const GValue *value,
+ GType fundamental,
+ gboolean *handled);
+
+PyObject *pyg__gvalue_get(PyObject *module, PyObject *pygvalue);
+PyObject *pyg__gvalue_set(PyObject *module, PyObject *args);
+PyObject *pyg__gvalue_get_type(PyObject *module, PyObject *pygvalue);
+
+G_END_DECLS
+
+#endif /* __PYGI_VALUE_H__ */
diff --git a/gi/pygi.h b/gi/pygi.h
deleted file mode 100644
index 3bf40bb..0000000
--- a/gi/pygi.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- *
- * Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGI_H__
-#define __PYGI_H__
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#define NO_IMPORT_PYGOBJECT
-#include <pygobject.h>
-
-#include <girepository.h>
-#include "pygi-cache.h"
-
-extern PyObject *PyGIDeprecationWarning;
-
-typedef struct {
- PyObject_HEAD
- GIRepository *repository;
-} PyGIRepository;
-
-typedef struct {
- PyObject_HEAD
- GIBaseInfo *info;
- PyObject *inst_weakreflist;
- PyGICallableCache *cache;
-} PyGIBaseInfo;
-
-typedef struct {
- PyGIBaseInfo base;
-
- /* Reference the unbound version of this struct.
- * We use this for the actual call to invoke because it manages the cache.
- */
- struct PyGICallableInfo *py_unbound_info;
-
- /* Holds bound argument for instance, class, and vfunc methods. */
- PyObject *py_bound_arg;
-
-} PyGICallableInfo;
-
-typedef struct {
- PyGPointer base;
- gboolean free_on_dealloc;
-} PyGIStruct;
-
-typedef struct {
- PyGBoxed base;
- gboolean slice_allocated;
- gsize size;
-} PyGIBoxed;
-
-typedef struct {
- PyObject_HEAD
- GCallback callback;
- GIFunctionInfo *info;
- gpointer user_data;
- GIScopeType scope;
- GDestroyNotify destroy_notify_func;
- PyGICallableCache *cache;
-} PyGICCallback;
-
-typedef PyObject * (*PyGIArgOverrideToGIArgumentFunc) (PyObject *value,
- GIInterfaceInfo *interface_info,
- GITransfer transfer,
- GIArgument *arg);
-typedef PyObject * (*PyGIArgOverrideFromGIArgumentFunc) (GIInterfaceInfo *interface_info,
- gpointer data);
-typedef PyObject * (*PyGIArgOverrideReleaseFunc) (GITypeInfo *type_info,
- gpointer struct_);
-
-struct PyGI_API {
- PyObject* (*type_import_by_g_type) (GType g_type);
- PyObject* (*get_property_value) (PyGObject *instance,
- GParamSpec *pspec);
- gint (*set_property_value) (PyGObject *instance,
- GParamSpec *pspec,
- PyObject *value);
- GClosure * (*signal_closure_new) (PyGObject *instance,
- GType g_type,
- const gchar *sig_name,
- PyObject *callback,
- PyObject *extra_args,
- PyObject *swap_data);
- void (*register_foreign_struct) (const char* namespace_,
- const char* name,
- PyGIArgOverrideToGIArgumentFunc to_func,
- PyGIArgOverrideFromGIArgumentFunc from_func,
- PyGIArgOverrideReleaseFunc release_func);
-};
-
-static struct PyGI_API *PyGI_API = NULL;
-
-static int
-_pygi_import (void)
-{
- if (PyGI_API != NULL) {
- return 1;
- }
- PyGI_API = (struct PyGI_API*) PyCapsule_Import("gi._API", FALSE);
- if (PyGI_API == NULL) {
- return -1;
- }
-
- return 0;
-}
-
-static inline PyObject *
-pygi_type_import_by_g_type (GType g_type)
-{
- if (_pygi_import() < 0) {
- return NULL;
- }
- return PyGI_API->type_import_by_g_type(g_type);
-}
-
-static inline PyObject *
-pygi_get_property_value (PyGObject *instance,
- GParamSpec *pspec)
-{
- if (_pygi_import() < 0) {
- return NULL;
- }
- return PyGI_API->get_property_value(instance, pspec);
-}
-
-static inline gint
-pygi_set_property_value (PyGObject *instance,
- GParamSpec *pspec,
- PyObject *value)
-{
- if (_pygi_import() < 0) {
- return -1;
- }
- return PyGI_API->set_property_value(instance, pspec, value);
-}
-
-static inline GClosure *
-pygi_signal_closure_new (PyGObject *instance,
- GType g_type,
- const gchar *sig_name,
- PyObject *callback,
- PyObject *extra_args,
- PyObject *swap_data)
-{
- if (_pygi_import() < 0) {
- return NULL;
- }
- return PyGI_API->signal_closure_new(instance, g_type, sig_name, callback, extra_args, swap_data);
-}
-
-static inline PyObject *
-pygi_register_foreign_struct (const char* namespace_,
- const char* name,
- PyGIArgOverrideToGIArgumentFunc to_func,
- PyGIArgOverrideFromGIArgumentFunc from_func,
- PyGIArgOverrideReleaseFunc release_func)
-{
- if (_pygi_import() < 0) {
- return NULL;
- }
- PyGI_API->register_foreign_struct(namespace_,
- name,
- to_func,
- from_func,
- release_func);
- Py_RETURN_NONE;
-}
-
-#endif /* __PYGI_H__ */
diff --git a/gi/_gobject/pyginterface.c b/gi/pyginterface.c
index eb76ba0..288fbb2 100644
--- a/gi/_gobject/pyginterface.c
+++ b/gi/pyginterface.c
@@ -15,25 +15,22 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
#include <Python.h>
-#include "pyglib.h"
-#include "pygobject-private.h"
+#include <glib-object.h>
+#include "pygi-util.h"
#include "pyginterface.h"
+#include "pygi-type.h"
GQuark pyginterface_type_key;
GQuark pyginterface_info_key;
-PYGLIB_DEFINE_TYPE("gobject.GInterface", PyGInterface_Type, PyObject)
+PYGI_DEFINE_TYPE("gobject.GInterface", PyGInterface_Type, PyObject)
static int
pyg_interface_init(PyObject *self, PyObject *args, PyObject *kwargs)
@@ -72,7 +69,8 @@ pyg_register_interface(PyObject *dict, const gchar *class_name,
{
PyObject *o;
- Py_TYPE(type) = &PyType_Type;
+ Py_SET_TYPE(type, &PyType_Type);
+ g_assert (Py_TYPE (&PyGInterface_Type) != NULL);
type->tp_base = &PyGInterface_Type;
if (PyType_Ready(type) < 0) {
@@ -87,15 +85,21 @@ pyg_register_interface(PyObject *dict, const gchar *class_name,
}
g_type_set_qdata(gtype, pyginterface_type_key, type);
-
+
PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type);
-
+
}
void
pyg_register_interface_info(GType gtype, const GInterfaceInfo *info)
{
- g_type_set_qdata(gtype, pyginterface_info_key, (gpointer) info);
+ GInterfaceInfo *prev_info = pyg_lookup_interface_info (gtype);
+
+ if (prev_info) {
+ g_free (prev_info);
+ }
+
+ g_type_set_qdata(gtype, pyginterface_info_key, g_memdup2 (info, sizeof(GInterfaceInfo)));
}
const GInterfaceInfo *
@@ -104,21 +108,35 @@ pyg_lookup_interface_info(GType gtype)
return g_type_get_qdata(gtype, pyginterface_info_key);
}
-void
-pygobject_interface_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_interface_register_types(PyObject *d)
{
- pyginterface_type_key = g_quark_from_static_string("PyGInterface::type");
- pyginterface_info_key = g_quark_from_static_string("PyGInterface::info");
+ PyObject *pygtype;
+
+ pyginterface_type_key = g_quark_from_static_string("PyGInterface::type");
+ pyginterface_info_key = g_quark_from_static_string("PyGInterface::info");
+
+ PyGInterface_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
+ PyGInterface_Type.tp_init = (initproc)pyg_interface_init;
+ PyGInterface_Type.tp_free = (freefunc)pyg_interface_free;
+ PyGInterface_Type.tp_alloc = PyType_GenericAlloc;
+ PyGInterface_Type.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyGInterface_Type))
+ return -1;
+
+ pygtype = pyg_type_wrapper_new (G_TYPE_INTERFACE);
+ PyDict_SetItemString (PyGInterface_Type.tp_dict, "__gtype__", pygtype);
+ Py_DECREF (pygtype);
- PyGInterface_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
- PyGInterface_Type.tp_init = (initproc)pyg_interface_init;
- PyGInterface_Type.tp_free = (freefunc)pyg_interface_free;
+ PyDict_SetItemString(PyGInterface_Type.tp_dict, "__doc__",
+ pyg_object_descr_doc_get());
+ PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gdoc__",
+ pyg_object_descr_doc_get());
- PYGOBJECT_REGISTER_GTYPE(d, PyGInterface_Type, "GInterface", G_TYPE_INTERFACE)
+ PyDict_SetItemString(d, "GInterface", (PyObject *)&PyGInterface_Type);
- PyDict_SetItemString(PyGInterface_Type.tp_dict, "__doc__",
- pyg_object_descr_doc_get());
- PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gdoc__",
- pyg_object_descr_doc_get());
-
+ return 0;
}
diff --git a/gi/_gobject/pyginterface.h b/gi/pyginterface.h
index 0f390c2..d5819ce 100644
--- a/gi/_gobject/pyginterface.h
+++ b/gi/pyginterface.h
@@ -15,9 +15,7 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGOBJECT_INTERFACE_H__
@@ -35,6 +33,6 @@ void pyg_register_interface(PyObject *dict,
const GInterfaceInfo * pyg_lookup_interface_info(GType gtype);
void pyg_register_interface_info(GType gtype, const
GInterfaceInfo *info);
-void pygobject_interface_register_types(PyObject *d);
+int pygi_interface_register_types(PyObject *d);
#endif /* __PYGOBJECT_INTERFACE_H__ */
diff --git a/gi/pygobject-external.h b/gi/pygobject-external.h
deleted file mode 100644
index 8299864..0000000
--- a/gi/pygobject-external.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*-
- * vim: tabstop=4 shiftwidth=4 expandtab
- *
- * Copyright (C) 2009 Simon van der Linden <svdlinden@src.gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#ifndef __PYGOBJECT_EXTERN_H__
-#define __PYGOBJECT_EXTERN_H__
-
-#include <Python.h>
-
-G_BEGIN_DECLS
-
-static PyTypeObject *_PyGTypeWrapper_Type;
-
-#define PyGTypeWrapper_Type (*_PyGTypeWrapper_Type)
-
-G_GNUC_UNUSED
-static int
-_pygobject_import (void)
-{
- static gboolean imported = FALSE;
- PyObject *from_list;
- PyObject *module;
- int retval = 0;
-
- if (imported) {
- return 1;
- }
-
- from_list = Py_BuildValue ("(s)", "GType");
- if (from_list == NULL) {
- return -1;
- }
-
- module = PyImport_ImportModuleEx ("gi._gobject", NULL, NULL, from_list);
-
- Py_DECREF (from_list);
-
- if (module == NULL) {
- return -1;
- }
-
- _PyGTypeWrapper_Type = (PyTypeObject *) PyObject_GetAttrString (module, "GType");
- if (_PyGTypeWrapper_Type == NULL) {
- retval = -1;
- goto out;
- }
-
- imported = TRUE;
-
-out:
- Py_DECREF (module);
-
- return retval;
-}
-
-G_END_DECLS
-
-#endif /* __PYGOBJECT_EXTERN_H__ */
diff --git a/gi/pygobject-internal.h b/gi/pygobject-internal.h
new file mode 100644
index 0000000..2cd82c5
--- /dev/null
+++ b/gi/pygobject-internal.h
@@ -0,0 +1,7 @@
+#ifndef _PYGOBJECT_INTERNAL_H_
+#define _PYGOBJECT_INTERNAL_H_
+
+#define _INSIDE_PYGOBJECT_
+#include "pygobject.h"
+
+#endif /*_PYGOBJECT_INTERNAL_H_*/
diff --git a/gi/_gobject/pygobject.c b/gi/pygobject-object.c
index 126c80e..961f6dd 100644
--- a/gi/_gobject/pygobject.c
+++ b/gi/pygobject-object.c
@@ -15,31 +15,32 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
-#include <pyglib.h>
-#include "pygobject-private.h"
+#include "pygobject-object.h"
#include "pyginterface.h"
#include "pygparamspec.h"
+#include "pygi-type.h"
+#include "pygboxed.h"
+#include "gimodule.h"
-#include "pygi.h"
+#include "pygi-util.h"
+#include "pygi-value.h"
+#include "pygi-type.h"
+#include "pygi-property.h"
+#include "pygi-signal-closure.h"
+#include "pygi-basictype.h"
+extern PyObject *PyGIDeprecationWarning;
static void pygobject_dealloc(PyGObject *self);
static int pygobject_traverse(PyGObject *self, visitproc visit, void *arg);
-static int pygobject_clear(PyGObject *self);
static PyObject * pyg_type_get_bases(GType gtype);
static inline int pygobject_clear(PyGObject *self);
static PyObject * pygobject_weak_ref_new(GObject *obj, PyObject *callback, PyObject *user_data);
-static PyObject * pygbinding_weak_ref_new(GObject *obj);
-static inline PyGObjectData * pyg_object_peek_inst_data(GObject *obj);
static void pygobject_inherit_slots(PyTypeObject *type, PyObject *bases,
gboolean check_for_present);
static void pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset,
@@ -52,6 +53,31 @@ GQuark pygobject_wrapper_key;
GQuark pygobject_has_updated_constructor_key;
GQuark pygobject_instance_data_key;
+/* PyPy doesn't support tp_dictoffset, so we have to work around it */
+#ifndef PYPY_VERSION
+#define PYGI_OBJECT_USE_CUSTOM_DICT
+#endif
+
+GClosure *
+gclosure_from_pyfunc(PyGObject *object, PyObject *func)
+{
+ GSList *l;
+ PyGObjectData *inst_data;
+ inst_data = pyg_object_peek_inst_data(object->obj);
+ if (inst_data) {
+ for (l = inst_data->closures; l; l = l->next) {
+ PyGClosure *pyclosure = l->data;
+ int res = PyObject_RichCompareBool(pyclosure->callback, func, Py_EQ);
+ if (res == -1) {
+ PyErr_Clear(); /* Is there anything else to do? */
+ } else if (res) {
+ return (GClosure*)pyclosure;
+ }
+ }
+ }
+ return NULL;
+}
+
/* Copied from glib. gobject uses hyphens in property names, but in Python
* we can only represent hyphens as underscores. Convert underscores to
* hyphens for glib compatibility. */
@@ -74,19 +100,20 @@ canonicalize_key (gchar *key)
/* -------------- class <-> wrapper manipulation --------------- */
-void
+static void
pygobject_data_free(PyGObjectData *data)
{
/* This function may be called after the python interpreter has already
* been shut down. If this happens, we cannot do any python calls, so just
* free the memory. */
- PyGILState_STATE state;
+ PyGILState_STATE state = 0;
PyThreadState *_save = NULL;
-
+ gboolean state_saved;
GSList *closures, *tmp;
- if (Py_IsInitialized()) {
- state = pyglib_gil_state_ensure();
+ state_saved = Py_IsInitialized();
+ if (state_saved) {
+ state = PyGILState_Ensure();
Py_DECREF(data->type);
/* We cannot use Py_BEGIN_ALLOW_THREADS here because this is inside
* a branch. */
@@ -112,9 +139,9 @@ pygobject_data_free(PyGObjectData *data)
g_free(data);
- if (Py_IsInitialized()) {
+ if (state_saved && Py_IsInitialized ()) {
Py_BLOCK_THREADS; /* Restores _save */
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
}
}
@@ -180,7 +207,7 @@ typedef struct {
guint index;
} PyGPropsIter;
-PYGLIB_DEFINE_TYPE("gi._gobject.GPropsIter", PyGPropsIter_Type, PyGPropsIter);
+PYGI_DEFINE_TYPE("gi._gi.GPropsIter", PyGPropsIter_Type, PyGPropsIter);
static void
pyg_props_iter_dealloc(PyGPropsIter *self)
@@ -236,14 +263,12 @@ build_parameter_list(GObjectClass *class)
name = g_strdup(g_param_spec_get_name(props[i]));
/* hyphens cannot belong in identifiers */
g_strdelimit(name, "-", '_');
- prop_str = PYGLIB_PyUnicode_FromString(name);
+ prop_str = PyUnicode_FromString (name);
PyList_SetItem(props_list, i, prop_str);
g_free(name);
}
- g_type_class_unref(class);
-
if (props)
g_free(props);
@@ -256,22 +281,14 @@ PyGProps_getattro(PyGProps *self, PyObject *attr)
char *attr_name, *property_name;
GObjectClass *class;
GParamSpec *pspec;
- GValue value = { 0, };
- PyObject *ret;
- attr_name = PYGLIB_PyUnicode_AsString(attr);
+ attr_name = PyUnicode_AsUTF8 (attr);
if (!attr_name) {
PyErr_Clear();
return PyObject_GenericGetAttr((PyObject *)self, attr);
}
class = g_type_class_ref(self->gtype);
-
- if (!strcmp(attr_name, "__members__")) {
- ret = build_parameter_list(class);
- g_type_class_unref(class);
- return ret;
- }
/* g_object_class_find_property recurses through the class hierarchy,
* so the resulting pspec tells us the owner_type that owns the property
@@ -286,36 +303,12 @@ PyGProps_getattro(PyGProps *self, PyObject *attr)
return PyObject_GenericGetAttr((PyObject *)self, attr);
}
- if (!(pspec->flags & G_PARAM_READABLE)) {
- PyErr_Format(PyExc_TypeError,
- "property '%s' is not readable", attr_name);
- return NULL;
- }
-
if (!self->pygobject) {
/* If we're doing it without an instance, return a GParamSpec */
return pyg_param_spec_new(pspec);
}
- if (!pyg_gtype_is_custom (pspec->owner_type)) {
- /* The GType is not implemented at the Python level: see if we can
- * read the property value via gi. */
- ret = pygi_get_property_value (self->pygobject, pspec);
- if (ret)
- return ret;
- }
-
- /* The GType is implemented in Python, or we failed to read it via gi:
- * do a straightforward read. */
- Py_BEGIN_ALLOW_THREADS;
- g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
- g_object_get_property(self->pygobject->obj, pspec->name, &value);
- Py_END_ALLOW_THREADS;
-
- ret = pyg_param_gvalue_as_pyobject(&value, TRUE, pspec);
- g_value_unset(&value);
-
- return ret;
+ return pygi_get_property_value (self->pygobject, pspec);
}
static gboolean
@@ -340,10 +333,10 @@ set_property_from_pspec(GObject *obj,
g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
if (pyg_param_gvalue_from_pyobject(&value, pvalue, pspec) < 0) {
- PyObject *pvalue_str = PyObject_Str(pvalue);
+ PyObject *pvalue_str = PyObject_Repr(pvalue);
PyErr_Format(PyExc_TypeError,
- "could not convert '%s' to type '%s' when setting property '%s.%s'",
- PYGLIB_PyUnicode_AsString(pvalue_str),
+ "could not convert %s to type '%s' when setting property '%s.%s'",
+ PyUnicode_AsUTF8 (pvalue_str),
g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)),
G_OBJECT_TYPE_NAME(obj),
pspec->name);
@@ -359,7 +352,7 @@ set_property_from_pspec(GObject *obj,
return TRUE;
}
-PYGLIB_DEFINE_TYPE("gi._gobject.GProps", PyGProps_Type, PyGProps);
+PYGI_DEFINE_TYPE("gi._gi.GProps", PyGProps_Type, PyGProps);
static int
PyGProps_setattro(PyGProps *self, PyObject *attr, PyObject *pvalue)
@@ -375,7 +368,7 @@ PyGProps_setattro(PyGProps *self, PyObject *attr, PyObject *pvalue)
return -1;
}
- attr_name = PYGLIB_PyUnicode_AsString(attr);
+ attr_name = PyUnicode_AsUTF8 (attr);
if (!attr_name) {
PyErr_Clear();
return PyObject_GenericSetAttr((PyObject *)self, attr, pvalue);
@@ -441,6 +434,25 @@ pygobject_props_get_iter(PyGProps *self)
return (PyObject *) iter;
}
+static PyObject*
+pygobject_props_dir(PyGProps *self)
+{
+ PyObject *ret;
+ GObjectClass *class;
+
+ class = g_type_class_ref (self->gtype);
+ ret = build_parameter_list (class);
+ g_type_class_unref (class);
+
+ return ret;
+}
+
+static PyMethodDef pygobject_props_methods[] = {
+ { "__dir__", (PyCFunction)pygobject_props_dir, METH_NOARGS},
+ { NULL, NULL, 0}
+};
+
+
static Py_ssize_t
PyGProps_length(PyGProps *self)
{
@@ -466,7 +478,7 @@ static PySequenceMethods _PyGProps_as_sequence = {
0
};
-PYGLIB_DEFINE_TYPE("gi._gobject.GPropsDescr", PyGPropsDescr_Type, PyObject);
+PYGI_DEFINE_TYPE("gi._gi.GPropsDescr", PyGPropsDescr_Type, PyObject);
static PyObject *
pyg_props_descr_descr_get(PyObject *self, PyObject *obj, PyObject *type)
@@ -548,7 +560,7 @@ pygobject_register_class(PyObject *dict, const gchar *type_name,
} else
bases = runtime_bases;
- Py_TYPE(type) = PyGObject_MetaType;
+ Py_SET_TYPE(type, PyGObject_MetaType);
type->tp_bases = bases;
if (G_LIKELY(bases)) {
type->tp_base = (PyTypeObject *)PyTuple_GetItem(bases, 0);
@@ -567,7 +579,7 @@ pygobject_register_class(PyObject *dict, const gchar *type_name,
*/
s = strrchr(type->tp_name, '.');
if (s != NULL) {
- mod_name = PYGLIB_PyUnicode_FromStringAndSize(type->tp_name, (int)(s - type->tp_name));
+ mod_name = PyUnicode_FromStringAndSize (type->tp_name, (int)(s - type->tp_name));
PyDict_SetItemString(type->tp_dict, "__module__", mod_name);
Py_DECREF(mod_name);
}
@@ -592,17 +604,49 @@ pygobject_register_class(PyObject *dict, const gchar *type_name,
static void
pyg_toggle_notify (gpointer data, GObject *object, gboolean is_last_ref)
{
- PyGObject *self = (PyGObject*) data;
+ PyGObject *self;
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
- if (is_last_ref)
- Py_DECREF(self);
- else
- Py_INCREF(self);
+ /* Avoid thread safety problems by using qdata for wrapper retrieval
+ * instead of the user data argument.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=709223
+ */
+ self = (PyGObject *)g_object_get_qdata (object, pygobject_wrapper_key);
+ if (self) {
+ if (is_last_ref)
+ Py_DECREF(self);
+ else
+ Py_INCREF(self);
+ }
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
+}
+
+static inline gboolean
+pygobject_toggle_ref_is_required (PyGObject *self)
+{
+#ifdef PYGI_OBJECT_USE_CUSTOM_DICT
+ return self->inst_dict != NULL;
+#else
+ PyObject *dict;
+ gboolean result;
+ dict = PyObject_GetAttrString ((PyObject *)self, "__dict__");
+ if (!dict) {
+ PyErr_Clear ();
+ return FALSE;
+ }
+ result = PyDict_Size (dict) != 0;
+ Py_DECREF (dict);
+ return result;
+#endif
+}
+
+static inline gboolean
+pygobject_toggle_ref_is_active (PyGObject *self)
+{
+ return self->private_flags.flags & PYGOBJECT_USING_TOGGLE_REF;
}
/* Called when the inst_dict is first created; switches the
@@ -611,17 +655,23 @@ pyg_toggle_notify (gpointer data, GObject *object, gboolean is_last_ref)
inst_dict was NULL the python wrapper is allowed to die at
will and is recreated on demand. */
static inline void
-pygobject_switch_to_toggle_ref(PyGObject *self)
+pygobject_toggle_ref_ensure (PyGObject *self)
{
- g_assert(self->obj->ref_count >= 1);
+ if (pygobject_toggle_ref_is_active (self))
+ return;
- if (self->private_flags.flags & PYGOBJECT_USING_TOGGLE_REF)
- return; /* already using toggle ref */
+ if (!pygobject_toggle_ref_is_required (self))
+ return;
+
+ if (self->obj == NULL)
+ return;
+
+ g_assert(self->obj->ref_count >= 1);
self->private_flags.flags |= PYGOBJECT_USING_TOGGLE_REF;
/* Note that add_toggle_ref will never immediately call back into
pyg_toggle_notify */
Py_INCREF((PyObject *) self);
- g_object_add_toggle_ref(self->obj, pyg_toggle_notify, self);
+ g_object_add_toggle_ref(self->obj, pyg_toggle_notify, NULL);
g_object_unref(self->obj);
}
@@ -672,8 +722,8 @@ pygobject_register_wrapper(PyObject *self)
g_assert(gself->obj->ref_count >= 1);
/* save wrapper pointer so we can access it later */
g_object_set_qdata_full(gself->obj, pygobject_wrapper_key, gself, NULL);
- if (gself->inst_dict)
- pygobject_switch_to_toggle_ref(gself);
+
+ pygobject_toggle_ref_ensure (gself);
}
static PyObject *
@@ -683,7 +733,7 @@ pyg_type_get_bases(GType gtype)
guint n_interfaces;
PyTypeObject *py_parent_type, *py_interface_type;
PyObject *bases;
- int i;
+ guint i;
if (G_UNLIKELY(gtype == G_TYPE_OBJECT))
return NULL;
@@ -728,10 +778,8 @@ pygobject_new_with_interfaces(GType gtype)
PyObject *dict;
PyTypeObject *py_parent_type;
PyObject *bases;
- PyObject *modules, *module;
- gchar *type_name, *mod_name, *gtype_name;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
bases = pyg_type_get_bases(gtype);
py_parent_type = (PyTypeObject *) PyTuple_GetItem(bases, 0);
@@ -745,36 +793,18 @@ pygobject_new_with_interfaces(GType gtype)
/* set up __doc__ descriptor on type */
PyDict_SetItemString(dict, "__doc__", pyg_object_descr_doc_get());
- /* generate the pygtk module name and extract the base type name */
- gtype_name = (gchar*)g_type_name(gtype);
- if (g_str_has_prefix(gtype_name, "Gtk")) {
- mod_name = "gtk";
- gtype_name += 3;
- type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
- } else if (g_str_has_prefix(gtype_name, "Gdk")) {
- mod_name = "gtk.gdk";
- gtype_name += 3;
- type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
- } else if (g_str_has_prefix(gtype_name, "Atk")) {
- mod_name = "atk";
- gtype_name += 3;
- type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
- } else if (g_str_has_prefix(gtype_name, "Pango")) {
- mod_name = "pango";
- gtype_name += 5;
- type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
- } else {
- mod_name = "__main__";
- type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
- }
+ /* Something special to point out that it's not accessible through
+ * gi.repository */
+ o = PyUnicode_FromString ("__gi__");
+ PyDict_SetItemString (dict, "__module__", o);
+ Py_DECREF (o);
type = (PyTypeObject*)PyObject_CallFunction((PyObject *) Py_TYPE(py_parent_type),
- "sNN", type_name, bases, dict);
- g_free(type_name);
+ "sNN", g_type_name (gtype), bases, dict);
if (type == NULL) {
PyErr_Print();
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return NULL;
}
@@ -799,21 +829,15 @@ pygobject_new_with_interfaces(GType gtype)
if (PyType_Ready(type) < 0) {
g_warning ("couldn't make the type `%s' ready", type->tp_name);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return NULL;
}
- /* insert type name in module dict */
- modules = PyImport_GetModuleDict();
- if ((module = PyDict_GetItemString(modules, mod_name)) != NULL) {
- if (PyObject_SetAttrString(module, gtype_name, (PyObject *)type) < 0)
- PyErr_Clear();
- }
/* stash a pointer to the python class with the GType */
Py_INCREF(type);
g_type_set_qdata(gtype, pygobject_class_key, type);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return type;
}
@@ -846,16 +870,13 @@ static void
pygobject_inherit_slots(PyTypeObject *type, PyObject *bases, gboolean check_for_present)
{
static int slot_offsets[] = { offsetof(PyTypeObject, tp_richcompare),
-#if PY_VERSION_HEX < 0x03000000
- offsetof(PyTypeObject, tp_compare),
-#endif
offsetof(PyTypeObject, tp_richcompare),
offsetof(PyTypeObject, tp_hash),
offsetof(PyTypeObject, tp_iter),
offsetof(PyTypeObject, tp_repr),
offsetof(PyTypeObject, tp_str),
- offsetof(PyTypeObject, tp_print) };
- int i;
+ };
+ gsize i;
/* Happens when registering gobject.GObject itself, at least. */
if (!bases)
@@ -869,11 +890,11 @@ static void
pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset,
gboolean check_for_present)
{
-#define TYPE_SLOT(type) (* (void **) (((char *) (type)) + slot_offset))
+#define TYPE_SLOT(type) (* (void **) (void *) (((char *) (type)) + slot_offset))
void *found_slot = NULL;
- int num_bases = PyTuple_Size(bases);
- int i;
+ Py_ssize_t num_bases = PyTuple_Size(bases);
+ Py_ssize_t i;
if (check_for_present && TYPE_SLOT(type) != NULL) {
/* We are requested to check if there is any custom slot value
@@ -921,6 +942,8 @@ pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset,
* or interface has been registered for the given GType, then a new
* type will be created.
*
+ * Does not set an exception when NULL is returned.
+ *
* Returns: The wrapper class for the GObject or NULL if the
* GType has no registered type and a new type couldn't be created
*/
@@ -930,19 +953,22 @@ pygobject_lookup_class(GType gtype)
PyTypeObject *py_type;
if (gtype == G_TYPE_INTERFACE)
- return &PyGInterface_Type;
+ return &PyGInterface_Type;
py_type = g_type_get_qdata(gtype, pygobject_class_key);
if (py_type == NULL) {
- py_type = g_type_get_qdata(gtype, pyginterface_type_key);
+ py_type = g_type_get_qdata(gtype, pyginterface_type_key);
- if (py_type == NULL)
- py_type = (PyTypeObject *)pygi_type_import_by_g_type(gtype);
+ if (py_type == NULL) {
+ py_type = (PyTypeObject *)pygi_type_import_by_g_type(gtype);
+ PyErr_Clear ();
+ }
- if (py_type == NULL) {
- py_type = pygobject_new_with_interfaces(gtype);
- g_type_set_qdata(gtype, pyginterface_type_key, py_type);
- }
+ if (py_type == NULL) {
+ py_type = pygobject_new_with_interfaces(gtype);
+ PyErr_Clear ();
+ g_type_set_qdata(gtype, pyginterface_type_key, py_type);
+ }
}
return py_type;
@@ -1040,7 +1066,12 @@ pygobject_unwatch_closure(gpointer data, GClosure *closure)
{
PyGObjectData *inst_data = data;
+ /* Despite no Python API is called the list inst_data->closures
+ * must be protected by GIL as it is used by GC in
+ * pygobject_traverse */
+ PyGILState_STATE state = PyGILState_Ensure();
inst_data->closures = g_slist_remove (inst_data->closures, closure);
+ PyGILState_Release(state);
}
/**
@@ -1067,6 +1098,7 @@ pygobject_watch_closure(PyObject *self, GClosure *closure)
gself = (PyGObject *)self;
data = pygobject_get_inst_data(gself);
+ g_return_if_fail(data != NULL);
g_return_if_fail(g_slist_find(data->closures, closure) == NULL);
data->closures = g_slist_prepend(data->closures, closure);
g_closure_add_invalidate_notifier(closure, data, pygobject_unwatch_closure);
@@ -1075,7 +1107,7 @@ pygobject_watch_closure(PyObject *self, GClosure *closure)
/* -------------- PyGObject behaviour ----------------- */
-PYGLIB_DEFINE_TYPE("gi._gobject.GObject", PyGObject_Type, PyGObject);
+PYGI_DEFINE_TYPE("gi._gi.GObject", PyGObject_Type, PyGObject);
static void
pygobject_dealloc(PyGObject *self)
@@ -1087,7 +1119,9 @@ pygobject_dealloc(PyGObject *self)
* object. */
PyObject_GC_UnTrack((PyObject *)self);
- PyObject_ClearWeakRefs((PyObject *)self);
+ if (self->weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject *)self);
+
/* this forces inst_data->type to be updated, which could prove
* important if a new wrapper has to be created and it is of a
* unregistered type */
@@ -1118,29 +1152,46 @@ pygobject_richcompare(PyObject *self, PyObject *other, int op)
return Py_NotImplemented;
}
- return _pyglib_generic_ptr_richcompare(((PyGObject*)self)->obj,
- ((PyGObject*)other)->obj,
- op);
+ return pyg_ptr_richcompare(((PyGObject*)self)->obj,
+ ((PyGObject*)other)->obj,
+ op);
}
-static long
+static Py_hash_t
pygobject_hash(PyGObject *self)
{
- return (long)self->obj;
+ return (Py_hash_t)(gintptr)(self->obj);
}
static PyObject *
pygobject_repr(PyGObject *self)
{
- gchar buf[256];
+ PyObject *module, *repr;
+ gchar *module_str, *namespace;
- g_snprintf(buf, sizeof(buf),
- "<%s object at 0x%lx (%s at 0x%lx)>",
- Py_TYPE(self)->tp_name,
- (long)self,
- self->obj ? G_OBJECT_TYPE_NAME(self->obj) : "uninitialized",
- (long)self->obj);
- return PYGLIB_PyUnicode_FromString(buf);
+ module = PyObject_GetAttrString ((PyObject *)self, "__module__");
+ if (module == NULL)
+ return NULL;
+
+ if (!PyUnicode_Check (module)) {
+ Py_DECREF (module);
+ return NULL;
+ }
+
+ module_str = PyUnicode_AsUTF8 (module);
+ namespace = g_strrstr (module_str, ".");
+ if (namespace == NULL) {
+ namespace = module_str;
+ } else {
+ namespace += 1;
+ }
+
+ repr = PyUnicode_FromFormat ("<%s.%s object at %p (%s at %p)>",
+ namespace, Py_TYPE (self)->tp_name, self,
+ self->obj ? G_OBJECT_TYPE_NAME (self->obj) : "uninitialized",
+ self->obj);
+ Py_DECREF (module);
+ return repr;
}
@@ -1154,8 +1205,10 @@ pygobject_traverse(PyGObject *self, visitproc visit, void *arg)
if (self->inst_dict) ret = visit(self->inst_dict, arg);
if (ret != 0) return ret;
- if (data) {
-
+ /* Only let the GC track the closures when tp_clear() would free them.
+ * https://bugzilla.gnome.org/show_bug.cgi?id=731501
+ */
+ if (data && self->obj->ref_count == 1) {
for (tmp = data->closures; tmp != NULL; tmp = tmp->next) {
PyGClosure *closure = tmp->data;
@@ -1177,8 +1230,8 @@ pygobject_clear(PyGObject *self)
{
if (self->obj) {
g_object_set_qdata_full(self->obj, pygobject_wrapper_key, NULL, NULL);
- if (self->inst_dict) {
- g_object_remove_toggle_ref(self->obj, pyg_toggle_notify, self);
+ if (pygobject_toggle_ref_is_active (self)) {
+ g_object_remove_toggle_ref(self->obj, pyg_toggle_notify, NULL);
self->private_flags.flags &= ~PYGOBJECT_USING_TOGGLE_REF;
} else {
Py_BEGIN_ALLOW_THREADS;
@@ -1197,23 +1250,28 @@ pygobject_free(PyObject *op)
PyObject_GC_Del(op);
}
-gboolean
+static gboolean
pygobject_prepare_construct_properties(GObjectClass *class, PyObject *kwargs,
- guint *n_params, GParameter **params)
+ guint *n_properties, const char **names[], const GValue **values)
{
- *n_params = 0;
- *params = NULL;
+ *n_properties = 0;
+ *names = NULL;
+ *values = NULL;
if (kwargs) {
Py_ssize_t pos = 0;
PyObject *key;
PyObject *value;
+ Py_ssize_t len;
- *params = g_new0(GParameter, PyDict_Size(kwargs));
+ len = PyDict_Size(kwargs);
+ *names = g_new(const char*, len);
+ *values = g_new0(GValue, len);
while (PyDict_Next(kwargs, &pos, &key, &value)) {
GParamSpec *pspec;
- GParameter *param = &(*params)[*n_params];
- const gchar *key_str = PYGLIB_PyUnicode_AsString(key);
+ GValue *gvalue = &(*values)[*n_properties];
+
+ const gchar *key_str = PyUnicode_AsUTF8 (key);
pspec = g_object_class_find_property(class, key_str);
if (!pspec) {
@@ -1222,16 +1280,16 @@ pygobject_prepare_construct_properties(GObjectClass *class, PyObject *kwargs,
G_OBJECT_CLASS_NAME(class), key_str);
return FALSE;
}
- g_value_init(&param->value, G_PARAM_SPEC_VALUE_TYPE(pspec));
- if (pyg_param_gvalue_from_pyobject(&param->value, value, pspec) < 0) {
+ g_value_init(gvalue, G_PARAM_SPEC_VALUE_TYPE(pspec));
+ if (pyg_param_gvalue_from_pyobject(gvalue, value, pspec) < 0) {
PyErr_Format(PyExc_TypeError,
"could not convert value for property `%s' from %s to %s",
key_str, Py_TYPE(value)->tp_name,
g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)));
return FALSE;
}
- param->name = g_strdup(key_str);
- ++(*n_params);
+ (*names)[*n_properties] = g_strdup(key_str);
+ ++(*n_properties);
}
}
return TRUE;
@@ -1243,11 +1301,24 @@ static int
pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs)
{
GType object_type;
- guint n_params = 0, i;
- GParameter *params = NULL;
+ guint n_properties = 0, i;
+ const GValue *values = NULL;
+ const char **names = NULL;
GObjectClass *class;
- if (!PyArg_ParseTuple(args, ":GObject.__init__", &object_type))
+ /* Only do GObject creation and property setting if the GObject hasn't
+ * already been created. The case where self->obj already exists can occur
+ * when C constructors are called directly (Gtk.Button.new_with_label)
+ * and we are simply wrapping the result with a PyGObject.
+ * In these cases we want to ignore any keyword arguments passed along
+ * to __init__ and simply return.
+ *
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=705810
+ */
+ if (self->obj != NULL)
+ return 0;
+
+ if (!PyArg_ParseTuple(args, ":GObject.__init__", NULL))
return -1;
object_type = pyg_type_from_object((PyObject *)self);
@@ -1266,18 +1337,20 @@ pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs)
return -1;
}
- if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
+ if (!pygobject_prepare_construct_properties (class, kwargs, &n_properties, &names, &values))
goto cleanup;
- if (pygobject_constructv(self, n_params, params))
- PyErr_SetString(PyExc_RuntimeError, "could not create object");
-
+ if (pygobject_constructv(self, n_properties, names, values))
+ PyErr_SetString(PyExc_RuntimeError, "could not create object");
+
cleanup:
- for (i = 0; i < n_params; i++) {
- g_free((gchar *) params[i].name);
- g_value_unset(&params[i].value);
+ for (i = 0; i < n_properties; i++) {
+ g_free(names[i]);
+ g_value_unset(&values[i]);
}
- g_free(params);
+ g_free(names);
+ g_free(values);
+
g_type_class_unref(class);
return (self->obj) ? 0 : -1;
@@ -1292,46 +1365,23 @@ pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs)
}
static PyObject *
-pygobject_get_property(PyGObject *self, PyObject *args)
+pygobject_get_property (PyGObject *self, PyObject *args)
{
gchar *param_name;
- GParamSpec *pspec;
- GValue value = { 0, };
- PyObject *ret;
- if (!PyArg_ParseTuple(args, "s:GObject.get_property", &param_name))
- return NULL;
+ if (!PyArg_ParseTuple (args, "s:GObject.get_property", &param_name)) {
+ return NULL;
+ }
CHECK_GOBJECT(self);
-
- pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
- param_name);
- if (!pspec) {
- PyErr_Format(PyExc_TypeError,
- "object of type `%s' does not have property `%s'",
- g_type_name(G_OBJECT_TYPE(self->obj)), param_name);
- return NULL;
- }
- if (!(pspec->flags & G_PARAM_READABLE)) {
- PyErr_Format(PyExc_TypeError, "property %s is not readable",
- param_name);
- return NULL;
- }
- g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
- Py_BEGIN_ALLOW_THREADS;
- g_object_get_property(self->obj, param_name, &value);
- Py_END_ALLOW_THREADS;
- ret = pyg_param_gvalue_as_pyobject(&value, TRUE, pspec);
- g_value_unset(&value);
- return ret;
+ return pygi_get_property_value_by_name (self, param_name);
}
static PyObject *
pygobject_get_properties(PyGObject *self, PyObject *args)
{
- GObjectClass *class;
- int len, i;
+ Py_ssize_t len, i;
PyObject *tuple;
if ((len = PyTuple_Size(args)) < 1) {
@@ -1340,48 +1390,27 @@ pygobject_get_properties(PyGObject *self, PyObject *args)
}
tuple = PyTuple_New(len);
- class = G_OBJECT_GET_CLASS(self->obj);
for (i = 0; i < len; i++) {
PyObject *py_property = PyTuple_GetItem(args, i);
gchar *property_name;
- GParamSpec *pspec;
- GValue value = { 0 };
PyObject *item;
- if (!PYGLIB_PyUnicode_Check(py_property)) {
+ if (!PyUnicode_Check (py_property)) {
PyErr_SetString(PyExc_TypeError,
"Expected string argument for property.");
- return NULL;
- }
-
- property_name = PYGLIB_PyUnicode_AsString(py_property);
-
- pspec = g_object_class_find_property(class,
- property_name);
- if (!pspec) {
- PyErr_Format(PyExc_TypeError,
- "object of type `%s' does not have property `%s'",
- g_type_name(G_OBJECT_TYPE(self->obj)), property_name);
- return NULL;
- }
- if (!(pspec->flags & G_PARAM_READABLE)) {
- PyErr_Format(PyExc_TypeError, "property %s is not readable",
- property_name);
- return NULL;
+ goto fail;
}
- g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
-
- Py_BEGIN_ALLOW_THREADS;
- g_object_get_property(self->obj, property_name, &value);
- Py_END_ALLOW_THREADS;
- item = pyg_value_as_pyobject(&value, TRUE);
- PyTuple_SetItem(tuple, i, item);
-
- g_value_unset(&value);
+ property_name = PyUnicode_AsUTF8 (py_property);
+ item = pygi_get_property_value_by_name (self, property_name);
+ PyTuple_SetItem (tuple, i, item);
}
return tuple;
+
+fail:
+ Py_DECREF (tuple);
+ return NULL;
}
static PyObject *
@@ -1439,7 +1468,7 @@ pygobject_set_properties(PyGObject *self, PyObject *args, PyObject *kwargs)
pos = 0;
while (kwargs && PyDict_Next (kwargs, &pos, &key, &value)) {
- gchar *key_str = PYGLIB_PyUnicode_AsString(key);
+ gchar *key_str = PyUnicode_AsUTF8 (key);
GParamSpec *pspec;
int ret = -1;
@@ -1482,10 +1511,10 @@ pygbinding_closure_invalidate(gpointer data, GClosure *closure)
PyGClosure *pc = (PyGClosure *)closure;
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
Py_XDECREF(pc->callback);
Py_XDECREF(pc->extra_args);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
pc->callback = NULL;
pc->extra_args = NULL;
@@ -1504,7 +1533,7 @@ pygbinding_marshal (GClosure *closure,
PyObject *params, *ret;
GValue *out_value;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
/* construct Python tuple for the parameter values */
params = PyTuple_New(2);
@@ -1539,7 +1568,7 @@ pygbinding_marshal (GClosure *closure,
out:
Py_DECREF(params);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
}
static GClosure *
@@ -1623,14 +1652,14 @@ pygobject_bind_property(PyGObject *self, PyObject *args)
source_repr = PyObject_Repr((PyObject*)self);
target_repr = PyObject_Repr(target);
PyErr_Format(PyExc_TypeError, "Cannot create binding from %s.%s to %s.%s",
- PYGLIB_PyUnicode_AsString(source_repr), source_name,
- PYGLIB_PyUnicode_AsString(target_repr), target_name);
+ PyUnicode_AsUTF8 (source_repr), source_name,
+ PyUnicode_AsUTF8 (target_repr), target_name);
Py_DECREF(source_repr);
Py_DECREF(target_repr);
return NULL;
}
- return pygbinding_weak_ref_new(G_OBJECT (binding));
+ return pygobject_new (G_OBJECT (binding));
}
static PyObject *
@@ -1646,12 +1675,21 @@ connect_helper(PyGObject *self, gchar *name, PyObject *callback, PyObject *extra
&sigid, &detail, TRUE)) {
PyObject *repr = PyObject_Repr((PyObject*)self);
PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- PYGLIB_PyUnicode_AsString(repr),
+ PyUnicode_AsUTF8 (repr),
name);
Py_DECREF(repr);
return NULL;
}
+ if (object && !PyObject_TypeCheck (object, &PyGObject_Type)) {
+ if (PyErr_WarnEx (PyGIDeprecationWarning,
+ "Using non GObject arguments for connect_object() is deprecated, use: "
+ "connect_data(signal, callback, data, connect_flags=GObject.ConnectFlags.SWAPPED)",
+ 1)) {
+ return NULL;
+ }
+ }
+
g_signal_query (sigid, &query_info);
if (!pyg_gtype_is_custom (query_info.itype)) {
/* The signal is implemented by a non-Python class, probably
@@ -1670,7 +1708,7 @@ connect_helper(PyGObject *self, gchar *name, PyObject *callback, PyObject *extra
pygobject_watch_closure((PyObject *)self, closure);
handlerid = g_signal_connect_closure_by_id(self->obj, sigid, detail,
closure, after);
- return PyLong_FromUnsignedLong(handlerid);
+ return pygi_gulong_to_py (handlerid);
}
static PyObject *
@@ -1678,7 +1716,7 @@ pygobject_connect(PyGObject *self, PyObject *args)
{
PyObject *first, *callback, *extra_args, *ret;
gchar *name;
- guint len;
+ Py_ssize_t len;
len = PyTuple_Size(args);
if (len < 2) {
@@ -1845,13 +1883,13 @@ pygobject_emit(PyGObject *self, PyObject *args)
&signal_id, &detail, TRUE)) {
repr = PyObject_Repr((PyObject*)self);
PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
- PYGLIB_PyUnicode_AsString(repr),
+ PyUnicode_AsUTF8 (repr),
name);
Py_DECREF(repr);
return NULL;
}
g_signal_query(signal_id, &query);
- if (len != query.n_params + 1) {
+ if ((gsize)len != query.n_params + 1) {
gchar buf[128];
g_snprintf(buf, sizeof(buf),
@@ -1890,15 +1928,26 @@ pygobject_emit(PyGObject *self, PyObject *args)
if (query.return_type != G_TYPE_NONE)
g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+ Py_BEGIN_ALLOW_THREADS;
g_signal_emitv(params, signal_id, detail, &ret);
+ Py_END_ALLOW_THREADS;
for (i = 0; i < query.n_params + 1; i++)
g_value_unset(&params[i]);
g_free(params);
if ((query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE) != G_TYPE_NONE) {
+ gboolean was_floating = FALSE;
+
+ if (G_VALUE_HOLDS_OBJECT (&ret)) {
+ GObject *obj = g_value_get_object (&ret);
+ if (obj != NULL && G_IS_OBJECT(obj)) {
+ was_floating = g_object_is_floating (obj);
+ }
+ }
py_ret = pyg_value_as_pyobject(&ret, TRUE);
- g_value_unset(&ret);
+ if (!was_floating)
+ g_value_unset(&ret);
} else {
Py_INCREF(Py_None);
py_ret = Py_None;
@@ -1936,7 +1985,7 @@ pygobject_chain_from_overridden(PyGObject *self, PyObject *args)
return NULL;
}
g_signal_query(signal_id, &query);
- if (len != query.n_params) {
+ if (len < 0 || (gsize)len != query.n_params) {
gchar buf[128];
g_snprintf(buf, sizeof(buf),
@@ -1992,7 +2041,7 @@ pygobject_chain_from_overridden(PyGObject *self, PyObject *args)
static PyObject *
pygobject_weak_ref(PyGObject *self, PyObject *args)
{
- int len;
+ Py_ssize_t len;
PyObject *callback = NULL, *user_data = NULL;
PyObject *retval;
@@ -2047,7 +2096,7 @@ pygobject_disconnect_by_func(PyGObject *self, PyObject *args)
if (!closure) {
repr = PyObject_Repr((PyObject*)pyfunc);
PyErr_Format(PyExc_TypeError, "nothing connected to %s",
- PYGLIB_PyUnicode_AsString(repr));
+ PyUnicode_AsUTF8 (repr));
Py_DECREF(repr);
return NULL;
}
@@ -2057,7 +2106,7 @@ pygobject_disconnect_by_func(PyGObject *self, PyObject *args)
0, 0,
closure,
NULL, NULL);
- return PYGLIB_PyLong_FromLong(retval);
+ return pygi_guint_to_py (retval);
}
static PyObject *
@@ -2081,7 +2130,7 @@ pygobject_handler_block_by_func(PyGObject *self, PyObject *args)
if (!closure) {
repr = PyObject_Repr((PyObject*)pyfunc);
PyErr_Format(PyExc_TypeError, "nothing connected to %s",
- PYGLIB_PyUnicode_AsString(repr));
+ PyUnicode_AsUTF8 (repr));
Py_DECREF(repr);
return NULL;
}
@@ -2091,7 +2140,7 @@ pygobject_handler_block_by_func(PyGObject *self, PyObject *args)
0, 0,
closure,
NULL, NULL);
- return PYGLIB_PyLong_FromLong(retval);
+ return pygi_guint_to_py (retval);
}
static PyObject *
@@ -2115,7 +2164,7 @@ pygobject_handler_unblock_by_func(PyGObject *self, PyObject *args)
if (!closure) {
repr = PyObject_Repr((PyObject*)pyfunc);
PyErr_Format(PyExc_TypeError, "nothing connected to %s",
- PYGLIB_PyUnicode_AsString(repr));
+ PyUnicode_AsUTF8 (repr));
Py_DECREF(repr);
return NULL;
}
@@ -2125,7 +2174,7 @@ pygobject_handler_unblock_by_func(PyGObject *self, PyObject *args)
0, 0,
closure,
NULL, NULL);
- return PYGLIB_PyLong_FromLong(retval);
+ return pygi_guint_to_py (retval);
}
@@ -2150,20 +2199,18 @@ static PyMethodDef pygobject_methods[] = {
{ NULL, NULL, 0 }
};
-
+#ifdef PYGI_OBJECT_USE_CUSTOM_DICT
static PyObject *
pygobject_get_dict(PyGObject *self, void *closure)
{
if (self->inst_dict == NULL) {
- self->inst_dict = PyDict_New();
- if (self->inst_dict == NULL)
- return NULL;
- if (G_LIKELY(self->obj))
- pygobject_switch_to_toggle_ref(self);
+ self->inst_dict = PyDict_New();
+ pygobject_toggle_ref_ensure (self);
}
Py_INCREF(self->inst_dict);
return self->inst_dict;
}
+#endif
static PyObject *
pygobject_get_refcount(PyGObject *self, void *closure)
@@ -2172,32 +2219,28 @@ pygobject_get_refcount(PyGObject *self, void *closure)
PyErr_Format(PyExc_TypeError, "GObject instance is not yet created");
return NULL;
}
- return PYGLIB_PyLong_FromLong(self->obj->ref_count);
+ return pygi_guint_to_py (self->obj->ref_count);
}
static PyObject *
pygobject_get_pointer(PyGObject *self, void *closure)
{
- return PYGLIB_CPointer_WrapPointer (self->obj, NULL);
+ return PyCapsule_New (self->obj, NULL, NULL);
}
static int
pygobject_setattro(PyObject *self, PyObject *name, PyObject *value)
{
int res;
- PyGObject *gself = (PyGObject *) self;
- PyObject *inst_dict_before = gself->inst_dict;
- /* call parent type's setattro */
res = PyGObject_Type.tp_base->tp_setattro(self, name, value);
- if (inst_dict_before == NULL && gself->inst_dict != NULL) {
- if (G_LIKELY(gself->obj))
- pygobject_switch_to_toggle_ref(gself);
- }
+ pygobject_toggle_ref_ensure ((PyGObject *) self);
return res;
}
static PyGetSetDef pygobject_getsets[] = {
+#ifdef PYGI_OBJECT_USE_CUSTOM_DICT
{ "__dict__", (getter)pygobject_get_dict, (setter)0 },
+#endif
{ "__grefcount__", (getter)pygobject_get_refcount, (setter)0, },
{ "__gpointer__", (getter)pygobject_get_pointer, (setter)0, },
{ NULL, 0, 0 }
@@ -2215,7 +2258,7 @@ typedef struct {
gboolean have_floating_ref;
} PyGObjectWeakRef;
-PYGLIB_DEFINE_TYPE("gi._gobject.GObjectWeakRef", PyGObjectWeakRef_Type, PyGObjectWeakRef);
+PYGI_DEFINE_TYPE("gi._gi.GObjectWeakRef", PyGObjectWeakRef_Type, PyGObjectWeakRef);
static int
pygobject_weak_ref_traverse(PyGObjectWeakRef *self, visitproc visit, void *arg)
@@ -2233,7 +2276,7 @@ pygobject_weak_ref_notify(PyGObjectWeakRef *self, GObject *dummy)
self->obj = NULL;
if (self->callback) {
PyObject *retval;
- PyGILState_STATE state = pyglib_gil_state_ensure();
+ PyGILState_STATE state = PyGILState_Ensure();
retval = PyObject_Call(self->callback, self->user_data, NULL);
if (retval) {
if (retval != Py_None)
@@ -2251,7 +2294,7 @@ pygobject_weak_ref_notify(PyGObjectWeakRef *self, GObject *dummy)
self->have_floating_ref = FALSE;
Py_DECREF((PyObject *) self);
}
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
}
}
@@ -2334,63 +2377,15 @@ pygobject_weak_ref_call(PyGObjectWeakRef *self, PyObject *args, PyObject *kw)
}
}
-
-/* -------------- GBinding Weak Reference ----------------- */
-
-/**
- * BindingWeakRef
- *
- * The BindingWeakRef object is used to manage GBinding objects within python
- * created through GObject.bind_property. It is a sub-class PyGObjectWeakRef so
- * that we can maintain the same reference counting semantics between Python
- * and GObject Binding objects. This gives explicit direct control of the
- * binding lifetime by using the "unbind" method on the BindingWeakRef object
- * along with implicit management based on the lifetime of the source or
- * target objects.
- */
-
-PYGLIB_DEFINE_TYPE("gi._gobject.GBindingWeakRef", PyGBindingWeakRef_Type, PyGObjectWeakRef);
-
-static PyObject *
-pygbinding_weak_ref_new(GObject *obj)
-{
- PyGObjectWeakRef *self;
-
- self = PyObject_GC_New(PyGObjectWeakRef, &PyGBindingWeakRef_Type);
- self->callback = NULL;
- self->user_data = NULL;
- self->obj = obj;
- g_object_weak_ref(self->obj, (GWeakNotify) pygobject_weak_ref_notify, self);
- return (PyObject *) self;
-}
-
-static PyObject *
-pygbinding_weak_ref_unbind(PyGObjectWeakRef *self, PyObject *args)
-{
- if (!self->obj) {
- PyErr_SetString(PyExc_ValueError, "weak binding ref already unreffed");
- return NULL;
- }
- g_object_unref(self->obj);
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef pygbinding_weak_ref_methods[] = {
- { "unbind", (PyCFunction)pygbinding_weak_ref_unbind, METH_NOARGS},
- { NULL, NULL, 0}
-};
-
-
static gpointer
pyobject_copy(gpointer boxed)
{
PyObject *object = boxed;
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
Py_INCREF(object);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return object;
}
@@ -2400,13 +2395,16 @@ pyobject_free(gpointer boxed)
PyObject *object = boxed;
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
Py_DECREF(object);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
}
-void
-pygobject_object_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pyi_object_register_types(PyObject *d)
{
PyObject *o, *descr;
@@ -2435,7 +2433,9 @@ pygobject_object_register_types(PyObject *d)
PyGObject_Type.tp_weaklistoffset = offsetof(PyGObject, weakreflist);
PyGObject_Type.tp_methods = pygobject_methods;
PyGObject_Type.tp_getset = pygobject_getsets;
+#ifdef PYGI_OBJECT_USE_CUSTOM_DICT
PyGObject_Type.tp_dictoffset = offsetof(PyGObject, inst_dict);
+#endif
PyGObject_Type.tp_init = (initproc)pygobject_init;
PyGObject_Type.tp_free = (freefunc)pygobject_free;
PyGObject_Type.tp_alloc = PyType_GenericAlloc;
@@ -2455,18 +2455,19 @@ pygobject_object_register_types(PyObject *d)
"Python attributes.";
PyGProps_Type.tp_traverse = (traverseproc)pygobject_props_traverse;
PyGProps_Type.tp_iter = (getiterfunc)pygobject_props_get_iter;
+ PyGProps_Type.tp_methods = pygobject_props_methods;
if (PyType_Ready(&PyGProps_Type) < 0)
- return;
+ return -1;
/* GPropsDescr */
PyGPropsDescr_Type.tp_flags = Py_TPFLAGS_DEFAULT;
PyGPropsDescr_Type.tp_descr_get = pyg_props_descr_descr_get;
if (PyType_Ready(&PyGPropsDescr_Type) < 0)
- return;
+ return -1;
descr = PyObject_New(PyObject, &PyGPropsDescr_Type);
PyDict_SetItemString(PyGObject_Type.tp_dict, "props", descr);
PyDict_SetItemString(PyGObject_Type.tp_dict, "__module__",
- o=PYGLIB_PyUnicode_FromString("gi._gobject._gobject"));
+ o=PyUnicode_FromString ("gi._gi"));
Py_DECREF(o);
/* GPropsIter */
@@ -2475,7 +2476,7 @@ pygobject_object_register_types(PyObject *d)
PyGPropsIter_Type.tp_doc = "GObject properties iterator";
PyGPropsIter_Type.tp_iternext = (iternextfunc)pygobject_props_iter_next;
if (PyType_Ready(&PyGPropsIter_Type) < 0)
- return;
+ return -1;
PyGObjectWeakRef_Type.tp_dealloc = (destructor)pygobject_weak_ref_dealloc;
PyGObjectWeakRef_Type.tp_call = (ternaryfunc)pygobject_weak_ref_call;
@@ -2485,14 +2486,66 @@ pygobject_object_register_types(PyObject *d)
PyGObjectWeakRef_Type.tp_clear = (inquiry)pygobject_weak_ref_clear;
PyGObjectWeakRef_Type.tp_methods = pygobject_weak_ref_methods;
if (PyType_Ready(&PyGObjectWeakRef_Type) < 0)
- return;
+ return -1;
PyDict_SetItemString(d, "GObjectWeakRef", (PyObject *) &PyGObjectWeakRef_Type);
- PyGBindingWeakRef_Type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
- PyGBindingWeakRef_Type.tp_doc = "A GBinding weak reference";
- PyGBindingWeakRef_Type.tp_methods = pygbinding_weak_ref_methods;
- PyGBindingWeakRef_Type.tp_base = &PyGObjectWeakRef_Type;
- if (PyType_Ready(&PyGBindingWeakRef_Type) < 0)
- return;
- PyDict_SetItemString(d, "GBindingWeakRef", (PyObject *) &PyGBindingWeakRef_Type);
+ return 0;
+}
+
+PyObject *
+pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyObject *pytype;
+ GType type;
+ GObject *obj = NULL;
+ GObjectClass *class;
+ guint n_properties = 0, i;
+ const GValue *values = NULL;
+ const char **names = NULL;
+
+ if (!PyArg_ParseTuple (args, "O:gobject.new", &pytype)) {
+ return NULL;
+ }
+
+ if ((type = pyg_type_from_object (pytype)) == 0)
+ return NULL;
+
+ if (G_TYPE_IS_ABSTRACT(type)) {
+ PyErr_Format(PyExc_TypeError, "cannot create instance of abstract "
+ "(non-instantiable) type `%s'", g_type_name(type));
+ return NULL;
+ }
+
+ if ((class = g_type_class_ref (type)) == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "could not get a reference to type class");
+ return NULL;
+ }
+
+ if (!pygobject_prepare_construct_properties (class, kwargs, &n_properties, &names, &values))
+ goto cleanup;
+
+ obj = pygobject_object_new_with_properties(type, n_properties, names, values);
+
+ if (!obj)
+ PyErr_SetString (PyExc_RuntimeError, "could not create object");
+
+ cleanup:
+ for (i = 0; i < n_properties; i++) {
+ g_free(names[i]);
+ g_value_unset(&values[i]);
+ }
+ g_free(names);
+ g_free(values);
+
+ g_type_class_unref(class);
+
+ if (obj) {
+ pygobject_sink (obj);
+ self = (PyGObject *) pygobject_new((GObject *)obj);
+ g_object_unref(obj);
+ } else
+ self = NULL;
+
+ return (PyObject *) self;
}
diff --git a/gi/pygobject-object.h b/gi/pygobject-object.h
new file mode 100644
index 0000000..95e95aa
--- /dev/null
+++ b/gi/pygobject-object.h
@@ -0,0 +1,52 @@
+#ifndef _PYGOBJECT_OBJECT_H_
+#define _PYGOBJECT_OBJECT_H_
+
+#include <Python.h>
+#include <glib-object.h>
+#include "pygobject-internal.h"
+
+/* Data that belongs to the GObject instance, not the Python wrapper */
+struct _PyGObjectData {
+ PyTypeObject *type; /* wrapper type for this instance */
+ GSList *closures;
+};
+
+extern GType PY_TYPE_OBJECT;
+extern GQuark pygobject_instance_data_key;
+extern GQuark pygobject_custom_key;
+extern GQuark pygobject_wrapper_key;
+extern GQuark pygobject_class_key;
+extern GQuark pygobject_class_init_key;
+
+extern PyTypeObject PyGObjectWeakRef_Type;
+extern PyTypeObject PyGPropsIter_Type;
+extern PyTypeObject PyGPropsDescr_Type;
+extern PyTypeObject PyGProps_Type;
+extern PyTypeObject PyGObject_Type;
+extern PyTypeObject *PyGObject_MetaType;
+
+static inline PyGObjectData *
+pyg_object_peek_inst_data(GObject *obj)
+{
+ return ((PyGObjectData *)
+ g_object_get_qdata(obj, pygobject_instance_data_key));
+}
+
+void pygobject_register_class (PyObject *dict,
+ const gchar *type_name,
+ GType gtype, PyTypeObject *type,
+ PyObject *bases);
+void pygobject_register_wrapper (PyObject *self);
+PyObject * pygobject_new (GObject *obj);
+PyObject * pygobject_new_full (GObject *obj, gboolean steal, gpointer g_class);
+void pygobject_sink (GObject *obj);
+PyTypeObject *pygobject_lookup_class (GType gtype);
+void pygobject_watch_closure (PyObject *self, GClosure *closure);
+int pyi_object_register_types (PyObject *d);
+void pygobject_ref_float(PyGObject *self);
+void pygobject_ref_sink(PyGObject *self);
+PyObject * pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs);
+
+GClosure * gclosure_from_pyfunc(PyGObject *object, PyObject *func);
+
+#endif /*_PYGOBJECT_OBJECT_H_*/
diff --git a/gi/_gobject/pygobject.h b/gi/pygobject.h
index 76b8b11..a45a4b0 100644
--- a/gi/_gobject/pygobject.h
+++ b/gi/pygobject.h
@@ -25,7 +25,7 @@ struct _PyGClosure {
typedef enum {
PYGOBJECT_USING_TOGGLE_REF = 1 << 0,
PYGOBJECT_IS_FLOATING_REF = 1 << 1,
- PYGOBJECT_GOBJECT_WAS_FLOATING = 1 << 2,
+ PYGOBJECT_GOBJECT_WAS_FLOATING = 1 << 2
} PyGObjectFlags;
/* closures is just an alias for what is found in the
@@ -57,6 +57,8 @@ typedef struct {
} PyGBoxed;
#define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed)
+#define pyg_boxed_get_ptr(v) (((PyGBoxed *)(v))->boxed)
+#define pyg_boxed_set_ptr(v,p) (((PyGBoxed *)(v))->boxed = (gpointer)p)
#define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode)
typedef struct {
@@ -66,6 +68,8 @@ typedef struct {
} PyGPointer;
#define pyg_pointer_get(v,t) ((t *)((PyGPointer *)(v))->pointer)
+#define pyg_pointer_get_ptr(v) (((PyGPointer *)(v))->pointer)
+#define pyg_pointer_set_ptr(v,p) (((PyGPointer *)(v))->pointer = (gpointer)p)
#define pyg_pointer_check(v,typecode) (PyObject_TypeCheck(v, &PyGPointer_Type) && ((PyGPointer *)(v))->gtype == typecode)
typedef void (*PyGFatalExceptionFunc) (void);
@@ -76,8 +80,13 @@ typedef struct {
GParamSpec *pspec;
} PyGParamSpec;
-#define PyGParamSpec_Get(v) (((PyGParamSpec *)v)->pspec)
-#define PyGParamSpec_Check(v) (PyObject_TypeCheck(v, &PyGParamSpec_Type))
+#define pyg_param_spec_get(v) (((PyGParamSpec *)v)->pspec)
+#define pyg_param_spec_set(v,p) (((PyGParamSpec *)v)->pspec = (GParamSpec*)p)
+#define pyg_param_spec_check(v) (PyObject_TypeCheck(v, &PyGParamSpec_Type))
+
+/* Deprecated in favor of lower case with underscore macros above. */
+#define PyGParamSpec_Get pyg_param_spec_get
+#define PyGParamSpec_Check pyg_param_spec_check
typedef int (*PyGClassInitFunc) (gpointer gclass, PyTypeObject *pyclass);
typedef PyTypeObject * (*PyGTypeRegistrationFunction) (const gchar *name,
@@ -145,12 +154,14 @@ struct _PyGObject_Functions {
PyObject *(* paramspec_new)(GParamSpec *spec);
GParamSpec *(*paramspec_get)(PyObject *tuple);
int (*pyobj_to_unichar_conv)(PyObject *pyobj, void* ptr);
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
gboolean (*parse_constructor_args)(GType obj_type,
char **arg_names,
char **prop_names,
GParameter *params,
guint *nparams,
PyObject **py_args);
+G_GNUC_END_IGNORE_DEPRECATIONS
PyObject *(* param_gvalue_as_pyobject) (const GValue* gvalue,
gboolean copy_boxed,
const GParamSpec* pspec);
@@ -199,21 +210,12 @@ struct _PyGObject_Functions {
};
-#ifdef DISABLE_THREADING
-# define pyg_threads_enabled FALSE
-# define pyg_gil_state_ensure() 0
-# define pyg_gil_state_release(state)
-# define pyg_begin_allow_threads G_STMT_START {
-# define pyg_end_allow_threads } G_STMT_END
-#else
-# define pyg_threads_enabled TRUE
-# define pyg_gil_state_ensure PyGILState_Ensure
-# define pyg_gil_state_release PyGILState_Release
-# define pyg_begin_allow_threads Py_BEGIN_ALLOW_THREADS
-# define pyg_end_allow_threads Py_END_ALLOW_THREADS
-#endif
-
/* Deprecated, only available for API compatibility. */
+#define pyg_threads_enabled TRUE
+#define pyg_gil_state_ensure PyGILState_Ensure
+#define pyg_gil_state_release PyGILState_Release
+#define pyg_begin_allow_threads Py_BEGIN_ALLOW_THREADS
+#define pyg_end_allow_threads Py_END_ALLOW_THREADS
#define pyg_enable_threads()
#define pyg_set_thread_block_funcs(a, b)
#define pyg_block_threads()
@@ -343,11 +345,13 @@ pygobject_init(int req_major, int req_minor, int req_micro)
}
cobject = PyObject_GetAttrString(gobject, "_PyGObject_API");
- if (cobject && PyCapsule_CheckExact(cobject))
+ if (cobject && PyCapsule_CheckExact(cobject)) {
_PyGObject_API = (struct _PyGObject_Functions *) PyCapsule_GetPointer(cobject, "gobject._PyGObject_API");
- else {
+ Py_DECREF (cobject);
+ } else {
PyErr_SetString(PyExc_ImportError,
"could not import gobject (could not find _PyGObject_API object)");
+ Py_XDECREF (cobject);
Py_DECREF(gobject);
return NULL;
}
diff --git a/gi/_glib/pygoptioncontext.c b/gi/pygoptioncontext.c
index 8ecbff8..c2f402c 100644
--- a/gi/_glib/pygoptioncontext.c
+++ b/gi/pygoptioncontext.c
@@ -15,20 +15,52 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
-#include <pyglib.h>
-#include "pyglib-private.h"
#include "pygoptioncontext.h"
+#include "pygi-error.h"
+#include "pygi-util.h"
+#include "pygi-basictype.h"
-PYGLIB_DEFINE_TYPE("gi._glib.OptionContext", PyGOptionContext_Type, PyGOptionContext)
+PYGI_DEFINE_TYPE("gi._gi.OptionContext", PyGOptionContext_Type, PyGOptionContext)
+
+/**
+ * pyg_option_group_transfer_group:
+ * @group: a GOptionGroup wrapper
+ *
+ * This is used to transfer the GOptionGroup to a GOptionContext. After this
+ * is called, the calle must handle the release of the GOptionGroup.
+ *
+ * When #NULL is returned, the GOptionGroup was already transfered.
+ *
+ * Returns: Either #NULL or the wrapped GOptionGroup.
+ */
+static GOptionGroup *
+pyglib_option_group_transfer_group(PyObject *obj)
+{
+ PyGOptionGroup *self = (PyGOptionGroup*)obj;
+
+ if (self->is_in_context)
+ return NULL;
+
+ self->is_in_context = TRUE;
+
+ /* Here we increase the reference count of the PyGOptionGroup, because now
+ * the GOptionContext holds an reference to us (it is the userdata passed
+ * to g_option_group_new().
+ *
+ * The GOptionGroup is freed with the GOptionContext.
+ *
+ * We set it here because if we would do this in the init method we would
+ * hold two references and the PyGOptionGroup would never be freed.
+ */
+ Py_INCREF(self);
+
+ return self->group;
+}
/**
* pyg_option_context_new:
@@ -58,7 +90,7 @@ pyg_option_context_init(PyGOptionContext *self,
{
char *parameter_string;
- if (!PyArg_ParseTuple(args, "s:gi._glib.GOptionContext.__init__",
+ if (!PyArg_ParseTuple(args, "s:gi._gi.GOptionContext.__init__",
&parameter_string))
return -1;
@@ -119,7 +151,7 @@ pyg_option_context_parse(PyGOptionContext *self,
for (pos = 0; pos < argv_length; pos++)
{
arg = PyList_GetItem(argv, pos);
- argv_content[pos] = g_strdup(PYGLIB_PyUnicode_AsString(arg));
+ argv_content[pos] = g_strdup(PyUnicode_AsUTF8 (arg));
if (argv_content[pos] == NULL)
{
g_strfreev(argv_content);
@@ -129,7 +161,7 @@ pyg_option_context_parse(PyGOptionContext *self,
original = g_strdupv(argv_content);
g_assert(argv_length <= G_MAXINT);
- argv_length_int = argv_length;
+ argv_length_int = (gint)argv_length;
Py_BEGIN_ALLOW_THREADS;
result = g_option_context_parse(self->context, &argv_length_int, &argv_content,
&error);
@@ -140,14 +172,14 @@ pyg_option_context_parse(PyGOptionContext *self,
{
g_strfreev(argv_content);
g_strfreev(original);
- pyglib_error_check(&error);
+ pygi_error_check(&error);
return NULL;
}
new_argv = PyList_New(g_strv_length(argv_content));
for (pos = 0; pos < argv_length; pos++)
{
- arg = PYGLIB_PyUnicode_FromString(argv_content[pos]);
+ arg = PyUnicode_FromString (argv_content[pos]);
PyList_SetItem(new_argv, pos, arg);
}
@@ -178,7 +210,7 @@ pyg_option_context_set_help_enabled(PyGOptionContext *self,
static PyObject *
pyg_option_context_get_help_enabled(PyGOptionContext *self)
{
- return PyBool_FromLong(g_option_context_get_help_enabled(self->context));
+ return pygi_gboolean_to_py (g_option_context_get_help_enabled(self->context));
}
static PyObject *
@@ -205,7 +237,7 @@ pyg_option_context_set_ignore_unknown_options(PyGOptionContext *self,
static PyObject *
pyg_option_context_get_ignore_unknown_options(PyGOptionContext *self)
{
- return PyBool_FromLong(
+ return pygi_gboolean_to_py (
g_option_context_get_ignore_unknown_options(self->context));
}
@@ -297,9 +329,9 @@ static PyObject*
pyg_option_context_richcompare(PyObject *self, PyObject *other, int op)
{
if (Py_TYPE(self) == Py_TYPE(other) && Py_TYPE(self) == &PyGOptionContext_Type)
- return _pyglib_generic_ptr_richcompare(((PyGOptionContext*)self)->context,
- ((PyGOptionContext*)other)->context,
- op);
+ return pyg_ptr_richcompare(((PyGOptionContext*)self)->context,
+ ((PyGOptionContext*)other)->context,
+ op);
else {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
@@ -309,7 +341,7 @@ pyg_option_context_richcompare(PyObject *self, PyObject *other, int op)
static PyObject *
pyg_option_get_context(PyGOptionContext *self)
{
- return PYGLIB_CPointer_WrapPointer(self->context, "goption.context");
+ return PyCapsule_New (self->context, "goption.context", NULL);
}
static PyMethodDef pyg_option_context_methods[] = {
@@ -325,13 +357,23 @@ static PyMethodDef pyg_option_context_methods[] = {
{ NULL, NULL, 0 },
};
-void
-pyglib_option_context_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_option_context_register_types(PyObject *d)
{
PyGOptionContext_Type.tp_dealloc = (destructor)pyg_option_context_dealloc;
PyGOptionContext_Type.tp_richcompare = pyg_option_context_richcompare;
PyGOptionContext_Type.tp_flags = Py_TPFLAGS_DEFAULT;
PyGOptionContext_Type.tp_methods = pyg_option_context_methods;
PyGOptionContext_Type.tp_init = (initproc)pyg_option_context_init;
- PYGLIB_REGISTER_TYPE(d, PyGOptionContext_Type, "OptionContext");
+ PyGOptionContext_Type.tp_alloc = PyType_GenericAlloc;
+ PyGOptionContext_Type.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyGOptionContext_Type))
+ return -1;
+
+ PyDict_SetItemString(d, "OptionContext", (PyObject *)&PyGOptionContext_Type);
+
+ return 0;
}
diff --git a/gi/_glib/pygoptioncontext.h b/gi/pygoptioncontext.h
index efe5ffa..4dea56d 100644
--- a/gi/_glib/pygoptioncontext.h
+++ b/gi/pygoptioncontext.h
@@ -14,9 +14,7 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYG_OPTIONCONTEXT_H__
@@ -34,6 +32,6 @@ typedef struct {
PyObject* pyg_option_context_new(GOptionContext *context);
-void pyglib_option_context_register_types(PyObject *d);
+int pygi_option_context_register_types(PyObject *d);
#endif /* __PYG_OPTIONCONTEXT_H__ */
diff --git a/gi/_glib/pygoptiongroup.c b/gi/pygoptiongroup.c
index 2990342..9d1bdc1 100644
--- a/gi/_glib/pygoptiongroup.c
+++ b/gi/pygoptiongroup.c
@@ -15,20 +15,16 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
-#include <pyglib.h>
-#include "pyglib-private.h"
#include "pygoptiongroup.h"
+#include "pygi-error.h"
+#include "pygi-util.h"
-PYGLIB_DEFINE_TYPE("gi._glib.OptionGroup", PyGOptionGroup_Type, PyGOptionGroup)
+PYGI_DEFINE_TYPE("gi._gi.OptionGroup", PyGOptionGroup_Type, PyGOptionGroup)
/**
* pyg_option_group_new:
@@ -62,7 +58,7 @@ check_if_owned(PyGOptionGroup *self)
if (self->other_owner)
{
PyErr_SetString(PyExc_ValueError, "The GOptionGroup was not created by "
- "gi._glib.OptionGroup(), so operation is not possible.");
+ "gi._gi.OptionGroup(), so operation is not possible.");
return TRUE;
}
return FALSE;
@@ -72,7 +68,7 @@ static void
destroy_g_group(PyGOptionGroup *self)
{
PyGILState_STATE state;
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
self->group = NULL;
Py_CLEAR(self->callback);
@@ -85,7 +81,7 @@ destroy_g_group(PyGOptionGroup *self)
Py_DECREF(self);
}
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
}
static int
@@ -119,8 +115,11 @@ pyg_option_group_dealloc(PyGOptionGroup *self)
{
GOptionGroup *tmp = self->group;
self->group = NULL;
- if (tmp)
+ if (tmp) {
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_option_group_free(tmp);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ }
}
PyObject_Del(self);
@@ -136,8 +135,7 @@ arg_func(const gchar *option_name,
PyGILState_STATE state;
gboolean no_error;
- state = pyglib_gil_state_ensure();
-
+ state = PyGILState_Ensure();
if (value == NULL)
ret = PyObject_CallFunction(self->callback, "sOO",
option_name, Py_None, self);
@@ -150,9 +148,9 @@ arg_func(const gchar *option_name,
Py_DECREF(ret);
no_error = TRUE;
} else
- no_error = pyglib_gerror_exception_check(error) != -1;
+ no_error = pygi_gerror_exception_check(error) != -1;
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return no_error;
}
@@ -271,9 +269,9 @@ pyg_option_group_richcompare(PyObject *self, PyObject *other, int op)
{
if (Py_TYPE(self) == Py_TYPE(other) &&
Py_TYPE(self) == &PyGOptionGroup_Type) {
- return _pyglib_generic_ptr_richcompare(((PyGOptionGroup*)self)->group,
- ((PyGOptionGroup*)other)->group,
- op);
+ return pyg_ptr_richcompare(((PyGOptionGroup*)self)->group,
+ ((PyGOptionGroup*)other)->group,
+ op);
} else {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
@@ -286,13 +284,24 @@ static PyMethodDef pyg_option_group_methods[] = {
{ NULL, NULL, 0 },
};
-void
-pyglib_option_group_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_option_group_register_types(PyObject *d)
{
PyGOptionGroup_Type.tp_dealloc = (destructor)pyg_option_group_dealloc;
PyGOptionGroup_Type.tp_richcompare = pyg_option_group_richcompare;
PyGOptionGroup_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
PyGOptionGroup_Type.tp_methods = pyg_option_group_methods;
PyGOptionGroup_Type.tp_init = (initproc)pyg_option_group_init;
- PYGLIB_REGISTER_TYPE(d, PyGOptionGroup_Type, "OptionGroup");
+ PyGOptionGroup_Type.tp_alloc = PyType_GenericAlloc;
+ PyGOptionGroup_Type.tp_new = PyType_GenericNew;
+
+ if (PyType_Ready(&PyGOptionGroup_Type))
+ return -1;
+
+ PyDict_SetItemString(d, "OptionGroup", (PyObject *)&PyGOptionGroup_Type);
+
+ return 0;
}
diff --git a/gi/_glib/pygoptiongroup.h b/gi/pygoptiongroup.h
index 872b9c6..65d08e4 100644
--- a/gi/_glib/pygoptiongroup.h
+++ b/gi/pygoptiongroup.h
@@ -14,14 +14,15 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYG_OPTIONGROUP_H__
#define __PYG_OPTIONGROUP_H__
+#include <Python.h>
+#include <glib.h>
+
extern PyTypeObject PyGOptionGroup_Type;
typedef struct {
@@ -35,7 +36,7 @@ typedef struct {
PyObject* pyg_option_group_new(GOptionGroup *group);
-void pyglib_option_group_register_types(PyObject *d);
+int pygi_option_group_register_types(PyObject *d);
#endif /* __PYG_OPTIONGROUP_H__ */
diff --git a/gi/pygparamspec.c b/gi/pygparamspec.c
new file mode 100644
index 0000000..e49bd36
--- /dev/null
+++ b/gi/pygparamspec.c
@@ -0,0 +1,423 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * Copyright (C) 2004 Johan Dahlin
+ *
+ * pygenum.c: GEnum and GFlag wrappers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <Python.h>
+#include <glib-object.h>
+
+#include "pygenum.h"
+#include "pygflags.h"
+#include "pygi-type.h"
+#include "pygparamspec.h"
+#include "pygi-util.h"
+#include "pygi-basictype.h"
+
+PYGI_DEFINE_TYPE("gobject.GParamSpec", PyGParamSpec_Type, PyGParamSpec);
+
+static PyObject*
+pyg_param_spec_richcompare(PyObject *self, PyObject *other, int op)
+{
+ if (Py_TYPE(self) == Py_TYPE(other) && Py_TYPE(self) == &PyGParamSpec_Type)
+ return pyg_ptr_richcompare (pyg_param_spec_get (self),
+ pyg_param_spec_get (other),
+ op);
+ else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+}
+
+static Py_hash_t
+pyg_param_spec_hash(PyGParamSpec *self)
+{
+ return (Py_hash_t)(gintptr)(pyg_param_spec_get (self));
+}
+
+static PyObject *
+pyg_param_spec_repr(PyGParamSpec *self)
+{
+ char buf[80];
+
+ g_snprintf(buf, sizeof(buf), "<%s '%s'>",
+ G_PARAM_SPEC_TYPE_NAME (pyg_param_spec_get (self)),
+ g_param_spec_get_name (pyg_param_spec_get (self)));
+ return PyUnicode_FromString (buf);
+}
+
+static void
+pyg_param_spec_dealloc(PyGParamSpec *self)
+{
+ g_param_spec_unref (pyg_param_spec_get (self));
+ PyObject_DEL(self);
+}
+
+
+static PyObject *
+pygenum_from_pspec(GParamSpec *pspec)
+{
+ PyObject *pyclass;
+ GParamSpecEnum *enum_pspec;
+ GType enum_type;
+
+ enum_pspec = G_PARAM_SPEC_ENUM(pspec);
+ enum_type = G_ENUM_CLASS_TYPE(enum_pspec->enum_class);
+ pyclass = (PyObject*)g_type_get_qdata(enum_type, pygenum_class_key);
+ if (pyclass == NULL) {
+ pyclass = pyg_enum_add(NULL, g_type_name(enum_type), NULL, enum_type);
+ if (pyclass == NULL)
+ pyclass = Py_None;
+ }
+
+ Py_INCREF(pyclass);
+ return pyclass;
+}
+
+static PyObject *
+pygflags_from_pspec(GParamSpec *pspec)
+{
+ PyObject *pyclass;
+ GParamSpecFlags *flag_pspec;
+ GType flag_type;
+
+ flag_pspec = G_PARAM_SPEC_FLAGS(pspec);
+ flag_type = G_FLAGS_CLASS_TYPE(flag_pspec->flags_class);
+ pyclass = (PyObject*)g_type_get_qdata(flag_type, pygflags_class_key);
+ if (pyclass == NULL) {
+ pyclass = pyg_flags_add(NULL, g_type_name(flag_type), NULL, flag_type);
+ if (pyclass == NULL)
+ pyclass = Py_None;
+ }
+ Py_INCREF(pyclass);
+ return pyclass;
+}
+
+static PyObject *
+pyg_param_spec_getattr(PyGParamSpec *self, const gchar *attr)
+{
+ GParamSpec *pspec;
+
+ pspec = pyg_param_spec_get (self);
+
+ /* common attributes */
+ if (!strcmp(attr, "__gtype__")) {
+ return pyg_type_wrapper_new(G_PARAM_SPEC_TYPE(pspec));
+ } else if (!strcmp(attr, "name")) {
+ return Py_BuildValue("s", g_param_spec_get_name(pspec));
+ } else if (!strcmp(attr, "nick")) {
+ return Py_BuildValue("s", g_param_spec_get_nick(pspec));
+ } else if (!strcmp(attr, "blurb") || !strcmp(attr, "__doc__")) {
+ return Py_BuildValue("s", g_param_spec_get_blurb(pspec));
+ } else if (!strcmp(attr, "flags")) {
+ return pygi_guint_to_py (pspec->flags);
+ } else if (!strcmp(attr, "value_type")) {
+ return pyg_type_wrapper_new(pspec->value_type);
+ } else if (!strcmp(attr, "owner_type")) {
+ return pyg_type_wrapper_new(pspec->owner_type);
+ }
+
+ if (G_IS_PARAM_SPEC_CHAR(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return PyUnicode_FromFormat(
+ "%c", G_PARAM_SPEC_CHAR(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_gint8_to_py (G_PARAM_SPEC_CHAR(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_gint8_to_py (G_PARAM_SPEC_CHAR(pspec)->maximum);
+ }
+ } else if (G_IS_PARAM_SPEC_UCHAR(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return PyUnicode_FromFormat(
+ "%c", G_PARAM_SPEC_UCHAR(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_guint8_to_py (G_PARAM_SPEC_UCHAR(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_guint8_to_py (G_PARAM_SPEC_UCHAR(pspec)->maximum);
+ }
+ } else if (G_IS_PARAM_SPEC_BOOLEAN(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_gboolean_to_py (G_PARAM_SPEC_BOOLEAN(pspec)->default_value);
+ }
+ } else if (G_IS_PARAM_SPEC_INT(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_gint_to_py (G_PARAM_SPEC_INT(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_gint_to_py (G_PARAM_SPEC_INT(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_gint_to_py (G_PARAM_SPEC_INT(pspec)->maximum);
+ }
+ } else if (G_IS_PARAM_SPEC_UINT(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_guint_to_py (G_PARAM_SPEC_UINT(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_guint_to_py (G_PARAM_SPEC_UINT(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_guint_to_py (G_PARAM_SPEC_UINT(pspec)->maximum);
+ }
+ } else if (G_IS_PARAM_SPEC_LONG(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_glong_to_py (G_PARAM_SPEC_LONG(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_glong_to_py (G_PARAM_SPEC_LONG(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_glong_to_py (G_PARAM_SPEC_LONG(pspec)->maximum);
+ }
+ } else if (G_IS_PARAM_SPEC_ULONG(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_gulong_to_py (G_PARAM_SPEC_ULONG(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_gulong_to_py (G_PARAM_SPEC_ULONG(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_gulong_to_py (G_PARAM_SPEC_ULONG(pspec)->maximum);
+ }
+ } else if (G_IS_PARAM_SPEC_INT64(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_gint64_to_py (G_PARAM_SPEC_INT64(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_gint64_to_py (G_PARAM_SPEC_INT64(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_gint64_to_py (G_PARAM_SPEC_INT64(pspec)->maximum);
+ }
+ } else if (G_IS_PARAM_SPEC_UINT64(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_guint64_to_py (G_PARAM_SPEC_UINT64(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_guint64_to_py (G_PARAM_SPEC_UINT64(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_guint64_to_py (G_PARAM_SPEC_UINT64(pspec)->maximum);
+ }
+ } else if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return PyUnicode_FromFormat(
+ "%c", G_PARAM_SPEC_UNICHAR(pspec)->default_value);
+ }
+ } else if (G_IS_PARAM_SPEC_ENUM(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pyg_enum_from_gtype(
+ pspec->value_type, G_PARAM_SPEC_ENUM(pspec)->default_value);
+ } else if (!strcmp(attr, "enum_class")) {
+ return pygenum_from_pspec(pspec);
+ }
+ } else if (G_IS_PARAM_SPEC_FLAGS(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pyg_flags_from_gtype(
+ pspec->value_type, G_PARAM_SPEC_FLAGS(pspec)->default_value);
+ } else if (!strcmp(attr, "flags_class")) {
+ return pygflags_from_pspec(pspec);
+ }
+ } else if (G_IS_PARAM_SPEC_FLOAT(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_gfloat_to_py (G_PARAM_SPEC_FLOAT(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_gfloat_to_py (G_PARAM_SPEC_FLOAT(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_gfloat_to_py (G_PARAM_SPEC_FLOAT(pspec)->maximum);
+ } else if (!strcmp(attr, "epsilon")) {
+ return pygi_gfloat_to_py (G_PARAM_SPEC_FLOAT(pspec)->epsilon);
+ }
+ } else if (G_IS_PARAM_SPEC_DOUBLE(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return pygi_gdouble_to_py (
+ G_PARAM_SPEC_DOUBLE(pspec)->default_value);
+ } else if (!strcmp(attr, "minimum")) {
+ return pygi_gdouble_to_py (G_PARAM_SPEC_DOUBLE(pspec)->minimum);
+ } else if (!strcmp(attr, "maximum")) {
+ return pygi_gdouble_to_py (G_PARAM_SPEC_DOUBLE(pspec)->maximum);
+ } else if (!strcmp(attr, "epsilon")) {
+ return pygi_gdouble_to_py (G_PARAM_SPEC_DOUBLE(pspec)->epsilon);
+ }
+ } else if (G_IS_PARAM_SPEC_STRING(pspec)) {
+ if (!strcmp(attr, "default_value")) {
+ return Py_BuildValue(
+ "s", G_PARAM_SPEC_STRING(pspec)->default_value);
+ } else if (!strcmp(attr, "cset_first")) {
+ return Py_BuildValue(
+ "s", G_PARAM_SPEC_STRING(pspec)->cset_first);
+ } else if (!strcmp(attr, "cset_nth")) {
+ return Py_BuildValue(
+ "s", G_PARAM_SPEC_STRING(pspec)->cset_nth);
+ } else if (!strcmp(attr, "substitutor")) {
+ return Py_BuildValue(
+ "c", G_PARAM_SPEC_STRING(pspec)->substitutor);
+ } else if (!strcmp(attr, "null_fold_if_empty")) {
+ return pygi_gboolean_to_py (
+ G_PARAM_SPEC_STRING(pspec)->null_fold_if_empty);
+ } else if (!strcmp(attr, "ensure_non_null")) {
+ return pygi_gboolean_to_py (
+ G_PARAM_SPEC_STRING(pspec)->ensure_non_null);
+ }
+ } else {
+ /* This is actually not what's exported by GObjects paramspecs,
+ * But we exported this in earlier versions, so it's better to keep it here
+ * compatibility. But don't return it in __dir__, to "hide" it.
+ */
+ if (!strcmp(attr, "default_value")) {
+ /* XXX: Raise deprecation warning */
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ }
+
+ PyErr_SetString(PyExc_AttributeError, attr);
+ return NULL;
+}
+
+
+static PyObject *
+pyg_param_spec_dir(PyGParamSpec *self, PyObject *dummy)
+{
+ GParamSpec *pspec = pyg_param_spec_get (self);
+
+ if (G_IS_PARAM_SPEC_CHAR(pspec)) {
+ return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value", "flags",
+ "maximum", "minimum", "name", "nick",
+ "owner_type", "value_type");
+ } else if (G_IS_PARAM_SPEC_UCHAR(pspec)) {
+ return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "maximum", "minimum",
+ "name", "nick", "owner_type",
+ "value_type");
+ } else if (G_IS_PARAM_SPEC_BOOLEAN(pspec)) {
+ return Py_BuildValue("[sssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "name", "nick", "owner_type",
+ "value_type");
+ } else if (G_IS_PARAM_SPEC_INT(pspec)) {
+ return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "maximum", "minimum", "name",
+ "nick", "owner_type", "value_type");
+ } else if (G_IS_PARAM_SPEC_UINT(pspec)) {
+ return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "maximum", "minimum",
+ "name", "nick", "owner_type",
+ "value_type");
+ } else if (G_IS_PARAM_SPEC_LONG(pspec)) {
+ return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "maximum", "minimum", "name",
+ "nick", "owner_type", "value_type");
+ } else if (G_IS_PARAM_SPEC_ULONG(pspec)) {
+ return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "maximum", "minimum", "name",
+ "nick", "owner_type", "value_type");
+ } else if (G_IS_PARAM_SPEC_INT64(pspec)) {
+ return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "maximum", "minimum", "name",
+ "nick", "owner_type", "value_type");
+ } else if (G_IS_PARAM_SPEC_UINT64(pspec)) {
+ return Py_BuildValue("[sssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "maximum", "minimum",
+ "name", "nick", "owner_type",
+ "value_type");
+ } else if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
+ return Py_BuildValue("[sssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "name", "nick", "owner_type",
+ "value_type");
+ } else if (G_IS_PARAM_SPEC_ENUM(pspec)) {
+ return Py_BuildValue("[ssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value", "enum_class",
+ "flags", "name", "nick", "owner_type",
+ "value_type");
+ } else if (G_IS_PARAM_SPEC_FLAGS(pspec)) {
+ return Py_BuildValue("[ssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value",
+ "flags", "flags_class", "name", "nick",
+ "owner_type", "value_type");
+ } else if (G_IS_PARAM_SPEC_FLOAT(pspec)) {
+ return Py_BuildValue("[ssssssssssss]", "__doc__", "__gtype__",
+ "blurb", "epsilon",
+ "flags", "maximum", "minimum", "name", "nick", "owner_type",
+ "value_type",
+ "default_value");
+ } else if (G_IS_PARAM_SPEC_DOUBLE(pspec)) {
+ return Py_BuildValue("[ssssssssssss]", "__doc__", "__gtype__",
+ "blurb", "default_value", "epsilon",
+ "flags", "maximum", "minimum", "name", "nick",
+ "owner_type", "value_type");
+ } else if (G_IS_PARAM_SPEC_STRING(pspec)) {
+ return Py_BuildValue("[ssssssssssssss]", "__doc__", "__gtype__",
+ "blurb", "cset_first", "cset_nth", "default_value",
+ "ensure_non_null", "flags", "name", "nick",
+ "null_fold_if_empty", "owner_type", "substitutor",
+ "value_type");
+ } else {
+ return Py_BuildValue("[ssssssss]", "__doc__", "__gtype__", "blurb",
+ "flags", "name", "nick",
+ "owner_type", "value_type");
+ }
+}
+
+static PyMethodDef pyg_param_spec_methods[] = {
+ { "__dir__", (PyCFunction)pyg_param_spec_dir, METH_NOARGS},
+ { NULL, NULL, 0}
+};
+
+/**
+ * pyg_param_spec_new:
+ * @pspec: a GParamSpec.
+ *
+ * Creates a wrapper for a GParamSpec.
+ *
+ * Returns: the GParamSpec wrapper.
+ */
+PyObject *
+pyg_param_spec_new(GParamSpec *pspec)
+{
+ PyGParamSpec *self;
+
+ self = (PyGParamSpec *)PyObject_NEW(PyGParamSpec,
+ &PyGParamSpec_Type);
+ if (self == NULL)
+ return NULL;
+
+ pyg_param_spec_set (self, g_param_spec_ref (pspec));
+ return (PyObject *)self;
+}
+
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_paramspec_register_types(PyObject *d)
+{
+ Py_SET_TYPE(&PyGParamSpec_Type, &PyType_Type);
+ PyGParamSpec_Type.tp_dealloc = (destructor)pyg_param_spec_dealloc;
+ PyGParamSpec_Type.tp_getattr = (getattrfunc)pyg_param_spec_getattr;
+ PyGParamSpec_Type.tp_richcompare = pyg_param_spec_richcompare;
+ PyGParamSpec_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ PyGParamSpec_Type.tp_repr = (reprfunc)pyg_param_spec_repr;
+ PyGParamSpec_Type.tp_hash = (hashfunc)pyg_param_spec_hash;
+ PyGParamSpec_Type.tp_methods = pyg_param_spec_methods;
+
+ if (PyType_Ready(&PyGParamSpec_Type))
+ return -1;
+ PyDict_SetItemString(d, "GParamSpec", (PyObject *)&PyGParamSpec_Type);
+
+ return 0;
+}
diff --git a/gi/_gobject/pygparamspec.h b/gi/pygparamspec.h
index 64aab0c..8798535 100644
--- a/gi/_gobject/pygparamspec.h
+++ b/gi/pygparamspec.h
@@ -15,17 +15,17 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGOBJECT_PARAMSPEC_H__
#define __PYGOBJECT_PARAMSPEC_H__
+#include <glib-object.h>
+
extern PyTypeObject PyGParamSpec_Type;
PyObject * pyg_param_spec_new (GParamSpec *pspec);
-void pygobject_paramspec_register_types(PyObject *d);
+int pygi_paramspec_register_types(PyObject *d);
#endif /* __PYGOBJECT_PARAMSPEC_H__ */
diff --git a/gi/_gobject/pygpointer.c b/gi/pygpointer.c
index 575c751..6d6b62f 100644
--- a/gi/_gobject/pygpointer.c
+++ b/gi/pygpointer.c
@@ -15,25 +15,22 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
-#include <pyglib.h>
-#include "pygobject-private.h"
+#include <Python.h>
+#include <glib-object.h>
#include "pygpointer.h"
-
-#include "pygi.h"
+#include "pygi-type.h"
+#include "pygi-type.h"
+#include "pygi-util.h"
GQuark pygpointer_class_key;
-PYGLIB_DEFINE_TYPE("gobject.GPointer", PyGPointer_Type, PyGPointer);
+PYGI_DEFINE_TYPE("gobject.GPointer", PyGPointer_Type, PyGPointer);
static void
pyg_pointer_dealloc(PyGPointer *self)
@@ -45,19 +42,19 @@ static PyObject*
pyg_pointer_richcompare(PyObject *self, PyObject *other, int op)
{
if (Py_TYPE(self) == Py_TYPE(other))
- return _pyglib_generic_ptr_richcompare(((PyGPointer*)self)->pointer,
- ((PyGPointer*)other)->pointer,
- op);
+ return pyg_ptr_richcompare (pyg_pointer_get_ptr (self),
+ pyg_pointer_get_ptr (other),
+ op);
else {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
}
-static long
+static Py_hash_t
pyg_pointer_hash(PyGPointer *self)
{
- return (long)self->pointer;
+ return (Py_hash_t)(gintptr)(pyg_pointer_get_ptr (self));
}
static PyObject *
@@ -65,9 +62,10 @@ pyg_pointer_repr(PyGPointer *self)
{
gchar buf[128];
- g_snprintf(buf, sizeof(buf), "<%s at 0x%lx>", g_type_name(self->gtype),
- (long)self->pointer);
- return PYGLIB_PyUnicode_FromString(buf);
+ g_snprintf(buf, sizeof(buf), "<%s at 0x%" G_GUINTPTR_FORMAT ">",
+ g_type_name(self->gtype),
+ (guintptr)pyg_pointer_get_ptr (self));
+ return PyUnicode_FromString (buf);
}
static int
@@ -78,7 +76,7 @@ pyg_pointer_init(PyGPointer *self, PyObject *args, PyObject *kwargs)
if (!PyArg_ParseTuple(args, ":GPointer.__init__"))
return -1;
- self->pointer = NULL;
+ pyg_pointer_set_ptr (self, NULL);
self->gtype = 0;
g_snprintf(buf, sizeof(buf), "%s can not be constructed",
@@ -116,7 +114,8 @@ pyg_register_pointer(PyObject *dict, const gchar *class_name,
if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_pointer_dealloc;
- Py_TYPE(type) = &PyType_Type;
+ Py_SET_TYPE(type, &PyType_Type);
+ g_assert (Py_TYPE (&PyGPointer_Type) != NULL);
type->tp_base = &PyGPointer_Type;
if (PyType_Ready(type) < 0) {
@@ -154,11 +153,11 @@ pyg_pointer_new(GType pointer_type, gpointer pointer)
PyTypeObject *tp;
g_return_val_if_fail(pointer_type != 0, NULL);
- state = pyglib_gil_state_ensure();
+ state = PyGILState_Ensure();
if (!pointer) {
Py_INCREF(Py_None);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
return Py_None;
}
@@ -171,20 +170,25 @@ pyg_pointer_new(GType pointer_type, gpointer pointer)
tp = (PyTypeObject *)&PyGPointer_Type; /* fallback */
self = PyObject_NEW(PyGPointer, tp);
- pyglib_gil_state_release(state);
+ PyGILState_Release(state);
if (self == NULL)
return NULL;
- self->pointer = pointer;
+ pyg_pointer_set_ptr (self, pointer);
self->gtype = pointer_type;
return (PyObject *)self;
}
-void
-pygobject_pointer_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_pointer_register_types(PyObject *d)
{
+ PyObject *pygtype;
+
pygpointer_class_key = g_quark_from_static_string("PyGPointer::class");
PyGPointer_Type.tp_dealloc = (destructor)pyg_pointer_dealloc;
@@ -194,5 +198,16 @@ pygobject_pointer_register_types(PyObject *d)
PyGPointer_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
PyGPointer_Type.tp_init = (initproc)pyg_pointer_init;
PyGPointer_Type.tp_free = (freefunc)pyg_pointer_free;
- PYGOBJECT_REGISTER_GTYPE(d, PyGPointer_Type, "GPointer", G_TYPE_POINTER);
+ PyGPointer_Type.tp_alloc = PyType_GenericAlloc;
+ PyGPointer_Type.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyGPointer_Type))
+ return -1;
+
+ pygtype = pyg_type_wrapper_new (G_TYPE_POINTER);
+ PyDict_SetItemString (PyGPointer_Type.tp_dict, "__gtype__", pygtype);
+ Py_DECREF (pygtype);
+
+ PyDict_SetItemString(d, "GPointer", (PyObject *)&PyGPointer_Type);
+
+ return 0;
}
diff --git a/gi/_gobject/pygpointer.h b/gi/pygpointer.h
index f2923da..df2c1e0 100644
--- a/gi/_gobject/pygpointer.h
+++ b/gi/pygpointer.h
@@ -14,14 +14,22 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGOBJECT_POINTER_H__
#define __PYGOBJECT_POINTER_H__
-void pygobject_pointer_register_types(PyObject *d);
+#include <Python.h>
+
+extern GQuark pygpointer_class_key;
+
+extern PyTypeObject PyGPointer_Type;
+
+void pyg_register_pointer (PyObject *dict, const gchar *class_name,
+ GType pointer_type, PyTypeObject *type);
+PyObject * pyg_pointer_new (GType pointer_type, gpointer pointer);
+
+int pygi_pointer_register_types(PyObject *d);
#endif /* __PYGOBJECT_POINTER_H__ */
diff --git a/gi/_glib/pygspawn.c b/gi/pygspawn.c
index 72746b8..56ecf06 100644
--- a/gi/_glib/pygspawn.c
+++ b/gi/pygspawn.c
@@ -16,30 +16,38 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <Python.h>
#include <glib.h>
-#include "pyglib.h"
-#include "pyglib-private.h"
-
+#include "pygi-util.h"
+#include "pygi-basictype.h"
#include "pygspawn.h"
+#include "pygi-error.h"
struct _PyGChildSetupData {
PyObject *func;
PyObject *data;
};
-PYGLIB_DEFINE_TYPE("gi._glib.Pid", PyGPid_Type, PYGLIB_PyLongObject)
+PYGI_DEFINE_TYPE("gi._gi.Pid", PyGPid_Type, PyLongObject)
+
+static GPid
+pyg_pid_get_pid (PyObject *self)
+{
+#ifdef G_OS_WIN32
+ return (GPid)PyLong_AsVoidPtr (self);
+#else
+ return (GPid)PyLong_AsLong (self);
+#endif
+}
static PyObject *
pyg_pid_close(PyObject *self, PyObject *args, PyObject *kwargs)
{
- g_spawn_close_pid(PYGLIB_PyLong_AsLong(self));
+ g_spawn_close_pid(pyg_pid_get_pid (self));
Py_INCREF(Py_None);
return Py_None;
}
@@ -52,22 +60,28 @@ static PyMethodDef pyg_pid_methods[] = {
static void
pyg_pid_free(PyObject *gpid)
{
- g_spawn_close_pid((GPid) PYGLIB_PyLong_AsLong(gpid));
- PYGLIB_PyLong_Type.tp_free((void *) gpid);
+ g_spawn_close_pid(pyg_pid_get_pid (gpid));
+ PyLong_Type.tp_free((void *) gpid);
}
static int
pyg_pid_tp_init(PyObject *self, PyObject *args, PyObject *kwargs)
{
- PyErr_SetString(PyExc_TypeError, "gi._glib.Pid cannot be manually instantiated");
+ PyErr_SetString(PyExc_TypeError, "gi._gi.Pid cannot be manually instantiated");
return -1;
}
PyObject *
pyg_pid_new(GPid pid)
{
- return PyObject_CallMethod((PyObject*)&PyGPid_Type, "__new__", "Oi",
- &PyGPid_Type, pid);
+ PyObject *long_val;
+#ifdef G_OS_WIN32
+ long_val = PyLong_FromVoidPtr (pid);
+#else
+ long_val = pygi_gint_to_py (pid);
+#endif
+ return PyObject_CallMethod((PyObject*)&PyGPid_Type, "__new__", "ON",
+ &PyGPid_Type, long_val);
}
static void
@@ -78,7 +92,7 @@ _pyg_spawn_async_callback(gpointer user_data)
PyGILState_STATE gil;
data = (struct _PyGChildSetupData *) user_data;
- gil = pyglib_gil_state_ensure();
+ gil = PyGILState_Ensure();
if (data->data)
retval = PyObject_CallFunction(data->func, "O", data->data);
else
@@ -90,7 +104,7 @@ _pyg_spawn_async_callback(gpointer user_data)
Py_DECREF(data->func);
Py_XDECREF(data->data);
g_slice_free(struct _PyGChildSetupData, data);
- pyglib_gil_state_release(gil);
+ PyGILState_Release(gil);
}
PyObject *
@@ -108,10 +122,10 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
gint *standard_input, *standard_output, *standard_error;
struct _PyGChildSetupData *callback_data = NULL;
GError *error = NULL;
- GPid child_pid = -1;
+ GPid child_pid = 0;
Py_ssize_t len, i;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OsiOOOOO:gi._glib.spawn_async",
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OsiOOOOO:gi._gi.spawn_async",
kwlist,
&pyargv, &pyenvp, &working_directory, &flags,
&func, &user_data,
@@ -136,7 +150,7 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
/* parse argv */
if (!PySequence_Check(pyargv)) {
PyErr_SetString(PyExc_TypeError,
- "gi._glib.spawn_async: "
+ "gi._gi.spawn_async: "
"first argument must be a sequence of strings");
return NULL;
}
@@ -144,15 +158,15 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
argv = g_new0(char *, len + 1);
for (i = 0; i < len; ++i) {
PyObject *tmp = PySequence_ITEM(pyargv, i);
- if (tmp == NULL || !PYGLIB_PyUnicode_Check(tmp)) {
+ if (tmp == NULL || !PyUnicode_Check (tmp)) {
PyErr_SetString(PyExc_TypeError,
- "gi._glib.spawn_async: "
+ "gi._gi.spawn_async: "
"first argument must be a sequence of strings");
g_free(argv);
Py_XDECREF(tmp);
return NULL;
}
- argv[i] = PYGLIB_PyUnicode_AsString(tmp);
+ argv[i] = PyUnicode_AsUTF8 (tmp);
Py_DECREF(tmp);
}
@@ -160,7 +174,7 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
if (pyenvp) {
if (!PySequence_Check(pyenvp)) {
PyErr_SetString(PyExc_TypeError,
- "gi._glib.spawn_async: "
+ "gi._gi.spawn_async: "
"second argument must be a sequence of strings");
g_free(argv);
return NULL;
@@ -169,16 +183,16 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
envp = g_new0(char *, len + 1);
for (i = 0; i < len; ++i) {
PyObject *tmp = PySequence_ITEM(pyenvp, i);
- if (tmp == NULL || !PYGLIB_PyUnicode_Check(tmp)) {
+ if (tmp == NULL || !PyUnicode_Check (tmp)) {
PyErr_SetString(PyExc_TypeError,
- "gi._glib.spawn_async: "
+ "gi._gi.spawn_async: "
"second argument must be a sequence of strings");
g_free(envp);
Py_XDECREF(tmp);
g_free(argv);
return NULL;
}
- envp[i] = PYGLIB_PyUnicode_AsString(tmp);
+ envp[i] = PyUnicode_AsUTF8 (tmp);
Py_DECREF(tmp);
}
}
@@ -216,28 +230,28 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
Py_XDECREF(callback_data->data);
g_slice_free(struct _PyGChildSetupData, callback_data);
}
- pyglib_error_check(&error);
+ pygi_error_check(&error);
return NULL;
}
g_free(argv);
if (envp) g_free(envp);
if (standard_input)
- pystdin = PYGLIB_PyLong_FromLong(*standard_input);
+ pystdin = pygi_gint_to_py(*standard_input);
else {
Py_INCREF(Py_None);
pystdin = Py_None;
}
if (standard_output)
- pystdout = PYGLIB_PyLong_FromLong(*standard_output);
+ pystdout = pygi_gint_to_py(*standard_output);
else {
Py_INCREF(Py_None);
pystdout = Py_None;
}
if (standard_error)
- pystderr = PYGLIB_PyLong_FromLong(*standard_error);
+ pystderr = pygi_gint_to_py(*standard_error);
else {
Py_INCREF(Py_None);
pystderr = Py_None;
@@ -246,14 +260,24 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
return Py_BuildValue("NNNN", pyg_pid_new(child_pid), pystdin, pystdout, pystderr);
}
-void
-pyglib_spawn_register_types(PyObject *d)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_spawn_register_types(PyObject *d)
{
- PyGPid_Type.tp_base = &PYGLIB_PyLong_Type;
+ PyGPid_Type.tp_base = &PyLong_Type;
PyGPid_Type.tp_flags = Py_TPFLAGS_DEFAULT;
PyGPid_Type.tp_methods = pyg_pid_methods;
PyGPid_Type.tp_init = pyg_pid_tp_init;
PyGPid_Type.tp_free = (freefunc)pyg_pid_free;
- PyGPid_Type.tp_new = PYGLIB_PyLong_Type.tp_new;
- PYGLIB_REGISTER_TYPE(d, PyGPid_Type, "Pid");
+ PyGPid_Type.tp_new = PyLong_Type.tp_new;
+ PyGPid_Type.tp_alloc = PyType_GenericAlloc;
+
+ if (PyType_Ready(&PyGPid_Type))
+ return -1;
+
+ PyDict_SetItemString(d, "Pid", (PyObject *)&PyGPid_Type);
+
+ return 0;
}
diff --git a/gi/_glib/pygspawn.h b/gi/pygspawn.h
index 2e8dd3c..c493ef8 100644
--- a/gi/_glib/pygspawn.h
+++ b/gi/pygspawn.h
@@ -14,16 +14,14 @@
* 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 Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PYG_PID_H__
#define __PYG_PID_H__
PyObject * pyg_pid_new(GPid pid);
-void pyglib_spawn_register_types(PyObject *d);
+int pygi_spawn_register_types(PyObject *d);
PyObject * pyglib_spawn_async(PyObject *self, PyObject *args, PyObject *kwargs);
diff --git a/gi/pygtkcompat.py b/gi/pygtkcompat.py
index 4a9c4be..364fb6c 100644
--- a/gi/pygtkcompat.py
+++ b/gi/pygtkcompat.py
@@ -1,4 +1,3 @@
-from __future__ import absolute_import
import warnings
from gi import PyGIDeprecationWarning
diff --git a/gi/repository/Makefile.am b/gi/repository/Makefile.am
deleted file mode 100644
index 1177ad5..0000000
--- a/gi/repository/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-pygirepositorydir = $(pyexecdir)/gi/repository
-
-pygirepository_PYTHON = \
- __init__.py
-
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pygirepository_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-all-local: build_pylinks
-check-local: build_pylinks
diff --git a/gi/repository/Makefile.in b/gi/repository/Makefile.in
deleted file mode 100644
index 72cbd29..0000000
--- a/gi/repository/Makefile.in
+++ /dev/null
@@ -1,574 +0,0 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = gi/repository
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(pygirepository_PYTHON) $(top_srcdir)/py-compile
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
- $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-SOURCES =
-DIST_SOURCES =
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile)
-am__installdirs = "$(DESTDIR)$(pygirepositorydir)"
-am__pep3147_tweak = \
- sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|'
-py_compile = $(top_srcdir)/py-compile
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CAIRO_CFLAGS = @CAIRO_CFLAGS@
-CAIRO_LIBS = @CAIRO_LIBS@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
-CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
-CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DATADIR = @DATADIR@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FFI_CFLAGS = @FFI_CFLAGS@
-FFI_LIBS = @FFI_LIBS@
-FGREP = @FGREP@
-GENHTML = @GENHTML@
-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_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
-GLIB_LIBS = @GLIB_LIBS@
-GLIB_MKENUMS = @GLIB_MKENUMS@
-GOBJECT_QUERY = @GOBJECT_QUERY@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
-INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBFFI_PC = @LIBFFI_PC@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLATFORM = @PLATFORM@
-PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@
-PYCAIRO_LIBS = @PYCAIRO_LIBS@
-PYGOBJECT_MAJOR_VERSION = @PYGOBJECT_MAJOR_VERSION@
-PYGOBJECT_MICRO_VERSION = @PYGOBJECT_MICRO_VERSION@
-PYGOBJECT_MINOR_VERSION = @PYGOBJECT_MINOR_VERSION@
-PYTHON = @PYTHON@
-PYTHON_BASENAME = @PYTHON_BASENAME@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_INCLUDES = @PYTHON_INCLUDES@
-PYTHON_LIBS = @PYTHON_LIBS@
-PYTHON_LIB_LOC = @PYTHON_LIB_LOC@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_SO = @PYTHON_SO@
-PYTHON_VERSION = @PYTHON_VERSION@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-THREADING_CFLAGS = @THREADING_CFLAGS@
-VERSION = @VERSION@
-WARN_CFLAGS = @WARN_CFLAGS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-pygirepositorydir = $(pyexecdir)/gi/repository
-pygirepository_PYTHON = \
- __init__.py
-
-all: all-am
-
-.SUFFIXES:
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign gi/repository/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign gi/repository/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-pygirepositoryPYTHON: $(pygirepository_PYTHON)
- @$(NORMAL_INSTALL)
- @list='$(pygirepository_PYTHON)'; dlist=; list2=; test -n "$(pygirepositorydir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(pygirepositorydir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pygirepositorydir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \
- if test -f $$b$$p; then \
- $(am__strip_dir) \
- dlist="$$dlist $$f"; \
- list2="$$list2 $$b$$p"; \
- else :; fi; \
- done; \
- for file in $$list2; do echo $$file; done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pygirepositorydir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(pygirepositorydir)" || exit $$?; \
- done || exit $$?; \
- if test -n "$$dlist"; then \
- $(am__py_compile) --destdir "$(DESTDIR)" \
- --basedir "$(pygirepositorydir)" $$dlist; \
- else :; fi
-
-uninstall-pygirepositoryPYTHON:
- @$(NORMAL_UNINSTALL)
- @list='$(pygirepository_PYTHON)'; test -n "$(pygirepositorydir)" || list=; \
- py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$py_files" || exit 0; \
- dir='$(DESTDIR)$(pygirepositorydir)'; \
- pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \
- pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \
- py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \
- echo "$$py_files_pep3147";\
- pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \
- pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \
- st=0; \
- for files in \
- "$$py_files" \
- "$$pyc_files" \
- "$$pyo_files" \
- "$$pyc_files_pep3147" \
- "$$pyo_files_pep3147" \
- ; do \
- $(am__uninstall_files_from_dir) || st=$$?; \
- done; \
- exit $$st
-tags TAGS:
-
-ctags CTAGS:
-
-cscope cscopelist:
-
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) check-local
-check: check-am
-all-am: Makefile all-local
-installdirs:
- for dir in "$(DESTDIR)$(pygirepositorydir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-am
- -rm -f Makefile
-distclean-am: clean-am distclean-generic
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-pygirepositoryPYTHON
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-pygirepositoryPYTHON
-
-.MAKE: check-am install-am install-strip
-
-.PHONY: all all-am all-local check check-am check-local clean \
- clean-generic clean-libtool cscopelist-am ctags-am distclean \
- distclean-generic distclean-libtool distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-pdf install-pdf-am \
- install-ps install-ps-am install-pygirepositoryPYTHON \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags-am uninstall uninstall-am uninstall-pygirepositoryPYTHON
-
-
-# if we build in a separate tree, we need to symlink the *.py files from the
-# source tree; Python does not accept the extensions and modules in different
-# paths
-build_pylinks:
- for f in $(pygirepository_PYTHON); do \
- [ -e $(builddir)/$$f ] || $(LN_S) $(srcdir)/$$f $(builddir)/$$f; \
- done
-
-all-local: build_pylinks
-check-local: build_pylinks
-
-# 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.
-.NOEXPORT:
diff --git a/gi/repository/__init__.py b/gi/repository/__init__.py
index 5c5552a..640fc8e 100644
--- a/gi/repository/__init__.py
+++ b/gi/repository/__init__.py
@@ -18,8 +18,6 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-from __future__ import absolute_import
-
import sys
from ..importer import DynamicImporter
diff --git a/gi/repository/meson.build b/gi/repository/meson.build
new file mode 100644
index 0000000..fdc136b
--- /dev/null
+++ b/gi/repository/meson.build
@@ -0,0 +1,5 @@
+python_sources = ['__init__.py']
+
+python.install_sources(python_sources,
+ subdir : join_paths('gi', 'repository')
+)
diff --git a/gi/types.py b/gi/types.py
index 7c0f617..9205936 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -20,14 +20,10 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-from __future__ import absolute_import
+import re
-import sys
-import warnings
-
-from . import _gobject
-from ._gobject._gobject import GInterface
-from ._gobject.constants import TYPE_INVALID
+from ._constants import TYPE_INVALID
+from .docstring import generate_doc_string
from ._gi import \
InterfaceInfo, \
@@ -35,15 +31,19 @@ from ._gi import \
StructInfo, \
VFuncInfo, \
register_interface_info, \
- hook_up_vfunc_implementation
+ hook_up_vfunc_implementation, \
+ GInterface
+from . import _gi
+
+StructInfo, GInterface # pyflakes
+from . import _propertyhelper as propertyhelper
+from . import _signalhelper as signalhelper
-StructInfo # pyflakes
-if (3, 0) <= sys.version_info < (3, 3):
- # callable not available for python 3.0 thru 3.2
- def callable(obj):
- return hasattr(obj, '__call__')
+def snake_case(name):
+ s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
+ return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
class MetaClassHelper(object):
@@ -51,6 +51,17 @@ class MetaClassHelper(object):
for method_info in cls.__info__.get_methods():
setattr(cls, method_info.__name__, method_info)
+ def _setup_class_methods(cls):
+ info = cls.__info__
+ class_struct = info.get_class_struct()
+ if class_struct is None:
+ return
+ for method_info in class_struct.get_methods():
+ name = method_info.__name__
+ # Don't mask regular methods or base class methods with TypeClass methods.
+ if not hasattr(cls, name):
+ setattr(cls, name, classmethod(method_info))
+
def _setup_fields(cls):
for field_info in cls.__info__.get_fields():
name = field_info.get_name().replace('-', '_')
@@ -67,6 +78,8 @@ class MetaClassHelper(object):
if not vfunc_name.startswith("do_") or not callable(py_vfunc):
continue
+ skip_ambiguity_check = False
+
# If a method name starts with "do_" assume it is a vfunc, and search
# in the base classes for a method with the same name to override.
# Recursion is necessary as overriden methods in most immediate parent
@@ -78,6 +91,20 @@ class MetaClassHelper(object):
vfunc_info = method
break
+ if not hasattr(base, '__info__') or not hasattr(base.__info__, 'get_vfuncs'):
+ continue
+
+ base_name = snake_case(base.__info__.get_type_name())
+
+ for v in base.__info__.get_vfuncs():
+ if vfunc_name == 'do_%s_%s' % (base_name, v.get_name()):
+ vfunc_info = v
+ skip_ambiguity_check = True
+ break
+
+ if vfunc_info:
+ break
+
# If we did not find a matching method name in the bases, we might
# be overriding an interface virtual method. Since interfaces do not
# provide implementations, there will be no method attribute installed
@@ -88,22 +115,22 @@ class MetaClassHelper(object):
vfunc_info = find_vfunc_info_in_interface(cls.__bases__, vfunc_name[len("do_"):])
if vfunc_info is not None:
- assert vfunc_name == ('do_' + vfunc_info.get_name())
# Check to see if there are vfuncs with the same name in the bases.
# We have no way of specifying which one we are supposed to override.
- ambiguous_base = find_vfunc_conflict_in_bases(vfunc_info, cls.__bases__)
- if ambiguous_base is not None:
- base_info = vfunc_info.get_container()
- raise TypeError('Method %s() on class %s.%s is ambiguous '
- 'with methods in base classes %s.%s and %s.%s' %
- (vfunc_name,
- cls.__info__.get_namespace(),
- cls.__info__.get_name(),
- base_info.get_namespace(),
- base_info.get_name(),
- ambiguous_base.__info__.get_namespace(),
- ambiguous_base.__info__.get_name()
- ))
+ if not skip_ambiguity_check:
+ ambiguous_base = find_vfunc_conflict_in_bases(vfunc_info, cls.__bases__)
+ if ambiguous_base is not None:
+ base_info = vfunc_info.get_container()
+ raise TypeError('Method %s() on class %s.%s is ambiguous '
+ 'with methods in base classes %s.%s and %s.%s' %
+ (vfunc_name,
+ cls.__info__.get_namespace(),
+ cls.__info__.get_name(),
+ base_info.get_namespace(),
+ base_info.get_name(),
+ ambiguous_base.__info__.get_namespace(),
+ ambiguous_base.__info__.get_name()
+ ))
hook_up_vfunc_implementation(vfunc_info, cls.__gtype__,
py_vfunc)
@@ -132,7 +159,7 @@ def find_vfunc_info_in_interface(bases, vfunc_name):
# This can be seen in IntrospectionModule.__getattr__() in module.py.
# We do not need to search regular classes here, only wrapped interfaces.
# We also skip GInterface, because it is not wrapped and has no __info__ attr.
- # Skip bases without __info__ (static _gobject._gobject.GObject)
+ # Skip bases without __info__ (static _gi.GObject)
if base is GInterface or\
not issubclass(base, GInterface) or\
not hasattr(base, '__info__'):
@@ -169,8 +196,32 @@ def find_vfunc_conflict_in_bases(vfunc, bases):
return None
-class GObjectMeta(_gobject.GObjectMeta, MetaClassHelper):
+class _GObjectMetaBase(type):
+ """Metaclass for automatically registering GObject classes."""
+ def __init__(cls, name, bases, dict_):
+ type.__init__(cls, name, bases, dict_)
+ propertyhelper.install_properties(cls)
+ signalhelper.install_signals(cls)
+ cls._type_register(cls.__dict__)
+
+ def _type_register(cls, namespace):
+ # don't register the class if already registered
+ if '__gtype__' in namespace:
+ return
+
+ # Do not register a new GType for the overrides, as this would sort of
+ # defeat the purpose of overrides...
+ if cls.__module__.startswith('gi.overrides.'):
+ return
+ _gi.type_register(cls, namespace.get('__gtype_name__'))
+
+
+_gi._install_metaclass(_GObjectMetaBase)
+
+
+class GObjectMeta(_GObjectMetaBase, MetaClassHelper):
+ """Meta class used for GI GObject based types."""
def __init__(cls, name, bases, dict_):
super(GObjectMeta, cls).__init__(name, bases, dict_)
is_gi_defined = False
@@ -184,6 +235,8 @@ class GObjectMeta(_gobject.GObjectMeta, MetaClassHelper):
if is_python_defined:
cls._setup_vfuncs()
elif is_gi_defined:
+ if isinstance(cls.__info__, ObjectInfo):
+ cls._setup_class_methods()
cls._setup_methods()
cls._setup_constants()
cls._setup_native_vfuncs()
@@ -196,6 +249,22 @@ class GObjectMeta(_gobject.GObjectMeta, MetaClassHelper):
def mro(cls):
return mro(cls)
+ @property
+ def __doc__(cls):
+ """Meta class property which shows up on any class using this meta-class."""
+ if cls == GObjectMeta:
+ return ''
+
+ doc = cls.__dict__.get('__doc__', None)
+ if doc is not None:
+ return doc
+
+ # For repository classes, dynamically generate a doc string if it wasn't overridden.
+ if cls.__module__.startswith(('gi.repository.', 'gi.overrides')):
+ return generate_doc_string(cls.__info__)
+
+ return None
+
def mro(C):
"""Compute the class precedence list (mro) according to C3, with GObject
@@ -218,19 +287,7 @@ def mro(C):
# in __mro__ at each point. Therefore at this point we know that
# we already have our base class MRO's available to us, there is
# no need for us to (re)calculate them.
- if hasattr(base, '__mro__'):
- bases_of_subclasses += [list(base.__mro__)]
- else:
- warnings.warn('Mixin class %s is an old style class, please '
- 'update this to derive from "object".' % base,
- RuntimeWarning)
- # For old-style classes (Python2 only), the MRO is not
- # easily accessible. As we do need it here, we calculate
- # it via recursion, according to the C3 algorithm. Using C3
- # for old style classes deviates from Python's own behaviour,
- # but visible effects here would be a corner case triggered by
- # questionable design.
- bases_of_subclasses += [mro(base)]
+ bases_of_subclasses += [list(base.__mro__)]
bases_of_subclasses += [list(C.__bases__)]
while bases_of_subclasses:
@@ -257,7 +314,12 @@ def mro(C):
return bases
+def nothing(*args, **kwargs):
+ pass
+
+
class StructMeta(type, MetaClassHelper):
+ """Meta class used for GI Struct based types."""
def __init__(cls, name, bases, dict_):
super(StructMeta, cls).__init__(name, bases, dict_)
@@ -273,6 +335,16 @@ class StructMeta(type, MetaClassHelper):
for method_info in cls.__info__.get_methods():
if method_info.is_constructor() and \
method_info.__name__ == 'new' and \
- not method_info.get_arguments():
+ (not method_info.get_arguments() or
+ cls.__info__.get_size() == 0):
cls.__new__ = staticmethod(method_info)
+ # Boxed will raise an exception
+ # if arguments are given to __init__
+ cls.__init__ = nothing
break
+
+ @property
+ def __doc__(cls):
+ if cls == StructMeta:
+ return ''
+ return generate_doc_string(cls.__info__)