summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.am23
-rw-r--r--tests/Makefile.in41
-rw-r--r--tests/compat_test_pygtk.py (renamed from tests/test_pygtkcompat.py)44
-rwxr-xr-xtests/runtests.py3
-rw-r--r--tests/test_atoms.py31
-rw-r--r--tests/test_everything.py405
-rw-r--r--tests/test_gi.py382
-rw-r--r--tests/test_glib.py186
-rw-r--r--tests/test_gobject.py152
-rw-r--r--tests/test_gtype.py53
-rw-r--r--tests/test_interface.py4
-rw-r--r--tests/test_iochannel.py424
-rw-r--r--tests/test_mainloop.py18
-rw-r--r--tests/test_option.py56
-rw-r--r--tests/test_overrides.py29
-rw-r--r--tests/test_overrides_gtk.py74
-rw-r--r--tests/test_properties.py124
-rw-r--r--tests/test_signal.py87
-rw-r--r--tests/test_source.py223
-rw-r--r--tests/test_subprocess.py133
-rw-r--r--tests/test_thread.py2
-rw-r--r--tests/test_uris.py16
-rw-r--r--tests/testhelpermodule.c3
23 files changed, 2234 insertions, 279 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7a619bf..a91c814 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,7 +8,7 @@ libgimarshallingtests_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS)
# This is a hack to make sure a shared library is built
libgimarshallingtests.la: $(libgimarshallingtests_la_OBJECTS) $(libgimarshallingtests_la_DEPENDENCIES)
- $(LINK) -rpath $(pkgpyexecdir) $(libgimarshallingtests_la_LDFLAGS) $(libgimarshallingtests_la_OBJECTS) $(libgimarhallingtests_la_LIBADD) $(LIBS)
+ $(AM_V_GEN) $(LINK) -rpath $(pkgpyexecdir) $(libgimarshallingtests_la_LDFLAGS) $(libgimarshallingtests_la_OBJECTS) $(libgimarhallingtests_la_LIBADD) $(LIBS)
GIMarshallingTests-1.0.gir: libgimarshallingtests.la Makefile
$(AM_V_GEN) g-ir-scanner --include=Gio-2.0 \
@@ -30,7 +30,7 @@ libregress_la_CFLAGS = $(GIO_CFLAGS) $(CAIRO_CFLAGS)
libregress_la_LDFLAGS = -module -avoid-version $(GIO_LIBS) $(CAIRO_LIBS)
libregress.la: $(libregress_la_OBJECTS) $(libregress_la_DEPENDENCIES)
- $(LINK) -rpath $(pkgpyexecdir) $(libregress_la_LDFLAGS) $(libregress_la_OBJECTS) $(libregress_la_LIBADD) $(LIBS)
+ $(AM_V_GEN) $(LINK) -rpath $(pkgpyexecdir) $(libregress_la_LDFLAGS) $(libregress_la_OBJECTS) $(libregress_la_LIBADD) $(LIBS)
# g-i doesn't ship these as shared libraries anymore; we build them here
Regress-1.0.gir: libregress.la Makefile
@@ -65,7 +65,7 @@ testhelper_la_SOURCES = \
# This is a hack to make sure a shared library is built
testhelper.la: $(testhelper_la_OBJECTS) $(testhelper_la_DEPENDENCIES)
- $(LINK) -rpath $(pkgpyexecdir) $(testhelper_la_LDFLAGS) $(testhelper_la_OBJECTS) $(testhelper_la_LIBADD) $(LIBS)
+ $(AM_V_GEN) $(LINK) -rpath $(pkgpyexecdir) $(testhelper_la_LDFLAGS) $(testhelper_la_OBJECTS) $(testhelper_la_LIBADD) $(LIBS)
.la.so:
@@ -86,7 +86,9 @@ EXTRA_DIST = \
org.gnome.test.gschema.xml \
test_glib.py \
test_gobject.py \
+ test_gtype.py \
test_interface.py \
+ test_iochannel.py \
test_mainloop.py \
test_option.py \
test_properties.py \
@@ -94,7 +96,6 @@ EXTRA_DIST = \
test_source.py \
test_subprocess.py \
test_thread.py \
- test_uris.py \
test_everything.py \
test_gi.py \
test_gdbus.py \
@@ -105,7 +106,7 @@ EXTRA_DIST = \
test_overrides_gdk.py \
test_overrides_gtk.py \
test_atoms.py \
- test_pygtkcompat.py \
+ compat_test_pygtk.py \
gi/__init__.py \
gi/overrides/__init__.py \
gi/overrides/Regress.py \
@@ -121,15 +122,21 @@ RUN_TESTS_ENV_VARS= \
GI_TYPELIB_PATH=$(builddir):$$GI_TYPELIB_PATH \
XDG_DATA_DIRS=$$XDG_DATA_DIRS:/usr/share \
MALLOC_PERTURB_=85 \
+ MALLOC_CHECK_=3 \
TESTS_BUILDDIR=$(builddir)
+# pygtkcompat tests need to be run in a separate process as they
+# clobber global name space
check-local: $(LTLIBRARIES:.la=.so) $(test_typelibs) gschemas.compiled
@echo " CHECK Pyflakes"
@if type pyflakes >/dev/null 2>&1; then pyflakes $(top_srcdir); else echo "skipped, pyflakes not installed"; fi
- @echo " CHECK PEP8"
- @if type pep8 >/dev/null 2>&1; then pep8 --ignore=E501,E123,E124 --repeat --show-source $(top_srcdir); else echo "skipped, pep8 not installed"; fi
+ @if test -z "$$SKIP_PEP8"; then \
+ echo " CHECK PEP8"; \
+ if type pep8 >/dev/null 2>&1; then pep8 --ignore=E501,E123,E124 --repeat --show-source $(top_srcdir); else echo "skipped, pep8 not installed"; fi; \
+ fi
export `$(DBUS_LAUNCH)` && \
- $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning $(srcdir)/runtests.py; rc=$$?; \
+ $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning -Werror::RuntimeWarning $(srcdir)/runtests.py; rc=$$?; \
+ [ "$$rc" -ne 0 ] || [ -n "$$TEST_NAMES" ] || { TEST_NAMES=compat_test_pygtk $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning -Werror::RuntimeWarning $(srcdir)/runtests.py; rc=$$?; }; \
kill $$DBUS_SESSION_BUS_PID; \
exit $$rc
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 9993ec7..60fc5cc 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -59,8 +59,10 @@ subdir = tests
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
- $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/python.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/jhflags.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/python.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -149,6 +151,9 @@ CAIRO_LIBS = @CAIRO_LIBS@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
+CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
+CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -166,6 +171,7 @@ EXEEXT = @EXEEXT@
FFI_CFLAGS = @FFI_CFLAGS@
FFI_LIBS = @FFI_LIBS@
FGREP = @FGREP@
+GENHTML = @GENHTML@
GIO_CFLAGS = @GIO_CFLAGS@
GIO_LIBS = @GIO_LIBS@
GI_CFLAGS = @GI_CFLAGS@
@@ -185,6 +191,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+LCOV = @LCOV@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBFFI_PC = @LIBFFI_PC@
@@ -194,7 +201,6 @@ LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
@@ -326,7 +332,9 @@ EXTRA_DIST = \
org.gnome.test.gschema.xml \
test_glib.py \
test_gobject.py \
+ test_gtype.py \
test_interface.py \
+ test_iochannel.py \
test_mainloop.py \
test_option.py \
test_properties.py \
@@ -334,7 +342,6 @@ EXTRA_DIST = \
test_source.py \
test_subprocess.py \
test_thread.py \
- test_uris.py \
test_everything.py \
test_gi.py \
test_gdbus.py \
@@ -345,7 +352,7 @@ EXTRA_DIST = \
test_overrides_gdk.py \
test_overrides_gtk.py \
test_atoms.py \
- test_pygtkcompat.py \
+ compat_test_pygtk.py \
gi/__init__.py \
gi/overrides/__init__.py \
gi/overrides/Regress.py \
@@ -358,13 +365,14 @@ RUN_TESTS_ENV_VARS = \
GI_TYPELIB_PATH=$(builddir):$$GI_TYPELIB_PATH \
XDG_DATA_DIRS=$$XDG_DATA_DIRS:/usr/share \
MALLOC_PERTURB_=85 \
+ MALLOC_CHECK_=3 \
TESTS_BUILDDIR=$(builddir)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .la .lo .o .obj .so
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@@ -389,9 +397,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
@@ -696,7 +704,7 @@ uninstall-am:
# This is a hack to make sure a shared library is built
libgimarshallingtests.la: $(libgimarshallingtests_la_OBJECTS) $(libgimarshallingtests_la_DEPENDENCIES)
- $(LINK) -rpath $(pkgpyexecdir) $(libgimarshallingtests_la_LDFLAGS) $(libgimarshallingtests_la_OBJECTS) $(libgimarhallingtests_la_LIBADD) $(LIBS)
+ $(AM_V_GEN) $(LINK) -rpath $(pkgpyexecdir) $(libgimarshallingtests_la_LDFLAGS) $(libgimarshallingtests_la_OBJECTS) $(libgimarhallingtests_la_LIBADD) $(LIBS)
GIMarshallingTests-1.0.gir: libgimarshallingtests.la Makefile
$(AM_V_GEN) g-ir-scanner --include=Gio-2.0 \
@@ -710,7 +718,7 @@ GIMarshallingTests-1.0.typelib: GIMarshallingTests-1.0.gir Makefile
$(AM_V_GEN) g-ir-compiler $< -o $@
@ENABLE_CAIRO_TRUE@libregress.la: $(libregress_la_OBJECTS) $(libregress_la_DEPENDENCIES)
-@ENABLE_CAIRO_TRUE@ $(LINK) -rpath $(pkgpyexecdir) $(libregress_la_LDFLAGS) $(libregress_la_OBJECTS) $(libregress_la_LIBADD) $(LIBS)
+@ENABLE_CAIRO_TRUE@ $(AM_V_GEN) $(LINK) -rpath $(pkgpyexecdir) $(libregress_la_LDFLAGS) $(libregress_la_OBJECTS) $(libregress_la_LIBADD) $(LIBS)
# g-i doesn't ship these as shared libraries anymore; we build them here
@ENABLE_CAIRO_TRUE@Regress-1.0.gir: libregress.la Makefile
@@ -729,7 +737,7 @@ gschemas.compiled: org.gnome.test.gschema.xml
# This is a hack to make sure a shared library is built
testhelper.la: $(testhelper_la_OBJECTS) $(testhelper_la_DEPENDENCIES)
- $(LINK) -rpath $(pkgpyexecdir) $(testhelper_la_LDFLAGS) $(testhelper_la_OBJECTS) $(testhelper_la_LIBADD) $(LIBS)
+ $(AM_V_GEN) $(LINK) -rpath $(pkgpyexecdir) $(testhelper_la_LDFLAGS) $(testhelper_la_OBJECTS) $(testhelper_la_LIBADD) $(LIBS)
.la.so:
test -L $@ || $(LN_S) .libs/$@ $@
@@ -739,13 +747,18 @@ all: $(LTLIBRARIES:.la=.so)
clean-local:
rm -f $(LTLIBRARIES:.la=.so) file.txt~
+# pygtkcompat tests need to be run in a separate process as they
+# clobber global name space
check-local: $(LTLIBRARIES:.la=.so) $(test_typelibs) gschemas.compiled
@echo " CHECK Pyflakes"
@if type pyflakes >/dev/null 2>&1; then pyflakes $(top_srcdir); else echo "skipped, pyflakes not installed"; fi
- @echo " CHECK PEP8"
- @if type pep8 >/dev/null 2>&1; then pep8 --ignore=E501,E123,E124 --repeat --show-source $(top_srcdir); else echo "skipped, pep8 not installed"; fi
+ @if test -z "$$SKIP_PEP8"; then \
+ echo " CHECK PEP8"; \
+ if type pep8 >/dev/null 2>&1; then pep8 --ignore=E501,E123,E124 --repeat --show-source $(top_srcdir); else echo "skipped, pep8 not installed"; fi; \
+ fi
export `$(DBUS_LAUNCH)` && \
- $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning $(srcdir)/runtests.py; rc=$$?; \
+ $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning -Werror::RuntimeWarning $(srcdir)/runtests.py; rc=$$?; \
+ [ "$$rc" -ne 0 ] || [ -n "$$TEST_NAMES" ] || { TEST_NAMES=compat_test_pygtk $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning -Werror::RuntimeWarning $(srcdir)/runtests.py; rc=$$?; }; \
kill $$DBUS_SESSION_BUS_PID; \
exit $$rc
diff --git a/tests/test_pygtkcompat.py b/tests/compat_test_pygtk.py
index 5fabf2a..10be6a3 100644
--- a/tests/test_pygtkcompat.py
+++ b/tests/compat_test_pygtk.py
@@ -12,10 +12,10 @@ try:
from gi.repository import Gtk
(Atk, Gtk, Pango) # pyflakes
- import gi.pygtkcompat
+ import pygtkcompat
- gi.pygtkcompat.enable()
- gi.pygtkcompat.enable_gtk(version='3.0')
+ pygtkcompat.enable()
+ pygtkcompat.enable_gtk(version='3.0')
import atk
import pango
@@ -28,54 +28,54 @@ except ImportError:
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestATKCompat(unittest.TestCase):
- def testObject(self):
+ def test_object(self):
self.assertTrue(hasattr(atk, 'Object'))
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestPangoCompat(unittest.TestCase):
- def testLayout(self):
+ def test_layout(self):
self.assertTrue(hasattr(pango, 'Layout'))
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestPangoCairoCompat(unittest.TestCase):
- def testErrorUnderlinePath(self):
+ def test_error_underline_path(self):
self.assertTrue(hasattr(pangocairo, 'error_underline_path'))
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestGTKCompat(unittest.TestCase):
- def testButtons(self):
+ def test_buttons(self):
self.assertEqual(Gdk._2BUTTON_PRESS, 5)
self.assertEqual(Gdk.BUTTON_PRESS, 4)
- def testEnums(self):
+ def test_enums(self):
self.assertEqual(gtk.WINDOW_TOPLEVEL, Gtk.WindowType.TOPLEVEL)
self.assertEqual(gtk.PACK_START, Gtk.PackType.START)
- def testFlags(self):
+ def test_flags(self):
self.assertEqual(gtk.EXPAND, Gtk.AttachOptions.EXPAND)
self.assertEqual(gtk.gdk.SHIFT_MASK, Gdk.ModifierType.SHIFT_MASK)
- def testKeysyms(self):
+ def test_keysyms(self):
import gtk.keysyms
self.assertEqual(gtk.keysyms.Escape, Gdk.KEY_Escape)
self.assertTrue(gtk.keysyms._0, Gdk.KEY_0)
- def testStyle(self):
+ def test_style(self):
widget = gtk.Button()
self.assertTrue(isinstance(widget.style.base[gtk.STATE_NORMAL],
gtk.gdk.Color))
- def testAlignment(self):
+ def test_alignment(self):
a = gtk.Alignment()
self.assertEqual(a.props.xalign, 0.0)
self.assertEqual(a.props.yalign, 0.0)
self.assertEqual(a.props.xscale, 0.0)
self.assertEqual(a.props.yscale, 0.0)
- def testBox(self):
+ def test_box(self):
box = gtk.Box()
child = gtk.Button()
@@ -94,7 +94,7 @@ class TestGTKCompat(unittest.TestCase):
self.assertEqual(padding, 0)
self.assertEqual(pack_type, gtk.PACK_END)
- def testComboBoxEntry(self):
+ def test_combobox_entry(self):
liststore = gtk.ListStore(int, str)
liststore.append((1, 'One'))
liststore.append((2, 'Two'))
@@ -102,8 +102,10 @@ class TestGTKCompat(unittest.TestCase):
# 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)
- combo = gtk.ComboBoxEntry(model=liststore)
- GLib.log_set_always_fatal(old_mask)
+ try:
+ 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)
@@ -120,18 +122,18 @@ class TestGTKCompat(unittest.TestCase):
self.assertEqual(combo.get_text_column(), 1)
self.assertEqual(combo.get_child().get_text(), 'One')
- def testSizeRequest(self):
+ def test_size_request(self):
box = gtk.Box()
self.assertEqual(box.size_request(), [0, 0])
- def testPixbuf(self):
+ def test_pixbuf(self):
gtk.gdk.Pixbuf()
- def testPixbufLoader(self):
+ def test_pixbuf_loader(self):
loader = gtk.gdk.PixbufLoader('png')
loader.close()
- def testPixbufFormats(self):
+ def test_pixbuf_formats(self):
formats = gtk.gdk.pixbuf_get_formats()
self.assertEqual(type(formats[0]), dict)
self.assertTrue('name' in formats[0])
@@ -139,7 +141,7 @@ class TestGTKCompat(unittest.TestCase):
self.assertTrue('mime_types' in formats[0])
self.assertEqual(type(formats[0]['extensions']), list)
- def testGdkWindow(self):
+ def test_gdk_window(self):
w = gtk.Window()
w.realize()
self.assertEqual(w.get_window().get_origin(), (0, 0))
diff --git a/tests/runtests.py b/tests/runtests.py
index c518fcc..9f3a7ec 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -34,6 +34,9 @@ if sys.version_info[:2] == (2, 6):
unittest.TestCase.assertGreater = assertGreater
unittest.TestCase.assertIsInstance = assertIsInstance
+if sys.version_info[:2] == (2, 7):
+ unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
+
if '--help' in sys.argv:
print("Usage: ./runtests.py <testfiles>")
sys.exit(0)
diff --git a/tests/test_atoms.py b/tests/test_atoms.py
index a59d15a..1561dbd 100644
--- a/tests/test_atoms.py
+++ b/tests/test_atoms.py
@@ -13,6 +13,18 @@ class TestGdkAtom(unittest.TestCase):
atom = Gdk.Atom.intern('my_string', False)
self.assertEqual(atom.name(), 'my_string')
+ def test_str(self):
+ atom = Gdk.Atom.intern('my_string', False)
+ self.assertEqual(str(atom), 'my_string')
+
+ self.assertEqual(str(Gdk.SELECTION_CLIPBOARD), 'CLIPBOARD')
+
+ def test_repr(self):
+ atom = Gdk.Atom.intern('my_string', False)
+ self.assertEqual(repr(atom), 'Gdk.Atom<my_string>')
+
+ self.assertEqual(repr(Gdk.SELECTION_CLIPBOARD), 'Gdk.Atom<CLIPBOARD>')
+
def test_in_single(self):
a_selection = Gdk.Atom.intern('test_clipboard', False)
clipboard = Gtk.Clipboard.get(a_selection)
@@ -36,6 +48,25 @@ class TestGdkAtom(unittest.TestCase):
self.assertTrue(Gtk.targets_include_image([a_jpeg], False))
self.assertTrue(Gtk.targets_include_image([a_jpeg, a_plain], False))
+ def test_out_array(self):
+ a_selection = Gdk.Atom.intern('my_clipboard', False)
+ clipboard = Gtk.Clipboard.get(a_selection)
+
+ # empty
+ (res, targets) = clipboard.wait_for_targets()
+ self.assertEqual(res, False)
+ self.assertEqual(targets, [])
+
+ # text
+ clipboard.set_text('hello', 5)
+ (res, targets) = clipboard.wait_for_targets()
+ self.assertEqual(res, True)
+ self.assertNotEqual(targets, [])
+ self.assertEqual(type(targets[0]), Gdk.Atom)
+ names = [t.name() for t in targets]
+ self.assertFalse(None in names, names)
+ self.assertTrue('TEXT' in names, names)
+
def test_out_glist(self):
display = Gdk.Display.get_default()
dm = display.get_device_manager()
diff --git a/tests/test_everything.py b/tests/test_everything.py
index 4c4535f..f1f14b7 100644
--- a/tests/test_everything.py
+++ b/tests/test_everything.py
@@ -4,14 +4,10 @@
import unittest
import traceback
+import ctypes
import warnings
-import gc
-gc
-
import sys
-from sys import getrefcount
-import copy
try:
import cairo
has_cairo = True
@@ -37,6 +33,17 @@ else:
UNICHAR = "♥"
+class RawGList(ctypes.Structure):
+ _fields_ = [('data', ctypes.c_void_p),
+ ('next', ctypes.c_void_p),
+ ('prev', ctypes.c_void_p)]
+
+ @classmethod
+ def from_wrapped(cls, obj):
+ offset = sys.getsizeof(object()) # size of PyObject_HEAD
+ return ctypes.POINTER(cls).from_address(id(obj) + offset)
+
+
@unittest.skipUnless(has_cairo, 'built without cairo support')
class TestEverything(unittest.TestCase):
@@ -73,6 +80,123 @@ class TestEverything(unittest.TestCase):
self.assertEqual(surface.get_width(), 10)
self.assertEqual(surface.get_height(), 10)
+ def test_bool(self):
+ self.assertEqual(Everything.test_boolean(False), False)
+ self.assertEqual(Everything.test_boolean(True), True)
+ self.assertEqual(Everything.test_boolean('hello'), True)
+ self.assertEqual(Everything.test_boolean(''), False)
+
+ self.assertEqual(Everything.test_boolean_true(True), True)
+ self.assertEqual(Everything.test_boolean_false(False), False)
+
+ def test_int8(self):
+ self.assertEqual(Everything.test_int8(GObject.G_MAXINT8),
+ GObject.G_MAXINT8)
+ self.assertEqual(Everything.test_int8(GObject.G_MININT8),
+ GObject.G_MININT8)
+ self.assertRaises(ValueError, Everything.test_int8, GObject.G_MAXINT8 + 1)
+
+ self.assertEqual(Everything.test_uint8(GObject.G_MAXUINT8),
+ GObject.G_MAXUINT8)
+ self.assertEqual(Everything.test_uint8(0), 0)
+ self.assertRaises(ValueError, Everything.test_uint8, -1)
+ self.assertRaises(ValueError, Everything.test_uint8, GObject.G_MAXUINT8 + 1)
+
+ def test_int16(self):
+ self.assertEqual(Everything.test_int16(GObject.G_MAXINT16),
+ GObject.G_MAXINT16)
+ self.assertEqual(Everything.test_int16(GObject.G_MININT16),
+ GObject.G_MININT16)
+ self.assertRaises(ValueError, Everything.test_int16, GObject.G_MAXINT16 + 1)
+
+ self.assertEqual(Everything.test_uint16(GObject.G_MAXUINT16),
+ GObject.G_MAXUINT16)
+ self.assertEqual(Everything.test_uint16(0), 0)
+ self.assertRaises(ValueError, Everything.test_uint16, -1)
+ self.assertRaises(ValueError, Everything.test_uint16, GObject.G_MAXUINT16 + 1)
+
+ def test_int32(self):
+ self.assertEqual(Everything.test_int32(GObject.G_MAXINT32),
+ GObject.G_MAXINT32)
+ self.assertEqual(Everything.test_int32(GObject.G_MININT32),
+ GObject.G_MININT32)
+ self.assertRaises(ValueError, Everything.test_int32, GObject.G_MAXINT32 + 1)
+
+ self.assertEqual(Everything.test_uint32(GObject.G_MAXUINT32),
+ GObject.G_MAXUINT32)
+ self.assertEqual(Everything.test_uint32(0), 0)
+ self.assertRaises(ValueError, Everything.test_uint32, -1)
+ self.assertRaises(ValueError, Everything.test_uint32, GObject.G_MAXUINT32 + 1)
+
+ def test_int64(self):
+ self.assertEqual(Everything.test_int64(GObject.G_MAXINT64),
+ GObject.G_MAXINT64)
+ self.assertEqual(Everything.test_int64(GObject.G_MININT64),
+ GObject.G_MININT64)
+ self.assertRaises(ValueError, Everything.test_int64, GObject.G_MAXINT64 + 1)
+
+ self.assertEqual(Everything.test_uint64(GObject.G_MAXUINT64),
+ GObject.G_MAXUINT64)
+ self.assertEqual(Everything.test_uint64(0), 0)
+ self.assertRaises(ValueError, Everything.test_uint64, -1)
+ self.assertRaises(ValueError, Everything.test_uint64, GObject.G_MAXUINT64 + 1)
+
+ def test_int(self):
+ self.assertEqual(Everything.test_int(GObject.G_MAXINT),
+ GObject.G_MAXINT)
+ self.assertEqual(Everything.test_int(GObject.G_MININT),
+ GObject.G_MININT)
+ self.assertRaises(ValueError, Everything.test_int, GObject.G_MAXINT + 1)
+
+ self.assertEqual(Everything.test_uint(GObject.G_MAXUINT),
+ GObject.G_MAXUINT)
+ self.assertEqual(Everything.test_uint(0), 0)
+ self.assertRaises(ValueError, Everything.test_uint, -1)
+ self.assertRaises(ValueError, Everything.test_uint, GObject.G_MAXUINT + 1)
+
+ def test_short(self):
+ self.assertEqual(Everything.test_short(GObject.G_MAXSHORT),
+ GObject.G_MAXSHORT)
+ self.assertEqual(Everything.test_short(GObject.G_MINSHORT),
+ GObject.G_MINSHORT)
+ self.assertRaises(ValueError, Everything.test_short, GObject.G_MAXSHORT + 1)
+
+ self.assertEqual(Everything.test_ushort(GObject.G_MAXUSHORT),
+ GObject.G_MAXUSHORT)
+ self.assertEqual(Everything.test_ushort(0), 0)
+ self.assertRaises(ValueError, Everything.test_ushort, -1)
+ self.assertRaises(ValueError, Everything.test_ushort, GObject.G_MAXUSHORT + 1)
+
+ def test_long(self):
+ self.assertEqual(Everything.test_long(GObject.G_MAXLONG),
+ GObject.G_MAXLONG)
+ self.assertEqual(Everything.test_long(GObject.G_MINLONG),
+ GObject.G_MINLONG)
+ self.assertRaises(ValueError, Everything.test_long, GObject.G_MAXLONG + 1)
+
+ self.assertEqual(Everything.test_ulong(GObject.G_MAXULONG),
+ GObject.G_MAXULONG)
+ self.assertEqual(Everything.test_ulong(0), 0)
+ self.assertRaises(ValueError, Everything.test_ulong, -1)
+ self.assertRaises(ValueError, Everything.test_ulong, GObject.G_MAXULONG + 1)
+
+ def test_size(self):
+ self.assertEqual(Everything.test_ssize(GObject.G_MAXSSIZE),
+ GObject.G_MAXSSIZE)
+ self.assertEqual(Everything.test_ssize(GObject.G_MINSSIZE),
+ GObject.G_MINSSIZE)
+ self.assertRaises(ValueError, Everything.test_ssize, GObject.G_MAXSSIZE + 1)
+
+ self.assertEqual(Everything.test_size(GObject.G_MAXSIZE),
+ GObject.G_MAXSIZE)
+ self.assertEqual(Everything.test_size(0), 0)
+ self.assertRaises(ValueError, Everything.test_size, -1)
+ self.assertRaises(ValueError, Everything.test_size, GObject.G_MAXSIZE + 1)
+
+ def test_timet(self):
+ self.assertEqual(Everything.test_timet(42), 42)
+ self.assertRaises(ValueError, Everything.test_timet, GObject.G_MAXUINT64 + 1)
+
def test_unichar(self):
self.assertEqual("c", Everything.test_unichar("c"))
@@ -82,6 +206,96 @@ class TestEverything(unittest.TestCase):
self.assertRaises(TypeError, Everything.test_unichar, "")
self.assertRaises(TypeError, Everything.test_unichar, "morethanonechar")
+ def test_float(self):
+ self.assertEqual(Everything.test_float(GObject.G_MAXFLOAT),
+ GObject.G_MAXFLOAT)
+ self.assertEqual(Everything.test_float(GObject.G_MINFLOAT),
+ GObject.G_MINFLOAT)
+ self.assertRaises(ValueError, Everything.test_float, GObject.G_MAXFLOAT * 2)
+
+ def test_double(self):
+ self.assertEqual(Everything.test_double(GObject.G_MAXDOUBLE),
+ GObject.G_MAXDOUBLE)
+ self.assertEqual(Everything.test_double(GObject.G_MINDOUBLE),
+ GObject.G_MINDOUBLE)
+ self.assertRaises(ValueError, Everything.test_double, GObject.G_MAXDOUBLE * 2)
+
+ (two, three) = Everything.test_multi_double_args(2.5)
+ self.assertAlmostEqual(two, 5.0)
+ self.assertAlmostEqual(three, 7.5)
+
+ def test_value(self):
+ self.assertEqual(Everything.test_int_value_arg(GObject.G_MAXINT), GObject.G_MAXINT)
+ self.assertEqual(Everything.test_value_return(GObject.G_MAXINT), GObject.G_MAXINT)
+
+ def test_variant(self):
+ v = Everything.test_gvariant_i()
+ self.assertEqual(v.get_type_string(), 'i')
+ self.assertEqual(v.get_int32(), 1)
+
+ v = Everything.test_gvariant_s()
+ self.assertEqual(v.get_type_string(), 's')
+ self.assertEqual(v.get_string(), 'one')
+
+ v = Everything.test_gvariant_v()
+ self.assertEqual(v.get_type_string(), 'v')
+ vi = v.get_variant()
+ self.assertEqual(vi.get_type_string(), 's')
+ self.assertEqual(vi.get_string(), 'contents')
+
+ v = Everything.test_gvariant_as()
+ self.assertEqual(v.get_type_string(), 'as')
+ self.assertEqual(v.get_strv(), ['one', 'two', 'three'])
+
+ v = Everything.test_gvariant_asv()
+ self.assertEqual(v.get_type_string(), 'a{sv}')
+ self.assertEqual(v.lookup_value('nosuchkey', None), None)
+ name = v.lookup_value('name', None)
+ self.assertEqual(name.get_string(), 'foo')
+ timeout = v.lookup_value('timeout', None)
+ self.assertEqual(timeout.get_int32(), 10)
+
+ def test_string(self):
+ const_str = b'const \xe2\x99\xa5 utf8'
+ if sys.version_info >= (3, 0):
+ const_str = const_str.decode('UTF-8')
+ noconst_str = 'non' + const_str
+
+ self.assertEqual(Everything.test_utf8_const_return(), const_str)
+ self.assertEqual(Everything.test_utf8_nonconst_return(), noconst_str)
+ self.assertEqual(Everything.test_utf8_out(), noconst_str)
+
+ Everything.test_utf8_const_in(const_str)
+ self.assertEqual(Everything.test_utf8_inout(const_str), noconst_str)
+
+ self.assertEqual(Everything.test_filename_return(), ['åäö', '/etc/fstab'])
+
+ # returns g_utf8_strlen() in out argument
+ self.assertEqual(Everything.test_int_out_utf8(''), 0)
+ self.assertEqual(Everything.test_int_out_utf8('hello world'), 11)
+ self.assertEqual(Everything.test_int_out_utf8('åäö'), 3)
+
+ self.assertEqual(Everything.test_utf8_out_out(), ('first', 'second'))
+ self.assertEqual(Everything.test_utf8_out_nonconst_return(), ('first', 'second'))
+
+ def test_enum(self):
+ self.assertEqual(Everything.test_enum_param(Everything.TestEnum.VALUE1), 'value1')
+ self.assertEqual(Everything.test_enum_param(Everything.TestEnum.VALUE3), 'value3')
+ self.assertRaises(TypeError, Everything.test_enum_param, 'hello')
+
+ # FIXME: ValueError: invalid enum value: 2147483648
+ @unittest.expectedFailure
+ def test_enum_unsigned(self):
+ self.assertEqual(Everything.test_unsigned_enum_param(Everything.TestEnumUnsigned.VALUE1), 'value1')
+ self.assertEqual(Everything.test_unsigned_enum_param(Everything.TestEnumUnsigned.VALUE3), 'value3')
+ self.assertRaises(TypeError, Everything.test_unsigned_enum_param, 'hello')
+
+ def test_flags(self):
+ result = Everything.global_get_flags_out()
+ # assert that it's not an int
+ self.assertEqual(type(result), Everything.TestFlags)
+ self.assertEqual(result, Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3)
+
def test_floating(self):
e = Everything.TestFloating()
self.assertEqual(e.__grefcount__, 1)
@@ -121,6 +335,9 @@ class TestEverything(unittest.TestCase):
self.assertEqual(struct_b.nested_a.some_double, struct_b_clone.nested_a.some_double)
self.assertEqual(struct_b.nested_a.some_enum, struct_b_clone.nested_a.some_enum)
+ struct_a = Everything.test_struct_a_parse('ignored')
+ self.assertEqual(struct_a.some_int, 23)
+
def test_wrong_type_of_arguments(self):
try:
Everything.test_int8()
@@ -173,6 +390,34 @@ class TestEverything(unittest.TestCase):
# test that there are no duplicates returned
self.assertEqual(len(attr_list), len(set(attr_list)))
+ def test_array(self):
+ self.assertEqual(Everything.test_array_int_in([]), 0)
+ self.assertEqual(Everything.test_array_int_in([1, 5, -2]), 4)
+ self.assertEqual(Everything.test_array_int_out(), [0, 1, 2, 3, 4])
+ self.assertEqual(Everything.test_array_int_full_out(), [0, 1, 2, 3, 4])
+ self.assertEqual(Everything.test_array_int_none_out(), [1, 2, 3, 4, 5])
+ self.assertEqual(Everything.test_array_int_inout([1, 5, 42, -8]), [6, 43, -7])
+
+ if sys.version_info >= (3, 0):
+ self.assertEqual(Everything.test_array_gint8_in(b'\x01\x03\x05'), 9)
+ self.assertEqual(Everything.test_array_gint8_in([1, 3, 5, -50]), -41)
+ self.assertEqual(Everything.test_array_gint16_in([256, 257, -1000, 10000]), 9513)
+ self.assertEqual(Everything.test_array_gint32_in([30000, 1, -2]), 29999)
+ self.assertEqual(Everything.test_array_gint64_in([2 ** 33, 2 ** 34]), 2 ** 33 + 2 ** 34)
+
+ self.assertEqual(Everything.test_array_gtype_in(
+ [GObject.TYPE_STRING, GObject.TYPE_UINT64, GObject.TYPE_VARIANT]),
+ '[gchararray,guint64,GVariant,]')
+
+ def test_array_fixed_size(self):
+ # fixed length of 5
+ self.assertEqual(Everything.test_array_fixed_size_int_in([1, 2, -10, 5, 3]), 1)
+ self.assertRaises(ValueError, Everything.test_array_fixed_size_int_in, [1, 2, 3, 4])
+ self.assertRaises(ValueError, Everything.test_array_fixed_size_int_in, [1, 2, 3, 4, 5, 6])
+
+ self.assertEqual(Everything.test_array_fixed_size_int_out(), [0, 1, 2, 3, 4])
+ self.assertEqual(Everything.test_array_fixed_size_int_return(), [0, 1, 2, 3, 4])
+
def test_ptrarray(self):
# transfer container
result = Everything.test_garray_container_return()
@@ -184,7 +429,43 @@ class TestEverything(unittest.TestCase):
self.assertEqual(result, ['regress'])
result = None
+ def test_strv(self):
+ self.assertEqual(Everything.test_strv_out(), ['thanks', 'for', 'all', 'the', 'fish'])
+ self.assertEqual(Everything.test_strv_out_c(), ['thanks', 'for', 'all', 'the', 'fish'])
+ self.assertEqual(Everything.test_strv_out_container(), ['1', '2', '3'])
+ self.assertEqual(Everything.test_strv_outarg(), ['1', '2', '3'])
+
+ self.assertEqual(Everything.test_strv_in_gvalue(), ['one', 'two', 'three'])
+
+ Everything.test_strv_in(['1', '2', '3'])
+
+ def test_glist(self):
+ self.assertEqual(Everything.test_glist_nothing_return(), ['1', '2', '3'])
+ self.assertEqual(Everything.test_glist_nothing_return2(), ['1', '2', '3'])
+ self.assertEqual(Everything.test_glist_container_return(), ['1', '2', '3'])
+ self.assertEqual(Everything.test_glist_everything_return(), ['1', '2', '3'])
+
+ Everything.test_glist_nothing_in(['1', '2', '3'])
+ Everything.test_glist_nothing_in2(['1', '2', '3'])
+
+ def test_gslist(self):
+ self.assertEqual(Everything.test_gslist_nothing_return(), ['1', '2', '3'])
+ self.assertEqual(Everything.test_gslist_nothing_return2(), ['1', '2', '3'])
+ self.assertEqual(Everything.test_gslist_container_return(), ['1', '2', '3'])
+ self.assertEqual(Everything.test_gslist_everything_return(), ['1', '2', '3'])
+
+ Everything.test_gslist_nothing_in(['1', '2', '3'])
+ Everything.test_gslist_nothing_in2(['1', '2', '3'])
+
def test_hash_return(self):
+ expected = {'foo': 'bar', 'baz': 'bat', 'qux': 'quux'}
+
+ self.assertEqual(Everything.test_ghash_null_return(), None)
+ self.assertEqual(Everything.test_ghash_nothing_return(), expected)
+ self.assertEqual(Everything.test_ghash_nothing_return(), expected)
+ self.assertEqual(Everything.test_ghash_container_return(), expected)
+ self.assertEqual(Everything.test_ghash_everything_return(), expected)
+
result = Everything.test_ghash_gvalue_return()
self.assertEqual(result['integer'], 12)
self.assertEqual(result['boolean'], True)
@@ -194,6 +475,11 @@ class TestEverything(unittest.TestCase):
self.assertEqual(result['enum'], Everything.TestEnum.VALUE2)
result = None
+ # FIXME: CRITICAL **: Unsupported type ghash
+ def disabled_test_hash_return_nested(self):
+ self.assertEqual(Everything.test_ghash_nested_everything_return(), {})
+ self.assertEqual(Everything.test_ghash_nested_everything_return2(), {})
+
def test_hash_in(self):
# specifying a simple string array for "strings" does not work due to
# https://bugzilla.gnome.org/show_bug.cgi?id=666636
@@ -201,6 +487,11 @@ class TestEverything(unittest.TestCase):
class GStrv(list):
__gtype__ = GObject.TYPE_STRV
+ expected = {'foo': 'bar', 'baz': 'bat', 'qux': 'quux'}
+
+ Everything.test_ghash_nothing_in(expected)
+ Everything.test_ghash_nothing_in2(expected)
+
data = {'integer': 12,
'boolean': True,
'string': 'some text',
@@ -212,24 +503,24 @@ class TestEverything(unittest.TestCase):
data = None
def test_struct_gpointer(self):
- l1 = GLib.List()
- self.assertEqual(l1.data, None)
- init_refcount = getrefcount(l1)
+ glist = GLib.List()
+ raw = RawGList.from_wrapped(glist)
+
+ self.assertEqual(glist.data, None)
+ self.assertEqual(raw.contents.data, None)
- l1.data = 'foo'
- self.assertEqual(l1.data, 'foo')
+ glist.data = 123
+ self.assertEqual(glist.data, 123)
+ self.assertEqual(raw.contents.data, 123)
- l2 = l1
- self.assertEqual(l1.data, l2.data)
- self.assertEqual(getrefcount(l1), init_refcount + 1)
+ glist.data = None
+ self.assertEqual(glist.data, None)
+ self.assertEqual(raw.contents.data, None)
- l3 = copy.copy(l1)
- l3.data = 'bar'
- self.assertEqual(l1.data, 'foo')
- self.assertEqual(l2.data, 'foo')
- self.assertEqual(l3.data, 'bar')
- self.assertEqual(getrefcount(l1), init_refcount + 1)
- self.assertEqual(getrefcount(l3), init_refcount)
+ # Setting to anything other than an int should raise
+ self.assertRaises(TypeError, setattr, glist.data, 'nan')
+ self.assertRaises(TypeError, setattr, glist.data, object())
+ self.assertRaises(TypeError, setattr, glist.data, 123.321)
def test_struct_opaque(self):
# we should get a sensible error message
@@ -375,13 +666,37 @@ class TestCallbacks(unittest.TestCase):
def callback():
TestCallbacks.called += 1
- return 0
+ return TestCallbacks.called
refcount = sys.getrefcount(callback)
- Everything.test_multi_callback(callback)
+ result = Everything.test_multi_callback(callback)
+ # first callback should give 1, second 2, and the function sums them up
+ self.assertEqual(result, 3)
self.assertEqual(TestCallbacks.called, 2)
self.assertEqual(sys.getrefcount(callback), refcount)
+ # FIXME: TypeError: callback() takes 2 positional arguments but 4 were given
+ # does not remove the array length arguments
+ @unittest.expectedFailure
+ def test_callback_scope_call_array(self):
+ # This tests a callback that gets called multiple times from a
+ # single scope call in python with array arguments
+ TestCallbacks.callargs = []
+
+ # works with:
+ #def callback(one, one_length, two, two_length):
+ def callback(one, two):
+ TestCallbacks.callargs.append((one, two))
+ return len(TestCallbacks.callargs)
+
+ refcount = sys.getrefcount(callback)
+ result = Everything.test_array_callback(callback)
+ # first callback should give 1, second 2, and the function sums them up
+ self.assertEqual(result, 3)
+ self.assertEqual(TestCallbacks.callargs,
+ [([-1, 0, 1, 2], ['one', 'two', 'three'])] * 2)
+ self.assertEqual(sys.getrefcount(callback), refcount)
+
def test_callback_userdata(self):
TestCallbacks.called = 0
@@ -556,6 +871,16 @@ class TestCallbacks(unittest.TestCase):
@unittest.skipUnless(has_cairo, 'built without cairo support')
class TestClosures(unittest.TestCase):
+ def test_no_arg(self):
+ def callback():
+ self.called = True
+ return 42
+
+ self.called = False
+ result = Everything.test_closure(callback)
+ self.assertTrue(self.called)
+ self.assertEqual(result, 42)
+
def test_int_arg(self):
def callback(num):
self.called = True
@@ -589,6 +914,22 @@ class TestClosures(unittest.TestCase):
self.assertRaises(TypeError, Everything.test_closure_variant, callback, 'foo')
self.assertFalse(self.called)
+ def test_variant_wrong_return_type(self):
+ 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))
+ # ... 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)
+
@unittest.skipUnless(has_cairo, 'built without cairo support')
class TestProperties(unittest.TestCase):
@@ -647,7 +988,27 @@ class TestProperties(unittest.TestCase):
self.assertTrue(isinstance(object_.props.boxed, Everything.TestBoxed))
self.assertEqual(object_.props.boxed.some_int8, 42)
+ def test_boxed_alternative_constructor(self):
+ boxed = Everything.TestBoxed.new_alternative_constructor1(5)
+ self.assertEqual(boxed.some_int8, 5)
+
+ boxed = Everything.TestBoxed.new_alternative_constructor2(5, 3)
+ self.assertEqual(boxed.some_int8, 8)
+
+ boxed = Everything.TestBoxed.new_alternative_constructor3("-3")
+ self.assertEqual(boxed.some_int8, -3)
+
def test_boxed_equality(self):
+ boxed42 = Everything.TestBoxed.new_alternative_constructor1(42)
+ boxed5 = Everything.TestBoxed.new_alternative_constructor1(5)
+ boxed42_2 = Everything.TestBoxed.new_alternative_constructor2(41, 1)
+
+ self.assertFalse(boxed42.equals(boxed5))
+ self.assertTrue(boxed42.equals(boxed42_2))
+ self.assertTrue(boxed42_2.equals(boxed42))
+ self.assertTrue(boxed42.equals(boxed42))
+
+ def test_boxed_c_equality(self):
boxed = Everything.TestBoxedC()
# TestBoxedC uses refcounting, so we know that
# the pointer is the same when copied
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 51cb6f9..4837204 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -11,6 +11,7 @@ import os
import locale
import subprocess
import gc
+import weakref
from io import StringIO, BytesIO
import gi
@@ -18,7 +19,7 @@ from gi.repository import GObject, GLib, Gio
from gi.repository import GIMarshallingTests
-from compathelper import _bytes
+from compathelper import _bytes, _unicode
if sys.version_info < (3, 0):
CONSTANT_UTF8 = "const \xe2\x99\xa5 utf8"
@@ -64,6 +65,15 @@ class TestConstant(unittest.TestCase):
def test_constant_number(self):
self.assertEqual(CONSTANT_NUMBER, GIMarshallingTests.CONSTANT_NUMBER)
+ def test_min_max_int(self):
+ self.assertEqual(GLib.MAXINT32, 2 ** 31 - 1)
+ self.assertEqual(GLib.MININT32, -2 ** 31)
+ self.assertEqual(GLib.MAXUINT32, 2 ** 32 - 1)
+
+ self.assertEqual(GLib.MAXINT64, 2 ** 63 - 1)
+ self.assertEqual(GLib.MININT64, -2 ** 63)
+ self.assertEqual(GLib.MAXUINT64, 2 ** 64 - 1)
+
class TestBoolean(unittest.TestCase):
@@ -325,8 +335,8 @@ class TestUInt64(unittest.TestCase):
class TestShort(unittest.TestCase):
- MAX = GObject.constants.G_MAXSHORT
- MIN = GObject.constants.G_MINSHORT
+ MAX = GObject.G_MAXSHORT
+ MIN = GObject.G_MINSHORT
def test_short_return(self):
self.assertEqual(self.MAX, GIMarshallingTests.short_return_max())
@@ -358,7 +368,7 @@ class TestShort(unittest.TestCase):
class TestUShort(unittest.TestCase):
- MAX = GObject.constants.G_MAXUSHORT
+ MAX = GObject.G_MAXUSHORT
def test_ushort_return(self):
self.assertEqual(self.MAX, GIMarshallingTests.ushort_return())
@@ -384,8 +394,8 @@ class TestUShort(unittest.TestCase):
class TestInt(unittest.TestCase):
- MAX = GObject.constants.G_MAXINT
- MIN = GObject.constants.G_MININT
+ MAX = GObject.G_MAXINT
+ MIN = GObject.G_MININT
def test_int_return(self):
self.assertEqual(self.MAX, GIMarshallingTests.int_return_max())
@@ -418,7 +428,7 @@ class TestInt(unittest.TestCase):
class TestUInt(unittest.TestCase):
- MAX = GObject.constants.G_MAXUINT
+ MAX = GObject.G_MAXUINT
def test_uint_return(self):
self.assertEqual(self.MAX, GIMarshallingTests.uint_return())
@@ -444,8 +454,8 @@ class TestUInt(unittest.TestCase):
class TestLong(unittest.TestCase):
- MAX = GObject.constants.G_MAXLONG
- MIN = GObject.constants.G_MINLONG
+ MAX = GObject.G_MAXLONG
+ MIN = GObject.G_MINLONG
def test_long_return(self):
self.assertEqual(self.MAX, GIMarshallingTests.long_return_max())
@@ -477,7 +487,7 @@ class TestLong(unittest.TestCase):
class TestULong(unittest.TestCase):
- MAX = GObject.constants.G_MAXULONG
+ MAX = GObject.G_MAXULONG
def test_ulong_return(self):
self.assertEqual(self.MAX, GIMarshallingTests.ulong_return())
@@ -503,8 +513,8 @@ class TestULong(unittest.TestCase):
class TestSSize(unittest.TestCase):
- MAX = GObject.constants.G_MAXLONG
- MIN = GObject.constants.G_MINLONG
+ MAX = GObject.G_MAXLONG
+ MIN = GObject.G_MINLONG
def test_ssize_return(self):
self.assertEqual(self.MAX, GIMarshallingTests.ssize_return_max())
@@ -536,7 +546,7 @@ class TestSSize(unittest.TestCase):
class TestSize(unittest.TestCase):
- MAX = GObject.constants.G_MAXULONG
+ MAX = GObject.G_MAXULONG
def test_size_return(self):
self.assertEqual(self.MAX, GIMarshallingTests.size_return())
@@ -560,10 +570,26 @@ class TestSize(unittest.TestCase):
self.assertEqual(0, GIMarshallingTests.size_inout(Number(self.MAX)))
+class TestTimet(unittest.TestCase):
+
+ def test_time_t_return(self):
+ self.assertEqual(1234567890, GIMarshallingTests.time_t_return())
+
+ def test_time_t_in(self):
+ GIMarshallingTests.time_t_in(1234567890)
+ self.assertRaises(TypeError, GIMarshallingTests.time_t_in, "hello")
+
+ def test_time_t_out(self):
+ self.assertEqual(1234567890, GIMarshallingTests.time_t_out())
+
+ def test_time_t_inout(self):
+ self.assertEqual(0, GIMarshallingTests.time_t_inout(1234567890))
+
+
class TestFloat(unittest.TestCase):
- MAX = GObject.constants.G_MAXFLOAT
- MIN = GObject.constants.G_MINFLOAT
+ MAX = GObject.G_MAXFLOAT
+ MIN = GObject.G_MINFLOAT
def test_float_return(self):
self.assertAlmostEqual(self.MAX, GIMarshallingTests.float_return())
@@ -582,8 +608,8 @@ class TestFloat(unittest.TestCase):
class TestDouble(unittest.TestCase):
- MAX = GObject.constants.G_MAXDOUBLE
- MIN = GObject.constants.G_MINDOUBLE
+ MAX = GObject.G_MAXDOUBLE
+ MIN = GObject.G_MINDOUBLE
def test_double_return(self):
self.assertAlmostEqual(self.MAX, GIMarshallingTests.double_return())
@@ -662,6 +688,36 @@ class TestUtf8(unittest.TestCase):
self.assertEqual("", GIMarshallingTests.utf8_full_inout(CONSTANT_UTF8))
+class TestFilename(unittest.TestCase):
+ def setUp(self):
+ self.workdir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self.workdir)
+
+ def test_filename_in(self):
+ fname = os.path.join(self.workdir, _unicode('testäø.txt'))
+ self.assertRaises(GLib.GError, GLib.file_get_contents, fname)
+
+ with open(fname.encode('UTF-8'), 'wb') as f:
+ f.write(b'hello world!\n\x01\x02')
+
+ (result, contents) = GLib.file_get_contents(fname)
+ self.assertEqual(result, True)
+ self.assertEqual(contents, b'hello world!\n\x01\x02')
+
+ def test_filename_out(self):
+ self.assertRaises(GLib.GError, GLib.Dir.make_tmp, 'test')
+
+ dirname = GLib.Dir.make_tmp('testäø.XXXXXX')
+ self.assertTrue('/testäø.' in dirname, dirname)
+ self.assertTrue(os.path.isdir(dirname))
+ os.rmdir(dirname)
+
+ def test_filename_type_error(self):
+ self.assertRaises(TypeError, GLib.file_get_contents, 23)
+
+
class TestArray(unittest.TestCase):
def test_array_fixed_int_return(self):
@@ -690,8 +746,16 @@ class TestArray(unittest.TestCase):
def test_array_return(self):
self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.array_return())
+ def test_array_return_etc(self):
+ self.assertEqual(([5, 0, 1, 9], 14), GIMarshallingTests.array_return_etc(5, 9))
+
def test_array_in(self):
GIMarshallingTests.array_in(Sequence([-1, 0, 1, 2]))
+ GIMarshallingTests.array_in_guint64_len(Sequence([-1, 0, 1, 2]))
+ GIMarshallingTests.array_in_guint8_len(Sequence([-1, 0, 1, 2]))
+
+ def test_array_in_len_before(self):
+ GIMarshallingTests.array_in_len_before(Sequence([-1, 0, 1, 2]))
def test_array_in_len_zero_terminated(self):
GIMarshallingTests.array_in_len_zero_terminated(Sequence([-1, 0, 1, 2]))
@@ -700,12 +764,22 @@ class TestArray(unittest.TestCase):
GIMarshallingTests.array_uint8_in(Sequence([97, 98, 99, 100]))
GIMarshallingTests.array_uint8_in(_bytes("abcd"))
+ def test_array_string_in(self):
+ GIMarshallingTests.array_string_in(['foo', 'bar'])
+
def test_array_out(self):
self.assertEqual([-1, 0, 1, 2], GIMarshallingTests.array_out())
+ def test_array_out_etc(self):
+ self.assertEqual(([-5, 0, 1, 9], 4), GIMarshallingTests.array_out_etc(-5, 9))
+
def test_array_inout(self):
self.assertEqual([-2, -1, 0, 1, 2], GIMarshallingTests.array_inout(Sequence([-1, 0, 1, 2])))
+ def test_array_inout_etc(self):
+ self.assertEqual(([-5, -1, 0, 1, 9], 4),
+ GIMarshallingTests.array_inout_etc(-5, Sequence([-1, 0, 1, 2]), 9))
+
def test_method_array_in(self):
object_ = GIMarshallingTests.Object()
object_.method_array_in(Sequence([-1, 0, 1, 2]))
@@ -737,6 +811,29 @@ class TestArray(unittest.TestCase):
GIMarshallingTests.array_struct_in([struct1, struct2, struct3])
+ def test_array_boxed_struct_take_in(self):
+ struct1 = GIMarshallingTests.BoxedStruct()
+ struct1.long_ = 1
+ struct2 = GIMarshallingTests.BoxedStruct()
+ struct2.long_ = 2
+ struct3 = GIMarshallingTests.BoxedStruct()
+ struct3.long_ = 3
+
+ GIMarshallingTests.array_struct_take_in([struct1, struct2, struct3])
+
+ self.assertEqual(1, struct1.long_)
+
+ @unittest.expectedFailure
+ def test_array_boxed_struct_return(self):
+ (struct1, struct2, struct3) = GIMarshallingTests.array_zero_terminated_return_struct()
+ self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct1))
+ self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct2))
+ self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct3))
+ # FIXME: gets bogus values
+ self.assertEqual(42, struct1.long_)
+ self.assertEqual(43, struct2.long_)
+ self.assertEqual(44, struct3.long_)
+
def test_array_simple_struct_in(self):
struct1 = GIMarshallingTests.SimpleStruct()
struct1.long_ = 1
@@ -777,6 +874,12 @@ class TestArray(unittest.TestCase):
def test_array_zero_terminated_inout(self):
self.assertEqual(['-1', '0', '1', '2'], GIMarshallingTests.array_zero_terminated_inout(['0', '1', '2']))
+ def test_init_function(self):
+ self.assertEqual((True, []), GIMarshallingTests.init_function([]))
+ self.assertEqual((True, []), GIMarshallingTests.init_function(['hello']))
+ self.assertEqual((True, ['hello']),
+ GIMarshallingTests.init_function(['hello', 'world']))
+
class TestGStrv(unittest.TestCase):
@@ -898,6 +1001,60 @@ class TestGPtrArray(unittest.TestCase):
self.assertEqual(['-2', '-1', '0', '1'], GIMarshallingTests.gptrarray_utf8_full_inout(['0', '1', '2']))
+class TestGBytes(unittest.TestCase):
+ def test_gbytes_create(self):
+ b = GLib.Bytes.new(b'\x00\x01\xFF')
+ self.assertEqual(3, b.get_size())
+ self.assertEqual(b'\x00\x01\xFF', b.get_data())
+
+ def test_gbytes_create_take(self):
+ b = GLib.Bytes.new_take(b'\x00\x01\xFF')
+ self.assertEqual(3, b.get_size())
+ self.assertEqual(b'\x00\x01\xFF', b.get_data())
+
+ @unittest.skipUnless(hasattr(GIMarshallingTests, 'gbytes_full_return'),
+ 'too old gobject-introspection')
+ def test_gbytes_full_return(self):
+ b = GIMarshallingTests.gbytes_full_return()
+ self.assertEqual(4, b.get_size())
+ self.assertEqual(b'\x00\x31\xFF\x33', b.get_data())
+
+ @unittest.skipUnless(hasattr(GIMarshallingTests, 'gbytes_full_return'),
+ 'too old gobject-introspection')
+ def test_gbytes_none_in(self):
+ b = GIMarshallingTests.gbytes_full_return()
+ GIMarshallingTests.gbytes_none_in(b)
+
+ def test_compare(self):
+ a1 = GLib.Bytes.new(b'\x00\x01\xFF')
+ a2 = GLib.Bytes.new(b'\x00\x01\xFF')
+ b = GLib.Bytes.new(b'\x00\x01\xFE')
+
+ self.assertTrue(a1.equal(a2))
+ self.assertTrue(a2.equal(a1))
+ self.assertFalse(a1.equal(b))
+ self.assertFalse(b.equal(a2))
+
+ self.assertEqual(0, a1.compare(a2))
+ self.assertEqual(1, a1.compare(b))
+ self.assertEqual(-1, b.compare(a1))
+
+
+class TestGByteArray(unittest.TestCase):
+ def test_new(self):
+ ba = GLib.ByteArray.new()
+ self.assertEqual(b'', ba)
+
+ ba = GLib.ByteArray.new_take(b'\x01\x02\xFF')
+ self.assertEqual(b'\x01\x02\xFF', ba)
+
+ def test_bytearray_full_return(self):
+ self.assertEqual(b'\x001\xFF3', GIMarshallingTests.bytearray_full_return())
+
+ def test_bytearray_none_in(self):
+ GIMarshallingTests.bytearray_none_in(b'\x00\x31\xFF\x33')
+
+
class TestGList(unittest.TestCase):
def test_glist_int_none_return(self):
@@ -1061,6 +1218,23 @@ class TestGValue(unittest.TestCase):
value.set_int64(GObject.G_MAXINT64)
GIMarshallingTests.gvalue_int64_in(value)
+ def test_gvalue_in_with_type(self):
+ value = GObject.Value()
+ value.init(GObject.TYPE_STRING)
+ value.set_string('foo')
+ GIMarshallingTests.gvalue_in_with_type(value, GObject.TYPE_STRING)
+
+ value = GObject.Value()
+ value.init(GIMarshallingTests.Flags.__gtype__)
+ value.set_flags(GIMarshallingTests.Flags.VALUE1)
+ GIMarshallingTests.gvalue_in_with_type(value, GObject.TYPE_FLAGS)
+
+ def test_gvalue_in_enum(self):
+ value = GObject.Value()
+ value.init(GIMarshallingTests.Enum.__gtype__)
+ value.set_enum(GIMarshallingTests.Enum.VALUE3)
+ GIMarshallingTests.gvalue_in_enum(value)
+
def test_gvalue_out(self):
self.assertEqual(42, GIMarshallingTests.gvalue_out())
@@ -1085,6 +1259,88 @@ class TestGValue(unittest.TestCase):
values = GIMarshallingTests.return_gvalue_flat_array()
self.assertEqual(values, [42, '42', True])
+ def test_gvalue_gobject_ref_counts(self):
+ # Tests a GObject held by a GValue
+ obj = GObject.Object()
+ ref = weakref.ref(obj)
+ grefcount = obj.__grefcount__
+
+ value = GObject.Value()
+ value.init(GObject.TYPE_OBJECT)
+
+ # TYPE_OBJECT will inc ref count as it should
+ value.set_object(obj)
+ self.assertEqual(obj.__grefcount__, grefcount + 1)
+
+ # multiple set_object should not inc ref count
+ value.set_object(obj)
+ self.assertEqual(obj.__grefcount__, grefcount + 1)
+
+ # get_object will re-use the same wrapper as obj
+ res = value.get_object()
+ self.assertEqual(obj, res)
+ self.assertEqual(obj.__grefcount__, grefcount + 1)
+
+ # multiple get_object should not inc ref count
+ res = value.get_object()
+ self.assertEqual(obj.__grefcount__, grefcount + 1)
+
+ # deletion of the result and value holder should bring the
+ # refcount back to where we started
+ del res
+ del value
+ gc.collect()
+ self.assertEqual(obj.__grefcount__, grefcount)
+
+ del obj
+ gc.collect()
+ self.assertEqual(ref(), None)
+
+ def test_gvalue_boxed_ref_counts(self):
+ # Tests a boxed type wrapping a python object pointer (TYPE_PYOBJECT)
+ # held by a GValue
+ class Obj(object):
+ pass
+
+ obj = Obj()
+ ref = weakref.ref(obj)
+ refcount = sys.getrefcount(obj)
+
+ value = GObject.Value()
+ value.init(GObject.TYPE_PYOBJECT)
+
+ # boxed TYPE_PYOBJECT will inc ref count as it should
+ value.set_boxed(obj)
+ self.assertEqual(sys.getrefcount(obj), refcount + 1)
+
+ # multiple set_boxed should not inc ref count
+ value.set_boxed(obj)
+ self.assertEqual(sys.getrefcount(obj), refcount + 1)
+
+ res = value.get_boxed()
+ self.assertEqual(obj, res)
+ self.assertEqual(sys.getrefcount(obj), refcount + 2)
+
+ # multiple get_boxed should not inc ref count
+ res = value.get_boxed()
+ self.assertEqual(sys.getrefcount(obj), refcount + 2)
+
+ # deletion of the result and value holder should bring the
+ # refcount back to where we started
+ del res
+ del value
+ gc.collect()
+ self.assertEqual(sys.getrefcount(obj), refcount)
+
+ del obj
+ gc.collect()
+ self.assertEqual(ref(), None)
+
+ # FIXME: crashes
+ def disabled_test_gvalue_flat_array_round_trip(self):
+ self.assertEqual([42, '42', True],
+ GIMarshallingTests.gvalue_flat_array_round_trip(42, '42', True))
+
class TestGClosure(unittest.TestCase):
@@ -1154,6 +1410,11 @@ class TestEnum(unittest.TestCase):
self.assertRaises(TypeError, GIMarshallingTests.enum_in, 43)
self.assertRaises(TypeError, GIMarshallingTests.enum_in, 'GIMarshallingTests.Enum.VALUE3')
+ def test_enum_return(self):
+ enum = GIMarshallingTests.enum_returnv()
+ self.assertTrue(isinstance(enum, GIMarshallingTests.Enum))
+ self.assertEqual(enum, GIMarshallingTests.Enum.VALUE3)
+
def test_enum_out(self):
enum = GIMarshallingTests.enum_out()
self.assertTrue(isinstance(enum, GIMarshallingTests.Enum))
@@ -1200,6 +1461,11 @@ class TestGEnum(unittest.TestCase):
self.assertRaises(TypeError, GIMarshallingTests.genum_in, 43)
self.assertRaises(TypeError, GIMarshallingTests.genum_in, 'GIMarshallingTests.GEnum.VALUE3')
+ def test_genum_return(self):
+ genum = GIMarshallingTests.genum_returnv()
+ self.assertTrue(isinstance(genum, GIMarshallingTests.GEnum))
+ self.assertEqual(genum, GIMarshallingTests.GEnum.VALUE3)
+
def test_genum_out(self):
genum = GIMarshallingTests.genum_out()
self.assertTrue(isinstance(genum, GIMarshallingTests.GEnum))
@@ -1241,6 +1507,11 @@ class TestGFlags(unittest.TestCase):
self.assertRaises(TypeError, GIMarshallingTests.flags_in, 1 << 1)
self.assertRaises(TypeError, GIMarshallingTests.flags_in, 'GIMarshallingTests.Flags.VALUE2')
+ def test_flags_return(self):
+ flags = GIMarshallingTests.flags_returnv()
+ self.assertTrue(isinstance(flags, GIMarshallingTests.Flags))
+ self.assertEqual(flags, GIMarshallingTests.Flags.VALUE2)
+
def test_flags_out(self):
flags = GIMarshallingTests.flags_out()
self.assertTrue(isinstance(flags, GIMarshallingTests.Flags))
@@ -1281,6 +1552,11 @@ class TestNoTypeFlags(unittest.TestCase):
self.assertRaises(TypeError, GIMarshallingTests.no_type_flags_in, 1 << 1)
self.assertRaises(TypeError, GIMarshallingTests.no_type_flags_in, 'GIMarshallingTests.NoTypeFlags.VALUE2')
+ def test_flags_return(self):
+ flags = GIMarshallingTests.no_type_flags_returnv()
+ self.assertTrue(isinstance(flags, GIMarshallingTests.NoTypeFlags))
+ self.assertEqual(flags, GIMarshallingTests.NoTypeFlags.VALUE2)
+
def test_flags_out(self):
flags = GIMarshallingTests.no_type_flags_out()
self.assertTrue(isinstance(flags, GIMarshallingTests.NoTypeFlags))
@@ -1738,13 +2014,8 @@ class TestPythonGObject(unittest.TestCase):
self.assertEqual(object_.val, 87)
def test_dynamic_module(self):
- from gi.module import DynamicGObjectModule
- self.assertTrue(isinstance(GObject, DynamicGObjectModule))
- # compare the same enum from both the pygobject attrs and gi GObject attrs
- self.assertEqual(GObject.SIGNAL_ACTION, GObject.SignalFlags.ACTION)
- # compare a static gobject attr with a dynamic GObject attr
- import gi._gobject
- self.assertEqual(GObject.GObject, gi._gobject.GObject)
+ from gi.module import DynamicModule
+ self.assertTrue(isinstance(GObject, DynamicModule))
def test_subobject_non_vfunc_do_method(self):
class PythonObjectWithNonVFuncDoMethod:
@@ -2198,11 +2469,12 @@ class TestPropertiesObject(unittest.TestCase):
# wrong; this will raise an assertion critical which we need to ignore
old_mask = GLib.log_set_always_fatal(
GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_ERROR)
- self.assertEqual(self.obj.props.some_char, 0)
- self.obj.props.some_char = GObject.G_MAXINT8
- self.assertEqual(self.obj.props.some_char, GObject.G_MAXINT8)
-
- GLib.log_set_always_fatal(old_mask)
+ try:
+ self.assertEqual(self.obj.props.some_char, 0)
+ self.obj.props.some_char = GObject.G_MAXINT8
+ self.assertEqual(self.obj.props.some_char, GObject.G_MAXINT8)
+ finally:
+ GLib.log_set_always_fatal(old_mask)
obj = GIMarshallingTests.PropertiesObject(some_char=-42)
self.assertEqual(obj.props.some_char, -42)
@@ -2349,6 +2621,28 @@ class TestPropertiesObject(unittest.TestCase):
obj = GIMarshallingTests.PropertiesObject(some_boxed_struct=struct1)
self.assertEqual(obj.props.some_boxed_struct.long_, 1)
+ @unittest.skipUnless(hasattr(GIMarshallingTests.PropertiesObject, 'some_variant'),
+ 'too old gobject-introspection')
+ def test_variant(self):
+ self.assertEqual(self.obj.props.some_variant, None)
+
+ self.obj.props.some_variant = GLib.Variant('o', '/myobj')
+ self.assertEqual(self.obj.props.some_variant.get_type_string(), 'o')
+ self.assertEqual(self.obj.props.some_variant.print_(False), "'/myobj'")
+
+ self.obj.props.some_variant = None
+ self.assertEqual(self.obj.props.some_variant, None)
+
+ obj = GIMarshallingTests.PropertiesObject(some_variant=GLib.Variant('b', True))
+ self.assertEqual(obj.props.some_variant.get_type_string(), 'b')
+ self.assertEqual(obj.props.some_variant.get_boolean(), True)
+
+ self.assertRaises(TypeError, setattr, self.obj.props, 'some_variant', 'foo')
+ self.assertRaises(TypeError, setattr, self.obj.props, 'some_variant', 23)
+
+ self.assertEqual(obj.props.some_variant.get_type_string(), 'b')
+ self.assertEqual(obj.props.some_variant.get_boolean(), True)
+
class TestKeywords(unittest.TestCase):
def test_method(self):
@@ -2435,3 +2729,33 @@ class TestObjectInfo(unittest.TestCase):
repo = gi.gi.Repository.get_default()
info = repo.find_by_name('GObject', 'Object')
self.assertFalse(info.get_abstract())
+
+
+class TestSignatureArgs(unittest.TestCase):
+ def test_split_args_multi_out(self):
+ in_args, out_args = gi.types.split_function_info_args(GIMarshallingTests.int_out_out.__info__)
+ self.assertEqual(len(in_args), 0)
+ self.assertEqual(len(out_args), 2)
+ self.assertEqual(out_args[0].get_pytype_hint(), 'int')
+ self.assertEqual(out_args[1].get_pytype_hint(), 'int')
+
+ def test_split_args_inout(self):
+ in_args, out_args = gi.types.split_function_info_args(GIMarshallingTests.long_inout_max_min.__info__)
+ self.assertEqual(len(in_args), 1)
+ self.assertEqual(len(out_args), 1)
+ self.assertEqual(in_args[0].get_name(), out_args[0].get_name())
+ self.assertEqual(in_args[0].get_pytype_hint(), out_args[0].get_pytype_hint())
+
+ def test_split_args_none(self):
+ obj = GIMarshallingTests.Object(int=33)
+ in_args, out_args = gi.types.split_function_info_args(obj.none_inout.__info__)
+ self.assertEqual(len(in_args), 1)
+ self.assertEqual(len(out_args), 1)
+
+ def test_final_signature_with_full_inout(self):
+ self.assertEqual(GIMarshallingTests.Object.full_inout.__doc__,
+ 'full_inout(object:GIMarshallingTests.Object) -> object:GIMarshallingTests.Object')
+
+ def test_overridden_doc_is_not_clobbered(self):
+ self.assertEqual(GIMarshallingTests.OverridesObject.method.__doc__,
+ 'Overridden doc string.')
diff --git a/tests/test_glib.py b/tests/test_glib.py
index a36eca6..1a45fd8 100644
--- a/tests/test_glib.py
+++ b/tests/test_glib.py
@@ -1,9 +1,15 @@
# -*- Mode: Python -*-
+# encoding: UTF-8
import unittest
import os.path
+import warnings
+import subprocess
from gi.repository import GLib
+from gi import PyGIDeprecationWarning
+
+from compathelper import _unicode, _bytes
class TestGLib(unittest.TestCase):
@@ -13,3 +19,183 @@ class TestGLib(unittest.TestCase):
self.assertTrue(os.path.exists(bash_path))
self.assertEqual(GLib.find_program_in_path('non existing'), None)
+
+ def test_markup_escape_text(self):
+ self.assertEqual(GLib.markup_escape_text(_unicode('a&bä')), 'a&amp;bä')
+ self.assertEqual(GLib.markup_escape_text(_bytes('a&b\x05')), 'a&amp;b&#x5;')
+
+ # with explicit length argument
+ self.assertEqual(GLib.markup_escape_text(_bytes('a\x05\x01\x02'), 2), 'a&#x5;')
+
+ def test_progname(self):
+ GLib.set_prgname('moo')
+ self.assertEqual(GLib.get_prgname(), 'moo')
+
+ def test_appname(self):
+ GLib.set_application_name('moo')
+ self.assertEqual(GLib.get_application_name(), 'moo')
+
+ def test_xdg_dirs(self):
+ self.assertTrue(os.path.isdir(GLib.get_user_data_dir()))
+ self.assertTrue(os.path.isdir(GLib.get_user_special_dir(GLib.USER_DIRECTORY_DESKTOP)))
+ # also works with backwards compatible enum names
+ self.assertEqual(GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_MUSIC),
+ GLib.get_user_special_dir(GLib.USER_DIRECTORY_MUSIC))
+
+ for d in GLib.get_system_config_dirs():
+ self.assertTrue('/' in d, d)
+ for d in GLib.get_system_data_dirs():
+ self.assertTrue('/' in d, d)
+
+ def test_main_depth(self):
+ self.assertEqual(GLib.main_depth(), 0)
+
+ def test_filenames(self):
+ self.assertEqual(GLib.filename_display_name('foo'), 'foo')
+ self.assertEqual(GLib.filename_display_basename('bar/foo'), 'foo')
+
+ # this is locale dependent, so we cannot completely verify the result
+ res = GLib.filename_from_utf8(_unicode('aäb'))
+ self.assertTrue(isinstance(res, bytes))
+ self.assertGreaterEqual(len(res), 3)
+
+ # with explicit length argument
+ self.assertEqual(GLib.filename_from_utf8(_unicode('aäb'), 1), b'a')
+
+ def test_uri_extract(self):
+ res = GLib.uri_list_extract_uris('''# some comment
+http://example.com
+https://my.org/q?x=1&y=2
+ http://gnome.org/new''')
+ self.assertEqual(res, ['http://example.com',
+ 'https://my.org/q?x=1&y=2',
+ 'http://gnome.org/new'])
+
+ def test_current_time(self):
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always')
+ tm = GLib.get_current_time()
+ self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+ self.assertTrue(isinstance(tm, float))
+ self.assertGreater(tm, 1350000000.0)
+
+ def test_main_loop(self):
+ # note we do not test run() here, as we use this in countless other
+ # tests
+ ml = GLib.MainLoop()
+ self.assertFalse(ml.is_running())
+
+ context = ml.get_context()
+ self.assertEqual(context, GLib.MainContext.default())
+ self.assertTrue(context.is_owner() in [True, False])
+ self.assertTrue(context.pending() in [True, False])
+ self.assertFalse(context.iteration(False))
+
+ def test_main_loop_with_context(self):
+ context = GLib.MainContext()
+ ml = GLib.MainLoop(context)
+ self.assertFalse(ml.is_running())
+ self.assertEqual(ml.get_context(), context)
+
+ def test_main_context(self):
+ # constructor
+ context = GLib.MainContext()
+ self.assertTrue(context.is_owner() in [True, False])
+ self.assertFalse(context.pending())
+ self.assertFalse(context.iteration(False))
+
+ # GLib API
+ context = GLib.MainContext.default()
+ self.assertTrue(context.is_owner() in [True, False])
+ self.assertTrue(context.pending() in [True, False])
+ self.assertTrue(context.iteration(False) in [True, False])
+
+ # backwards compatible API
+ context = GLib.main_context_default()
+ self.assertTrue(context.is_owner() in [True, False])
+ self.assertTrue(context.pending() in [True, False])
+ self.assertTrue(context.iteration(False) in [True, False])
+
+ def test_io_add_watch_no_data(self):
+ (r, w) = os.pipe()
+ call_data = []
+
+ def cb(fd, condition):
+ call_data.append((fd, condition, os.read(fd, 1)))
+ return True
+
+ # io_add_watch() takes an IOChannel, calling with an fd is deprecated
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always')
+ GLib.io_add_watch(r, GLib.IOCondition.IN, cb)
+ self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+ ml = GLib.MainLoop()
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(call_data, [(r, GLib.IOCondition.IN, b'a'),
+ (r, GLib.IOCondition.IN, b'b')])
+
+ def test_io_add_watch_with_data(self):
+ (r, w) = os.pipe()
+ call_data = []
+
+ def cb(fd, condition, data):
+ call_data.append((fd, condition, os.read(fd, 1), data))
+ return True
+
+ # io_add_watch() takes an IOChannel, calling with an fd is deprecated
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always')
+ GLib.io_add_watch(r, GLib.IOCondition.IN, cb, 'moo')
+ self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+ ml = GLib.MainLoop()
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(call_data, [(r, GLib.IOCondition.IN, b'a', 'moo'),
+ (r, GLib.IOCondition.IN, b'b', 'moo')])
+
+ def test_io_add_watch_pyfile(self):
+ call_data = []
+
+ cmd = subprocess.Popen('sleep 0.1; echo hello; sleep 0.2; echo world',
+ shell=True, stdout=subprocess.PIPE)
+
+ def cb(file, condition):
+ call_data.append((file, condition, file.readline()))
+ return True
+
+ # io_add_watch() takes an IOChannel, calling with a Python file is deprecated
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always')
+ GLib.io_add_watch(cmd.stdout, GLib.IOCondition.IN, cb)
+ self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+ ml = GLib.MainLoop()
+ GLib.timeout_add(400, ml.quit)
+ ml.run()
+
+ cmd.wait()
+
+ self.assertEqual(call_data, [(cmd.stdout, GLib.IOCondition.IN, b'hello\n'),
+ (cmd.stdout, GLib.IOCondition.IN, b'world\n')])
+
+ def test_glib_version(self):
+ (major, minor, micro) = GLib.glib_version
+ self.assertGreaterEqual(major, 2)
+ self.assertGreaterEqual(minor, 0)
+ self.assertGreaterEqual(micro, 0)
+
+ def test_pyglib_version(self):
+ (major, minor, micro) = GLib.pyglib_version
+ self.assertGreaterEqual(major, 3)
+ self.assertGreaterEqual(minor, 7)
+ self.assertGreaterEqual(micro, 2)
diff --git a/tests/test_gobject.py b/tests/test_gobject.py
index a28a145..99f471b 100644
--- a/tests/test_gobject.py
+++ b/tests/test_gobject.py
@@ -1,37 +1,93 @@
# -*- Mode: Python -*-
+import sys
import gc
import unittest
+import warnings
from gi.repository import GObject
-import sys
+from gi import PyGIDeprecationWarning
+from gi.module import get_introspection_module
+from gi._gobject import _gobject
+
import testhelper
class TestGObjectAPI(unittest.TestCase):
- def testGObjectModule(self):
- obj = GObject.GObject()
+ def test_gobject_inheritance(self):
+ # GObject.Object is a class hierarchy as follows:
+ # overrides.Object -> introspection.Object -> static.GObject
+ GIObjectModule = get_introspection_module('GObject')
+ self.assertTrue(issubclass(GObject.Object, GIObjectModule.Object))
+ self.assertTrue(issubclass(GIObjectModule.Object, _gobject.GObject))
+
+ self.assertEqual(_gobject.GObject.__gtype__, GObject.TYPE_OBJECT)
+ self.assertEqual(GIObjectModule.Object.__gtype__, GObject.TYPE_OBJECT)
+ self.assertEqual(GObject.Object.__gtype__, GObject.TYPE_OBJECT)
+
+ # The pytype wrapper should hold the outer most Object class from overrides.
+ self.assertEqual(GObject.TYPE_OBJECT.pytype, GObject.Object)
+
+ @unittest.skipIf(sys.version_info[:2] < (2, 7), 'Python 2.7 is required')
+ def test_gobject_unsupported_overrides(self):
+ obj = GObject.Object()
+
+ with self.assertRaisesRegex(RuntimeError, 'Data access methods are unsupported.*'):
+ obj.get_data()
+
+ with self.assertRaisesRegex(RuntimeError, 'This method is currently unsupported.*'):
+ obj.force_floating()
+
+ def test_compat_api(self):
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always')
+ # GObject formerly exposed a lot of GLib's functions
+ self.assertEqual(GObject.markup_escape_text('foo'), 'foo')
+
+ ml = GObject.MainLoop()
+ self.assertFalse(ml.is_running())
- self.assertEqual(obj.__module__,
- 'gi._gobject._gobject')
+ context = GObject.main_context_default()
+ self.assertTrue(context.pending() in [False, True])
+
+ context = GObject.MainContext()
+ self.assertFalse(context.pending())
+
+ self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
+ self.assertTrue('GLib.markup_escape_text' in str(w[0]), str(w[0]))
+
+ self.assertLess(GObject.PRIORITY_HIGH, GObject.PRIORITY_DEFAULT)
+
+ def test_min_max_int(self):
+ self.assertEqual(GObject.G_MAXINT16, 2 ** 15 - 1)
+ self.assertEqual(GObject.G_MININT16, -2 ** 15)
+ self.assertEqual(GObject.G_MAXUINT16, 2 ** 16 - 1)
+
+ self.assertEqual(GObject.G_MAXINT32, 2 ** 31 - 1)
+ self.assertEqual(GObject.G_MININT32, -2 ** 31)
+ self.assertEqual(GObject.G_MAXUINT32, 2 ** 32 - 1)
+
+ self.assertEqual(GObject.G_MAXINT64, 2 ** 63 - 1)
+ self.assertEqual(GObject.G_MININT64, -2 ** 63)
+ self.assertEqual(GObject.G_MAXUINT64, 2 ** 64 - 1)
class TestReferenceCounting(unittest.TestCase):
- def testRegularObject(self):
+ def test_regular_object(self):
obj = GObject.GObject()
self.assertEqual(obj.__grefcount__, 1)
obj = GObject.new(GObject.GObject)
self.assertEqual(obj.__grefcount__, 1)
- def testFloating(self):
+ def test_floating(self):
obj = testhelper.Floating()
self.assertEqual(obj.__grefcount__, 1)
obj = GObject.new(testhelper.Floating)
self.assertEqual(obj.__grefcount__, 1)
- def testOwnedByLibrary(self):
+ def test_owned_by_library(self):
# Upon creation, the refcount of the object should be 2:
# - someone already has a reference on the new object.
# - the python wrapper should hold its own reference.
@@ -44,7 +100,7 @@ class TestReferenceCounting(unittest.TestCase):
obj.release()
self.assertEqual(obj.__grefcount__, 1)
- def testOwnedByLibraryOutOfScope(self):
+ def test_owned_by_library_out_of_scope(self):
obj = testhelper.OwnedByLibrary()
self.assertEqual(obj.__grefcount__, 2)
@@ -62,7 +118,7 @@ class TestReferenceCounting(unittest.TestCase):
obj.release()
self.assertEqual(obj.__grefcount__, 1)
- def testOwnedByLibraryUsingGObjectNew(self):
+ def test_owned_by_library_using_gobject_new(self):
# Upon creation, the refcount of the object should be 2:
# - someone already has a reference on the new object.
# - the python wrapper should hold its own reference.
@@ -75,7 +131,7 @@ class TestReferenceCounting(unittest.TestCase):
obj.release()
self.assertEqual(obj.__grefcount__, 1)
- def testOwnedByLibraryOutOfScopeUsingGobjectNew(self):
+ def test_owned_by_library_out_of_scope_using_gobject_new(self):
obj = GObject.new(testhelper.OwnedByLibrary)
self.assertEqual(obj.__grefcount__, 2)
@@ -93,7 +149,7 @@ class TestReferenceCounting(unittest.TestCase):
obj.release()
self.assertEqual(obj.__grefcount__, 1)
- def testFloatingAndSunk(self):
+ def test_floating_and_sunk(self):
# Upon creation, the refcount of the object should be 2:
# - someone already has a reference on the new object.
# - the python wrapper should hold its own reference.
@@ -106,7 +162,7 @@ class TestReferenceCounting(unittest.TestCase):
obj.release()
self.assertEqual(obj.__grefcount__, 1)
- def testFloatingAndSunkOutOfScope(self):
+ def test_floating_and_sunk_out_of_scope(self):
obj = testhelper.FloatingAndSunk()
self.assertEqual(obj.__grefcount__, 2)
@@ -124,7 +180,7 @@ class TestReferenceCounting(unittest.TestCase):
obj.release()
self.assertEqual(obj.__grefcount__, 1)
- def testFloatingAndSunkUsingGObjectNew(self):
+ def test_floating_and_sunk_using_gobject_new(self):
# Upon creation, the refcount of the object should be 2:
# - someone already has a reference on the new object.
# - the python wrapper should hold its own reference.
@@ -137,7 +193,7 @@ class TestReferenceCounting(unittest.TestCase):
obj.release()
self.assertEqual(obj.__grefcount__, 1)
- def testFloatingAndSunkOutOfScopeUsingGObjectNew(self):
+ def test_floating_and_sunk_out_of_scope_using_gobject_new(self):
obj = GObject.new(testhelper.FloatingAndSunk)
self.assertEqual(obj.__grefcount__, 2)
@@ -155,7 +211,7 @@ class TestReferenceCounting(unittest.TestCase):
obj.release()
self.assertEqual(obj.__grefcount__, 1)
- def testUninitializedObject(self):
+ def test_uninitialized_object(self):
class Obj(GObject.GObject):
def __init__(self):
x = self.__grefcount__
@@ -176,19 +232,19 @@ class TestPythonReferenceCounting(unittest.TestCase):
# Newly created instances should alwayshave two references: one for
# the GC, and one for the bound variable in the local scope.
- def testNewInstanceHasTwoRefs(self):
+ def test_new_instance_has_two_refs(self):
obj = GObject.GObject()
self.assertEqual(sys.getrefcount(obj), 2)
- def testNewInstanceHasTwoRefsUsingGObjectNew(self):
+ def test_new_instance_has_two_refs_using_gobject_new(self):
obj = GObject.new(GObject.GObject)
self.assertEqual(sys.getrefcount(obj), 2)
- def testNewSubclassInstanceHasTwoRefs(self):
+ def test_new_subclass_instance_has_two_refs(self):
obj = A()
self.assertEqual(sys.getrefcount(obj), 2)
- def testNewSubclassInstanceHasTwoRefsUsingGObjectNew(self):
+ def test_new_subclass_instance_has_two_refs_using_gobject_new(self):
obj = GObject.new(A)
self.assertEqual(sys.getrefcount(obj), 2)
@@ -206,7 +262,7 @@ class TestContextManagers(unittest.TestCase):
self.obj = self.ContextTestObject()
self.handler = self.obj.connect('notify::prop', self.on_prop_set)
- def testFreezeNotifyContext(self):
+ def test_freeze_notify_context(self):
# Verify prop tracking list
self.assertEqual(self.tracking, [])
self.obj.props.prop = 1
@@ -215,22 +271,28 @@ class TestContextManagers(unittest.TestCase):
self.assertEqual(self.tracking, [1, 2])
self.assertEqual(self.obj.__grefcount__, 1)
- # Using the context manager the tracking list should not be affected
- # and the GObject reference count should go up.
+ pyref_count = sys.getrefcount(self.obj)
+
+ # Using the context manager the tracking list should not be affected.
+ # The GObject reference count should stay the same and the python
+ # object ref-count should go up.
with self.obj.freeze_notify():
- self.assertEqual(self.obj.__grefcount__, 2)
+ self.assertEqual(self.obj.__grefcount__, 1)
+ self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1)
self.obj.props.prop = 3
self.assertEqual(self.obj.props.prop, 3)
self.assertEqual(self.tracking, [1, 2])
# After the context manager, the prop should have been modified,
- # the tracking list will be modified, and the GObject ref
+ # the tracking list will be modified, and the python object ref
# count goes back down.
+ gc.collect()
self.assertEqual(self.obj.props.prop, 3)
self.assertEqual(self.tracking, [1, 2, 3])
self.assertEqual(self.obj.__grefcount__, 1)
+ self.assertEqual(sys.getrefcount(self.obj), pyref_count)
- def testHandlerBlockContext(self):
+ def test_handler_block_context(self):
# Verify prop tracking list
self.assertEqual(self.tracking, [])
self.obj.props.prop = 1
@@ -239,10 +301,14 @@ class TestContextManagers(unittest.TestCase):
self.assertEqual(self.tracking, [1, 2])
self.assertEqual(self.obj.__grefcount__, 1)
- # Using the context manager the tracking list should not be affected
- # and the GObject reference count should go up.
+ pyref_count = sys.getrefcount(self.obj)
+
+ # Using the context manager the tracking list should not be affected.
+ # The GObject reference count should stay the same and the python
+ # object ref-count should go up.
with self.obj.handler_block(self.handler):
- self.assertEqual(self.obj.__grefcount__, 2)
+ self.assertEqual(self.obj.__grefcount__, 1)
+ self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1)
self.obj.props.prop = 3
self.assertEqual(self.obj.props.prop, 3)
self.assertEqual(self.tracking, [1, 2])
@@ -250,11 +316,13 @@ class TestContextManagers(unittest.TestCase):
# After the context manager, the prop should have been modified
# the tracking list should have stayed the same and the GObject ref
# count goes back down.
+ gc.collect()
self.assertEqual(self.obj.props.prop, 3)
self.assertEqual(self.tracking, [1, 2])
self.assertEqual(self.obj.__grefcount__, 1)
+ self.assertEqual(sys.getrefcount(self.obj), pyref_count)
- def testFreezeNotifyContextNested(self):
+ def test_freeze_notify_context_nested(self):
self.assertEqual(self.tracking, [])
with self.obj.freeze_notify():
self.obj.props.prop = 1
@@ -274,7 +342,7 @@ class TestContextManagers(unittest.TestCase):
# and the last one sent.
self.assertEqual(self.tracking, [3])
- def testHandlerBlockContextNested(self):
+ def test_handler_block_context_nested(self):
self.assertEqual(self.tracking, [])
with self.obj.handler_block(self.handler):
self.obj.props.prop = 1
@@ -295,7 +363,7 @@ class TestContextManagers(unittest.TestCase):
self.assertEqual(self.obj.props.prop, 3)
self.assertEqual(self.tracking, [])
- def testFreezeNotifyNormalUsageRefCounts(self):
+ def test_freeze_notify_normal_usage_ref_counts(self):
# Ensure ref counts without using methods as context managers
# maintain the same count.
self.assertEqual(self.obj.__grefcount__, 1)
@@ -304,14 +372,14 @@ class TestContextManagers(unittest.TestCase):
self.obj.thaw_notify()
self.assertEqual(self.obj.__grefcount__, 1)
- def testHandlerBlockNormalUsageRefCounts(self):
+ def test_handler_block_normal_usage_ref_counts(self):
self.assertEqual(self.obj.__grefcount__, 1)
self.obj.handler_block(self.handler)
self.assertEqual(self.obj.__grefcount__, 1)
self.obj.handler_unblock(self.handler)
self.assertEqual(self.obj.__grefcount__, 1)
- def testFreezeNotifyContextError(self):
+ def test_freeze_notify_context_error(self):
# Test an exception occurring within a freeze context exits the context
try:
with self.obj.freeze_notify():
@@ -329,7 +397,7 @@ class TestContextManagers(unittest.TestCase):
self.obj.props.prop = 2
self.assertEqual(self.tracking, [1, 2])
- def testHandlerBlockContextError(self):
+ def test_handler_block_context_error(self):
# Test an exception occurring within a handler block exits the context
try:
with self.obj.handler_block(self.handler):
@@ -356,7 +424,7 @@ class TestPropertyBindings(unittest.TestCase):
self.source = self.TestObject()
self.target = self.TestObject()
- def testDefaultBinding(self):
+ def test_default_binding(self):
binding = self.source.bind_property('int_prop', self.target, 'int_prop',
GObject.BindingFlags.DEFAULT)
binding = binding # PyFlakes
@@ -371,7 +439,7 @@ class TestPropertyBindings(unittest.TestCase):
self.assertEqual(self.source.int_prop, 1)
self.assertEqual(self.target.int_prop, 2)
- def testBiDirectionalBinding(self):
+ def test_bidirectional_binding(self):
binding = self.source.bind_property('int_prop', self.target, 'int_prop',
GObject.BindingFlags.BIDIRECTIONAL)
binding = binding # PyFlakes
@@ -386,7 +454,7 @@ class TestPropertyBindings(unittest.TestCase):
self.assertEqual(self.source.int_prop, 2)
self.assertEqual(self.target.int_prop, 2)
- def testTransformToOnly(self):
+ def test_transform_to_only(self):
def transform_to(binding, value, user_data=None):
self.assertEqual(user_data, 'test-data')
return value * 2
@@ -404,7 +472,7 @@ class TestPropertyBindings(unittest.TestCase):
self.assertEqual(self.source.int_prop, 1)
self.assertEqual(self.target.int_prop, 1)
- def testTransformFromOnly(self):
+ def test_transform_from_only(self):
def transform_from(binding, value, user_data=None):
self.assertEqual(user_data, None)
return value * 2
@@ -422,7 +490,7 @@ class TestPropertyBindings(unittest.TestCase):
self.assertEqual(self.source.int_prop, 2)
self.assertEqual(self.target.int_prop, 1)
- def testTransformBidrectional(self):
+ def test_transform_bidirectional(self):
def transform_to(binding, value, user_data=None):
self.assertEqual(user_data, 'test-data')
return value * 2
@@ -445,7 +513,7 @@ class TestPropertyBindings(unittest.TestCase):
self.assertEqual(self.source.int_prop, 2)
self.assertEqual(self.target.int_prop, 4)
- def testExplicitUnbindClearsConnection(self):
+ def test_explicit_unbind_clears_connection(self):
self.assertEqual(self.source.int_prop, 0)
self.assertEqual(self.target.int_prop, 0)
@@ -465,7 +533,7 @@ class TestPropertyBindings(unittest.TestCase):
# An already unbound BindingWeakRef will raise if unbind is attempted a second time.
self.assertRaises(ValueError, binding.unbind)
- def testReferenceCounts(self):
+ def test_reference_counts(self):
self.assertEqual(self.source.__grefcount__, 1)
self.assertEqual(self.target.__grefcount__, 1)
diff --git a/tests/test_gtype.py b/tests/test_gtype.py
new file mode 100644
index 0000000..dec716e
--- /dev/null
+++ b/tests/test_gtype.py
@@ -0,0 +1,53 @@
+import unittest
+
+from gi.repository import GObject
+from gi.repository import GIMarshallingTests
+
+
+class CustomBase(GObject.GObject):
+ pass
+
+
+class CustomChild(CustomBase, GIMarshallingTests.Interface):
+ pass
+
+
+class TestTypeModuleLevelFunctions(unittest.TestCase):
+ def test_type_name(self):
+ self.assertEqual(GObject.type_name(GObject.TYPE_NONE), 'void')
+ self.assertEqual(GObject.type_name(GObject.TYPE_OBJECT), 'GObject')
+ self.assertEqual(GObject.type_name(GObject.TYPE_PYOBJECT), 'PyObject')
+
+ def test_type_from_name(self):
+ # A complete test is not needed here since the TYPE_* defines are created
+ # using this method.
+ self.assertRaises(RuntimeError, GObject.type_from_name, '!NOT_A_REAL_TYPE!')
+ self.assertEqual(GObject.type_from_name('GObject'), GObject.TYPE_OBJECT)
+ self.assertEqual(GObject.type_from_name('GObject'), GObject.GObject.__gtype__)
+
+ def test_type_is_a(self):
+ self.assertTrue(GObject.type_is_a(CustomBase, GObject.TYPE_OBJECT))
+ self.assertTrue(GObject.type_is_a(CustomChild, CustomBase))
+ self.assertTrue(GObject.type_is_a(CustomBase, GObject.GObject))
+ self.assertTrue(GObject.type_is_a(CustomBase.__gtype__, GObject.TYPE_OBJECT))
+ self.assertFalse(GObject.type_is_a(GObject.TYPE_OBJECT, CustomBase))
+ self.assertFalse(GObject.type_is_a(CustomBase, int)) # invalid type
+ self.assertRaises(TypeError, GObject.type_is_a, CustomBase, 1)
+ self.assertRaises(TypeError, GObject.type_is_a, 2, GObject.TYPE_OBJECT)
+ self.assertRaises(TypeError, GObject.type_is_a, 1, 2)
+
+ def test_type_children(self):
+ self.assertSequenceEqual(GObject.type_children(CustomBase),
+ [CustomChild.__gtype__])
+ self.assertEqual(len(GObject.type_children(CustomChild)), 0)
+
+ def test_type_interfaces(self):
+ self.assertEqual(len(GObject.type_interfaces(CustomBase)), 0)
+ self.assertEqual(len(GObject.type_interfaces(CustomChild)), 1)
+ self.assertSequenceEqual(GObject.type_interfaces(CustomChild),
+ [GIMarshallingTests.Interface.__gtype__])
+
+ def test_type_parent(self):
+ self.assertEqual(GObject.type_parent(CustomChild), CustomBase.__gtype__)
+ self.assertEqual(GObject.type_parent(CustomBase), GObject.TYPE_OBJECT)
+ self.assertRaises(RuntimeError, GObject.type_parent, GObject.GObject)
diff --git a/tests/test_interface.py b/tests/test_interface.py
index 2df61b1..dd01af8 100644
--- a/tests/test_interface.py
+++ b/tests/test_interface.py
@@ -37,12 +37,12 @@ GObject.type_register(MyObject)
class TestIfaceImpl(unittest.TestCase):
- def testReImplementInterface(self):
+ def test_reimplement_interface(self):
m = MyUnknown()
m.iface_method()
self.assertEqual(m.called, True)
- def testImplementInterface(self):
+ def test_implement_interface(self):
m = MyObject()
m.iface_method()
self.assertEqual(m.called, True)
diff --git a/tests/test_iochannel.py b/tests/test_iochannel.py
new file mode 100644
index 0000000..0cc1b4b
--- /dev/null
+++ b/tests/test_iochannel.py
@@ -0,0 +1,424 @@
+# -*- Mode: Python -*-
+# encoding: UTF-8
+from __future__ import unicode_literals
+
+import unittest
+import tempfile
+import os.path
+import fcntl
+import shutil
+import warnings
+
+from gi.repository import GLib
+from gi import PyGIDeprecationWarning
+
+from compathelper import _unicode
+
+
+class IOChannel(unittest.TestCase):
+ def setUp(self):
+ self.workdir = tempfile.mkdtemp()
+
+ self.testutf8 = os.path.join(self.workdir, 'testutf8.txt')
+ with open(self.testutf8, 'wb') as f:
+ f.write('''hello ♥ world
+second line
+
+À demain!'''.encode('UTF-8'))
+
+ self.testlatin1 = os.path.join(self.workdir, 'testlatin1.txt')
+ with open(self.testlatin1, 'wb') as f:
+ f.write(b'''hell\xf8 world
+second line
+
+\xc0 demain!''')
+
+ self.testout = os.path.join(self.workdir, 'testout.txt')
+
+ def tearDown(self):
+ shutil.rmtree(self.workdir)
+
+ def test_file_readline_utf8(self):
+ ch = GLib.IOChannel(filename=self.testutf8)
+ self.assertEqual(ch.get_encoding(), 'UTF-8')
+ self.assertTrue(ch.get_close_on_unref())
+ self.assertEqual(_unicode(ch.readline()), 'hello ♥ world\n')
+ self.assertEqual(ch.get_buffer_condition(), GLib.IOCondition.IN)
+ self.assertEqual(ch.readline(), 'second line\n')
+ self.assertEqual(ch.readline(), '\n')
+ self.assertEqual(_unicode(ch.readline()), 'À demain!')
+ self.assertEqual(ch.get_buffer_condition(), 0)
+ self.assertEqual(ch.readline(), '')
+ ch.close()
+
+ def test_file_readline_latin1(self):
+ ch = GLib.IOChannel(filename=self.testlatin1, mode='r')
+ ch.set_encoding('latin1')
+ self.assertEqual(ch.get_encoding(), 'latin1')
+ self.assertEqual(_unicode(ch.readline()), 'hellø world\n')
+ self.assertEqual(ch.readline(), 'second line\n')
+ self.assertEqual(ch.readline(), '\n')
+ self.assertEqual(_unicode(ch.readline()), 'À demain!')
+ ch.close()
+
+ def test_file_iter(self):
+ items = []
+ ch = GLib.IOChannel(filename=self.testutf8)
+ for item in ch:
+ items.append(item)
+ self.assertEqual(len(items), 4)
+ self.assertEqual(_unicode(items[0]), 'hello ♥ world\n')
+ ch.close()
+
+ def test_file_readlines(self):
+ ch = GLib.IOChannel(filename=self.testutf8)
+ lines = ch.readlines()
+ # Note, this really ought to be 4, but the static bindings add an extra
+ # empty one
+ self.assertGreaterEqual(len(lines), 4)
+ self.assertLessEqual(len(lines), 5)
+ self.assertEqual(_unicode(lines[0]), 'hello ♥ world\n')
+ self.assertEqual(_unicode(lines[3]), 'À demain!')
+ if len(lines) == 4:
+ self.assertEqual(lines[4], '')
+
+ def test_file_read(self):
+ ch = GLib.IOChannel(filename=self.testutf8)
+ with open(self.testutf8, 'rb') as f:
+ self.assertEqual(ch.read(), f.read())
+
+ ch = GLib.IOChannel(filename=self.testutf8)
+ with open(self.testutf8, 'rb') as f:
+ self.assertEqual(ch.read(10), f.read(10))
+
+ ch = GLib.IOChannel(filename=self.testutf8)
+ with open(self.testutf8, 'rb') as f:
+ self.assertEqual(ch.read(max_count=15), f.read(15))
+
+ def test_seek(self):
+ ch = GLib.IOChannel(filename=self.testutf8)
+ ch.seek(2)
+ self.assertEqual(ch.read(3), b'llo')
+
+ ch.seek(2, 0) # SEEK_SET
+ self.assertEqual(ch.read(3), b'llo')
+
+ ch.seek(1, 1) # SEEK_CUR, skip the space
+ self.assertEqual(ch.read(3), b'\xe2\x99\xa5')
+
+ ch.seek(2, 2) # SEEK_END
+ # FIXME: does not work currently
+ #self.assertEqual(ch.read(2), b'n!')
+
+ # invalid whence value
+ self.assertRaises(ValueError, ch.seek, 0, 3)
+
+ def test_file_write(self):
+ ch = GLib.IOChannel(filename=self.testout, mode='w')
+ ch.set_encoding('latin1')
+ ch.write('hellø world\n')
+ ch.close()
+ ch = GLib.IOChannel(filename=self.testout, mode='a')
+ ch.set_encoding('latin1')
+ ch.write('À demain!')
+ ch.close()
+
+ 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()
+
+ with open(self.testout, 'r') as f:
+ self.assertEqual(f.read(), 'foobar\nbaz\nend')
+
+ def test_buffering(self):
+ writer = GLib.IOChannel(filename=self.testout, mode='w')
+ writer.set_encoding(None)
+ self.assertTrue(writer.get_buffered())
+ self.assertGreater(writer.get_buffer_size(), 10)
+
+ reader = GLib.IOChannel(filename=self.testout, mode='r')
+
+ # does not get written immediately on buffering
+ writer.write('abc')
+ self.assertEqual(reader.read(), b'')
+ writer.flush()
+ self.assertEqual(reader.read(), b'abc')
+
+ # does get written immediately without buffering
+ writer.set_buffered(False)
+ writer.write('def')
+ self.assertEqual(reader.read(), b'def')
+
+ # writes after buffer overflow
+ writer.set_buffer_size(10)
+ writer.write('0123456789012')
+ self.assertTrue(reader.read().startswith(b'012'))
+ writer.flush()
+ reader.read() # ignore bits written after flushing
+
+ # closing flushes
+ writer.set_buffered(True)
+ writer.write('ghi')
+ writer.close()
+ self.assertEqual(reader.read(), b'ghi')
+ reader.close()
+
+ def test_fd_read(self):
+ (r, w) = os.pipe()
+
+ ch = GLib.IOChannel(filedes=r)
+ ch.set_encoding(None)
+ ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK)
+ self.assertNotEqual(ch.get_flags() | GLib.IOFlags.NONBLOCK, 0)
+ self.assertEqual(ch.read(), b'')
+ os.write(w, b'\x01\x02')
+ self.assertEqual(ch.read(), b'\x01\x02')
+
+ # now test blocking case, after closing the write end
+ ch.set_flags(GLib.IOFlags(ch.get_flags() & ~GLib.IOFlags.NONBLOCK))
+ os.write(w, b'\x03\x04')
+ os.close(w)
+ self.assertEqual(ch.read(), b'\x03\x04')
+
+ ch.close()
+
+ def test_fd_write(self):
+ (r, w) = os.pipe()
+ fcntl.fcntl(r, fcntl.F_SETFL, fcntl.fcntl(r, fcntl.F_GETFL) | os.O_NONBLOCK)
+
+ ch = GLib.IOChannel(filedes=w, mode='w')
+ ch.set_encoding(None)
+ ch.set_buffered(False)
+ ch.write(b'\x01\x02')
+ self.assertEqual(os.read(r, 10), b'\x01\x02')
+
+ # 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()
+ self.assertEqual(os.read(r, 10), b'\x03\x04')
+ os.close(r)
+
+ def test_deprecated_method_add_watch_no_data(self):
+ (r, w) = os.pipe()
+
+ ch = GLib.IOChannel(filedes=r)
+ ch.set_encoding(None)
+ ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK)
+
+ cb_reads = []
+
+ def cb(channel, condition):
+ self.assertEqual(channel, ch)
+ self.assertEqual(condition, GLib.IOCondition.IN)
+ cb_reads.append(channel.read())
+ return True
+
+ # io_add_watch() method is deprecated, use GLib.io_add_watch
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always')
+ ch.add_watch(GLib.IOCondition.IN, cb)
+ self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+ ml = GLib.MainLoop()
+
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(cb_reads, [b'a', b'b'])
+
+ def test_deprecated_method_add_watch_data_priority(self):
+ (r, w) = os.pipe()
+
+ ch = GLib.IOChannel(filedes=r)
+ ch.set_encoding(None)
+ ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK)
+
+ cb_reads = []
+
+ def cb(channel, condition, data):
+ self.assertEqual(channel, ch)
+ self.assertEqual(condition, GLib.IOCondition.IN)
+ self.assertEqual(data, 'hello')
+ cb_reads.append(channel.read())
+ return True
+
+ ml = GLib.MainLoop()
+ # io_add_watch() method is deprecated, use GLib.io_add_watch
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always')
+ id = ch.add_watch(GLib.IOCondition.IN, cb, 'hello', priority=GLib.PRIORITY_HIGH)
+ self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(cb_reads, [b'a', b'b'])
+
+ def test_add_watch_no_data(self):
+ (r, w) = os.pipe()
+
+ ch = GLib.IOChannel(filedes=r)
+ ch.set_encoding(None)
+ ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK)
+
+ cb_reads = []
+
+ def cb(channel, condition):
+ self.assertEqual(channel, ch)
+ self.assertEqual(condition, GLib.IOCondition.IN)
+ cb_reads.append(channel.read())
+ return True
+
+ id = GLib.io_add_watch(ch, GLib.PRIORITY_HIGH, GLib.IOCondition.IN, cb)
+
+ ml = GLib.MainLoop()
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(cb_reads, [b'a', b'b'])
+
+ def test_add_watch_with_data(self):
+ (r, w) = os.pipe()
+
+ ch = GLib.IOChannel(filedes=r)
+ ch.set_encoding(None)
+ ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK)
+
+ cb_reads = []
+
+ def cb(channel, condition, data):
+ self.assertEqual(channel, ch)
+ self.assertEqual(condition, GLib.IOCondition.IN)
+ self.assertEqual(data, 'hello')
+ cb_reads.append(channel.read())
+ return True
+
+ id = GLib.io_add_watch(ch, GLib.PRIORITY_HIGH, GLib.IOCondition.IN, cb, 'hello')
+
+ ml = GLib.MainLoop()
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(cb_reads, [b'a', b'b'])
+
+ def test_add_watch_with_multi_data(self):
+ (r, w) = os.pipe()
+
+ ch = GLib.IOChannel(filedes=r)
+ ch.set_encoding(None)
+ ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK)
+
+ cb_reads = []
+
+ def cb(channel, condition, data1, data2, data3):
+ self.assertEqual(channel, ch)
+ self.assertEqual(condition, GLib.IOCondition.IN)
+ self.assertEqual(data1, 'a')
+ self.assertEqual(data2, 'b')
+ self.assertEqual(data3, 'c')
+ cb_reads.append(channel.read())
+ return True
+
+ id = GLib.io_add_watch(ch, GLib.PRIORITY_HIGH, GLib.IOCondition.IN, cb,
+ 'a', 'b', 'c')
+
+ ml = GLib.MainLoop()
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(cb_reads, [b'a', b'b'])
+
+ def test_deprecated_add_watch_no_data(self):
+ (r, w) = os.pipe()
+
+ ch = GLib.IOChannel(filedes=r)
+ ch.set_encoding(None)
+ ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK)
+
+ cb_reads = []
+
+ def cb(channel, condition):
+ self.assertEqual(channel, ch)
+ self.assertEqual(condition, GLib.IOCondition.IN)
+ cb_reads.append(channel.read())
+ return True
+
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always')
+ id = GLib.io_add_watch(ch, GLib.IOCondition.IN, cb, priority=GLib.PRIORITY_HIGH)
+ self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+ ml = GLib.MainLoop()
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(cb_reads, [b'a', b'b'])
+
+ def test_deprecated_add_watch_with_data(self):
+ (r, w) = os.pipe()
+
+ ch = GLib.IOChannel(filedes=r)
+ ch.set_encoding(None)
+ ch.set_flags(ch.get_flags() | GLib.IOFlags.NONBLOCK)
+
+ cb_reads = []
+
+ def cb(channel, condition, data):
+ self.assertEqual(channel, ch)
+ self.assertEqual(condition, GLib.IOCondition.IN)
+ self.assertEqual(data, 'hello')
+ cb_reads.append(channel.read())
+ return True
+
+ with warnings.catch_warnings(record=True) as warn:
+ warnings.simplefilter('always')
+ id = GLib.io_add_watch(ch, GLib.IOCondition.IN, cb, 'hello',
+ priority=GLib.PRIORITY_HIGH)
+ self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+ ml = GLib.MainLoop()
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+ GLib.timeout_add(100, lambda: os.write(w, b'b') and False)
+ GLib.timeout_add(200, ml.quit)
+ ml.run()
+
+ self.assertEqual(cb_reads, [b'a', b'b'])
+
+ def test_backwards_compat_flags(self):
+ self.assertEqual(GLib.IOCondition.IN, GLib.IO_IN)
+ 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()
diff --git a/tests/test_mainloop.py b/tests/test_mainloop.py
index 408a123..44197b3 100644
--- a/tests/test_mainloop.py
+++ b/tests/test_mainloop.py
@@ -34,7 +34,7 @@ class TestMainLoop(unittest.TestCase):
raise Exception("deadbabe")
loop = GLib.MainLoop()
- GLib.child_watch_add(pid, child_died, loop)
+ GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, child_died, loop)
os.close(pipe_r)
os.write(pipe_w, _bytes("Y"))
@@ -79,3 +79,19 @@ class TestMainLoop(unittest.TestCase):
loop2.quit()
finally:
signal.signal(signal.SIGUSR1, orig_handler)
+
+ def test_sigint(self):
+ pid = os.fork()
+ if pid == 0:
+ time.sleep(0.5)
+ os.kill(os.getppid(), signal.SIGINT)
+ os._exit(0)
+
+ loop = GLib.MainLoop()
+ try:
+ loop.run()
+ self.fail('expected KeyboardInterrupt exception')
+ except KeyboardInterrupt:
+ pass
+ self.assertFalse(loop.is_running())
+ os.waitpid(pid, 0)
diff --git a/tests/test_option.py b/tests/test_option.py
index 345d0ad..2900edd 100644
--- a/tests/test_option.py
+++ b/tests/test_option.py
@@ -10,17 +10,15 @@ try:
except ImportError:
from io import StringIO
-# FIXME: we need a way to import the options module from a public module
-from gi._glib.option import OptionParser, OptionGroup, OptionValueError, \
- make_option, BadOptionError
+from gi.repository import GLib
class TestOption(unittest.TestCase):
EXCEPTION_MESSAGE = "This callback fails"
def setUp(self):
- self.parser = OptionParser("NAMES...",
- description="Option unit test")
+ self.parser = GLib.option.OptionParser("NAMES...",
+ description="Option unit test")
self.parser.add_option("-t", "--test", help="Unit test option",
action="store_false", dest="test", default=True)
self.parser.add_option("--g-fatal-warnings",
@@ -32,22 +30,22 @@ class TestOption(unittest.TestCase):
def option_callback(option, opt, value, parser):
raise Exception(self.EXCEPTION_MESSAGE)
- group = OptionGroup(
+ group = GLib.option.OptionGroup(
"unittest", "Unit test options", "Show all unittest options",
option_list=[
- make_option("-f", "-u", "--file", "--unit-file",
- type="filename",
- dest="unit_file",
- help="Unit test option"),
- make_option("--test-integer",
- type="int",
- dest="test_integer",
- help="Unit integer option"),
- make_option("--callback-failure-test",
- action="callback",
- callback=option_callback,
- dest="test_integer",
- help="Unit integer option"),
+ GLib.option.make_option("-f", "-u", "--file", "--unit-file",
+ type="filename",
+ dest="unit_file",
+ help="Unit test option"),
+ GLib.option.make_option("--test-integer",
+ type="int",
+ dest="test_integer",
+ help="Unit integer option"),
+ GLib.option.make_option("--callback-failure-test",
+ action="callback",
+ callback=option_callback,
+ dest="test_integer",
+ help="Unit integer option"),
])
group.add_option("-t", "--test",
action="store_false",
@@ -57,7 +55,7 @@ class TestOption(unittest.TestCase):
self.parser.add_option_group(group)
return group
- def testParseArgs(self):
+ def test_parse_args(self):
options, args = self.parser.parse_args(
["test_option.py"])
self.assertFalse(args)
@@ -70,12 +68,12 @@ class TestOption(unittest.TestCase):
["test_option.py", "foo", "bar"])
self.assertEqual(args, [])
- def testParseArgsDoubleDash(self):
+ def test_parse_args_double_dash(self):
options, args = self.parser.parse_args(
["test_option.py", "--", "-xxx"])
#self.assertEqual(args, ["-xxx"])
- def testParseArgsGroup(self):
+ def test_parse_args_group(self):
group = self._create_group()
options, args = self.parser.parse_args(
@@ -89,20 +87,20 @@ class TestOption(unittest.TestCase):
self.assertEqual(group.values.unit_file, "test")
self.assertFalse(args)
- def testOptionValueError(self):
+ def test_option_value_error(self):
self._create_group()
- self.assertRaises(OptionValueError, self.parser.parse_args,
+ self.assertRaises(GLib.option.OptionValueError, self.parser.parse_args,
["test_option.py", "--test-integer=text"])
- def testBadOptionError(self):
- self.assertRaises(BadOptionError,
+ def test_bad_option_error(self):
+ self.assertRaises(GLib.option.BadOptionError,
self.parser.parse_args,
["test_option.py", "--unknwon-option"])
- def testOptionGroupConstructor(self):
- self.assertRaises(TypeError, OptionGroup)
+ def test_option_group_constructor(self):
+ self.assertRaises(TypeError, GLib.option.OptionGroup)
- def testStandardError(self):
+ def test_standard_error(self):
self._create_group()
sio = StringIO()
old_stderr = sys.stderr
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index dd2aa6a..e1af1f1 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -4,6 +4,8 @@
import unittest
import gi.overrides
+import gi.module
+
try:
from gi.repository import Regress
Regress # pyflakes
@@ -27,3 +29,30 @@ class TestRegistry(unittest.TestCase):
# Regress override is in tests/gi/overrides, separate from gi/overrides
# https://bugzilla.gnome.org/show_bug.cgi?id=680913
self.assertEqual(Regress.REGRESS_OVERRIDE, 42)
+
+
+class TestModule(unittest.TestCase):
+ # Tests for gi.module
+
+ def test_get_introspection_module_caching(self):
+ # This test attempts to minimize side effects by
+ # using a DynamicModule directly instead of going though:
+ # from gi.repository import Foo
+
+ # Clear out introspection module cache before running this test.
+ old_modules = gi.module._introspection_modules
+ gi.module._introspection_modules = {}
+
+ mod_name = 'GIMarshallingTests'
+ mod1 = gi.module.get_introspection_module(mod_name)
+ mod2 = gi.module.get_introspection_module(mod_name)
+ self.assertTrue(mod1 is mod2)
+
+ # Using a DynamicModule will use get_introspection_module internally
+ # in its _load method.
+ mod_overridden = gi.module.DynamicModule(mod_name)
+ mod_overridden._load()
+ self.assertTrue(mod1 is mod_overridden._introspection_module)
+
+ # Restore the previous cache
+ gi.module._introspection_modules = old_modules
diff --git a/tests/test_overrides_gtk.py b/tests/test_overrides_gtk.py
index ee41457..6148479 100644
--- a/tests/test_overrides_gtk.py
+++ b/tests/test_overrides_gtk.py
@@ -2,8 +2,6 @@
# vim: tabstop=4 shiftwidth=4 expandtab
import unittest
-import ctypes
-import sys
from compathelper import _unicode, _bytes
@@ -18,19 +16,6 @@ except ImportError:
Gtk = None
-class RawTreeIter(ctypes.Structure):
- """Class used for testing Gtk.TreeIter raw data."""
- _fields_ = [('stamp', ctypes.c_int),
- ('user_data', ctypes.c_void_p),
- ('user_data2', ctypes.c_void_p),
- ('user_data3', ctypes.c_void_p)]
-
- @classmethod
- def from_iter(cls, iter):
- offset = sys.getsizeof(object()) # size of PyObject_HEAD
- return ctypes.POINTER(cls).from_address(id(iter) + offset)
-
-
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestGtk(unittest.TestCase):
def test_container(self):
@@ -1324,13 +1309,14 @@ class TestTreeView(unittest.TestCase):
# will raise a Gtk-CRITICAL which we ignore for now
old_mask = GLib.log_set_always_fatal(
GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_ERROR)
- view.set_cursor(store[1].path)
- view.set_cursor(str(store[1].path))
+ try:
+ view.set_cursor(store[1].path)
+ view.set_cursor(str(store[1].path))
- view.get_cell_area(store[1].path)
- view.get_cell_area(str(store[1].path))
-
- GLib.log_set_always_fatal(old_mask)
+ view.get_cell_area(store[1].path)
+ view.get_cell_area(str(store[1].path))
+ finally:
+ GLib.log_set_always_fatal(old_mask)
def test_tree_view_column(self):
cell = Gtk.CellRendererText()
@@ -1361,10 +1347,12 @@ class TestTreeView(unittest.TestCase):
# 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)
- # causes the widget to get realized and cellN.props.text receive a
- # value, otherwise it will be None.
- tree.get_preferred_size()
- GLib.log_set_always_fatal(old_mask)
+ try:
+ # causes the widget to get realized and cellN.props.text receive a
+ # value, otherwise it will be None.
+ tree.get_preferred_size()
+ finally:
+ GLib.log_set_always_fatal(old_mask)
self.assertEqual(tree.get_column(0).get_title(), 'Head1')
self.assertEqual(tree.get_column(1).get_title(), 'Head2')
@@ -1396,10 +1384,12 @@ class TestTreeView(unittest.TestCase):
# 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)
- # This will make cell.props.text receive a value, otherwise it
- # will be None.
- treeview.get_preferred_size()
- GLib.log_set_always_fatal(old_mask)
+ try:
+ # This will make cell.props.text receive a value, otherwise it
+ # will be None.
+ treeview.get_preferred_size()
+ finally:
+ GLib.log_set_always_fatal(old_mask)
self.assertTrue(cell.props.text in directors)
@@ -1432,32 +1422,6 @@ class TestTreeView(unittest.TestCase):
self.assertEqual(m, store)
self.assertEqual(store.get_path(s), firstpath)
- def test_tree_iter_user_data_int(self):
- pyiter = Gtk.TreeIter()
- rawiter = RawTreeIter.from_iter(pyiter)
-
- initial_ref_count = sys.getrefcount(1)
- pyiter.user_data = 1
-
- # verify setting int value increases refcount of the "1" object
- self.assertEqual(sys.getrefcount(1), initial_ref_count + 1)
- # verify the address of the '1' object is what user_data is actually set to.
- self.assertEqual(id(1), rawiter.contents.user_data)
-
- def test_tree_iter_user_data_null(self):
- pyiter = Gtk.TreeIter()
- rawiter = RawTreeIter.from_iter(pyiter)
-
- self.assertEqual(pyiter.user_data, None)
- self.assertEqual(rawiter.contents.user_data, None)
-
- # Setting user_data to None should not increase None's ref count.
- # and the raw iters user_data should also come back as None/NULL.
- initial_ref_count = sys.getrefcount(None)
- pyiter.user_data = None
- self.assertEqual(sys.getrefcount(None), initial_ref_count)
- self.assertEqual(rawiter.contents.user_data, None)
-
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestTextBuffer(unittest.TestCase):
diff --git a/tests/test_properties.py b/tests/test_properties.py
index 490b1ae..ccb80a6 100644
--- a/tests/test_properties.py
+++ b/tests/test_properties.py
@@ -13,13 +13,14 @@ from gi.repository.GObject import \
TYPE_UINT64, TYPE_GTYPE, TYPE_INVALID, TYPE_NONE, TYPE_STRV, \
TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_BOOLEAN, TYPE_FLOAT, \
TYPE_DOUBLE, TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, \
- TYPE_STRING, TYPE_PYOBJECT
+ TYPE_STRING, TYPE_PYOBJECT, TYPE_VARIANT
from gi.repository.GObject import \
G_MININT, G_MAXINT, G_MAXUINT, G_MINLONG, G_MAXLONG, G_MAXULONG
from gi.repository import Gio
from gi.repository import GLib
+from gi.repository import Regress
from gi.repository import GIMarshallingTests
from gi._gobject import propertyhelper
@@ -60,6 +61,42 @@ class PropertyObject(GObject.GObject):
strings = GObject.Property(
type=TYPE_STRV, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
+ variant = GObject.Property(
+ type=TYPE_VARIANT, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
+
+ variant_def = GObject.Property(
+ type=TYPE_VARIANT, flags=PARAM_READWRITE | PARAM_CONSTRUCT,
+ default=GLib.Variant('i', 42))
+
+
+class PropertyInheritanceObject(Regress.TestObj):
+ # override property from the base class, with a different type
+ string = GObject.Property(type=int)
+
+ # a property entirely defined at the Python level
+ python_prop = GObject.Property(type=str)
+
+
+class PropertySubClassObject(PropertyInheritanceObject):
+ # override property from the base class, with a different type
+ python_prop = GObject.Property(type=int)
+
+
+class TestPropertyInheritanceObject(unittest.TestCase):
+ def test_override_gi_property(self):
+ self.assertNotEqual(Regress.TestObj.props.string.value_type,
+ PropertyInheritanceObject.props.string.value_type)
+ obj = PropertyInheritanceObject()
+ self.assertEqual(type(obj.props.string), int)
+ obj.props.string = 4
+ self.assertEqual(obj.props.string, 4)
+
+ def test_override_python_property(self):
+ obj = PropertySubClassObject()
+ self.assertEqual(type(obj.props.python_prop), int)
+ obj.props.python_prop = 5
+ self.assertEqual(obj.props.python_prop, 5)
+
class TestPropertyObject(unittest.TestCase):
def test_get_set(self):
@@ -82,19 +119,24 @@ class TestPropertyObject(unittest.TestCase):
def test_iteration(self):
for obj in (PropertyObject.props, PropertyObject().props):
+ names = []
for pspec in obj:
gtype = GType(pspec)
self.assertEqual(gtype.parent.name, 'GParam')
- self.assertTrue(pspec.name in ['normal',
- 'construct',
- 'construct-only',
- 'uint64',
- 'enum',
- 'flags',
- 'gtype',
- 'strings',
- 'boxed'])
- self.assertEqual(len(obj), 9)
+ names.append(pspec.name)
+
+ names.sort()
+ self.assertEqual(names, ['boxed',
+ 'construct',
+ 'construct-only',
+ 'enum',
+ 'flags',
+ 'gtype',
+ 'normal',
+ 'strings',
+ 'uint64',
+ 'variant',
+ 'variant-def'])
def test_normal(self):
obj = new(PropertyObject, normal="123")
@@ -300,6 +342,52 @@ class TestPropertyObject(unittest.TestCase):
self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
default=['hello', 1])
+ def test_variant(self):
+ obj = new(PropertyObject)
+
+ self.assertEqual(obj.props.variant, None)
+ self.assertEqual(obj.variant, None)
+
+ obj.variant = GLib.Variant('s', 'hello')
+ self.assertEqual(obj.variant.print_(True), "'hello'")
+
+ obj.variant = GLib.Variant('b', True)
+ self.assertEqual(obj.variant.print_(True), "true")
+
+ obj.props.variant = GLib.Variant('y', 2)
+ self.assertEqual(obj.variant.print_(True), "byte 0x02")
+
+ obj.variant = None
+ self.assertEqual(obj.variant, None)
+
+ # set in constructor
+ obj = new(PropertyObject, variant=GLib.Variant('u', 5))
+ self.assertEqual(obj.props.variant.print_(True), 'uint32 5')
+
+ GObject.Property(type=TYPE_VARIANT, default=GLib.Variant('i', 1))
+
+ # incompatible types
+ self.assertRaises(TypeError, setattr, obj, 'variant', 'foo')
+ self.assertRaises(TypeError, setattr, obj, 'variant', 42)
+
+ self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT,
+ default='foo')
+ self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT,
+ default=object())
+
+ def test_variant_default(self):
+ obj = new(PropertyObject)
+
+ self.assertEqual(obj.props.variant_def.print_(True), '42')
+ self.assertEqual(obj.variant_def.print_(True), '42')
+
+ obj.props.variant_def = GLib.Variant('y', 2)
+ self.assertEqual(obj.variant_def.print_(True), "byte 0x02")
+
+ # set in constructor
+ obj = new(PropertyObject, variant_def=GLib.Variant('u', 5))
+ self.assertEqual(obj.props.variant_def.print_(True), 'uint32 5')
+
def test_range(self):
# kiwi code
def max(c):
@@ -689,14 +777,20 @@ class TestProperty(unittest.TestCase):
del t
self.assertEqual(sys.getrefcount(o), rc)
- def test_doc_string_as_blurb(self):
+ def test_doc_strings(self):
class C(GObject.GObject):
+ foo_blurbed = GObject.Property(type=int, blurb='foo_blurbed doc string')
+
@GObject.Property
- def blurbed(self):
- """blurbed doc string"""
+ def foo_getter(self):
+ """foo_getter doc string"""
return 0
- self.assertEqual(C.blurbed.blurb, 'blurbed doc string')
+ self.assertEqual(C.foo_blurbed.blurb, 'foo_blurbed doc string')
+ self.assertEqual(C.foo_blurbed.__doc__, 'foo_blurbed doc string')
+
+ self.assertEqual(C.foo_getter.blurb, 'foo_getter doc string')
+ self.assertEqual(C.foo_getter.__doc__, 'foo_getter doc string')
def test_python_to_glib_type_mapping(self):
tester = GObject.Property()
diff --git a/tests/test_signal.py b/tests/test_signal.py
index 8b9d8ce..fc8c835 100644
--- a/tests/test_signal.py
+++ b/tests/test_signal.py
@@ -4,7 +4,7 @@ import gc
import unittest
import sys
-from gi.repository import GObject
+from gi.repository import GObject, GLib
from gi._gobject import signalhelper
import testhelper
from compathelper import _long
@@ -49,11 +49,11 @@ class TestChaining(unittest.TestCase):
assert args[2:] == (1, 2, 3)
- def testChaining(self):
+ def test_chaining(self):
self.inst.emit("my_signal", 42)
assert self.inst.arg == 42
- def testChaining2(self):
+ def test_chaining2(self):
inst2 = D()
inst2.emit("my_signal", 44)
assert inst2.arg == 44
@@ -63,18 +63,24 @@ class TestChaining(unittest.TestCase):
class TestGSignalsError(unittest.TestCase):
- def testInvalidType(self, *args):
+ def test_invalid_type(self, *args):
def foo():
class Foo(GObject.GObject):
__gsignals__ = None
self.assertRaises(TypeError, foo)
gc.collect()
- def testInvalidName(self, *args):
+ def test_invalid_name(self, *args):
def foo():
class Foo(GObject.GObject):
__gsignals__ = {'not-exists': 'override'}
- self.assertRaises(TypeError, foo)
+ # 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:
+ self.assertRaises(TypeError, foo)
+ finally:
+ GLib.log_set_always_fatal(old_mask)
gc.collect()
@@ -294,7 +300,7 @@ class TestClosures(unittest.TestCase):
self.assertEqual(inst.a, 1)
gc.collect()
- def testGString(self):
+ def test_gstring(self):
class C(GObject.GObject):
__gsignals__ = {'my_signal': (GObject.SignalFlags.RUN_LAST, GObject.TYPE_GSTRING,
(GObject.TYPE_GSTRING,))}
@@ -592,7 +598,8 @@ class TestSignalDecorator(unittest.TestCase):
class TestSignalConnectors(unittest.TestCase):
class CustomButton(GObject.GObject):
- value = 0
+ on_notify_called = False
+ value = GObject.Property(type=int)
@GObject.Signal(arg_types=(int,))
def clicked(self, value):
@@ -606,6 +613,16 @@ class TestSignalConnectors(unittest.TestCase):
self.obj = obj
self.value = value
+ def test_signal_notify(self):
+ def on_notify(obj, param):
+ obj.on_notify_called = True
+
+ obj = self.CustomButton()
+ obj.connect('notify', on_notify)
+ self.assertFalse(obj.on_notify_called)
+ obj.notify('value')
+ self.assertTrue(obj.on_notify_called)
+
def test_signal_emit(self):
# standard callback connection with different forms of emit.
obj = self.CustomButton()
@@ -734,5 +751,59 @@ class TestPython3Signals(unittest.TestCase):
str)
+class TestSignalModuleLevelFunctions(unittest.TestCase):
+ @unittest.skipIf(sys.version_info < (2, 7), 'Requires Python >= 2.7')
+ def test_signal_list_ids_with_invalid_type(self):
+ with self.assertRaisesRegex(TypeError, 'type must be instantiable or an interface.*'):
+ GObject.signal_list_ids(GObject.TYPE_INVALID)
+
+ @unittest.skipIf(sys.version_info < (2, 7), 'Requires Python >= 2.7')
+ def test_signal_list_ids(self):
+ with self.assertRaisesRegex(TypeError, 'type must be instantiable or an interface.*'):
+ GObject.signal_list_ids(GObject.TYPE_INT)
+
+ ids = GObject.signal_list_ids(C)
+ self.assertEqual(len(ids), 1)
+ # Note canonicalized names
+ self.assertEqual(GObject.signal_name(ids[0]), 'my-signal')
+ # There is no signal 0 in gobject
+ self.assertEqual(GObject.signal_name(0), None)
+
+ @unittest.skipIf(sys.version_info < (2, 7), 'Requires Python >= 2.7')
+ def test_signal_lookup_with_invalid_type(self):
+ with self.assertRaisesRegex(TypeError, 'type must be instantiable or an interface.*'):
+ GObject.signal_lookup('NOT_A_SIGNAL_NAME', GObject.TYPE_INVALID)
+
+ @unittest.skipIf(sys.version_info < (2, 7), 'Requires Python >= 2.7')
+ def test_signal_lookup(self):
+ ids = GObject.signal_list_ids(C)
+ self.assertEqual(ids[0], GObject.signal_lookup('my_signal', C))
+ self.assertEqual(ids[0], GObject.signal_lookup('my-signal', C))
+
+ with self.assertRaisesRegex(TypeError, 'type must be instantiable or an interface.*'):
+ GObject.signal_lookup('NOT_A_SIGNAL_NAME', GObject.TYPE_INT)
+
+ # Invalid signal names return 0 instead of raising
+ self.assertEqual(GObject.signal_lookup('NOT_A_SIGNAL_NAME', C),
+ 0)
+
+ def test_signal_query(self):
+ my_signal_id, = GObject.signal_list_ids(C)
+
+ # Form is: (id, name, gtype, arg_count, return_type, (arg_type1, ...))
+ my_signal_expected_query_result = [my_signal_id, 'my-signal', C.__gtype__,
+ 1, GObject.TYPE_NONE, (GObject.TYPE_INT,)]
+ # signal_query(name, type)
+ self.assertSequenceEqual(GObject.signal_query('my-signal', C),
+ my_signal_expected_query_result)
+ # signal_query(signal_id)
+ self.assertSequenceEqual(GObject.signal_query(my_signal_id),
+ my_signal_expected_query_result)
+ # invalid query returns None instead of raising
+ self.assertEqual(GObject.signal_query(0), None)
+ self.assertEqual(GObject.signal_query('NOT_A_SIGNAL', C),
+ None)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_source.py b/tests/test_source.py
index fe674cd..dda492a 100644
--- a/tests/test_source.py
+++ b/tests/test_source.py
@@ -1,8 +1,10 @@
# -*- Mode: Python -*-
import unittest
+import warnings
-from gi.repository import GLib
+from gi.repository import GLib, GObject
+from gi import PyGIDeprecationWarning
class Idle(GLib.Idle):
@@ -43,25 +45,35 @@ class TestSource(unittest.TestCase):
timeout.set_callback(self.timeout_callback, loop)
timeout.attach()
- def testSources(self):
+ def test_sources(self):
loop = GLib.MainLoop()
self.setup_timeout(loop)
idle = Idle(loop)
+ self.assertEqual(idle.get_context(), None)
idle.attach()
+ self.assertEqual(idle.get_context(), GLib.main_context_default())
self.pos = 0
m = MySource()
+ self.assertEqual(m.get_context(), None)
m.set_callback(self.my_callback, loop)
m.attach()
+ self.assertEqual(m.get_context(), GLib.main_context_default())
loop.run()
- assert self.pos >= 0 and idle.count >= 0
+ m.destroy()
+ idle.destroy()
- def testSourcePrepare(self):
+ self.assertGreater(self.pos, 0)
+ self.assertGreaterEqual(idle.count, 0)
+ self.assertTrue(m.is_destroyed())
+ self.assertTrue(idle.is_destroyed())
+
+ def test_source_prepare(self):
# this test may not terminate if prepare() is wrapped incorrectly
dispatched = [False]
loop = GLib.MainLoop()
@@ -89,7 +101,7 @@ class TestSource(unittest.TestCase):
assert dispatched[0]
- def testIsDestroyedSimple(self):
+ def test_is_destroyed_simple(self):
s = GLib.Source()
self.assertFalse(s.is_destroyed())
@@ -103,7 +115,7 @@ class TestSource(unittest.TestCase):
s.destroy()
self.assertTrue(s.is_destroyed())
- def testIsDestroyedContext(self):
+ def test_is_destroyed_context(self):
def f():
c = GLib.MainContext()
s = GLib.Source()
@@ -113,12 +125,207 @@ class TestSource(unittest.TestCase):
s = f()
self.assertTrue(s.is_destroyed())
+ def test_remove(self):
+ s = GLib.idle_add(dir)
+ self.assertEqual(GLib.source_remove(s), True)
+ # s is now removed, should fail now
+ self.assertEqual(GLib.source_remove(s), False)
+
+ # accepts large source IDs (they are unsigned)
+ self.assertEqual(GLib.source_remove(GObject.G_MAXINT32), False)
+ self.assertEqual(GLib.source_remove(GObject.G_MAXINT32 + 1), False)
+ self.assertEqual(GLib.source_remove(GObject.G_MAXUINT32), False)
+
+ def test_recurse_property(self):
+ s = GLib.Idle()
+ self.assertTrue(s.can_recurse in [False, True])
+ s.can_recurse = False
+ self.assertFalse(s.can_recurse)
+
+ def test_priority(self):
+ s = GLib.Idle()
+ self.assertEqual(s.priority, GLib.PRIORITY_DEFAULT_IDLE)
+ s.priority = GLib.PRIORITY_HIGH
+ self.assertEqual(s.priority, GLib.PRIORITY_HIGH)
+
+ s = GLib.Idle(GLib.PRIORITY_LOW)
+ self.assertEqual(s.priority, GLib.PRIORITY_LOW)
-class TestTimeout(unittest.TestCase):
- def test504337(self):
+ s = GLib.Timeout(1, GLib.PRIORITY_LOW)
+ self.assertEqual(s.priority, GLib.PRIORITY_LOW)
+
+ s = GLib.Source()
+ self.assertEqual(s.priority, GLib.PRIORITY_DEFAULT)
+
+ def test_get_current_time(self):
+ # Note, deprecated API
+ s = GLib.Idle()
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always')
+ time = s.get_current_time()
+ self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
+
+ self.assertTrue(isinstance(time, float))
+ # plausibility check, and check magnitude of result
+ self.assertGreater(time, 1300000000.0)
+ self.assertLess(time, 2000000000.0)
+
+ def test_add_remove_poll(self):
+ # FIXME: very shallow test, only verifies the API signature
+ pollfd = GLib.PollFD(99, GLib.IOCondition.IN | GLib.IOCondition.HUP)
+ self.assertEqual(pollfd.fd, 99)
+ source = GLib.Source()
+ source.add_poll(pollfd)
+ source.remove_poll(pollfd)
+
+ def test_out_of_scope_before_dispatch(self):
+ # https://bugzilla.gnome.org/show_bug.cgi?id=504337
GLib.Timeout(20)
GLib.Idle()
+class TestUserData(unittest.TestCase):
+ def test_idle_no_data(self):
+ ml = GLib.MainLoop()
+
+ def cb():
+ ml.quit()
+ id = GLib.idle_add(cb)
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_DEFAULT_IDLE)
+ ml.run()
+
+ def test_timeout_no_data(self):
+ ml = GLib.MainLoop()
+
+ def cb():
+ ml.quit()
+ id = GLib.timeout_add(50, cb)
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_DEFAULT)
+ ml.run()
+
+ def test_idle_data(self):
+ ml = GLib.MainLoop()
+
+ def cb(data):
+ data['called'] = True
+ ml.quit()
+ data = {}
+ id = GLib.idle_add(cb, data)
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_DEFAULT_IDLE)
+ ml.run()
+ self.assertTrue(data['called'])
+
+ def test_idle_multidata(self):
+ ml = GLib.MainLoop()
+
+ def cb(data, data2):
+ data['called'] = True
+ data['data2'] = data2
+ ml.quit()
+ data = {}
+ id = GLib.idle_add(cb, data, 'hello')
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_DEFAULT_IDLE)
+ ml.run()
+ self.assertTrue(data['called'])
+ self.assertEqual(data['data2'], 'hello')
+
+ def test_timeout_data(self):
+ ml = GLib.MainLoop()
+
+ def cb(data):
+ data['called'] = True
+ ml.quit()
+ data = {}
+ id = GLib.timeout_add(50, cb, data)
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_DEFAULT)
+ ml.run()
+ self.assertTrue(data['called'])
+
+ def test_timeout_multidata(self):
+ ml = GLib.MainLoop()
+
+ def cb(data, data2):
+ data['called'] = True
+ data['data2'] = data2
+ ml.quit()
+ data = {}
+ id = GLib.timeout_add(50, cb, data, 'hello')
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_DEFAULT)
+ ml.run()
+ self.assertTrue(data['called'])
+ self.assertEqual(data['data2'], 'hello')
+
+ def test_idle_no_data_priority(self):
+ ml = GLib.MainLoop()
+
+ def cb():
+ ml.quit()
+ id = GLib.idle_add(cb, priority=GLib.PRIORITY_HIGH)
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ ml.run()
+
+ def test_timeout_no_data_priority(self):
+ ml = GLib.MainLoop()
+
+ def cb():
+ ml.quit()
+ id = GLib.timeout_add(50, cb, priority=GLib.PRIORITY_HIGH)
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ ml.run()
+
+ def test_idle_data_priority(self):
+ ml = GLib.MainLoop()
+
+ def cb(data):
+ data['called'] = True
+ ml.quit()
+ data = {}
+ id = GLib.idle_add(cb, data, priority=GLib.PRIORITY_HIGH)
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ ml.run()
+ self.assertTrue(data['called'])
+
+ def test_timeout_data_priority(self):
+ ml = GLib.MainLoop()
+
+ def cb(data):
+ data['called'] = True
+ ml.quit()
+ data = {}
+ id = GLib.timeout_add(50, cb, data, priority=GLib.PRIORITY_HIGH)
+ self.assertEqual(ml.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ ml.run()
+ self.assertTrue(data['called'])
+
+ def cb_no_data(self):
+ self.loop.quit()
+
+ def test_idle_method_callback_no_data(self):
+ self.loop = GLib.MainLoop()
+ GLib.idle_add(self.cb_no_data)
+ self.loop.run()
+
+ def cb_with_data(self, data):
+ data['called'] = True
+ self.loop.quit()
+
+ def test_idle_method_callback_with_data(self):
+ self.loop = GLib.MainLoop()
+ data = {}
+ GLib.idle_add(self.cb_with_data, data)
+ self.loop.run()
+ self.assertTrue(data['called'])
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_subprocess.py b/tests/test_subprocess.py
index 69f5f4c..26308e8 100644
--- a/tests/test_subprocess.py
+++ b/tests/test_subprocess.py
@@ -1,24 +1,145 @@
# -*- Mode: Python -*-
import sys
+import os
import unittest
+import warnings
from gi.repository import GLib
+from gi import PyGIDeprecationWarning
class TestProcess(unittest.TestCase):
- def _child_watch_cb(self, pid, condition, data):
- self.data = data
- self.loop.quit()
+ def test_deprecated_child_watch_no_data(self):
+ def cb(pid, status):
+ self.status = status
+ self.loop.quit()
- def testChildWatch(self):
+ self.status = None
+ self.loop = GLib.MainLoop()
+ argv = [sys.executable, '-c', 'import sys']
+ pid, stdin, stdout, stderr = GLib.spawn_async(
+ argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD)
+ pid.close()
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always')
+ GLib.child_watch_add(pid, cb)
+ self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
+ self.loop.run()
+ self.assertEqual(self.status, 0)
+
+ def test_deprecated_child_watch_data_priority(self):
+ def cb(pid, status, data):
+ self.data = data
+ self.status = status
+ self.loop.quit()
+
+ self.status = None
+ self.data = None
+ self.loop = GLib.MainLoop()
+ argv = [sys.executable, '-c', 'import sys']
+ pid, stdin, stdout, stderr = GLib.spawn_async(
+ argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD)
+ pid.close()
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always')
+ id = GLib.child_watch_add(pid, cb, 12345, GLib.PRIORITY_HIGH)
+ self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
+ self.assertEqual(self.loop.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ self.loop.run()
+ self.assertEqual(self.data, 12345)
+ self.assertEqual(self.status, 0)
+
+ def test_deprecated_child_watch_data_priority_kwargs(self):
+ def cb(pid, status, data):
+ self.data = data
+ self.status = status
+ self.loop.quit()
+
+ self.status = None
self.data = None
self.loop = GLib.MainLoop()
argv = [sys.executable, '-c', 'import sys']
pid, stdin, stdout, stderr = GLib.spawn_async(
- argv, flags=GLib.SPAWN_DO_NOT_REAP_CHILD)
+ argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD)
pid.close()
- GLib.child_watch_add(pid, self._child_watch_cb, 12345)
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always')
+ id = GLib.child_watch_add(pid, cb, priority=GLib.PRIORITY_HIGH, data=12345)
+ self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
+ self.assertEqual(self.loop.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
self.loop.run()
self.assertEqual(self.data, 12345)
+ self.assertEqual(self.status, 0)
+
+ def test_child_watch_no_data(self):
+ def cb(pid, status):
+ self.status = status
+ self.loop.quit()
+
+ self.status = None
+ self.loop = GLib.MainLoop()
+ argv = [sys.executable, '-c', 'import sys']
+ pid, stdin, stdout, stderr = GLib.spawn_async(
+ argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD)
+ pid.close()
+ id = GLib.child_watch_add(GLib.PRIORITY_HIGH, pid, cb)
+ self.assertEqual(self.loop.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ self.loop.run()
+ self.assertEqual(self.status, 0)
+
+ def test_child_watch_with_data(self):
+ def cb(pid, status, data):
+ self.status = status
+ self.data = data
+ self.loop.quit()
+
+ self.data = None
+ self.status = None
+ self.loop = GLib.MainLoop()
+ argv = [sys.executable, '-c', 'import sys']
+ pid, stdin, stdout, stderr = GLib.spawn_async(
+ argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD)
+ self.assertEqual(stdin, None)
+ self.assertEqual(stdout, None)
+ self.assertEqual(stderr, None)
+ pid.close()
+ id = GLib.child_watch_add(GLib.PRIORITY_HIGH, pid, cb, 12345)
+ self.assertEqual(self.loop.get_context().find_source_by_id(id).priority,
+ GLib.PRIORITY_HIGH)
+ self.loop.run()
+ self.assertEqual(self.data, 12345)
+ self.assertEqual(self.status, 0)
+
+ def test_spawn_async_fds(self):
+ pid, stdin, stdout, stderr = GLib.spawn_async(
+ ['cat'], flags=GLib.SpawnFlags.SEARCH_PATH, standard_input=True,
+ standard_output=True, standard_error=True)
+ os.write(stdin, b'hello world!\n')
+ os.close(stdin)
+ out = os.read(stdout, 50)
+ os.close(stdout)
+ err = os.read(stderr, 50)
+ os.close(stderr)
+ pid.close()
+ self.assertEqual(out, b'hello world!\n')
+ self.assertEqual(err, b'')
+
+ def test_spawn_async_envp(self):
+ pid, stdin, stdout, stderr = GLib.spawn_async(
+ ['sh', '-c', 'echo $TEST_VAR'], ['TEST_VAR=moo!'],
+ flags=GLib.SpawnFlags.SEARCH_PATH, standard_output=True)
+ self.assertEqual(stdin, None)
+ self.assertEqual(stderr, None)
+ out = os.read(stdout, 50)
+ os.close(stdout)
+ pid.close()
+ self.assertEqual(out, b'moo!\n')
+
+ def test_backwards_compat_flags(self):
+ self.assertEqual(GLib.SpawnFlags.DO_NOT_REAP_CHILD,
+ GLib.SPAWN_DO_NOT_REAP_CHILD)
diff --git a/tests/test_thread.py b/tests/test_thread.py
index b707bc4..3d0557e 100644
--- a/tests/test_thread.py
+++ b/tests/test_thread.py
@@ -20,7 +20,7 @@ class TestThread(unittest.TestCase):
self.obj.connect('from-thread', self.from_thread_cb)
self.obj.emit('emit-signal')
- def testExtensionModule(self):
+ def test_extension_module(self):
GLib.idle_add(self.idle_cb)
GLib.timeout_add(50, self.timeout_cb)
self.main.run()
diff --git a/tests/test_uris.py b/tests/test_uris.py
deleted file mode 100644
index 143cc7b..0000000
--- a/tests/test_uris.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import unittest
-
-from gi.repository import GLib
-
-
-class TestUris(unittest.TestCase):
- def testExtractUris(self):
- uri_list_text = """# urn:isbn:0-201-08372-8
-http://www.huh.org/books/foo.html
-http://www.huh.org/books/foo.pdf
-ftp://ftp.foo.org/books/foo.txt
-"""
- uri_list = GLib.uri_list_extract_uris(uri_list_text)
- assert uri_list[0] == "http://www.huh.org/books/foo.html"
- assert uri_list[1] == "http://www.huh.org/books/foo.pdf"
- assert uri_list[2] == "ftp://ftp.foo.org/books/foo.txt"
diff --git a/tests/testhelpermodule.c b/tests/testhelpermodule.c
index bc83e9d..16bb39e 100644
--- a/tests/testhelpermodule.c
+++ b/tests/testhelpermodule.c
@@ -602,12 +602,11 @@ PYGLIB_MODULE_START(testhelper, "testhelper")
{
PyObject *m, *d;
- g_thread_init(NULL);
pygobject_init(-1, -1, -1);
d = PyModule_GetDict(module);
- if ((m = PyImport_ImportModule("gi._gobject")) != NULL) {
+ if ((m = PyImport_ImportModule("gi._gobject._gobject")) != NULL) {
PyObject *moddict = PyModule_GetDict(m);
_PyGObject_Type = (PyTypeObject *)PyDict_GetItemString(moddict, "GObject");