Imported Upstream version 0.29.4 upstream/0.29.4
authorDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 31 Dec 2020 03:04:45 +0000 (12:04 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 31 Dec 2020 03:04:45 +0000 (12:04 +0900)
CHANGES.rst
Cython/Compiler/Optimize.py
Cython/Shadow.py
Cython/Utility/Optimize.c
runtests.py
tests/run/float_division.pyx
tests/run/future_division.pyx
tests/run/modop.pyx
tests/run/non_future_division.pyx
tests/run/numpy_subarray.pyx
tests/run/sequential_parallel.pyx

index a29750ffcffcd0ac0af14be0b6bb83d0285fdc7e..84a9a92715a626bbd4065b5a42f2e85969e9c1db 100644 (file)
@@ -2,6 +2,16 @@
 Cython Changelog
 ================
 
+0.29.4 (2019-02-01)
+===================
+
+Bugs fixed
+----------
+
+* Division of numeric constants by a runtime value of 0 could fail to raise a
+  ``ZeroDivisionError``.  (Github issue #2820)
+
+
 0.29.3 (2019-01-19)
 ===================
 
index 4c306d56642fc8e43f43a2c7c42c58fc52030c77..5c6dd02cd50b7050b74a21fbf1cc49214653b750 100644 (file)
@@ -3166,6 +3166,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
                 PyrexTypes.CFuncTypeArg("op2", PyrexTypes.py_object_type, None),
                 PyrexTypes.CFuncTypeArg("cval", ctype, None),
                 PyrexTypes.CFuncTypeArg("inplace", PyrexTypes.c_bint_type, None),
+                PyrexTypes.CFuncTypeArg("zerodiv_check", PyrexTypes.c_bint_type, None),
             ], exception_value=None if ret_type.is_pyobject else ret_type.exception_value))
         for ctype in (PyrexTypes.c_long_type, PyrexTypes.c_double_type)
         for ret_type in (PyrexTypes.py_object_type, PyrexTypes.c_bint_type)
@@ -3297,12 +3298,22 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
             # Cut off at an integer border that is still safe for all operations.
             return node
 
+        if operator in ('TrueDivide', 'FloorDivide', 'Divide', 'Remainder'):
+            if args[1].constant_result == 0:
+                # Don't optimise division by 0. :)
+                return node
+
         args = list(args)
         args.append((ExprNodes.FloatNode if is_float else ExprNodes.IntNode)(
             numval.pos, value=numval.value, constant_result=numval.constant_result,
             type=num_type))
         inplace = node.inplace if isinstance(node, ExprNodes.NumBinopNode) else False
         args.append(ExprNodes.BoolNode(node.pos, value=inplace, constant_result=inplace))
+        if is_float or operator not in ('Eq', 'Ne'):
+            # "PyFloatBinop" and "PyIntBinop" take an additional "check for zero division" argument.
+            zerodivision_check = arg_order == 'CObj' and (
+                not node.cdivision if isinstance(node, ExprNodes.DivNode) else False)
+            args.append(ExprNodes.BoolNode(node.pos, value=zerodivision_check, constant_result=zerodivision_check))
 
         utility_code = TempitaUtilityCode.load_cached(
             "PyFloatBinop" if is_float else "PyIntCompare" if operator in ('Eq', 'Ne') else "PyIntBinop",
index 4ac0150eeca51dd985cddad42aefe2b989e6dc60..ab11c3307522efbdf9e484a1be434225acc02831 100644 (file)
@@ -1,7 +1,7 @@
 # cython.* namespace for pure mode.
 from __future__ import absolute_import
 
-__version__ = "0.29.3"
+__version__ = "0.29.4"
 
 try:
     from __builtin__ import basestring
index 3366f9cf04dc5e857a41edc92d693c7f99db181c..04b3ec75aab3188cd0fa5d15982ea5140e6fc7cb 100644 (file)
@@ -787,9 +787,9 @@ static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject els
 
 {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}}
 #if !CYTHON_COMPILING_IN_PYPY
-static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, int inplace); /*proto*/
+static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); /*proto*/
 #else
-#define __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(op1, op2, intval, inplace) \
+#define __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(op1, op2, intval, inplace, zerodivision_check) \
     {{if op in ('Eq', 'Ne')}}{{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}(PyObject_RichCompare(op1, op2, Py_{{op.upper()}}))
     {{else}}(inplace ? PyNumber_InPlace{{op}}(op1, op2) : PyNumber_{{op}}(op1, op2))
     {{endif}}
@@ -804,6 +804,8 @@ static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op
 {{py: return_true = 'Py_RETURN_TRUE' if ret_type.is_pyobject else 'return 1'}}
 {{py: return_false = 'Py_RETURN_FALSE' if ret_type.is_pyobject else 'return 0'}}
 {{py: slot_name = {'TrueDivide': 'true_divide', 'FloorDivide': 'floor_divide'}.get(op, op.lower()) }}
+{{py: cfunc_name = '__Pyx_PyInt_%s%s%s' % ('' if ret_type.is_pyobject else 'Bool', op, order)}}
+{{py: zerodiv_check = lambda operand, _cfunc_name=cfunc_name: '%s_ZeroDivisionError(%s)' % (_cfunc_name, operand)}}
 {{py:
 c_op = {
     'Add': '+', 'Subtract': '-', 'Remainder': '%', 'TrueDivide': '/', 'FloorDivide': '/',
@@ -812,7 +814,21 @@ c_op = {
     }[op]
 }}
 
-static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, CYTHON_UNUSED int inplace) {
+{{if op in ('TrueDivide', 'FloorDivide', 'Remainder')}}
+#if PY_MAJOR_VERSION < 3 || CYTHON_USE_PYLONG_INTERNALS
+#define {{zerodiv_check('operand')}} \
+    if (unlikely(zerodivision_check && ((operand) == 0))) { \
+        PyErr_SetString(PyExc_ZeroDivisionError, "integer division{{if op == 'Remainder'}} or modulo{{endif}} by zero"); \
+        return NULL; \
+    }
+#endif
+{{endif}}
+
+static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, int inplace, int zerodivision_check) {
+    // Prevent "unused" warnings.
+    (void)inplace;
+    (void)zerodivision_check;
+
     {{if op in ('Eq', 'Ne')}}
     if (op1 == op2) {
         {{return_true if op == 'Eq' else return_false}};
@@ -841,18 +857,21 @@ static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op
                 return PyInt_FromLong(x);
             return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
         {{elif c_op == '%'}}
+            {{zerodiv_check('b')}}
             // see ExprNodes.py :: mod_int_utility_code
             x = a % b;
             x += ((x != 0) & ((x ^ b) < 0)) * b;
             return PyInt_FromLong(x);
         {{elif op == 'TrueDivide'}}
+            {{zerodiv_check('b')}}
             if (8 * sizeof(long) <= 53 || likely(labs({{ival}}) <= ((PY_LONG_LONG)1 << 53))) {
                 return PyFloat_FromDouble((double)a / (double)b);
             }
             // let Python do the rounding
             return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
         {{elif op == 'FloorDivide'}}
-            // INT_MIN / -1  is the only case that overflows
+            // INT_MIN / -1  is the only case that overflows, b == 0 is an error case
+            {{zerodiv_check('b')}}
             if (unlikely(b == -1 && ((unsigned long)a) == 0-(unsigned long)a))
                 return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
             else {
@@ -934,16 +953,19 @@ static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op
             }
         {{else}}
             {{if c_op == '%'}}
+                {{zerodiv_check('b')}}
                 // see ExprNodes.py :: mod_int_utility_code
                 x = a % b;
                 x += ((x != 0) & ((x ^ b) < 0)) * b;
             {{elif op == 'TrueDivide'}}
+                {{zerodiv_check('b')}}
                 if ((8 * sizeof(long) <= 53 || likely(labs({{ival}}) <= ((PY_LONG_LONG)1 << 53)))
-                    || __Pyx_sst_abs(size) <= 52 / PyLong_SHIFT) {
+                        || __Pyx_sst_abs(size) <= 52 / PyLong_SHIFT) {
                     return PyFloat_FromDouble((double)a / (double)b);
                 }
                 return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
             {{elif op == 'FloorDivide'}}
+                {{zerodiv_check('b')}}
                 {
                     long q, r;
                     // see ExprNodes.py :: div_int_utility_code
@@ -1008,6 +1030,12 @@ static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op
             }
         {{else}}
             double result;
+            {{if op == 'TrueDivide'}}
+            if (unlikely(zerodivision_check && b == 0)) {
+                PyErr_SetString(PyExc_ZeroDivisionError, "float division by zero");
+                return NULL;
+            }
+            {{endif}}
             // copied from floatobject.c in Py3.5:
             PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
             result = ((double)a) {{c_op}} (double)b;
@@ -1030,9 +1058,9 @@ static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op
 
 {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}}
 #if !CYTHON_COMPILING_IN_PYPY
-static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, int inplace); /*proto*/
+static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, int inplace, int zerodivision_check); /*proto*/
 #else
-#define __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(op1, op2, floatval, inplace) \
+#define __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(op1, op2, floatval, inplace, zerodivision_check) \
     {{if op in ('Eq', 'Ne')}}{{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}(PyObject_RichCompare(op1, op2, Py_{{op.upper()}}))
     {{elif op == 'Divide'}}((inplace ? __Pyx_PyNumber_InPlaceDivide(op1, op2) : __Pyx_PyNumber_Divide(op1, op2)))
     {{else}}(inplace ? PyNumber_InPlace{{op}}(op1, op2) : PyNumber_{{op}}(op1, op2))
@@ -1047,6 +1075,8 @@ static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{
 {{py: return_true = 'Py_RETURN_TRUE' if ret_type.is_pyobject else 'return 1'}}
 {{py: return_false = 'Py_RETURN_FALSE' if ret_type.is_pyobject else 'return 0'}}
 {{py: pyval, fval = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }}
+{{py: cfunc_name = '__Pyx_PyFloat_%s%s%s' % ('' if ret_type.is_pyobject else 'Bool', op, order) }}
+{{py: zerodiv_check = lambda operand, _cfunc_name=cfunc_name: '%s_ZeroDivisionError(%s)' % (_cfunc_name, operand)}}
 {{py:
 c_op = {
     'Add': '+', 'Subtract': '-', 'TrueDivide': '/', 'Divide': '/', 'Remainder': '%',
@@ -1054,9 +1084,19 @@ c_op = {
     }[op]
 }}
 
-static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, CYTHON_UNUSED int inplace) {
+{{if order == 'CObj' and c_op in '%/'}}
+#define {{zerodiv_check('operand')}} if (unlikely(zerodivision_check && ((operand) == 0))) { \
+    PyErr_SetString(PyExc_ZeroDivisionError, "float division{{if op == 'Remainder'}} or modulo{{endif}} by zero"); \
+    return NULL; \
+}
+{{endif}}
+
+static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatval, int inplace, int zerodivision_check) {
     const double {{'a' if order == 'CObj' else 'b'}} = floatval;
     double {{fval}}{{if op not in ('Eq', 'Ne')}}, result{{endif}};
+    // Prevent "unused" warnings.
+    (void)inplace;
+    (void)zerodivision_check;
 
     {{if op in ('Eq', 'Ne')}}
     if (op1 == op2) {
@@ -1066,11 +1106,13 @@ static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{
 
     if (likely(PyFloat_CheckExact({{pyval}}))) {
         {{fval}} = PyFloat_AS_DOUBLE({{pyval}});
+        {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check(fval)}}{{endif}}
     } else
 
     #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_CheckExact({{pyval}}))) {
         {{fval}} = (double) PyInt_AS_LONG({{pyval}});
+        {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check(fval)}}{{endif}}
     } else
     #endif
 
@@ -1079,7 +1121,7 @@ static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{
         const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
         const Py_ssize_t size = Py_SIZE({{pyval}});
         switch (size) {
-            case  0: {{fval}} = 0.0; break;
+            case  0: {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check('0')}}{{else}}{{fval}} = 0.0;{{endif}} break;
             case -1: {{fval}} = -(double) digits[0]; break;
             case  1: {{fval}} = (double) digits[0]; break;
             {{for _size in (2, 3, 4)}}
@@ -1111,6 +1153,7 @@ static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{
         {{else}}
             {{fval}} = PyLong_AsDouble({{pyval}});
             if (unlikely({{fval}} == -1.0 && PyErr_Occurred())) return NULL;
+            {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check(fval)}}{{endif}}
         {{endif}}
         }
     } else {
@@ -1132,6 +1175,7 @@ static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{
         }
     {{else}}
         // copied from floatobject.c in Py3.5:
+        {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check('b')}}{{endif}}
         PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
         {{if c_op == '%'}}
         result = fmod(a, b);
index 80e77b51b1b1d286a30f5071d57c61fc2856917b..1f843c9e76f63ab4db3fe81ec94bbe929f88b3f6 100755 (executable)
@@ -1310,7 +1310,6 @@ def run_forked_test(result, run_func, test_name, fork=True):
     child_id = os.fork()
     if not child_id:
         result_code = 0
-        output = None
         try:
             try:
                 tests = partial_result = None
@@ -1330,8 +1329,9 @@ def run_forked_test(result, run_func, test_name, fork=True):
                                 _shortDescription=test_name,
                                 module_name=None)
                         partial_result.addError(tests, sys.exc_info())
-                output = open(result_file, 'wb')
-                pickle.dump(partial_result.data(), output)
+                if partial_result is not None:
+                    with open(result_file, 'wb') as output:
+                        pickle.dump(partial_result.data(), output)
             except:
                 traceback.print_exc()
         finally:
@@ -1339,11 +1339,6 @@ def run_forked_test(result, run_func, test_name, fork=True):
             except: pass
             try: sys.stdout.flush()
             except: pass
-            try:
-                if output is not None:
-                    output.close()
-            except:
-                pass
             os._exit(result_code)
 
     try:
@@ -1353,18 +1348,22 @@ def run_forked_test(result, run_func, test_name, fork=True):
         # upper byte of result_code, and the signal it was
         # killed by in the lower byte
         if result_code & 255:
-            raise Exception("Tests in module '%s' were unexpectedly killed by signal %d"%
-                            (module_name, result_code & 255))
+            raise Exception(
+                "Tests in module '%s' were unexpectedly killed by signal %d, see test output for details." % (
+                    module_name, result_code & 255))
         result_code >>= 8
         if result_code in (0,1):
-            input = open(result_file, 'rb')
             try:
-                PartialTestResult.join_results(result, pickle.load(input))
-            finally:
-                input.close()
+                with open(result_file, 'rb') as f:
+                    PartialTestResult.join_results(result, pickle.load(f))
+            except Exception:
+                raise Exception(
+                    "Failed to load test result from test in module '%s' after exit status %d,"
+                    " see test output for details." % (module_name, result_code))
         if result_code:
-            raise Exception("Tests in module '%s' exited with status %d" %
-                            (module_name, result_code))
+            raise Exception(
+                "Tests in module '%s' exited with status %d, see test output for details." % (
+                    module_name, result_code))
     finally:
         try:
             os.unlink(result_file)
index 36d6009384608eef2a3c510b1fd1c4c18803d073..69a8f1c3eaa6040b85758d9b764a1544c9700c99 100644 (file)
@@ -26,6 +26,39 @@ def float_by_float():
     return 3.0 / 2.0
 
 
+def div_by_0(x):
+    """
+    >>> div_by_0(0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_by_0(0.0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_by_0(1)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_by_0(1.0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> float('inf') / 0.0  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_by_0(float('inf'))  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_by_0(float('-inf'))  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> float('nan') / 0.0  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_by_0(float('nan'))  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    """
+    return x / 0.0
+
+
 def div_1_by(x):
     """
     >>> div_1_by(1.0)
@@ -42,6 +75,12 @@ def div_1_by(x):
     -0.0
     >>> div_1_by(float('nan'))
     nan
+    >>> div_1_by(0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_1_by(0.0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
     """
     return 1.0 / x
 
@@ -116,6 +155,12 @@ def div_neg_2_by(x):
     nan
     >>> div_neg_2_by(float('nan'))
     nan
+    >>> div_neg_2_by(0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_neg_2_by(0.0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
     """
     return (-2.0) / x
 
@@ -148,6 +193,12 @@ def div_nan_by(x):
     nan
     >>> div_nan_by(float('nan'))
     nan
+    >>> div_nan_by(0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_nan_by(0.0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
     """
     return float("nan") / x
 
@@ -182,6 +233,15 @@ def div_inf_by(x):
     nan
     >>> div_inf_by(float('-inf'))
     nan
+    >>> float("inf") / 0.0  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_inf_by(0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_inf_by(0.0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
     """
     return float("inf") / x
 
@@ -196,5 +256,14 @@ def div_neg_inf_by(x):
     inf
     >>> div_neg_inf_by(-1.0)
     inf
+    >>> float("-inf") / 0.0  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_neg_inf_by(0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
+    >>> div_neg_inf_by(0.0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: float division...
     """
     return float("-inf") / x
index 58208c6f9b5f5482972d6b4b9b56358b011e57c4..737fb06d351905767fad4b852d965ee6fdfbad4d 100644 (file)
@@ -157,3 +157,73 @@ def int_int(int a, int b):
     (0.5, 2.0)
     """
     return a/b, b/a
+
+
+def div_by_0(a):
+    """
+    >>> div_by_0(0)
+    'OK'
+    >>> div_by_0(0.0)
+    'OK'
+    """
+    try:
+        1/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 1"
+    try:
+        1//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 2"
+    try:
+        5.0/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 3"
+    try:
+        5.0//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 4"
+    try:
+        5/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 5"
+    try:
+        5//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 6"
+    try:
+        (2**15)/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 7"
+    try:
+        (2**15)//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 8"
+    try:
+        (2**30)/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 9"
+    try:
+        (2**30)//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 10"
+    return 'OK'
index 2b9a3380a48d1d099d23ae9e84cd950e5ae86c1a..c7b4c7d57ef78cbdcfec8794f2e1a3e3074c19d6 100644 (file)
@@ -7,11 +7,25 @@ def modobj(obj2, obj3):
     1
     >>> modobj('%d', 5)
     '5'
+    >>> modobj(1, 0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: integer division...
     """
     obj1 = obj2 % obj3
     return obj1
 
 
+def mod_10_obj(int2):
+    """
+    >>> mod_10_obj(0)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ZeroDivisionError: integer division...
+    >>> mod_10_obj(3)
+    1
+    """
+    return 10 % int2
+
+
 def mod_obj_10(int2):
     """
     >>> 0 % 10
index 70bcd174f3c48dcac81d05bc30c09c3bb55023dc..d1d84549bfc6eeb8809654a54e702f0e6390f980 100644 (file)
@@ -143,3 +143,73 @@ def int_int(int a, int b):
     (0, 2)
     """
     return a/b, b/a
+
+
+def div_by_0(a):
+    """
+    >>> div_by_0(0)
+    'OK'
+    >>> div_by_0(0.0)
+    'OK'
+    """
+    try:
+        1/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 1"
+    try:
+        1//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 2"
+    try:
+        5.0/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 3"
+    try:
+        5.0//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 4"
+    try:
+        5/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 5"
+    try:
+        5//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 6"
+    try:
+        (2**15)/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 7"
+    try:
+        (2**15)//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 8"
+    try:
+        (2**30)/a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 9"
+    try:
+        (2**30)//a
+    except ZeroDivisionError:
+        pass
+    else:
+        return "FAIL 10"
+    return 'OK'
index a572d49146d232021b67c1de9d9b6ecc8b18fcaf..c5d82d4b1ac6d8ec73a9043d063e42e5de7bc55b 100644 (file)
@@ -21,7 +21,7 @@ def test_record_subarray():
 
     # Make sure the dtype looks like we expect
     assert descr.fields == {'a': (py_numpy.dtype('int32'), 0),
-                            'b': (py_numpy.dtype(('<f8', (3, 3))), 4)}, descr.fields
+                            'b': (py_numpy.dtype(('=f8', (3, 3))), 4)}, descr.fields
 
     # Make sure that HASSUBARRAY is working
     assert not np.PyDataType_HASSUBARRAY(descr)
index 64e8233bde558f933561757c97ed12d3092f8833..415d0bdc761792f3924c02e1ab69026da353b658 100644 (file)
@@ -60,7 +60,7 @@ def test_prange_matches_range(int start, int stop, int step):
     >>> test_prange_matches_range(2, -10, -3)
     >>> test_prange_matches_range(3, -10, -3)
     """
-    cdef int i, range_last, prange_last
+    cdef int i = -765432, range_last = -876543, prange_last = -987654
     prange_set = set()
     for i in prange(start, stop, step, nogil=True, num_threads=3):
         prange_last = i