Permalink
Browse files

refactored plugin resolver to handle session plugins

  • Loading branch information...
1 parent a451dc4 commit 955663dca50db076efbc84d5a3ed1d3f8bb50728 @igorsobreira committed Sep 21, 2010
Showing with 162 additions and 26 deletions.
  1. +65 −14 eizzek/lib/resolver.py
  2. +97 −12 tests/functional/test_resolver.py
View
79 eizzek/lib/resolver.py
@@ -1,18 +1,47 @@
-from eizzek.lib.registry import registry
+from eizzek.lib.registry import registry, session_registry
+from eizzek.lib.persistence import session
class PluginResolver(object):
'''
- This has a way to find and call plugins.
+ The way to find and call plugins.
'''
- def resolve(self, string, connection_data):
+ def resolve(self, message, connection_data):
'''
- Returns the result of a plugin call. ``string`` is the
+ Returns the result of a plugin call. ``message`` is the
message body received by the bot.
- Raises ``LookupError`` if the plugin is not found.
+ Searches for simple plugins then session plugins. If a simple
+ plugin is found just call the callable passing the connection
+ dict and arguments from the regex.
+
+ If a session plugin is found verify if the session is
+ open, if it is, call the ``handle()`` method of the plugin passing
+ the connection dict and the raw message received.
+ If the session is not open yet, open it and call the ``begin()`` method
+ passing the connection dict and arguments from the regex.
+
+ Raises ``LookupError`` if no plugin is not found.
+
+ '''
+ try:
+ return self._resolve_simple_plugin(message, connection_data)
+ except LookupError:
+ return self._resolve_session_plugin(message, connection_data)
+
+ def handle_session_plugin(self, message, connection_data):
'''
- func, match = self.find(string)
+ This method is called when a new message arrives and there is
+ an open session for the JID.
+ '''
+ jid = connection_data['message']['from']
+ plugin_name = session.get_current(jid)['plugin']
+ _, plugin_class = session_registry.plugins[plugin_name]
+ plugin = plugin_class()
+ return plugin.handle(connection_data, message)
+
+ def _resolve_simple_plugin(self, message, connection_data):
+ func, match = self.find(message, registry)
kwargs = self._clear_kwargs(match.groupdict())
if kwargs:
@@ -24,19 +53,41 @@ def resolve(self, string, connection_data):
return func(connection_data)
- def find(self, string):
- '''
- Returns a tuple: the plugin callable and the match result object.
- ``string`` is the message body received by the bot.
+ def _resolve_session_plugin(self, message, connection_data):
+ klass, match = self.find(message, session_registry)
+ plugin = klass()
+ jid = connection_data.get('message',{}).get('from', '')
+
+ if session.is_open(jid):
+ session.end(jid)
+
+ session.begin(jid, plugin.name)
- Raises ``LookupError`` if the plugin is not found.
+ kwargs = self._clear_kwargs(match.groupdict())
+ if kwargs:
+ return plugin.begin(connection_data, **kwargs)
+
+ args = self._clear_args(match.groups())
+ if args:
+ return plugin.begin(connection_data, *args)
+
+ return plugin.begin(connection_data)
+
+ def find(self, message, registry):
+ '''
+ Searches for a plugin in ``registry`` trying to match on each
+ regex. If found, returns a tuple (callable_obj, match). Else,
+ raises ``LookupError``.
+
+ Where ``message`` is the message body received by the bot.
+
'''
- for name, (regex, func) in registry.plugins.items():
- match = regex.match(string)
+ for name, (regex, callable_obj) in registry.plugins.items():
+ match = regex.match(message)
if match: break
else:
raise LookupError(u"Plugin not found")
- return func, match
+ return callable_obj, match
def _clear_kwargs(self, kwargs):
''' Don't pass parameters where the value is None '''
View
109 tests/functional/test_resolver.py
@@ -1,12 +1,28 @@
import unittest
+import redis
-from eizzek import PluginResolver, plugin, registry
+from eizzek import config, PluginResolver, plugin, session_plugin, registry, session_registry
+from eizzek.lib.persistence import SessionPersistence
class PluginResolverTest(unittest.TestCase):
+ def __init__(self, *args, **kwargs):
+ unittest.TestCase.__init__(self, *args, **kwargs)
+ self._redis = redis.Redis(host=config.REDIS_HOST, port=config.REDIS_PORT, db=config.REDIS_DB)
+ self.session = SessionPersistence()
+
def setUp(self):
registry.clear()
-
+ session_registry.clear()
+ self._create_simple_plugins()
+ self._create_session_plugins()
+ self.resolver = PluginResolver()
+
+ self.jid = 'igor@igorsobreira.com/Adium1234'
+ self.conn_data = {'message': {'from': self.jid}}
+ self._redis.hdel(self.jid, 'plugin')
+
+ def _create_simple_plugins(self):
@plugin(r"age (\d+)")
def age(conn, num):
return "you're %d" % int(num)
@@ -18,38 +34,107 @@ def age_default(conn, num=0):
@plugin(r"hello ?(?P<name>\w+)?")
def hello(conn, name='stranger'):
return "hello %s" % name
+
+ def _create_session_plugins(self):
+ @session_plugin
+ class Translate(object):
+ name = 'translate'
+ regex = '^translate (?P<from_lang>[\w-]+) (?P<to_lang>[\w-]+)$'
+
+ def begin(self, conn, from_lang, to_lang):
+ return u"translating from %s to %s" % (from_lang, to_lang)
+
+ def handle(self, conn, msg):
+ return u"qual o seu nome?"
+
+ @session_plugin
+ class Twitter(object):
+ name = 'twitter'
+ regex = '^twitter (\w+)$'
+
+ def begin(self, conn, account):
+ return u"twitter account @%s" % account
+
+ def handle(self, conn, msg):
+ return u"message: '%s'" % msg
+
+ @session_plugin
+ class DummyPlugin(object):
+ name = 'dummy'
+ regex = r'^dummy$'
+
+ def begin(self, conn):
+ return u"I'm dummy"
+
+ def handle(self, conn, msg):
+ return "message: '%s'" % msg
+
+ # tests for simple plugins
- self.resolver = PluginResolver()
-
def test_dont_find_plugin(self):
try:
- self.resolver.resolve("no plugin", {})
+ self.resolver.resolve("no plugin", self.conn_data)
assert 0, u"Shouldn't find any plugin"
except LookupError:
pass
def test_call_plugin_with_args(self):
- result = self.resolver.resolve('age 22', {})
+ result = self.resolver.resolve('age 22', self.conn_data)
assert u"you're 22" == result
def test_call_plugin_with_kwargs(self):
- result = self.resolver.resolve('hello igor', {})
+ result = self.resolver.resolve('hello igor', self.conn_data)
assert u"hello igor" == result
def test_call_plugin_with_kwargs_and_default_argument(self):
- result = self.resolver.resolve('hello', {})
+ result = self.resolver.resolve('hello', self.conn_data)
assert u"hello stranger" == result
def test_call_plugin_with_args_and_default_argument(self):
- result = self.resolver.resolve('aged', {})
+ result = self.resolver.resolve('aged', self.conn_data)
assert "you're 0"
+
+ # tests for session plugins
+
+ def test_session_plugin_with_kwargs(self):
+ result = self.resolver.resolve('twitter igorsobreira', self.conn_data)
+
+ assert u"twitter account @igorsobreira" == result
+
+ def test_session_plugin_with_kwargs(self):
+ result = self.resolver.resolve('translate en pt-br', self.conn_data)
+
+ assert u"translating from en to pt-br" == result
+
+ def test_session_plugin_with_no_arguments(self):
+ result = self.resolver.resolve('dummy', self.conn_data)
+
+ assert u"I'm dummy" == result
- def test_find_callable_function(self):
- func, _ = self.resolver.find('age 22')
+ def test_session_plugin_starts_session(self):
+ result = self.resolver.resolve('translate en pt-br', self.conn_data)
+
+ assert u"translating from en to pt-br" == result
+ assert u"translate" == self._redis.hget(self.jid, 'plugin')
+
+ def test_trying_to_start_two_sessions_closes_the_first_one(self):
+ result = self.resolver.resolve('translate en pt-br', self.conn_data)
+
+ assert u"translating from en to pt-br" == result
+ assert u"translate" == self._redis.hget(self.jid, 'plugin')
- assert 'age' == func.__name__
+ result = self.resolver.resolve('twitter igorsobreira', self.conn_data)
+
+ assert u"twitter account @igorsobreira" == result
+ assert u"twitter" == self._redis.hget(self.jid, 'plugin')
+
+ def test_handle_session_plugin_should_call_handle_method_of_the_plugin(self):
+ self.resolver.resolve('translate en pt-br', self.conn_data)
+ result = self.resolver.handle_session_plugin("what's your name?", self.conn_data)
+
+ assert u"qual o seu nome?" == result

0 comments on commit 955663d

Please sign in to comment.