OLD | NEW |
| (Empty) |
1 # -*- Python -*- | |
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 | |
6 # TODO: | |
7 # * send script | |
8 # * replace method | |
9 # * save readline history | |
10 # * save-history-as-python | |
11 # * save transcript | |
12 # * identifier completion | |
13 | |
14 import code, string, sys, traceback, types | |
15 import gtk | |
16 | |
17 from twisted.python import rebuild, util | |
18 from twisted.spread.ui import gtkutil | |
19 from twisted.spread import pb | |
20 from twisted.manhole import explorer | |
21 | |
22 True = gtk.TRUE | |
23 False = gtk.FALSE | |
24 | |
25 try: | |
26 import spelunk_gnome | |
27 except ImportError: | |
28 _GNOME_POWER = False | |
29 else: | |
30 _GNOME_POWER = True | |
31 | |
32 | |
33 ## def findBeginningOfLineWithPoint(entry): | |
34 ## pos = entry.get_point() | |
35 ## while pos: | |
36 ## pos = pos - 1 | |
37 ## c = entry.get_chars(pos, pos+1) | |
38 ## if c == '\n': | |
39 ## return pos+1 | |
40 ## return 0 | |
41 | |
42 import pywidgets | |
43 | |
44 class Interaction(pywidgets.Interaction, pb.Referenceable): | |
45 loginWindow = None | |
46 | |
47 capabilities = { | |
48 "Explorer": 'Set', | |
49 } | |
50 | |
51 def __init__(self): | |
52 pywidgets.Interaction.__init__(self) | |
53 self.signal_connect('destroy', gtk.mainquit, None) | |
54 | |
55 if _GNOME_POWER: | |
56 self.display = BrowserDisplay() | |
57 dWindow = gtk.GtkWindow(title="Spelunking") | |
58 dWindow.add(self.display) | |
59 dWindow.show_all() | |
60 self.display.makeDefaultCanvas() | |
61 else: | |
62 self.display = BrowserDisplay(self) | |
63 | |
64 # The referencable attached to the Perspective | |
65 self.client = self | |
66 | |
67 def remote_console(self, message): | |
68 self.output.console(message) | |
69 | |
70 def remote_receiveExplorer(self, xplorer): | |
71 if _GNOME_POWER: | |
72 self.display.receiveExplorer(xplorer) | |
73 else: | |
74 XXX # text display? | |
75 | |
76 def remote_listCapabilities(self): | |
77 return self.capabilities | |
78 | |
79 def connected(self, perspective): | |
80 self.loginWindow.hide() | |
81 self.name = self.loginWindow.username.get_text() | |
82 self.hostname = self.loginWindow.hostname.get_text() | |
83 perspective.broker.notifyOnDisconnect(self.connectionLost) | |
84 self.perspective = perspective | |
85 self.show_all() | |
86 self.set_title("Manhole: %s@%s" % (self.name, self.hostname)) | |
87 | |
88 def connectionLost(self, reason=None): | |
89 if not reason: | |
90 reason = "Connection Lost" | |
91 self.loginWindow.loginReport(reason) | |
92 self.hide() | |
93 self.loginWindow.show() | |
94 | |
95 def codeInput(self, text): | |
96 methodName = 'do' | |
97 if text[0] == '/': | |
98 split = string.split(text[1:],' ',1) | |
99 statement = split[0] | |
100 if len(split) == 2: | |
101 remainder = split[1] | |
102 if statement in ('browse', 'explore'): | |
103 methodName = 'explore' | |
104 text = remainder | |
105 elif statement == 'watch': | |
106 methodName = 'watch' | |
107 text = remainder | |
108 elif statement == 'self_rebuild': | |
109 rebuild.rebuild(explorer) | |
110 if _GNOME_POWER: | |
111 rebuild.rebuild(spelunk_gnome) | |
112 rebuild.rebuild(sys.modules[__name__]) | |
113 return | |
114 try: | |
115 self.perspective.callRemote(methodName, text) | |
116 except pb.ProtocolError: | |
117 # ASSUMPTION: pb.ProtocolError means we lost our connection. | |
118 (eType, eVal, tb) = sys.exc_info() | |
119 del tb | |
120 s = string.join(traceback.format_exception_only(eType, eVal), | |
121 '') | |
122 self.connectionLost(s) | |
123 except: | |
124 traceback.print_exc() | |
125 gtk.mainquit() | |
126 | |
127 | |
128 class LineOrientedBrowserDisplay: | |
129 def __init__(self, toplevel=None): | |
130 if toplevel: | |
131 self.toplevel = toplevel | |
132 | |
133 def receiveBrowserObject(self, obj): | |
134 """Display a browser ObjectLink. | |
135 """ | |
136 # This is a stop-gap implementation. Ideally, everything | |
137 # would be nicely formatted with pretty colours and you could | |
138 # select referenced objects to browse them with | |
139 # browse(selectedLink.identifier) | |
140 | |
141 if obj.type in map(explorer.typeString, [types.FunctionType, | |
142 types.MethodType]): | |
143 arglist = [] | |
144 for arg in obj.value['signature']: | |
145 if arg.has_key('default'): | |
146 a = "%s=%s" % (arg['name'], arg['default']) | |
147 elif arg.has_key('list'): | |
148 a = "*%s" % (arg['name'],) | |
149 elif arg.has_key('keywords'): | |
150 a = "**%s" % (arg['name'],) | |
151 else: | |
152 a = arg['name'] | |
153 arglist.append(a) | |
154 | |
155 things = '' | |
156 if obj.value.has_key('class'): | |
157 things = "Class: %s\n" % (obj.value['class'],) | |
158 if obj.value.has_key('self'): | |
159 things = things + "Self: %s\n" % (obj.value['self'],) | |
160 | |
161 s = "%(name)s(%(arglist)s)\n%(things)s\n%(doc)s\n" % { | |
162 'name': obj.value['name'], | |
163 'doc': obj.value['doc'], | |
164 'things': things, | |
165 'arglist': string.join(arglist,", "), | |
166 } | |
167 else: | |
168 s = str(obj) + '\n' | |
169 | |
170 self.toplevel.output.console([('stdout',s)]) | |
171 | |
172 | |
173 if _GNOME_POWER: | |
174 BrowserDisplay = spelunk_gnome.SpelunkDisplay | |
175 else: | |
176 BrowserDisplay = LineOrientedBrowserDisplay | |
177 | |
178 class Signature(pb.RemoteCopy, explorer.Signature): | |
179 def __init__(self): | |
180 pass | |
181 | |
182 __str__ = explorer.Signature.__str__ | |
183 | |
184 pb.setCopierForClass('twisted.manhole.explorer.Signature', Signature) | |
OLD | NEW |