commit
50c7ab6c6e
|
@ -596,24 +596,26 @@ class MycroftSkill(object):
|
|||
text = f.read().replace('{{', '{').replace('}}', '}')
|
||||
return text.format(**data or {}).split('\n')
|
||||
|
||||
def add_event(self, name, handler, need_self=False):
|
||||
def add_event(self, name, handler, need_self=False, once=False):
|
||||
"""
|
||||
Create event handler for executing intent
|
||||
|
||||
Args:
|
||||
name: IntentParser name
|
||||
handler: method to call
|
||||
need_self: optional parameter, when called from a decorated
|
||||
intent handler the function will need the self
|
||||
variable passed as well.
|
||||
need_self: optional parameter, when called from a decorated
|
||||
intent handler the function will need the self
|
||||
variable passed as well.
|
||||
once: optional parameter, Event handler will be removed
|
||||
after it has been run once.
|
||||
"""
|
||||
|
||||
def wrapper(message):
|
||||
try:
|
||||
# Indicate that the skill handler is starting
|
||||
name = get_handler_name(handler)
|
||||
handler_name = get_handler_name(handler)
|
||||
self.emitter.emit(Message("mycroft.skill.handler.start",
|
||||
data={'handler': name}))
|
||||
data={'handler': handler_name}))
|
||||
|
||||
stopwatch = Stopwatch()
|
||||
with stopwatch:
|
||||
|
@ -653,24 +655,29 @@ class MycroftSkill(object):
|
|||
|
||||
except Exception as e:
|
||||
# Convert "MyFancySkill" to "My Fancy Skill" for speaking
|
||||
name = re.sub("([a-z])([A-Z])", "\g<1> \g<2>", self.name)
|
||||
handler_name = re.sub("([a-z])([A-Z])", "\g<1> \g<2>",
|
||||
self.name)
|
||||
# TODO: Localize
|
||||
self.speak(
|
||||
"An error occurred while processing a request in " +
|
||||
name)
|
||||
self.speak("An error occurred while processing a request in " +
|
||||
handler_name)
|
||||
LOG.error(
|
||||
"An error occurred while processing a request in " +
|
||||
self.name, exc_info=True)
|
||||
# indicate completion with exception
|
||||
self.emitter.emit(Message('mycroft.skill.handler.complete',
|
||||
data={'handler': name,
|
||||
data={'handler': handler_name,
|
||||
'exception': e.message}))
|
||||
# Indicate that the skill handler has completed
|
||||
self.emitter.emit(Message('mycroft.skill.handler.complete',
|
||||
data={'handler': name}))
|
||||
data={'handler': handler_name}))
|
||||
if once:
|
||||
self.remove_event(name)
|
||||
|
||||
if handler:
|
||||
self.emitter.on(name, wrapper)
|
||||
if once:
|
||||
self.emitter.once(name, wrapper)
|
||||
else:
|
||||
self.emitter.on(name, wrapper)
|
||||
self.events.append((name, wrapper))
|
||||
|
||||
def remove_event(self, name):
|
||||
|
@ -682,8 +689,15 @@ class MycroftSkill(object):
|
|||
"""
|
||||
for _name, _handler in self.events:
|
||||
if name == _name:
|
||||
self.events.remove((_name, _handler))
|
||||
self.emitter.remove(_name, _handler)
|
||||
try:
|
||||
self.events.remove((_name, _handler))
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
self.emitter.remove(_name, _handler)
|
||||
except ValueError:
|
||||
LOG.debug('{} is not registered in the emitter'.format(
|
||||
_name))
|
||||
|
||||
def register_intent(self, intent_parser, handler, need_self=False):
|
||||
"""
|
||||
|
@ -946,12 +960,12 @@ class MycroftSkill(object):
|
|||
Underlying method for schedle_event and schedule_repeating_event.
|
||||
Takes scheduling information and sends it of on the message bus.
|
||||
"""
|
||||
data = data or {}
|
||||
if not name:
|
||||
name = self.name + handler.__name__
|
||||
name = self._unique_name(name)
|
||||
|
||||
self.add_event(name, handler, False)
|
||||
data = data or {}
|
||||
self.add_event(name, handler, once=not repeat)
|
||||
event_data = {}
|
||||
event_data['time'] = time.mktime(when.timetuple())
|
||||
event_data['event'] = name
|
||||
|
|
|
@ -20,6 +20,7 @@ import mock
|
|||
from adapt.intent import IntentBuilder
|
||||
from os.path import join, dirname, abspath
|
||||
from re import error
|
||||
from datetime import datetime
|
||||
|
||||
from mycroft.configuration import Configuration
|
||||
from mycroft.messagebus.message import Message
|
||||
|
@ -399,15 +400,108 @@ class MycroftSkillTest(unittest.TestCase):
|
|||
self.assertEqual(s.location_pretty, None)
|
||||
self.assertEqual(s.location_timezone, None)
|
||||
|
||||
@mock.patch.object(Configuration, 'get')
|
||||
def test_add_event(self, mock_config_get):
|
||||
test_config = {
|
||||
'skills': {
|
||||
}
|
||||
}
|
||||
mock_config_get.return_value = test_config
|
||||
emitter = mock.MagicMock()
|
||||
s = TestSkill1()
|
||||
s.bind(emitter)
|
||||
s.add_event('handler1', s.handler)
|
||||
# Check that the handler was registered with the emitter
|
||||
self.assertEqual(emitter.on.call_args[0][0], 'handler1')
|
||||
# Check that the handler was stored in the skill
|
||||
self.assertTrue('handler1' in zip(*s.events)[0])
|
||||
|
||||
@mock.patch.object(Configuration, 'get')
|
||||
def test_remove_event(self, mock_config_get):
|
||||
test_config = {
|
||||
'skills': {
|
||||
}
|
||||
}
|
||||
mock_config_get.return_value = test_config
|
||||
emitter = mock.MagicMock()
|
||||
s = TestSkill1()
|
||||
s.bind(emitter)
|
||||
s.add_event('handler1', s.handler)
|
||||
self.assertTrue('handler1' in zip(*s.events)[0])
|
||||
# Remove event handler
|
||||
s.remove_event('handler1')
|
||||
# make sure it's not in the event list anymore
|
||||
self.assertTrue('handler1' not in zip(*s.events)[0])
|
||||
# Check that the handler was registered with the emitter
|
||||
self.assertEqual(emitter.remove.call_args[0][0], 'handler1')
|
||||
|
||||
@mock.patch.object(Configuration, 'get')
|
||||
def test_add_scheduled_event(self, mock_config_get):
|
||||
test_config = {
|
||||
'skills': {
|
||||
}
|
||||
}
|
||||
mock_config_get.return_value = test_config
|
||||
emitter = mock.MagicMock()
|
||||
s = TestSkill1()
|
||||
s.bind(emitter)
|
||||
s.schedule_event(s.handler, datetime.now(), name='sched_handler1')
|
||||
# Check that the handler was registered with the emitter
|
||||
self.assertEqual(emitter.once.call_args[0][0], '0:sched_handler1')
|
||||
self.assertTrue('0:sched_handler1' in zip(*s.events)[0])
|
||||
|
||||
@mock.patch.object(Configuration, 'get')
|
||||
def test_remove_scheduled_event(self, mock_config_get):
|
||||
test_config = {
|
||||
'skills': {
|
||||
}
|
||||
}
|
||||
mock_config_get.return_value = test_config
|
||||
emitter = mock.MagicMock()
|
||||
s = TestSkill1()
|
||||
s.bind(emitter)
|
||||
s.schedule_event(s.handler, datetime.now(), name='sched_handler1')
|
||||
# Check that the handler was registered with the emitter
|
||||
self.assertTrue('0:sched_handler1' in zip(*s.events)[0])
|
||||
s.cancel_scheduled_event('sched_handler1')
|
||||
# Check that the handler was removed
|
||||
self.assertEqual(emitter.remove.call_args[0][0], '0:sched_handler1')
|
||||
self.assertTrue('0:sched_handler1' not in zip(*s.events)[0])
|
||||
|
||||
@mock.patch.object(Configuration, 'get')
|
||||
def test_run_scheduled_event(self, mock_config_get):
|
||||
test_config = {
|
||||
'skills': {
|
||||
}
|
||||
}
|
||||
mock_config_get.return_value = test_config
|
||||
emitter = mock.MagicMock()
|
||||
s = TestSkill1()
|
||||
with mock.patch.object(s, '_settings',
|
||||
create=True, value=mock.MagicMock()):
|
||||
s.bind(emitter)
|
||||
s.schedule_event(s.handler, datetime.now(), name='sched_handler1')
|
||||
# Check that the handler was registered with the emitter
|
||||
emitter.once.call_args[0][1](Message('message'))
|
||||
# Check that the handler was run
|
||||
self.assertTrue(s.handler_run)
|
||||
# Check that the handler was removed from the list of registred
|
||||
# handler
|
||||
self.assertTrue('0:sched_handler1' not in zip(*s.events)[0])
|
||||
|
||||
|
||||
class TestSkill1(MycroftSkill):
|
||||
def __init__(self):
|
||||
super(TestSkill1, self).__init__()
|
||||
self.handler_run = False
|
||||
|
||||
""" Test skill for normal intent builder syntax """
|
||||
def initialize(self):
|
||||
i = IntentBuilder('a').require('Keyword').build()
|
||||
self.register_intent(i, self.handler)
|
||||
|
||||
def handler(self, message):
|
||||
pass
|
||||
self.handler_run = True
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue