bpo-32381: Add _PyRun_AnyFileObject() (GH-23723)

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()
This commit is contained in:
Victor Stinner 2020-12-09 22:37:27 +01:00 committed by GitHub
parent ca06440207
commit a82f63f5af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 53 deletions

View File

@ -44,6 +44,7 @@ PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(PyObject *), PyObject *);
PyAPI_FUNC(void) _Py_RestoreSignals(void); PyAPI_FUNC(void) _Py_RestoreSignals(void);
PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *); 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 *); PyAPI_FUNC(void) _Py_SetProgramFullPath(const wchar_t *);

View File

@ -13,6 +13,11 @@ PyAPI_FUNC(int) PyRun_AnyFileExFlags(
const char *filename, /* decoded from the filesystem encoding */ const char *filename, /* decoded from the filesystem encoding */
int closeit, int closeit,
PyCompilerFlags *flags); PyCompilerFlags *flags);
PyAPI_FUNC(int) _PyRun_AnyFileObject(
FILE *fp,
PyObject *filename,
int closeit,
PyCompilerFlags *flags);
PyAPI_FUNC(int) PyRun_SimpleFileExFlags( PyAPI_FUNC(int) PyRun_SimpleFileExFlags(
FILE *fp, FILE *fp,
const char *filename, /* decoded from the filesystem encoding */ const char *filename, /* decoded from the filesystem encoding */
@ -30,6 +35,10 @@ PyAPI_FUNC(int) PyRun_InteractiveLoopFlags(
FILE *fp, FILE *fp,
const char *filename, /* decoded from the filesystem encoding */ const char *filename, /* decoded from the filesystem encoding */
PyCompilerFlags *flags); PyCompilerFlags *flags);
PyAPI_FUNC(int) _PyRun_InteractiveLoopObject(
FILE *fp,
PyObject *filename,
PyCompilerFlags *flags);
PyAPI_FUNC(PyObject *) PyRun_StringFlags(const char *, int, PyObject *, PyAPI_FUNC(PyObject *) PyRun_StringFlags(const char *, int, PyObject *,

View File

@ -313,17 +313,8 @@ pymain_run_file(const PyConfig *config, PyCompilerFlags *cf)
} }
FILE *fp = _Py_wfopen(filename, L"rb"); FILE *fp = _Py_wfopen(filename, L"rb");
if (fp == NULL) { if (fp == NULL) {
char *cfilename_buffer; fprintf(stderr, "%ls: can't open file '%ls': [Errno %d] %s\n",
const char *cfilename; config->program_name, filename, errno, strerror(errno));
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);
return 2; return 2;
} }
@ -353,25 +344,15 @@ pymain_run_file(const PyConfig *config, PyCompilerFlags *cf)
return pymain_exit_err_print(); return pymain_exit_err_print();
} }
PyObject *unicode, *bytes = NULL; PyObject *filename_obj = PyUnicode_FromWideChar(filename, -1);
const char *filename_str; if (filename_obj == NULL) {
PyErr_Print();
unicode = PyUnicode_FromWideChar(filename, wcslen(filename)); return -1;
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>";
} }
/* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */ /* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */
int run = PyRun_AnyFileExFlags(fp, filename_str, 1, cf); int run = _PyRun_AnyFileObject(fp, filename_obj, 1, cf);
Py_XDECREF(bytes); Py_XDECREF(filename_obj);
return (run != 0); return (run != 0);
} }

View 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(). */ /* Wrappers around sigaction() or signal(). */
PyOS_sighandler_t PyOS_sighandler_t

View File

@ -67,44 +67,69 @@ static PyObject* pyrun_file(FILE *fp, PyObject *filename, int start,
PyCompilerFlags *flags); PyCompilerFlags *flags);
int
_PyRun_AnyFileObject(FILE *fp, PyObject *filename, int closeit,
PyCompilerFlags *flags)
{
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);
}
}
else {
res = _PyRun_SimpleFileObject(fp, filename, closeit, flags);
}
if (decref_filename) {
Py_DECREF(filename);
}
return res;
}
/* Parse input from a file and execute it */ /* Parse input from a file and execute it */
int int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit, PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags) PyCompilerFlags *flags)
{ {
if (filename == NULL) PyObject *filename_obj;
filename = "???"; if (filename != NULL) {
if (Py_FdIsInteractive(fp, filename)) { filename_obj = PyUnicode_DecodeFSDefault(filename);
int err = PyRun_InteractiveLoopFlags(fp, filename, flags); if (filename_obj == NULL) {
if (closeit)
fclose(fp);
return err;
}
else
return PyRun_SimpleFileExFlags(fp, filename, closeit, flags);
}
int
PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, 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(); PyErr_Print();
return -1; 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) { if (flags == NULL) {
flags = &local_flags; flags = &local_flags;
} }
v = _PySys_GetObjectId(&PyId_ps1);
PyObject *v = _PySys_GetObjectId(&PyId_ps1);
if (v == NULL) { if (v == NULL) {
_PySys_SetObjectId(&PyId_ps1, v = PyUnicode_FromString(">>> ")); _PySys_SetObjectId(&PyId_ps1, v = PyUnicode_FromString(">>> "));
Py_XDECREF(v); Py_XDECREF(v);
@ -114,7 +139,13 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
_PySys_SetObjectId(&PyId_ps2, v = PyUnicode_FromString("... ")); _PySys_SetObjectId(&PyId_ps2, v = PyUnicode_FromString("... "));
Py_XDECREF(v); 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 { do {
ret = PyRun_InteractiveOneObjectEx(fp, filename, flags); ret = PyRun_InteractiveOneObjectEx(fp, filename, flags);
if (ret == -1 && PyErr_Occurred()) { if (ret == -1 && PyErr_Occurred()) {
@ -141,10 +172,26 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
} }
#endif #endif
} while (ret != E_EOF); } while (ret != E_EOF);
Py_DECREF(filename);
return err; 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 /* A PyRun_InteractiveOneObject() auxiliary function that does not print the
* error on failure. */ * error on failure. */
static int static int