gh-77782: Py_FdIsInteractive() now uses PyConfig.interactive (#93916)

This commit is contained in:
Victor Stinner 2022-06-17 15:19:28 +02:00 committed by GitHub
parent c5b750dc0b
commit 1735710873
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 29 additions and 23 deletions

View File

@ -21,10 +21,12 @@ Operating System Utilities
Return true (nonzero) if the standard I/O file *fp* with name *filename* is Return true (nonzero) if the standard I/O file *fp* with name *filename* is
deemed interactive. This is the case for files for which ``isatty(fileno(fp))`` deemed interactive. This is the case for files for which ``isatty(fileno(fp))``
is true. If the global flag :c:data:`Py_InteractiveFlag` is true, this function is true. If the :c:member:`PyConfig.interactive` is non-zero, this function
also returns true if the *filename* pointer is ``NULL`` or if the name is equal to also returns true if the *filename* pointer is ``NULL`` or if the name is equal to
one of the strings ``'<stdin>'`` or ``'???'``. one of the strings ``'<stdin>'`` or ``'???'``.
This function must not be called before Python is initialized.
.. c:function:: void PyOS_BeforeFork() .. c:function:: void PyOS_BeforeFork()

View File

@ -70,16 +70,17 @@ class CAPITest(unittest.TestCase):
'import _testcapi;' 'import _testcapi;'
'_testcapi.crash_no_current_thread()'], '_testcapi.crash_no_current_thread()'],
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE) stderr=subprocess.PIPE,
text=True)
(out, err) = p.communicate() (out, err) = p.communicate()
self.assertEqual(out, b'') self.assertEqual(out, '')
# This used to cause an infinite loop. # This used to cause an infinite loop.
self.assertTrue(err.rstrip().startswith( msg = ("Fatal Python error: PyThreadState_Get: "
b'Fatal Python error: ' "the function must be called with the GIL held, "
b'PyThreadState_Get: ' "after Python initialization and before Python finalization, "
b'the function must be called with the GIL held, ' "but the GIL is released "
b'but the GIL is released ' "(the current Python thread state is NULL)")
b'(the current Python thread state is NULL)'), self.assertTrue(err.rstrip().startswith(msg),
err) err)
def test_memoryview_from_NULL_pointer(self): def test_memoryview_from_NULL_pointer(self):

View File

@ -348,8 +348,8 @@ _Py_FatalError_TstateNULL(const char *func)
{ {
_Py_FatalErrorFunc(func, _Py_FatalErrorFunc(func,
"the function must be called with the GIL held, " "the function must be called with the GIL held, "
"but the GIL is released " "after Python initialization and before Python finalization, "
"(the current Python thread state is NULL)"); "but the GIL is released (the current Python thread state is NULL)");
} }
int int

View File

@ -180,7 +180,7 @@ int Py_UTF8Mode = 0;
int Py_DebugFlag = 0; /* Needed by parser.c */ int Py_DebugFlag = 0; /* Needed by parser.c */
int Py_VerboseFlag = 0; /* Needed by import.c */ int Py_VerboseFlag = 0; /* Needed by import.c */
int Py_QuietFlag = 0; /* Needed by sysmodule.c */ int Py_QuietFlag = 0; /* Needed by sysmodule.c */
int Py_InteractiveFlag = 0; /* Needed by Py_FdIsInteractive() below */ int Py_InteractiveFlag = 0; /* Previously, was used by Py_FdIsInteractive() */
int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */ int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */
int Py_OptimizeFlag = 0; /* Needed by compile.c */ int Py_OptimizeFlag = 0; /* Needed by compile.c */
int Py_NoSiteFlag = 0; /* Suppress 'import site' */ int Py_NoSiteFlag = 0; /* Suppress 'import site' */

View File

@ -2938,28 +2938,30 @@ Py_Exit(int sts)
int int
Py_FdIsInteractive(FILE *fp, const char *filename) Py_FdIsInteractive(FILE *fp, const char *filename)
{ {
if (isatty((int)fileno(fp))) if (isatty(fileno(fp))) {
return 1; return 1;
if (!Py_InteractiveFlag) }
if (!_Py_GetConfig()->interactive) {
return 0; return 0;
return (filename == NULL) || }
(strcmp(filename, "<stdin>") == 0) || return ((filename == NULL)
(strcmp(filename, "???") == 0); || (strcmp(filename, "<stdin>") == 0)
|| (strcmp(filename, "???") == 0));
} }
int int
_Py_FdIsInteractive(FILE *fp, PyObject *filename) _Py_FdIsInteractive(FILE *fp, PyObject *filename)
{ {
if (isatty((int)fileno(fp))) { if (isatty(fileno(fp))) {
return 1; return 1;
} }
if (!Py_InteractiveFlag) { if (!_Py_GetConfig()->interactive) {
return 0; return 0;
} }
return (filename == NULL) || return ((filename == NULL)
(PyUnicode_CompareWithASCIIString(filename, "<stdin>") == 0) || || (PyUnicode_CompareWithASCIIString(filename, "<stdin>") == 0)
(PyUnicode_CompareWithASCIIString(filename, "???") == 0); || (PyUnicode_CompareWithASCIIString(filename, "???") == 0));
} }

View File

@ -2136,6 +2136,7 @@ _Py_GetConfig(void)
{ {
assert(PyGILState_Check()); assert(PyGILState_Check());
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
_Py_EnsureTstateNotNULL(tstate);
return _PyInterpreterState_GetConfig(tstate->interp); return _PyInterpreterState_GetConfig(tstate->interp);
} }