summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/Setup.stdlib.in2
-rw-r--r--Modules/_testcapi/parts.h1
-rw-r--r--Modules/_testcapi/run.c112
-rw-r--r--Modules/_testcapimodule.c13
4 files changed, 127 insertions, 1 deletions
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index 26720ef..0b0c1ee 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -162,7 +162,7 @@
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
-@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c
+@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h
index 2336cc0..0e24e44 100644
--- a/Modules/_testcapi/parts.h
+++ b/Modules/_testcapi/parts.h
@@ -51,6 +51,7 @@ int _PyTestCapi_Init_Exceptions(PyObject *module);
int _PyTestCapi_Init_Code(PyObject *module);
int _PyTestCapi_Init_Buffer(PyObject *module);
int _PyTestCapi_Init_PyAtomic(PyObject *module);
+int _PyTestCapi_Init_Run(PyObject *module);
int _PyTestCapi_Init_File(PyObject *module);
int _PyTestCapi_Init_Codec(PyObject *module);
int _PyTestCapi_Init_Immortal(PyObject *module);
diff --git a/Modules/_testcapi/run.c b/Modules/_testcapi/run.c
new file mode 100644
index 0000000..fa3251c
--- /dev/null
+++ b/Modules/_testcapi/run.c
@@ -0,0 +1,112 @@
+#include "parts.h"
+#include "util.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+
+static PyObject *
+run_stringflags(PyObject *mod, PyObject *pos_args)
+{
+ const char *str;
+ Py_ssize_t size;
+ int start;
+ PyObject *globals = NULL;
+ PyObject *locals = NULL;
+ PyCompilerFlags flags = _PyCompilerFlags_INIT;
+ PyCompilerFlags *pflags = NULL;
+ int cf_flags = 0;
+ int cf_feature_version = 0;
+
+ if (!PyArg_ParseTuple(pos_args, "z#iO|Oii",
+ &str, &size, &start, &globals, &locals,
+ &cf_flags, &cf_feature_version)) {
+ return NULL;
+ }
+
+ NULLABLE(globals);
+ NULLABLE(locals);
+ if (cf_flags || cf_feature_version) {
+ flags.cf_flags = cf_flags;
+ flags.cf_feature_version = cf_feature_version;
+ pflags = &flags;
+ }
+
+ return PyRun_StringFlags(str, start, globals, locals, pflags);
+}
+
+static PyObject *
+run_fileexflags(PyObject *mod, PyObject *pos_args)
+{
+ PyObject *result = NULL;
+ const char *filename = NULL;
+ Py_ssize_t filename_size;
+ int start;
+ PyObject *globals = NULL;
+ PyObject *locals = NULL;
+ int closeit = 0;
+ PyCompilerFlags flags = _PyCompilerFlags_INIT;
+ PyCompilerFlags *pflags = NULL;
+ int cf_flags = 0;
+ int cf_feature_version = 0;
+
+ FILE *fp = NULL;
+
+ if (!PyArg_ParseTuple(pos_args, "z#iO|Oiii",
+ &filename, &filename_size, &start, &globals, &locals,
+ &closeit, &cf_flags, &cf_feature_version)) {
+ return NULL;
+ }
+
+ NULLABLE(globals);
+ NULLABLE(locals);
+ if (cf_flags || cf_feature_version) {
+ flags.cf_flags = cf_flags;
+ flags.cf_feature_version = cf_feature_version;
+ pflags = &flags;
+ }
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
+ return NULL;
+ }
+
+ result = PyRun_FileExFlags(fp, filename, start, globals, locals, closeit, pflags);
+
+#if !defined(__wasi__)
+ /* The behavior of fileno() after fclose() is undefined. */
+ if (closeit && result && fileno(fp) >= 0) {
+ PyErr_SetString(PyExc_AssertionError, "File was not closed after excution");
+ Py_DECREF(result);
+ fclose(fp);
+ return NULL;
+ }
+#endif
+ if (!closeit && fileno(fp) < 0) {
+ PyErr_SetString(PyExc_AssertionError, "Bad file descriptor after excution");
+ Py_XDECREF(result);
+ return NULL;
+ }
+
+ if (!closeit) {
+ fclose(fp); /* don't need open file any more*/
+ }
+
+ return result;
+}
+
+static PyMethodDef test_methods[] = {
+ {"run_stringflags", run_stringflags, METH_VARARGS},
+ {"run_fileexflags", run_fileexflags, METH_VARARGS},
+ {NULL},
+};
+
+int
+_PyTestCapi_Init_Run(PyObject *mod)
+{
+ if (PyModule_AddFunctions(mod, test_methods) < 0) {
+ return -1;
+ }
+ return 0;
+}
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index eff61dd..034a30fa 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3904,6 +3904,16 @@ PyInit__testcapi(void)
PyModule_AddIntConstant(m, "the_number_three", 3);
PyModule_AddIntMacro(m, Py_C_RECURSION_LIMIT);
+ if (PyModule_AddIntMacro(m, Py_single_input)) {
+ return NULL;
+ }
+ if (PyModule_AddIntMacro(m, Py_file_input)) {
+ return NULL;
+ }
+ if (PyModule_AddIntMacro(m, Py_eval_input)) {
+ return NULL;
+ }
+
testcapistate_t *state = get_testcapi_state(m);
state->error = PyErr_NewException("_testcapi.error", NULL, NULL);
PyModule_AddObject(m, "error", state->error);
@@ -3998,6 +4008,9 @@ PyInit__testcapi(void)
if (_PyTestCapi_Init_PyAtomic(m) < 0) {
return NULL;
}
+ if (_PyTestCapi_Init_Run(m) < 0) {
+ return NULL;
+ }
if (_PyTestCapi_Init_Hash(m) < 0) {
return NULL;
}