Imported Upstream version 3.17.1 upstream/3.17.1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 30 Oct 2018 01:28:11 +0000 (10:28 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 30 Oct 2018 01:28:11 +0000 (10:28 +0900)
16 files changed:
ChangeLog
NEWS
PKG-INFO
configure
configure.ac
gi/__init__.py
gi/gimodule.c
gi/importer.py
gi/overrides/Gdk.py
gi/pygi-argument.c
gi/pygi-argument.h
gi/pygi-info.c
tests/Makefile.am
tests/Makefile.in
tests/test_fields.py [new file with mode: 0644]
tests/test_gi.py

index 89506bb..5d17a82 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,39 @@
-commit ecb2e6c64cbc420ed8f0d8dc8d1c3f6c516d6f63
+commit 2048dc8d1d708abce7037f96483c6d776567d6b5
+Author: Christoph Reiter <creiter@src.gnome.org>
+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 <creiter@src.gnome.org>
+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 <creiter@src.gnome.org>
 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 <sfeltman@src.gnome.org>
-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 <sfeltman@src.gnome.org>
-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 <sfeltman@src.gnome.org>
 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 <reiter.christoph@gmail.com>
+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 <reiter.christoph@gmail.com>
+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 <reiter.christoph@gmail.com>
+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 <sfeltman@src.gnome.org>
-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 <sfeltman@src.gnome.org>
diff --git a/NEWS b/NEWS
index bb9c3a9..e9b37e3 100644 (file)
--- 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
 
index 15f49bd..8c4e160 100644 (file)
--- 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
index f4b3c79..c6da85f 100755 (executable)
--- 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 <http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject>.
 #
@@ -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\\"
 
index 63fd7eb..c66ba35 100644 (file)
@@ -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 ...
index fe4abcf..caad569 100644 (file)
@@ -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')
index de9b787..74bf7cd 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <pyglib-python-compat.h>
 
+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);
 
index c097b74..0acbc23 100644 (file)
@@ -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):
index 15f2a0a..3ab5d6d 100644 (file)
@@ -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):
index d63520d..0c322e8 100644 (file)
@@ -25,7 +25,6 @@
 #include <string.h>
 #include <time.h>
 
-#include <datetime.h>
 #include <pyglib-python-compat.h>
 #include <pyglib.h>
 
@@ -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;
-}
-
index 73770bd..a923fd9 100644 (file)
@@ -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);
index 8e0892a..cc8656b 100644 (file)
@@ -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)
index dedf243..07eae97 100644 (file)
@@ -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 \
index f3cfd16..9f99c72 100644 (file)
@@ -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 (file)
index 0000000..def3511
--- /dev/null
@@ -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)
index 22a5738..f69a61c 100644 (file)
@@ -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()