This commit is contained in:
mdehoon 2026-05-04 09:10:48 +12:00 committed by GitHub
commit e1d58b5282
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 81 additions and 8 deletions

View file

@ -0,0 +1,55 @@
# test_tkinter_pipe.py
import unittest
import subprocess
import sys
from test import support
@unittest.skipUnless(support.has_subprocess_support, "test requires subprocess")
class TkinterPipeTest(unittest.TestCase):
def test_tkinter_pipe_buffered(self):
args = [sys.executable, "-i"]
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write(b"import tkinter\n")
proc.stdin.write(b"interpreter = tkinter.Tcl()\n")
proc.stdin.write(b"print('hello')\n")
proc.stdin.write(b"print('goodbye')\n")
proc.stdin.write(b"quit()\n")
stdout, stderr = proc.communicate()
stdout = stdout.decode()
self.assertEqual(stdout.split(), ['hello', 'goodbye'])
def test_tkinter_pipe_unbuffered(self):
args = [sys.executable, "-i", "-u"]
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write(b"import tkinter\n")
proc.stdin.write(b"interpreter = tkinter.Tcl()\n")
proc.stdin.write(b"print('hello')\n")
proc.stdin.flush()
stdout = proc.stdout.readline()
stdout = stdout.decode()
self.assertEqual(stdout.strip(), 'hello')
proc.stdin.write(b"print('hello again')\n")
proc.stdin.flush()
stdout = proc.stdout.readline()
stdout = stdout.decode()
self.assertEqual(stdout.strip(), 'hello again')
proc.stdin.write(b"print('goodbye')\n")
proc.stdin.write(b"quit()\n")
stdout, stderr = proc.communicate()
stdout = stdout.decode()
self.assertEqual(stdout.strip(), 'goodbye')
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1,3 @@
Avoid tkinter to hang on Windows if stdin is redirected to a pipe in an
interactive session. This is helpful for testing interactive usage of
tkinter from a script, for example as part of the cpython test suite.

View file

@ -3352,10 +3352,10 @@ static PyMethodDef moduleMethods[] =
};
#ifdef WAIT_FOR_STDIN
#ifndef MS_WINDOWS
static int stdin_ready = 0;
#ifndef MS_WINDOWS
static void
MyFileProc(void *clientData, int mask)
{
@ -3368,22 +3368,37 @@ static PyThreadState *event_tstate = NULL;
static int
EventHook(void)
{
#ifndef MS_WINDOWS
#ifdef MS_WINDOWS
HANDLE hStdin;
DWORD type;
#else
int tfile;
stdin_ready = 0;
#endif
PyEval_RestoreThread(event_tstate);
stdin_ready = 0;
errorInCmd = 0;
#ifndef MS_WINDOWS
#ifdef MS_WINDOWS
hStdin = GetStdHandle(STD_INPUT_HANDLE);
type = GetFileType(hStdin);
while (!errorInCmd) {
#else
tfile = fileno(stdin);
Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
#endif
while (!errorInCmd && !stdin_ready) {
#endif
int result;
#ifdef MS_WINDOWS
if (_kbhit()) {
stdin_ready = 1;
break;
if (type == FILE_TYPE_CHAR) {
if (_kbhit()) break;
}
else if (type == FILE_TYPE_PIPE) {
DWORD available;
if (PeekNamedPipe(hStdin, NULL, 0, NULL, &available, NULL)) {
if (available > 0) break;
}
else {
if (GetLastError() == ERROR_BROKEN_PIPE) break;
}
}
#endif
Py_BEGIN_ALLOW_THREADS