diff options
| author | David Pursehouse <david.pursehouse@sonymobile.com> | 2012-07-24 18:08:10 +0900 |
|---|---|---|
| committer | David Pursehouse <david.pursehouse@sonymobile.com> | 2012-07-31 11:16:39 +0900 |
| commit | b6ba6d314ad8f764daa5ea8a2774c69439093c77 (patch) | |
| tree | c2c7b82da8b2da96c550225bc767239ea152490c /pygerrit/stream.py | |
| parent | 3e4893b19eb586b130f9e96d6820c7805b8f9ca1 (diff) | |
| download | pygerrit-b6ba6d314ad8f764daa5ea8a2774c69439093c77.tar.gz | |
Refactor into submodules
Data models, events, errors, and stream handler are split from the
single module into submodules.
Change-Id: I03537c5e268135966c6b6e77ecaca1cb579a5fde
Diffstat (limited to 'pygerrit/stream.py')
| -rw-r--r-- | pygerrit/stream.py | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/pygerrit/stream.py b/pygerrit/stream.py new file mode 100644 index 0000000..97daca6 --- /dev/null +++ b/pygerrit/stream.py @@ -0,0 +1,108 @@ +""" Gerrit event stream interface. + +Class to listen to the Gerrit event stream and dispatch events. + +""" + +import json + +from events import PatchsetCreatedEvent, \ + RefUpdatedEvent, ChangeMergedEvent, CommentAddedEvent, \ + ChangeAbandonedEvent, ChangeRestoredEvent, \ + DraftPublishedEvent + + +# Event types +CHANGE_MERGED = "change-merged" +PATCHSET_CREATED = "patchset-created" +DRAFT_PUBLISHED = "draft-published" +COMMENT_ADDED = "comment-added" +CHANGE_ABANDONED = "change-abandoned" +CHANGE_RESTORED = "change-restored" +REF_UPDATED = "ref-updated" + + +class GerritStreamError(Exception): + ''' GerritStreamError is raised when an error occurs while + reading the Gerrit events stream. + ''' + + +class GerritStream(object): + ''' Gerrit stream handler. + ''' + + # Map the event types to class names. + _event_dict = {CHANGE_MERGED: "ChangeMergedEvent", + PATCHSET_CREATED: "PatchsetCreatedEvent", + DRAFT_PUBLISHED: "DraftPublishedEvent", + COMMENT_ADDED: "CommentAddedEvent", + CHANGE_ABANDONED: "ChangeAbandonedEvent", + CHANGE_RESTORED: "ChangeRestoredEvent", + REF_UPDATED: "RefUpdatedEvent"} + + def __init__(self): + self.listeners = [] + + def attach(self, listener): + ''' Attach the `listener` to the list of listeners. + Raise GerritStreamError if the listener does not match the + expected signature, or if its event handler is not callable. + ''' + if not hasattr(listener, "on_gerrit_event"): + raise GerritStreamError("Listener must have `on_gerrit_event` " + "event handler method") + if not callable(listener.on_gerrit_event): + raise GerritStreamError("`on_gerrit_event` must be callable") + if not listener.on_gerrit_event.func_code.co_argcount == 2: + raise GerritStreamError("`on_gerrit_event` must take 1 arg") + if not listener in self.listeners: + self.listeners.append(listener) + + def detach(self, listener): + ''' Remove the `listener` from the list of listeners. + ''' + if listener in self.listeners: + try: + self.listeners.remove(listener) + except ValueError: + pass + + def _get_event(self, json_data): + ''' Create a new 'GerritEvent' from the JSON object + described in `json_data`. + Return an instance of one of the GerritEvent subclasses. + Raise GerritStreamError if any error occurs. + ''' + event_type = json_data["type"] + if event_type in self._event_dict: + classname = self._event_dict[event_type] + try: + return globals()[classname](json_data) + except KeyError, e: + raise GerritStreamError("Error creating event: %s" % e) + + raise GerritStreamError("Unexpected event type `%s`" % event_type) + + def _dispatch_event(self, event): + ''' Dispatch the `event` to the listeners. + ''' + for listener in self.listeners: + listener.on_gerrit_event(event) + + def stream(self, inputstream): + ''' Listen to the `inputstream` and handle JSON objects. + ''' + try: + done = 0 + while not done: + line = inputstream.readline() + if line: + data = json.loads(line) + self._dispatch_event(self._get_event(data)) + else: + break + except IOError, e: + raise GerritStreamError("Error reading event stream: %s" % e) + except ValueError, e: + raise GerritStreamError("Invalid JSON data in event stream: %s" % e) |
