Index: third_party/twisted_8_1/twisted/manhole/ui/gtk2manhole.py |
diff --git a/third_party/twisted_8_1/twisted/manhole/ui/gtk2manhole.py b/third_party/twisted_8_1/twisted/manhole/ui/gtk2manhole.py |
deleted file mode 100644 |
index cff81da8905a52fa6de6d8e1f5d9cc76ceae4ae7..0000000000000000000000000000000000000000 |
--- a/third_party/twisted_8_1/twisted/manhole/ui/gtk2manhole.py |
+++ /dev/null |
@@ -1,377 +0,0 @@ |
-# -*- Python -*- |
-# $Id: gtk2manhole.py,v 1.9 2003/09/07 19:58:09 acapnotic Exp $ |
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories. |
-# See LICENSE for details. |
- |
- |
-"""Manhole client with a GTK v2.x front-end. |
-""" |
- |
-__version__ = '$Revision: 1.9 $'[11:-2] |
- |
-from twisted import copyright |
-from twisted.internet import reactor |
-from twisted.python import components, failure, log, util |
-from twisted.spread import pb |
-from twisted.spread.ui import gtk2util |
- |
-from twisted.manhole.service import IManholeClient |
-from zope.interface import implements |
- |
-# The pygtk.require for version 2.0 has already been done by the reactor. |
-import gtk |
- |
-import code, types, inspect |
- |
-# TODO: |
-# Make wrap-mode a run-time option. |
-# Explorer. |
-# Code doesn't cleanly handle opening a second connection. Fix that. |
-# Make some acknowledgement of when a command has completed, even if |
-# it has no return value so it doesn't print anything to the console. |
- |
-class OfflineError(Exception): |
- pass |
- |
-class ManholeWindow(components.Componentized, gtk2util.GladeKeeper): |
- gladefile = util.sibpath(__file__, "gtk2manhole.glade") |
- |
- _widgets = ('input','output','manholeWindow') |
- |
- def __init__(self): |
- self.defaults = {} |
- gtk2util.GladeKeeper.__init__(self) |
- components.Componentized.__init__(self) |
- |
- self.input = ConsoleInput(self._input) |
- self.input.toplevel = self |
- self.output = ConsoleOutput(self._output) |
- |
- # Ugh. GladeKeeper actually isn't so good for composite objects. |
- # I want this connected to the ConsoleInput's handler, not something |
- # on this class. |
- self._input.connect("key_press_event", self.input._on_key_press_event) |
- |
- def setDefaults(self, defaults): |
- self.defaults = defaults |
- |
- def login(self): |
- client = self.getComponent(IManholeClient) |
- d = gtk2util.login(client, **self.defaults) |
- d.addCallback(self._cbLogin) |
- d.addCallback(client._cbLogin) |
- d.addErrback(self._ebLogin) |
- |
- def _cbDisconnected(self, perspective): |
- self.output.append("%s went away. :(\n" % (perspective,), "local") |
- self._manholeWindow.set_title("Manhole") |
- |
- def _cbLogin(self, perspective): |
- peer = perspective.broker.transport.getPeer() |
- self.output.append("Connected to %s\n" % (peer,), "local") |
- perspective.notifyOnDisconnect(self._cbDisconnected) |
- self._manholeWindow.set_title("Manhole - %s" % (peer)) |
- return perspective |
- |
- def _ebLogin(self, reason): |
- self.output.append("Login FAILED %s\n" % (reason.value,), "exception") |
- |
- def _on_aboutMenuItem_activate(self, widget, *unused): |
- import sys |
- from os import path |
- self.output.append("""\ |
-a Twisted Manhole client |
- Versions: |
- %(twistedVer)s |
- Python %(pythonVer)s on %(platform)s |
- GTK %(gtkVer)s / PyGTK %(pygtkVer)s |
- %(module)s %(modVer)s |
-http://twistedmatrix.com/ |
-""" % {'twistedVer': copyright.longversion, |
- 'pythonVer': sys.version.replace('\n', '\n '), |
- 'platform': sys.platform, |
- 'gtkVer': ".".join(map(str, gtk.gtk_version)), |
- 'pygtkVer': ".".join(map(str, gtk.pygtk_version)), |
- 'module': path.basename(__file__), |
- 'modVer': __version__, |
- }, "local") |
- |
- def _on_openMenuItem_activate(self, widget, userdata=None): |
- self.login() |
- |
- def _on_manholeWindow_delete_event(self, widget, *unused): |
- reactor.stop() |
- |
- def _on_quitMenuItem_activate(self, widget, *unused): |
- reactor.stop() |
- |
- def on_reload_self_activate(self, *unused): |
- from twisted.python import rebuild |
- rebuild.rebuild(inspect.getmodule(self.__class__)) |
- |
- |
-tagdefs = { |
- 'default': {"family": "monospace"}, |
- # These are message types we get from the server. |
- 'stdout': {"foreground": "black"}, |
- 'stderr': {"foreground": "#AA8000"}, |
- 'result': {"foreground": "blue"}, |
- 'exception': {"foreground": "red"}, |
- # Messages generate locally. |
- 'local': {"foreground": "#008000"}, |
- 'log': {"foreground": "#000080"}, |
- 'command': {"foreground": "#666666"}, |
- } |
- |
-# TODO: Factor Python console stuff back out to pywidgets. |
- |
-class ConsoleOutput: |
- _willScroll = None |
- def __init__(self, textView): |
- self.textView = textView |
- self.buffer = textView.get_buffer() |
- |
- # TODO: Make this a singleton tag table. |
- for name, props in tagdefs.iteritems(): |
- tag = self.buffer.create_tag(name) |
- # This can be done in the constructor in newer pygtk (post 1.99.14) |
- for k, v in props.iteritems(): |
- tag.set_property(k, v) |
- |
- self.buffer.tag_table.lookup("default").set_priority(0) |
- |
- self._captureLocalLog() |
- |
- def _captureLocalLog(self): |
- return log.startLogging(_Notafile(self, "log"), setStdout=False) |
- |
- def append(self, text, kind=None): |
- # XXX: It seems weird to have to do this thing with always applying |
- # a 'default' tag. Can't we change the fundamental look instead? |
- tags = ["default"] |
- if kind is not None: |
- tags.append(kind) |
- |
- self.buffer.insert_with_tags_by_name(self.buffer.get_end_iter(), |
- text, *tags) |
- # Silly things, the TextView needs to update itself before it knows |
- # where the bottom is. |
- if self._willScroll is None: |
- self._willScroll = gtk.idle_add(self._scrollDown) |
- |
- def _scrollDown(self, *unused): |
- self.textView.scroll_to_iter(self.buffer.get_end_iter(), 0, |
- True, 1.0, 1.0) |
- self._willScroll = None |
- return False |
- |
-class History: |
- def __init__(self, maxhist=10000): |
- self.ringbuffer = [''] |
- self.maxhist = maxhist |
- self.histCursor = 0 |
- |
- def append(self, htext): |
- self.ringbuffer.insert(-1, htext) |
- if len(self.ringbuffer) > self.maxhist: |
- self.ringbuffer.pop(0) |
- self.histCursor = len(self.ringbuffer) - 1 |
- self.ringbuffer[-1] = '' |
- |
- def move(self, prevnext=1): |
- ''' |
- Return next/previous item in the history, stopping at top/bottom. |
- ''' |
- hcpn = self.histCursor + prevnext |
- if hcpn >= 0 and hcpn < len(self.ringbuffer): |
- self.histCursor = hcpn |
- return self.ringbuffer[hcpn] |
- else: |
- return None |
- |
- def histup(self, textbuffer): |
- if self.histCursor == len(self.ringbuffer) - 1: |
- si, ei = textbuffer.get_start_iter(), textbuffer.get_end_iter() |
- self.ringbuffer[-1] = textbuffer.get_text(si,ei) |
- newtext = self.move(-1) |
- if newtext is None: |
- return |
- textbuffer.set_text(newtext) |
- |
- def histdown(self, textbuffer): |
- newtext = self.move(1) |
- if newtext is None: |
- return |
- textbuffer.set_text(newtext) |
- |
- |
-class ConsoleInput: |
- toplevel, rkeymap = None, None |
- __debug = False |
- |
- def __init__(self, textView): |
- self.textView=textView |
- self.rkeymap = {} |
- self.history = History() |
- for name in dir(gtk.keysyms): |
- try: |
- self.rkeymap[getattr(gtk.keysyms, name)] = name |
- except TypeError: |
- pass |
- |
- def _on_key_press_event(self, entry, event): |
- stopSignal = False |
- ksym = self.rkeymap.get(event.keyval, None) |
- |
- mods = [] |
- for prefix, mask in [('ctrl', gtk.gdk.CONTROL_MASK), ('shift', gtk.gdk.SHIFT_MASK)]: |
- if event.state & mask: |
- mods.append(prefix) |
- |
- if mods: |
- ksym = '_'.join(mods + [ksym]) |
- |
- if ksym: |
- rvalue = getattr( |
- self, 'key_%s' % ksym, lambda *a, **kw: None)(entry, event) |
- |
- if self.__debug: |
- print ksym |
- return rvalue |
- |
- def getText(self): |
- buffer = self.textView.get_buffer() |
- iter1, iter2 = buffer.get_bounds() |
- text = buffer.get_text(iter1, iter2, False) |
- return text |
- |
- def setText(self, text): |
- self.textView.get_buffer().set_text(text) |
- |
- def key_Return(self, entry, event): |
- text = self.getText() |
- # Figure out if that Return meant "next line" or "execute." |
- try: |
- c = code.compile_command(text) |
- except SyntaxError, e: |
- # This could conceivably piss you off if the client's python |
- # doesn't accept keywords that are known to the manhole's |
- # python. |
- point = buffer.get_iter_at_line_offset(e.lineno, e.offset) |
- buffer.place(point) |
- # TODO: Componentize! |
- self.toplevel.output.append(str(e), "exception") |
- except (OverflowError, ValueError), e: |
- self.toplevel.output.append(str(e), "exception") |
- else: |
- if c is not None: |
- self.sendMessage() |
- # Don't insert Return as a newline in the buffer. |
- self.history.append(text) |
- self.clear() |
- # entry.emit_stop_by_name("key_press_event") |
- return True |
- else: |
- # not a complete code block |
- return False |
- |
- return False |
- |
- def key_Up(self, entry, event): |
- # if I'm at the top, previous history item. |
- textbuffer = self.textView.get_buffer() |
- if textbuffer.get_iter_at_mark(textbuffer.get_insert()).get_line() == 0: |
- self.history.histup(textbuffer) |
- return True |
- return False |
- |
- def key_Down(self, entry, event): |
- textbuffer = self.textView.get_buffer() |
- if textbuffer.get_iter_at_mark(textbuffer.get_insert()).get_line() == ( |
- textbuffer.get_line_count() - 1): |
- self.history.histdown(textbuffer) |
- return True |
- return False |
- |
- key_ctrl_p = key_Up |
- key_ctrl_n = key_Down |
- |
- def key_ctrl_shift_F9(self, entry, event): |
- if self.__debug: |
- import pdb; pdb.set_trace() |
- |
- def clear(self): |
- buffer = self.textView.get_buffer() |
- buffer.delete(*buffer.get_bounds()) |
- |
- def sendMessage(self): |
- buffer = self.textView.get_buffer() |
- iter1, iter2 = buffer.get_bounds() |
- text = buffer.get_text(iter1, iter2, False) |
- self.toplevel.output.append(pythonify(text), 'command') |
- # TODO: Componentize better! |
- try: |
- return self.toplevel.getComponent(IManholeClient).do(text) |
- except OfflineError: |
- self.toplevel.output.append("Not connected, command not sent.\n", |
- "exception") |
- |
- |
-def pythonify(text): |
- ''' |
- Make some text appear as though it was typed in at a Python prompt. |
- ''' |
- lines = text.split('\n') |
- lines[0] = '>>> ' + lines[0] |
- return '\n... '.join(lines) + '\n' |
- |
-class _Notafile: |
- """Curry to make failure.printTraceback work with the output widget.""" |
- def __init__(self, output, kind): |
- self.output = output |
- self.kind = kind |
- |
- def write(self, txt): |
- self.output.append(txt, self.kind) |
- |
- def flush(self): |
- pass |
- |
-class ManholeClient(components.Adapter, pb.Referenceable): |
- implements(IManholeClient) |
- |
- capabilities = { |
-# "Explorer": 'Set', |
- "Failure": 'Set' |
- } |
- |
- def _cbLogin(self, perspective): |
- self.perspective = perspective |
- perspective.notifyOnDisconnect(self._cbDisconnected) |
- return perspective |
- |
- def remote_console(self, messages): |
- for kind, content in messages: |
- if isinstance(content, types.StringTypes): |
- self.original.output.append(content, kind) |
- elif (kind == "exception") and isinstance(content, failure.Failure): |
- content.printTraceback(_Notafile(self.original.output, |
- "exception")) |
- else: |
- self.original.output.append(str(content), kind) |
- |
- def remote_receiveExplorer(self, xplorer): |
- pass |
- |
- def remote_listCapabilities(self): |
- return self.capabilities |
- |
- def _cbDisconnected(self, perspective): |
- self.perspective = None |
- |
- def do(self, text): |
- if self.perspective is None: |
- raise OfflineError |
- return self.perspective.callRemote("do", text) |
- |
-components.registerAdapter(ManholeClient, ManholeWindow, IManholeClient) |