[Python-checkins] gh-105922: Refactor PyRun_InteractiveOneObjectEx() (#105925)

vstinner webhook-mailer at python.org
Mon Jun 19 18:55:26 EDT 2023


https://github.com/python/cpython/commit/a5c2ad0c3d23d2b1e61ab8e0d7ee64f7e1288547
commit: a5c2ad0c3d23d2b1e61ab8e0d7ee64f7e1288547
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2023-06-20T00:55:23+02:00
summary:

gh-105922: Refactor PyRun_InteractiveOneObjectEx() (#105925)

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.

files:
M Python/pythonrun.c

diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 05e7b4370869..f9e798ebcd65 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -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;
 }
@@ -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;
@@ -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 */
@@ -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;
 }
 
@@ -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;
 }
 



More information about the Python-checkins mailing list