I changed it to work with python 1.5.2 and PyGTK 0.6.6 as well (see the attached).
NOTE: I changed the banner wording slightly.
I'd like to include this in the PyGTK Tutorial if you don't mind because I think it's a great tool for people learning and exploring PyGTK.
John
#!/usr/bin/env python # -*- Mode: python; c-basic-offset: 4 -*- # # Interactive PyGtk Console, Johan Dahlin 2002 #
import os
import signal
import sys
import string
from code import InteractiveInterpreter, InteractiveConsole
import gtk
from gtk import TRUE, FALSE
# For compatibility, instead of using GDK.INPUT_READ or
# gtk.gdk.INPUT_READ depending on the PyGtk version
GDK_INPUT_READ = 1
class Mainloop(InteractiveInterpreter):
def __init__(self, read_fd, pid):
InteractiveInterpreter.__init__(self)
self._rfd = os.fdopen(read_fd, 'r')
self.pid = pid
gtk.input_add(read_fd, GDK_INPUT_READ, self.input_func)
def read_message(self):
length = ord(self._rfd.read(1))
return self._rfd.read(length)
def input_func(self, fd, cond):
data = self.read_message()
more = self.runsource(data)
if more:
signal_id = signal.SIGUSR1
else:
signal_id = signal.SIGUSR2
# Now when we're done, notify the console (parent process)
os.kill(self.pid, signal_id)
return TRUE
def run(self):
gtk.mainloop()
class Console(InteractiveConsole):
def __init__(self, write_fd, pid):
InteractiveConsole.__init__(self)
self._wfd = os.fdopen(write_fd, 'w')
self.pid = pid
# Listen on SIGUSR1, SIGUSR2
signal.signal(signal.SIGUSR1, self.signal_handler)
signal.signal(signal.SIGUSR2, self.signal_handler)
def signal_handler(self, sig_id, frame):
# We receive different signals depend on if
# we have more data in the buffer to interpret
if sig_id == signal.SIGUSR1:
self.more = 1
elif sig_id == signal.SIGUSR2:
self.more = 0
def send_message(self, message):
self._wfd.write('%c%s' % (len(message), message))
self._wfd.flush()
def interact(self, banner=None):
InteractiveConsole.interact(self, banner)
# Die parent die
os.kill(self.pid, 9)
def runsource(self, source, filename):
self.send_message(source)
# wait for notification from parent
signal.pause()
return self.more
class GtkInterpreter(Console):
def __init__(self):
rfd, wfd = os.pipe()
parent_pid = os.getpid()
child_pid = os.fork()
if not child_pid:
g = Mainloop(rfd, parent_pid)
g.run()
else:
Console.__init__(self, wfd, child_pid)
def interact():
try:
import readline
import rlcompleter
readline.parse_and_bind('tab: complete')
except ImportError:
pass
gi = GtkInterpreter()
gi.push("from gtk import *")
python_version = string.split(sys.version)[0]
try:
pygtk_version = '.'.join(map(str, gtk.pygtk_version))
gtk_version = '.'.join(map(str, gtk.gtk_version))
except:
pygtk_version = ''
gtk_version = ''
banner = """Python %s, PyGTK %s (Gtk+ %s)
Interactive console to manipulate GTK+ widgets
interactively, without blocking on the mainloop.""" % (python_version,
pygtk_version,
gtk_version)
gi.interact(banner)
if __name__ == '__main__':
interact()
