def test_reset_converse(self): """Check that a blank stt sends the reset signal to the skills.""" print(self.intent_service.active_skills) reset_msg = Message('mycroft.speech.recognition.unknown', data={'lang': 'en-US'}) t = Thread(target=self.intent_service.reset_converse, args=(reset_msg, )) t.start() time.sleep(0.5) self.intent_service.handle_converse_error( Message('converse.error', { 'skill_id': 'c64_skill', 'error': 'skill id does not exist' })) time.sleep(0.5) self.intent_service.handle_converse_response( Message('converse.response', { 'skill_id': 'atari_skill', 'result': False })) # Check send messages c64_message = self.intent_service.bus.emit.call_args_list[0][0][0] self.assertTrue(check_converse_request(c64_message, 'c64_skill')) atari_message = self.intent_service.bus.emit.call_args_list[1][0][0] self.assertTrue(check_converse_request(atari_message, 'atari_skill'))
def response(message, return_msg_type): c64 = Message(return_msg_type, {'skill_id': 'c64_skill', 'result': False}) atari = Message(return_msg_type, {'skill_id': 'atari_skill', 'result': True}) msgs = {'c64_skill': c64, 'atari_skill': atari} return msgs[message.data['skill_id']]
def initialize(self): """ Perform any final setup needed for the skill here. This function is invoked after the skill is fully constructed and registered with the system. Intents will be registered and Skill settings will be available.""" my_setting = self.settings.get('my_setting') self.bus.emit(Message("test")) self.bus.emit(Message("test2"))
def test_play_internals(self, play_wav_mock, play_ogg_mock, play_mp3_mock): bus = mock.Mock() process_mock = mock.Mock(name='process') completed = False def wait_for_completion(): nonlocal completed if not completed: return None else: completed = False return True process_mock.poll.side_effect = wait_for_completion play_wav_mock.return_value = process_mock play_ogg_mock.return_value = process_mock play_mp3_mock.return_value = process_mock service = simple.SimpleAudioService(config, bus) tracks = ['a.mp3', ['b.ogg', 'audio/ogg'], ['c.wav', 'audio/wav']] service.add_list(tracks) service.play() thread = Thread(target=service._play, args=[Message('plaything')]) thread.daemon = True thread.start() time.sleep(0.1) play_mp3_mock.assert_called_with('a.mp3') completed = True time.sleep(1) self.assertEqual(service.index, 1) thread.join() thread = Thread(target=service._play, args=[Message('plaything')]) thread.daemon = True thread.start() time.sleep(0.1) play_ogg_mock.assert_called_with('b.ogg') service.pause() process_mock.send_signal.assert_called_with(signal.SIGSTOP) self.assertEqual(service._paused, True) service.resume() self.assertEqual(service._paused, False) completed = True thread.join() thread = Thread(target=service._play, args=[Message('plaything')]) thread.daemon = True thread.start() time.sleep(0.2) play_wav_mock.assert_called_with('c.wav') service.stop() thread.join()
def test_get_no_match_after_detach_skill(self): """Check that a removed skill's intent doesn't match.""" self.setup_simple_adapt_intent() # Check that no intent is matched msg = Message('detach_intent', data={'skill_id': 'skill'}) self.intent_service.handle_detach_skill(msg) msg = Message('intent.service.adapt.get', data={'utterance': 'test'}) self.intent_service.handle_get_adapt(msg) reply = get_last_message(self.intent_service.bus) self.assertEqual(reply.data['intent'], None)
def test_common_test_skill_action(self): """Test that the optional action is triggered.""" query_action = self.bus.on.call_args_list[-1][0][1] query_action(Message('query:action', data={ 'phrase': 'What\'s the meaning of life', 'skill_id': 'asdf'})) self.skill.CQS_action.assert_not_called() query_action(Message('query:action', data={ 'phrase': 'What\'s the meaning of life', 'skill_id': 'CQSTest'})) self.skill.CQS_action.assert_called_once_with( 'What\'s the meaning of life', None)
def response(message, return_msg_type): c64 = Message(return_msg_type, {'skill_id': 'c64_skill', 'result': False}) amiga = Message(return_msg_type, {'skill_id': 'amiga_skill', 'error': 'skill id does not exist'}) atari = Message(return_msg_type, {'skill_id': 'atari_skill', 'result': False}) msgs = {'c64_skill': c64, 'atari_skill': atari, 'amiga_skill': amiga} return msgs[message.data['skill_id']]
def test_stop(self, check_for_signal_mock, tts_factory_mock, config_mock): """Ensure the stop handler signals stop correctly.""" setup_mocks(config_mock, tts_factory_mock) bus = mock.Mock() config_mock.get.return_value = {'tts': {'module': 'test'}} speech.init(bus) speech._last_stop_signal = 0 check_for_signal_mock.return_value = False speech.handle_stop(Message('mycroft.stop')) self.assertEqual(speech._last_stop_signal, 0) check_for_signal_mock.return_value = True speech.handle_stop(Message('mycroft.stop')) self.assertNotEqual(speech._last_stop_signal, 0)
def _communicate_load_status(self): if self.loaded: message = Message('mycroft.skills.loaded', data=dict(path=self.skill_directory, id=self.skill_id, name=self.instance.name, modified=self.last_modified)) self.bus.emit(message) LOG.info('Skill {} loaded successfully'.format(self.skill_id)) else: message = Message('mycroft.skills.loading_failure', data=dict(path=self.skill_directory, id=self.skill_id)) self.bus.emit(message) LOG.error('Skill {} failed to load'.format(self.skill_id))
def setup_simple_adapt_intent(self): msg = create_vocab_msg('testKeyword', 'test') self.intent_service.handle_register_vocab(msg) intent = IntentBuilder('skill:testIntent').require('testKeyword') msg = Message('register_intent', intent.__dict__) self.intent_service.handle_register_intent(msg)
def before_all(context): log = create_voight_kampff_logger() bus = InterceptAllBusClient() bus_connected = Event() bus.once('open', bus_connected.set) create_daemon(bus.run_forever) context.msm = MycroftSkillsManager() # Wait for connection log.info('Waiting for messagebus connection...') bus_connected.wait() log.info('Waiting for skills to be loaded...') start = monotonic() while True: response = bus.wait_for_response(Message('mycroft.skills.all_loaded')) if response and response.data['status']: break elif monotonic() - start >= 2 * 60: raise Exception('Timeout waiting for skills to become ready.') else: sleep(1) context.bus = bus context.matched_message = None context.log = log
def test_get_adapt_intent_manifest(self): """Make sure the manifest returns a list of Intent Parser objects.""" self.setup_simple_adapt_intent() msg = Message('intent.service.adapt.manifest.get') self.intent_service.handle_adapt_manifest(msg) reply = get_last_message(self.intent_service.bus) self.assertEqual(reply.data['intents'][0]['name'], 'skill:testIntent')
def when_user_says(context, text): context.bus.emit(Message('recognizer_loop:utterance', data={'utterances': [text], 'lang': context.lang, 'session': '', 'ident': time.time()}, context={'client_name': 'mycroft_listener'}))
def deactivate_deprecated(self, message=None): # Deactivate official skill # TODO depending on https://github.com/MycroftAI/skill-speak/issues/24 # code bellow can be removed skills_config = self.config_core.get("skills", {}) blacklisted_skills = skills_config.get("blacklisted_skills", []) config = LocalConf(USER_CONFIG) blacklisted_skills += config.get("skills", {}).get("blacklisted_skills", []) store = False for skill in ["skill-repeat-recent", "mycroft-speak.mycroftai"]: if skill not in blacklisted_skills: self.log.info("Parrot skill blacklisted conflicting skill " + skill) self.bus.emit( Message('skillmanager.deactivate', {"skill": skill})) blacklisted_skills.append(skill) if "skills" not in config: config["skills"] = {} if "blacklisted_skills" not in config["skills"]: config["skills"]["blacklisted_skills"] = [] config["skills"]["blacklisted_skills"] += blacklisted_skills store = True if store: config.store()
def test_audio_service_queue_methods(self, mock_load_services): """Check that backend methods are called during playback.""" backend, second_backend = setup_mock_backends(mock_load_services, self.emitter) mock_load_services.return_value = [backend, second_backend] service = audio_service.AudioService(self.emitter) service.load_services_callback() service.default = backend # Check that play doesn't play unsupported media uri type # Test queueing starts playback if stopped backend.play.reset_mock() backend.add_list.reset_mock() m = Message('audio.service.queue', data={'tracks': ['http://hello']}) service._queue(m) backend.add_list.called_with(['http://hello']) self.assertTrue(backend.play.called) # Test queuing doesn't call play if play is in progress backend.play.reset_mock() backend.add_list.reset_mock() service._queue(m) backend.add_list.called_with(['http://hello']) self.assertFalse(backend.play.called) service.shutdown()
def test_reset_converse(self): """Check that a blank stt sends the reset signal to the skills.""" def response(message, return_msg_type): c64 = Message(return_msg_type, {'skill_id': 'c64_skill', 'error': 'skill id does not exist'}) atari = Message(return_msg_type, {'skill_id': 'atari_skill', 'result': False}) msgs = {'c64_skill': c64, 'atari_skill': atari} return msgs[message.data['skill_id']] reset_msg = Message('mycroft.speech.recognition.unknown', data={'lang': 'en-US'}) self.intent_service.bus.wait_for_response.side_effect = response self.intent_service.reset_converse(reset_msg) # Check send messages wait_for_response_mock = self.intent_service.bus.wait_for_response c64_message = wait_for_response_mock.call_args_list[0][0][0] self.assertTrue(check_converse_request(c64_message, 'c64_skill')) atari_message = wait_for_response_mock.call_args_list[1][0][0] self.assertTrue(check_converse_request(atari_message, 'atari_skill')) first_active_skill = self.intent_service.active_skills[0][0] self.assertEqual(first_active_skill, 'atari_skill')
def test_handle_start_playback(self): """Test common play start method.""" self.skill.audioservice.is_playing = True start_playback = self.bus.on.call_args_list[-1][0][1] phrase = 'Don\'t open until doomsday' start_playback(Message('play:start', data={'phrase': phrase, 'skill_id': 'asdf'})) self.skill.CPS_start.assert_not_called() self.bus.emit.reset_mock() start_playback(Message('play:start', data={'phrase': phrase, 'skill_id': self.skill.skill_id})) self.audioservice.stop.assert_called_once_with() self.skill.CPS_start.assert_called_once_with(phrase, None)
def test_converse(self): """Check that the _converse method reports if the utterance is handled. Also check that the skill that handled the query is moved to the top of the active skill list. """ def response(message, return_msg_type): c64 = Message(return_msg_type, {'skill_id': 'c64_skill', 'result': False}) atari = Message(return_msg_type, {'skill_id': 'atari_skill', 'result': True}) msgs = {'c64_skill': c64, 'atari_skill': atari} return msgs[message.data['skill_id']] self.intent_service.bus.wait_for_response.side_effect = response hello = ['hello old friend'] utterance_msg = Message('recognizer_loop:utterance', data={'lang': 'en-US', 'utterances': hello}) result = self.intent_service._converse(hello, 'en-US', utterance_msg) # Check that the active skill list was updated to set the responding # Skill first. first_active_skill = self.intent_service.active_skills[0][0] self.assertEqual(first_active_skill, 'atari_skill') # Check that a skill responded that it could handle the message self.assertTrue(result)
def wrapper(message): stopwatch = Stopwatch() try: # TODO: Fix for real in mycroft-messagebus-client # Makes sure the message type is consistent with the type declared # in mycroft.messagebus and isinstance will work. message = Message(message.msg_type, data=message.data, context=message.context) message = unmunge_message(message, skill_id) if on_start: on_start(message) with stopwatch: if len(signature(handler).parameters) == 0: handler() else: handler(message) except Exception as e: if on_error: on_error(e) finally: if on_end: on_end(message) # Send timing metrics context = message.context if context and 'ident' in context: report_timing(context['ident'], 'skill_handler', stopwatch, { 'handler': handler.__name__, 'skill_id': skill_id })
def patch_config(context, patch): """Apply patch to config and wait for it to take effect. Args: context: Behave context for test patch: patch to apply """ context.log.info('Patching config with {}'.format(patch)) # If this is first patch in scenario if not hasattr(context, 'original_config'): context.original_config = {} # store originals in context for key in patch: # If this patch is redefining an already changed key don't update if key not in context.original_config: context.original_config[key] = context.config.get(key) # Patch config patch_config_msg = Message('configuration.patch', {'config': patch}) context.bus.emit(patch_config_msg) context.add_cleanup(reset_config, context) # Wait until one of the keys has been updated key = list(patch.keys())[0] wait_for_config_change(context, key, patch[key])
def test_get_intent_manifest(self): """Check that if the intent doesn't match at all None is returned.""" self.setup_simple_adapt_intent() # Check that no intent is matched msg = Message('intent.service.intent.get', data={'utterance': 'five'}) self.intent_service.handle_get_intent(msg) reply = get_last_message(self.intent_service.bus) self.assertEqual(reply.data['intent'], None)
def then_user_follow_up(context, text): time.sleep(2) wait_while_speaking() context.bus.emit(Message('recognizer_loop:utterance', data={'utterances': [text], 'lang': context.lang, 'session': '', 'ident': time.time()}, context={'client_name': 'mycroft_listener'}))
def test_get_adapt_intent(self): self.setup_simple_adapt_intent() # Check that the intent is returned msg = Message('intent.service.adapt.get', data={'utterance': 'test'}) self.intent_service.handle_get_adapt(msg) reply = get_last_message(self.intent_service.bus) self.assertEqual(reply.data['intent']['intent_type'], 'skill:testIntent')
def test_get_adapt_vocab_manifest(self): self.setup_simple_adapt_intent() msg = Message('intent.service.adapt.vocab.manifest.get') self.intent_service.handle_vocab_manifest(msg) reply = get_last_message(self.intent_service.bus) value = reply.data['vocab'][0]['start'] keyword = reply.data['vocab'][0]['end'] self.assertEqual(keyword, 'testKeyword') self.assertEqual(value, 'test')
def CPS_send_status(self, artist='', track='', image=''): data = { 'skill': self.name, 'artist': artist, 'track': track, 'image': image, 'status': None # TODO Add status system } self.bus.emit(Message('play:status', data))
def on_message(self, _, message): """Extends normal operation by storing the received message. Args: message (Message): message from the Mycroft bus """ with self.message_lock: self.messages.append(Message.deserialize(message)) self.new_message_available.set() super().on_message(_, message)
def reset_config(context): """Cleanup callback to reset patched configuration Args: context (Context): Behave context of current scenario """ context.log.info('Resetting patched configuration...') context.bus.emit(Message('configuration.patch.clear')) key = list(context.original_config)[0] wait_for_config_change(context, key, context.original_config[key])
def reset_config(context): """Reset configuration with changes stored in original_config of context. """ context.log.info('Resetting patched configuration...') context.bus.emit(Message('configuration.patch.clear')) key = list(context.original_config)[0] while context.config[key] != context.original_config[key]: sleep(0.5) context.original_config = {}
def test_keyword_backwards_compatibility(self): self.setup_simple_adapt_intent( create_old_style_vocab_msg('testKeyword', 'test')) # Check that the intent is returned msg = Message('intent.service.adapt.get', data={'utterance': 'test'}) self.intent_service.handle_get_adapt(msg) reply = get_last_message(self.intent_service.bus) self.assertEqual(reply.data['intent']['intent_type'], 'skill:testIntent')
def test_converse(self): """Check that the _converse method reports if the utterance is handled. Also check that the skill that handled the query is moved to the top of the active skill list. """ result = None def runner(utterances, lang, message): nonlocal result result = self.intent_service._converse(utterances, lang, message) hello = ['hello old friend'] utterance_msg = Message('recognizer_loop:utterance', data={ 'lang': 'en-US', 'utterances': hello }) t = Thread(target=runner, args=(hello, 'en-US', utterance_msg)) t.start() time.sleep(0.5) self.intent_service.handle_converse_response( Message('converse.response', { 'skill_id': 'c64_skill', 'result': False })) time.sleep(0.5) self.intent_service.handle_converse_response( Message('converse.response', { 'skill_id': 'atari_skill', 'result': True })) t.join() # Check that the active skill list was updated to set the responding # Skill first. first_active_skill = self.intent_service.active_skills[0][0] self.assertEqual(first_active_skill, 'atari_skill') # Check that a skill responded that it could handle the message self.assertTrue(result)