Skip to content

Commit

Permalink
Adds room event and message iterators.
Browse files Browse the repository at this point in the history
resolves #43, resolves #65
  • Loading branch information
jeremyBanks committed May 15, 2014
1 parent 6f213cc commit 54cca16
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 54 deletions.
8 changes: 8 additions & 0 deletions chatexchange/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ def watch_room_socket(self, room_id, on_activity):
socket_watcher = RoomSocketWatcher(self, room_id, on_activity)
self.sockets[room_id] = socket_watcher
socket_watcher.start()
return socket_watcher

def watch_room_http(self, room_id, on_activity, interval):
"""
Expand All @@ -249,6 +250,7 @@ def watch_room_http(self, room_id, on_activity, interval):
http_watcher = RoomPollingWatcher(self, room_id, on_activity, interval)
self.polls[room_id] = http_watcher
http_watcher.start()
return http_watcher

def toggle_starring(self, message_id):
return self.post_fkeyed(
Expand Down Expand Up @@ -566,6 +568,9 @@ def __init__(self, browser, room_id, on_activity):
self.on_activity = on_activity
self.killed = False

def close(self):
self.killed = True

def start(self):
last_event_time = self.browser.rooms[self.room_id]['eventtime']

Expand Down Expand Up @@ -607,6 +612,9 @@ def start(self):
self.thread.setDaemon(True)
self.thread.start()

def close(self):
self.killed = True

def _runner(self):
while not self.killed:
last_event_time = self.browser.rooms[self.room_id]['eventtime']
Expand Down
29 changes: 1 addition & 28 deletions chatexchange/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, host='stackexchange.com', email=None, password=None):
If email and password are provided, the client will L{login}.
"""
self.logger = logger.getChild('SEChatWraper')
self.logger = logger.getChild('Client')

if email or password:
assert email and password, (
Expand Down Expand Up @@ -254,30 +254,3 @@ def _do_action_despite_throttling(self, action):

def _join_room(self, room_id):
self._br.join_room(room_id)

def _room_events(self, activity, room_id):
"""
Returns a list of Events associated with a particular room,
given an activity message from the server.
"""
room_activity = activity.get('r%s' % (room_id,), {})
room_events_data = room_activity.get('e', [])
for room_event_data in room_events_data:
if room_event_data:
event = events.make(room_event_data, self)
self._recently_gotten_objects.appendleft(event)
yield event

def _watch_room_polling(self, room_id, event_callback, interval):
def on_activity(activity):
for event in self._room_events(activity, room_id):
event_callback(event, self)

self._br.watch_room_http(room_id, on_activity, interval)

def _watch_room_socket(self, room_id, event_callback):
def on_activity(activity):
for event in self._room_events(activity, room_id):
event_callback(event, self)

self._br.watch_room_socket(room_id, on_activity)
74 changes: 63 additions & 11 deletions chatexchange/rooms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import Queue
import contextlib
import logging

from . import _utils, events
import collections


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -52,26 +55,75 @@ def watch(self, event_callback):
return self.watch_polling(event_callback, 3)

def watch_polling(self, event_callback, interval):
return self._client._watch_room_polling(self.id, event_callback, interval)
def on_activity(activity):
for event in self._events_from_activity(activity, self.id):
event_callback(event, self._client)

return self._client._br.watch_room_http(self.id, on_activity, interval)

def watch_socket(self, event_callback):
return self._client._watch_room_socket(self.id, event_callback)
def on_activity(activity):
for event in self._events_from_activity(activity, self.id):
event_callback(event, self._client)

return self._client._br.watch_room_socket(self.id, on_activity)

def _events_from_activity(self, activity, room_id):
"""
Returns a list of Events associated with a particular room,
given an activity message from the server.
"""
room_activity = activity.get('r%s' % (room_id,), {})
room_events_data = room_activity.get('e', [])
for room_event_data in room_events_data:
if room_event_data:
event = events.make(room_event_data, self._client)
self._client._recently_gotten_objects.appendleft(event)
yield event

def new_events(self, types=events.Event):
raise NotImplementedError()
events = FilteredEventIterator()

self.watch_socket()

return events
return FilteredEventIterator(self, types)

def new_messages(self):
raise NotImplementedError()
return MessageIterator(self)


class FilteredEventIterator(object):
pass
def __init__(self, room, types):
self.types = types
self._queue = Queue.Queue()

room.join()
self._watcher = room.watch(self._on_event)

def __enter__(self):
return self

def __exit__(self, exc_type, exc_value, tracback):
self._watcher.close()

def __iter__(self):
while True:
yield self._queue.get()

def _on_event(self, event, client):
if isinstance(event, self.types):
self._queue.put(event)


class MessageIterator(object):
pass
def __init__(self, room):
self._event_iter = FilteredEventIterator(room, events.MessagePosted)

def __enter__(self):
return self

def __exit__(self, exc_type, exc_value, tracback):
self._event_iter._watcher.close()

def __iter__(self):
for event in self._event_iter:
yield event.message

def _on_event(self, event, client):
return self._event_iter._on_event(event)
4 changes: 1 addition & 3 deletions examples/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ def main():
if 'ChatExchangeU' in os.environ:
email = os.environ['ChatExchangeU']
else:
sys.stderr.write("Username: ")
sys.stderr.flush()
email = raw_input()
email = raw_input("Email: ")
if 'ChatExchangeP' in os.environ:
password = os.environ['ChatExchangeP']
else:
Expand Down
21 changes: 14 additions & 7 deletions examples/hello_world.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
#!/usr/bin/env python
from getpass import getpass
import getpass
import logging
import os

import chatexchange
from chatexchange.events import MessageEdited


logging.basicConfig(level=logging.DEBUG)

email = raw_input('Email: ')
password = getpass()
if 'ChatExchangeU' in os.environ:
email = os.environ['ChatExchangeU']
else:
email = raw_input("Email: ")
if 'ChatExchangeP' in os.environ:
password = os.environ['ChatExchangeP']
else:
password = getpass.getpass("Password: ")
client = chatexchange.Client('stackexchange.com', email, password)

me = client.get_me()
sandbox = client.get_room(11540)
sandbox = client.get_room(14219)
my_message = None

with sandbox.messages() as messages:
sandbox._send_message("hello worl")
with sandbox.new_messages() as messages:
sandbox.send_message("hello worl")

for message in messages:
if message.owner is me:
Expand All @@ -26,7 +33,7 @@
print "message sent successfully"
break

with sandbox.events(MessageEdited) as edits:
with sandbox.new_events(MessageEdited) as edits:
my_message.edit("hello world")

for edit in edits:
Expand Down
2 changes: 1 addition & 1 deletion examples/web_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def get_state(self):
'name': self.room.name
},
'recent_events':
map(str, self.client.recent_events),
map(str, self.client._recently_gotten_objects),
'messages': [{
'id': message.id,
'owner_user_id': message.owner.id,
Expand Down
11 changes: 7 additions & 4 deletions test/test_rooms.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import pytest
import logging

import chatexchange
from chatexchange.events import MessageEdited

import live_testing


logger = logging.getLogger(__name__)


if live_testing.enabled:
def test_room_info():
client = chatexchange.Client('stackexchange.com')
Expand All @@ -25,8 +28,6 @@ def test_room_info():
sandbox.text_description
sandbox.parent_site_name + sandbox.name

@pytest.mark.timeout(60)
@pytest.mark.xfail(reason="event iterators not yet implemented")
def test_room_iterators():
client = chatexchange.Client(
'stackexchange.com', live_testing.email, live_testing.password)
Expand All @@ -37,13 +38,15 @@ def test_room_iterators():
my_message = None

with sandbox.new_messages() as messages:
sandbox._send_message("hello worl")
sandbox.send_message("hello worl")

for message in messages:
if message.owner is me:
my_message = message
assert my_message.content == "hello worl"
break
else:
logger.info("ignoring message: %r", message)

with sandbox.new_events(MessageEdited) as edits:
my_message.edit("hello world")
Expand Down

0 comments on commit 54cca16

Please sign in to comment.