Skip to content

Commit

Permalink
gh-105922: Refactor PyRun_InteractiveOneObjectEx() (#105925)
Browse files Browse the repository at this point in the history
Refactor PyRun_InteractiveOneObjectEx(), _PyRun_SimpleFileObject()
and PyRun_SimpleStringFlags():

* Keep a strong reference to the __main__ module while using its
  dictionary (PyModule_GetDict()). Use PyImport_AddModule() with
  Py_XNewRef().
* Declare variables closer to where they are defined.
* Rename variables to use name longer than 1 character.
* Add pyrun_one_parse_ast() sub-function.
  • Loading branch information
vstinner authored Jun 19, 2023
1 parent 33f0a85 commit a5c2ad0
Showing 1 changed file with 108 additions and 74 deletions.
182 changes: 108 additions & 74 deletions Python/pythonrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,90 +179,118 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flag
}


/* A PyRun_InteractiveOneObject() auxiliary function that does not print the
* error on failure. */
// Call _PyParser_ASTFromFile() with sys.stdin.encoding, sys.ps1 and sys.ps2
static int
PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,
PyCompilerFlags *flags)
pyrun_one_parse_ast(FILE *fp, PyObject *filename,
PyCompilerFlags *flags, PyArena *arena, mod_ty *pmod)
{
PyObject *m, *d, *v, *w, *oenc = NULL;
mod_ty mod;
PyArena *arena;
const char *ps1 = "", *ps2 = "", *enc = NULL;
int errcode = 0;
PyThreadState *tstate = _PyThreadState_GET();

// Get sys.stdin.encoding (as UTF-8)
PyObject *attr; // borrowed ref
PyObject *encoding_obj = NULL;
const char *encoding = NULL;
if (fp == stdin) {
/* Fetch encoding from sys.stdin if possible. */
v = _PySys_GetAttr(tstate, &_Py_ID(stdin));
if (v && v != Py_None) {
oenc = PyObject_GetAttr(v, &_Py_ID(encoding));
if (oenc)
enc = PyUnicode_AsUTF8(oenc);
if (!enc)
PyErr_Clear();
attr = _PySys_GetAttr(tstate, &_Py_ID(stdin));
if (attr && attr != Py_None) {
encoding_obj = PyObject_GetAttr(attr, &_Py_ID(encoding));
if (encoding_obj) {
encoding = PyUnicode_AsUTF8(encoding_obj);
if (!encoding) {
PyErr_Clear();
}
}
}
}
v = _PySys_GetAttr(tstate, &_Py_ID(ps1));
if (v != NULL) {
v = PyObject_Str(v);
if (v == NULL)

// Get sys.ps1 (as UTF-8)
attr = _PySys_GetAttr(tstate, &_Py_ID(ps1));
PyObject *ps1_obj = NULL;
const char *ps1 = "";
if (attr != NULL) {
ps1_obj = PyObject_Str(attr);
if (ps1_obj == NULL) {
PyErr_Clear();
else if (PyUnicode_Check(v)) {
ps1 = PyUnicode_AsUTF8(v);
}
else if (PyUnicode_Check(ps1_obj)) {
ps1 = PyUnicode_AsUTF8(ps1_obj);
if (ps1 == NULL) {
PyErr_Clear();
ps1 = "";
}
}
}
w = _PySys_GetAttr(tstate, &_Py_ID(ps2));
if (w != NULL) {
w = PyObject_Str(w);
if (w == NULL)

// Get sys.ps2 (as UTF-8)
attr = _PySys_GetAttr(tstate, &_Py_ID(ps2));
PyObject *ps2_obj = NULL;
const char *ps2 = "";
if (attr != NULL) {
ps2_obj = PyObject_Str(attr);
if (ps2_obj == NULL) {
PyErr_Clear();
else if (PyUnicode_Check(w)) {
ps2 = PyUnicode_AsUTF8(w);
}
else if (PyUnicode_Check(ps2_obj)) {
ps2 = PyUnicode_AsUTF8(ps2_obj);
if (ps2 == NULL) {
PyErr_Clear();
ps2 = "";
}
}
}
arena = _PyArena_New();
if (arena == NULL) {
Py_XDECREF(v);
Py_XDECREF(w);
Py_XDECREF(oenc);
return -1;
}

mod = _PyParser_ASTFromFile(fp, filename, enc, Py_single_input,
ps1, ps2, flags, &errcode, arena);

Py_XDECREF(v);
Py_XDECREF(w);
Py_XDECREF(oenc);
if (mod == NULL) {
_PyArena_Free(arena);
int errcode = 0;
*pmod = _PyParser_ASTFromFile(fp, filename, encoding,
Py_single_input, ps1, ps2,
flags, &errcode, arena);
Py_XDECREF(ps1_obj);
Py_XDECREF(ps2_obj);
Py_XDECREF(encoding_obj);

if (*pmod == NULL) {
if (errcode == E_EOF) {
PyErr_Clear();
return E_EOF;
}
return -1;
}
m = PyImport_AddModuleObject(&_Py_ID(__main__));
if (m == NULL) {
return 0;
}


/* A PyRun_InteractiveOneObject() auxiliary function that does not print the
* error on failure. */
static int
PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,
PyCompilerFlags *flags)
{
PyArena *arena = _PyArena_New();
if (arena == NULL) {
return -1;
}

mod_ty mod;
int parse_res = pyrun_one_parse_ast(fp, filename, flags, arena, &mod);
if (parse_res != 0) {
_PyArena_Free(arena);
return parse_res;
}

PyObject *main_module = Py_XNewRef(PyImport_AddModuleObject(&_Py_ID(__main__)));
if (main_module == NULL) {
_PyArena_Free(arena);
return -1;
}
d = PyModule_GetDict(m);
v = run_mod(mod, filename, d, d, flags, arena);
PyObject *main_dict = PyModule_GetDict(main_module); // borrowed ref

PyObject *res = run_mod(mod, filename, main_dict, main_dict, flags, arena);
_PyArena_Free(arena);
if (v == NULL) {
Py_DECREF(main_module);
if (res == NULL) {
return -1;
}
Py_DECREF(v);
Py_DECREF(res);

flush_io();
return 0;
}
Expand Down Expand Up @@ -376,22 +404,22 @@ int
_PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit,
PyCompilerFlags *flags)
{
PyObject *m, *d, *v;
int set_file_name = 0, ret = -1;
int ret = -1;

m = PyImport_AddModule("__main__");
if (m == NULL)
PyObject *main_module = Py_XNewRef(PyImport_AddModule("__main__"));
if (main_module == NULL)
return -1;
Py_INCREF(m);
d = PyModule_GetDict(m);
if (_PyDict_GetItemStringWithError(d, "__file__") == NULL) {
PyObject *dict = PyModule_GetDict(main_module); // borrowed ref

int set_file_name = 0;
if (_PyDict_GetItemStringWithError(dict, "__file__") == NULL) {
if (PyErr_Occurred()) {
goto done;
}
if (PyDict_SetItemString(d, "__file__", filename) < 0) {
if (PyDict_SetItemString(dict, "__file__", filename) < 0) {
goto done;
}
if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) {
if (PyDict_SetItemString(dict, "__cached__", Py_None) < 0) {
goto done;
}
set_file_name = 1;
Expand All @@ -402,6 +430,7 @@ _PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit,
goto done;
}

PyObject *v;
if (pyc) {
FILE *pyc_fp;
/* Try to run a pyc file. First, re-open in binary */
Expand All @@ -415,42 +444,43 @@ _PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit,
goto done;
}

if (set_main_loader(d, filename, "SourcelessFileLoader") < 0) {
if (set_main_loader(dict, filename, "SourcelessFileLoader") < 0) {
fprintf(stderr, "python: failed to set __main__.__loader__\n");
ret = -1;
fclose(pyc_fp);
goto done;
}
v = run_pyc_file(pyc_fp, d, d, flags);
v = run_pyc_file(pyc_fp, dict, dict, flags);
} else {
/* When running from stdin, leave __main__.__loader__ alone */
if (PyUnicode_CompareWithASCIIString(filename, "<stdin>") != 0 &&
set_main_loader(d, filename, "SourceFileLoader") < 0) {
set_main_loader(dict, filename, "SourceFileLoader") < 0) {
fprintf(stderr, "python: failed to set __main__.__loader__\n");
ret = -1;
goto done;
}
v = pyrun_file(fp, filename, Py_file_input, d, d,
v = pyrun_file(fp, filename, Py_file_input, dict, dict,
closeit, flags);
}
flush_io();
if (v == NULL) {
Py_CLEAR(m);
Py_CLEAR(main_module);
PyErr_Print();
goto done;
}
Py_DECREF(v);
ret = 0;

done:
if (set_file_name) {
if (PyDict_DelItemString(d, "__file__")) {
if (PyDict_DelItemString(dict, "__file__")) {
PyErr_Clear();
}
if (PyDict_DelItemString(d, "__cached__")) {
if (PyDict_DelItemString(dict, "__cached__")) {
PyErr_Clear();
}
}
Py_XDECREF(m);
Py_XDECREF(main_module);
return ret;
}

Expand All @@ -472,17 +502,21 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
int
PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)
{
PyObject *m, *d, *v;
m = PyImport_AddModule("__main__");
if (m == NULL)
PyObject *main_module = Py_XNewRef(PyImport_AddModule("__main__"));
if (main_module == NULL) {
return -1;
d = PyModule_GetDict(m);
v = PyRun_StringFlags(command, Py_file_input, d, d, flags);
if (v == NULL) {
}
PyObject *dict = PyModule_GetDict(main_module); // borrowed ref

PyObject *res = PyRun_StringFlags(command, Py_file_input,
dict, dict, flags);
Py_DECREF(main_module);
if (res == NULL) {
PyErr_Print();
return -1;
}
Py_DECREF(v);

Py_DECREF(res);
return 0;
}

Expand Down

0 comments on commit a5c2ad0

Please sign in to comment.