mirror of https://github.com/python/cpython
gh-93649: Split exception tests from _testcapimodule.c (GH-102173)
Automerge-Triggered-By: GH:erlend-aasland
This commit is contained in:
parent
e07b304bb0
commit
efc985a714
|
@ -0,0 +1,145 @@
|
|||
import re
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
from test.support.script_helper import assert_python_failure
|
||||
|
||||
from .test_misc import decode_stderr
|
||||
|
||||
# Skip this test if the _testcapi module isn't available.
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
class Test_Exceptions(unittest.TestCase):
|
||||
|
||||
def test_exception(self):
|
||||
raised_exception = ValueError("5")
|
||||
new_exc = TypeError("TEST")
|
||||
try:
|
||||
raise raised_exception
|
||||
except ValueError as e:
|
||||
orig_sys_exception = sys.exception()
|
||||
orig_exception = _testcapi.set_exception(new_exc)
|
||||
new_sys_exception = sys.exception()
|
||||
new_exception = _testcapi.set_exception(orig_exception)
|
||||
reset_sys_exception = sys.exception()
|
||||
|
||||
self.assertEqual(orig_exception, e)
|
||||
|
||||
self.assertEqual(orig_exception, raised_exception)
|
||||
self.assertEqual(orig_sys_exception, orig_exception)
|
||||
self.assertEqual(reset_sys_exception, orig_exception)
|
||||
self.assertEqual(new_exception, new_exc)
|
||||
self.assertEqual(new_sys_exception, new_exception)
|
||||
else:
|
||||
self.fail("Exception not raised")
|
||||
|
||||
def test_exc_info(self):
|
||||
raised_exception = ValueError("5")
|
||||
new_exc = TypeError("TEST")
|
||||
try:
|
||||
raise raised_exception
|
||||
except ValueError as e:
|
||||
tb = e.__traceback__
|
||||
orig_sys_exc_info = sys.exc_info()
|
||||
orig_exc_info = _testcapi.set_exc_info(new_exc.__class__, new_exc, None)
|
||||
new_sys_exc_info = sys.exc_info()
|
||||
new_exc_info = _testcapi.set_exc_info(*orig_exc_info)
|
||||
reset_sys_exc_info = sys.exc_info()
|
||||
|
||||
self.assertEqual(orig_exc_info[1], e)
|
||||
|
||||
self.assertSequenceEqual(orig_exc_info, (raised_exception.__class__, raised_exception, tb))
|
||||
self.assertSequenceEqual(orig_sys_exc_info, orig_exc_info)
|
||||
self.assertSequenceEqual(reset_sys_exc_info, orig_exc_info)
|
||||
self.assertSequenceEqual(new_exc_info, (new_exc.__class__, new_exc, None))
|
||||
self.assertSequenceEqual(new_sys_exc_info, new_exc_info)
|
||||
else:
|
||||
self.assertTrue(False)
|
||||
|
||||
|
||||
class Test_FatalError(unittest.TestCase):
|
||||
|
||||
def check_fatal_error(self, code, expected, not_expected=()):
|
||||
with support.SuppressCrashReport():
|
||||
rc, out, err = assert_python_failure('-sSI', '-c', code)
|
||||
|
||||
err = decode_stderr(err)
|
||||
self.assertIn('Fatal Python error: test_fatal_error: MESSAGE\n',
|
||||
err)
|
||||
|
||||
match = re.search(r'^Extension modules:(.*) \(total: ([0-9]+)\)$',
|
||||
err, re.MULTILINE)
|
||||
if not match:
|
||||
self.fail(f"Cannot find 'Extension modules:' in {err!r}")
|
||||
modules = set(match.group(1).strip().split(', '))
|
||||
total = int(match.group(2))
|
||||
|
||||
for name in expected:
|
||||
self.assertIn(name, modules)
|
||||
for name in not_expected:
|
||||
self.assertNotIn(name, modules)
|
||||
self.assertEqual(len(modules), total)
|
||||
|
||||
@support.requires_subprocess()
|
||||
def test_fatal_error(self):
|
||||
# By default, stdlib extension modules are ignored,
|
||||
# but not test modules.
|
||||
expected = ('_testcapi',)
|
||||
not_expected = ('sys',)
|
||||
code = 'import _testcapi, sys; _testcapi.fatal_error(b"MESSAGE")'
|
||||
self.check_fatal_error(code, expected, not_expected)
|
||||
|
||||
# Mark _testcapi as stdlib module, but not sys
|
||||
expected = ('sys',)
|
||||
not_expected = ('_testcapi',)
|
||||
code = """if True:
|
||||
import _testcapi, sys
|
||||
sys.stdlib_module_names = frozenset({"_testcapi"})
|
||||
_testcapi.fatal_error(b"MESSAGE")
|
||||
"""
|
||||
self.check_fatal_error(code, expected)
|
||||
|
||||
|
||||
class Test_ErrSetAndRestore(unittest.TestCase):
|
||||
|
||||
def test_err_set_raised(self):
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_set_raised(ValueError())
|
||||
v = ValueError()
|
||||
try:
|
||||
_testcapi.err_set_raised(v)
|
||||
except ValueError as ex:
|
||||
self.assertIs(v, ex)
|
||||
|
||||
def test_err_restore(self):
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1, None)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, ValueError())
|
||||
try:
|
||||
_testcapi.err_restore(KeyError, "hi")
|
||||
except KeyError as k:
|
||||
self.assertEqual("hi", k.args[0])
|
||||
try:
|
||||
1/0
|
||||
except Exception as e:
|
||||
tb = e.__traceback__
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1, tb)
|
||||
with self.assertRaises(TypeError):
|
||||
_testcapi.err_restore(ValueError, 1, 0)
|
||||
try:
|
||||
_testcapi.err_restore(ValueError, 1, tb)
|
||||
except ValueError as v:
|
||||
self.assertEqual(1, v.args[0])
|
||||
self.assertIs(tb, v.__traceback__.tb_next)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -8,7 +8,6 @@ import importlib.util
|
|||
import os
|
||||
import pickle
|
||||
import random
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
|
@ -91,51 +90,6 @@ class CAPITest(unittest.TestCase):
|
|||
def test_memoryview_from_NULL_pointer(self):
|
||||
self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer)
|
||||
|
||||
def test_exception(self):
|
||||
raised_exception = ValueError("5")
|
||||
new_exc = TypeError("TEST")
|
||||
try:
|
||||
raise raised_exception
|
||||
except ValueError as e:
|
||||
orig_sys_exception = sys.exception()
|
||||
orig_exception = _testcapi.set_exception(new_exc)
|
||||
new_sys_exception = sys.exception()
|
||||
new_exception = _testcapi.set_exception(orig_exception)
|
||||
reset_sys_exception = sys.exception()
|
||||
|
||||
self.assertEqual(orig_exception, e)
|
||||
|
||||
self.assertEqual(orig_exception, raised_exception)
|
||||
self.assertEqual(orig_sys_exception, orig_exception)
|
||||
self.assertEqual(reset_sys_exception, orig_exception)
|
||||
self.assertEqual(new_exception, new_exc)
|
||||
self.assertEqual(new_sys_exception, new_exception)
|
||||
else:
|
||||
self.fail("Exception not raised")
|
||||
|
||||
def test_exc_info(self):
|
||||
raised_exception = ValueError("5")
|
||||
new_exc = TypeError("TEST")
|
||||
try:
|
||||
raise raised_exception
|
||||
except ValueError as e:
|
||||
tb = e.__traceback__
|
||||
orig_sys_exc_info = sys.exc_info()
|
||||
orig_exc_info = _testcapi.set_exc_info(new_exc.__class__, new_exc, None)
|
||||
new_sys_exc_info = sys.exc_info()
|
||||
new_exc_info = _testcapi.set_exc_info(*orig_exc_info)
|
||||
reset_sys_exc_info = sys.exc_info()
|
||||
|
||||
self.assertEqual(orig_exc_info[1], e)
|
||||
|
||||
self.assertSequenceEqual(orig_exc_info, (raised_exception.__class__, raised_exception, tb))
|
||||
self.assertSequenceEqual(orig_sys_exc_info, orig_exc_info)
|
||||
self.assertSequenceEqual(reset_sys_exc_info, orig_exc_info)
|
||||
self.assertSequenceEqual(new_exc_info, (new_exc.__class__, new_exc, None))
|
||||
self.assertSequenceEqual(new_sys_exc_info, new_exc_info)
|
||||
else:
|
||||
self.assertTrue(False)
|
||||
|
||||
@unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.')
|
||||
def test_seq_bytes_to_charp_array(self):
|
||||
# Issue #15732: crash in _PySequence_BytesToCharpArray()
|
||||
|
@ -837,46 +791,6 @@ class CAPITest(unittest.TestCase):
|
|||
self.assertRaises(TypeError, pynumber_tobase, '123', 10)
|
||||
self.assertRaises(SystemError, pynumber_tobase, 123, 0)
|
||||
|
||||
def check_fatal_error(self, code, expected, not_expected=()):
|
||||
with support.SuppressCrashReport():
|
||||
rc, out, err = assert_python_failure('-sSI', '-c', code)
|
||||
|
||||
err = decode_stderr(err)
|
||||
self.assertIn('Fatal Python error: test_fatal_error: MESSAGE\n',
|
||||
err)
|
||||
|
||||
match = re.search(r'^Extension modules:(.*) \(total: ([0-9]+)\)$',
|
||||
err, re.MULTILINE)
|
||||
if not match:
|
||||
self.fail(f"Cannot find 'Extension modules:' in {err!r}")
|
||||
modules = set(match.group(1).strip().split(', '))
|
||||
total = int(match.group(2))
|
||||
|
||||
for name in expected:
|
||||
self.assertIn(name, modules)
|
||||
for name in not_expected:
|
||||
self.assertNotIn(name, modules)
|
||||
self.assertEqual(len(modules), total)
|
||||
|
||||
@support.requires_subprocess()
|
||||
def test_fatal_error(self):
|
||||
# By default, stdlib extension modules are ignored,
|
||||
# but not test modules.
|
||||
expected = ('_testcapi',)
|
||||
not_expected = ('sys',)
|
||||
code = 'import _testcapi, sys; _testcapi.fatal_error(b"MESSAGE")'
|
||||
self.check_fatal_error(code, expected, not_expected)
|
||||
|
||||
# Mark _testcapi as stdlib module, but not sys
|
||||
expected = ('sys',)
|
||||
not_expected = ('_testcapi',)
|
||||
code = textwrap.dedent('''
|
||||
import _testcapi, sys
|
||||
sys.stdlib_module_names = frozenset({"_testcapi"})
|
||||
_testcapi.fatal_error(b"MESSAGE")
|
||||
''')
|
||||
self.check_fatal_error(code, expected)
|
||||
|
||||
def test_pyobject_repr_from_null(self):
|
||||
s = _testcapi.pyobject_repr_from_null()
|
||||
self.assertEqual(s, '<NULL>')
|
||||
|
@ -1214,9 +1128,9 @@ class TestPendingCalls(unittest.TestCase):
|
|||
self.pendingcalls_wait(l, n)
|
||||
|
||||
def test_gen_get_code(self):
|
||||
def genf(): yield
|
||||
gen = genf()
|
||||
self.assertEqual(_testcapi.gen_get_code(gen), gen.gi_code)
|
||||
def genf(): yield
|
||||
gen = genf()
|
||||
self.assertEqual(_testcapi.gen_get_code(gen), gen.gi_code)
|
||||
|
||||
|
||||
class SubinterpreterTest(unittest.TestCase):
|
||||
|
@ -1641,44 +1555,5 @@ class Test_Pep523API(unittest.TestCase):
|
|||
self.do_test(func2)
|
||||
|
||||
|
||||
class Test_ErrSetAndRestore(unittest.TestCase):
|
||||
|
||||
def test_err_set_raised(self):
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_set_raised(ValueError())
|
||||
v = ValueError()
|
||||
try:
|
||||
_testcapi.err_set_raised(v)
|
||||
except ValueError as ex:
|
||||
self.assertIs(v, ex)
|
||||
|
||||
def test_err_restore(self):
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1, None)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, ValueError())
|
||||
try:
|
||||
_testcapi.err_restore(KeyError, "hi")
|
||||
except KeyError as k:
|
||||
self.assertEqual("hi", k.args[0])
|
||||
try:
|
||||
1/0
|
||||
except Exception as e:
|
||||
tb = e.__traceback__
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1, tb)
|
||||
with self.assertRaises(TypeError):
|
||||
_testcapi.err_restore(ValueError, 1, 0)
|
||||
try:
|
||||
_testcapi.err_restore(ValueError, 1, tb)
|
||||
except ValueError as v:
|
||||
self.assertEqual(1, v.args[0])
|
||||
self.assertIs(tb, v.__traceback__.tb_next)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -169,7 +169,7 @@
|
|||
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
|
||||
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
|
||||
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c
|
||||
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/pytime.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c
|
||||
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/pytime.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c
|
||||
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
|
||||
|
||||
# Some testing modules MUST be built as shared libraries.
|
||||
|
|
|
@ -0,0 +1,277 @@
|
|||
#include "parts.h"
|
||||
|
||||
static PyObject *
|
||||
err_set_raised(PyObject *self, PyObject *exc)
|
||||
{
|
||||
Py_INCREF(exc);
|
||||
PyErr_SetRaisedException(exc);
|
||||
assert(PyErr_Occurred());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
err_restore(PyObject *self, PyObject *args) {
|
||||
PyObject *type = NULL, *value = NULL, *traceback = NULL;
|
||||
switch(PyTuple_Size(args)) {
|
||||
case 3:
|
||||
traceback = PyTuple_GetItem(args, 2);
|
||||
Py_INCREF(traceback);
|
||||
/* fall through */
|
||||
case 2:
|
||||
value = PyTuple_GetItem(args, 1);
|
||||
Py_INCREF(value);
|
||||
/* fall through */
|
||||
case 1:
|
||||
type = PyTuple_GetItem(args, 0);
|
||||
Py_INCREF(type);
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"wrong number of arguments");
|
||||
return NULL;
|
||||
}
|
||||
PyErr_Restore(type, value, traceback);
|
||||
assert(PyErr_Occurred());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* To test the format of exceptions as printed out. */
|
||||
static PyObject *
|
||||
exception_print(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *value;
|
||||
PyObject *tb = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:exception_print", &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyExceptionInstance_Check(value)) {
|
||||
tb = PyException_GetTraceback(value);
|
||||
}
|
||||
|
||||
PyErr_Display((PyObject *) Py_TYPE(value), value, tb);
|
||||
Py_XDECREF(tb);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException).
|
||||
Run via Lib/test/test_exceptions.py */
|
||||
static PyObject *
|
||||
make_exception_with_doc(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
const char *name;
|
||||
const char *doc = NULL;
|
||||
PyObject *base = NULL;
|
||||
PyObject *dict = NULL;
|
||||
|
||||
static char *kwlist[] = {"name", "doc", "base", "dict", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||
"s|sOO:make_exception_with_doc", kwlist,
|
||||
&name, &doc, &base, &dict))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyErr_NewExceptionWithDoc(name, doc, base, dict);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
raise_exception(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *exc;
|
||||
int num_args;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Oi:raise_exception", &exc, &num_args)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *exc_args = PyTuple_New(num_args);
|
||||
if (exc_args == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < num_args; ++i) {
|
||||
PyObject *v = PyLong_FromLong(i);
|
||||
if (v == NULL) {
|
||||
Py_DECREF(exc_args);
|
||||
return NULL;
|
||||
}
|
||||
PyTuple_SET_ITEM(exc_args, i, v);
|
||||
}
|
||||
PyErr_SetObject(exc, exc_args);
|
||||
Py_DECREF(exc_args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* reliably raise a MemoryError */
|
||||
static PyObject *
|
||||
raise_memoryerror(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
test_fatal_error(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *message;
|
||||
int release_gil = 0;
|
||||
if (!PyArg_ParseTuple(args, "y|i:fatal_error", &message, &release_gil)) {
|
||||
return NULL;
|
||||
}
|
||||
if (release_gil) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
Py_FatalError(message);
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
else {
|
||||
Py_FatalError(message);
|
||||
}
|
||||
// Py_FatalError() does not return, but exits the process.
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
test_set_exc_info(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *new_type, *new_value, *new_tb;
|
||||
PyObject *type, *value, *tb;
|
||||
if (!PyArg_ParseTuple(args, "OOO:test_set_exc_info",
|
||||
&new_type, &new_value, &new_tb))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyErr_GetExcInfo(&type, &value, &tb);
|
||||
|
||||
Py_INCREF(new_type);
|
||||
Py_INCREF(new_value);
|
||||
Py_INCREF(new_tb);
|
||||
PyErr_SetExcInfo(new_type, new_value, new_tb);
|
||||
|
||||
PyObject *orig_exc = PyTuple_Pack(3,
|
||||
type ? type : Py_None,
|
||||
value ? value : Py_None,
|
||||
tb ? tb : Py_None);
|
||||
Py_XDECREF(type);
|
||||
Py_XDECREF(value);
|
||||
Py_XDECREF(tb);
|
||||
return orig_exc;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
test_set_exception(PyObject *self, PyObject *new_exc)
|
||||
{
|
||||
PyObject *exc = PyErr_GetHandledException();
|
||||
assert(PyExceptionInstance_Check(exc) || exc == NULL);
|
||||
|
||||
PyErr_SetHandledException(new_exc);
|
||||
return exc;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
test_write_unraisable_exc(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *exc, *err_msg, *obj;
|
||||
if (!PyArg_ParseTuple(args, "OOO", &exc, &err_msg, &obj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *err_msg_utf8;
|
||||
if (err_msg != Py_None) {
|
||||
err_msg_utf8 = PyUnicode_AsUTF8(err_msg);
|
||||
if (err_msg_utf8 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
err_msg_utf8 = NULL;
|
||||
}
|
||||
|
||||
PyErr_SetObject((PyObject *)Py_TYPE(exc), exc);
|
||||
_PyErr_WriteUnraisableMsg(err_msg_utf8, obj);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* To test the format of tracebacks as printed out. */
|
||||
static PyObject *
|
||||
traceback_print(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *file;
|
||||
PyObject *traceback;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OO:traceback_print",
|
||||
&traceback, &file))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyTraceBack_Print(traceback, file) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Define the PyRecurdingInfinitelyError_Type
|
||||
*/
|
||||
|
||||
static PyTypeObject PyRecursingInfinitelyError_Type;
|
||||
|
||||
static int
|
||||
recurse_infinitely_error_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *type = (PyObject *)&PyRecursingInfinitelyError_Type;
|
||||
|
||||
/* Instantiating this exception starts infinite recursion. */
|
||||
Py_INCREF(type);
|
||||
PyErr_SetObject(type, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyTypeObject PyRecursingInfinitelyError_Type = {
|
||||
.tp_name = "RecursingInfinitelyError",
|
||||
.tp_basicsize = sizeof(PyBaseExceptionObject),
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
||||
.tp_doc = PyDoc_STR("Instantiating this exception starts infinite recursion."),
|
||||
.tp_init = (initproc)recurse_infinitely_error_init,
|
||||
};
|
||||
|
||||
static PyMethodDef test_methods[] = {
|
||||
{"err_restore", err_restore, METH_VARARGS},
|
||||
{"err_set_raised", err_set_raised, METH_O},
|
||||
{"exception_print", exception_print, METH_VARARGS},
|
||||
{"fatal_error", test_fatal_error, METH_VARARGS,
|
||||
PyDoc_STR("fatal_error(message, release_gil=False): call Py_FatalError(message)")},
|
||||
{"make_exception_with_doc", _PyCFunction_CAST(make_exception_with_doc),
|
||||
METH_VARARGS | METH_KEYWORDS},
|
||||
{"raise_exception", raise_exception, METH_VARARGS},
|
||||
{"raise_memoryerror", raise_memoryerror, METH_NOARGS},
|
||||
{"set_exc_info", test_set_exc_info, METH_VARARGS},
|
||||
{"set_exception", test_set_exception, METH_O},
|
||||
{"traceback_print", traceback_print, METH_VARARGS},
|
||||
{"write_unraisable_exc", test_write_unraisable_exc, METH_VARARGS},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
int
|
||||
_PyTestCapi_Init_Exceptions(PyObject *mod)
|
||||
{
|
||||
PyRecursingInfinitelyError_Type.tp_base = (PyTypeObject *)PyExc_Exception;
|
||||
if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddObjectRef(mod, "RecursingInfinitelyError",
|
||||
(PyObject *)&PyRecursingInfinitelyError_Type) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PyModule_AddFunctions(mod, test_methods) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -36,6 +36,7 @@ int _PyTestCapi_Init_Watchers(PyObject *module);
|
|||
int _PyTestCapi_Init_Long(PyObject *module);
|
||||
int _PyTestCapi_Init_Float(PyObject *module);
|
||||
int _PyTestCapi_Init_Structmember(PyObject *module);
|
||||
int _PyTestCapi_Init_Exceptions(PyObject *module);
|
||||
|
||||
#ifdef LIMITED_API_AVAILABLE
|
||||
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
|
||||
|
|
|
@ -720,33 +720,6 @@ pyobject_bytes_from_null(PyObject *self, PyObject *Py_UNUSED(ignored))
|
|||
return PyObject_Bytes(NULL);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
raise_exception(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *exc;
|
||||
PyObject *exc_args, *v;
|
||||
int num_args, i;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Oi:raise_exception",
|
||||
&exc, &num_args))
|
||||
return NULL;
|
||||
|
||||
exc_args = PyTuple_New(num_args);
|
||||
if (exc_args == NULL)
|
||||
return NULL;
|
||||
for (i = 0; i < num_args; ++i) {
|
||||
v = PyLong_FromLong(i);
|
||||
if (v == NULL) {
|
||||
Py_DECREF(exc_args);
|
||||
return NULL;
|
||||
}
|
||||
PyTuple_SET_ITEM(exc_args, i, v);
|
||||
}
|
||||
PyErr_SetObject(exc, exc_args);
|
||||
Py_DECREF(exc_args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_errno(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
@ -759,40 +732,6 @@ set_errno(PyObject *self, PyObject *args)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
test_set_exception(PyObject *self, PyObject *new_exc)
|
||||
{
|
||||
PyObject *exc = PyErr_GetHandledException();
|
||||
assert(PyExceptionInstance_Check(exc) || exc == NULL);
|
||||
|
||||
PyErr_SetHandledException(new_exc);
|
||||
return exc;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
test_set_exc_info(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *orig_exc;
|
||||
PyObject *new_type, *new_value, *new_tb;
|
||||
PyObject *type, *value, *tb;
|
||||
if (!PyArg_ParseTuple(args, "OOO:test_set_exc_info",
|
||||
&new_type, &new_value, &new_tb))
|
||||
return NULL;
|
||||
|
||||
PyErr_GetExcInfo(&type, &value, &tb);
|
||||
|
||||
Py_INCREF(new_type);
|
||||
Py_INCREF(new_value);
|
||||
Py_INCREF(new_tb);
|
||||
PyErr_SetExcInfo(new_type, new_value, new_tb);
|
||||
|
||||
orig_exc = PyTuple_Pack(3, type ? type : Py_None, value ? value : Py_None, tb ? tb : Py_None);
|
||||
Py_XDECREF(type);
|
||||
Py_XDECREF(value);
|
||||
Py_XDECREF(tb);
|
||||
return orig_exc;
|
||||
}
|
||||
|
||||
/* test_thread_state spawns a thread of its own, and that thread releases
|
||||
* `thread_done` when it's finished. The driver code has to know when the
|
||||
* thread finishes, because the thread uses a PyObject (the callable) that
|
||||
|
@ -1272,57 +1211,6 @@ profile_int(PyObject *self, PyObject* args)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* To test the format of tracebacks as printed out. */
|
||||
static PyObject *
|
||||
traceback_print(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *file;
|
||||
PyObject *traceback;
|
||||
int result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OO:traceback_print",
|
||||
&traceback, &file))
|
||||
return NULL;
|
||||
|
||||
result = PyTraceBack_Print(traceback, file);
|
||||
if (result < 0)
|
||||
return NULL;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* To test the format of exceptions as printed out. */
|
||||
static PyObject *
|
||||
exception_print(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *value;
|
||||
PyObject *tb = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:exception_print",
|
||||
&value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyExceptionInstance_Check(value)) {
|
||||
tb = PyException_GetTraceback(value);
|
||||
}
|
||||
|
||||
PyErr_Display((PyObject *) Py_TYPE(value), value, tb);
|
||||
Py_XDECREF(tb);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* reliably raise a MemoryError */
|
||||
static PyObject *
|
||||
raise_memoryerror(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Issue 6012 */
|
||||
static PyObject *str1, *str2;
|
||||
static int
|
||||
|
@ -1368,26 +1256,6 @@ code_newempty(PyObject *self, PyObject *args)
|
|||
return (PyObject *)PyCode_NewEmpty(filename, funcname, firstlineno);
|
||||
}
|
||||
|
||||
/* Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException).
|
||||
Run via Lib/test/test_exceptions.py */
|
||||
static PyObject *
|
||||
make_exception_with_doc(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
const char *name;
|
||||
const char *doc = NULL;
|
||||
PyObject *base = NULL;
|
||||
PyObject *dict = NULL;
|
||||
|
||||
static char *kwlist[] = {"name", "doc", "base", "dict", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||
"s|sOO:make_exception_with_doc", kwlist,
|
||||
&name, &doc, &base, &dict))
|
||||
return NULL;
|
||||
|
||||
return PyErr_NewExceptionWithDoc(name, doc, base, dict);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
make_memoryview_from_NULL_pointer(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||
{
|
||||
|
@ -2491,31 +2359,6 @@ negative_refcount(PyObject *self, PyObject *Py_UNUSED(args))
|
|||
#endif
|
||||
|
||||
|
||||
static PyObject*
|
||||
test_write_unraisable_exc(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *exc, *err_msg, *obj;
|
||||
if (!PyArg_ParseTuple(args, "OOO", &exc, &err_msg, &obj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *err_msg_utf8;
|
||||
if (err_msg != Py_None) {
|
||||
err_msg_utf8 = PyUnicode_AsUTF8(err_msg);
|
||||
if (err_msg_utf8 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
err_msg_utf8 = NULL;
|
||||
}
|
||||
|
||||
PyErr_SetObject((PyObject *)Py_TYPE(exc), exc);
|
||||
_PyErr_WriteUnraisableMsg(err_msg_utf8, obj);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
sequence_getitem(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
@ -2874,25 +2717,6 @@ test_py_is_funcs(PyObject *self, PyObject *Py_UNUSED(ignored))
|
|||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
test_fatal_error(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *message;
|
||||
int release_gil = 0;
|
||||
if (!PyArg_ParseTuple(args, "y|i:fatal_error", &message, &release_gil))
|
||||
return NULL;
|
||||
if (release_gil) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
Py_FatalError(message);
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
else {
|
||||
Py_FatalError(message);
|
||||
}
|
||||
// Py_FatalError() does not return, but exits the process.
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
// type->tp_version_tag
|
||||
static PyObject *
|
||||
type_get_version(PyObject *self, PyObject *type)
|
||||
|
@ -3492,46 +3316,9 @@ function_set_kw_defaults(PyObject *self, PyObject *args)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
err_set_raised(PyObject *self, PyObject *exc)
|
||||
{
|
||||
Py_INCREF(exc);
|
||||
PyErr_SetRaisedException(exc);
|
||||
assert(PyErr_Occurred());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
err_restore(PyObject *self, PyObject *args) {
|
||||
PyObject *type = NULL, *value = NULL, *traceback = NULL;
|
||||
switch(PyTuple_Size(args)) {
|
||||
case 3:
|
||||
traceback = PyTuple_GetItem(args, 2);
|
||||
Py_INCREF(traceback);
|
||||
/* fall through */
|
||||
case 2:
|
||||
value = PyTuple_GetItem(args, 1);
|
||||
Py_INCREF(value);
|
||||
/* fall through */
|
||||
case 1:
|
||||
type = PyTuple_GetItem(args, 0);
|
||||
Py_INCREF(type);
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"wrong number of arguments");
|
||||
return NULL;
|
||||
}
|
||||
PyErr_Restore(type, value, traceback);
|
||||
assert(PyErr_Occurred());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
|
||||
|
||||
static PyMethodDef TestMethods[] = {
|
||||
{"raise_exception", raise_exception, METH_VARARGS},
|
||||
{"raise_memoryerror", raise_memoryerror, METH_NOARGS},
|
||||
{"set_errno", set_errno, METH_VARARGS},
|
||||
{"test_config", test_config, METH_NOARGS},
|
||||
{"test_sizeof_c_types", test_sizeof_c_types, METH_NOARGS},
|
||||
|
@ -3574,15 +3361,9 @@ static PyMethodDef TestMethods[] = {
|
|||
#ifdef HAVE_GETTIMEOFDAY
|
||||
{"profile_int", profile_int, METH_NOARGS},
|
||||
#endif
|
||||
{"traceback_print", traceback_print, METH_VARARGS},
|
||||
{"exception_print", exception_print, METH_VARARGS},
|
||||
{"set_exception", test_set_exception, METH_O},
|
||||
{"set_exc_info", test_set_exc_info, METH_VARARGS},
|
||||
{"argparsing", argparsing, METH_VARARGS},
|
||||
{"code_newempty", code_newempty, METH_VARARGS},
|
||||
{"eval_code_ex", eval_eval_code_ex, METH_VARARGS},
|
||||
{"make_exception_with_doc", _PyCFunction_CAST(make_exception_with_doc),
|
||||
METH_VARARGS | METH_KEYWORDS},
|
||||
{"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer,
|
||||
METH_NOARGS},
|
||||
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
|
||||
|
@ -3633,7 +3414,6 @@ static PyMethodDef TestMethods[] = {
|
|||
#ifdef Py_REF_DEBUG
|
||||
{"negative_refcount", negative_refcount, METH_NOARGS},
|
||||
#endif
|
||||
{"write_unraisable_exc", test_write_unraisable_exc, METH_VARARGS},
|
||||
{"sequence_getitem", sequence_getitem, METH_VARARGS},
|
||||
{"sequence_setitem", sequence_setitem, METH_VARARGS},
|
||||
{"sequence_delitem", sequence_delitem, METH_VARARGS},
|
||||
|
@ -3653,8 +3433,6 @@ static PyMethodDef TestMethods[] = {
|
|||
{"test_refcount_funcs", test_refcount_funcs, METH_NOARGS},
|
||||
{"test_py_is_macros", test_py_is_macros, METH_NOARGS},
|
||||
{"test_py_is_funcs", test_py_is_funcs, METH_NOARGS},
|
||||
{"fatal_error", test_fatal_error, METH_VARARGS,
|
||||
PyDoc_STR("fatal_error(message, release_gil=False): call Py_FatalError(message)")},
|
||||
{"type_get_version", type_get_version, METH_O, PyDoc_STR("type->tp_version_tag")},
|
||||
{"test_tstate_capi", test_tstate_capi, METH_NOARGS, NULL},
|
||||
{"frame_getlocals", frame_getlocals, METH_O, NULL},
|
||||
|
@ -3680,8 +3458,6 @@ static PyMethodDef TestMethods[] = {
|
|||
{"function_set_defaults", function_set_defaults, METH_VARARGS, NULL},
|
||||
{"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL},
|
||||
{"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL},
|
||||
{"err_set_raised", err_set_raised, METH_O, NULL},
|
||||
{"err_restore", err_restore, METH_VARARGS, NULL},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
@ -3902,61 +3678,6 @@ static PyTypeObject awaitType = {
|
|||
};
|
||||
|
||||
|
||||
static int recurse_infinitely_error_init(PyObject *, PyObject *, PyObject *);
|
||||
|
||||
static PyTypeObject PyRecursingInfinitelyError_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"RecursingInfinitelyError", /* tp_name */
|
||||
sizeof(PyBaseExceptionObject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
0, /* tp_dealloc */
|
||||
0, /* tp_vectorcall_offset */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_as_async */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
PyDoc_STR("Instantiating this exception starts infinite recursion."), /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)recurse_infinitely_error_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
0, /* tp_new */
|
||||
};
|
||||
|
||||
static int
|
||||
recurse_infinitely_error_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *type = (PyObject *)&PyRecursingInfinitelyError_Type;
|
||||
|
||||
/* Instantiating this exception starts infinite recursion. */
|
||||
Py_INCREF(type);
|
||||
PyErr_SetObject(type, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Test bpo-35983: create a subclass of "list" which checks that instances
|
||||
* are not deallocated twice */
|
||||
|
||||
|
@ -4283,14 +4004,6 @@ PyInit__testcapi(void)
|
|||
Py_INCREF(&MethStatic_Type);
|
||||
PyModule_AddObject(m, "MethStatic", (PyObject *)&MethStatic_Type);
|
||||
|
||||
PyRecursingInfinitelyError_Type.tp_base = (PyTypeObject *)PyExc_Exception;
|
||||
if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(&PyRecursingInfinitelyError_Type);
|
||||
PyModule_AddObject(m, "RecursingInfinitelyError",
|
||||
(PyObject *)&PyRecursingInfinitelyError_Type);
|
||||
|
||||
PyModule_AddObject(m, "CHAR_MAX", PyLong_FromLong(CHAR_MAX));
|
||||
PyModule_AddObject(m, "CHAR_MIN", PyLong_FromLong(CHAR_MIN));
|
||||
PyModule_AddObject(m, "UCHAR_MAX", PyLong_FromLong(UCHAR_MAX));
|
||||
|
@ -4368,6 +4081,9 @@ PyInit__testcapi(void)
|
|||
if (_PyTestCapi_Init_Structmember(m) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (_PyTestCapi_Init_Exceptions(m) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef LIMITED_API_AVAILABLE
|
||||
PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False);
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
<ClCompile Include="..\Modules\_testcapi\float.c" />
|
||||
<ClCompile Include="..\Modules\_testcapi\long.c" />
|
||||
<ClCompile Include="..\Modules\_testcapi\structmember.c" />
|
||||
<ClCompile Include="..\Modules\_testcapi\exceptions.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\PC\python_nt.rc" />
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
<ClCompile Include="..\Modules\_testcapi\structmember.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Modules\_testcapi\exceptions.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\PC\python_nt.rc">
|
||||
|
|
Loading…
Reference in New Issue