Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / manhole / _inspectro.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4
5 """An input/output window for the glade reactor inspector.
6 """
7
8 import time
9 import gtk
10 import gobject
11 import gtk.glade
12 from twisted.python.util import sibpath
13 from twisted.python import reflect
14
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
20
21 # the glade file uses stock icons, which requires gnome to be installed
22 import gnome
23 version = "$Revision: 1.1 $"[11:-2]
24 gnome.init("gladereactor Inspector", version)
25
26 class ConsoleOutput(gtk2manhole.ConsoleOutput):
27     def _captureLocalLog(self):
28         self.fobs = log.FileLogObserver(gtk2manhole._Notafile(self, "log"))
29         self.fobs.start()
30
31     def stop(self):
32         self.fobs.stop()
33         del self.fobs
34
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)
40         self.do(text)
41
42     def do(self, text):
43         self.toplevel.do(text)
44
45 class INode(Interface):
46     """A node in the inspector tree model.
47     """
48
49     def __adapt__(adaptable, default):
50         if hasattr(adaptable, "__dict__"):
51             return InstanceNode(adaptable)
52         return AttributesNode(adaptable)
53
54 class InspectorNode(Adapter):
55     implements(INode)
56
57     def postInit(self, offset, parent, slot):
58         self.offset = offset
59         self.parent = parent
60         self.slot = slot
61
62     def getPath(self):
63         L = []
64         x = self
65         while x.parent is not None:
66             L.append(x.offset)
67             x = x.parent
68         L.reverse()
69         return L
70
71     def __getitem__(self, index):
72         slot, o = self.get(index)
73         n = INode(o, persist=False)
74         n.postInit(index, self, slot)
75         return n
76
77     def origstr(self):
78         return str(self.original)
79
80     def format(self):
81         return (self.slot, self.origstr())
82
83
84 class ConstantNode(InspectorNode):
85     def __len__(self):
86         return 0
87
88 class DictionaryNode(InspectorNode):
89     def get(self, index):
90         L = self.original.items()
91         L.sort()
92         return L[index]
93
94     def __len__(self):
95         return len(self.original)
96
97     def origstr(self):
98         return "Dictionary"
99
100 class ListNode(InspectorNode):
101     def get(self, index):
102         return index, self.original[index]
103
104     def origstr(self):
105         return "List"
106
107     def __len__(self):
108         return len(self.original)
109
110 class AttributesNode(InspectorNode):
111     def __len__(self):
112         return len(dir(self.original))
113
114     def get(self, index):
115         L = dir(self.original)
116         L.sort()
117         return L[index], getattr(self.original, L[index])
118
119 class InstanceNode(InspectorNode):
120     def __len__(self):
121         return len(self.original.__dict__) + 1
122
123     def get(self, index):
124         if index == 0:
125             if hasattr(self.original, "__class__"):
126                 v = self.original.__class__
127             else:
128                 v = type(self.original)
129             return "__class__", v
130         else:
131             index -= 1
132             L = self.original.__dict__.items()
133             L.sort()
134             return L[index]
135
136 import types
137
138 for x in dict, types.DictProxyType:
139     registerAdapter(DictionaryNode, x, INode)
140 for x in list, tuple:
141     registerAdapter(ListNode, x, INode)
142 for x in int, str:
143     registerAdapter(ConstantNode, x, INode)
144
145
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')
151
152     def on_get_flags(self):
153         return 0
154
155     def on_get_n_columns(self):
156         return 1
157
158     def on_get_column_type(self, index):
159         return gobject.TYPE_STRING
160
161     def on_get_path(self, node):
162         return node.getPath()
163
164     def on_get_iter(self, path):
165         x = self.root
166         for elem in path:
167             x = x[elem]
168         return x
169
170     def on_get_value(self, node, column):
171         return node.format()[column]
172
173     def on_iter_next(self, node):
174         try:
175             return node.parent[node.offset + 1]
176         except IndexError:
177             return None
178
179     def on_iter_children(self, node):
180         return node[0]
181
182     def on_iter_has_child(self, node):
183         return len(node)
184
185     def on_iter_n_children(self, node):
186         return len(node)
187
188     def on_iter_nth_child(self, node, n):
189         if node is None:
190             return None
191         return node[n]
192
193     def on_iter_parent(self, node):
194         return node.parent
195
196
197 class Inspectro:
198     selected = None
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(
205                 gtk.TreeViewColumn(
206                 colnames[i], gtk.CellRendererText(), text=i))
207         d = {}
208         for m in reflect.prefixedMethods(self, "on_"):
209             d[m.im_func.__name__] = m
210         self.xml.signal_autoconnect(d)
211         if o is not None:
212             self.inspect(o)
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'))
219
220     def select(self, o):
221         self.selected = o
222         self.ns['it'] = o
223         self.xml.get_widget("itname").set_text(repr(o))
224         self.xml.get_widget("itpath").set_text("???")
225
226     def inspect(self, o):
227         self.model = InspectorTreeModel(o)
228         self.tree_view.set_model(self.model)
229         self.inspected = o
230
231     def do(self, command):
232         filename = '<inspector>'
233         try:
234             print repr(command)
235             try:
236                 code = compile(command, filename, 'eval')
237             except:
238                 code = compile(command, filename, 'single')
239             val = eval(code, self.ns, self.ns)
240             if val is not None:
241                 print repr(val)
242             self.ns['_'] = val
243         except:
244             log.err()
245
246     def on_inspect(self, *a):
247         self.inspect(self.selected)
248
249     def on_inspect_new(self, *a):
250         Inspectro(self.selected)
251
252     def on_row_activated(self, tv, path, column):
253         self.select(self.model.on_get_iter(path).original)
254
255
256 class LoggingProtocol(policies.ProtocolWrapper):
257     """Log network traffic."""
258
259     logging = True
260     logViewer = None
261     
262     def __init__(self, *args):
263         policies.ProtocolWrapper.__init__(self, *args)
264         self.inLog = []
265         self.outLog = []
266
267     def write(self, data):
268         if self.logging:
269             self.outLog.append((time.time(), data))
270             if self.logViewer:
271                 self.logViewer.updateOut(self.outLog[-1])
272         policies.ProtocolWrapper.write(self, data)
273
274     def dataReceived(self, data):
275         if self.logging:
276             self.inLog.append((time.time(), data))
277             if self.logViewer:
278                 self.logViewer.updateIn(self.inLog[-1])
279         policies.ProtocolWrapper.dataReceived(self, data)
280
281     def __repr__(self):
282         r = "wrapped " + repr(self.wrappedProtocol)
283         if self.logging:
284             r += " (logging)"
285         return r
286
287
288 class LoggingFactory(policies.WrappingFactory):
289     """Wrap protocols with logging wrappers."""
290
291     protocol = LoggingProtocol
292     logging = True
293     
294     def buildProtocol(self, addr):
295         p = self.protocol(self, self.wrappedFactory.buildProtocol(addr))    
296         p.logging = self.logging
297         return p
298
299     def __repr__(self):
300         r = "wrapped " + repr(self.wrappedFactory)
301         if self.logging:
302             r += " (logging)"
303         return r
304
305
306 class LogViewer:
307     """Display log of network traffic."""
308     
309     def __init__(self, p):
310         self.p = p
311         vals = [time.time()]
312         if p.inLog:
313             vals.append(p.inLog[0][0])
314         if p.outLog:
315             vals.append(p.outLog[0][0])
316         self.startTime = min(vals)
317         p.logViewer = self
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)
327         # add a column
328         for col in [
329             gtk.TreeViewColumn('Time',
330                                gtk.CellRendererText(),
331                                text=0),
332             gtk.TreeViewColumn('D',
333                                gtk.CellRendererText(),
334                                text=1),
335             gtk.TreeViewColumn('Data',
336                                gtk.CellRendererText(),
337                                text=2)]:
338             self.loglist.append_column(col)
339             col.set_resizable(1)
340         r = []
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])))
345         r.sort()
346         for i in r:
347             self.model.append(i)
348     
349     def updateIn(self, (time, data)):
350         self.model.append((str(time - self.startTime), "R", repr(data)[1:-1]))
351
352     def updateOut(self, (time, data)):
353         self.model.append((str(time - self.startTime), "S", repr(data)[1:-1]))
354
355     def on_logview_destroy(self, w):
356         self.p.logViewer = None
357         del self.p
358
359
360 def main():
361     x = Inspectro()
362     x.inspect(x)
363     gtk.main()
364
365 if __name__ == '__main__':
366     import sys
367     log.startLogging(sys.stdout)
368     main()
369