From: DongHun Kwak Date: Tue, 11 Jul 2017 23:43:36 +0000 (+0900) Subject: Imported Upstream version 3.17.1 X-Git-Tag: upstream/3.9.92~51 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F77%2F138277%2F1;p=platform%2Fupstream%2Fpygobject2.git Imported Upstream version 3.17.1 Change-Id: I800646617d0436ee18c74de23f96863a5d100237 Signed-off-by: DongHun Kwak --- diff --git a/ChangeLog b/ChangeLog index 89506bb..5d17a82 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,39 @@ -commit ecb2e6c64cbc420ed8f0d8dc8d1c3f6c516d6f63 +commit 2048dc8d1d708abce7037f96483c6d776567d6b5 +Author: Christoph Reiter +Date: Mon Mar 2 20:58:04 2015 +0100 + + Add gi.PyGIWarning and use it instead of PyGIDeprecationWarning in + case the version to import wasn't specified. + + This makes the warning visible by default. + See commit ef3bff4e570363e4f383d4cdae9cecd4073b03d8 for more info + on the warning. + + https://bugzilla.gnome.org/show_bug.cgi?id=727379 + + gi/__init__.py | 2 ++ + gi/gimodule.c | 6 ++++++ + gi/importer.py | 3 ++- + tests/test_gi.py | 15 +++++++++++++++ + 4 files changed, 25 insertions(+), 1 deletion(-) + +commit 7a3bb6971f22accd25e987496d377e1879f6e1ba +Author: Christoph Reiter +Date: Sat May 30 17:46:54 2015 +0200 + + Remove Gdk.Rectangle alias with newer gobject-introspection and GTK+ + + The new GdkRectangle in the typelib confuses the marshalling code + as PyGObject uses the Python class from the overrides for marshalling + to Python but uses the gtype from the typelib to do + type checking when marshalling from Python. + + https://bugzilla.gnome.org/show_bug.cgi?id=749625 + + gi/overrides/Gdk.py | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +commit 64be2069d39b4d2767eb1efd47bb3f268ad7fb0d Author: Christoph Reiter Date: Thu Apr 23 22:03:54 2015 +0200 @@ -20,25 +55,7 @@ Date: Thu Apr 23 22:03:54 2015 +0200 gi/overrides/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) -commit eddc46202fc813f03137fcaba80090d19cc8f200 -Author: Simon Feltman -Date: Mon Apr 13 19:48:24 2015 -0700 - - configure.ac: post release version bump to 3.16.2 - - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -commit 763510d091bcb9833a3de7f9646d9a06282135da -Author: Simon Feltman -Date: Mon Apr 13 19:46:48 2015 -0700 - - release 3.16.1 - - NEWS | 4 ++++ - 1 file changed, 4 insertions(+) - -commit 7291cb1f841c384f1a18cc744c8d9c6be20c48e2 +commit 6772e990ad889af817b9224e88ea9d79a04caef7 Author: Simon Feltman Date: Mon Apr 13 19:33:40 2015 -0700 @@ -52,14 +69,67 @@ Date: Mon Apr 13 19:33:40 2015 -0700 gi/overrides/Gdk.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) -commit c5952495351b551b5295afc36643e3d10004225e +commit 26c015b177ddcc0f35c97bcd7a4f2114fb2e8e2a +Author: Christoph Reiter +Date: Sun Mar 29 23:23:09 2015 +0200 + + Field setters: Remove unneeded type/range checks and resulting + unused code. + + These checks are performed in the actual marshalling code + paths as well, no need to do them twice. + + Also move _pygi_g_registered_type_info_check_object() to pygi-info.c + as it's the only place where it is still used. + + https://bugzilla.gnome.org/show_bug.cgi?id=746985 + + gi/pygi-argument.c | 626 + --------------------------------------------------- + gi/pygi-argument.h | 12 - + gi/pygi-info.c | 90 ++++++-- + tests/test_fields.py | 14 +- + 4 files changed, 83 insertions(+), 659 deletions(-) + +commit dbb0b199268ece884e19eb99093fc26bd7bf92af +Author: Christoph Reiter +Date: Sun Mar 29 21:51:42 2015 +0200 + + pygi-argument: Remove unused imports/includes + + https://bugzilla.gnome.org/show_bug.cgi?id=746985 + + gi/gimodule.c | 1 - + gi/pygi-argument.c | 7 ------- + gi/pygi-argument.h | 2 -- + 3 files changed, 10 deletions(-) + +commit 7dee04efff418677eead36ee9ed497cc3eadf8f7 +Author: Christoph Reiter +Date: Sun Mar 29 21:47:47 2015 +0200 + + Improve test coverage for field setters/getters. + + Field setters are the sole users of the GIArgument value validation + code and the error handling is hardly tested. This tries to improve + the coverage for the field types available in + GLib/Regress/GIMarshallingTests. + + https://bugzilla.gnome.org/show_bug.cgi?id=746985 + + tests/Makefile.am | 1 + + tests/test_fields.py | 186 + +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 187 insertions(+) + +commit b0170220fabbf878a36e0c14b0a3024973b7355f Author: Simon Feltman -Date: Sun Mar 29 16:29:35 2015 -0700 +Date: Sun Mar 29 16:35:47 2015 -0700 - configure.ac: post release version bump to 3.16.1 + configure.ac: post release version bump to 3.17.1 - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + configure.ac | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) commit 46f463a3a3ff45eb8eba67fbb59ecc861b1e1d73 Author: Simon Feltman diff --git a/NEWS b/NEWS index bb9c3a9..e9b37e3 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,18 @@ -3.16.2 15-Jun-2015 +3.17.1 15-Jun-2015 + - Add gi.PyGIWarning used when import version is not specified + (Christoph Reiter) (#727379) + - Remove Gdk.Rectangle alias with newer gobject-introspection and GTK+ + (Christoph Reiter) (#749625) - overrides: Provide _overrides_module attribute (Christoph Reiter) (#736678) - -3.16.1 13-Apr-2015 - overrides: Conditionalize touch override support in Gdk (Simon Feltman) (#747717) + - Field setters: Remove unneeded type/range checks and unused code + (Christoph Reiter) (#746985) + - pygi-argument: Remove unused imports/includes + (Christoph Reiter) (#746985) + - Improve test coverage for field setters/getters + (Christoph Reiter) (#746985) 3.16.0 24-Mar-2015 diff --git a/PKG-INFO b/PKG-INFO index 15f49bd..8c4e160 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: PyGObject -Version: 3.16.2 +Version: 3.17.1 Summary: Python bindings for GObject Home-page: http://www.pygtk.org/ Author: James Henstridge @@ -8,7 +8,7 @@ Author-email: james@daa.com.au Maintainer: Simon Feltman Maintainer-email: sfeltman@src.gnome.org License: GNU LGPL -Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.16/pygobject-3.16.2.tar.gz +Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.17/pygobject-3.17.1.tar.gz Description: Python bindings for GLib and GObject Platform: POSIX, Windows Classifier: Development Status :: 5 - Production/Stable diff --git a/configure b/configure index f4b3c79..c6da85f 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for pygobject 3.16.2. +# Generated by GNU Autoconf 2.69 for pygobject 3.17.1. # # Report bugs to . # @@ -591,8 +591,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pygobject' PACKAGE_TARNAME='pygobject' -PACKAGE_VERSION='3.16.2' -PACKAGE_STRING='pygobject 3.16.2' +PACKAGE_VERSION='3.17.1' +PACKAGE_STRING='pygobject 3.17.1' PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject' PACKAGE_URL='https://wiki.gnome.org/Projects/PyGObject/' @@ -1395,7 +1395,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pygobject 3.16.2 to adapt to many kinds of systems. +\`configure' configures pygobject 3.17.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1465,7 +1465,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pygobject 3.16.2:";; + short | recursive ) echo "Configuration of pygobject 3.17.1:";; esac cat <<\_ACEOF @@ -1603,7 +1603,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pygobject configure 3.16.2 +pygobject configure 3.17.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1881,7 +1881,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pygobject $as_me 3.16.2, which was +It was created by pygobject $as_me 3.17.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2240,14 +2240,14 @@ $as_echo "#define PYGOBJECT_MAJOR_VERSION 3" >>confdefs.h PYGOBJECT_MAJOR_VERSION=3 -$as_echo "#define PYGOBJECT_MINOR_VERSION 16" >>confdefs.h +$as_echo "#define PYGOBJECT_MINOR_VERSION 17" >>confdefs.h -PYGOBJECT_MINOR_VERSION=16 +PYGOBJECT_MINOR_VERSION=17 -$as_echo "#define PYGOBJECT_MICRO_VERSION 2" >>confdefs.h +$as_echo "#define PYGOBJECT_MICRO_VERSION 1" >>confdefs.h -PYGOBJECT_MICRO_VERSION=2 +PYGOBJECT_MICRO_VERSION=1 ac_config_headers="$ac_config_headers config.h" @@ -2767,7 +2767,7 @@ fi # Define the identity of the package. PACKAGE='pygobject' - VERSION='3.16.2' + VERSION='3.17.1' cat >>confdefs.h <<_ACEOF @@ -15377,7 +15377,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pygobject $as_me 3.16.2, which was +This file was extended by pygobject $as_me 3.17.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -15444,7 +15444,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -pygobject config.status 3.16.2 +pygobject config.status 3.17.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 63fd7eb..c66ba35 100644 --- a/configure.ac +++ b/configure.ac @@ -17,8 +17,8 @@ m4_define(python3_min_ver, 3.1) dnl the pygobject version number m4_define(pygobject_major_version, 3) -m4_define(pygobject_minor_version, 16) -m4_define(pygobject_micro_version, 2) +m4_define(pygobject_minor_version, 17) +m4_define(pygobject_micro_version, 1) m4_define(pygobject_version, pygobject_major_version.pygobject_minor_version.pygobject_micro_version) dnl versions of packages we require ... diff --git a/gi/__init__.py b/gi/__init__.py index fe4abcf..caad569 100644 --- a/gi/__init__.py +++ b/gi/__init__.py @@ -44,9 +44,11 @@ from ._gi import _gobject from ._gi import _API from ._gi import Repository from ._gi import PyGIDeprecationWarning +from ._gi import PyGIWarning _API = _API # pyflakes PyGIDeprecationWarning = PyGIDeprecationWarning +PyGIWarning = PyGIWarning _versions = {} _overridesdir = os.path.join(os.path.dirname(__file__), 'overrides') diff --git a/gi/gimodule.c b/gi/gimodule.c index de9b787..74bf7cd 100644 --- a/gi/gimodule.c +++ b/gi/gimodule.c @@ -32,6 +32,7 @@ #include +PyObject *PyGIWarning; PyObject *PyGIDeprecationWarning; PyObject *_PyGIDefaultArgPlaceholder; @@ -636,7 +637,8 @@ PYGLIB_MODULE_START(_gi, "_gi") _pygi_struct_register_types (module); _pygi_boxed_register_types (module); _pygi_ccallback_register_types (module); - _pygi_argument_init (); + + PyGIWarning = PyErr_NewException ("gi.PyGIWarning", PyExc_Warning, NULL); /* Use RuntimeWarning as the base class of PyGIDeprecationWarning * for unstable (odd minor version) and use DeprecationWarning for @@ -656,6 +658,9 @@ PYGLIB_MODULE_START(_gi, "_gi") */ _PyGIDefaultArgPlaceholder = PyObject_New(PyObject, &PyType_Type); + Py_INCREF (PyGIWarning); + PyModule_AddObject (module, "PyGIWarning", PyGIWarning); + Py_INCREF(PyGIDeprecationWarning); PyModule_AddObject(module, "PyGIDeprecationWarning", PyGIDeprecationWarning); diff --git a/gi/importer.py b/gi/importer.py index c097b74..0acbc23 100644 --- a/gi/importer.py +++ b/gi/importer.py @@ -28,6 +28,7 @@ from contextlib import contextmanager import gi from ._gi import Repository +from ._gi import PyGIWarning from .module import get_introspection_module from .overrides import load_overrides @@ -119,7 +120,7 @@ def _check_require_version(namespace, stacklevel): "Use gi.require_version('%(namespace)s', '%(version)s') before " "import to ensure that the right version gets loaded." % {"namespace": namespace, "version": version}, - ImportWarning, stacklevel=stacklevel) + PyGIWarning, stacklevel=stacklevel) class DynamicImporter(object): diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py index 15f2a0a..3ab5d6d 100644 --- a/gi/overrides/Gdk.py +++ b/gi/overrides/Gdk.py @@ -126,10 +126,14 @@ if Gdk._version == '2.0': Rectangle = override(Rectangle) __all__.append('Rectangle') else: - from gi.repository import cairo as _cairo - Rectangle = _cairo.RectangleInt - - __all__.append('Rectangle') + # Newer GTK+/gobject-introspection (3.17.x) include GdkRectangle in the + # typelib. See https://bugzilla.gnome.org/show_bug.cgi?id=748832 and + # https://bugzilla.gnome.org/show_bug.cgi?id=748833 + if not hasattr(Gdk, 'Rectangle'): + from gi.repository import cairo as _cairo + Rectangle = _cairo.RectangleInt + + __all__.append('Rectangle') if Gdk._version == '2.0': class Drawable(Gdk.Drawable): diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index d63520d..0c322e8 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -132,632 +131,6 @@ _pygi_arg_to_hash_pointer (const GIArgument *arg, } } -static void -_pygi_g_type_tag_py_bounds (GITypeTag type_tag, - PyObject **lower, - PyObject **upper) -{ - switch (type_tag) { - case GI_TYPE_TAG_INT8: - *lower = PYGLIB_PyLong_FromLong (-128); - *upper = PYGLIB_PyLong_FromLong (127); - break; - case GI_TYPE_TAG_UINT8: - *upper = PYGLIB_PyLong_FromLong (255); - *lower = PYGLIB_PyLong_FromLong (0); - break; - case GI_TYPE_TAG_INT16: - *lower = PYGLIB_PyLong_FromLong (-32768); - *upper = PYGLIB_PyLong_FromLong (32767); - break; - case GI_TYPE_TAG_UINT16: - *upper = PYGLIB_PyLong_FromLong (65535); - *lower = PYGLIB_PyLong_FromLong (0); - break; - case GI_TYPE_TAG_INT32: - *lower = PYGLIB_PyLong_FromLong (G_MININT32); - *upper = PYGLIB_PyLong_FromLong (G_MAXINT32); - break; - case GI_TYPE_TAG_UINT32: - /* Note: On 32-bit archs, this number doesn't fit in a long. */ - *upper = PyLong_FromLongLong (G_MAXUINT32); - *lower = PYGLIB_PyLong_FromLong (0); - break; - case GI_TYPE_TAG_INT64: - /* Note: On 32-bit archs, these numbers don't fit in a long. */ - *lower = PyLong_FromLongLong (G_MININT64); - *upper = PyLong_FromLongLong (G_MAXINT64); - break; - case GI_TYPE_TAG_UINT64: - *upper = PyLong_FromUnsignedLongLong (G_MAXUINT64); - *lower = PYGLIB_PyLong_FromLong (0); - break; - case GI_TYPE_TAG_FLOAT: - *upper = PyFloat_FromDouble (G_MAXFLOAT); - *lower = PyFloat_FromDouble (-G_MAXFLOAT); - break; - case GI_TYPE_TAG_DOUBLE: - *upper = PyFloat_FromDouble (G_MAXDOUBLE); - *lower = PyFloat_FromDouble (-G_MAXDOUBLE); - break; - default: - PyErr_SetString (PyExc_TypeError, "Non-numeric type tag"); - *lower = *upper = NULL; - return; - } -} - -gint -_pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, - gboolean is_instance, - PyObject *object) -{ - gint retval; - - GType g_type; - PyObject *py_type; - gchar *type_name_expected = NULL; - GIInfoType interface_type; - - interface_type = g_base_info_get_type (info); - if ( (interface_type == GI_INFO_TYPE_STRUCT) && - (g_struct_info_is_foreign ( (GIStructInfo*) info))) { - /* TODO: Could we check is the correct foreign type? */ - return 1; - } - - g_type = g_registered_type_info_get_g_type (info); - if (g_type != G_TYPE_NONE) { - py_type = _pygi_type_get_from_g_type (g_type); - } else { - py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info); - } - - if (py_type == NULL) { - return 0; - } - - g_assert (PyType_Check (py_type)); - - if (is_instance) { - retval = PyObject_IsInstance (object, py_type); - if (!retval) { - type_name_expected = _pygi_g_base_info_get_fullname ( - (GIBaseInfo *) info); - } - } else { - if (!PyObject_Type (py_type)) { - type_name_expected = "type"; - retval = 0; - } else if (!PyType_IsSubtype ( (PyTypeObject *) object, - (PyTypeObject *) py_type)) { - type_name_expected = _pygi_g_base_info_get_fullname ( - (GIBaseInfo *) info); - retval = 0; - } else { - retval = 1; - } - } - - Py_DECREF (py_type); - - if (!retval) { - PyTypeObject *object_type; - - if (type_name_expected == NULL) { - return -1; - } - - object_type = (PyTypeObject *) PyObject_Type (object); - if (object_type == NULL) { - return -1; - } - - PyErr_Format (PyExc_TypeError, "Must be %s, not %s", - type_name_expected, object_type->tp_name); - - g_free (type_name_expected); - } - - return retval; -} - -gint -_pygi_g_type_interface_check_object (GIBaseInfo *info, - PyObject *object) -{ - gint retval = 1; - GIInfoType info_type; - - info_type = g_base_info_get_type (info); - switch (info_type) { - case GI_INFO_TYPE_CALLBACK: - if (!PyCallable_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be callable, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - case GI_INFO_TYPE_ENUM: - retval = 0; - if (PyNumber_Check (object)) { - PyObject *number = PYGLIB_PyNumber_Long (object); - if (number == NULL) - PyErr_Clear(); - else { - glong value = PYGLIB_PyLong_AsLong (number); - int i; - for (i = 0; i < g_enum_info_get_n_values (info); i++) { - GIValueInfo *value_info = g_enum_info_get_value (info, i); - glong enum_value = g_value_info_get_value (value_info); - g_base_info_unref (value_info); - if (value == enum_value) { - retval = 1; - break; - } - } - } - } - if (retval < 1) - retval = _pygi_g_registered_type_info_check_object ( - (GIRegisteredTypeInfo *) info, TRUE, object); - break; - case GI_INFO_TYPE_FLAGS: - if (PyNumber_Check (object)) { - /* Accept 0 as a valid flag value */ - PyObject *number = PYGLIB_PyNumber_Long (object); - if (number == NULL) - PyErr_Clear(); - else { - long value = PYGLIB_PyLong_AsLong (number); - if (value == 0) - break; - else if (value == -1) - PyErr_Clear(); - } - } - retval = _pygi_g_registered_type_info_check_object ( - (GIRegisteredTypeInfo *) info, TRUE, object); - break; - case GI_INFO_TYPE_STRUCT: - { - GType type; - - /* Handle special cases. */ - type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); - if (g_type_is_a (type, G_TYPE_CLOSURE)) { - if (!(PyCallable_Check (object) || - pyg_type_from_object_strict (object, FALSE) == G_TYPE_CLOSURE)) { - PyErr_Format (PyExc_TypeError, "Must be callable, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - } else if (g_type_is_a (type, G_TYPE_VALUE)) { - /* we can't check g_values because we don't have - * enough context so just pass them through */ - break; - } - - /* Fallback. */ - } - case GI_INFO_TYPE_BOXED: - case GI_INFO_TYPE_INTERFACE: - case GI_INFO_TYPE_OBJECT: - retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object); - break; - case GI_INFO_TYPE_UNION: - - - retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object); - - /* If not the same type then check to see if the object's type - * is the same as one of the union's members - */ - if (retval == 0) { - gint i; - gint n_fields; - - n_fields = g_union_info_get_n_fields ( (GIUnionInfo *) info); - - for (i = 0; i < n_fields; i++) { - gint member_retval; - GIFieldInfo *field_info; - GITypeInfo *field_type_info; - - field_info = - g_union_info_get_field ( (GIUnionInfo *) info, i); - field_type_info = g_field_info_get_type (field_info); - - member_retval = _pygi_g_type_info_check_object( - field_type_info, - object, - TRUE); - - g_base_info_unref ( ( GIBaseInfo *) field_type_info); - g_base_info_unref ( ( GIBaseInfo *) field_info); - - if (member_retval == 1) { - retval = member_retval; - break; - } - } - } - - break; - default: - g_assert_not_reached(); - } - - return retval; -} - -gint -_pygi_g_type_info_check_object (GITypeInfo *type_info, - PyObject *object, - gboolean allow_none) -{ - GITypeTag type_tag; - gint retval = 1; - - if (allow_none && object == Py_None) { - return retval; - } - - type_tag = g_type_info_get_tag (type_info); - - switch (type_tag) { - case GI_TYPE_TAG_VOID: - /* No check; VOID means undefined type */ - break; - case GI_TYPE_TAG_BOOLEAN: - /* No check; every Python object has a truth value. */ - break; - case GI_TYPE_TAG_UINT8: - case GI_TYPE_TAG_INT8: - /* (U)INT8 types can be characters */ - if (PYGLIB_PyBytes_Check(object)) { - if (PYGLIB_PyBytes_Size(object) != 1) { - PyErr_Format (PyExc_TypeError, "Must be a single character"); - retval = 0; - break; - } - - break; - } - case GI_TYPE_TAG_INT16: - case GI_TYPE_TAG_UINT16: - case GI_TYPE_TAG_INT32: - case GI_TYPE_TAG_UINT32: - case GI_TYPE_TAG_INT64: - case GI_TYPE_TAG_UINT64: - case GI_TYPE_TAG_FLOAT: - case GI_TYPE_TAG_DOUBLE: - { - PyObject *number, *lower, *upper; - - if (!PyNumber_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be number, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - if (type_tag == GI_TYPE_TAG_FLOAT || type_tag == GI_TYPE_TAG_DOUBLE) { - number = PyNumber_Float (object); - } else { - number = PYGLIB_PyNumber_Long (object); - } - - _pygi_g_type_tag_py_bounds (type_tag, &lower, &upper); - - if (lower == NULL || upper == NULL || number == NULL) { - retval = -1; - goto check_number_release; - } - - /* Check bounds */ - if (PyObject_RichCompareBool (lower, number, Py_GT) - || PyObject_RichCompareBool (upper, number, Py_LT)) { - PyObject *lower_str; - PyObject *upper_str; - - if (PyErr_Occurred()) { - retval = -1; - goto check_number_release; - } - - lower_str = PyObject_Str (lower); - upper_str = PyObject_Str (upper); - if (lower_str == NULL || upper_str == NULL) { - retval = -1; - goto check_number_error_release; - } - -#if PY_VERSION_HEX < 0x03000000 - PyErr_Format (PyExc_ValueError, "Must range from %s to %s", - PyString_AS_STRING (lower_str), - PyString_AS_STRING (upper_str)); -#else - { - PyObject *lower_pybytes_obj; - PyObject *upper_pybytes_obj; - - lower_pybytes_obj = PyUnicode_AsUTF8String (lower_str); - if (!lower_pybytes_obj) { - goto utf8_fail; - } - - upper_pybytes_obj = PyUnicode_AsUTF8String (upper_str); - if (!upper_pybytes_obj) { - Py_DECREF(lower_pybytes_obj); - goto utf8_fail; - } - - PyErr_Format (PyExc_ValueError, "Must range from %s to %s", - PyBytes_AsString (lower_pybytes_obj), - PyBytes_AsString (upper_pybytes_obj)); - Py_DECREF (lower_pybytes_obj); - Py_DECREF (upper_pybytes_obj); - } -utf8_fail: -#endif - retval = 0; - -check_number_error_release: - Py_XDECREF (lower_str); - Py_XDECREF (upper_str); - } - -check_number_release: - Py_XDECREF (number); - Py_XDECREF (lower); - Py_XDECREF (upper); - break; - } - case GI_TYPE_TAG_GTYPE: - { - if (pyg_type_from_object (object) == 0) { - PyErr_Format (PyExc_TypeError, "Must be gobject.GType, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - } - case GI_TYPE_TAG_UNICHAR: - { - Py_ssize_t size; - if (PyUnicode_Check (object)) { - size = PyUnicode_GET_SIZE (object); -#if PY_VERSION_HEX < 0x03000000 - } else if (PyString_Check (object)) { - PyObject *pyuni = PyUnicode_FromEncodedObject (object, "UTF-8", "strict"); - size = PyUnicode_GET_SIZE (pyuni); - Py_DECREF(pyuni); -#endif - } else { - PyErr_Format (PyExc_TypeError, "Must be string, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - if (size != 1) { - PyErr_Format (PyExc_TypeError, "Must be a one character string, not %" G_GINT64_FORMAT " characters", - (gint64)size); - retval = 0; - break; - } - - break; - } - case GI_TYPE_TAG_UTF8: - case GI_TYPE_TAG_FILENAME: - if (!PYGLIB_PyBaseString_Check (object) ) { - PyErr_Format (PyExc_TypeError, "Must be string, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - case GI_TYPE_TAG_ARRAY: - { - gssize fixed_size; - Py_ssize_t length; - GITypeInfo *item_type_info; - Py_ssize_t i; - - if (!PySequence_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be sequence, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - length = PySequence_Length (object); - if (length < 0) { - retval = -1; - break; - } - - fixed_size = g_type_info_get_array_fixed_size (type_info); - if (fixed_size >= 0 && length != fixed_size) { - PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd", - fixed_size, length); - retval = 0; - break; - } - - item_type_info = g_type_info_get_param_type (type_info, 0); - g_assert (item_type_info != NULL); - - /* FIXME: This is insain. We really should only check the first - * object and perhaps have a debugging mode. Large arrays - * will cause apps to slow to a crawl. - */ - for (i = 0; i < length; i++) { - PyObject *item; - - item = PySequence_GetItem (object, i); - if (item == NULL) { - retval = -1; - break; - } - - retval = _pygi_g_type_info_check_object (item_type_info, item, TRUE); - - Py_DECREF (item); - - if (retval < 0) { - break; - } - if (!retval) { - _PyGI_ERROR_PREFIX ("Item %zd: ", i); - break; - } - } - - g_base_info_unref ( (GIBaseInfo *) item_type_info); - - break; - } - case GI_TYPE_TAG_INTERFACE: - { - GIBaseInfo *info; - - info = g_type_info_get_interface (type_info); - g_assert (info != NULL); - - retval = _pygi_g_type_interface_check_object(info, object); - - g_base_info_unref (info); - break; - } - case GI_TYPE_TAG_GLIST: - case GI_TYPE_TAG_GSLIST: - { - Py_ssize_t length; - GITypeInfo *item_type_info; - Py_ssize_t i; - - if (!PySequence_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be sequence, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - length = PySequence_Length (object); - if (length < 0) { - retval = -1; - break; - } - - item_type_info = g_type_info_get_param_type (type_info, 0); - g_assert (item_type_info != NULL); - - for (i = 0; i < length; i++) { - PyObject *item; - - item = PySequence_GetItem (object, i); - if (item == NULL) { - retval = -1; - break; - } - - retval = _pygi_g_type_info_check_object (item_type_info, item, TRUE); - - Py_DECREF (item); - - if (retval < 0) { - break; - } - if (!retval) { - _PyGI_ERROR_PREFIX ("Item %zd: ", i); - break; - } - } - - g_base_info_unref ( (GIBaseInfo *) item_type_info); - break; - } - case GI_TYPE_TAG_GHASH: - { - Py_ssize_t length; - PyObject *keys; - PyObject *values; - GITypeInfo *key_type_info; - GITypeInfo *value_type_info; - Py_ssize_t i; - - keys = PyMapping_Keys (object); - if (keys == NULL) { - PyErr_Format (PyExc_TypeError, "Must be mapping, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - length = PyMapping_Length (object); - if (length < 0) { - Py_DECREF (keys); - retval = -1; - break; - } - - values = PyMapping_Values (object); - if (values == NULL) { - retval = -1; - Py_DECREF (keys); - break; - } - - key_type_info = g_type_info_get_param_type (type_info, 0); - g_assert (key_type_info != NULL); - - value_type_info = g_type_info_get_param_type (type_info, 1); - g_assert (value_type_info != NULL); - - for (i = 0; i < length; i++) { - PyObject *key; - PyObject *value; - - key = PyList_GET_ITEM (keys, i); - value = PyList_GET_ITEM (values, i); - - retval = _pygi_g_type_info_check_object (key_type_info, key, TRUE); - if (retval < 0) { - break; - } - if (!retval) { - _PyGI_ERROR_PREFIX ("Key %zd :", i); - break; - } - - retval = _pygi_g_type_info_check_object (value_type_info, value, TRUE); - if (retval < 0) { - break; - } - if (!retval) { - _PyGI_ERROR_PREFIX ("Value %zd :", i); - break; - } - } - - g_base_info_unref ( (GIBaseInfo *) key_type_info); - g_base_info_unref ( (GIBaseInfo *) value_type_info); - Py_DECREF (values); - Py_DECREF (keys); - break; - } - case GI_TYPE_TAG_ERROR: - PyErr_SetString (PyExc_NotImplementedError, "Error marshalling is not supported yet"); - /* TODO */ - break; - } - - return retval; -} - /** * _pygi_argument_array_length_marshal: @@ -1856,9 +1229,3 @@ _pygi_argument_release (GIArgument *arg, } } -void -_pygi_argument_init (void) -{ - PyDateTime_IMPORT; -} - diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h index 73770bd..a923fd9 100644 --- a/gi/pygi-argument.h +++ b/gi/pygi-argument.h @@ -42,18 +42,6 @@ gpointer _pygi_arg_to_hash_pointer (const GIArgument *arg, void _pygi_hash_pointer_to_arg (GIArgument *arg, GITypeTag type_tag); -gint _pygi_g_type_interface_check_object (GIBaseInfo *info, - PyObject *object); - -gint _pygi_g_type_info_check_object (GITypeInfo *type_info, - PyObject *object, - gboolean allow_none); - -gint _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, - gboolean is_instance, - PyObject *object); - - GArray* _pygi_argument_to_array (GIArgument *arg, PyGIArgArrayLengthPolicy array_length_policy, void *user_data1, @@ -74,8 +62,6 @@ void _pygi_argument_release (GIArgument *arg, GITransfer transfer, GIDirection direction); -void _pygi_argument_init (void); - gboolean pygi_argument_to_gssize (GIArgument *arg_in, GITypeTag type_tag, gssize *gssize_out); diff --git a/gi/pygi-info.c b/gi/pygi-info.c index 8e0892a..cc8656b 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -1812,6 +1812,81 @@ out: return array_len; } +static gint +_pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, + gboolean is_instance, + PyObject *object) +{ + gint retval; + + GType g_type; + PyObject *py_type; + gchar *type_name_expected = NULL; + GIInfoType interface_type; + + interface_type = g_base_info_get_type (info); + if ( (interface_type == GI_INFO_TYPE_STRUCT) && + (g_struct_info_is_foreign ( (GIStructInfo*) info))) { + /* TODO: Could we check is the correct foreign type? */ + return 1; + } + + g_type = g_registered_type_info_get_g_type (info); + if (g_type != G_TYPE_NONE) { + py_type = _pygi_type_get_from_g_type (g_type); + } else { + py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info); + } + + if (py_type == NULL) { + return 0; + } + + g_assert (PyType_Check (py_type)); + + if (is_instance) { + retval = PyObject_IsInstance (object, py_type); + if (!retval) { + type_name_expected = _pygi_g_base_info_get_fullname ( + (GIBaseInfo *) info); + } + } else { + if (!PyObject_Type (py_type)) { + type_name_expected = "type"; + retval = 0; + } else if (!PyType_IsSubtype ( (PyTypeObject *) object, + (PyTypeObject *) py_type)) { + type_name_expected = _pygi_g_base_info_get_fullname ( + (GIBaseInfo *) info); + retval = 0; + } else { + retval = 1; + } + } + + Py_DECREF (py_type); + + if (!retval) { + PyTypeObject *object_type; + + if (type_name_expected == NULL) { + return -1; + } + + object_type = (PyTypeObject *) PyObject_Type (object); + if (object_type == NULL) { + return -1; + } + + PyErr_Format (PyExc_TypeError, "Must be %s, not %s", + type_name_expected, object_type->tp_name); + + g_free (type_name_expected); + } + + return retval; +} + static PyObject * _wrap_g_field_info_get_value (PyGIBaseInfo *self, PyObject *args) @@ -1965,21 +2040,6 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self, field_type_info = g_field_info_get_type ( (GIFieldInfo *) self->info); - /* Check the value. */ - { - gboolean retval; - - retval = _pygi_g_type_info_check_object (field_type_info, py_value, TRUE); - if (retval < 0) { - goto out; - } - - if (!retval) { - _PyGI_ERROR_PREFIX ("argument 2: "); - goto out; - } - } - /* Set the field's value. */ /* A few types are not handled by g_field_info_set_field, so do it here. */ if (!g_type_info_is_pointer (field_type_info) diff --git a/tests/Makefile.am b/tests/Makefile.am index dedf243..07eae97 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -86,6 +86,7 @@ EXTRA_DIST = \ org.gnome.test.gschema.xml \ test_cairo.py \ test_error.py \ + test_fields.py \ test_gio.py \ test_glib.py \ test_gobject.py \ diff --git a/tests/Makefile.in b/tests/Makefile.in index f3cfd16..9f99c72 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -387,6 +387,7 @@ EXTRA_DIST = \ org.gnome.test.gschema.xml \ test_cairo.py \ test_error.py \ + test_fields.py \ test_gio.py \ test_glib.py \ test_gobject.py \ diff --git a/tests/test_fields.py b/tests/test_fields.py new file mode 100644 index 0000000..def3511 --- /dev/null +++ b/tests/test_fields.py @@ -0,0 +1,188 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# coding=utf-8 + +import math +import unittest + +from gi.repository import GLib +from gi.repository import Regress +from gi.repository import GIMarshallingTests + +from compathelper import _unicode + + +class Number(object): + + def __init__(self, value): + self.value = value + + def __int__(self): + return int(self.value) + + def __float__(self): + return float(self.value) + + +class TestFields(unittest.TestCase): + + def test_int8(self): + s = Regress.TestStructA() + s.some_int8 = 21 + self.assertEqual(s.some_int8, 21) + + s.some_int8 = b"\x42" + self.assertEqual(s.some_int8, 0x42) + + self.assertRaises(TypeError, setattr, s, "some_int8", b"ab") + self.assertRaises(TypeError, setattr, s, "some_int8", None) + self.assertRaises(OverflowError, setattr, s, "some_int8", 128) + self.assertRaises(OverflowError, setattr, s, "some_int8", -129) + + s.some_int8 = 3.6 + self.assertEqual(s.some_int8, 3) + + s.some_int8 = Number(55) + self.assertEqual(s.some_int8, 55) + + def test_int(self): + s = Regress.TestStructA() + s.some_int = GLib.MAXINT + self.assertEqual(s.some_int, GLib.MAXINT) + + self.assertRaises(TypeError, setattr, s, "some_int", b"a") + self.assertRaises(TypeError, setattr, s, "some_int", None) + self.assertRaises( + OverflowError, setattr, s, "some_int", GLib.MAXINT + 1) + self.assertRaises( + OverflowError, setattr, s, "some_int", GLib.MININT - 1) + + s.some_int = 3.6 + self.assertEqual(s.some_int, 3) + + s.some_int = Number(GLib.MININT) + self.assertEqual(s.some_int, GLib.MININT) + + def test_long(self): + s = GIMarshallingTests.SimpleStruct() + s.long_ = GLib.MAXLONG + self.assertEqual(s.long_, GLib.MAXLONG) + + self.assertRaises(TypeError, setattr, s, "long_", b"a") + self.assertRaises(TypeError, setattr, s, "long_", None) + self.assertRaises(OverflowError, setattr, s, "long_", GLib.MAXLONG + 1) + self.assertRaises(OverflowError, setattr, s, "long_", GLib.MINLONG - 1) + + s.long_ = 3.6 + self.assertEqual(s.long_, 3) + + s.long_ = Number(GLib.MINLONG) + self.assertEqual(s.long_, GLib.MINLONG) + + def test_double(self): + s = Regress.TestStructA() + s.some_double = GLib.MAXDOUBLE + self.assertEqual(s.some_double, GLib.MAXDOUBLE) + s.some_double = GLib.MINDOUBLE + self.assertEqual(s.some_double, GLib.MINDOUBLE) + + s.some_double = float("nan") + self.assertTrue(math.isnan(s.some_double)) + + self.assertRaises(TypeError, setattr, s, "some_double", b"a") + self.assertRaises(TypeError, setattr, s, "some_double", None) + + def test_gtype(self): + s = Regress.TestStructE() + + s.some_type = Regress.TestObj + self.assertEqual(s.some_type, Regress.TestObj.__gtype__) + + self.assertRaises(TypeError, setattr, s, "some_type", 42) + + def test_unichar(self): + # I can't find a unichar field.. + pass + + def test_utf8(self): + s = GIMarshallingTests.BoxedStruct() + s.string_ = "hello" + self.assertEqual(s.string_, "hello") + + s.string_ = _unicode("hello") + self.assertEqual(s.string_, _unicode("hello")) + + s.string_ = None + self.assertEqual(s.string_, None) + + self.assertRaises(TypeError, setattr, s, "string_", 42) + + def test_array_of_structs(self): + s = Regress.TestStructD() + self.assertEqual(s.array1, []) + self.assertEqual(s.array2, []) + + def test_interface(self): + s = Regress.TestStructC() + + obj = Regress.TestObj() + s.obj = obj + self.assertTrue(s.obj is obj) + + s.obj = None + self.assertTrue(s.obj is None) + + self.assertRaises(TypeError, setattr, s, "obj", object()) + + def test_glist(self): + s = Regress.TestStructD() + self.assertEqual(s.list, []) + + self.assertRaises(TypeError, setattr, s, "list", [object()]) + + def test_gpointer(self): + glist = GLib.List() + + glist.data = 123 + self.assertEqual(glist.data, 123) + + glist.data = None + self.assertEqual(glist.data, 0) + + def test_gptrarray(self): + s = Regress.TestStructD() + self.assertEqual(s.garray, []) + + self.assertRaises(TypeError, setattr, s, "garray", [object()]) + + def test_enum(self): + s = Regress.TestStructA() + + s.some_enum = Regress.TestEnum.VALUE3 + self.assertEqual(s.some_enum, Regress.TestEnum.VALUE3) + + self.assertRaises(TypeError, setattr, s, "some_enum", object()) + + s.some_enum = 0 + self.assertEqual(s.some_enum, Regress.TestEnum.VALUE1) + + def test_union(self): + s = Regress.TestStructE() + self.assertEqual(s.some_union, [None, None]) + + def test_struct(self): + s = GIMarshallingTests.NestedStruct() + + # FIXME: segfaults + # https://bugzilla.gnome.org/show_bug.cgi?id=747002 + # s.simple_struct = None + + self.assertRaises(TypeError, setattr, s, "simple_struct", object()) + + sub = GIMarshallingTests.SimpleStruct() + sub.long_ = 42 + s.simple_struct = sub + self.assertEqual(s.simple_struct.long_, 42) + + def test_ghashtable(self): + obj = Regress.TestObj() + self.assertTrue(obj.hash_table is None) diff --git a/tests/test_gi.py b/tests/test_gi.py index 22a5738..f69a61c 100644 --- a/tests/test_gi.py +++ b/tests/test_gi.py @@ -17,6 +17,7 @@ from io import StringIO, BytesIO import gi import gi.overrides +from gi import PyGIWarning from gi import PyGIDeprecationWarning from gi.repository import GObject, GLib, Gio @@ -2773,6 +2774,20 @@ class TestProjectVersion(unittest.TestCase): gi.check_version("3.3.5") +class TestGIWarning(unittest.TestCase): + + def test_warning(self): + ignored_by_default = (DeprecationWarning, PendingDeprecationWarning, + ImportWarning) + + with warnings.catch_warnings(record=True) as warn: + warnings.simplefilter('always') + warnings.warn("test", PyGIWarning) + self.assertTrue(issubclass(warn[0].category, Warning)) + # We don't want PyGIWarning get ignored by default + self.assertFalse(issubclass(warn[0].category, ignored_by_default)) + + class TestDeprecation(unittest.TestCase): def test_method(self): d = GLib.Date.new()