import time
import unittest
+from unittest import mock
from test import support
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
INVALID_UNDERSCORE_LITERALS)
+try:
+ import _pylong
+except ImportError:
+ _pylong = None
+
L = [
('0', 0),
('1', 1),
with self.assertRaises(ValueError) as err:
int('_' + s)
+ @support.cpython_only # tests implementation details of CPython.
+ @unittest.skipUnless(_pylong, "_pylong module required")
+ @mock.patch.object(_pylong, "int_to_decimal_string")
+ def test_pylong_misbehavior_error_path_to_str(
+ self, mock_int_to_str):
+ with support.adjust_int_max_str_digits(20_000):
+ big_value = int('7'*19_999)
+ mock_int_to_str.return_value = None # not a str
+ with self.assertRaises(TypeError) as ctx:
+ str(big_value)
+ self.assertIn('_pylong.int_to_decimal_string did not',
+ str(ctx.exception))
+ mock_int_to_str.side_effect = RuntimeError("testABC")
+ with self.assertRaises(RuntimeError):
+ str(big_value)
+
+ @support.cpython_only # tests implementation details of CPython.
+ @unittest.skipUnless(_pylong, "_pylong module required")
+ @mock.patch.object(_pylong, "int_from_string")
+ def test_pylong_misbehavior_error_path_from_str(
+ self, mock_int_from_str):
+ big_value = '7'*19_999
+ with support.adjust_int_max_str_digits(20_000):
+ mock_int_from_str.return_value = b'not an int'
+ with self.assertRaises(TypeError) as ctx:
+ int(big_value)
+ self.assertIn('_pylong.int_from_string did not',
+ str(ctx.exception))
+
+ mock_int_from_str.side_effect = RuntimeError("test123")
+ with self.assertRaises(RuntimeError):
+ int(big_value)
+
if __name__ == "__main__":
unittest.main()
if (s == NULL) {
goto error;
}
- assert(PyUnicode_Check(s));
+ if (!PyUnicode_Check(s)) {
+ PyErr_SetString(PyExc_TypeError,
+ "_pylong.int_to_decimal_string did not return a str");
+ goto error;
+ }
if (writer) {
Py_ssize_t size = PyUnicode_GET_LENGTH(s);
if (_PyUnicodeWriter_Prepare(writer, size, '9') == -1) {
}
PyObject *s = PyUnicode_FromStringAndSize(start, end-start);
if (s == NULL) {
+ Py_DECREF(mod);
goto error;
}
PyObject *result = PyObject_CallMethod(mod, "int_from_string", "O", s);
goto error;
}
if (!PyLong_Check(result)) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
+ PyErr_SetString(PyExc_TypeError,
+ "_pylong.int_from_string did not return an int");
goto error;
}
*res = (PyLongObject *)result;
return 0;
error:
*res = NULL;
- return 0;
+ return 0; // See the long_from_string_base() API comment.
}
#endif /* WITH_PYLONG_MODULE */
* Return values:
*
* - Returns -1 on syntax error (exception needs to be set, *res is untouched)
- * - Returns 0 and sets *res to NULL for MemoryError/OverflowError.
+ * - Returns 0 and sets *res to NULL for MemoryError, OverflowError, or
+ * _pylong.int_from_string() errors.
* - Returns 0 and sets *res to an unsigned, unnormalized PyLong (success!).
*
* Afterwards *str is set to point to the first non-digit (which may be *str!).