gh-93649: Split exception tests from _testcapimodule.c (GH-102173)

Automerge-Triggered-By: GH:erlend-aasland
This commit is contained in:
Erlend E. Aasland 2023-02-23 16:03:13 +01:00 committed by GitHub
parent e07b304bb0
commit efc985a714
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 434 additions and 416 deletions

View File

@ -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()

View File

@ -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()

View File

@ -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.

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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" />

View File

@ -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">