• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define PYTESTCAPI_NEED_INTERNAL_API
2 #include "parts.h"
3 #include "util.h"
4 #include "pycore_fileutils.h"     // _Py_IsValidFD()
5 
6 #include <stdio.h>
7 #include <errno.h>
8 
9 
10 static PyObject *
run_stringflags(PyObject * mod,PyObject * pos_args)11 run_stringflags(PyObject *mod, PyObject *pos_args)
12 {
13     const char *str;
14     Py_ssize_t size;
15     int start;
16     PyObject *globals = NULL;
17     PyObject *locals = NULL;
18     PyCompilerFlags flags = _PyCompilerFlags_INIT;
19     PyCompilerFlags *pflags = NULL;
20     int cf_flags = 0;
21     int cf_feature_version = 0;
22 
23     if (!PyArg_ParseTuple(pos_args, "z#iO|Oii",
24                           &str, &size, &start, &globals, &locals,
25                           &cf_flags, &cf_feature_version)) {
26         return NULL;
27     }
28 
29     NULLABLE(globals);
30     NULLABLE(locals);
31     if (cf_flags || cf_feature_version) {
32         flags.cf_flags = cf_flags;
33         flags.cf_feature_version = cf_feature_version;
34         pflags = &flags;
35     }
36 
37     return PyRun_StringFlags(str, start, globals, locals, pflags);
38 }
39 
40 static PyObject *
run_fileexflags(PyObject * mod,PyObject * pos_args)41 run_fileexflags(PyObject *mod, PyObject *pos_args)
42 {
43     PyObject *result = NULL;
44     const char *filename = NULL;
45     Py_ssize_t filename_size;
46     int start;
47     PyObject *globals = NULL;
48     PyObject *locals = NULL;
49     int closeit = 0;
50     PyCompilerFlags flags = _PyCompilerFlags_INIT;
51     PyCompilerFlags *pflags = NULL;
52     int cf_flags = 0;
53     int cf_feature_version = 0;
54 
55     FILE *fp = NULL;
56 
57     if (!PyArg_ParseTuple(pos_args, "z#iO|Oiii",
58                           &filename, &filename_size, &start, &globals, &locals,
59                           &closeit, &cf_flags, &cf_feature_version)) {
60         return NULL;
61     }
62 
63     NULLABLE(globals);
64     NULLABLE(locals);
65     if (cf_flags || cf_feature_version) {
66         flags.cf_flags = cf_flags;
67         flags.cf_feature_version = cf_feature_version;
68         pflags = &flags;
69     }
70 
71     fp = fopen(filename, "r");
72     if (fp == NULL) {
73         PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
74         return NULL;
75     }
76     int fd = fileno(fp);
77 
78     result = PyRun_FileExFlags(fp, filename, start, globals, locals, closeit, pflags);
79 
80     if (closeit && result && _Py_IsValidFD(fd)) {
81         PyErr_SetString(PyExc_AssertionError, "File was not closed after excution");
82         Py_DECREF(result);
83         fclose(fp);
84         return NULL;
85     }
86 
87     if (!closeit && !_Py_IsValidFD(fd)) {
88         PyErr_SetString(PyExc_AssertionError, "Bad file descriptor after excution");
89         Py_XDECREF(result);
90         return NULL;
91     }
92 
93     if (!closeit) {
94         fclose(fp); /* don't need open file any more*/
95     }
96 
97     return result;
98 }
99 
100 static PyMethodDef test_methods[] = {
101     {"run_stringflags", run_stringflags, METH_VARARGS},
102     {"run_fileexflags", run_fileexflags, METH_VARARGS},
103     {NULL},
104 };
105 
106 int
_PyTestCapi_Init_Run(PyObject * mod)107 _PyTestCapi_Init_Run(PyObject *mod)
108 {
109     if (PyModule_AddFunctions(mod, test_methods) < 0) {
110         return -1;
111     }
112     return 0;
113 }
114