commit e4ea4f64e19c53a85414294f5b446d10cce4a074 Author: Damian Johnson atagar@torproject.org Date: Tue Apr 15 09:42:54 2014 -0700
Interpretor event handling
Supporting SETEVENTS and an '/event [type]' interpretor command for listing the events we've received. --- stem/interpretor/commands.py | 42 ++++++++++++++++++++++++++++++++++++++++- stem/interpretor/settings.cfg | 6 ++++++ 2 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/stem/interpretor/commands.py b/stem/interpretor/commands.py index af1948c..c711ade 100644 --- a/stem/interpretor/commands.py +++ b/stem/interpretor/commands.py @@ -47,6 +47,7 @@ SIGNAL_DESCRIPTIONS = (
HELP_OPTIONS = { 'HELP': ("/help [OPTION]", 'help.help'), + 'EVENTS': ("/events [types]", 'help.events'), 'QUIT': ("/quit", 'help.quit'), 'GETINFO': ("GETINFO OPTION", 'help.getinfo'), 'GETCONF': ("GETCONF OPTION", 'help.getconf'), @@ -196,6 +197,14 @@ class ControlInterpretor(object):
def __init__(self, controller): self.controller = controller + self.received_events = [] + + def register_event(self, event): + """ + Adds the event to our buffer so it'll be in '/events' output. + """ + + self.received_events.append(event)
def do_help(self, arg): """ @@ -317,6 +326,21 @@ class ControlInterpretor(object):
return output
+ def do_events(self, arg): + """ + Performs the '/events' operation, dumping the events that we've received + belonging to the given types. If no types are specified then this provides + all buffered events. + """ + + events = self.received_events + event_types = arg.upper().split() + + if event_types: + events = filter(lambda event: event.type in event_types, events) + + return '\n'.join([format(str(event), *OUTPUT_FORMAT) for event in events]) + def run_command(self, command): """ Runs the given command. Requests starting with a '/' are special commands @@ -356,6 +380,8 @@ class ControlInterpretor(object): if cmd.startswith('/'): if cmd == "/quit": raise stem.SocketClosed() + elif cmd == "/events": + output = self.do_events(arg) elif cmd == "/help": output = self.do_help(arg) else: @@ -411,7 +437,21 @@ class ControlInterpretor(object): except stem.ControllerError as exc: output = format(str(exc), *ERROR_FORMAT) elif cmd == 'SETEVENTS': - pass # TODO: implement + try: + # first discontinue listening to prior events + + self.controller.remove_event_listener(self.register_event) + + # attach listeners for the given group of events + + if arg: + events = arg.split() + self.controller.add_event_listener(self.register_event, *events) + output = format('Listing for %s events\n' % ', '.join(events), *OUTPUT_FORMAT) + else: + output = format('Disabled event listening\n', *OUTPUT_FORMAT) + except stem.ControllerError as exc: + output = format(str(exc), *ERROR_FORMAT) elif cmd.replace('+', '') in ('LOADCONF', 'POSTDESCRIPTOR'): # provides a notice that multi-line controller input isn't yet implemented output = format(msg('msg.multiline_unimplemented_notice'), *ERROR_FORMAT) diff --git a/stem/interpretor/settings.cfg b/stem/interpretor/settings.cfg index 9cd2201..e93b0e8 100644 --- a/stem/interpretor/settings.cfg +++ b/stem/interpretor/settings.cfg @@ -15,6 +15,7 @@ help.takeownership Instructs Tor to gracefully shut down when this control conne help.general |Interpretor commands include: | /help - provides information for interpretor and tor commands/config options +| /events - prints events that we've received | /quit - shuts down the interpretor | |Tor commands include: @@ -48,6 +49,11 @@ help.help |Example: | /help GETINFO # usage information for tor's GETINFO controller option
+help.events +|Provides events that we've received belonging to the given event types. If +|no types are specified then this provides all the messages that we've +|received. + help.getinfo |Queries the tor process for information. Options are... |
tor-commits@lists.torproject.org