summaryrefslogtreecommitdiffstats
path: root/Demo/tkinter/guido/shell_window.py
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2010-11-26 08:59:40 (GMT)
committerGeorg Brandl <georg@python.org>2010-11-26 08:59:40 (GMT)
commitf55aa80b372268902d27ad8ae3a45e465c6b9b19 (patch)
treec8dd7533c37a9d1e49350aadf5aa32c6672102bb /Demo/tkinter/guido/shell_window.py
parentd62ecbf0bae673af61fb87d8932cdb1ea80e8922 (diff)
downloadcpython-f55aa80b372268902d27ad8ae3a45e465c6b9b19.zip
cpython-f55aa80b372268902d27ad8ae3a45e465c6b9b19.tar.gz
cpython-f55aa80b372268902d27ad8ae3a45e465c6b9b19.tar.bz2
Merged revisions 85820,85823,85825,85840,85843-85845,85849-85851,85855,85867,85875,85907-85908,85911,85914 via svnmerge from
svn+ssh://svn.python.org/python/branches/py3k ........ r85820 | georg.brandl | 2010-10-24 16:20:22 +0200 (So, 24 Okt 2010) | 1 line Remove usage of exception indexing. ........ r85823 | georg.brandl | 2010-10-24 16:32:45 +0200 (So, 24 Okt 2010) | 1 line Fix style. ........ r85825 | georg.brandl | 2010-10-24 17:16:02 +0200 (So, 24 Okt 2010) | 1 line Add documentation about the default warnings filters. ........ r85840 | georg.brandl | 2010-10-25 19:50:20 +0200 (Mo, 25 Okt 2010) | 1 line #3018: tkinter demo fixes for py3k. ........ r85843 | georg.brandl | 2010-10-26 08:59:23 +0200 (Di, 26 Okt 2010) | 1 line Markup fix. ........ r85844 | georg.brandl | 2010-10-26 12:39:14 +0200 (Di, 26 Okt 2010) | 1 line Work a bit more on tkinter demos. ........ r85845 | georg.brandl | 2010-10-26 12:42:16 +0200 (Di, 26 Okt 2010) | 1 line faqwiz is removed. ........ r85849 | georg.brandl | 2010-10-26 21:31:06 +0200 (Di, 26 Okt 2010) | 1 line #10200: typo. ........ r85850 | georg.brandl | 2010-10-26 21:58:11 +0200 (Di, 26 Okt 2010) | 1 line #10200: typo. ........ r85851 | georg.brandl | 2010-10-26 22:12:37 +0200 (Di, 26 Okt 2010) | 1 line Fix import. ........ r85855 | georg.brandl | 2010-10-27 09:21:54 +0200 (Mi, 27 Okt 2010) | 1 line Encoding fix. ........ r85867 | georg.brandl | 2010-10-27 22:01:51 +0200 (Mi, 27 Okt 2010) | 1 line Add David. ........ r85875 | georg.brandl | 2010-10-28 10:38:30 +0200 (Do, 28 Okt 2010) | 1 line Fix bytes/str issues in get-remote-certificate.py. ........ r85907 | georg.brandl | 2010-10-29 06:54:13 +0200 (Fr, 29 Okt 2010) | 1 line #10222: fix for overzealous AIX compiler. ........ r85908 | georg.brandl | 2010-10-29 07:22:17 +0200 (Fr, 29 Okt 2010) | 1 line send_bytes obviously needs bytes... ........ r85911 | georg.brandl | 2010-10-29 07:36:28 +0200 (Fr, 29 Okt 2010) | 1 line Fix markup error and update false positive entries from "make suspicious". ........ r85914 | georg.brandl | 2010-10-29 08:17:38 +0200 (Fr, 29 Okt 2010) | 1 line (?:...) is a non-capturing, but still grouping construct. ........
Diffstat (limited to 'Demo/tkinter/guido/shell_window.py')
-rw-r--r--Demo/tkinter/guido/shell_window.py146
1 files changed, 146 insertions, 0 deletions
diff --git a/Demo/tkinter/guido/shell_window.py b/Demo/tkinter/guido/shell_window.py
new file mode 100644
index 0000000..c5a0401
--- /dev/null
+++ b/Demo/tkinter/guido/shell_window.py
@@ -0,0 +1,146 @@
+import os
+import sys
+from tkinter import *
+from tkinter.scrolledtext import ScrolledText
+from tkinter.dialog import Dialog
+import signal
+
+BUFSIZE = 512
+
+class ShellWindow(ScrolledText):
+
+ def __init__(self, master=None, shell=None, **cnf):
+ if not shell:
+ try:
+ shell = os.environ['SHELL']
+ except KeyError:
+ shell = '/bin/sh'
+ shell = shell + ' -i'
+ args = shell.split()
+ shell = args[0]
+
+ ScrolledText.__init__(self, master, **cnf)
+ self.pos = '1.0'
+ self.bind('<Return>', self.inputhandler)
+ self.bind('<Control-c>', self.sigint)
+ self.bind('<Control-t>', self.sigterm)
+ self.bind('<Control-k>', self.sigkill)
+ self.bind('<Control-d>', self.sendeof)
+
+ self.pid, self.fromchild, self.tochild = spawn(shell, args)
+ self.tk.createfilehandler(self.fromchild, READABLE,
+ self.outputhandler)
+
+ def outputhandler(self, file, mask):
+ data = os.read(file, BUFSIZE).decode()
+ if not data:
+ self.tk.deletefilehandler(file)
+ pid, sts = os.waitpid(self.pid, 0)
+ print('pid', pid, 'status', sts)
+ self.pid = None
+ detail = sts>>8
+ cause = sts & 0xff
+ if cause == 0:
+ msg = "exit status %d" % detail
+ else:
+ msg = "killed by signal %d" % (cause & 0x7f)
+ if cause & 0x80:
+ msg = msg + " -- core dumped"
+ Dialog(self.master,
+ text=msg,
+ title="Exit status",
+ bitmap='warning',
+ default=0,
+ strings=('OK',))
+ return
+ self.insert(END, data)
+ self.pos = self.index("end - 1 char")
+ self.yview_pickplace(END)
+
+ def inputhandler(self, *args):
+ if not self.pid:
+ self.no_process()
+ return "break"
+ self.insert(END, "\n")
+ line = self.get(self.pos, "end - 1 char")
+ self.pos = self.index(END)
+ os.write(self.tochild, line.encode())
+ return "break"
+
+ def sendeof(self, *args):
+ if not self.pid:
+ self.no_process()
+ return "break"
+ os.close(self.tochild)
+ return "break"
+
+ def sendsig(self, sig):
+ if not self.pid:
+ self.no_process()
+ return "break"
+ os.kill(self.pid, sig)
+ return "break"
+
+ def sigint(self, *args):
+ return self.sendsig(signal.SIGINT)
+
+ def sigquit(self, *args):
+ return self.sendsig(signal.SIGQUIT)
+
+ def sigterm(self, *args):
+ return self.sendsig(signal.SIGTERM)
+
+ def sigkill(self, *args):
+ return self.sendsig(signal.SIGKILL)
+
+ def no_process(self):
+ Dialog(self.master,
+ text="No active process",
+ title="No process",
+ bitmap='error',
+ default=0,
+ strings=('OK',))
+
+MAXFD = 100 # Max number of file descriptors (os.getdtablesize()???)
+
+def spawn(prog, args):
+ p2cread, p2cwrite = os.pipe()
+ c2pread, c2pwrite = os.pipe()
+ pid = os.fork()
+ if pid == 0:
+ # Child
+ for i in 0, 1, 2:
+ try:
+ os.close(i)
+ except os.error:
+ pass
+ if os.dup(p2cread) != 0:
+ sys.stderr.write('popen2: bad read dup\n')
+ if os.dup(c2pwrite) != 1:
+ sys.stderr.write('popen2: bad write dup\n')
+ if os.dup(c2pwrite) != 2:
+ sys.stderr.write('popen2: bad write dup\n')
+ os.closerange(3, MAXFD)
+ try:
+ os.execvp(prog, args)
+ finally:
+ sys.stderr.write('execvp failed\n')
+ os._exit(1)
+ os.close(p2cread)
+ os.close(c2pwrite)
+ return pid, c2pread, p2cwrite
+
+def test():
+ shell = ' '.join(sys.argv[1: ])
+ root = Tk()
+ root.minsize(1, 1)
+ if shell:
+ w = ShellWindow(root, shell=shell)
+ else:
+ w = ShellWindow(root)
+ w.pack(expand=1, fill=BOTH)
+ w.focus_set()
+ w.tk.mainloop()
+
+if __name__ == '__main__':
+ test()