[pygobject] int converters: unify overflow error handling



commit 0520434aa75e191c1b679bbc1a738f7ee136c2e2
Author: Christoph Reiter <reiter christoph gmail com>
Date:   Sat Apr 14 11:48:49 2018 +0200

    int converters: unify overflow error handling
    
    In case functions like PyLong_AsLong() fail we bail out and just return the
    error set by it. In most cases this is due to overflow and results in error
    messages such as "too large to convert" and "too large to convert to C long".
    
    The problem here is that for the same type of error we get different error
    messages depending on the Python version, the architecture (long size) or the
    size of the value itself.
    
    To unify the error message reraise the OverflowError with our default
    error message in all cases.

 gi/pygi-basictype.c          | 252 ++++++++++++++++++++++++++++++-------------
 gi/pygi-util.c               |  32 ++++++
 gi/pygi-util.h               |   1 +
 tests/test_everything.py     | 211 ++++++++++++++++++++++++++++++++++--
 tests/test_gi.py             |  15 ++-
 tests/test_overrides_glib.py |   2 +-
 6 files changed, 422 insertions(+), 91 deletions(-)
---
diff --git a/gi/pygi-basictype.c b/gi/pygi-basictype.c
index 75db0b26..3dab06d5 100644
--- a/gi/pygi-basictype.c
+++ b/gi/pygi-basictype.c
@@ -23,6 +23,7 @@
 #include "pygi-type.h"
 #include "pygi-basictype.h"
 #include "pygi-argument.h"
+#include "pygi-util.h"
 
 #ifdef G_OS_WIN32
 #include <math.h>
@@ -497,18 +498,25 @@ pygi_gint_from_py (PyObject *object, gint *result)
         return FALSE;
 
     long_value = PYGLIB_PyLong_AsLong (number);
-    Py_DECREF (number);
-    if (PyErr_Occurred ())
-        return FALSE;
-
-    if (long_value < G_MININT || long_value > G_MAXINT) {
-        PyErr_Format (PyExc_OverflowError, "%ld not in range %d to %d",
-                      long_value, (int)G_MININT, (int)G_MAXINT);
+    if (PyErr_Occurred ()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value < G_MININT || long_value > G_MAXINT) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (gint)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %d to %d",
+        number, (int)G_MININT, (int)G_MAXINT);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 PyObject *
@@ -528,18 +536,25 @@ pygi_guint_from_py (PyObject *object, guint *result)
         return FALSE;
 
     long_value = PyLong_AsUnsignedLong (number);
-    Py_DECREF (number);
-    if (PyErr_Occurred ())
-        return FALSE;
-
-    if (long_value > G_MAXUINT) {
-        PyErr_Format (PyExc_OverflowError, "%lu not in range %ld to %lu",
-                      long_value, (long)0, (unsigned long)G_MAXUINT);
+    if (PyErr_Occurred ()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value > G_MAXUINT) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (gint)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %lu",
+        number, (long)0, (unsigned long)G_MAXUINT);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 PyObject *
@@ -565,12 +580,23 @@ pygi_glong_from_py (PyObject *object, glong *result)
         return FALSE;
 
     long_value = PyLong_AsLong (number);
-    Py_DECREF (number);
-    if (long_value == -1 && PyErr_Occurred ())
+    if (long_value == -1 && PyErr_Occurred ()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    }
 
+    Py_DECREF (number);
     *result = (glong)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %ld",
+        number, (long)G_MINLONG, (long)G_MAXLONG);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 PyObject *
@@ -590,12 +616,23 @@ pygi_gulong_from_py (PyObject *object, gulong *result)
         return FALSE;
 
     long_value = PyLong_AsUnsignedLong (number);
-    Py_DECREF (number);
-    if (PyErr_Occurred ())
+    if (PyErr_Occurred ()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    }
 
+    Py_DECREF (number);
     *result = (gulong)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %lu",
+        number, (long)0, (unsigned long)G_MAXULONG);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 PyObject *
@@ -628,18 +665,25 @@ pygi_gint8_from_py (PyObject *object, gint8 *result)
         return FALSE;
 
     long_value = PyLong_AsLong (number);
-    Py_DECREF (number);
-    if (long_value == -1 && PyErr_Occurred())
-        return FALSE;
-
-    if (long_value < G_MININT8 || long_value > G_MAXINT8) {
-        PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
-                      long_value, (long)G_MININT8, (long)G_MAXINT8);
+    if (long_value == -1 && PyErr_Occurred()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value < G_MININT8 || long_value > G_MAXINT8) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (gint8)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %ld",
+        number, (long)G_MININT8, (long)G_MAXINT8);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 PyObject *
@@ -669,18 +713,25 @@ pygi_guint8_from_py (PyObject *object, guint8 *result)
         return FALSE;
 
     long_value = PyLong_AsLong (number);
-    Py_DECREF (number);
-    if (long_value == -1 && PyErr_Occurred())
-        return FALSE;
-
-    if (long_value < 0 || long_value > G_MAXUINT8) {
-        PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
-                      long_value, (long)0, (long)G_MAXUINT8);
+    if (long_value == -1 && PyErr_Occurred()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value < 0 || long_value > G_MAXUINT8) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (guint8)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %ld",
+        number, (long)0, (long)G_MAXUINT8);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 PyObject *
@@ -700,18 +751,25 @@ pygi_gint16_from_py (PyObject *object, gint16 *result)
         return FALSE;
 
     long_value = PyLong_AsLong (number);
-    Py_DECREF (number);
-    if (long_value == -1 && PyErr_Occurred())
-        return FALSE;
-
-    if (long_value < G_MININT16 || long_value > G_MAXINT16) {
-        PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
-                      long_value, (long)G_MININT16, (long)G_MAXINT16);
+    if (long_value == -1 && PyErr_Occurred()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value < G_MININT16 || long_value > G_MAXINT16) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (gint16)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %ld",
+        number, (long)G_MININT16, (long)G_MAXINT16);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 static PyObject *
@@ -731,18 +789,25 @@ pygi_guint16_from_py (PyObject *object, guint16 *result)
         return FALSE;
 
     long_value = PyLong_AsLong (number);
-    Py_DECREF (number);
-    if (long_value == -1 && PyErr_Occurred())
-        return FALSE;
-
-    if (long_value < 0 || long_value > G_MAXUINT16) {
-        PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
-                      long_value, (long)0, (long)G_MAXUINT16);
+    if (long_value == -1 && PyErr_Occurred()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value < 0 || long_value > G_MAXUINT16) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (guint16)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %ld",
+        number, (long)0, (long)G_MAXUINT16);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 static PyObject *
@@ -762,18 +827,25 @@ pygi_gint32_from_py (PyObject *object, gint32 *result)
         return FALSE;
 
     long_value = PyLong_AsLong (number);
-    Py_DECREF (number);
-    if (long_value == -1 && PyErr_Occurred())
-        return FALSE;
-
-    if (long_value < G_MININT32 || long_value > G_MAXINT32) {
-        PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
-                      long_value, (long)G_MININT32, (long)G_MAXINT32);
+    if (long_value == -1 && PyErr_Occurred()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value < G_MININT32 || long_value > G_MAXINT32) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (gint32)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %ld",
+        number, (long)G_MININT32, (long)G_MAXINT32);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 static PyObject *
@@ -793,18 +865,25 @@ pygi_guint32_from_py (PyObject *object, guint32 *result)
         return FALSE;
 
     long_value = PyLong_AsLongLong (number);
-    Py_DECREF (number);
-    if (PyErr_Occurred ())
-        return FALSE;
-
-    if (long_value < 0 || long_value > G_MAXUINT32) {
-        PyErr_Format (PyExc_OverflowError, "%lld not in range %ld to %lu",
-                      long_value, (long)0, (unsigned long)G_MAXUINT32);
+    if (PyErr_Occurred ()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value < 0 || long_value > G_MAXUINT32) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (guint32)long_value;
     return TRUE;
+
+overflow:
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %lu",
+        number, (long)0, (unsigned long)G_MAXUINT32);
+    Py_DECREF (number);
+    return FALSE;
 }
 
 static PyObject *
@@ -824,25 +903,36 @@ gboolean
 pygi_gint64_from_py (PyObject *object, gint64 *result)
 {
     long long long_value;
-    PyObject *number;
+    PyObject *number, *min, *max;
 
     number = base_number_checks (object);
     if (number == NULL)
         return FALSE;
 
     long_value = PyLong_AsLongLong (number);
-    Py_DECREF (number);
-    if (PyErr_Occurred ())
-        return FALSE;
-
-    if (long_value < G_MININT64 || long_value > G_MAXINT64) {
-        PyErr_Format (PyExc_OverflowError, "%lld not in range %lld to %lld",
-                      long_value, (long long)G_MININT64, (long long)G_MAXINT64);
+    if (PyErr_Occurred ()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value < G_MININT64 || long_value > G_MAXINT64) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (gint64)long_value;
     return TRUE;
+
+overflow:
+    min = pygi_gint64_to_py (G_MININT64);
+    max = pygi_gint64_to_py (G_MAXINT64);
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %S to %S",
+        number, min, max);
+    Py_DECREF (number);
+    Py_DECREF (min);
+    Py_DECREF (max);
+    return FALSE;
 }
 
 PyObject *
@@ -858,26 +948,34 @@ gboolean
 pygi_guint64_from_py (PyObject *object, guint64 *result)
 {
     unsigned long long long_value;
-    PyObject *number;
+    PyObject *number, *max;
 
     number = base_number_checks (object);
     if (number == NULL)
         return FALSE;
 
     long_value = PyLong_AsUnsignedLongLong (number);
-    Py_DECREF (number);
-    if (PyErr_Occurred ())
-        return FALSE;
-
-    if (long_value > G_MAXUINT64) {
-        PyErr_Format (PyExc_OverflowError, "%llu not in range %llu to %llu",
-                      long_value,
-                      (unsigned long long)0, (unsigned long long)G_MAXUINT64);
+    if (PyErr_Occurred ()) {
+        if (PyErr_ExceptionMatches (PyExc_OverflowError))
+            goto overflow;
+        Py_DECREF (number);
         return FALSE;
+    } else if (long_value > G_MAXUINT64) {
+        goto overflow;
     }
 
+    Py_DECREF (number);
     *result = (guint64)long_value;
     return TRUE;
+
+overflow:
+    max = pygi_guint64_to_py (G_MAXUINT64);
+    pygi_pyerr_format (
+        PyExc_OverflowError, "%S not in range %ld to %S",
+        number, (long)0, max);
+    Py_DECREF (number);
+    Py_DECREF (max);
+    return FALSE;
 }
 
 PyObject *
diff --git a/gi/pygi-util.c b/gi/pygi-util.c
index ee322238..c02a53c0 100644
--- a/gi/pygi-util.c
+++ b/gi/pygi-util.c
@@ -18,6 +18,38 @@
 
 #include "pygi-util.h"
 
+/**
+ * Like PyErr_Format, but supports the format syntax of
+ * PyUnicode_FromFormat also under Python 2.
+ * Note: Python 2 doesn't support %lld and %llo there.
+ */
+PyObject*
+pygi_pyerr_format (PyObject *exception, const char *format, ...)
+{
+    PyObject *text;
+    va_list argp;
+    va_start(argp, format);
+    text = PyUnicode_FromFormatV (format, argp);
+    va_end(argp);
+
+    if (text != NULL) {
+#if PY_MAJOR_VERSION < 3
+        PyObject *str;
+        str = PyUnicode_AsUTF8String (text);
+        Py_DECREF (text);
+        if (str) {
+            PyErr_SetObject (exception, str);
+            Py_DECREF (str);
+        }
+#else
+        PyErr_SetObject (exception, text);
+        Py_DECREF (text);
+#endif
+    }
+
+    return NULL;
+}
+
 gboolean
 pygi_guint_from_pyssize (Py_ssize_t pyval, guint *result)
 {
diff --git a/gi/pygi-util.h b/gi/pygi-util.h
index 592adf65..2f9847e6 100644
--- a/gi/pygi-util.h
+++ b/gi/pygi-util.h
@@ -12,6 +12,7 @@ PyObject * pyg_integer_richcompare(PyObject *v, PyObject *w, int op);
 PyObject * pyg_ptr_richcompare(void* a, void *b, int op);
 const gchar * pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix);
 PyObject * pygi_import_module (const char *name);
+PyObject * pygi_pyerr_format (PyObject *exception, const char *format, ...);
 
 gboolean pygi_guint_from_pyssize (Py_ssize_t pyval, guint *result);
 
diff --git a/tests/test_everything.py b/tests/test_everything.py
index 429404a0..1dec539c 100644
--- a/tests/test_everything.py
+++ b/tests/test_everything.py
@@ -12,6 +12,8 @@ import sys
 import os
 import platform
 
+import pytest
+
 from gi.repository import Regress as Everything
 from gi.repository import GObject
 from gi.repository import GLib
@@ -70,76 +72,214 @@ class TestEverything(unittest.TestCase):
                          GLib.MININT8)
         self.assertRaises(OverflowError, Everything.test_int8, GLib.MAXINT8 + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXINT8 + 1, GLib.MININT8, GLib.MAXINT8)):
+            Everything.test_int8(GLib.MAXINT8 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MININT8, GLib.MAXINT8)):
+            Everything.test_int8(GLib.MAXUINT64 * 2)
+
+    def test_uint8(self):
         self.assertEqual(Everything.test_uint8(GLib.MAXUINT8),
                          GLib.MAXUINT8)
         self.assertEqual(Everything.test_uint8(0), 0)
         self.assertRaises(OverflowError, Everything.test_uint8, -1)
         self.assertRaises(OverflowError, Everything.test_uint8, GLib.MAXUINT8 + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT8 + 1, GLib.MAXUINT8)):
+            Everything.test_uint8(GLib.MAXUINT8 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MAXUINT8)):
+            Everything.test_uint8(GLib.MAXUINT64 * 2)
+
     def test_int16(self):
         self.assertEqual(Everything.test_int16(GLib.MAXINT16),
                          GLib.MAXINT16)
         self.assertEqual(Everything.test_int16(GLib.MININT16),
                          GLib.MININT16)
-        self.assertRaises(OverflowError, Everything.test_int16, GLib.MAXINT16 + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="32768 not in range -32768 to 32767"):
+            Everything.test_int16(GLib.MAXINT16 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="36893488147419103230 not in range -32768 to 32767"):
+            Everything.test_int16(GLib.MAXUINT64 * 2)
+
+    def test_uint16(self):
         self.assertEqual(Everything.test_uint16(GLib.MAXUINT16),
                          GLib.MAXUINT16)
         self.assertEqual(Everything.test_uint16(0), 0)
         self.assertRaises(OverflowError, Everything.test_uint16, -1)
-        self.assertRaises(OverflowError, Everything.test_uint16, GLib.MAXUINT16 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT16 + 1, GLib.MAXUINT16)):
+            Everything.test_uint16(GLib.MAXUINT16 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MAXUINT16)):
+            Everything.test_uint16(GLib.MAXUINT64 * 2)
 
     def test_int32(self):
         self.assertEqual(Everything.test_int32(GLib.MAXINT32),
                          GLib.MAXINT32)
         self.assertEqual(Everything.test_int32(GLib.MININT32),
                          GLib.MININT32)
-        self.assertRaises(OverflowError, Everything.test_int32, GLib.MAXINT32 + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="2147483648 not in range -2147483648 to 2147483647"):
+            Everything.test_int32(GLib.MAXINT32 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range -2147483648 to 2147483647" % (
+                    GLib.MAXINT64 + 1,)):
+            Everything.test_int32(GLib.MAXINT64 + 1)
+
+    def test_uint32(self):
         self.assertEqual(Everything.test_uint32(GLib.MAXUINT32),
                          GLib.MAXUINT32)
         self.assertEqual(Everything.test_uint32(0), 0)
         self.assertRaises(OverflowError, Everything.test_uint32, -1)
-        self.assertRaises(OverflowError, Everything.test_uint32, GLib.MAXUINT32 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT32 + 1, GLib.MAXUINT32)):
+            Everything.test_uint32(GLib.MAXUINT32 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MAXUINT32)):
+            Everything.test_uint32(GLib.MAXUINT64 * 2)
 
     def test_int64(self):
         self.assertEqual(Everything.test_int64(GLib.MAXINT64),
                          GLib.MAXINT64)
         self.assertEqual(Everything.test_int64(GLib.MININT64),
                          GLib.MININT64)
-        self.assertRaises(OverflowError, Everything.test_int64, GLib.MAXINT64 + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXINT64 + 1, GLib.MININT64, GLib.MAXINT64)):
+            Everything.test_int64(GLib.MAXINT64 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MININT64, GLib.MAXINT64)):
+            Everything.test_int64(GLib.MAXUINT64 * 2)
+
+    def test_uint64(self):
         self.assertEqual(Everything.test_uint64(GLib.MAXUINT64),
                          GLib.MAXUINT64)
         self.assertEqual(Everything.test_uint64(0), 0)
         self.assertRaises(OverflowError, Everything.test_uint64, -1)
         self.assertRaises(OverflowError, Everything.test_uint64, GLib.MAXUINT64 + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 + 1, GLib.MAXUINT64)):
+            Everything.test_uint64(GLib.MAXUINT64 + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MAXUINT64)):
+            Everything.test_uint64(GLib.MAXUINT64 * 2)
+
     def test_int(self):
         self.assertEqual(Everything.test_int(GLib.MAXINT),
                          GLib.MAXINT)
         self.assertEqual(Everything.test_int(GLib.MININT),
                          GLib.MININT)
-        self.assertRaises(OverflowError, Everything.test_int, GLib.MAXINT + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXINT + 1, GLib.MININT, GLib.MAXINT)):
+            Everything.test_int(GLib.MAXINT + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MININT, GLib.MAXINT)):
+            Everything.test_int(GLib.MAXUINT64 * 2)
+
+    def test_uint(self):
         self.assertEqual(Everything.test_uint(GLib.MAXUINT),
                          GLib.MAXUINT)
         self.assertEqual(Everything.test_uint(0), 0)
         self.assertRaises(OverflowError, Everything.test_uint, -1)
-        self.assertRaises(OverflowError, Everything.test_uint, GLib.MAXUINT + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT + 1, GLib.MAXUINT)):
+            Everything.test_uint(GLib.MAXUINT + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MAXUINT)):
+            Everything.test_uint(GLib.MAXUINT64 * 2)
 
     def test_short(self):
         self.assertEqual(Everything.test_short(GLib.MAXSHORT),
                          GLib.MAXSHORT)
         self.assertEqual(Everything.test_short(GLib.MINSHORT),
                          GLib.MINSHORT)
-        self.assertRaises(OverflowError, Everything.test_short, GLib.MAXSHORT + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXSHORT + 1, GLib.MINSHORT, GLib.MAXSHORT)):
+            Everything.test_short(GLib.MAXSHORT + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MINSHORT, GLib.MAXSHORT)):
+            Everything.test_short(GLib.MAXUINT64 * 2)
+
+    def test_ushort(self):
         self.assertEqual(Everything.test_ushort(GLib.MAXUSHORT),
                          GLib.MAXUSHORT)
         self.assertEqual(Everything.test_ushort(0), 0)
         self.assertRaises(OverflowError, Everything.test_ushort, -1)
-        self.assertRaises(OverflowError, Everything.test_ushort, GLib.MAXUSHORT + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUSHORT + 1, GLib.MAXUSHORT)):
+            Everything.test_ushort(GLib.MAXUSHORT + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MAXUSHORT)):
+            Everything.test_ushort(GLib.MAXUINT64 * 2)
 
     def test_long(self):
         self.assertEqual(Everything.test_long(GLib.MAXLONG),
@@ -148,25 +288,74 @@ class TestEverything(unittest.TestCase):
                          GLib.MINLONG)
         self.assertRaises(OverflowError, Everything.test_long, GLib.MAXLONG + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXLONG + 1, GLib.MINLONG, GLib.MAXLONG)):
+            Everything.test_long(GLib.MAXLONG + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MINLONG, GLib.MAXLONG)):
+            Everything.test_long(GLib.MAXUINT64 * 2)
+
+    def test_ulong(self):
         self.assertEqual(Everything.test_ulong(GLib.MAXULONG),
                          GLib.MAXULONG)
         self.assertEqual(Everything.test_ulong(0), 0)
         self.assertRaises(OverflowError, Everything.test_ulong, -1)
-        self.assertRaises(OverflowError, Everything.test_ulong, GLib.MAXULONG + 1)
 
-    def test_size(self):
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXULONG + 1, GLib.MAXULONG)):
+            Everything.test_ulong(GLib.MAXULONG + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MAXULONG)):
+            Everything.test_ulong(GLib.MAXUINT64 * 2)
+
+    def test_ssize(self):
         self.assertEqual(Everything.test_ssize(GLib.MAXSSIZE),
                          GLib.MAXSSIZE)
         self.assertEqual(Everything.test_ssize(GLib.MINSSIZE),
                          GLib.MINSSIZE)
         self.assertRaises(OverflowError, Everything.test_ssize, GLib.MAXSSIZE + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXSSIZE + 1, GLib.MINSSIZE, GLib.MAXSSIZE)):
+            Everything.test_ssize(GLib.MAXSSIZE + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range %s to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MINSSIZE, GLib.MAXSSIZE)):
+            Everything.test_ssize(GLib.MAXUINT64 * 2)
+
+    def test_size(self):
         self.assertEqual(Everything.test_size(GLib.MAXSIZE),
                          GLib.MAXSIZE)
         self.assertEqual(Everything.test_size(0), 0)
         self.assertRaises(OverflowError, Everything.test_size, -1)
         self.assertRaises(OverflowError, Everything.test_size, GLib.MAXSIZE + 1)
 
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXSIZE + 1, GLib.MAXSIZE)):
+            Everything.test_size(GLib.MAXSIZE + 1)
+
+        with pytest.raises(
+                OverflowError,
+                match="%s not in range 0 to %s" % (
+                    GLib.MAXUINT64 * 2, GLib.MAXSIZE)):
+            Everything.test_size(GLib.MAXUINT64 * 2)
+
     def test_timet(self):
         self.assertEqual(Everything.test_timet(42), 42)
         self.assertRaises(OverflowError, Everything.test_timet, GLib.MAXUINT64 + 1)
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 2a6466cf..51a9ecd0 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1618,10 +1618,21 @@ class TestGValue(unittest.TestCase):
 
         with pytest.raises(
                 OverflowError,
-                match=r'.*(not in range %d to %d|too large to convert).*' % (
-                    GLib.MININT, GLib.MAXINT)):
+                match='Item 0: %d not in range %d to %d' % (
+                    GLib.MAXINT + 1, GLib.MININT, GLib.MAXINT)):
             GIMarshallingTests.gvalue_flat_array([GLib.MAXINT + 1, "42", True])
 
+        if PY2:
+            min_, max_ = GLib.MINLONG, GLib.MAXLONG
+        else:
+            min_, max_ = GLib.MININT, GLib.MAXINT
+
+        with pytest.raises(
+                OverflowError,
+                match='Item 0: %d not in range %d to %d' % (
+                    GLib.MAXUINT64 * 2, min_, max_)):
+            GIMarshallingTests.gvalue_flat_array([GLib.MAXUINT64 * 2, "42", True])
+
     def test_gvalue_flat_array_out(self):
         values = GIMarshallingTests.return_gvalue_flat_array()
         self.assertEqual(values, [42, '42', True])
diff --git a/tests/test_overrides_glib.py b/tests/test_overrides_glib.py
index 4fd8b1d6..34672535 100644
--- a/tests/test_overrides_glib.py
+++ b/tests/test_overrides_glib.py
@@ -577,7 +577,7 @@ class TestGVariant(unittest.TestCase):
 
         gerror = GLib.Error(code=GLib.MAXUINT)
         self.assertRaisesRegexp(OverflowError,
-                                ".*(not in range|too large to convert).*",
+                                ".*not in range.*",
                                 GLib.Variant.parse_error_print_context,
                                 gerror, source_str)
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]