]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-32381: Add _PyRun_AnyFileObject() (GH-23723)
authorVictor Stinner <vstinner@python.org>
Wed, 9 Dec 2020 21:37:27 +0000 (22:37 +0100)
committerGitHub <noreply@github.com>
Wed, 9 Dec 2020 21:37:27 +0000 (22:37 +0100)
pymain_run_file() no longer encodes the filename: pass the filename
as an object to the new _PyRun_AnyFileObject() function.

Add new private functions:

* _PyRun_AnyFileObject()
* _PyRun_InteractiveLoopObject()
* _Py_FdIsInteractive()

Include/cpython/pylifecycle.h
Include/cpython/pythonrun.h
Modules/main.c
Python/pylifecycle.c
Python/pythonrun.c

index f38ec5a4ae3990ae180e8560a75ea866ca15120a..b4e2c8a8427c8a182a2cbc84988a1824da5db318 100644 (file)
@@ -44,6 +44,7 @@ PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(PyObject *), PyObject *);
 PyAPI_FUNC(void) _Py_RestoreSignals(void);
 
 PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
+PyAPI_FUNC(int) _Py_FdIsInteractive(FILE *fp, PyObject *filename);
 
 PyAPI_FUNC(void) _Py_SetProgramFullPath(const wchar_t *);
 
index febda73f3ec6c0fda3f25088460d3b57129bff7f..e396a674bc468412e1f02f861f1c43fc06a2449c 100644 (file)
@@ -13,6 +13,11 @@ PyAPI_FUNC(int) PyRun_AnyFileExFlags(
     const char *filename,       /* decoded from the filesystem encoding */
     int closeit,
     PyCompilerFlags *flags);
+PyAPI_FUNC(int) _PyRun_AnyFileObject(
+    FILE *fp,
+    PyObject *filename,
+    int closeit,
+    PyCompilerFlags *flags);
 PyAPI_FUNC(int) PyRun_SimpleFileExFlags(
     FILE *fp,
     const char *filename,       /* decoded from the filesystem encoding */
@@ -30,6 +35,10 @@ PyAPI_FUNC(int) PyRun_InteractiveLoopFlags(
     FILE *fp,
     const char *filename,       /* decoded from the filesystem encoding */
     PyCompilerFlags *flags);
+PyAPI_FUNC(int) _PyRun_InteractiveLoopObject(
+    FILE *fp,
+    PyObject *filename,
+    PyCompilerFlags *flags);
 
 
 PyAPI_FUNC(PyObject *) PyRun_StringFlags(const char *, int, PyObject *,
index 3aa4d91c9a3cdca1d7c50f9be9415fae48c29375..7ffcb07a7fd4b6c435ca3a274766bf839e8d6420 100644 (file)
@@ -313,17 +313,8 @@ pymain_run_file(const PyConfig *config, PyCompilerFlags *cf)
     }
     FILE *fp = _Py_wfopen(filename, L"rb");
     if (fp == NULL) {
-        char *cfilename_buffer;
-        const char *cfilename;
-        int err = errno;
-        cfilename_buffer = _Py_EncodeLocaleRaw(filename, NULL);
-        if (cfilename_buffer != NULL)
-            cfilename = cfilename_buffer;
-        else
-            cfilename = "<unprintable file name>";
-        fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n",
-                config->program_name, cfilename, err, strerror(err));
-        PyMem_RawFree(cfilename_buffer);
+        fprintf(stderr, "%ls: can't open file '%ls': [Errno %d] %s\n",
+                config->program_name, filename, errno, strerror(errno));
         return 2;
     }
 
@@ -353,25 +344,15 @@ pymain_run_file(const PyConfig *config, PyCompilerFlags *cf)
         return pymain_exit_err_print();
     }
 
-    PyObject *unicode, *bytes = NULL;
-    const char *filename_str;
-
-    unicode = PyUnicode_FromWideChar(filename, wcslen(filename));
-    if (unicode != NULL) {
-        bytes = PyUnicode_EncodeFSDefault(unicode);
-        Py_DECREF(unicode);
-    }
-    if (bytes != NULL) {
-        filename_str = PyBytes_AsString(bytes);
-    }
-    else {
-        PyErr_Clear();
-        filename_str = "<filename encoding error>";
+    PyObject *filename_obj = PyUnicode_FromWideChar(filename, -1);
+    if (filename_obj == NULL) {
+        PyErr_Print();
+        return -1;
     }
 
     /* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */
-    int run = PyRun_AnyFileExFlags(fp, filename_str, 1, cf);
-    Py_XDECREF(bytes);
+    int run = _PyRun_AnyFileObject(fp, filename_obj, 1, cf);
+    Py_XDECREF(filename_obj);
     return (run != 0);
 }
 
index 70824ff674129a1f429d4676e68025aaea449ee8..6a705b4d2b4b9e38024f77ca195962e5d5dc52ab 100644 (file)
@@ -2739,6 +2739,21 @@ Py_FdIsInteractive(FILE *fp, const char *filename)
 }
 
 
+int
+_Py_FdIsInteractive(FILE *fp, PyObject *filename)
+{
+    if (isatty((int)fileno(fp))) {
+        return 1;
+    }
+    if (!Py_InteractiveFlag) {
+        return 0;
+    }
+    return (filename == NULL) ||
+           (PyUnicode_CompareWithASCIIString(filename, "<stdin>") == 0) ||
+           (PyUnicode_CompareWithASCIIString(filename, "???") == 0);
+}
+
+
 /* Wrappers around sigaction() or signal(). */
 
 PyOS_sighandler_t
index 15e407d9195c0c4e450e5a8f5e9c6ac2c8941662..dacf1a647106fb822531b6bdcc5d58cf881e4c5e 100644 (file)
@@ -67,44 +67,69 @@ static PyObject* pyrun_file(FILE *fp, PyObject *filename, int start,
                             PyCompilerFlags *flags);
 
 
-/* Parse input from a file and execute it */
 int
-PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
+_PyRun_AnyFileObject(FILE *fp, PyObject *filename, int closeit,
                      PyCompilerFlags *flags)
 {
-    if (filename == NULL)
-        filename = "???";
-    if (Py_FdIsInteractive(fp, filename)) {
-        int err = PyRun_InteractiveLoopFlags(fp, filename, flags);
-        if (closeit)
+    int decref_filename = 0;
+    if (filename == NULL) {
+        filename = PyUnicode_FromString("???");
+        if (filename == NULL) {
+            PyErr_Print();
+            return -1;
+        }
+        decref_filename = 1;
+    }
+
+    int res;
+    if (_Py_FdIsInteractive(fp, filename)) {
+        res = _PyRun_InteractiveLoopObject(fp, filename, flags);
+        if (closeit) {
             fclose(fp);
-        return err;
+        }
+    }
+    else {
+        res = _PyRun_SimpleFileObject(fp, filename, closeit, flags);
+    }
+
+    if (decref_filename) {
+        Py_DECREF(filename);
     }
-    else
-        return PyRun_SimpleFileExFlags(fp, filename, closeit, flags);
+    return res;
 }
 
+
+/* Parse input from a file and execute it */
 int
-PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags)
+PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
+                     PyCompilerFlags *flags)
 {
-    PyObject *filename, *v;
-    int ret, err;
-    PyCompilerFlags local_flags = _PyCompilerFlags_INIT;
-    int nomem_count = 0;
-#ifdef Py_REF_DEBUG
-    int show_ref_count = _Py_GetConfig()->show_ref_count;
-#endif
-
-    filename = PyUnicode_DecodeFSDefault(filename_str);
-    if (filename == NULL) {
-        PyErr_Print();
-        return -1;
+    PyObject *filename_obj;
+    if (filename != NULL) {
+        filename_obj = PyUnicode_DecodeFSDefault(filename);
+        if (filename_obj == NULL) {
+            PyErr_Print();
+            return -1;
+        }
     }
+    else {
+        filename_obj = NULL;
+    }
+    int res = _PyRun_AnyFileObject(fp, filename_obj, closeit, flags);
+    Py_XDECREF(filename_obj);
+    return res;
+}
 
+
+int
+_PyRun_InteractiveLoopObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
+{
+    PyCompilerFlags local_flags = _PyCompilerFlags_INIT;
     if (flags == NULL) {
         flags = &local_flags;
     }
-    v = _PySys_GetObjectId(&PyId_ps1);
+
+    PyObject *v = _PySys_GetObjectId(&PyId_ps1);
     if (v == NULL) {
         _PySys_SetObjectId(&PyId_ps1, v = PyUnicode_FromString(">>> "));
         Py_XDECREF(v);
@@ -114,7 +139,13 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
         _PySys_SetObjectId(&PyId_ps2, v = PyUnicode_FromString("... "));
         Py_XDECREF(v);
     }
-    err = 0;
+
+#ifdef Py_REF_DEBUG
+    int show_ref_count = _Py_GetConfig()->show_ref_count;
+#endif
+    int err = 0;
+    int ret;
+    int nomem_count = 0;
     do {
         ret = PyRun_InteractiveOneObjectEx(fp, filename, flags);
         if (ret == -1 && PyErr_Occurred()) {
@@ -141,10 +172,26 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
         }
 #endif
     } while (ret != E_EOF);
-    Py_DECREF(filename);
     return err;
 }
 
+
+int
+PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
+{
+    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);
+    if (filename_obj == NULL) {
+        PyErr_Print();
+        return -1;
+    }
+
+    int err = _PyRun_InteractiveLoopObject(fp, filename_obj, flags);
+    Py_DECREF(filename_obj);
+    return err;
+
+}
+
+
 /* A PyRun_InteractiveOneObject() auxiliary function that does not print the
  * error on failure. */
 static int