1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
"""An input/output window for the glade reactor inspector.
12
from twisted.python.util import sibpath
13
from twisted.python import reflect
15
from twisted.manhole.ui import gtk2manhole
16
from twisted.python.components import Adapter, registerAdapter
17
from twisted.python import log
18
from twisted.protocols import policies
19
from zope.interface import implements, Interface
21
# the glade file uses stock icons, which requires gnome to be installed
23
version = "$Revision: 1.1 $"[11:-2]
24
gnome.init("gladereactor Inspector", version)
26
class ConsoleOutput(gtk2manhole.ConsoleOutput):
27
def _captureLocalLog(self):
28
self.fobs = log.FileLogObserver(gtk2manhole._Notafile(self, "log"))
35
class ConsoleInput(gtk2manhole.ConsoleInput):
36
def sendMessage(self):
37
buffer = self.textView.get_buffer()
38
iter1, iter2 = buffer.get_bounds()
39
text = buffer.get_text(iter1, iter2, False)
43
self.toplevel.do(text)
45
class INode(Interface):
46
"""A node in the inspector tree model.
49
def __adapt__(adaptable, default):
50
if hasattr(adaptable, "__dict__"):
51
return InstanceNode(adaptable)
52
return AttributesNode(adaptable)
54
class InspectorNode(Adapter):
57
def postInit(self, offset, parent, slot):
65
while x.parent is not None:
71
def __getitem__(self, index):
72
slot, o = self.get(index)
73
n = INode(o, persist=False)
74
n.postInit(index, self, slot)
78
return str(self.original)
81
return (self.slot, self.origstr())
84
class ConstantNode(InspectorNode):
88
class DictionaryNode(InspectorNode):
90
L = self.original.items()
95
return len(self.original)
100
class ListNode(InspectorNode):
101
def get(self, index):
102
return index, self.original[index]
108
return len(self.original)
110
class AttributesNode(InspectorNode):
112
return len(dir(self.original))
114
def get(self, index):
115
L = dir(self.original)
117
return L[index], getattr(self.original, L[index])
119
class InstanceNode(InspectorNode):
121
return len(self.original.__dict__) + 1
123
def get(self, index):
125
if hasattr(self.original, "__class__"):
126
v = self.original.__class__
128
v = type(self.original)
129
return "__class__", v
132
L = self.original.__dict__.items()
138
for x in dict, types.DictProxyType:
139
registerAdapter(DictionaryNode, x, INode)
140
for x in list, tuple:
141
registerAdapter(ListNode, x, INode)
143
registerAdapter(ConstantNode, x, INode)
146
class InspectorTreeModel(gtk.GenericTreeModel):
147
def __init__(self, root):
148
gtk.GenericTreeModel.__init__(self)
149
self.root = INode(root, persist=False)
150
self.root.postInit(0, None, 'root')
152
def on_get_flags(self):
155
def on_get_n_columns(self):
158
def on_get_column_type(self, index):
159
return gobject.TYPE_STRING
161
def on_get_path(self, node):
162
return node.getPath()
164
def on_get_iter(self, path):
170
def on_get_value(self, node, column):
171
return node.format()[column]
173
def on_iter_next(self, node):
175
return node.parent[node.offset + 1]
179
def on_iter_children(self, node):
182
def on_iter_has_child(self, node):
185
def on_iter_n_children(self, node):
188
def on_iter_nth_child(self, node, n):
193
def on_iter_parent(self, node):
199
def __init__(self, o=None):
200
self.xml = x = gtk.glade.XML(sibpath(__file__, "inspectro.glade"))
201
self.tree_view = x.get_widget("treeview")
202
colnames = ["Name", "Value"]
203
for i in range(len(colnames)):
204
self.tree_view.append_column(
206
colnames[i], gtk.CellRendererText(), text=i))
208
for m in reflect.prefixedMethods(self, "on_"):
209
d[m.im_func.__name__] = m
210
self.xml.signal_autoconnect(d)
213
self.ns = {'inspect': self.inspect}
214
iwidget = x.get_widget('input')
215
self.input = ConsoleInput(iwidget)
216
self.input.toplevel = self
217
iwidget.connect("key_press_event", self.input._on_key_press_event)
218
self.output = ConsoleOutput(x.get_widget('output'))
223
self.xml.get_widget("itname").set_text(repr(o))
224
self.xml.get_widget("itpath").set_text("???")
226
def inspect(self, o):
227
self.model = InspectorTreeModel(o)
228
self.tree_view.set_model(self.model)
231
def do(self, command):
232
filename = '<inspector>'
236
code = compile(command, filename, 'eval')
238
code = compile(command, filename, 'single')
239
val = eval(code, self.ns, self.ns)
246
def on_inspect(self, *a):
247
self.inspect(self.selected)
249
def on_inspect_new(self, *a):
250
Inspectro(self.selected)
252
def on_row_activated(self, tv, path, column):
253
self.select(self.model.on_get_iter(path).original)
256
class LoggingProtocol(policies.ProtocolWrapper):
257
"""Log network traffic."""
262
def __init__(self, *args):
263
policies.ProtocolWrapper.__init__(self, *args)
267
def write(self, data):
269
self.outLog.append((time.time(), data))
271
self.logViewer.updateOut(self.outLog[-1])
272
policies.ProtocolWrapper.write(self, data)
274
def dataReceived(self, data):
276
self.inLog.append((time.time(), data))
278
self.logViewer.updateIn(self.inLog[-1])
279
policies.ProtocolWrapper.dataReceived(self, data)
282
r = "wrapped " + repr(self.wrappedProtocol)
288
class LoggingFactory(policies.WrappingFactory):
289
"""Wrap protocols with logging wrappers."""
291
protocol = LoggingProtocol
294
def buildProtocol(self, addr):
295
p = self.protocol(self, self.wrappedFactory.buildProtocol(addr))
296
p.logging = self.logging
300
r = "wrapped " + repr(self.wrappedFactory)
307
"""Display log of network traffic."""
309
def __init__(self, p):
313
vals.append(p.inLog[0][0])
315
vals.append(p.outLog[0][0])
316
self.startTime = min(vals)
318
self.xml = x = gtk.glade.XML(sibpath(__file__, "logview.glade"))
319
self.xml.signal_autoconnect(self)
320
self.loglist = self.xml.get_widget("loglist")
321
# setup model, connect it to my treeview
322
self.model = gtk.ListStore(str, str, str)
323
self.loglist.set_model(self.model)
324
self.loglist.set_reorderable(1)
325
self.loglist.set_headers_clickable(1)
326
# self.servers.set_headers_draggable(1)
329
gtk.TreeViewColumn('Time',
330
gtk.CellRendererText(),
332
gtk.TreeViewColumn('D',
333
gtk.CellRendererText(),
335
gtk.TreeViewColumn('Data',
336
gtk.CellRendererText(),
338
self.loglist.append_column(col)
341
for t, data in p.inLog:
342
r.append(((str(t - self.startTime), "R", repr(data)[1:-1])))
343
for t, data in p.outLog:
344
r.append(((str(t - self.startTime), "S", repr(data)[1:-1])))
349
def updateIn(self, (time, data)):
350
self.model.append((str(time - self.startTime), "R", repr(data)[1:-1]))
352
def updateOut(self, (time, data)):
353
self.model.append((str(time - self.startTime), "S", repr(data)[1:-1]))
355
def on_logview_destroy(self, w):
356
self.p.logViewer = None
365
if __name__ == '__main__':
367
log.startLogging(sys.stdout)