+commit 9c1d66be67008604206e336a0433c5cdf824b837
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Wed Feb 14 01:47:12 2018 +0100
+
+ release
+
+ NEWS | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 86fb783d0f00a49ea7e66ad73be7e150eb0162db
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Wed Feb 14 02:07:13 2018 +0100
+
+ Fix make distcheck
+
+ tests/Makefile.am | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+commit 618ccf06ad75bc481dec59b7da86a550571968c5
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Wed Feb 14 01:34:02 2018 +0100
+
+ setup.py: cache pkg-config calls
+
+ This saves 300ms for a noop build_tests command
+
+ setup.py | 29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+commit ad9fc2d9cd8d9a0f3fd07a46e7056a182f18d399
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Wed Feb 14 01:29:09 2018 +0100
+
+ gitlab-ci: Install pytest-faulthandler
+
+ This makes pytest print a Python stack trace in case of a crash.
+
+ .gitlab-ci/test-docker.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0d3fbc2a8d10c9eea4e3eef905d52c946f8ab7e9
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Wed Feb 14 01:16:51 2018 +0100
+
+ setup.py: set the same env vars for testing as autotools
+
+ Also don't print a Python stack trace of the calling process on
+ error, just return the error status.
+
+ setup.py | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit 0fcd57846b0053319dc5a28503d3eab173927fc6
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Wed Feb 14 00:56:47 2018 +0100
+
+ tests: add a test for Gio.DBusNodeInfo.new_for_xml, see #164
+
+ This was fixed by the recent reverts
+
+ tests/test_gdbus.py | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+commit a506d5e3c64321c43a4ce7c2a72ca8d36e985999
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Tue Feb 13 23:26:21 2018 +0100
+
+ Revert "Revert "Refactor boxed wrapper memory management strategy""
+
+ This reverts commit daefdfa3e4dc97b4ae38250358d722f09764cc9b.
+
+ gi/gimodule.c | 6 +++-
+ gi/overrides/GLib.py | 4 ---
+ gi/overrides/GObject.py | 3 ++
+ gi/pygi-boxed.c | 32 +++++++++++++++-----
+ gi/pygi-boxed.h | 4 +--
+ gi/pygi-property.c | 6 +---
+ gi/pygi-source.c | 6 ++--
+ gi/pygi-struct-marshal.c | 78
+ ++++++++++++++++++++++++++++++++++++++++++++----
+ tests/test_gi.py | 1 -
+ tests/test_source.py | 8 +++--
+ 10 files changed, 119 insertions(+), 29 deletions(-)
+
+commit 700c785367975995d24a8ffd00b2aa028ccf77e8
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Tue Feb 13 23:26:15 2018 +0100
+
+ Revert "pygi-boxed: make in-place copy safer"
+
+ This reverts commit 9d96df1ea3ad533885fbcae4de693a3cd81e765a.
+
+ gi/pygi-boxed.c | 8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+commit fa555767464fbe551b14cfbc121febc5290b1371
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Tue Feb 13 23:26:03 2018 +0100
+
+ Revert "to python marshalling: collect cleanup data"
+
+ This reverts commit 80eab029ce4e181624d7b845a4b517051797080d.
+
+ gi/pygi-array.c | 24 ++++++------------------
+ gi/pygi-basictype.c | 8 +++-----
+ gi/pygi-basictype.h | 3 +--
+ gi/pygi-cache.h | 13 +++----------
+ gi/pygi-closure.c | 9 ++-------
+ gi/pygi-enum-marshal.c | 6 ++----
+ gi/pygi-error.c | 3 +--
+ gi/pygi-hashtable.c | 13 ++++---------
+ gi/pygi-invoke-state-struct.h | 3 ---
+ gi/pygi-invoke.c | 17 ++++-------------
+ gi/pygi-list.c | 38 +++++++-------------------------------
+ gi/pygi-marshal-cleanup.c | 13 +++++--------
+ gi/pygi-object.c | 8 +++-----
+ gi/pygi-struct-marshal.c | 5 ++---
+ 14 files changed, 43 insertions(+), 120 deletions(-)
+
+commit 10c062001ddd948b0a70545cbf613b38ed6fa46c
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Tue Feb 13 23:09:49 2018 +0100
+
+ Revert "to python struct marshalling: copy boxed during cleanup"
+
+ This reverts commit 7ed8191818733b9130bce84f782dc6f8f734abf7.
+
+ gi/pygi-struct-marshal.c | 34 +++++++---------------------------
+ tests/test_gi.py | 1 +
+ 2 files changed, 8 insertions(+), 27 deletions(-)
+
+commit e427d1a3a44e882c998543bb2c189700409df873
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Mon Feb 12 20:35:09 2018 +0100
+
+ tests: Fix tests under Wayland. Fixes #163
+
+ These tests try to test Gdk.Atom with the exsting API in libgdk
+ but under Wayland they either don't return Gdk.Atom or block.
+
+ Since they are disabled on other platforms just change them to only
+ run under X11.
+
+ tests/test_atoms.py | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+commit 3e91df3dca3691635b978d1dc661506213e0efe3
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Mon Feb 12 15:39:41 2018 +0100
+
+ docs: fix build with sphinx 1.7.0
+
+ 1.7.0 no longer allows non-class references as param types
+
+ docs/guide/api/signals.rst | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 5a25c98cb6d387791e41c7dc240c55814988519a
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Sun Feb 11 18:08:07 2018 +0100
+
+ tests: Make it possible to use pytest directly
+
+ pytest will just import the files passed to it and try to run tests.
+ Since we need to run some setup code convert the tests directory to
+ a Python package and do the initialization in __init__.py. This makes
+ the init code (env vars, typelib search path, dbus) always run when
+ something from the package gets imported.
+
+ python3 setup.py build_tests # build pygobject and tests
+ py.test-3 tests/test_gi.py # run tests in test_gi.py only
+
+ docs/devguide/building_testing.rst | 6 ++
+ setup.py | 10 +--
+ tests/Makefile.am | 8 ++-
+ tests/__init__.py | 102 ++++++++++++++++++++++++++
+ tests/helper.py | 4 +-
+ tests/runtests.py | 143
+ +++++++------------------------------
+ tests/test_atoms.py | 4 +-
+ tests/test_cairo.py | 6 +-
+ tests/test_docstring.py | 2 +
+ tests/test_error.py | 6 +-
+ tests/test_everything.py | 6 +-
+ tests/test_fields.py | 2 +
+ tests/test_gdbus.py | 2 +
+ tests/test_generictreemodel.py | 5 +-
+ tests/test_gi.py | 6 +-
+ tests/test_gio.py | 4 +-
+ tests/test_glib.py | 2 +
+ tests/test_gobject.py | 8 +--
+ tests/test_gtype.py | 2 +
+ tests/test_import_machinery.py | 2 +
+ tests/test_interface.py | 4 +-
+ tests/test_internal_api.py | 10 ++-
+ tests/test_iochannel.py | 6 +-
+ tests/test_mainloop.py | 2 +
+ tests/test_object_marshaling.py | 2 +
+ tests/test_option.py | 2 +
+ tests/test_ossig.py | 2 +
+ tests/test_overrides_gdk.py | 4 +-
+ tests/test_overrides_glib.py | 4 +-
+ tests/test_overrides_gtk.py | 4 +-
+ tests/test_overrides_pango.py | 2 +
+ tests/test_properties.py | 10 ++-
+ tests/test_pygtkcompat.py | 4 +-
+ tests/test_repository.py | 8 +--
+ tests/test_resulttuple.py | 2 +
+ tests/test_signal.py | 13 ++--
+ tests/test_source.py | 8 +--
+ tests/test_subprocess.py | 2 +
+ tests/test_thread.py | 5 +-
+ tests/test_typeclass.py | 6 +-
+ tests/test_unknown.py | 5 +-
+ tests/testmodule.py | 2 +
+ 42 files changed, 244 insertions(+), 193 deletions(-)
+
+commit 21cee6cc4fbc7fb1a28a15840924b0da52b49fca
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Sun Feb 11 16:08:18 2018 +0100
+
+ tests: Make patching in pygtkcompat reversible
+
+ Record all the attribute and sys.modules changes and add an API
+ for reverting them after tests are completed.
+
+ This allows us to run the pygtkcompat tests in the same test process
+ as other tests.
+
+ pygtkcompat/pygtkcompat.py | 273
+ ++++++++++++---------
+ setup.py | 7 -
+ tests/Makefile.am | 4 +-
+ tests/runtests.py | 2 +-
+ .../{compat_test_pygtk.py => test_pygtkcompat.py} | 96 ++++++--
+ 5 files changed, 237 insertions(+), 145 deletions(-)
+
+commit 7f5aedb6e1f317b33a96d0c77641b95f182b2a47
+Author: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Sat Feb 10 13:31:23 2018 +0100
+
+ version bump
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
commit c65efcb0bb4a73c9fb1ffa10225795adc489a081
Author: Christoph Reiter <reiter.christoph@gmail.com>
Date: Sat Feb 10 13:22:17 2018 +0100
+3.27.4 - 2018-02-14
+-------------------
+
+* tests: Fix tests under Wayland. :issue:`163`
+* tests: Make it possible to use pytest directly.
+* Reverted transfer-none boxed copy changes (:mr:`10`) due to regressions in
+ gnome-music. :issue:`164` :mr:`23`
+
+
3.27.3 - 2018-02-10
-------------------
Metadata-Version: 1.0
Name: PyGObject
-Version: 3.27.3
+Version: 3.27.4
Summary: Python bindings for GObject Introspection
Home-page: https://pygobject.readthedocs.io
Author: James Henstridge
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for pygobject 3.27.3.
+# Generated by GNU Autoconf 2.69 for pygobject 3.27.4.
#
# 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.27.3'
-PACKAGE_STRING='pygobject 3.27.3'
+PACKAGE_VERSION='3.27.4'
+PACKAGE_STRING='pygobject 3.27.4'
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.27.3 to adapt to many kinds of systems.
+\`configure' configures pygobject 3.27.4 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.27.3:";;
+ short | recursive ) echo "Configuration of pygobject 3.27.4:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-pygobject configure 3.27.3
+pygobject configure 3.27.4
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.27.3, which was
+It was created by pygobject $as_me 3.27.4, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
PYGOBJECT_MINOR_VERSION=27
-$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"
# Define the identity of the package.
PACKAGE='pygobject'
- VERSION='3.27.3'
+ VERSION='3.27.4'
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.27.3, which was
+This file was extended by pygobject $as_me 3.27.4, 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.27.3
+pygobject config.status 3.27.4
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, 27)
-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 ...
# Build in-tree
python3 setup.py build_ext --inplace
+ # Build in-tree including tests
+ python3 setup.py build_tests
+
# Executing some code after the build
PYTHONPATH=. python3 foo.py
TEST_NAMES=test_gi.TestUtf8 python3 setup.py test
TEST_NAMES=test_gi.TestUtf8.test_utf8_full_return python3 setup.py test
+ # using pytest directly
+ py.test-3 tests/test_gi.py
+
# Running flake8 tests
python3 setup.py quality
:param GObject.SignalFlags flags: Signal flags
:param GObject.GType return_type: Return type
:param list arg_types: List of :class:`GObject.GType` argument types
- :param GObject.SignalAccumulator accumulator: Accumulator function
+ :param accumulator: Accumulator function
+ :type accumulator: :obj:`GObject.SignalAccumulator`
:param object accu_data: User data for the accumulator
py_type = _pygi_type_import_by_name ("GLib", "VariantType");
- py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE, 0);
+ /* Pass the string directly and force a boxed copy. This works because
+ * GVariantType is just a char pointer. */
+ py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string,
+ TRUE, /* copy_boxed */
+ 0); /* slice_allocated */
return py_variant;
}
def __init__(self, *args, **kwargs):
return super(Source, self).__init__()
- def __del__(self):
- if hasattr(self, '__pygi_custom_source'):
- self.unref()
-
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
if self._free_on_dealloc and self.g_type != TYPE_INVALID:
self.unset()
+ # We must call base class __del__() after unset.
+ super(Value, self).__del__()
+
def set_boxed(self, boxed):
# Workaround the introspection marshalers inability to know
# these methods should be marshaling boxed types. This is because
_pygi_marshal_to_py_array (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
GArray *array_;
PyObject *py_obj = NULL;
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;
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
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;
+ &item_arg);
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);
/* 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;
+ 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,
static void
_pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
- gpointer cleanup_data,
+ PyObject *dummy,
gpointer data,
gboolean was_processed)
{
}
if (sequence_cache->item_cache->to_py_cleanup != NULL) {
- GPtrArray *item_cleanups = (GPtrArray *) cleanup_data;
gsize i;
guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
- PyGIMarshalToPyCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
+ PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
for (i = 0; i < len; i++) {
cleanup_func (state,
sequence_cache->item_cache,
- g_ptr_array_index(item_cleanups, i),
+ NULL,
(array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
was_processed);
}
- g_ptr_array_unref (item_cleanups);
}
if (array_ != NULL)
_pygi_marshal_to_py_void (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
if (arg_cache->is_pointer) {
return PyLong_FromVoidPtr (arg->v_pointer);
_pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
return _pygi_marshal_to_py_basic_type (arg,
arg_cache->type_tag,
static void
_pygi_marshal_cleanup_to_py_utf8 (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
- gpointer cleanup_data,
+ PyObject *dummy,
gpointer data,
gboolean was_processed)
{
PyObject *_pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data);
+ GIArgument *arg);
PyGIArgCache *pygi_arg_basic_type_new_from_info (GITypeInfo *type_info,
GIArgInfo *arg_info, /* may be null */
if ( ( (PyGBoxed *) self)->free_on_dealloc && boxed != NULL) {
if (self->slice_allocated) {
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, boxed);
goto out;
}
- self = (PyGIBoxed *) _pygi_boxed_new (type, boxed, TRUE, size);
+ self = (PyGIBoxed *) _pygi_boxed_new (type, boxed, FALSE, size);
if (self == NULL) {
g_slice_free1 (size, boxed);
goto out;
PYGLIB_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed);
PyObject *
-_pygi_boxed_new (PyTypeObject *type,
+_pygi_boxed_new (PyTypeObject *pytype,
gpointer boxed,
- gboolean free_on_dealloc,
+ gboolean copy_boxed,
gsize allocated_slice)
{
PyGIBoxed *self;
+ GType gtype;
if (!boxed) {
Py_RETURN_NONE;
}
- if (!PyType_IsSubtype (type, &PyGIBoxed_Type)) {
+ if (!PyType_IsSubtype (pytype, &PyGIBoxed_Type)) {
PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Boxed");
return NULL;
}
- self = (PyGIBoxed *) type->tp_alloc (type, 0);
+ gtype = pyg_type_from_object ((PyObject *)pytype);
+
+ /* Boxed objects with slice allocation means they come from caller allocated
+ * out arguments. In this case copy_boxed does not make sense because we
+ * already own the slice allocated memory and we should be receiving full
+ * ownership transfer. */
+ if (copy_boxed) {
+ g_assert (allocated_slice == 0);
+ boxed = g_boxed_copy (gtype, boxed);
+ }
+
+ self = (PyGIBoxed *) pytype->tp_alloc (pytype, 0);
if (self == NULL) {
return NULL;
}
- ( (PyGBoxed *) self)->gtype = pyg_type_from_object ( (PyObject *) type);
- ( (PyGBoxed *) self)->free_on_dealloc = free_on_dealloc;
+ /* We always free on dealloc because we always own the memory due to:
+ * 1) copy_boxed == TRUE
+ * 2) allocated_slice > 0
+ * 3) otherwise the mode is assumed "transfer everything".
+ */
+ ((PyGBoxed *)self)->free_on_dealloc = TRUE;
+ ((PyGBoxed *)self)->gtype = gtype;
pyg_boxed_set_ptr (self, boxed);
+
if (allocated_slice > 0) {
self->size = allocated_slice;
self->slice_allocated = TRUE;
_pygi_boxed_copy_in_place (PyGIBoxed *self)
{
PyGBoxed *pygboxed = (PyGBoxed *)self;
- gpointer ptr = pyg_boxed_get_ptr (self);
- gpointer copy = NULL;
-
- if (ptr)
- copy = g_boxed_copy (pygboxed->gtype, ptr);
+ gpointer copy = g_boxed_copy (pygboxed->gtype, pyg_boxed_get_ptr (self));
boxed_del (self);
pyg_boxed_set_ptr (pygboxed, copy);
extern PyTypeObject PyGIBoxed_Type;
-PyObject * _pygi_boxed_new (PyTypeObject *type,
+PyObject * _pygi_boxed_new (PyTypeObject *pytype,
gpointer boxed,
- gboolean free_on_dealloc,
+ gboolean copy_boxed,
gsize allocated_slice);
void * _pygi_boxed_alloc (GIBaseInfo *info,
typedef PyObject *(*PyGIMarshalToPyFunc) (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data);
+ GIArgument *arg);
typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
- PyObject *py_arg,
+ PyObject *py_arg, /* always NULL for to_py cleanup */
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
PyGIMarshalToPyFunc to_py_marshaller;
PyGIMarshalCleanupFunc from_py_cleanup;
- PyGIMarshalToPyCleanupFunc to_py_cleanup;
+ PyGIMarshalCleanupFunc to_py_cleanup;
GDestroyNotify destroy_notify;
} else if (arg_cache->meta_type != PYGI_META_ARG_TYPE_PARENT) {
continue;
} else {
- 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;
+ &state->args[i].arg_value);
if (value == NULL) {
pygi_marshal_cleanup_args_to_py_parameter_fail (state,
_pygi_marshal_to_py_interface_callback (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *arg_cleanup_data)
+ GIArgument *arg)
{
PyGICallbackCache *callback_cache = (PyGICallbackCache *) arg_cache;
gssize user_data_index;
_pygi_marshal_to_py_interface_enum (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
PyObject *py_obj = NULL;
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
_pygi_marshal_to_py_interface_flags (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
PyObject *py_obj = NULL;
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
_pygi_marshal_to_py_gerror (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
GError *error = arg->v_pointer;
PyObject *py_obj = NULL;
_pygi_marshal_to_py_ghash (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
GHashTable *hash_;
GHashTableIter hash_table_iter;
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;
py_key = key_to_py_marshaller ( state,
callable_cache,
key_arg_cache,
- &key_arg,
- &key_cleanup_data);
+ &key_arg);
if (py_key == NULL) {
Py_CLEAR (py_obj);
py_value = value_to_py_marshaller ( state,
callable_cache,
value_arg_cache,
- &value_arg,
- &value_cleanup_data);
+ &value_arg);
if (py_value == NULL) {
Py_CLEAR (py_obj);
static void
_pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
- gpointer cleanup_data,
+ PyObject *dummy,
gpointer data,
gboolean was_processed)
{
/* Holds from_py marshaler cleanup data. */
gpointer arg_cleanup_data;
- /* Holds to_py marshaler cleanup data. */
- gpointer to_py_arg_cleanup_data;
} PyGIInvokeArgState;
/* 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.
if (cache->return_cache) {
if (!cache->return_cache->is_skipped) {
- gpointer cleanup_data = NULL;
py_return = cache->return_cache->to_py_marshaller ( state,
cache,
cache->return_cache,
- &state->return_arg,
- &cleanup_data);
- state->to_py_return_arg_cleanup_data = cleanup_data;
+ &state->return_arg);
if (py_return == NULL) {
pygi_marshal_cleanup_args_return_fail (state,
cache);
}
} else {
if (cache->return_cache->transfer == GI_TRANSFER_EVERYTHING) {
- PyGIMarshalToPyCleanupFunc to_py_cleanup =
+ PyGIMarshalCleanupFunc to_py_cleanup =
cache->return_cache->to_py_cleanup;
if (to_py_cleanup != NULL)
} 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].arg_pointer.v_pointer,
- &cleanup_data);
- state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data = cleanup_data;
+ state->args[arg_cache->c_arg_index].arg_pointer.v_pointer);
if (py_out == NULL) {
pygi_marshal_cleanup_args_to_py_parameter_fail (state,
cache,
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].arg_pointer.v_pointer,
- &cleanup_data);
- state->args[arg_cache->c_arg_index].to_py_arg_cleanup_data = cleanup_data;
+ state->args[arg_cache->c_arg_index].arg_pointer.v_pointer);
if (py_obj == NULL) {
if (cache->has_return)
_pygi_marshal_to_py_glist (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
GList *list_;
gsize length;
gsize i;
- GPtrArray *item_cleanups;
PyGIMarshalToPyFunc item_to_py_marshaller;
PyGIArgCache *item_arg_cache;
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;
+ &item_arg);
if (py_item == NULL) {
Py_CLEAR (py_obj);
_PyGI_ERROR_PREFIX ("Item %zu: ", i);
- g_ptr_array_unref (item_cleanups);
return NULL;
}
_pygi_marshal_to_py_gslist (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
GSList *list_;
gsize length;
gsize i;
- GPtrArray *item_cleanups;
PyGIMarshalToPyFunc item_to_py_marshaller;
PyGIArgCache *item_arg_cache;
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);
+ &item_arg);
- g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
if (py_item == NULL) {
Py_CLEAR (py_obj);
_PyGI_ERROR_PREFIX ("Item %zu: ", i);
- g_ptr_array_unref (item_cleanups);
return NULL;
}
static void
_pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
- gpointer cleanup_data,
+ PyObject *dummy,
gpointer data,
gboolean was_processed)
{
- GPtrArray *item_cleanups = (GPtrArray *) cleanup_data;
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) {
- PyGIMarshalToPyCleanupFunc cleanup_func =
+ PyGIMarshalCleanupFunc 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),
+ NULL,
node->data,
was_processed);
node = node->next;
- i++;
}
}
g_assert_not_reached();
}
}
-
- g_ptr_array_unref (item_cleanups);
}
static void
PyGICallableCache *cache)
{
GSList *cache_item;
- guint i = 0;
-
/* clean up the return if available */
if (cache->return_cache != NULL) {
- PyGIMarshalToPyCleanupFunc cleanup_func = cache->return_cache->to_py_cleanup;
+ PyGIMarshalCleanupFunc 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,
+ NULL,
state->return_arg.v_pointer,
TRUE);
}
cache_item = cache->to_py_args;
while (cache_item) {
PyGIArgCache *arg_cache = (PyGIArgCache *) cache_item->data;
- PyGIMarshalToPyCleanupFunc cleanup_func = arg_cache->to_py_cleanup;
+ PyGIMarshalCleanupFunc 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,
+ NULL,
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,
+ NULL,
data,
TRUE);
}
- i++;
cache_item = cache_item->next;
}
}
_pygi_marshal_to_py_called_from_c_interface_object_cache_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
return pygi_arg_gobject_to_py_called_from_c (arg, arg_cache->transfer);
}
_pygi_marshal_to_py_called_from_py_interface_object_cache_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
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,
+ PyObject *dummy,
gpointer data,
gboolean was_processed)
{
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);
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;
}
- py_value = _pygi_argument_to_object (&arg, type_info, transfer);
+ py_value = _pygi_argument_to_object (&arg, type_info, GI_TRANSFER_NOTHING);
if (free_array) {
g_array_free (arg.v_pointer, FALSE);
source = (PyGRealSource*) g_source_new (&pyg_source_funcs, sizeof (PyGRealSource));
py_type = _pygi_type_import_by_name ("GLib", "Source");
- /* g_source_new uses malloc, not slices */
- source->obj = _pygi_boxed_new ( (PyTypeObject *) py_type, source, FALSE, 0);
+ /* Full ownership transfer of the source, this will be free'd with g_boxed_free. */
+ source->obj = _pygi_boxed_new ( (PyTypeObject *) py_type, source,
+ FALSE, /* copy_boxed */
+ 0); /* slice_allocated */
return source->obj;
}
arg->v_pointer);
} else if (g_type_is_a (g_type, G_TYPE_BOXED)) {
if (py_type) {
+ /* Force a boxed copy if we are not transfered ownership and the
+ * memory is not caller allocated. */
py_obj = _pygi_boxed_new ((PyTypeObject *) py_type,
arg->v_pointer,
- transfer == GI_TRANSFER_EVERYTHING || is_allocated,
+ transfer == GI_TRANSFER_NOTHING && !is_allocated,
is_allocated ?
g_struct_info_get_size(interface_info) : 0);
}
arg_struct_to_py_marshal_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg,
- gpointer *cleanup_data)
+ GIArgument *arg)
{
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- PyObject *ret;
- ret = pygi_arg_struct_to_py_marshal (arg,
- iface_cache->interface_info,
- iface_cache->g_type,
- iface_cache->py_type,
- arg_cache->transfer,
- arg_cache->is_caller_allocates,
- iface_cache->is_foreign);
+ return pygi_arg_struct_to_py_marshal (arg,
+ iface_cache->interface_info,
+ iface_cache->g_type,
+ iface_cache->py_type,
+ arg_cache->transfer,
+ arg_cache->is_caller_allocates,
+ iface_cache->is_foreign);
+}
+
+static PyObject *
+arg_boxed_to_py_marshal_pass_by_ref (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg)
+{
+ PyObject *py_obj = NULL;
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- *cleanup_data = ret;
+ if (arg->v_pointer == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
+ if (iface_cache->py_type) {
+ py_obj = _pygi_boxed_new ((PyTypeObject *) iface_cache->py_type,
+ arg->v_pointer,
+ FALSE, /* copy_boxed */
+ 0); /* slice_alloc */
+ ((PyGBoxed *)py_obj)->free_on_dealloc = FALSE;
+ }
+ } else {
+ PyErr_Format (PyExc_NotImplementedError,
+ "expected boxed type but got %s",
+ g_type_name (iface_cache->g_type));
+ }
- return ret;
+ return py_obj;
}
static void
arg_foreign_to_py_cleanup (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
- gpointer cleanup_data,
+ PyObject *dummy,
gpointer data,
gboolean was_processed)
{
}
}
-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,
static void
arg_struct_to_py_setup (PyGIArgCache *arg_cache,
GIInterfaceInfo *iface_info,
- GITransfer transfer)
+ GITransfer transfer,
+ GIArgInfo *arg_info)
{
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ /* HACK to force GtkTreeModel:iter_next() and iter_previous() vfunc implementations
+ * to receive their Gtk.TreeIter argument as pass-by-reference. We create a new
+ * PyGIBoxed wrapper which does not copy the memory and also does not free it.
+ * This is needed to hack the noted vfunc implementations so they can continue
+ * working with bug https://bugzilla.gnome.org/show_bug.cgi?id=722899
+ * being fixed. This hack should be removed once GTK+ has fixed bug
+ * https://bugzilla.gnome.org/show_bug.cgi?id=734465
+ * and we've moved to a new major version.
+ */
+ if (arg_info && g_strcmp0 (iface_cache->type_name, "Gtk.TreeIter") == 0) {
+
+ /* GICallbackInfo */
+ GIBaseInfo *info = g_base_info_get_container (arg_info);
+ if (info && g_base_info_get_type (info) == GI_INFO_TYPE_CALLBACK &&
+ (g_strcmp0 (g_base_info_get_name (info), "iter_next") == 0 ||
+ g_strcmp0 (g_base_info_get_name (info), "iter_previous") == 0)) {
+
+ /* GITypeInfo */
+ info = g_base_info_get_container (info);
+ if (info && g_base_info_get_type (info) == GI_INFO_TYPE_TYPE &&
+ g_type_info_get_tag ((GITypeInfo *)info) == GI_TYPE_TAG_INTERFACE) {
+
+ /* GIFieldInfo */
+ info = g_base_info_get_container (info);
+ if (info && g_base_info_get_type (info) == GI_INFO_TYPE_FIELD) {
+
+ /* GIStructInfo */
+ info = g_base_info_get_container (info);
+ if (info && g_base_info_get_type (info) == GI_INFO_TYPE_STRUCT &&
+ g_strcmp0 (g_base_info_get_name (info), "TreeModelIface") == 0) {
+ arg_cache->to_py_marshaller = arg_boxed_to_py_marshal_pass_by_ref;
+ }
+ }
+ }
+ }
+ }
+
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 *
}
if (direction & PYGI_DIRECTION_TO_PYTHON) {
- arg_struct_to_py_setup (cache, iface_info, transfer);
+ arg_struct_to_py_setup (cache, iface_info, transfer, arg_info);
}
return cache;
from gi.repository import GObject
+_patches = []
+_module_patches = []
+_unset = object()
+_enabled_registry = {}
+
+
+def _patch(obj, name, new_value):
+ old_value = getattr(obj, name, _unset)
+ setattr(obj, name, new_value)
+ _patches.append((obj, name, old_value))
+
+
+def _patch_module(name, new_value):
+ old_value = sys.modules.get(name, _unset)
+ sys.modules[name] = new_value
+ _module_patches.append((name, old_value))
+
+
def _install_enums(module, dest=None, strip=''):
if dest is None:
dest = module
name = name.replace(modname + '_', '')
if strip and name.startswith(strip):
name = name[len(strip):]
- setattr(dest, name, enum)
+ _patch(dest, name, enum)
except TypeError:
continue
try:
# FIXME: this happens for some large flags which do not
# fit into a long on 32 bit systems
continue
- setattr(dest, name, flag)
+ _patch(dest, name, flag)
except TypeError:
continue
-_enabled_registry = {}
-
-
def _check_enabled(name, version=None):
"""Returns True in case it is already enabled"""
# gobject
from gi.repository import GLib
- sys.modules['glib'] = GLib
+ _patch_module('glib', GLib)
# gobject
from gi.repository import GObject
- sys.modules['gobject'] = GObject
+ _patch_module('gobject', GObject)
from gi import _propertyhelper
- sys.modules['gobject.propertyhelper'] = _propertyhelper
+ _patch_module('gobject.propertyhelper', _propertyhelper)
# gio
from gi.repository import Gio
- sys.modules['gio'] = Gio
+ _patch_module('gio', Gio)
-_unset = object()
+def _disable_all():
+ """Reverse all effects of the enable_xxx() calls except for
+ require_version() calls and imports.
+ """
+
+ _enabled_registry.clear()
+
+ for obj, name, old_value in reversed(_patches):
+ if old_value is _unset:
+ delattr(obj, name)
+ else:
+ # try if deleting is enough (for override proxies)
+ delattr(obj, name)
+ if getattr(obj, name, _unset) is not old_value:
+ setattr(obj, name, old_value)
+ del _patches[:]
+
+ for name, old_value in reversed(_module_patches):
+ if old_value is _unset:
+ del sys.modules[name]
+ else:
+ sys.modules[name] = old_value
+ del _module_patches[:]
+
+ reload(sys)
+ if sys.version_info < (3, 0):
+ sys.setdefaultencoding('ascii')
def enable_gtk(version='3.0'):
# atk
gi.require_version('Atk', '1.0')
from gi.repository import Atk
- sys.modules['atk'] = Atk
+ _patch_module('atk', Atk)
_install_enums(Atk)
# pango
gi.require_version('Pango', '1.0')
from gi.repository import Pango
- sys.modules['pango'] = Pango
+ _patch_module('pango', Pango)
_install_enums(Pango)
# pangocairo
gi.require_version('PangoCairo', '1.0')
from gi.repository import PangoCairo
- sys.modules['pangocairo'] = PangoCairo
+ _patch_module('pangocairo', PangoCairo)
# gdk
gi.require_version('Gdk', version)
gi.require_version('GdkPixbuf', '2.0')
from gi.repository import Gdk
from gi.repository import GdkPixbuf
- sys.modules['gtk.gdk'] = Gdk
+ _patch_module('gtk.gdk', Gdk)
_install_enums(Gdk)
_install_enums(GdkPixbuf, dest=Gdk)
- Gdk._2BUTTON_PRESS = 5
- Gdk.BUTTON_PRESS = 4
-
- Gdk.screen_get_default = Gdk.Screen.get_default
- Gdk.Pixbuf = GdkPixbuf.Pixbuf
- Gdk.PixbufLoader = GdkPixbuf.PixbufLoader.new_with_type
- Gdk.pixbuf_new_from_data = GdkPixbuf.Pixbuf.new_from_data
- Gdk.pixbuf_new_from_file = GdkPixbuf.Pixbuf.new_from_file
+ _patch(Gdk, "_2BUTTON_PRESS", 5)
+ _patch(Gdk, "BUTTON_PRESS", 4)
+
+ _patch(Gdk, "screen_get_default", Gdk.Screen.get_default)
+ _patch(Gdk, "Pixbuf", GdkPixbuf.Pixbuf)
+ _patch(Gdk, "PixbufLoader", GdkPixbuf.PixbufLoader.new_with_type)
+ _patch(Gdk, "pixbuf_new_from_data", GdkPixbuf.Pixbuf.new_from_data)
+ _patch(Gdk, "pixbuf_new_from_file", GdkPixbuf.Pixbuf.new_from_file)
try:
- Gdk.pixbuf_new_from_file_at_scale = GdkPixbuf.Pixbuf.new_from_file_at_scale
+ _patch(Gdk, "pixbuf_new_from_file_at_scale", GdkPixbuf.Pixbuf.new_from_file_at_scale)
except AttributeError:
pass
- Gdk.pixbuf_new_from_file_at_size = GdkPixbuf.Pixbuf.new_from_file_at_size
- Gdk.pixbuf_new_from_inline = GdkPixbuf.Pixbuf.new_from_inline
- Gdk.pixbuf_new_from_stream = GdkPixbuf.Pixbuf.new_from_stream
- Gdk.pixbuf_new_from_stream_at_scale = GdkPixbuf.Pixbuf.new_from_stream_at_scale
- Gdk.pixbuf_new_from_xpm_data = GdkPixbuf.Pixbuf.new_from_xpm_data
- Gdk.pixbuf_get_file_info = GdkPixbuf.Pixbuf.get_file_info
+ _patch(Gdk, "pixbuf_new_from_file_at_size", GdkPixbuf.Pixbuf.new_from_file_at_size)
+ _patch(Gdk, "pixbuf_new_from_inline", GdkPixbuf.Pixbuf.new_from_inline)
+ _patch(Gdk, "pixbuf_new_from_stream", GdkPixbuf.Pixbuf.new_from_stream)
+ _patch(Gdk, "pixbuf_new_from_stream_at_scale", GdkPixbuf.Pixbuf.new_from_stream_at_scale)
+ _patch(Gdk, "pixbuf_new_from_xpm_data", GdkPixbuf.Pixbuf.new_from_xpm_data)
+ _patch(Gdk, "pixbuf_get_file_info", GdkPixbuf.Pixbuf.get_file_info)
orig_get_formats = GdkPixbuf.Pixbuf.get_formats
result.append(make_dict(format_))
return result
- Gdk.pixbuf_get_formats = get_formats
+ _patch(Gdk, "pixbuf_get_formats", get_formats)
orig_get_frame_extents = Gdk.Window.get_frame_extents
except TypeError:
rect = orig_get_frame_extents(window)
return rect
- Gdk.Window.get_frame_extents = get_frame_extents
+ _patch(Gdk.Window, "get_frame_extents", get_frame_extents)
orig_get_origin = Gdk.Window.get_origin
def get_origin(self):
return orig_get_origin(self)[1:]
- Gdk.Window.get_origin = get_origin
+ _patch(Gdk.Window, "get_origin", get_origin)
- Gdk.screen_width = Gdk.Screen.width
- Gdk.screen_height = Gdk.Screen.height
+ _patch(Gdk, "screen_width", Gdk.Screen.width)
+ _patch(Gdk, "screen_height", Gdk.Screen.height)
orig_gdk_window_get_geometry = Gdk.Window.get_geometry
def gdk_window_get_geometry(window):
return orig_gdk_window_get_geometry(window) + (window.get_visual().get_best_depth(),)
- Gdk.Window.get_geometry = gdk_window_get_geometry
+ _patch(Gdk.Window, "get_geometry", gdk_window_get_geometry)
# gtk
gi.require_version('Gtk', version)
from gi.repository import Gtk
- sys.modules['gtk'] = Gtk
- Gtk.gdk = Gdk
+ _patch_module('gtk', Gtk)
+ _patch(Gtk, "gdk", Gdk)
- Gtk.pygtk_version = (2, 99, 0)
+ _patch(Gtk, "pygtk_version", (2, 99, 0))
- Gtk.gtk_version = (Gtk.MAJOR_VERSION,
- Gtk.MINOR_VERSION,
- Gtk.MICRO_VERSION)
+ _patch(Gtk, "gtk_version", (Gtk.MAJOR_VERSION,
+ Gtk.MINOR_VERSION,
+ Gtk.MICRO_VERSION))
_install_enums(Gtk)
# Action
def set_tool_item_type(menuaction, gtype):
warnings.warn('set_tool_item_type() is not supported',
gi.PyGIDeprecationWarning, stacklevel=2)
- Gtk.Action.set_tool_item_type = classmethod(set_tool_item_type)
+ _patch(Gtk.Action, "set_tool_item_type", classmethod(set_tool_item_type))
# Alignment
self.props.xscale = xscale
self.props.yscale = yscale
- Gtk.Alignment = Alignment
+ _patch(Gtk, "Alignment", Alignment)
# Box
def pack_end(self, child, expand=True, fill=True, padding=0):
orig_pack_end(self, child, expand, fill, padding)
- Gtk.Box.pack_end = pack_end
+ _patch(Gtk.Box, "pack_end", pack_end)
orig_pack_start = Gtk.Box.pack_start
def pack_start(self, child, expand=True, fill=True, padding=0):
orig_pack_start(self, child, expand, fill, padding)
- Gtk.Box.pack_start = pack_start
+ _patch(Gtk.Box, "pack_start", pack_start)
# TreeViewColumn
def tree_view_column_pack_end(self, cell, expand=True):
orig_tree_view_column_pack_end(self, cell, expand)
- Gtk.TreeViewColumn.pack_end = tree_view_column_pack_end
+ _patch(Gtk.TreeViewColumn, "pack_end", tree_view_column_pack_end)
orig_tree_view_column_pack_start = Gtk.TreeViewColumn.pack_start
def tree_view_column_pack_start(self, cell, expand=True):
orig_tree_view_column_pack_start(self, cell, expand)
- Gtk.TreeViewColumn.pack_start = tree_view_column_pack_start
+ _patch(Gtk.TreeViewColumn, "pack_start", tree_view_column_pack_start)
# CellLayout
def cell_pack_end(self, cell, expand=True):
orig_cell_pack_end(self, cell, expand)
- Gtk.CellLayout.pack_end = cell_pack_end
+ _patch(Gtk.CellLayout, "pack_end", cell_pack_end)
orig_cell_pack_start = Gtk.CellLayout.pack_start
def cell_pack_start(self, cell, expand=True):
orig_cell_pack_start(self, cell, expand)
- Gtk.CellLayout.pack_start = cell_pack_start
+ _patch(Gtk.CellLayout, "pack_start", cell_pack_start)
orig_set_cell_data_func = Gtk.CellLayout.set_cell_data_func
args = args[:-1]
return func(*args)
orig_set_cell_data_func(self, cell, callback, user_data)
- Gtk.CellLayout.set_cell_data_func = set_cell_data_func
+ _patch(Gtk.CellLayout, "set_cell_data_func", set_cell_data_func)
# CellRenderer
class GenericCellRenderer(Gtk.CellRenderer):
pass
- Gtk.GenericCellRenderer = GenericCellRenderer
+ _patch(Gtk, "GenericCellRenderer", GenericCellRenderer)
# ComboBox
args = args[:-1]
return func(*args)
orig_combo_row_separator_func(self, callback, user_data)
- Gtk.ComboBox.set_row_separator_func = combo_row_separator_func
+ _patch(Gtk.ComboBox, "set_row_separator_func", combo_row_separator_func)
# ComboBoxEntry
def get_text_column(self):
return self.get_entry_text_column()
- Gtk.ComboBoxEntry = ComboBoxEntry
+ _patch(Gtk, "ComboBoxEntry", ComboBoxEntry)
def combo_box_entry_new():
return Gtk.ComboBoxEntry()
- Gtk.combo_box_entry_new = combo_box_entry_new
+ _patch(Gtk, "combo_box_entry_new", combo_box_entry_new)
def combo_box_entry_new_with_model(model):
return Gtk.ComboBoxEntry(model=model)
- Gtk.combo_box_entry_new_with_model = combo_box_entry_new_with_model
+ _patch(Gtk, "combo_box_entry_new_with_model", combo_box_entry_new_with_model)
# Container
def install_child_property(container, flag, pspec):
warnings.warn('install_child_property() is not supported',
gi.PyGIDeprecationWarning, stacklevel=2)
- Gtk.Container.install_child_property = classmethod(install_child_property)
+ _patch(Gtk.Container, "install_child_property", classmethod(install_child_property))
def new_text():
combo = Gtk.ComboBox()
combo.set_model(model)
combo.set_entry_text_column(0)
return combo
- Gtk.combo_box_new_text = new_text
+ _patch(Gtk, "combo_box_new_text", new_text)
def append_text(self, text):
model = self.get_model()
model.append([text])
- Gtk.ComboBox.append_text = append_text
- Gtk.expander_new_with_mnemonic = Gtk.Expander.new_with_mnemonic
- Gtk.icon_theme_get_default = Gtk.IconTheme.get_default
- Gtk.image_new_from_pixbuf = Gtk.Image.new_from_pixbuf
- Gtk.image_new_from_stock = Gtk.Image.new_from_stock
- Gtk.image_new_from_animation = Gtk.Image.new_from_animation
- Gtk.image_new_from_icon_set = Gtk.Image.new_from_icon_set
- Gtk.image_new_from_file = Gtk.Image.new_from_file
- Gtk.settings_get_default = Gtk.Settings.get_default
- Gtk.window_set_default_icon = Gtk.Window.set_default_icon
+ _patch(Gtk.ComboBox, "append_text", append_text)
+ _patch(Gtk, "expander_new_with_mnemonic", Gtk.Expander.new_with_mnemonic)
+ _patch(Gtk, "icon_theme_get_default", Gtk.IconTheme.get_default)
+ _patch(Gtk, "image_new_from_pixbuf", Gtk.Image.new_from_pixbuf)
+ _patch(Gtk, "image_new_from_stock", Gtk.Image.new_from_stock)
+ _patch(Gtk, "image_new_from_animation", Gtk.Image.new_from_animation)
+ _patch(Gtk, "image_new_from_icon_set", Gtk.Image.new_from_icon_set)
+ _patch(Gtk, "image_new_from_file", Gtk.Image.new_from_file)
+ _patch(Gtk, "settings_get_default", Gtk.Settings.get_default)
+ _patch(Gtk, "window_set_default_icon", Gtk.Window.set_default_icon)
try:
- Gtk.clipboard_get = Gtk.Clipboard.get
+ _patch(Gtk, "clipboard_get", Gtk.Clipboard.get)
except AttributeError:
pass
# AccelGroup
- Gtk.AccelGroup.connect_group = Gtk.AccelGroup.connect
+ _patch(Gtk.AccelGroup, "connect_group", Gtk.AccelGroup.connect)
# StatusIcon
- Gtk.status_icon_position_menu = Gtk.StatusIcon.position_menu
- Gtk.StatusIcon.set_tooltip = Gtk.StatusIcon.set_tooltip_text
+ _patch(Gtk, "status_icon_position_menu", Gtk.StatusIcon.position_menu)
+ _patch(Gtk.StatusIcon, "set_tooltip", Gtk.StatusIcon.set_tooltip_text)
# Scale
class HScale(orig_HScale):
def __init__(self, adjustment=None):
orig_HScale.__init__(self, adjustment=adjustment)
- Gtk.HScale = HScale
+ _patch(Gtk, "HScale", HScale)
class VScale(orig_VScale):
def __init__(self, adjustment=None):
orig_VScale.__init__(self, adjustment=adjustment)
- Gtk.VScale = VScale
+ _patch(Gtk, "VScale", VScale)
- Gtk.stock_add = lambda items: None
+ _patch(Gtk, "stock_add", lambda items: None)
# Widget
- Gtk.Widget.window = property(fget=Gtk.Widget.get_window)
+ _patch(Gtk.Widget, "window", property(fget=Gtk.Widget.get_window))
- Gtk.widget_get_default_direction = Gtk.Widget.get_default_direction
+ _patch(Gtk, "widget_get_default_direction", Gtk.Widget.get_default_direction)
orig_size_request = Gtk.Widget.size_request
def size_request(widget):
self.width = req.width
UserList.__init__(self, [self.width, self.height])
return SizeRequest(orig_size_request(widget))
- Gtk.Widget.size_request = size_request
- Gtk.Widget.hide_all = Gtk.Widget.hide
+ _patch(Gtk.Widget, "size_request", size_request)
+ _patch(Gtk.Widget, "hide_all", Gtk.Widget.hide)
class BaseGetter(object):
def __init__(self, context):
class StyleDescriptor(object):
def __get__(self, instance, class_):
return Styles(instance)
- Gtk.Widget.style = StyleDescriptor()
+ _patch(Gtk.Widget, "style", StyleDescriptor())
# TextView
use_align=False, xalign=0.5, yalign=0.5):
return orig_text_view_scroll_to_mark(self, mark, within_margin,
use_align, xalign, yalign)
- Gtk.TextView.scroll_to_mark = text_view_scroll_to_mark
+ _patch(Gtk.TextView, "scroll_to_mark", text_view_scroll_to_mark)
# Window
return orig_set_geometry_hints(self, geometry_widget, geometry, geom_mask)
- Gtk.Window.set_geometry_hints = set_geometry_hints
- Gtk.window_list_toplevels = Gtk.Window.list_toplevels
- Gtk.window_set_default_icon_name = Gtk.Window.set_default_icon_name
+ _patch(Gtk.Window, "set_geometry_hints", set_geometry_hints)
+ _patch(Gtk, "window_list_toplevels", Gtk.Window.list_toplevels)
+ _patch(Gtk, "window_set_default_icon_name", Gtk.Window.set_default_icon_name)
# gtk.unixprint
class UnixPrint(object):
pass
unixprint = UnixPrint()
- sys.modules['gtkunixprint'] = unixprint
+ _patch_module('gtkunixprint', unixprint)
# gtk.keysyms
warnings.simplefilter('ignore', category=RuntimeWarning)
from gi.overrides import keysyms
- sys.modules['gtk.keysyms'] = keysyms
- Gtk.keysyms = keysyms
+ _patch_module('gtk.keysyms', keysyms)
+ _patch(Gtk, "keysyms", keysyms)
from . import generictreemodel
- Gtk.GenericTreeModel = generictreemodel.GenericTreeModel
+ _patch(Gtk, "GenericTreeModel", generictreemodel.GenericTreeModel)
def enable_vte():
gi.require_version('Vte', '0.0')
from gi.repository import Vte
- sys.modules['vte'] = Vte
+ _patch_module('vte', Vte)
def enable_poppler():
gi.require_version('Poppler', '0.18')
from gi.repository import Poppler
- sys.modules['poppler'] = Poppler
- Poppler.pypoppler_version = (1, 0, 0)
+ _patch_module('poppler', Poppler)
+
+ _patch(Poppler, "pypoppler_version", (1, 0, 0))
def enable_webkit(version='1.0'):
gi.require_version('WebKit', version)
from gi.repository import WebKit
- sys.modules['webkit'] = WebKit
- WebKit.WebView.get_web_inspector = WebKit.WebView.get_inspector
+ _patch_module('webkit', WebKit)
+
+ _patch(WebKit.WebView, "get_web_inspector", WebKit.WebView.get_inspector)
def enable_gudev():
gi.require_version('GUdev', '1.0')
from gi.repository import GUdev
- sys.modules['gudev'] = GUdev
+ _patch_module('gudev', GUdev)
def enable_gst():
gi.require_version('Gst', '0.10')
from gi.repository import Gst
- sys.modules['gst'] = Gst
+ _patch_module('gst', Gst)
_install_enums(Gst)
- Gst.registry_get_default = Gst.Registry.get_default
- Gst.element_register = Gst.Element.register
- Gst.element_factory_make = Gst.ElementFactory.make
- Gst.caps_new_any = Gst.Caps.new_any
- Gst.get_pygst_version = lambda: (0, 10, 19)
- Gst.get_gst_version = lambda: (0, 10, 40)
+
+ _patch(Gst, "registry_get_default", Gst.Registry.get_default)
+ _patch(Gst, "element_register", Gst.Element.register)
+ _patch(Gst, "element_factory_make", Gst.ElementFactory.make)
+ _patch(Gst, "caps_new_any", Gst.Caps.new_any)
+ _patch(Gst, "get_pygst_version", lambda: (0, 10, 19))
+ _patch(Gst, "get_gst_version", lambda: (0, 10, 40))
from gi.repository import GstInterfaces
- sys.modules['gst.interfaces'] = GstInterfaces
+ _patch_module('gst.interfaces', GstInterfaces)
_install_enums(GstInterfaces)
from gi.repository import GstAudio
- sys.modules['gst.audio'] = GstAudio
+ _patch_module('gst.audio', GstAudio)
_install_enums(GstAudio)
from gi.repository import GstVideo
- sys.modules['gst.video'] = GstVideo
+ _patch_module('gst.video', GstVideo)
_install_enums(GstVideo)
from gi.repository import GstBase
- sys.modules['gst.base'] = GstBase
+ _patch_module('gst.base', GstBase)
_install_enums(GstBase)
- Gst.BaseTransform = GstBase.BaseTransform
- Gst.BaseSink = GstBase.BaseSink
+ _patch(Gst, "BaseTransform", GstBase.BaseTransform)
+ _patch(Gst, "BaseSink", GstBase.BaseSink)
from gi.repository import GstController
- sys.modules['gst.controller'] = GstController
+ _patch_module('gst.controller', GstController)
_install_enums(GstController, dest=Gst)
from gi.repository import GstPbutils
- sys.modules['gst.pbutils'] = GstPbutils
+ _patch_module('gst.pbutils', GstPbutils)
_install_enums(GstPbutils)
gi.require_version('GooCanvas', '2.0')
from gi.repository import GooCanvas
- sys.modules['goocanvas'] = GooCanvas
+ _patch_module('goocanvas', GooCanvas)
_install_enums(GooCanvas, strip='GOO_CANVAS_')
- GooCanvas.ItemSimple = GooCanvas.CanvasItemSimple
- GooCanvas.Item = GooCanvas.CanvasItem
- GooCanvas.Image = GooCanvas.CanvasImage
- GooCanvas.Group = GooCanvas.CanvasGroup
- GooCanvas.Rect = GooCanvas.CanvasRect
+
+ _patch(GooCanvas, "ItemSimple", GooCanvas.CanvasItemSimple)
+ _patch(GooCanvas, "Item", GooCanvas.CanvasItem)
+ _patch(GooCanvas, "Image", GooCanvas.CanvasImage)
+ _patch(GooCanvas, "Group", GooCanvas.CanvasGroup)
+ _patch(GooCanvas, "Rect", GooCanvas.CanvasRect)
return message
-def _run_pkg_config(args):
- command = ["pkg-config"] + args
+def _run_pkg_config(args, _cache={}):
+ command = tuple(["pkg-config"] + args)
- try:
- return subprocess.check_output(command)
- except OSError as e:
- if e.errno == errno.ENOENT:
- raise SystemExit(
- "%r not found.\nArguments: %r" % (command[0], command))
- raise SystemExit(e)
- except subprocess.CalledProcessError as e:
- raise SystemExit(e)
+ if command not in _cache:
+ try:
+ result = subprocess.check_output(command)
+ except OSError as e:
+ if e.errno == errno.ENOENT:
+ raise SystemExit(
+ "%r not found.\nArguments: %r" % (command[0], command))
+ raise SystemExit(e)
+ except subprocess.CalledProcessError as e:
+ raise SystemExit(e)
+ else:
+ _cache[command] = result
+
+ return _cache[command]
def pkg_config_version_check(pkg, version):
return True
def run(self):
+ cmd = self.reinitialize_command("build_ext")
+ cmd.inplace = True
+ cmd.ensure_finalized()
+ cmd.run()
+
from distutils.ccompiler import new_compiler
from distutils.sysconfig import customize_compiler
pass
def run(self):
- cmd = self.reinitialize_command("build_ext")
- cmd.inplace = True
- cmd.ensure_finalized()
- cmd.run()
-
cmd = self.reinitialize_command("build_tests")
cmd.ensure_finalized()
cmd.run()
env = os.environ.copy()
env.pop("MSYSTEM", None)
+ env["MALLOC_PERTURB_"] = "85"
+ env["MALLOC_CHECK_"] = "3"
+ env["G_SLICE"] = "debug-blocks"
+
tests_dir = os.path.join(get_script_dir(), "tests")
- subprocess.check_call([
+ sys.exit(subprocess.call([
sys.executable,
os.path.join(tests_dir, "runtests.py"),
- ], env=env)
-
- if not env.get("TEST_NAMES"):
- env["TEST_NAMES"] = "compat_test_pygtk"
- subprocess.check_call([
- sys.executable,
- os.path.join(tests_dir, "runtests.py"),
- ], env=env)
+ ], env=env))
class quality(Command):
test_object_marshaling.py \
test_option.py \
test_properties.py \
+ test_pygtkcompat.py \
test_signal.py \
test_source.py \
test_subprocess.py \
test_docstring.py \
test_repository.py \
test_resulttuple.py \
+ test_unknown.py \
test_ossig.py \
- compat_test_pygtk.py \
+ __init__.py \
gi/__init__.py \
gi/overrides/__init__.py \
gi/overrides/Regress.py \
$(NULL)
clean-local:
- rm -f $(target_libraries) file.txt~
+ rm -f $(target_libraries) file.txt~;
+ @if [ "$(abs_builddir)" != "$(abs_srcdir)" ]; then \
+ rm -f __init__.py; \
+ fi;
# Unsetting MSYSTEM prevents msys2 from changing os.path.sep to "/"
RUN_TESTS_ENV_VARS= \
MSYSTEM= \
TESTS_BUILDDIR=$(builddir)
+# for non-srcdir builds
+$(abs_builddir)/__init__.py: $(abs_srcdir)/__init__.py
+ echo "__path__ = __import__('pkgutil').extend_path(__path__, __name__)" > $@
+
# pygtkcompat tests need to be run in a separate process as they
# clobber global name space
-check-local: $(target_libraries) $(test_typelibs) gschemas.compiled
- $(RUN_TESTS_ENV_VARS) $(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py; rc=$$?; \
- [ "$$rc" -ne 0 ] || [ -n "$$TEST_NAMES" ] || { TEST_NAMES=compat_test_pygtk $(RUN_TESTS_ENV_VARS) $(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py; rc=$$?; }; \
- exit $$rc
+check-local: $(target_libraries) $(test_typelibs) gschemas.compiled $(abs_builddir)/__init__.py
+ $(RUN_TESTS_ENV_VARS) $(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) $(srcdir)/runtests.py;
check.gdb:
EXEC_NAME="gdb --args" $(MAKE) check
test_object_marshaling.py \
test_option.py \
test_properties.py \
+ test_pygtkcompat.py \
test_signal.py \
test_source.py \
test_subprocess.py \
test_docstring.py \
test_repository.py \
test_resulttuple.py \
+ test_unknown.py \
test_ossig.py \
- compat_test_pygtk.py \
+ __init__.py \
gi/__init__.py \
gi/overrides/__init__.py \
gi/overrides/Regress.py \
test -L $@ || $(LN_S) .libs/$@ $@
clean-local:
- rm -f $(target_libraries) file.txt~
+ rm -f $(target_libraries) file.txt~;
+ @if [ "$(abs_builddir)" != "$(abs_srcdir)" ]; then \
+ rm -f __init__.py; \
+ fi;
+
+# for non-srcdir builds
+$(abs_builddir)/__init__.py: $(abs_srcdir)/__init__.py
+ echo "__path__ = __import__('pkgutil').extend_path(__path__, __name__)" > $@
# pygtkcompat tests need to be run in a separate process as they
# clobber global name space
-check-local: $(target_libraries) $(test_typelibs) gschemas.compiled
- $(RUN_TESTS_ENV_VARS) $(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py; rc=$$?; \
- [ "$$rc" -ne 0 ] || [ -n "$$TEST_NAMES" ] || { TEST_NAMES=compat_test_pygtk $(RUN_TESTS_ENV_VARS) $(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py; rc=$$?; }; \
- exit $$rc
+check-local: $(target_libraries) $(test_typelibs) gschemas.compiled $(abs_builddir)/__init__.py
+ $(RUN_TESTS_ENV_VARS) $(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) $(srcdir)/runtests.py;
check.gdb:
EXEC_NAME="gdb --args" $(MAKE) check
--- /dev/null
+from __future__ import absolute_import
+
+import os
+import sys
+import unittest
+import signal
+import subprocess
+import atexit
+
+
+def init_test_environ():
+ # this was renamed in Python 3, provide backwards compatible name
+ if sys.version_info[:2] == (2, 7):
+ unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
+
+ if sys.version_info[0] == 3:
+ unittest.TestCase.assertRegexpMatches = unittest.TestCase.assertRegex
+ unittest.TestCase.assertRaisesRegexp = unittest.TestCase.assertRaisesRegex
+
+ def dbus_launch_session():
+ if os.name == "nt" or sys.platform == "darwin":
+ return (-1, "")
+
+ try:
+ out = subprocess.check_output([
+ "dbus-daemon", "--session", "--fork", "--print-address=1",
+ "--print-pid=1"])
+ except (subprocess.CalledProcessError, OSError):
+ return (-1, "")
+ else:
+ if sys.version_info[0] == 3:
+ out = out.decode("utf-8")
+ addr, pid = out.splitlines()
+ return int(pid), addr
+
+ pid, addr = dbus_launch_session()
+ if pid >= 0:
+ os.environ["DBUS_SESSION_BUS_ADDRESS"] = addr
+ atexit.register(os.kill, pid, signal.SIGKILL)
+ else:
+ os.environ["DBUS_SESSION_BUS_ADDRESS"] = "."
+
+ tests_builddir = os.path.abspath(os.environ.get('TESTS_BUILDDIR', os.path.dirname(__file__)))
+ builddir = os.path.dirname(tests_builddir)
+ tests_srcdir = os.path.abspath(os.path.dirname(__file__))
+ srcdir = os.path.dirname(tests_srcdir)
+
+ sys.path.insert(0, tests_srcdir)
+ sys.path.insert(0, srcdir)
+ sys.path.insert(0, tests_builddir)
+ sys.path.insert(0, builddir)
+
+ # force untranslated messages, as we check for them in some tests
+ os.environ['LC_MESSAGES'] = 'C'
+ os.environ['G_DEBUG'] = 'fatal-warnings fatal-criticals'
+ if sys.platform == "darwin":
+ # gtk 3.22 has warnings and ciriticals on OS X, ignore for now
+ os.environ['G_DEBUG'] = ''
+
+ # make Gio able to find our gschemas.compiled in tests/. This needs to be set
+ # before importing Gio. Support a separate build tree, so look in build dir
+ # first.
+ os.environ['GSETTINGS_BACKEND'] = 'memory'
+ os.environ['GSETTINGS_SCHEMA_DIR'] = tests_builddir
+ os.environ['G_FILENAME_ENCODING'] = 'UTF-8'
+
+ import gi
+ gi.require_version("GIRepository", "2.0")
+ from gi.repository import GIRepository
+ repo = GIRepository.Repository.get_default()
+ repo.prepend_library_path(os.path.join(tests_builddir))
+ repo.prepend_library_path(os.path.join(tests_builddir, ".libs"))
+ repo.prepend_search_path(tests_builddir)
+
+ def try_require_version(namespace, version):
+ try:
+ gi.require_version(namespace, version)
+ except ValueError:
+ # prevent tests from running with the wrong version
+ sys.modules["gi.repository." + namespace] = None
+
+ # Optional
+ try_require_version("Gtk", os.environ.get("TEST_GTK_VERSION", "3.0"))
+ try_require_version("Gdk", os.environ.get("TEST_GTK_VERSION", "3.0"))
+ try_require_version("GdkPixbuf", "2.0")
+ try_require_version("Pango", "1.0")
+ try_require_version("PangoCairo", "1.0")
+ try_require_version("Atk", "1.0")
+
+ # Required
+ gi.require_versions({
+ "GIMarshallingTests": "1.0",
+ "Regress": "1.0",
+ "GLib": "2.0",
+ "Gio": "2.0",
+ "GObject": "2.0",
+ })
+
+
+init_test_environ()
+
+__path__ = __import__('pkgutil').extend_path(__path__, __name__)
+from __future__ import absolute_import
+
import contextlib
import unittest
import inspect
from gi import PyGIDeprecationWarning
from gi.repository import GLib
-from compathelper import StringIO
+from .compathelper import StringIO
ExceptionInfo = namedtuple("ExceptionInfo", ["type", "value", "traceback"])
#!/usr/bin/env python
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import os
-import glob
import sys
-import signal
-import unittest
-import subprocess
-import atexit
import pytest
-# this was renamed in Python 3, provide backwards compatible name
-if sys.version_info[:2] == (2, 7):
- unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
-
-if sys.version_info[0] == 3:
- unittest.TestCase.assertRegexpMatches = unittest.TestCase.assertRegex
- unittest.TestCase.assertRaisesRegexp = unittest.TestCase.assertRaisesRegex
-
-if '--help' in sys.argv:
- print("Usage: ./runtests.py <testfiles>")
- sys.exit(0)
+def main(argv):
+ if '--help' in argv:
+ print("Usage: ./runtests.py <testfiles>")
+ return
+ mydir = os.path.dirname(os.path.abspath(__file__))
-def dbus_launch_session():
- if os.name == "nt" or sys.platform == "darwin":
- return (-1, "")
-
- try:
- out = subprocess.check_output([
- "dbus-daemon", "--session", "--fork", "--print-address=1",
- "--print-pid=1"])
- except (subprocess.CalledProcessError, OSError):
- return (-1, "")
+ if 'TEST_NAMES' in os.environ:
+ names = os.environ['TEST_NAMES'].split()
+ elif 'TEST_FILES' in os.environ:
+ names = []
+ for filename in os.environ['TEST_FILES'].split():
+ names.append(filename[:-3])
+ elif len(argv) > 1:
+ names = []
+ for filename in argv[1:]:
+ names.append(filename.replace('.py', ''))
else:
- if sys.version_info[0] == 3:
- out = out.decode("utf-8")
- addr, pid = out.splitlines()
- return int(pid), addr
-
-
-pid, addr = dbus_launch_session()
-if pid >= 0:
- os.environ["DBUS_SESSION_BUS_ADDRESS"] = addr
- atexit.register(os.kill, pid, signal.SIGKILL)
-else:
- os.environ["DBUS_SESSION_BUS_ADDRESS"] = "."
-
-mydir = os.path.dirname(os.path.abspath(__file__))
-tests_builddir = os.path.abspath(os.environ.get('TESTS_BUILDDIR', os.path.dirname(__file__)))
-builddir = os.path.dirname(tests_builddir)
-tests_srcdir = os.path.abspath(os.path.dirname(__file__))
-srcdir = os.path.dirname(tests_srcdir)
-
-sys.path.insert(0, tests_srcdir)
-sys.path.insert(0, srcdir)
-sys.path.insert(0, tests_builddir)
-sys.path.insert(0, builddir)
-
-# force untranslated messages, as we check for them in some tests
-os.environ['LC_MESSAGES'] = 'C'
-os.environ['G_DEBUG'] = 'fatal-warnings fatal-criticals'
-if sys.platform == "darwin":
- # gtk 3.22 has warnings and ciriticals on OS X, ignore for now
- os.environ['G_DEBUG'] = ''
-
-# make Gio able to find our gschemas.compiled in tests/. This needs to be set
-# before importing Gio. Support a separate build tree, so look in build dir
-# first.
-os.environ['GSETTINGS_BACKEND'] = 'memory'
-os.environ['GSETTINGS_SCHEMA_DIR'] = tests_builddir
-os.environ['G_FILENAME_ENCODING'] = 'UTF-8'
-
-import gi
-gi.require_version("GIRepository", "2.0")
-from gi.repository import GIRepository
-repo = GIRepository.Repository.get_default()
-repo.prepend_library_path(os.path.join(tests_builddir))
-repo.prepend_library_path(os.path.join(tests_builddir, ".libs"))
-repo.prepend_search_path(tests_builddir)
-
-
-def try_require_version(namespace, version):
- try:
- gi.require_version(namespace, version)
- except ValueError:
- # prevent tests from running with the wrong version
- sys.modules["gi.repository." + namespace] = None
-
-
-# Optional
-try_require_version("Gtk", os.environ.get("TEST_GTK_VERSION", "3.0"))
-try_require_version("Gdk", os.environ.get("TEST_GTK_VERSION", "3.0"))
-try_require_version("GdkPixbuf", "2.0")
-try_require_version("Pango", "1.0")
-try_require_version("PangoCairo", "1.0")
-try_require_version("Atk", "1.0")
-
-# Required
-gi.require_versions({
- "GIMarshallingTests": "1.0",
- "Regress": "1.0",
- "GLib": "2.0",
- "Gio": "2.0",
- "GObject": "2.0",
-})
-
-# Load tests.
-if 'TEST_NAMES' in os.environ:
- names = os.environ['TEST_NAMES'].split()
-elif 'TEST_FILES' in os.environ:
- names = []
- for filename in os.environ['TEST_FILES'].split():
- names.append(filename[:-3])
-elif len(sys.argv) > 1:
- names = []
- for filename in sys.argv[1:]:
- names.append(filename.replace('.py', ''))
-else:
- names = []
- for filename in glob.iglob(os.path.join(mydir, 'test_*.py')):
- names.append(os.path.basename(filename)[:-3])
+ return pytest.main([mydir])
+ def unittest_to_pytest_name(name):
+ parts = name.split(".")
+ parts[0] = os.path.join(mydir, parts[0] + ".py")
+ return "::".join(parts)
-def unittest_to_pytest_name(name):
- parts = name.split(".")
- parts[0] = os.path.join(mydir, parts[0] + ".py")
- return "::".join(parts)
+ return pytest.main([unittest_to_pytest_name(n) for n in names])
-sys.exit(pytest.main([unittest_to_pytest_name(n) for n in names]))
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
-import os
-import sys
+from __future__ import absolute_import
+
import unittest
try:
Atk = None
Gtk = None
-from helper import capture_glib_deprecation_warnings
+from .helper import capture_glib_deprecation_warnings
+
+
+def is_X11():
+ try:
+ from gi.repository import Gdk, GdkX11
+ except ImportError:
+ return False
+
+ display = Gdk.Display.get_default()
+ return isinstance(display, GdkX11.X11Display)
@unittest.skipUnless(Gdk, 'Gdk not available')
self.assertTrue(Gtk.targets_include_image([a_jpeg], False))
self.assertTrue(Gtk.targets_include_image([a_jpeg, a_plain], False))
- @unittest.skipIf(sys.platform == "darwin", "fails on OSX")
+ @unittest.skipUnless(is_X11(), "only on X11")
def test_out_array(self):
a_selection = Gdk.Atom.intern('my_clipboard', False)
clipboard = Gtk.Clipboard.get(a_selection)
self.assertFalse(None in names, names)
self.assertTrue('TEXT' in names, names)
- @unittest.skipIf(sys.platform == "darwin" or os.name == "nt",
- "fails on OSX/Windows")
+ @unittest.skipUnless(is_X11(), "only on X11")
@unittest.skipIf(not Gdk or Gdk._version == "4.0", "not in gdk4")
def test_out_glist(self):
display = Gdk.Display.get_default()
# coding=utf-8
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import unittest
import gi
result = self.pass_object_through_signal(pattern, self.tester.sig_pattern)
self.assertTrue(isinstance(result, cairo.Pattern))
self.assertTrue(isinstance(result, cairo.SolidPattern))
-
-
-if __name__ == '__main__':
- unittest.main()
+from __future__ import absolute_import
+
import unittest
import gi.docstring
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
+from __future__ import absolute_import
+
import unittest
from gi.repository import GLib
error1 = GLib.Error.new_literal(1, "error", 1)
GIMarshallingTests.compare_two_gerrors_in_gvalue(error, error1)
-
-
-if __name__ == '__main__':
- unittest.main()
# coding=utf-8
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import unittest
import traceback
import ctypes
except:
Gtk = None
-from compathelper import PY3
-from helper import capture_exceptions
+from .compathelper import PY3
+from .helper import capture_exceptions
if sys.version_info < (3, 0):
# -*- Mode: Python; py-indent-offset: 4 -*-
# coding=utf-8
+from __future__ import absolute_import
+
import math
import unittest
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import unittest
from gi.repository import GLib
has_dbus = True
+class TestDBusNodeInfo(unittest.TestCase):
+
+ def test_new_for_xml(self):
+ info = Gio.DBusNodeInfo.new_for_xml("""
+<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
+ 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
+<node>
+ <interface name='org.freedesktop.DBus.Introspectable'>
+ <method name='Introspect'>
+ <arg name='data' direction='out' type='s'/>
+ </method>
+ </interface>
+</node>
+""")
+
+ interfaces = info.interfaces
+ del info
+ assert len(interfaces) == 1
+ assert interfaces[0].name == "org.freedesktop.DBus.Introspectable"
+ methods = interfaces[0].methods
+ del interfaces
+ assert len(methods) == 1
+ assert methods[0].name == "Introspect"
+ out_args = methods[0].out_args
+ assert len(out_args)
+ del methods
+ assert out_args[0].name == "data"
+
+
@unittest.skipUnless(has_dbus, "no dbus running")
class TestGDBusClient(unittest.TestCase):
def setUp(self):
# 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 absolute_import
# system
import gc
with ExceptHook(NotImplementedError):
res = self.model.iter_parent(child)
self.assertEqual(res, None)
-
-
-if __name__ == '__main__':
- unittest.main()
# coding=utf-8
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import sys
import unittest
from gi.repository import GIMarshallingTests
-from compathelper import PY2, PY3
-from helper import capture_exceptions
+from .compathelper import PY2, PY3
+from .helper import capture_exceptions
CONSTANT_UTF8 = "const ♥ utf8"
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import os
import unittest
import warnings
from gi import PyGIWarning
from gi.repository import GLib, Gio
-from helper import ignore_gi_deprecation_warnings
+from .helper import ignore_gi_deprecation_warnings
class TestGio(unittest.TestCase):
# -*- Mode: Python -*-
# encoding: UTF-8
+from __future__ import absolute_import
+
import os
import sys
import unittest
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import sys
import gc
import unittest
from gi.module import get_introspection_module
from gi import _gi
-import testhelper
+from . import testhelper
class TestGObjectAPI(unittest.TestCase):
value = GObject.Value(GLib.Error)
self.assertEqual(value.g_type, GObject.type_from_name('GError'))
self.assertEqual(value.get_value(), None)
-
-
-if __name__ == '__main__':
- unittest.main()
+from __future__ import absolute_import
+
import unittest
from gi.repository import GObject
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import sys
import unittest
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import unittest
from gi.repository import GObject
-import testhelper
+from . import testhelper
GUnknown = GObject.type_from_name("TestUnknown")
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import unittest
from gi.repository import GLib, GObject
-import testhelper
-import testmodule
+from . import testhelper
+from . import testmodule
class TestObject(unittest.TestCase):
def test_no_gerror(self):
callable_ = lambda: GLib.file_get_contents(__file__)
self.assertEqual(testhelper.test_gerror_exception(callable_), None)
-
-
-if __name__ == '__main__':
- unittest.main()
# -*- Mode: Python -*-
# encoding: UTF-8
+from __future__ import absolute_import
+
import os
import unittest
import tempfile
self.assertEqual(GLib.IOFlags.NONBLOCK, GLib.IO_FLAG_NONBLOCK)
self.assertEqual(GLib.IOFlags.IS_SEEKABLE, GLib.IO_FLAG_IS_SEEKABLE)
self.assertEqual(GLib.IOStatus.NORMAL, GLib.IO_STATUS_NORMAL)
-
-
-if __name__ == '__main__':
- unittest.main()
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import os
import sys
import select
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import unittest
import weakref
import gc
#!/usr/bin/env python
+from __future__ import absolute_import
+
import unittest
import sys
# 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 absolute_import
+
import os
import signal
import unittest
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import os
import sys
import unittest
Gdk = None
Gdk_version = None
-from helper import capture_glib_deprecation_warnings
+from .helper import capture_glib_deprecation_warnings
@unittest.skipUnless(Gdk, 'Gdk not available')
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import gc
import unittest
import gi
from gi.repository import GLib
-from compathelper import _long
+from .compathelper import _long
class TestGVariant(unittest.TestCase):
# coding: UTF-8
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import contextlib
import unittest
import time
import sys
import warnings
-from helper import ignore_gi_deprecation_warnings, capture_glib_warnings
+from .helper import ignore_gi_deprecation_warnings, capture_glib_warnings
import gi.overrides
import gi.types
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import unittest
try:
# coding=utf-8
+from __future__ import absolute_import
+
import os
import gc
import sys
from gi.repository import Regress
from gi import _propertyhelper as propertyhelper
-from compathelper import _long
-from helper import capture_glib_warnings, capture_output
+from .compathelper import _long
+from .helper import capture_glib_warnings, capture_output
class PropertyObject(GObject.GObject):
def set_prop(self, obj, name, value):
obj.set_property(name, value)
-
-
-if __name__ == '__main__':
- unittest.main()
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
+from __future__ import absolute_import
+
import unittest
import base64
+import pygtkcompat
+from pygtkcompat.pygtkcompat import _disable_all as disable_all
+
+from .helper import capture_gi_deprecation_warnings, capture_glib_warnings
+
try:
- from gi.repository import Gtk
- from gi.repository import Pango
- from gi.repository import Atk
- from gi.repository import Gdk
- (Atk, Gtk, Pango) # pyflakes
-
- import pygtkcompat
-
- pygtkcompat.enable()
- pygtkcompat.enable_gtk(version=Gtk._version)
-
- import atk
- import pango
- import pangocairo
- import gtk
- import gtk.gdk
-except (ValueError, ImportError):
+ from gi.repository import Gtk, Gdk
+except ImportError:
Gtk = None
+else:
+ if Gtk._version != "3.0":
+ Gtk = None
+
+
+class TestGlibCompat(unittest.TestCase):
+
+ def setUp(self):
+ pygtkcompat.enable()
-from helper import capture_gi_deprecation_warnings, capture_glib_warnings
+ def tearDown(self):
+ disable_all()
+
+ def test_import(self):
+ import glib
+ import gio
+ glib, gio
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestMultipleEnable(unittest.TestCase):
+ def tearDown(self):
+ disable_all()
+
def test_main(self):
pygtkcompat.enable()
pygtkcompat.enable()
def test_gtk(self):
pygtkcompat.enable_gtk("3.0")
pygtkcompat.enable_gtk("3.0")
+ import gtk
# https://bugzilla.gnome.org/show_bug.cgi?id=759009
w = gtk.Window()
self.assertEqual(len(w.window.get_origin()), 2)
w.destroy()
+ def test_gtk_no_4(self):
+ self.assertRaises(ValueError, pygtkcompat.enable_gtk, version='4.0')
+
def test_gtk_version_conflict(self):
+ pygtkcompat.enable_gtk("3.0")
self.assertRaises(ValueError, pygtkcompat.enable_gtk, version='2.0')
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestATKCompat(unittest.TestCase):
+
+ def setUp(self):
+ pygtkcompat.enable_gtk("3.0")
+
+ def tearDown(self):
+ disable_all()
+
def test_object(self):
+ import atk
self.assertTrue(hasattr(atk, 'Object'))
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestPangoCompat(unittest.TestCase):
+
+ def setUp(self):
+ pygtkcompat.enable_gtk("3.0")
+
+ def tearDown(self):
+ disable_all()
+
def test_layout(self):
+ import pango
self.assertTrue(hasattr(pango, 'Layout'))
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestPangoCairoCompat(unittest.TestCase):
+
+ def setUp(self):
+ pygtkcompat.enable_gtk("3.0")
+
+ def tearDown(self):
+ disable_all()
+
def test_error_underline_path(self):
+ import pangocairo
self.assertTrue(hasattr(pangocairo, 'error_underline_path'))
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestGTKCompat(unittest.TestCase):
+
+ def setUp(self):
+ pygtkcompat.enable_gtk("3.0")
+
+ def tearDown(self):
+ disable_all()
+
def test_buttons(self):
- self.assertEqual(Gdk._2BUTTON_PRESS, 5)
- self.assertEqual(Gdk.BUTTON_PRESS, 4)
+ import gtk.gdk
+ self.assertEqual(gtk.gdk._2BUTTON_PRESS, 5)
+ self.assertEqual(gtk.gdk.BUTTON_PRESS, 4)
def test_enums(self):
+ import gtk
self.assertEqual(gtk.WINDOW_TOPLEVEL, Gtk.WindowType.TOPLEVEL)
self.assertEqual(gtk.PACK_START, Gtk.PackType.START)
def test_flags(self):
+ import gtk
self.assertEqual(gtk.EXPAND, Gtk.AttachOptions.EXPAND)
self.assertEqual(gtk.gdk.SHIFT_MASK, Gdk.ModifierType.SHIFT_MASK)
self.assertTrue(gtk.keysyms._0, Gdk.KEY_0)
def test_style(self):
+ import gtk
widget = gtk.Button()
with capture_gi_deprecation_warnings():
widget.get_style_context().set_state(gtk.STATE_NORMAL)
gtk.gdk.Color))
def test_alignment(self):
+ import gtk
# Creation of pygtk.Alignment causes hard warnings, ignore this in testing.
with capture_glib_warnings(allow_warnings=True):
a = gtk.Alignment()
self.assertEqual(a.props.yscale, 0.0)
def test_box(self):
+ import gtk
box = gtk.Box()
child = gtk.Button()
self.assertEqual(pack_type, gtk.PACK_END)
def test_combobox_entry(self):
+ import gtk
liststore = gtk.ListStore(int, str)
liststore.append((1, 'One'))
liststore.append((2, 'Two'))
self.assertEqual(combo.get_child().get_text(), 'One')
def test_size_request(self):
+ import gtk
box = gtk.Box()
with capture_gi_deprecation_warnings():
self.assertEqual(box.size_request(), [0, 0])
def test_pixbuf(self):
+ import gtk.gdk
gtk.gdk.Pixbuf()
def test_pixbuf_loader(self):
+ import gtk.gdk
# load a 1x1 pixel PNG from memory
data = base64.b64decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP4n8Dw'
'HwAGIAJf85Z3XgAAAABJRU5ErkJggg==')
self.assertEqual(pixbuf.get_height(), 1)
def test_pixbuf_formats(self):
+ import gtk.gdk
formats = gtk.gdk.pixbuf_get_formats()
self.assertEqual(type(formats[0]), dict)
self.assertTrue('name' in formats[0])
self.assertEqual(type(formats[0]['extensions']), list)
def test_gdk_window(self):
+ import gtk
w = gtk.Window()
w.realize()
origin = w.get_window().get_origin()
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
+from __future__ import absolute_import
+
import unittest
import collections
from gi.repository import GIMarshallingTests
from gi.repository import GIRepository as IntrospectedRepository
-from helper import capture_glib_warnings
+from .helper import capture_glib_warnings
def find_child_info(info, getter_name, name):
IntrospectedRepository.Argument.__info__ = 'not an info'
self.assertRaises(TypeError, IntrospectedRepository.Argument)
IntrospectedRepository.Argument.__info__ = old_info
-
-
-if __name__ == '__main__':
- unittest.main()
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
+from __future__ import absolute_import
+
import unittest
import pickle
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import gc
import unittest
import sys
from gi.repository import GObject, GLib, Regress, Gio
from gi import _signalhelper as signalhelper
-import testhelper
-from compathelper import _long
-from helper import capture_glib_warnings, capture_gi_deprecation_warnings
from gi.module import repository as repo
+from . import testhelper
+from .compathelper import _long
+from .helper import capture_glib_warnings, capture_gi_deprecation_warnings
+
class C(GObject.GObject):
__gsignals__ = {'my_signal': (GObject.SignalFlags.RUN_FIRST, None,
self.assertEqual(len(called), 1)
self.assertTrue(called[0].__grefcount__ > 0)
-
-
-if __name__ == '__main__':
- unittest.main()
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import sys
+import gc
import unittest
import warnings
from gi.repository import GLib
from gi import PyGIDeprecationWarning
-from helper import capture_glib_warnings
+from .helper import capture_glib_warnings
class Idle(GLib.Idle):
return s
s = f()
+ gc.collect()
self.assertTrue(s.is_destroyed())
def test_remove(self):
self.finalized = True
source = S()
- id = source.attach()
- print('source id:', id)
+ self.assertEqual(source.ref_count, 1)
+ source.attach()
+ self.assertEqual(source.ref_count, 2)
self.assertFalse(self.finalized)
self.assertFalse(source.is_destroyed())
pass
source.destroy()
+ self.assertEqual(source.ref_count, 1)
self.assertTrue(self.dispatched)
self.assertFalse(self.finalized)
self.assertTrue(source.is_destroyed())
GLib.idle_add(self.cb_with_data, data)
self.loop.run()
self.assertTrue(data['called'])
-
-
-if __name__ == '__main__':
- unittest.main()
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import sys
import os
import unittest
# -*- Mode: Python -*-
+from __future__ import absolute_import
+
import unittest
-import testhelper
from gi.repository import GLib
+from . import testhelper
+
class TestThread(unittest.TestCase):
def setUp(self):
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
+from __future__ import absolute_import
+
import unittest
from gi.repository import GObject
def test_find_child_property(self):
pspec = GIMarshallingTests.PropertiesObject.find_property('some-int')
self.assertEqual(pspec.name, 'some-int')
-
-
-if __name__ == '__main__':
- unittest.main()
--- /dev/null
+# -*- Mode: Python -*-
+
+from __future__ import absolute_import
+
+import unittest
+
+from gi.repository import GObject
+
+from . import testhelper
+
+
+TestInterface = GObject.GType.from_name('TestInterface')
+
+
+class TestUnknown(unittest.TestCase):
+ def test_unknown_interface(self):
+ obj = testhelper.get_unknown()
+ TestUnknownGType = GObject.GType.from_name('TestUnknown')
+ TestUnknown = GObject.new(TestUnknownGType).__class__
+ assert isinstance(obj, testhelper.Interface)
+ assert isinstance(obj, TestUnknown)
+
+ def test_property(self):
+ obj = testhelper.get_unknown()
+ self.assertEqual(obj.get_property('some-property'), None)
+ obj.set_property('some-property', 'foo')
+
+ def test_unknown_property(self):
+ obj = testhelper.get_unknown()
+ self.assertRaises(TypeError, obj.get_property, 'unknown')
+ self.assertRaises(TypeError, obj.set_property, 'unknown', '1')
+from __future__ import absolute_import
+
from gi.repository import GObject