+commit 1da98892cf505b35ce0280db22e1e8ba31c095e0
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Wed Aug 19 20:57:37 2015 -0700
+
+ configure.ac: pre-release version bump to 3.17.90
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 79d23e9accd331d954007dcae6b6b7fa2837cfa7
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Wed Feb 18 19:30:30 2015 +0100
+
+ Allow passing unicode lists to GStrv properties on Python 2
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=744745
+
+ gi/pygi-value.c | 41 ++++++++++++++++++++++++++++++++---------
+ tests/test_properties.py | 8 +++++++-
+ 2 files changed, 39 insertions(+), 10 deletions(-)
+
+commit 8aa3d5935b4541be6e76e8792e58bb301fa4f7d1
+Author: Rui Matos <tiagomatos@gmail.com>
+Date: Thu May 21 17:53:17 2015 +0200
+
+ Avoid a silent long to int truncation
+
+ If the python object contains a value bigger than MAXUINT we'd
+ silently truncate it when assigning to 'val' and the if condition
+ would always be true.
+
+ This was caught by a coverity scan.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=749698
+
+ gi/pygi-value.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 5af6c722e5b7db90a3ca0832c46efe0c9142a0d1
+Author: Christoph Reiter <creiter@src.gnome.org>
+Date: Sun Jul 5 11:58:50 2015 +0200
+
+ tests: add a test for test_glist_gtype_container_in()
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=749696
+
+ tests/test_everything.py | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+commit f69ce9f5f6cd81b057ed0006d1fe7f71fa294943
+Author: Mathieu Bridon <bochecha@daitauha.fr>
+Date: Sun Jul 5 11:07:00 2015 +0200
+
+ Handle gtype marshalling
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=749696
+
+ gi/pygi-argument.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 0ee1f562c975df51ce93578d35678ef1e915e202
+Author: Daniel Hahler <git@thequod.de>
+Date: Wed Mar 25 14:37:29 2015 +0100
+
+ pygi-foreign-cairo.c: fix include for py3cairo.h
+
+ The pkg-config info includes the "pycairo" folder already.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=746742
+
+ gi/pygi-foreign-cairo.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fea15145c2a3e6aac73350241a982a095e16c7d8
+Author: Christoph Reiter <creiter@src.gnome.org>
+Date: Thu Jun 18 13:36:52 2015 +0200
+
+ tests: Silence various error messages and warnings.
+
+ This silences glib warnings which are due to testing
+ of error handling, deprecation warnings which we ignore
+ since we want to continue testing deprecated code and
+ other error output of code which is supposed to fail.
+
+ To reduce code duplication and make things easier
+ this introduces a shared helper module containing
+ various context managers and decorators which allow
+ testing and silencing of warnings and errors.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=751156
+
+ tests/Makefile.am | 1 +
+ tests/compat_test_pygtk.py | 27 +++------
+ tests/compathelper.py | 8 +++
+ tests/helper.py | 132
+ ++++++++++++++++++++++++++++++++++++++++++++
+ tests/test_everything.py | 28 ++++++----
+ tests/test_gi.py | 6 +-
+ tests/test_gio.py | 3 +
+ tests/test_iochannel.py | 20 +++----
+ tests/test_overrides_gdk.py | 18 +++---
+ tests/test_overrides_gtk.py | 20 +++----
+ tests/test_properties.py | 21 +++----
+ tests/test_repository.py | 13 ++---
+ tests/test_signal.py | 24 +++-----
+ tests/test_source.py | 8 +--
+ 14 files changed, 231 insertions(+), 98 deletions(-)
+
+commit 619777730891b42b98da556c3aa9ca5a1b3f617b
+Author: Christoph Reiter <creiter@src.gnome.org>
+Date: Thu Jun 18 13:30:03 2015 +0200
+
+ Fix gcc warning regarding uninitialized use of variable
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=751156
+
+ gi/pygobject.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 1ed8200abefc3e51e4d2083b1372695aaf4163fb
+Author: Christoph Reiter <creiter@src.gnome.org>
+Date: Sun Jun 21 23:55:02 2015 +0200
+
+ Fix test regression when xdg-user-dirs is not installed.
+
+ GLib.get_user_special_dir is only guaranteed to always return
+ a path in case GLib.UserDirectory.DIRECTORY_DESKTOP is passed.
+ This was unintentionally changed to DIRECTORY_MUSIC
+ in 9948a67e677c8a351f2de1708.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=751299
+
+ tests/test_glib.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 79cf1f70d247b5a4d33d1e60107e47903ca76055
+Author: Garrett Regier <garrett.regier@riftio.com>
+Date: Mon May 18 02:32:18 2015 -0700
+
+ Explicitly check if an override exists instead of ImportError
+
+ If an override depended on another module and it did not
+ exist then the raised ImportError was consumed and assumed
+ to mean that the override did not exist. This makes it
+ difficult to diagnose issues with overrides.
+
+ This uses pkgutil.get_loader() as it is the easier way to
+ determine if a module exists in both Python 2 and 3
+ and avoid deprecated functions.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=749532
+
+ gi/overrides/__init__.py | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+commit d2faa619f5e204b75315a42fec99dd48fe7fb31c
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Mon Jun 15 01:24:16 2015 -0700
+
+ configure.ac: post-release version bump to 3.17.2
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6fa54fe868d0e2a9a9d4dc300a61cbfa079681a8
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Mon Jun 15 01:20:47 2015 -0700
+
+ release 3.17.1
+
+ NEWS | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
commit 2048dc8d1d708abce7037f96483c6d776567d6b5
Author: Christoph Reiter <creiter@src.gnome.org>
Date: Mon Mar 2 20:58:04 2015 +0100
+3.17.90 19-Aug-2015
+ - Allow passing unicode lists to GStrv properties on Python 2
+ (Christoph Reiter) (#744745)
+ - Avoid a silent long to int truncation (Rui Matos) (#749698)
+ - Handle gtype marshalling (Mathieu Bridon) (#749696)
+ - pygi-foreign-cairo.c: fix include for py3cairo.h
+ (Daniel Hahler) (#746742)
+ - tests: Silence various error messages and warnings
+ (Christoph Reiter) (#751156)
+ - Fix test regression when xdg-user-dirs is not installed
+ (Christoph Reiter) (#751299)
+ - Explicitly check if an override exists instead of ImportError
+ (Garrett Regier) (#749532)
+
3.17.1 15-Jun-2015
- Add gi.PyGIWarning used when import version is not specified
(Christoph Reiter) (#727379)
Metadata-Version: 1.0
Name: PyGObject
-Version: 3.17.1
+Version: 3.17.90
Summary: Python bindings for GObject
Home-page: http://www.pygtk.org/
Author: James Henstridge
Maintainer: Simon Feltman
Maintainer-email: sfeltman@src.gnome.org
License: GNU LGPL
-Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.17/pygobject-3.17.1.tar.gz
+Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.17/pygobject-3.17.90.tar.gz
Description: Python bindings for GLib and GObject
Platform: POSIX, Windows
Classifier: Development Status :: 5 - Production/Stable
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for pygobject 3.17.1.
+# Generated by GNU Autoconf 2.69 for pygobject 3.17.90.
#
# Report bugs to <http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject>.
#
# Identity of this package.
PACKAGE_NAME='pygobject'
PACKAGE_TARNAME='pygobject'
-PACKAGE_VERSION='3.17.1'
-PACKAGE_STRING='pygobject 3.17.1'
+PACKAGE_VERSION='3.17.90'
+PACKAGE_STRING='pygobject 3.17.90'
PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject'
PACKAGE_URL='https://wiki.gnome.org/Projects/PyGObject/'
# 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.17.1 to adapt to many kinds of systems.
+\`configure' configures pygobject 3.17.90 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of pygobject 3.17.1:";;
+ short | recursive ) echo "Configuration of pygobject 3.17.90:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-pygobject configure 3.17.1
+pygobject configure 3.17.90
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
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.17.1, which was
+It was created by pygobject $as_me 3.17.90, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
PYGOBJECT_MINOR_VERSION=17
-$as_echo "#define PYGOBJECT_MICRO_VERSION 1" >>confdefs.h
+$as_echo "#define PYGOBJECT_MICRO_VERSION 90" >>confdefs.h
-PYGOBJECT_MICRO_VERSION=1
+PYGOBJECT_MICRO_VERSION=90
ac_config_headers="$ac_config_headers config.h"
# Define the identity of the package.
PACKAGE='pygobject'
- VERSION='3.17.1'
+ VERSION='3.17.90'
cat >>confdefs.h <<_ACEOF
# 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.17.1, which was
+This file was extended by pygobject $as_me 3.17.90, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
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.17.1
+pygobject config.status 3.17.90
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
dnl the pygobject version number
m4_define(pygobject_major_version, 3)
m4_define(pygobject_minor_version, 17)
-m4_define(pygobject_micro_version, 1)
+m4_define(pygobject_micro_version, 90)
m4_define(pygobject_version, pygobject_major_version.pygobject_minor_version.pygobject_micro_version)
dnl versions of packages we require ...
import warnings
import importlib
import sys
+from pkgutil import get_loader
from gi import PyGIDeprecationWarning
from gi._gi import CallableInfo
modules[namespace] = proxy
try:
+ override_package_name = 'gi.overrides.' + namespace
+
+ # http://bugs.python.org/issue14710
try:
- override_mod = importlib.import_module('gi.overrides.' + namespace)
- except ImportError:
+ override_loader = get_loader(override_package_name)
+
+ except AttributeError:
+ override_loader = None
+
+ # 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
+
+ override_mod = importlib.import_module(override_package_name)
+
finally:
del modules[namespace]
del sys.modules[module_key]
case GI_TYPE_TAG_UINT32:
arg->v_uint32 = 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:
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:
#include <pycairo.h>
static Pycairo_CAPI_t *Pycairo_CAPI;
#else
-#include <pycairo/py3cairo.h>
+#include <py3cairo.h>
#endif
#include <cairo-gobject.h>
case G_TYPE_UINT:
{
if (PYGLIB_PyLong_Check(obj)) {
- guint val;
+ gulong val;
/* check that number is not negative */
if (PyLong_AsLongLong(obj) < 0)
val = PyLong_AsUnsignedLong(obj);
if (val <= G_MAXUINT)
- g_value_set_uint(value, val);
+ g_value_set_uint(value, (guint) val);
else
return -1;
} else {
Py_ssize_t argc, i;
gchar **argv;
- if (!(PyTuple_Check(obj) || PyList_Check(obj)))
+ 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)));
+ argc = PySequence_Length (obj);
+ argv = g_new (gchar *, argc + 1);
+ for (i = 0; i < argc; ++i) {
+ PyObject* item = PySequence_Fast_GET_ITEM (obj, i);
+ /* same as _pygi_marshal_from_py_utf8 */
+ if (PyUnicode_Check (item)) {
+ PyObject *pystr_obj = PyUnicode_AsUTF8String (item);
+ if (!pystr_obj) {
+ goto error;
+ }
+ argv[i] = g_strdup (PYGLIB_PyBytes_AsString (pystr_obj));
+ Py_DECREF (pystr_obj);
+ }
+#if PY_VERSION_HEX < 0x03000000
+ else if (PyString_Check (item)) {
+ argv[i] = g_strdup (PyString_AsString (item));
+ }
+#endif
+ else {
+ goto error;
+ }
+ }
+
argv[i] = NULL;
- g_value_take_boxed(value, argv);
+ 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;
}
* free the memory. */
PyGILState_STATE state;
PyThreadState *_save = NULL;
+ gboolean state_saved = FALSE;
GSList *closures, *tmp;
if (Py_IsInitialized()) {
+ state_saved = TRUE;
state = pyglib_gil_state_ensure();
Py_DECREF(data->type);
/* We cannot use Py_BEGIN_ALLOW_THREADS here because this is inside
g_free(data);
- if (Py_IsInitialized()) {
+ if (state_saved && Py_IsInitialized ()) {
Py_BLOCK_THREADS; /* Restores _save */
pyglib_gil_state_release(state);
}
all: $(check_LTLIBRARIES:.la=.$(OS_EXT))
EXTRA_DIST = \
+ helper.py \
compathelper.py \
runtests.py \
runtests-windows.py \
test-unknown.c
EXTRA_DIST = \
+ helper.py \
compathelper.py \
runtests.py \
runtests-windows.py \
# vim: tabstop=4 shiftwidth=4 expandtab
import unittest
-import contextlib
import base64
import gi
-from gi.repository import GLib
try:
try:
except ImportError:
Gtk = None
-
-@contextlib.contextmanager
-def ignore_glib_warnings():
- """Temporarily change GLib logging to not bail on warnings."""
- old_mask = GLib.log_set_always_fatal(
- GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
- yield
- GLib.log_set_always_fatal(old_mask)
+from helper import capture_gi_deprecation_warnings, capture_glib_warnings
@unittest.skipUnless(Gtk, 'Gtk not available')
def test_style(self):
widget = gtk.Button()
- self.assertTrue(isinstance(widget.style.base[gtk.STATE_NORMAL],
- gtk.gdk.Color))
+ with capture_gi_deprecation_warnings():
+ self.assertTrue(isinstance(widget.style.base[gtk.STATE_NORMAL],
+ gtk.gdk.Color))
def test_alignment(self):
# Creation of pygtk.Alignment causes hard warnings, ignore this in testing.
- with ignore_glib_warnings():
+ with capture_glib_warnings(allow_warnings=True):
a = gtk.Alignment()
self.assertEqual(a.props.xalign, 0.0)
liststore.append((2, 'Two'))
liststore.append((3, 'Three'))
# might cause a Pango warning, do not break on this
- old_mask = GLib.log_set_always_fatal(
- GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
- try:
+ with capture_glib_warnings(allow_warnings=True):
combo = gtk.ComboBoxEntry(model=liststore)
- finally:
- GLib.log_set_always_fatal(old_mask)
combo.set_text_column(1)
combo.set_active(0)
self.assertEqual(combo.get_text_column(), 1)
def test_size_request(self):
box = gtk.Box()
- self.assertEqual(box.size_request(), [0, 0])
+ with capture_gi_deprecation_warnings():
+ self.assertEqual(box.size_request(), [0, 0])
def test_pixbuf(self):
gtk.gdk.Pixbuf()
import sys
+import collections
if sys.version_info >= (3, 0):
'''
'''
_unicode = lambda s: str(s)
+
+ callable = lambda x: isinstance(x, collections.Callable)
+ from io import StringIO
+ StringIO
else:
_long = long
_basestring = basestring
_bytes = str
_unicode = lambda s: unicode(s, 'UTF-8')
+ callable = callable
+ from StringIO import StringIO
+ StringIO
--- /dev/null
+import contextlib
+import unittest
+import inspect
+import warnings
+import functools
+import sys
+from collections import namedtuple
+
+import gi
+from gi import PyGIDeprecationWarning
+from gi.repository import GLib
+
+from compathelper import callable, StringIO
+
+
+ExceptionInfo = namedtuple("ExceptionInfo", ["type", "value", "traceback"])
+"""The type used for storing exceptions used by capture_exceptions()"""
+
+
+@contextlib.contextmanager
+def capture_exceptions():
+ """Installs a temporary sys.excepthook which records all exceptions
+ instead of printing them.
+ """
+
+ exceptions = []
+
+ def custom_excepthook(*args):
+ exceptions.append(ExceptionInfo(*args))
+
+ old_hook = sys.excepthook
+ sys.excepthook = custom_excepthook
+ try:
+ yield exceptions
+ finally:
+ sys.excepthook = old_hook
+
+
+def ignore_gi_deprecation_warnings(func_or_class):
+ """A unittest class and function decorator which makes them ignore
+ PyGIDeprecationWarning.
+ """
+
+ if inspect.isclass(func_or_class):
+ assert issubclass(func_or_class, unittest.TestCase)
+ cls = func_or_class
+ for name, value in cls.__dict__.items():
+ if callable(value) and name.startswith("test_"):
+ new_value = ignore_gi_deprecation_warnings(value)
+ setattr(cls, name, new_value)
+ return cls
+ else:
+ func = func_or_class
+
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ with capture_gi_deprecation_warnings():
+ return func(*args, **kwargs)
+
+ return wrapper
+
+
+@contextlib.contextmanager
+def capture_gi_deprecation_warnings():
+ """Temporarily suppress PyGIDeprecationWarning output and record them"""
+
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always', category=PyGIDeprecationWarning)
+ yield warn
+
+
+@contextlib.contextmanager
+def capture_glib_warnings(allow_warnings=False, allow_criticals=False):
+ """Temporarily suppress glib warning output and record them.
+
+ The test suite is run with G_DEBUG="fatal-warnings fatal-criticals"
+ by default. Setting allow_warnings and allow_criticals will temporarily
+ allow warnings or criticals without terminating the test run.
+ """
+
+ old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags(0))
+
+ new_mask = old_mask
+ if allow_warnings:
+ new_mask &= ~GLib.LogLevelFlags.LEVEL_WARNING
+ if allow_criticals:
+ new_mask &= ~GLib.LogLevelFlags.LEVEL_CRITICAL
+
+ GLib.log_set_always_fatal(GLib.LogLevelFlags(new_mask))
+
+ GLibWarning = gi._gi._gobject.Warning
+ try:
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.filterwarnings('always', category=GLibWarning)
+ yield warn
+ finally:
+ GLib.log_set_always_fatal(old_mask)
+
+
+@contextlib.contextmanager
+def capture_glib_deprecation_warnings():
+ """Temporarily suppress glib deprecation warning output and record them"""
+
+ GLibWarning = gi._gi._gobject.Warning
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.filterwarnings(
+ 'always', category=GLibWarning,
+ message=".+ is deprecated and shouldn't be used anymore\. "
+ "It will be removed in a future version\.")
+ yield warn
+
+
+@contextlib.contextmanager
+def capture_output():
+ """
+ with capture_output as (stdout, stderr):
+ some_action()
+ print(stdout.getvalue(), stderr.getvalue())
+ """
+
+ err = StringIO()
+ out = StringIO()
+ old_err = sys.stderr
+ old_out = sys.stdout
+ sys.stderr = err
+ sys.stdout = out
+
+ try:
+ yield (out, err)
+ finally:
+ sys.stderr = old_err
+ sys.stdout = old_out
except:
Gtk = None
+from helper import capture_exceptions
+
+
if sys.version_info < (3, 0):
UNICHAR = "\xe2\x99\xa5"
PY2_UNICODE_UNICHAR = unicode(UNICHAR, 'UTF-8')
Everything.test_glist_nothing_in(['1', '2', '3'])
Everything.test_glist_nothing_in2(['1', '2', '3'])
+ @unittest.skipUnless(hasattr(Everything, 'test_glist_gtype_container_in'),
+ 'Requires newer version of GI')
+ def test_glist_gtype(self):
+ Everything.test_glist_gtype_container_in(
+ [Everything.TestObj, Everything.TestSubObj])
+
def test_gslist(self):
self.assertEqual(Everything.test_gslist_nothing_return(), ['1', '2', '3'])
self.assertEqual(Everything.test_gslist_nothing_return2(), ['1', '2', '3'])
# note that we do NOT expect the ZeroDivisionError to be propagated
# through from the callback, as it crosses the Python<->C boundary
# twice. (See GNOME #616279)
- Everything.test_simple_callback(callback)
+ with capture_exceptions() as exc:
+ Everything.test_simple_callback(callback)
+ self.assertTrue(exc)
+ self.assertEqual(exc[0].type, ZeroDivisionError)
def test_double_callback_exception(self):
"""
# note that we do NOT expect the ZeroDivisionError to be propagated
# through from the callback, as it crosses the Python<->C boundary
# twice. (See GNOME #616279)
- Everything.test_simple_callback(callback)
+ with capture_exceptions() as exc:
+ Everything.test_simple_callback(callback)
+ self.assertTrue(exc)
+ self.assertEqual(exc[0].type, ZeroDivisionError)
def test_return_value_callback(self):
TestCallbacks.called = False
def callback(variant):
return 'no_variant'
- # reset last error
- sys.last_type = None
-
- # this does not directly raise an exception (see
- # https://bugzilla.gnome.org/show_bug.cgi?id=616279)
- result = Everything.test_closure_variant(callback, GLib.Variant('i', 42))
+ with capture_exceptions() as exc:
+ # this does not directly raise an exception (see
+ # https://bugzilla.gnome.org/show_bug.cgi?id=616279)
+ result = Everything.test_closure_variant(callback, GLib.Variant('i', 42))
# ... but the result shouldn't be a string
self.assertEqual(result, None)
# and the error should be shown
- self.assertEqual(sys.last_type, TypeError)
- self.assertTrue('return value' in str(sys.last_value), sys.last_value)
+ self.assertEqual(len(exc), 1)
+ self.assertEqual(exc[0].type, TypeError)
+ self.assertTrue('return value' in str(exc[0].value), exc[0].value)
@unittest.skipUnless(has_cairo, 'built without cairo support')
from gi.repository import GIMarshallingTests
from compathelper import _bytes, _unicode
+from helper import capture_exceptions
if sys.version_info < (3, 0):
CONSTANT_UTF8 = "const \xe2\x99\xa5 utf8"
def test_exception_in_vfunc_return_value(self):
obj = self.ErrorObject()
- self.assertEqual(obj.vfunc_return_value_only(), 0)
+ with capture_exceptions() as exc:
+ self.assertEqual(obj.vfunc_return_value_only(), 0)
+ self.assertEqual(len(exc), 1)
+ self.assertEqual(exc[0].type, ValueError)
@unittest.skipUnless(hasattr(GIMarshallingTests, 'callback_owned_boxed'),
'requires newer version of GI')
import gi.overrides
from gi.repository import GLib, Gio
+from helper import ignore_gi_deprecation_warnings
+
class TestGio(unittest.TestCase):
def test_file_enumerator(self):
self.assertEqual(bool(empty), True)
self.assertEqual(empty.keys(), [])
+ @ignore_gi_deprecation_warnings
def test_change_event(self):
changed_log = []
change_event_log = []
def test_xdg_dirs(self):
d = GLib.get_user_data_dir()
self.assertTrue('/' in d, d)
- d = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_MUSIC)
+ d = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)
self.assertTrue('/' in d, d)
with warnings.catch_warnings():
warnings.simplefilter('ignore', PyGIDeprecationWarning)
self.assertEqual(_unicode(ch.readline()), 'À demain!')
self.assertEqual(ch.get_buffer_condition(), 0)
self.assertEqual(ch.readline(), '')
- ch.close()
+ ch.shutdown(True)
def test_file_readline_latin1(self):
ch = GLib.IOChannel(filename=self.testlatin1, mode='r')
self.assertEqual(ch.readline(), 'second line\n')
self.assertEqual(ch.readline(), '\n')
self.assertEqual(_unicode(ch.readline()), 'À demain!')
- ch.close()
+ ch.shutdown(True)
def test_file_iter(self):
items = []
items.append(item)
self.assertEqual(len(items), 4)
self.assertEqual(_unicode(items[0]), 'hello ♥ world\n')
- ch.close()
+ ch.shutdown(True)
def test_file_readlines(self):
ch = GLib.IOChannel(filename=self.testutf8)
ch = GLib.IOChannel(filename=self.testout, mode='w')
ch.set_encoding('latin1')
ch.write('hellø world\n')
- ch.close()
+ ch.shutdown(True)
ch = GLib.IOChannel(filename=self.testout, mode='a')
ch.set_encoding('latin1')
ch.write('À demain!')
- ch.close()
+ ch.shutdown(True)
with open(self.testout, 'rb') as f:
self.assertEqual(f.read().decode('latin1'), 'hellø world\nÀ demain!')
def test_file_writelines(self):
ch = GLib.IOChannel(filename=self.testout, mode='w')
ch.writelines(['foo', 'bar\n', 'baz\n', 'end'])
- ch.close()
+ ch.shutdown(True)
with open(self.testout, 'r') as f:
self.assertEqual(f.read(), 'foobar\nbaz\nend')
# closing flushes
writer.set_buffered(True)
writer.write('ghi')
- writer.close()
+ writer.shutdown(True)
self.assertEqual(reader.read(), b'ghi')
- reader.close()
+ reader.shutdown(True)
def test_fd_read(self):
(r, w) = os.pipe()
os.close(w)
self.assertEqual(ch.read(), b'\x03\x04')
- ch.close()
+ ch.shutdown(True)
def test_fd_write(self):
(r, w) = os.pipe()
# now test blocking case, after closing the write end
fcntl.fcntl(r, fcntl.F_SETFL, fcntl.fcntl(r, fcntl.F_GETFL) & ~os.O_NONBLOCK)
ch.write(b'\x03\x04')
- ch.close()
+ ch.shutdown(True)
self.assertEqual(os.read(r, 10), b'\x03\x04')
os.close(r)
# vim: tabstop=4 shiftwidth=4 expandtab
import unittest
-import warnings
import gi.overrides
from gi import PyGIDeprecationWarning
except ImportError:
Gdk = None
+from helper import capture_glib_deprecation_warnings
+
@unittest.skipUnless(Gdk, 'Gdk not available')
class TestGdk(unittest.TestCase):
self.assertEqual(color.red, 100)
self.assertEqual(color.green, 200)
self.assertEqual(color.blue, 300)
- self.assertEqual(color, Gdk.Color(100, 200, 300))
+ with capture_glib_deprecation_warnings():
+ self.assertEqual(color, Gdk.Color(100, 200, 300))
self.assertNotEqual(color, Gdk.Color(1, 2, 3))
def test_color_floats(self):
def test_cursor(self):
self.assertEqual(Gdk.Cursor, gi.overrides.Gdk.Cursor)
- c = Gdk.Cursor(Gdk.CursorType.WATCH)
+ with capture_glib_deprecation_warnings():
+ c = Gdk.Cursor(Gdk.CursorType.WATCH)
self.assertNotEqual(c, None)
- c = Gdk.Cursor(cursor_type=Gdk.CursorType.WATCH)
+ with capture_glib_deprecation_warnings():
+ c = Gdk.Cursor(cursor_type=Gdk.CursorType.WATCH)
self.assertNotEqual(c, None)
display_manager = Gdk.DisplayManager.get()
5,
10)
- with warnings.catch_warnings(record=True) as warn:
- warnings.simplefilter('always')
+ with capture_glib_deprecation_warnings() as warn:
c = Gdk.Cursor(display,
test_pixbuf,
y=0, x=0)
'<flags GDK_META_MASK | GDK_RELEASE_MASK of type GdkModifierType>')
def test_color_parse(self):
- c = Gdk.color_parse('#00FF80')
+ with capture_glib_deprecation_warnings():
+ c = Gdk.color_parse('#00FF80')
self.assertEqual(c.red, 0)
self.assertEqual(c.green, 65535)
self.assertEqual(c.blue, 32896)
import warnings
from compathelper import _unicode, _bytes
+from helper import ignore_gi_deprecation_warnings, capture_glib_warnings
import gi
import gi.overrides
Gtk.main_iteration()
-@contextlib.contextmanager
-def ignore_glib_warnings():
- """Temporarily change GLib logging to not bail on warnings."""
- old_mask = GLib.log_set_always_fatal(
- GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
- yield
- GLib.log_set_always_fatal(old_mask)
-
-
@unittest.skipUnless(Gtk, 'Gtk not available')
+@ignore_gi_deprecation_warnings
class TestGtk(unittest.TestCase):
def test_container(self):
box = Gtk.Box()
def test_file_chooser_dialog(self):
# might cause a GVFS warning, do not break on this
- with ignore_glib_warnings():
+ with capture_glib_warnings(allow_warnings=True):
dialog = Gtk.FileChooserDialog(title='file chooser dialog test',
action=Gtk.FileChooserAction.SAVE)
def test_file_chooser_dialog_default_action(self):
# might cause a GVFS warning, do not break on this
- with ignore_glib_warnings():
+ with capture_glib_warnings(allow_warnings=True):
dialog = Gtk.FileChooserDialog(title='file chooser dialog test')
action = dialog.get_property('action')
self.assertTrue(isinstance(button, Gtk.Widget))
# Using stock items causes hard warning in devel versions of GTK+.
- with ignore_glib_warnings():
+ with capture_glib_warnings(allow_warnings=True):
button = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE)
self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
# PyGTK compat
# Using stock items causes hard warning in devel versions of GTK+.
- with ignore_glib_warnings():
+ with capture_glib_warnings(allow_warnings=True):
button = Gtk.ToolButton()
self.assertEqual(button.props.stock_id, None)
self.assertEqual(signal_checker.after_sentinel, 2)
+@ignore_gi_deprecation_warnings
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestTreeModel(unittest.TestCase):
def test_tree_model_sort(self):
TEST_UTF8 = "♥"
UNICODE_UTF8 = TEST_UTF8
-from compathelper import _long
+from compathelper import _long, _unicode
+from helper import capture_glib_warnings, capture_output
class PropertyObject(GObject.GObject):
raise ValueError('something bad happend')
o = C()
- with self.assertRaisesRegex(ValueError, 'something bad happend'):
- o.prop
- with self.assertRaisesRegex(ValueError, 'something bad happend'):
- o.get_property('prop')
+ # silence exception printed to stderr
+ with capture_output():
+ with self.assertRaisesRegex(ValueError, 'something bad happend'):
+ o.prop
- with self.assertRaisesRegex(ValueError, 'something bad happend'):
- o.props.prop
+ with self.assertRaisesRegex(ValueError, 'something bad happend'):
+ o.get_property('prop')
+
+ with self.assertRaisesRegex(ValueError, 'something bad happend'):
+ o.props.prop
def test_custom_setter(self):
class C(GObject.GObject):
# we test known-bad values here which cause Gtk-WARNING logs.
# Explicitly allow these for this test.
- old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL)
- try:
+ with capture_glib_warnings(allow_warnings=True):
o = C()
self.assertEqual(o.prop_int, 1)
o.prop_float = 10.51
self.assertEqual(o.prop_float, 7.75)
- finally:
- GLib.log_set_always_fatal(old_mask)
def test_multiple_instances(self):
class C(GObject.GObject):
obj = GIMarshallingTests.PropertiesObject(some_strv=['hello', 'world'])
self.assertEqual(self.get_prop(obj, 'some-strv'), ['hello', 'world'])
+ # unicode on py2
+ obj = GIMarshallingTests.PropertiesObject(some_strv=[_unicode('foo')])
+ self.assertEqual(self.get_prop(obj, 'some-strv'), [_unicode('foo')])
+ self.assertRaises(TypeError, self.set_prop, self.obj, 'some-strv',
+ [_unicode('foo'), 1])
+
def test_boxed_struct(self):
self.assertEqual(self.get_prop(self.obj, 'some-boxed-struct'), None)
import gi._gi as GIRepository
from gi.module import repository as repo
from gi.repository import GObject
-from gi.repository import GLib
from gi.repository import GIMarshallingTests
from gi.repository import GIRepository as IntrospectedRepository
except ImportError:
has_cairo = False
+from helper import capture_glib_warnings
+
def find_child_info(info, getter_name, name):
getter = getattr(info, getter_name)
# also raise a RuntimeError.
GIMarshallingTests.NoTypeFlags # cause flags registration
info = repo.find_by_name('GIMarshallingTests', 'NoTypeFlags')
- old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
- try:
+ with capture_glib_warnings(allow_warnings=True):
self.assertRaises(RuntimeError,
GIRepository.flags_register_new_gtype_and_add,
info)
- finally:
- GLib.log_set_always_fatal(old_mask)
def test_enum_double_registration_error(self):
# a warning is printed for double registration and pygobject will
# also raise a RuntimeError.
GIMarshallingTests.Enum # cause enum registration
info = repo.find_by_name('GIMarshallingTests', 'Enum')
- old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
- try:
+ with capture_glib_warnings(allow_warnings=True):
self.assertRaises(RuntimeError,
GIRepository.enum_register_new_gtype_and_add,
info)
- finally:
- GLib.log_set_always_fatal(old_mask)
def test_enums(self):
self.assertTrue(hasattr(GIRepository, 'Direction'))
from gi import _signalhelper as signalhelper
import testhelper
from compathelper import _long
+from helper import capture_glib_warnings, capture_gi_deprecation_warnings
try:
import cairo
def foo():
class Foo(GObject.GObject):
__gsignals__ = {'not-exists': 'override'}
- # do not stumble over the warning thrown by GLib
- old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL |
- GLib.LogLevelFlags.LEVEL_ERROR)
- try:
+
+ with capture_glib_warnings(allow_warnings=True):
self.assertRaises(TypeError, foo)
- finally:
- GLib.log_set_always_fatal(old_mask)
gc.collect()
self.count += 1
def _callback_invalid_stop_emission_name(self, obj, prop):
- # We expect a GLib warning but there currently is no way to test that
- # This can at least make sure we don't crash
- old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL |
- GLib.LogLevelFlags.LEVEL_ERROR)
- try:
+ with capture_glib_warnings(allow_warnings=True) as warn:
obj.stop_emission_by_name('notasignal::baddetail')
- finally:
- GLib.log_set_always_fatal(old_mask)
self.emission_error = True
+ self.assertTrue(warn)
def test_disconnect_by_func(self):
e = E()
e = E()
e.connect('notify::prop', self._callback_invalid_stop_emission_name)
- e.set_property('prop', 1234)
+ with capture_glib_warnings():
+ e.set_property('prop', 1234)
self.assertTrue(self.emission_error)
def test_handler_block(self):
else:
connect_func = obj.connect_object
- connect_func('sig-with-int64-prop', callback, swap_obj, *user_data)
+ with capture_gi_deprecation_warnings():
+ connect_func('sig-with-int64-prop', callback, swap_obj, *user_data)
obj.emit('sig-with-int64-prop', *emit_args)
self.assertEqual(len(callback_args), 1)
return callback_args[0]
from gi.repository import GLib
from gi import PyGIDeprecationWarning
+from helper import capture_glib_warnings
+
class Idle(GLib.Idle):
def __init__(self, loop):
self.assertEqual(GLib.source_remove(s), True)
# Removing sources not found cause critical
- old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
- try:
+ with capture_glib_warnings(allow_criticals=True):
+
# s is now removed, should fail now
self.assertEqual(GLib.source_remove(s), False)
self.assertEqual(GLib.source_remove(GLib.MAXINT32), False)
self.assertEqual(GLib.source_remove(GLib.MAXINT32 + 1), False)
self.assertEqual(GLib.source_remove(GLib.MAXUINT32), False)
- finally:
- GLib.log_set_always_fatal(old_mask)
def test_recurse_property(self):
s = GLib.Idle()