import copy
import functools
from tests import unittest
from functools import partial
from botocore.hooks import HierarchicalEmitter, first_non_none_response
class TestHierarchicalEventEmitter(unittest.TestCase):
def setUp(self):
self.emitter = HierarchicalEmitter()
self.hook_calls = []
def hook(self, **kwargs):
self.hook_calls.append(kwargs)
def test_non_dot_behavior(self):
self.emitter.register('no-dot', self.hook)
self.emitter.emit('no-dot')
self.assertEqual(len(self.hook_calls), 1)
def test_with_dots(self):
self.emitter.register('foo.bar.baz', self.hook)
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 1)
def test_catch_all_hook(self):
self.emitter.register('foo', self.hook)
self.emitter.register('foo.bar', self.hook)
self.emitter.register('foo.bar.baz', self.hook)
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 3, self.hook_calls)
self.assertEqual([e['event_name'] for e in self.hook_calls],
['foo.bar.baz', 'foo.bar.baz', 'foo.bar.baz'])
def test_hook_called_in_proper_order(self):
calls = []
self.emitter.register('foo', lambda **kwargs: calls.append('foo'))
self.emitter.register('foo.bar',
lambda **kwargs: calls.append('foo.bar'))
self.emitter.register('foo.bar.baz',
lambda **kwargs: calls.append('foo.bar.baz'))
self.emitter.emit('foo.bar.baz')
self.assertEqual(calls, ['foo.bar.baz', 'foo.bar', 'foo'])
class TestStopProcessing(unittest.TestCase):
def setUp(self):
self.emitter = HierarchicalEmitter()
self.hook_calls = []
def hook1(self, **kwargs):
self.hook_calls.append('hook1')
def hook2(self, **kwargs):
self.hook_calls.append('hook2')
return 'hook2-response'
def hook3(self, **kwargs):
self.hook_calls.append('hook3')
return 'hook3-response'
def test_all_hooks(self):
self.emitter.register('foo', self.hook1)
self.emitter.register('foo', self.hook2)
self.emitter.register('foo', self.hook3)
self.emitter.emit('foo')
self.assertEqual(self.hook_calls, ['hook1', 'hook2', 'hook3'])
def test_stop_processing_after_first_response(self):
self.emitter.register('foo', self.hook1)
self.emitter.register('foo', self.hook2)
self.emitter.register('foo', self.hook3)
handler, response = self.emitter.emit_until_response('foo')
self.assertEqual(response, 'hook2-response')
self.assertEqual(self.hook_calls, ['hook1', 'hook2'])
def test_no_responses(self):
self.emitter.register('foo', self.hook1)
responses = self.emitter.emit('foo')
self.assertEqual(self.hook_calls, ['hook1'])
self.assertEqual(responses, [(self.hook1, None)])
def test_no_handlers(self):
handler, response = self.emitter.emit_until_response('foo')
self.assertIsNone(handler)
self.assertIsNone(response)
class TestFirstNonNoneResponse(unittest.TestCase):
def test_all_none(self):
self.assertIsNone(first_non_none_response([]))
def test_first_non_none(self):
correct_value = 'correct_value'
wrong_value = 'wrong_value'
responses = [(None, None), (None, correct_value), (None, wrong_value)]
self.assertEqual(first_non_none_response(responses), correct_value)
def test_default_value_if_non_none_found(self):
responses = [(None, None), (None, None)]
self.assertEqual(
first_non_none_response(responses, default='notfound'), 'notfound')
class TestWildcardHandlers(unittest.TestCase):
def setUp(self):
self.emitter = HierarchicalEmitter()
self.hook_calls = []
def hook(self, **kwargs):
self.hook_calls.append(kwargs)
def register(self, event_name):
func = partial(self.hook, registered_with=event_name)
self.emitter.register(event_name, func)
return func
def assert_hook_is_called_given_event(self, event):
starting = len(self.hook_calls)
self.emitter.emit(event)
after = len(self.hook_calls)
if not after > starting:
self.fail("Handler was not called for event: %s" % event)
self.assertEqual(self.hook_calls[-1]['event_name'], event)
def assert_hook_is_not_called_given_event(self, event):
starting = len(self.hook_calls)
self.emitter.emit(event)
after = len(self.hook_calls)
if not after == starting:
self.fail("Handler was called for event but was not "
"suppose to be called: %s, last_event: %s" %
(event, self.hook_calls[-1]))
def test_one_level_wildcard_handler(self):
self.emitter.register('foo.*.baz', self.hook)
self.emitter.register('other.bar.baz', self.hook)
self.emitter.register('qqq.baz', self.hook)
self.emitter.register('dont.call.me', self.hook)
self.emitter.register('dont', self.hook)
self.assert_hook_is_called_given_event('foo.bar.baz')
self.assert_hook_is_called_given_event('foo.qux.baz')
self.assert_hook_is_called_given_event('foo.anything.baz')
self.assert_hook_is_not_called_given_event('foo')
self.assert_hook_is_not_called_given_event('foo.bar')
self.assert_hook_is_not_called_given_event('bar.qux.baz')
self.assert_hook_is_not_called_given_event('foo-bar')
def test_hierarchical_wildcard_handler(self):
self.emitter.register('foo.*.baz', self.hook)
self.assert_hook_is_called_given_event('foo.bar.baz.qux')
self.assert_hook_is_called_given_event('foo.bar.baz.qux.foo')
self.assert_hook_is_called_given_event('foo.qux.baz.qux')
self.assert_hook_is_called_given_event('foo.qux.baz.qux.foo')
self.assert_hook_is_not_called_given_event('bar.qux.baz.foo')
def test_multiple_wildcard_events(self):
self.emitter.register('foo.*.*.baz', self.hook)
self.assert_hook_is_called_given_event('foo.bar.baz.baz')
self.assert_hook_is_called_given_event('foo.ANY.THING.baz')
self.assert_hook_is_called_given_event('foo.AT.ALL.baz')
self.assert_hook_is_called_given_event('foo.bar.baz.baz.extra')
self.assert_hook_is_called_given_event('foo.bar.baz.baz.extra.stuff')
self.assert_hook_is_not_called_given_event('foo')
self.assert_hook_is_not_called_given_event('foo.bar')
self.assert_hook_is_not_called_given_event('foo.bar.baz')
self.assert_hook_is_not_called_given_event('foo.ANY.THING.notbaz')
self.assert_hook_is_not_called_given_event('foo.ANY.THING.stillnotbaz')
def test_can_unregister_for_wildcard_events(self):
self.emitter.register('foo.*.*.baz', self.hook)
self.assert_hook_is_called_given_event('foo.bar.baz.baz')
self.assert_hook_is_called_given_event('foo.bar.baz.baz')
self.assert_hook_is_called_given_event('foo.bar.baz.baz')
self.emitter.unregister('foo.*.*.baz', self.hook)
self.assert_hook_is_not_called_given_event('foo.bar.baz.baz')
self.assert_hook_is_not_called_given_event('foo.bar.baz.baz')
self.assert_hook_is_not_called_given_event('foo.bar.baz.baz')
self.emitter.register('foo.*.*.baz', self.hook)
self.assert_hook_is_called_given_event('foo.bar.baz.baz')
self.assert_hook_is_called_given_event('foo.bar.baz.baz')
def test_unregister_does_not_exist(self):
self.emitter.register('foo.*.*.baz', self.hook)
self.emitter.unregister('foo.*.*.baz', self.hook)
self.emitter.unregister('foo.*.*.baz', self.hook)
self.assert_hook_is_not_called_given_event('foo.bar.baz.baz')
def test_cache_cleared_properly(self):
self.emitter.register('foo.*.*.baz', self.hook)
self.assert_hook_is_called_given_event('foo.bar.baz.baz')
self.emitter.register('foo.*.*.bar', self.hook)
self.assert_hook_is_called_given_event('foo.bar.baz.baz')
self.assert_hook_is_called_given_event('foo.bar.baz.bar')
self.emitter.unregister('foo.*.*.baz', self.hook)
self.assert_hook_is_called_given_event('foo.bar.baz.bar')
self.assert_hook_is_not_called_given_event('foo.bar.baz.baz')
def test_complicated_register_unregister(self):
r = self.emitter.register
u = partial(self.emitter.unregister, handler=self.hook)
r('foo.bar.baz.qux', self.hook)
r('foo.bar.baz', self.hook)
r('foo.bar', self.hook)
r('foo', self.hook)
u('foo.bar.baz')
u('foo')
u('foo.bar')
self.assert_hook_is_called_given_event('foo.bar.baz.qux')
self.assert_hook_is_not_called_given_event('foo.bar.baz')
self.assert_hook_is_not_called_given_event('foo.bar')
self.assert_hook_is_not_called_given_event('foo')
def test_register_multiple_handlers_for_same_event(self):
self.emitter.register('foo.bar.baz', self.hook)
self.emitter.register('foo.bar.baz', self.hook)
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 2)
def test_register_with_unique_id(self):
self.emitter.register('foo.bar.baz', self.hook, unique_id='foo')
self.emitter.register('foo.bar.baz', self.hook, unique_id='foo')
self.emitter.register('foo.other', self.hook, unique_id='foo')
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 1)
self.hook_calls = []
self.emitter.emit('foo.other')
self.assertEqual(len(self.hook_calls), 0)
def test_remove_handler_with_unique_id(self):
hook2 = lambda **kwargs: self.hook_calls.append(kwargs)
self.emitter.register('foo.bar.baz', self.hook, unique_id='foo')
self.emitter.register('foo.bar.baz', hook2)
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 2)
self.hook_calls = []
self.emitter.unregister('foo.bar.baz', hook2)
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 1)
self.hook_calls = []
self.emitter.unregister('foo.bar.baz', unique_id='foo')
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 0)
self.emitter.unregister('foo.bar.baz', unique_id='foo')
def test_remove_handler_with_and_without_unique_id(self):
self.emitter.register('foo.bar.baz', self.hook, unique_id='foo')
self.emitter.register('foo.bar.baz', self.hook)
self.emitter.unregister('foo.bar.baz', self.hook)
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 1)
self.hook_calls = []
self.emitter.unregister('foo.bar.baz', self.hook)
self.emitter.emit('foo.bar.baz')
self.assertEqual(len(self.hook_calls), 0)
def test_register_with_uses_count_initially(self):
self.emitter.register('foo', self.hook, unique_id='foo',
unique_id_uses_count=True)
with self.assertRaises(ValueError):
self.emitter.register('foo', self.hook, unique_id='foo')
def test_register_with_uses_count_not_initially(self):
self.emitter.register('foo', self.hook, unique_id='foo')
with self.assertRaises(ValueError):
self.emitter.register('foo', self.hook, unique_id='foo',
unique_id_uses_count=True)
def test_register_with_uses_count_unregister(self):
self.emitter.register('foo', self.hook, unique_id='foo',
unique_id_uses_count=True)
self.emitter.register('foo', self.hook, unique_id='foo',
unique_id_uses_count=True)
with self.assertRaises(ValueError):
self.emitter.unregister('foo', self.hook, unique_id='foo')
self.emitter.emit('foo')
self.assertEqual(len(self.hook_calls), 1)
self.emitter.unregister('foo', self.hook, unique_id='foo',
unique_id_uses_count=True)
self.hook_calls = []
self.emitter.emit('foo')
self.assertEqual(len(self.hook_calls), 1)
self.emitter.unregister('foo', self.hook, unique_id='foo',
unique_id_uses_count=True)
self.hook_calls = []
self.emitter.emit('foo')
self.assertEqual(len(self.hook_calls), 0)
def test_register_with_no_uses_count_unregister(self):
self.emitter.register('foo', self.hook, unique_id='foo')
with self.assertRaises(ValueError):
self.emitter.unregister('foo', self.hook, unique_id='foo',
unique_id_uses_count=True)
def test_handlers_called_in_order(self):
def handler(call_number, **kwargs):
kwargs['call_number'] = call_number
self.hook_calls.append(kwargs)
self.emitter.register('foo', partial(handler, call_number=1))
self.emitter.register('foo', partial(handler, call_number=2))
self.emitter.emit('foo')
self.assertEqual([k['call_number'] for k in self.hook_calls],
[1, 2])
def test_handler_call_order_with_hierarchy(self):
def handler(call_number, **kwargs):
kwargs['call_number'] = call_number
self.hook_calls.append(kwargs)
self.emitter.register('foo.bar.baz', partial(handler, call_number=1))
self.emitter.register('foo.bar', partial(handler, call_number=3))
self.emitter.register('foo', partial(handler, call_number=5))
self.emitter.register('foo.bar.baz', partial(handler, call_number=2))
self.emitter.register('foo.bar', partial(handler, call_number=4))
self.emitter.register('foo', partial(handler, call_number=6))
self.emitter.emit('foo.bar.baz')
self.assertEqual([k['call_number'] for k in self.hook_calls],
[1, 2, 3, 4, 5, 6])
def test_register_first_single_level(self):
def handler(call_number, **kwargs):
kwargs['call_number'] = call_number
self.hook_calls.append(kwargs)
self.emitter.register('foo', partial(handler, call_number=3))
self.emitter.register('foo', partial(handler, call_number=4))
self.emitter.register_first('foo', partial(handler, call_number=1))
self.emitter.register_first('foo', partial(handler, call_number=2))
self.emitter.register('foo', partial(handler, call_number=5))
self.emitter.emit('foo')
self.assertEqual([k['call_number'] for k in self.hook_calls],
[1, 2, 3, 4, 5])
def test_register_first_hierarchy(self):
def handler(call_number, **kwargs):
kwargs['call_number'] = call_number
self.hook_calls.append(kwargs)
self.emitter.register('foo', partial(handler, call_number=5))
self.emitter.register('foo.bar', partial(handler, call_number=2))
self.emitter.register_first('foo', partial(handler, call_number=4))
self.emitter.register_first('foo.bar', partial(handler, call_number=1))
self.emitter.register('foo', partial(handler, call_number=6))
self.emitter.register('foo.bar', partial(handler, call_number=3))
self.emitter.emit('foo.bar')
self.assertEqual([k['call_number'] for k in self.hook_calls],
[1, 2, 3, 4, 5, 6])
def test_register_last_hierarchy(self):
def handler(call_number, **kwargs):
kwargs['call_number'] = call_number
self.hook_calls.append(kwargs)
self.emitter.register_last('foo', partial(handler, call_number=3))
self.emitter.register('foo', partial(handler, call_number=2))
self.emitter.register_first('foo', partial(handler, call_number=1))
self.emitter.emit('foo')
self.assertEqual([k['call_number'] for k in self.hook_calls],
[1, 2, 3])
def test_register_unregister_first_last(self):
self.emitter.register('foo', self.hook)
self.emitter.register_last('foo.bar', self.hook)
self.emitter.register_first('foo.bar.baz', self.hook)
self.emitter.unregister('foo.bar.baz', self.hook)
self.emitter.unregister('foo.bar', self.hook)
self.emitter.unregister('foo', self.hook)
self.emitter.emit('foo')
self.assertEqual(self.hook_calls, [])
def test_copy_emitter(self):
first = []
def first_handler(id_name, **kwargs):
first.append(id_name)
second = []
def second_handler(id_name, **kwargs):
second.append(id_name)
self.emitter.register('foo.bar.baz', first_handler)
self.emitter.emit('foo.bar.baz', id_name='first-time')
self.assertEqual(first, ['first-time'])
self.assertEqual(second, [])
copied_emitter = copy.copy(self.emitter)
copied_emitter.emit('foo.bar.baz', id_name='second-time')
self.assertEqual(first, ['first-time', 'second-time'])
self.assertEqual(second, [])
copied_emitter.register('foo.bar.baz', second_handler)
copied_emitter.emit('foo.bar.baz', id_name='third-time')
self.assertEqual(first, ['first-time', 'second-time', 'third-time'])
self.assertEqual(second, ['third-time'])
self.emitter.unregister('foo.bar.baz', first_handler)
self.emitter.register('foo.bar.baz', first_handler)
self.emitter.emit('foo.bar.baz', id_name='last-time')
self.assertEqual(second, ['third-time'])
def test_copy_emitter_with_unique_id_event(self):
first = []
def first_handler(id_name, **kwargs):
first.append(id_name)
second = []
def second_handler(id_name, **kwargs):
second.append(id_name)
self.emitter.register('foo', first_handler, 'bar')
self.emitter.emit('foo', id_name='first-time')
self.assertEqual(first, ['first-time'])
self.assertEqual(second, [])
copied_emitter = copy.copy(self.emitter)
copied_emitter.register('foo', second_handler, 'bar')
copied_emitter.emit('foo', id_name='second-time')
self.assertEqual(first, ['first-time', 'second-time'])
self.assertEqual(second, [])
copied_emitter.unregister('foo', first_handler, 'bar')
copied_emitter.register('foo', second_handler, 'bar')
copied_emitter.emit('foo', id_name='third-time')
self.assertEqual(first, ['first-time', 'second-time'])
self.assertEqual(second, ['third-time'])
self.emitter.emit('foo', id_name='fourth-time')
self.assertEqual(first, ['first-time', 'second-time', 'fourth-time'])
self.assertEqual(second, ['third-time'])
def test_copy_events_with_partials(self):
def handler(a, b, **kwargs):
return b
f = functools.partial(handler, 1)
self.emitter.register('a.b', f)
copied = copy.copy(self.emitter)
self.assertEqual(copied.emit_until_response(
'a.b', b='return-val')[1], 'return-val')
if __name__ == '__main__':
unittest.main()