From 3a2fe8f548bb171295a989bf143f8c7a75715e6e Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Wed, 12 Jul 2017 08:46:58 +0900 Subject: [PATCH] Imported Upstream version 3.3.4 Change-Id: Iab0849da42c652542cc6997601d489efef86102f Signed-off-by: DongHun Kwak --- ChangeLog | 310 ++++++++++++++++++++++++++++++++++++++++++++ NEWS | 31 +++++ PKG-INFO | 4 +- config.sub | 11 +- configure | 30 ++--- configure.ac | 2 +- gi/_glib/glibmodule.c | 10 +- gi/_gobject/gobjectmodule.c | 17 ++- gi/_gobject/pygobject.c | 53 +++++--- gi/module.py | 29 ++++- gi/overrides/GLib.py | 6 +- gi/overrides/Gtk.py | 8 +- gi/pygi-argument.c | 156 +++++++++++++++------- gi/pygi-argument.h | 4 +- gi/pygi-cache.c | 2 + gi/pygi-closure.c | 11 ++ gi/pygi-info.c | 27 +++- gi/pygi-marshal-from-py.c | 9 +- gi/pygi-property.c | 1 + gi/pygi-signal-closure.c | 14 +- m4/python.m4 | 3 +- tests/test_gi.py | 63 +++++++++ tests/test_overrides.py | 9 ++ 23 files changed, 699 insertions(+), 111 deletions(-) diff --git a/ChangeLog b/ChangeLog index fed6790..7fd69d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,313 @@ +commit 126842b7227fcc1381dc158acdc5a96d0a465515 +Author: Martin Pitt +Date: Mon Jul 16 17:33:08 2012 +0200 + + release 3.3.4 + + NEWS | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +commit 079b73b3eb9083bd53e06d095f9dccc02acf2a6e +Author: Martin Pitt +Date: Mon Jul 16 17:29:22 2012 +0200 + + test_gi: Fix for Python 2 + + tests/test_gi.py | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +commit 30935fe31bfe201bbfdb7734f09fdd2bbaf80e08 +Author: Martin Pitt +Date: Mon Jul 16 16:35:33 2012 +0200 + + pygi-convert.sh: Drop bogus filter_new() conversion + + my_tree_model.filter_new() is still a method on GtkTreeModel, not a + constructor, so do not try to convert it to a constructor call. + + https://bugzilla.gnome.org/show_bug.cgi?id=679999 + + pygi-convert.sh | 1 - + 1 file changed, 1 deletion(-) + +commit c0607d970fc59528ca27d518282cf2871b92e909 +Author: Martin Pitt +Date: Mon Jul 16 16:00:40 2012 +0200 + + Fix help() for GI modules + + Derive DynamicModule from types.ModuleType, so that the inspect + modules' + ismodule() actually succeeds on those and generates useful help on + a GI + repository module. + + https://bugzilla.gnome.org/show_bug.cgi?id=679804 + + gi/module.py | 3 ++- + tests/test_gi.py | 15 +++++++++++++++ + 2 files changed, 17 insertions(+), 1 deletion(-) + +commit 3235f1a397c334de5a7570f5ceed4da709fe1714 +Author: Martin Pitt +Date: Mon Jul 16 15:53:31 2012 +0200 + + Skip gi.CallbackInfo objects from a module's dir() + + Skip gi.CallbackInfo items from IntrospectionModule's __dir__(), + as we do not + implement __getattr__ for those. + + Add a test case that dir() works on GI modules, contain expected + identifiers, + and that all identifiers in dir() can actually be retrieved. + + Prerequisite for https://bugzilla.gnome.org/show_bug.cgi?id=679804 + + gi/module.py | 7 +++++-- + tests/test_gi.py | 14 ++++++++++++++ + 2 files changed, 19 insertions(+), 2 deletions(-) + +commit f6cc039e014448a553d626aac4020ee69717edab +Author: Martin Pitt +Date: Mon Jul 16 15:38:05 2012 +0200 + + Fix __path__ module attribute + + get_typelib_path() returns bytes, not strings, so in Python 3 we + need to decode + it to get a proper __path__ attribute. + + gi/module.py | 17 +++++++++++++++++ + tests/test_gi.py | 10 ++++++++++ + 2 files changed, 27 insertions(+) + +commit 858048f7cec78129aa914e2341ab80aac0e95cc5 +Author: Joe R. Nassimian +Date: Mon Jul 16 15:02:10 2012 +0200 + + pygi-convert.sh: Fix some child → getChild() false positives + + https://bugzilla.gnome.org/show_bug.cgi?id=680004 + + pygi-convert.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit a31fabdc12f1da301c8df0af319ca3f4181671ee +Author: Mikkel Kamstrup Erlandsen +Date: Thu Jul 12 09:19:42 2012 +0200 + + Fix array handling for interfaces, properties, and signals + + Fix lots of corner cases where arrays are not handled properly. + _pygi_argument_to_object() now has the documented expectation of + getting arrays + packed in GArrays. This was implicit before and not correctly done + on most call + sites. + + The helper _pygi_argument_to_array() has been improved to work on + any kind of + array. Fix all call sites of _pygi_argument_to_object() to do the + array conversion appropriately before calling + _pygi_argument_to_object(). + + Adds a test case that implements a GInterface with a method that + takes an array + of variants as input. + + https://bugzilla.gnome.org/show_bug.cgi?id=667244 + + gi/pygi-argument.c | 156 + ++++++++++++++++++++++++++++++++-------------- + gi/pygi-argument.h | 4 +- + gi/pygi-closure.c | 11 ++++ + gi/pygi-info.c | 20 ++++-- + gi/pygi-property.c | 1 + + gi/pygi-signal-closure.c | 14 ++++- + tests/test_gi.py | 18 ++++++ + 7 files changed, 167 insertions(+), 57 deletions(-) + +commit bb80d124269ee2389c04d03a478475868fd9ff7b +Author: Manuel Quiñones +Date: Wed Jul 11 22:05:41 2012 -0300 + + Add conversion of the Gdk.PropMode constants to pygi-convert.sh script + + Signed-off-by: Manuel Quiñones + + https://bugzilla.gnome.org/show_bug.cgi?id=679775 + + pygi-convert.sh | 3 +++ + 1 file changed, 3 insertions(+) + +commit e3a63eefa5fb2abeabd210790e12642e577363c8 +Author: Manuel Quiñones +Date: Wed Jul 11 13:18:16 2012 -0300 + + Add the same rules for pack_start to convert pack_end + + Signed-off-by: Manuel Quiñones + + https://bugzilla.gnome.org/show_bug.cgi?id=679760 + + pygi-convert.sh | 5 +++++ + 1 file changed, 5 insertions(+) + +commit b4bef457c2d0ca6899e06a021f1f06252a37e326 +Author: Dave Malcolm +Date: Wed Jul 11 08:21:27 2012 +0200 + + Add error-checking for the case where _arg_cache_new() fails + + This can happen when a typelib and its underlying library are + out-of-sync. This + converts the segfault into a more helpful traceback. + + https://bugzilla.gnome.org/show_bug.cgi?id=678914 + + gi/pygi-cache.c | 2 ++ + 1 file changed, 2 insertions(+) + +commit 41287d8a439c656e4ac60361fddec643c713234c +Author: Manuel Quiñones +Date: Wed Jul 11 11:13:38 2012 -0300 + + Add conversion of the Gdk.NotifyType constants to pygi-convert.sh + script + + Signed-off-by: Manuel Quiñones + + https://bugzilla.gnome.org/show_bug.cgi?id=679754 + + pygi-convert.sh | 6 ++++++ + 1 file changed, 6 insertions(+) + +commit 5403149b900d1b73cbc78767dc43be2eb344c836 +Author: Simon Feltman +Date: Tue Jul 10 19:07:32 2012 -0700 + + Fix PyObject_Repr and PyObject_Str reference leaks + + Fix all calls to PyObject_Repr() and PyObject_Str() to be properly + DECREF'd. + + https://bugzilla.gnome.org/show_bug.cgi?id=675857 + + Signed-off-by: Martin Pitt + + gi/_glib/glibmodule.c | 10 ++++++-- + gi/_gobject/gobjectmodule.c | 17 ++++++++++---- + gi/_gobject/pygobject.c | 53 + +++++++++++++++++++++++++++++-------------- + gi/pygi-marshal-from-py.c | 9 +++++--- + 4 files changed, 62 insertions(+), 27 deletions(-) + +commit 0ddfecf3bf0a5d7893cd02cff41503d810ef6ce8 +Author: Martin Pitt +Date: Wed Jul 4 08:46:30 2012 +0200 + + [API add] Gtk overrides: Add TreePath.__len__() + + Use the path depth as length of a Gtk.TreePath object. + + https://bugzilla.gnome.org/show_bug.cgi?id=679199 + + gi/overrides/Gtk.py | 3 +++ + tests/test_overrides.py | 4 ++++ + 2 files changed, 7 insertions(+) + +commit e1e849d1a9af77c29ee35971db8d439bac60d573 +Author: Martin Pitt +Date: Wed Jul 4 08:35:16 2012 +0200 + + GLib.Variant: Fix repr(), add proper str() + + Fix the GLib.Variant override's repr() after commit 16280d6985. Also + add a + proper __str__() method, and tests for both. + + Thanks to Rul Matos for spotting this! + + https://bugzilla.gnome.org/show_bug.cgi?id=679336 + + gi/overrides/GLib.py | 6 +++++- + tests/test_overrides.py | 5 +++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +commit af20d7c929b9c1888454b52932a308d346e1c12b +Author: Martin Pitt +Date: Thu Jun 28 06:51:22 2012 +0200 + + m4/python.m4: Update Python version list + + Thanks to Dieter Verfaillie for pointing this out. + + m4/python.m4 | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit a96a26234e2aaa157837d26094864e3ad9b63edf +Author: Micah Carrick +Date: Mon Jun 25 09:05:59 2012 -0700 + + Remove "label" property from Gtk.MenuItem if it is not set + + The Gtk.MenuItem will not render as a separator if the "label" or + "user-underline" properties have been accessed. The constructor + for Gtk.MenuItem override should not pass the "label" property + as an argument if it is None since that will still result in an + empty label widget which breaks Gtk.SeparatorMenuItem. + + https://bugzilla.gnome.org/show_bug.cgi?id=670575 + + Signed-off-by: Martin Pitt + + gi/overrides/Gtk.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +commit afa12faf339efb4f7780168e884ecf49b630644a +Author: Martin Pitt +Date: Mon Jun 25 16:36:31 2012 +0200 + + configure.ac: Post-release bump to 3.3.4. + + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 198066effc0ca44ccb897e9f0738ab627e8b3275 +Author: Martin Pitt +Date: Mon Jun 25 16:35:49 2012 +0200 + + release 3.3.3.1 + + NEWS | 3 +++ + configure.ac | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +commit cb70ae0aa52ab7624b2b8c30297d8a52a7db7f44 +Author: Martin Pitt +Date: Mon Jun 25 16:32:45 2012 +0200 + + Do not escape enum and flag names that are Python keywords + + These are translated to upper case, and thus can never be + keywords. This broke + existing API such as Gtk.ShadowType.IN. + + gi/module.py | 2 +- + gi/pygi-info.c | 7 +++++++ + tests/test_gi.py | 3 +++ + 3 files changed, 11 insertions(+), 1 deletion(-) + +commit f2524a982b0b8ba7cdbb77003372416af0b7a978 +Author: Martin Pitt +Date: Mon Jun 25 15:39:50 2012 +0200 + + configure.ac: Post-release version bump to 3.3.4 + + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + commit fe56faa346c8e8f9fd5915602424778d458a776d Author: Martin Pitt Date: Mon Jun 25 15:36:37 2012 +0200 diff --git a/NEWS b/NEWS index 03736e6..cbcb952 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,34 @@ +3.3.4 16-Jul-2012 + - pygi-convert.sh: Drop bogus filter_new() conversion (Martin Pitt) + (#679999) + - Fix help() for GI modules (Martin Pitt) (#679804) + - Skip gi.CallbackInfo objects from a module's dir() (Martin Pitt) + (#679804) + - Fix __path__ module attribute (Martin Pitt) + - pygi-convert.sh: Fix some child → getChild() false positives + (Joe R. Nassimian) (#680004) + - Fix array handling for interfaces, properties, and signals + (Mikkel Kamstrup Erlandsen) (#667244) + - Add conversion of the Gdk.PropMode constants to pygi-convert.sh + script (Manuel Quiñones) (#679775) + - Add the same rules for pack_start to convert pack_end (Manuel + Quiñones) (#679760) + - Add error-checking for the case where _arg_cache_new() fails + (Dave Malcolm) (#678914) + - Add conversion of the Gdk.NotifyType constants to pygi-convert.sh + script (Manuel Quiñones) (#679754) + - Fix PyObject_Repr and PyObject_Str reference leaks (Simon Feltman) + (#675857) + - [API add] Gtk overrides: Add TreePath.__len__() (Martin Pitt) + (#679199) + - GLib.Variant: Fix repr(), add proper str() (Martin Pitt) (#679336) + - m4/python.m4: Update Python version list (Martin Pitt) + - Remove "label" property from Gtk.MenuItem if it is not set + (Micah Carrick) (#670575) + +3.3.3.1 25-Jun-2012 + - Do not escape enum and flag names that are Python keywords (Martin Pitt) + 3.3.3 25-Jun-2012 - Remove obsolete release-tag make target (Martin Pitt) - Do not do any python calls when GObjects are destroyed after the diff --git a/PKG-INFO b/PKG-INFO index 657dfd9..3c05ff2 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: PyGObject -Version: 3.3.3 +Version: 3.3.4 Summary: Python bindings for GObject Home-page: http://www.pygtk.org/ Author: James Henstridge @@ -8,7 +8,7 @@ Author-email: james@daa.com.au Maintainer: Johan Dahlin Maintainer-email: johan@gnome.org License: GNU LGPL -Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.3/pygobject-3.3.3.tar.gz +Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.3/pygobject-3.3.4.tar.gz Description: Python bindings for GLib and GObject Platform: POSIX, Windows Classifier: Development Status :: 5 - Production/Stable diff --git a/config.sub b/config.sub index c894da4..6205f84 100755 --- a/config.sub +++ b/config.sub @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. -timestamp='2012-02-10' +timestamp='2012-04-18' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -225,6 +225,12 @@ case $os in -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; -lynx*) os=-lynxos ;; @@ -1537,6 +1543,9 @@ case $basic_machine in c4x-* | tic4x-*) os=-coff ;; + hexagon-*) + os=-elf + ;; tic54x-*) os=-coff ;; diff --git a/configure b/configure index 66089c2..5586b30 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for pygobject 3.3.3. +# Generated by GNU Autoconf 2.69 for pygobject 3.3.4. # # Report bugs to . # @@ -591,8 +591,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pygobject' PACKAGE_TARNAME='pygobject' -PACKAGE_VERSION='3.3.3' -PACKAGE_STRING='pygobject 3.3.3' +PACKAGE_VERSION='3.3.4' +PACKAGE_STRING='pygobject 3.3.4' PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject' PACKAGE_URL='' @@ -1385,7 +1385,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pygobject 3.3.3 to adapt to many kinds of systems. +\`configure' configures pygobject 3.3.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1455,7 +1455,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pygobject 3.3.3:";; + short | recursive ) echo "Configuration of pygobject 3.3.4:";; esac cat <<\_ACEOF @@ -1584,7 +1584,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pygobject configure 3.3.3 +pygobject configure 3.3.4 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1862,7 +1862,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pygobject $as_me 3.3.3, which was +It was created by pygobject $as_me 3.3.4, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2226,9 +2226,9 @@ $as_echo "#define PYGOBJECT_MINOR_VERSION 3" >>confdefs.h PYGOBJECT_MINOR_VERSION=3 -$as_echo "#define PYGOBJECT_MICRO_VERSION 3" >>confdefs.h +$as_echo "#define PYGOBJECT_MICRO_VERSION 4" >>confdefs.h -PYGOBJECT_MICRO_VERSION=3 +PYGOBJECT_MICRO_VERSION=4 ac_config_headers="$ac_config_headers config.h" @@ -2739,7 +2739,7 @@ fi # Define the identity of the package. PACKAGE='pygobject' - VERSION='3.3.3' + VERSION='3.3.4' cat >>confdefs.h <<_ACEOF @@ -12130,7 +12130,7 @@ Usage: $0 [OPTIONS] Report bugs to ." lt_cl_version="\ -pygobject config.lt 3.3.3 +pygobject config.lt 3.3.4 configured by $0, generated by GNU Autoconf 2.69. Copyright (C) 2011 Free Software Foundation, Inc. @@ -14655,7 +14655,7 @@ if ${am_cv_pathless_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else - for am_cv_pathless_PYTHON in python python2 python3 python3.0 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do + for am_cv_pathless_PYTHON in python python2 python2.7 python2.6 python3 python3.2 python3.1 none; do test "$am_cv_pathless_PYTHON" = none && break prog="import sys # split strings by '.' and convert to numeric. Append some zeros @@ -14856,7 +14856,7 @@ fi # Find any Python interpreter. if test -z "$PYTHON"; then - for ac_prog in python python2 python3 python3.0 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 + for ac_prog in python python2 python2.7 python2.6 python3 python3.2 python3.1 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -16919,7 +16919,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pygobject $as_me 3.3.3, which was +This file was extended by pygobject $as_me 3.3.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16985,7 +16985,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -pygobject config.status 3.3.3 +pygobject config.status 3.3.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 6abe714..2bae0c7 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ m4_define(python3_min_ver, 3.1) dnl the pygobject version number m4_define(pygobject_major_version, 3) m4_define(pygobject_minor_version, 3) -m4_define(pygobject_micro_version, 3) +m4_define(pygobject_micro_version, 4) m4_define(pygobject_version, pygobject_major_version.pygobject_minor_version.pygobject_micro_version) dnl versions of packages we require ... diff --git a/gi/_glib/glibmodule.c b/gi/_glib/glibmodule.c index 2db764b..11b97f5 100644 --- a/gi/_glib/glibmodule.c +++ b/gi/_glib/glibmodule.c @@ -547,10 +547,13 @@ pyglib_get_application_name(PyObject *self) static PyObject* pyglib_set_application_name(PyObject *self, PyObject *arg) { + PyObject *repr = NULL; if (!PYGLIB_PyUnicode_Check(arg)) { + repr = PyObject_Repr(arg); PyErr_Format(PyExc_TypeError, "first argument must be a string, not '%s'", - PYGLIB_PyUnicode_AsString(PyObject_Repr(arg))); + PYGLIB_PyUnicode_AsString(repr)); + Py_DECREF(repr); return NULL; } g_set_application_name(PYGLIB_PyUnicode_AsString(arg)); @@ -574,10 +577,13 @@ pyglib_get_prgname(PyObject *self) static PyObject* pyglib_set_prgname(PyObject *self, PyObject *arg) { + PyObject *repr = NULL; if (!PYGLIB_PyUnicode_Check(arg)) { + repr = PyObject_Repr(arg); PyErr_Format(PyExc_TypeError, "first argument must be a string, not '%s'", - PYGLIB_PyUnicode_AsString(PyObject_Repr(arg))); + PYGLIB_PyUnicode_AsString(repr)); + Py_DECREF(repr); return NULL; } g_set_prgname(PYGLIB_PyUnicode_AsString(arg)); diff --git a/gi/_gobject/gobjectmodule.c b/gi/_gobject/gobjectmodule.c index 0d75b7e..526a8be 100644 --- a/gi/_gobject/gobjectmodule.c +++ b/gi/_gobject/gobjectmodule.c @@ -120,6 +120,7 @@ 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; " @@ -131,9 +132,11 @@ pyg_type_from_name (PyObject *self, PyObject *args) type = _pyg_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(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), name); + Py_DECREF(repr); return NULL; } @@ -1881,7 +1884,7 @@ out: static PyObject * pyg_add_emission_hook(PyGObject *self, PyObject *args) { - PyObject *first, *callback, *extra_args, *data; + PyObject *first, *callback, *extra_args, *data, *repr; gchar *name; gulong hook_id; guint sigid; @@ -1913,9 +1916,11 @@ pyg_add_emission_hook(PyGObject *self, PyObject *args) } 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(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), name); + Py_DECREF(repr); return NULL; } extra_args = PySequence_GetSlice(args, 3, len); @@ -1937,7 +1942,7 @@ pyg_add_emission_hook(PyGObject *self, PyObject *args) static PyObject * pyg_remove_emission_hook(PyGObject *self, PyObject *args) { - PyObject *pygtype; + PyObject *pygtype, *repr; char *name; guint signal_id; gulong hook_id; @@ -1952,9 +1957,11 @@ pyg_remove_emission_hook(PyGObject *self, PyObject *args) } if (!g_signal_parse_name(name, gtype, &signal_id, NULL, TRUE)) { + repr = PyObject_Repr((PyObject*)self); PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), name); + Py_DECREF(repr); return NULL; } diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c index 355c6d0..1b98ea0 100644 --- a/gi/_gobject/pygobject.c +++ b/gi/_gobject/pygobject.c @@ -1745,7 +1745,7 @@ pygobject_set_data(PyGObject *self, PyObject *args) static PyObject * pygobject_connect(PyGObject *self, PyObject *args) { - PyObject *first, *callback, *extra_args; + PyObject *first, *callback, *extra_args, *repr = NULL; gchar *name; guint sigid, len; gulong handlerid; @@ -1773,9 +1773,11 @@ pygobject_connect(PyGObject *self, PyObject *args) if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj), &sigid, &detail, TRUE)) { + repr = PyObject_Repr((PyObject*)self); PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), name); + Py_DECREF(repr); return NULL; } extra_args = PySequence_GetSlice(args, 2, len); @@ -1796,7 +1798,7 @@ pygobject_connect(PyGObject *self, PyObject *args) static PyObject * pygobject_connect_after(PyGObject *self, PyObject *args) { - PyObject *first, *callback, *extra_args; + PyObject *first, *callback, *extra_args, *repr = NULL; gchar *name; guint sigid; gulong handlerid; @@ -1826,9 +1828,11 @@ pygobject_connect_after(PyGObject *self, PyObject *args) if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj), &sigid, &detail, TRUE)) { + repr = PyObject_Repr((PyObject*)self); PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), name); + Py_DECREF(repr); return NULL; } extra_args = PySequence_GetSlice(args, 2, len); @@ -1849,7 +1853,7 @@ pygobject_connect_after(PyGObject *self, PyObject *args) static PyObject * pygobject_connect_object(PyGObject *self, PyObject *args) { - PyObject *first, *callback, *extra_args, *object; + PyObject *first, *callback, *extra_args, *object, *repr = NULL; gchar *name; guint sigid; gulong handlerid; @@ -1879,9 +1883,11 @@ pygobject_connect_object(PyGObject *self, PyObject *args) if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj), &sigid, &detail, TRUE)) { + repr = PyObject_Repr((PyObject*)self); PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), name); + Py_DECREF(repr); return NULL; } extra_args = PySequence_GetSlice(args, 3, len); @@ -1902,7 +1908,7 @@ pygobject_connect_object(PyGObject *self, PyObject *args) static PyObject * pygobject_connect_object_after(PyGObject *self, PyObject *args) { - PyObject *first, *callback, *extra_args, *object; + PyObject *first, *callback, *extra_args, *object, *repr = NULL; gchar *name; guint sigid; gulong handlerid; @@ -1932,9 +1938,11 @@ pygobject_connect_object_after(PyGObject *self, PyObject *args) if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj), &sigid, &detail, TRUE)) { + repr = PyObject_Repr((PyObject*)self); PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), name); + Py_DECREF(repr); return NULL; } extra_args = PySequence_GetSlice(args, 3, len); @@ -2013,7 +2021,7 @@ pygobject_emit(PyGObject *self, PyObject *args) guint signal_id, i; Py_ssize_t len; GQuark detail; - PyObject *first, *py_ret; + PyObject *first, *py_ret, *repr = NULL; gchar *name; GSignalQuery query; GValue *params, ret = { 0, }; @@ -2034,9 +2042,11 @@ pygobject_emit(PyGObject *self, PyObject *args) if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj), &signal_id, &detail, TRUE)) { + repr = PyObject_Repr((PyObject*)self); PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), name); + Py_DECREF(repr); return NULL; } g_signal_query(signal_id, &query); @@ -2102,6 +2112,7 @@ pygobject_stop_emission(PyGObject *self, PyObject *args) gchar *signal; guint signal_id; GQuark detail; + PyObject *repr = NULL; if (!PyArg_ParseTuple(args, "s:GObject.stop_emission", &signal)) return NULL; @@ -2110,9 +2121,11 @@ pygobject_stop_emission(PyGObject *self, PyObject *args) if (!g_signal_parse_name(signal, G_OBJECT_TYPE(self->obj), &signal_id, &detail, TRUE)) { + repr = PyObject_Repr((PyObject*)self); PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)self)), + PYGLIB_PyUnicode_AsString(repr), signal); + Py_DECREF(repr); return NULL; } g_signal_stop_emission(self->obj, signal_id, detail); @@ -2242,7 +2255,7 @@ pygobject_deepcopy(PyGObject *self, PyObject *args) static PyObject * pygobject_disconnect_by_func(PyGObject *self, PyObject *args) { - PyObject *pyfunc = NULL; + PyObject *pyfunc = NULL, *repr = NULL; GClosure *closure = NULL; guint retval; @@ -2258,8 +2271,10 @@ pygobject_disconnect_by_func(PyGObject *self, PyObject *args) closure = gclosure_from_pyfunc(self, pyfunc); if (!closure) { + repr = PyObject_Repr((PyObject*)pyfunc); PyErr_Format(PyExc_TypeError, "nothing connected to %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc))); + PYGLIB_PyUnicode_AsString(repr)); + Py_DECREF(repr); return NULL; } @@ -2274,7 +2289,7 @@ pygobject_disconnect_by_func(PyGObject *self, PyObject *args) static PyObject * pygobject_handler_block_by_func(PyGObject *self, PyObject *args) { - PyObject *pyfunc = NULL; + PyObject *pyfunc = NULL, *repr = NULL; GClosure *closure = NULL; guint retval; @@ -2290,8 +2305,10 @@ pygobject_handler_block_by_func(PyGObject *self, PyObject *args) closure = gclosure_from_pyfunc(self, pyfunc); if (!closure) { + repr = PyObject_Repr((PyObject*)pyfunc); PyErr_Format(PyExc_TypeError, "nothing connected to %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc))); + PYGLIB_PyUnicode_AsString(repr)); + Py_DECREF(repr); return NULL; } @@ -2306,7 +2323,7 @@ pygobject_handler_block_by_func(PyGObject *self, PyObject *args) static PyObject * pygobject_handler_unblock_by_func(PyGObject *self, PyObject *args) { - PyObject *pyfunc = NULL; + PyObject *pyfunc = NULL, *repr = NULL; GClosure *closure = NULL; guint retval; @@ -2322,8 +2339,10 @@ pygobject_handler_unblock_by_func(PyGObject *self, PyObject *args) closure = gclosure_from_pyfunc(self, pyfunc); if (!closure) { + repr = PyObject_Repr((PyObject*)pyfunc); PyErr_Format(PyExc_TypeError, "nothing connected to %s", - PYGLIB_PyUnicode_AsString(PyObject_Repr((PyObject*)pyfunc))); + PYGLIB_PyUnicode_AsString(repr)); + Py_DECREF(repr); return NULL; } diff --git a/gi/module.py b/gi/module.py index 8cd80ef..2d02c9a 100644 --- a/gi/module.py +++ b/gi/module.py @@ -22,6 +22,11 @@ from __future__ import absolute_import +import sys +import types + +_have_py3 = (sys.version_info.major >= 3) + from . import _glib, _gobject try: maketrans = ''.maketrans @@ -96,6 +101,9 @@ class IntrospectionModule(object): repository.require(self._namespace, self._version) 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') if self._version is None: self._version = repository.get_version(self._namespace) @@ -134,7 +142,7 @@ class IntrospectionModule(object): 'abcdefgjhijklmnopqrstuvwxyz', 'ABCDEFGJHIJKLMNOPQRSTUVWXYZ') for value_info in info.get_values(): - value_name = value_info.get_name().translate(ascii_upper_trans) + value_name = value_info.get_name_unescaped().translate(ascii_upper_trans) setattr(wrapper, value_name, wrapper(value_info.get_value())) if g_type != _gobject.TYPE_NONE: @@ -200,6 +208,9 @@ 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 "" % (self._namespace, path) def __dir__(self): @@ -208,14 +219,17 @@ class IntrospectionModule(object): result.update(self.__dict__.keys()) # update *set* because some repository attributes have already been - # wrapped by __getattr__() and included in self.__dict__ + # wrapped by __getattr__() and included in self.__dict__; but skip + # Callback types, as these are not real objects which we can actually + # get namespace_infos = repository.get_infos(self._namespace) - result.update(info.get_name() for info in namespace_infos) + result.update(info.get_name() for info in namespace_infos if + not isinstance(info, CallbackInfo)) return list(result) -class DynamicModule(object): +class DynamicModule(types.ModuleType): def __init__(self, namespace): self._namespace = namespace self._introspection_module = None @@ -230,6 +244,9 @@ class DynamicModule(object): overrides_modules = __import__('gi.overrides', fromlist=[self._namespace]) self._overrides_module = getattr(overrides_modules, self._namespace, 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: @@ -260,6 +277,10 @@ class DynamicModule(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 "<%s.%s %r from %r>" % (self.__class__.__module__, self.__class__.__name__, self._namespace, diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py index 1d15aff..c41f523 100644 --- a/gi/overrides/GLib.py +++ b/gi/overrides/GLib.py @@ -169,13 +169,17 @@ class Variant(GLib.Variant): (v, rest_format, _) = creator._create(format_string, [value]) if rest_format: raise TypeError('invalid remaining format string: "%s"' % rest_format) + v.format_string = format_string return v def __del__(self): self.unref() + def __str__(self): + return self.print_(True) + def __repr__(self): - return '' % getattr(self, 'print')(True) + return "GLib.Variant('%s', %s)" % (self.format_string, self.print_(True)) def __eq__(self, other): try: diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py index ff4de24..49c2747 100644 --- a/gi/overrides/Gtk.py +++ b/gi/overrides/Gtk.py @@ -334,7 +334,10 @@ __all__.append('SizeGroup') class MenuItem(Gtk.MenuItem): def __init__(self, label=None, **kwds): - super(MenuItem, self).__init__(label=label, **kwds) + if label: + super(MenuItem, self).__init__(label=label, **kwds) + else: + super(MenuItem, self).__init__(**kwds) MenuItem = override(MenuItem) __all__.append('MenuItem') @@ -1226,6 +1229,9 @@ class TreePath(Gtk.TreePath): def __iter__(self): return (int(part) for part in str(self).split(':')) + def __len__(self): + return self.get_depth() + TreePath = override(TreePath) __all__.append('TreePath') diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index fb798e1..b73973e 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -653,50 +653,105 @@ check_number_release: return retval; } +/** + * _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 + * @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 + * + * Make sure an array type argument is wrapped in a GArray. + * + * Note: This method can *not* be folded into _pygi_argument_to_object() because + * arrays are special in the sense that they might require access to @args in + * order to get the length. + * + * Returns: A GArray wrapping @arg. If @out_free_array has been set to TRUE then + * free the array with g_array_free() without freeing the data members. + * Otherwise don't free the array. + */ GArray * _pygi_argument_to_array (GIArgument *arg, GIArgument *args[], - GITypeInfo *type_info, - gboolean is_method) + GITypeInfo *type_info, + gboolean *out_free_array) { GITypeInfo *item_type_info; gboolean is_zero_terminated; gsize item_size; gssize length; GArray *g_array; + + g_return_val_if_fail (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY, NULL); if (arg->v_pointer == NULL) { return NULL; } + + switch (g_type_info_get_array_type (type_info)) { + case GI_ARRAY_TYPE_C: + is_zero_terminated = g_type_info_is_zero_terminated (type_info); + item_type_info = g_type_info_get_param_type (type_info, 0); - is_zero_terminated = g_type_info_is_zero_terminated (type_info); - item_type_info = g_type_info_get_param_type (type_info, 0); - - item_size = _pygi_g_type_info_size (item_type_info); + item_size = _pygi_g_type_info_size (item_type_info); - g_base_info_unref ( (GIBaseInfo *) item_type_info); + g_base_info_unref ( (GIBaseInfo *) item_type_info); - if (is_zero_terminated) { - length = g_strv_length (arg->v_pointer); - } else { - length = g_type_info_get_array_fixed_size (type_info); - if (length < 0) { - gint length_arg_pos; + if (is_zero_terminated) { + length = g_strv_length (arg->v_pointer); + } else { + length = g_type_info_get_array_fixed_size (type_info); + if (length < 0) { + if (G_UNLIKELY (args == NULL)) { + g_critical ("Unable to determine array length for %p", + arg->v_pointer); + g_array = g_array_new (is_zero_terminated, FALSE, item_size); + *out_free_array = TRUE; + return g_array; + } + gint length_arg_pos; - length_arg_pos = g_type_info_get_array_length (type_info); - g_assert (length_arg_pos >= 0); + length_arg_pos = g_type_info_get_array_length (type_info); + g_assert (length_arg_pos >= 0); - /* FIXME: Take into account the type of the argument. */ - length = args[length_arg_pos]->v_int; - } - } + /* FIXME: Take into account the type of the length argument */ + length = args[length_arg_pos]->v_int; + } + } - g_assert (length >= 0); + g_assert (length >= 0); - g_array = g_array_new (is_zero_terminated, FALSE, item_size); + g_array = g_array_new (is_zero_terminated, FALSE, item_size); - g_array->data = arg->v_pointer; - g_array->len = length; + g_array->data = arg->v_pointer; + g_array->len = length; + *out_free_array = TRUE; + break; + case GI_ARRAY_TYPE_ARRAY: + case GI_ARRAY_TYPE_BYTE_ARRAY: + /* Note: GByteArray is really just a GArray */ + g_array = arg->v_pointer; + *out_free_array = FALSE; + break; + case GI_ARRAY_TYPE_PTR_ARRAY: + { + GPtrArray *ptr_array = (GPtrArray*) arg->v_pointer; + g_array = g_array_sized_new (FALSE, FALSE, + sizeof(gpointer), + ptr_array->len); + g_array->data = (char*) ptr_array->pdata; + g_array->len = ptr_array->len; + *out_free_array = TRUE; + break; + } + default: + g_critical ("Unexpected array type %u", + g_type_info_get_array_type (type_info)); + g_array = NULL; + break; + } return g_array; } @@ -1345,6 +1400,18 @@ hash_table_release: return arg; } +/** + * _pygi_argument_to_object: + * @arg: The argument to convert to an object. + * @type_info: Type info for @arg + * @transfer: + * + * If the argument is of type array, it must be encoded in a GArray, by calling + * _pygi_argument_to_array(). This logic can not be folded into this method + * as determining array lengths may require access to method call arguments. + * + * Returns: A PyObject representing @arg + */ PyObject * _pygi_argument_to_object (GIArgument *arg, GITypeInfo *type_info, @@ -1481,19 +1548,30 @@ _pygi_argument_to_object (GIArgument *arg, } case GI_TYPE_TAG_ARRAY: { + /* Arrays are assumed to be packed in a GArray */ GArray *array; GITypeInfo *item_type_info; GITypeTag item_type_tag; GITransfer item_transfer; gsize i, item_size; - - array = arg->v_pointer; - + + if (arg->v_pointer == NULL) + return PyList_New (0); + item_type_info = g_type_info_get_param_type (type_info, 0); g_assert (item_type_info != NULL); item_type_tag = g_type_info_get_tag (item_type_info); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + array = arg->v_pointer; + item_size = g_array_get_element_size (array); + + if (G_UNLIKELY (item_size > sizeof(GIArgument))) { + g_critical ("Stack overflow protection. " + "Can't copy array element into GIArgument."); + return PyList_New (0); + } if (item_type_tag == GI_TYPE_TAG_UINT8) { /* Return as a byte array */ @@ -1516,31 +1594,13 @@ _pygi_argument_to_object (GIArgument *arg, break; } - } - item_size = g_array_get_element_size (array); + } for (i = 0; i < array->len; i++) { - GIArgument item; + GIArgument item = { 0 }; PyObject *py_item; - gboolean is_struct = FALSE; - - if (item_type_tag == GI_TYPE_TAG_INTERFACE) { - GIBaseInfo *iface_info = g_type_info_get_interface (item_type_info); - switch (g_base_info_get_type (iface_info)) { - case GI_INFO_TYPE_STRUCT: - case GI_INFO_TYPE_BOXED: - is_struct = TRUE; - default: - break; - } - g_base_info_unref ( (GIBaseInfo *) iface_info); - } - - if (is_struct) { - item.v_pointer = &_g_array_index (array, GIArgument, i); - } else { - memcpy (&item, &_g_array_index (array, GIArgument, i), item_size); - } + + memcpy (&item, array->data + i * item_size, item_size); py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer); if (py_item == NULL) { diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h index 7224c75..668fabb 100644 --- a/gi/pygi-argument.h +++ b/gi/pygi-argument.h @@ -44,8 +44,8 @@ gint _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, GArray* _pygi_argument_to_array (GIArgument *arg, GIArgument *args[], - GITypeInfo *type_info, - gboolean is_method); + GITypeInfo *type_info, + gboolean *out_free_array); GIArgument _pygi_argument_from_object (PyObject *object, GITypeInfo *type_info, diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c index 5083417..5d496d5 100644 --- a/gi/pygi-cache.c +++ b/gi/pygi-cache.c @@ -1277,6 +1277,8 @@ _args_cache_generate (GICallableInfo *callable_info, return_direction, -1, -1); + if (return_cache == NULL) + return FALSE; return_cache->is_skipped = g_callable_info_skip_return (callable_info); callable_cache->return_cache = return_cache; diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c index 241d91a..8c8e13d 100644 --- a/gi/pygi-closure.c +++ b/gi/pygi-closure.c @@ -185,10 +185,12 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) 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; } } @@ -235,6 +237,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); PyObject *value; GIArgument *arg; + gboolean free_array = FALSE; if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID && g_type_info_is_pointer (arg_type)) { @@ -290,8 +293,16 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, 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, args, + 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) { g_base_info_unref (arg_type); g_base_info_unref (arg_info); diff --git a/gi/pygi-info.c b/gi/pygi-info.c index 4efb467..8aafe8b 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -135,6 +135,12 @@ _wrap_g_base_info_get_name (PyGIBaseInfo *self) } static PyObject * +_wrap_g_base_info_get_name_unescaped (PyGIBaseInfo *self) +{ + return PYGLIB_PyUnicode_FromString (g_base_info_get_name (self->info)); +} + +static PyObject * _wrap_g_base_info_get_namespace (PyGIBaseInfo *self) { return PYGLIB_PyUnicode_FromString (g_base_info_get_namespace (self->info)); @@ -157,6 +163,7 @@ _wrap_g_base_info_get_container (PyGIBaseInfo *self) static PyMethodDef _PyGIBaseInfo_methods[] = { { "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 }, { "get_container", (PyCFunction) _wrap_g_base_info_get_container, METH_NOARGS }, { NULL, NULL, 0 } @@ -1140,6 +1147,7 @@ _wrap_g_constant_info_get_value (PyGIBaseInfo *self) GITypeInfo *type_info; GIArgument value; PyObject *py_value; + gboolean free_array = FALSE; if (g_constant_info_get_value ( (GIConstantInfo *) self->info, &value) < 0) { PyErr_SetString (PyExc_RuntimeError, "unable to get value"); @@ -1148,7 +1156,16 @@ _wrap_g_constant_info_get_value (PyGIBaseInfo *self) type_info = g_constant_info_get_type ( (GIConstantInfo *) self->info); + if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) { + value.v_pointer = _pygi_argument_to_array (&value, NULL, + type_info, &free_array); + } + py_value = _pygi_argument_to_object (&value, type_info, GI_TRANSFER_NOTHING); + + if (free_array) { + g_array_free (value.v_pointer, FALSE); + } g_constant_info_free_value (self->info, &value); g_base_info_unref ( (GIBaseInfo *) type_info); @@ -1195,6 +1212,7 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self, GITypeInfo *field_type_info; GIArgument value; PyObject *py_value = NULL; + gboolean free_array = FALSE; memset(&value, 0, sizeof(GIArgument)); @@ -1271,18 +1289,15 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self, goto out; } - if ( (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) && - (g_type_info_get_array_type (field_type_info) == GI_ARRAY_TYPE_C)) { + if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) { value.v_pointer = _pygi_argument_to_array (&value, NULL, - field_type_info, FALSE); + field_type_info, &free_array); } argument_to_object: py_value = _pygi_argument_to_object (&value, field_type_info, GI_TRANSFER_NOTHING); - if ( (value.v_pointer != NULL) && - (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) && - (g_type_info_get_array_type (field_type_info) == GI_ARRAY_TYPE_C)) { + if (free_array) { g_array_free (value.v_pointer, FALSE); } diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index adb7152..abdc49e 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -401,6 +401,8 @@ _pygi_marshal_from_py_int64 (PyGIInvokeState *state, if (PyUnicode_Check (py_str)) { PyObject *py_bytes = PyUnicode_AsUTF8String (py_str); + Py_DECREF (py_str); + if (py_bytes == NULL) return FALSE; @@ -413,9 +415,9 @@ _pygi_marshal_from_py_int64 (PyGIInvokeState *state, Py_DECREF (py_bytes); } else { long_str = g_strdup (PYGLIB_PyBytes_AsString(py_str)); + Py_DECREF (py_str); } - Py_DECREF (py_str); PyErr_Format (PyExc_ValueError, "%s not in range %ld to %ld", long_str, G_MININT64, G_MAXINT64); @@ -479,6 +481,8 @@ _pygi_marshal_from_py_uint64 (PyGIInvokeState *state, if (PyUnicode_Check (py_str)) { PyObject *py_bytes = PyUnicode_AsUTF8String (py_str); + Py_DECREF (py_str); + if (py_bytes == NULL) return FALSE; @@ -491,10 +495,9 @@ _pygi_marshal_from_py_uint64 (PyGIInvokeState *state, Py_DECREF (py_bytes); } else { long_str = g_strdup (PYGLIB_PyBytes_AsString (py_str)); + Py_DECREF (py_str); } - Py_DECREF (py_str); - PyErr_Format (PyExc_ValueError, "%s not in range %d to %lu", long_str, 0, G_MAXUINT64); diff --git a/gi/pygi-property.c b/gi/pygi-property.c index 56a9745..7c83eef 100644 --- a/gi/pygi-property.c +++ b/gi/pygi-property.c @@ -211,6 +211,7 @@ pygi_get_property_value_real (PyGObject *instance, arg.v_pointer = g_value_get_boxed (&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: diff --git a/gi/pygi-signal-closure.c b/gi/pygi-signal-closure.c index 1482529..4e9dcb5 100644 --- a/gi/pygi-signal-closure.c +++ b/gi/pygi-signal-closure.c @@ -145,13 +145,25 @@ pygi_signal_closure_marshal(GClosure *closure, GITransfer transfer; GIArgument arg = { 0, }; PyObject *item = NULL; + gboolean free_array = 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(¶m_values[i], &type_info); - item = _pygi_argument_to_object(&arg, &type_info, transfer); + + if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ARRAY) { + arg.v_pointer = _pygi_argument_to_array (&arg, NULL, + &type_info, &free_array); + } + + item = _pygi_argument_to_object (&arg, &type_info, transfer); + + if (free_array) { + g_array_free (arg.v_pointer, FALSE); + } + if (item == NULL) { goto out; diff --git a/m4/python.m4 b/m4/python.m4 index 3cfb9e2..c9cdf5d 100644 --- a/m4/python.m4 +++ b/m4/python.m4 @@ -146,8 +146,7 @@ AC_DEFUN([JD_PATH_PYTHON], dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported m4_define_default([_AM_PYTHON_INTERPRETER_LIST], - [python python2 python3 python3.0 python2.5 python2.4 python2.3 python2.2 dnl -python2.1 python2.0]) + [python python2 python2.7 python2.6 python3 python3.2 python3.1]) m4_if([$1],[],[ dnl No version check is needed. diff --git a/tests/test_gi.py b/tests/test_gi.py index 6aa7445..4348c29 100644 --- a/tests/test_gi.py +++ b/tests/test_gi.py @@ -10,6 +10,8 @@ import shutil import os import locale import subprocess +from io import StringIO, BytesIO + from gi.repository import GObject, GLib from gi.repository import GIMarshallingTests @@ -1643,6 +1645,16 @@ class TestPythonGObject(unittest.TestCase): def do_method_with_default_implementation(self, int8): self.val = int8 + class Interface3Impl(GObject.Object, GIMarshallingTests.Interface3): + def __init__(self): + GObject.Object.__init__(self) + self.variants = None + self.n_variants = None + + def do_test_variant_array_in(self, variants, n_variants): + self.variants = variants + self.n_variants = n_variants + def test_object(self): self.assertTrue(issubclass(self.Object, GIMarshallingTests.Object)) @@ -1732,6 +1744,14 @@ class TestPythonGObject(unittest.TestCase): GIMarshallingTests.SubSubObject.do_method_deep_hierarchy(sub_sub_sub_object, 5) self.assertEqual(sub_sub_sub_object.props.int, 5) + def test_interface3impl(self): + iface3 = self.Interface3Impl() + variants = [GLib.Variant('i', 27), GLib.Variant('s', 'Hello')] + iface3.test_variant_array_in(variants) + self.assertEqual(iface3.n_variants, 2) + self.assertEqual(iface3.variants[0].unpack(), 27) + self.assertEqual(iface3.variants[1].unpack(), 'Hello') + def test_python_subsubobject_vfunc(self): class PySubObject(GIMarshallingTests.Object): def __init__(self): @@ -2229,3 +2249,46 @@ class TestKeywords(unittest.TestCase): # we cannot currently instantiate GLib.Timer objects, so just ensure # the method exists self.assertTrue(callable(GLib.Timer.continue_)) + + def test_uppercase(self): + self.assertEqual(GLib.IOCondition.IN.value_nicks, ['in']) + + +class TestModule(unittest.TestCase): + def test_path(self): + self.assertTrue(GIMarshallingTests.__path__.endswith('GIMarshallingTests-1.0.typelib'), + GIMarshallingTests.__path__) + + def test_str(self): + self.assertTrue("'GIMarshallingTests' from '" in str(GIMarshallingTests), + str(GIMarshallingTests)) + + def test_dir(self): + _dir = dir(GIMarshallingTests) + self.assertGreater(len(_dir), 10) + + self.assertTrue('SimpleStruct' in _dir) + self.assertTrue('Interface2' in _dir) + self.assertTrue('CONSTANT_GERROR_CODE' in _dir) + self.assertTrue('array_zero_terminated_inout' in _dir) + + # assert that dir() does not contain garbage + for item_name in _dir: + item = getattr(GIMarshallingTests, item_name) + self.assertTrue(hasattr(item, '__class__')) + + def test_help(self): + orig_stdout = sys.stdout + try: + if sys.version_info.major < 3: + sys.stdout = BytesIO() + else: + sys.stdout = StringIO() + help(GIMarshallingTests) + output = sys.stdout.getvalue() + finally: + sys.stdout = orig_stdout + + self.assertTrue('SimpleStruct' in output, output) + self.assertTrue('Interface2' in output, output) + self.assertTrue('method_array_inout' in output, output) diff --git a/tests/test_overrides.py b/tests/test_overrides.py index 2968290..73b17a5 100644 --- a/tests/test_overrides.py +++ b/tests/test_overrides.py @@ -464,6 +464,11 @@ class TestGLib(unittest.TestCase): assert_equals_bool('v', GLib.Variant('i', 0)) assert_equals_bool('v', GLib.Variant('i', 1)) + def test_variant_repr(self): + v = GLib.Variant('(is)', (1, 'somestring')) + self.assertEqual(str(v), "(1, 'somestring')") + self.assertEqual(repr(v), "GLib.Variant('(is)', (1, 'somestring'))") + class TestPango(unittest.TestCase): @@ -1364,18 +1369,22 @@ class TestGtk(unittest.TestCase): p2 = Gtk.TreePath.new_first() self.assertEqual(p1, p2) self.assertEqual(str(p1), '0') + self.assertEqual(len(p1), 1) p1 = Gtk.TreePath(2) p2 = Gtk.TreePath.new_from_string('2') self.assertEqual(p1, p2) self.assertEqual(str(p1), '2') + self.assertEqual(len(p1), 1) p1 = Gtk.TreePath('1:2:3') p2 = Gtk.TreePath.new_from_string('1:2:3') self.assertEqual(p1, p2) self.assertEqual(str(p1), '1:2:3') + self.assertEqual(len(p1), 3) p1 = Gtk.TreePath((1, 2, 3)) p2 = Gtk.TreePath.new_from_string('1:2:3') self.assertEqual(p1, p2) self.assertEqual(str(p1), '1:2:3') + self.assertEqual(len(p1), 3) self.assertNotEqual(p1, None) self.assertTrue(p1 > None) self.assertTrue(p1 >= None) -- 2.7.4