# -*- Python -*-
# Twisted, the Framework of Your Internet
# $Id: gtkmanhole.py,v 1.39 2003/01/31 02:39:31 acapnotic Exp $
# Copyright (C) 2001 Matthew W. Lefkowitz
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# TODO:
# * send script
# * replace method
# * save readline history
# * save-history-as-python
# * save transcript
# * identifier completion
import code, string, sys, traceback, types
import gtk
from twisted.python import rebuild, util
from twisted.spread.ui import gtkutil
from twisted.spread import pb
from twisted.manhole import explorer
True = gtk.TRUE
False = gtk.FALSE
try:
import spelunk_gnome
except ImportError:
_GNOME_POWER = False
else:
_GNOME_POWER = True
## def findBeginningOfLineWithPoint(entry):
## pos = entry.get_point()
## while pos:
## pos = pos - 1
## c = entry.get_chars(pos, pos+1)
## if c == '\n':
## return pos+1
## return 0
import pywidgets
class Interaction(pywidgets.Interaction, pb.Referenceable):
loginWindow = None
capabilities = {
"Explorer": 'Set',
}
def __init__(self):
pywidgets.Interaction.__init__(self)
self.signal_connect('destroy', gtk.mainquit, None)
if _GNOME_POWER:
self.display = BrowserDisplay()
dWindow = gtk.GtkWindow(title="Spelunking")
dWindow.add(self.display)
dWindow.show_all()
self.display.makeDefaultCanvas()
else:
self.display = BrowserDisplay(self)
# The referencable attached to the Perspective
self.client = self
def remote_console(self, message):
self.output.console(message)
def remote_receiveExplorer(self, xplorer):
if _GNOME_POWER:
self.display.receiveExplorer(xplorer)
else:
XXX # text display?
def remote_listCapabilities(self):
return self.capabilities
def connected(self, perspective):
self.loginWindow.hide()
self.name = self.loginWindow.username.get_text()
self.hostname = self.loginWindow.hostname.get_text()
perspective.broker.notifyOnDisconnect(self.connectionLost)
self.perspective = perspective
self.show_all()
self.set_title("Manhole: %s@%s" % (self.name, self.hostname))
def connectionLost(self, reason=None):
if not reason:
reason = "Connection Lost"
self.loginWindow.loginReport(reason)
self.hide()
self.loginWindow.show()
def codeInput(self, text):
methodName = 'do'
if text[0] == '/':
split = string.split(text[1:],' ',1)
statement = split[0]
if len(split) == 2:
remainder = split[1]
if statement in ('browse', 'explore'):
methodName = 'explore'
text = remainder
elif statement == 'watch':
methodName = 'watch'
text = remainder
elif statement == 'self_rebuild':
rebuild.rebuild(explorer)
if _GNOME_POWER:
rebuild.rebuild(spelunk_gnome)
rebuild.rebuild(sys.modules[__name__])
return
try:
self.perspective.callRemote(methodName, text)
except pb.ProtocolError:
# ASSUMPTION: pb.ProtocolError means we lost our connection.
(eType, eVal, tb) = sys.exc_info()
del tb
s = string.join(traceback.format_exception_only(eType, eVal),
'')
self.connectionLost(s)
except:
traceback.print_exc()
gtk.mainquit()
class LineOrientedBrowserDisplay:
def __init__(self, toplevel=None):
if toplevel:
self.toplevel = toplevel
def receiveBrowserObject(self, obj):
"""Display a browser ObjectLink.
"""
# This is a stop-gap implementation. Ideally, everything
# would be nicely formatted with pretty colours and you could
# select referenced objects to browse them with
# browse(selectedLink.identifier)
if obj.type in map(explorer.typeString, [types.FunctionType,
types.MethodType]):
arglist = []
for arg in obj.value['signature']:
if arg.has_key('default'):
a = "%s=%s" % (arg['name'], arg['default'])
elif arg.has_key('list'):
a = "*%s" % (arg['name'],)
elif arg.has_key('keywords'):
a = "**%s" % (arg['name'],)
else:
a = arg['name']
arglist.append(a)
things = ''
if obj.value.has_key('class'):
things = "Class: %s\n" % (obj.value['class'],)
if obj.value.has_key('self'):
things = things + "Self: %s\n" % (obj.value['self'],)
s = "%(name)s(%(arglist)s)\n%(things)s\n%(doc)s\n" % {
'name': obj.value['name'],
'doc': obj.value['doc'],
'things': things,
'arglist': string.join(arglist,", "),
}
else:
s = str(obj) + '\n'
self.toplevel.output.console([('stdout',s)])
if _GNOME_POWER:
BrowserDisplay = spelunk_gnome.SpelunkDisplay
else:
BrowserDisplay = LineOrientedBrowserDisplay
class Signature(pb.RemoteCopy, explorer.Signature):
def __init__(self):
pass
__str__ = explorer.Signature.__str__
pb.setCopierForClass('twisted.manhole.explorer.Signature', Signature)
syntax highlighted by Code2HTML, v. 0.9.1