示例#1
0
async def invoke(handler: AnyFunc, request: Request) -> Response:
    """
    Invoke intent handler:

        awaits the call if handler is a coroutine
        runs in executor if handler is a simple `def`

    @param handler:
    @param request:
    @return:
    """

    with RequestContextVar(request=request):
        logger.debug(
            "Calling intent %s with handler: %s",
            repr(request.context.intent),
            repr(handler),
        )

        if inspect.iscoroutinefunction(handler):
            response = await handler(request)
        else:
            loop = asyncio.get_running_loop()
            response = await loop.run_in_executor(
                ContextVarExecutor(),
                handler,
                request,
            )

        if isinstance(response, str):
            response = Response(text=response)

        logger.debug("Intent call result: %s", repr(response))
        return response
示例#2
0
 def test_response_repr(self):
     """ Test Response representation
     """
     response = Response('Hola', RESPONSE_TYPE_ASK)
     self.assertEqual(
         "{'text': 'Hola', 'type_': 'ASK', 'card': None, "
         "'push_notification': None, 'result': {'data': {}, 'local': True}}",
         repr(response))
示例#3
0
 def test_dict_ask_deprecated(self, warn_mock):
     response = Response('abc123',
                         RESPONSE_TYPE_ASK,
                         ask_for=('location', 'CITY')).dict(self.ctx)
     self.assertNotIn('askForAttribute', response)
     warn_mock.assert_called_with('"ask_for" parameter is deprecated.',
                                  DeprecationWarning,
                                  stacklevel=2)
示例#4
0
 def test_response_returns_message(self):
     """ Test if context._ returns l10n.Message
     """
     l10n.translations = {'de': l10n.Translations()}
     context = create_context('TELEKOM_Demo_Intent')
     with patch('random.randint',
                return_value=Response(
                    text=context._('some text'))) as mock_gde:
         mock_gde.__name__ = 'mock_gde'
         intent = Intent('TELEKOM_Demo_Intent', random.randint)
         response = intent(context)
         self.assertIsInstance(response.text, l10n.Message)
示例#5
0
 def setUp(self):
     self.simple_response = Response("abc123", ResponseType.TELL)
     self.ask_response = Response("abc123", ResponseType.ASK)
     c = Card("SIMPLE", title_text="cardtitle", text="cardtext")
     self.card_response = Response(
         "abc123", ResponseType.TELL, card=c, result={"code": 22}
     )
     self.ctx = create_context("TELEKOM_Clock_GetTime")
示例#6
0
 def test_message(self):
     response = Response(l10n.Message('{abc}123', 'KEY',
                                      abc='abc')).dict(self.ctx)
     self.assertEqual(response['text'], 'abc123')
     self.assertEqual(response['type'], 'TELL')
     self.assertEqual(
         response['result']['data'], {
             'key': 'KEY',
             'value': '{abc}123',
             'args': (),
             'kwargs': {
                 'abc': 'abc'
             }
         })
示例#7
0
    def setUp(self):
        self.simple_response = Response('abc123')
        self.ask_response = Response('abc123', RESPONSE_TYPE_ASK, ask_for=('location', 'CITY'))
        card = Card('SIMPLE', title='cardtitle', text='cardtext', token_id={'secret': 'token'})
        self.card_response = Response('abc123', RESPONSE_TYPE_TELL, card=card, result={'code': 22})

        session = {'attributes': {"key-1": "value-1",
                                  "key-2": "value-2"}}
        self.ctx = create_context("TELEKOM_Clock_GetTime", session=session)
示例#8
0
class TestResponse(unittest.TestCase):

    def setUp(self):
        self.simple_response = Response('abc123')
        self.ask_response = Response('abc123', RESPONSE_TYPE_ASK, ask_for=('location', 'CITY'))
        card = Card('SIMPLE', title='cardtitle', text='cardtext', token_id={'secret': 'token'})
        self.card_response = Response('abc123', RESPONSE_TYPE_TELL, card=card, result={'code': 22})

        session = {'attributes': {"key-1": "value-1",
                                  "key-2": "value-2"}}
        self.ctx = create_context("TELEKOM_Clock_GetTime", session=session)

    def test_init_text(self):
        self.assertEqual(self.simple_response.text, 'abc123')
        self.assertEqual(self.simple_response.type_, RESPONSE_TYPE_TELL)

    def test_init_full(self):
        self.assertEqual(self.card_response.text, 'abc123')
        self.assertEqual(self.card_response.type_, RESPONSE_TYPE_TELL)
        self.assertEqual(self.card_response.card.data['title'], 'cardtitle')
        self.assertEqual(self.card_response.result['code'], 22)
        self.assertEqual(self.card_response.push_notification, None)

    def test_init_push_notification(self):
        self.simple_response.push_notification = {'device': [{'payload': 1}, {'payload': 2}]}
        response = self.simple_response.dict(self.ctx)
        self.assertEqual(response['text'], 'abc123')
        self.assertEqual(response['type'], 'TELL')
        self.assertEqual(response['pushNotification'], {'device': [{'payload': 1}, {'payload': 2}]})

    def test_init_bad_type(self):
        with self.assertRaises(ValueError):
            Response('abc123', 'TEL')

    def test_dict_ask(self):
        response = self.ask_response.dict(self.ctx)
        self.assertEqual(response['text'], 'abc123')
        self.assertEqual(response['type'], 'ASK')

    @patch('skill_sdk.responses.warn')
    def test_dict_ask_deprecated(self, warn_mock):
        response = Response('abc123', RESPONSE_TYPE_ASK, ask_for=('location', 'CITY')).dict(self.ctx)
        self.assertNotIn('askForAttribute', response)
        warn_mock.assert_called_with('"ask_for" parameter is deprecated.', DeprecationWarning, stacklevel=2)

    def test_dict_simple(self):
        response = self.simple_response.dict(self.ctx)
        self.assertEqual(response['text'], 'abc123')
        self.assertEqual(response['type'], 'TELL')
        self.assertNotIn('pushNotification', response)

    def test_dict_card(self):
        response = self.card_response.dict(self.ctx)
        self.assertEqual(response['text'], 'abc123')
        self.assertEqual(response['type'], 'TELL')
        self.assertEqual(response['card']['data']['title'], 'cardtitle')
        self.assertEqual(response['result']['data']['code'], 22)
        self.assertEqual(response['card']['tokenId'], {'secret': 'token'})

    @patch.object(Response, 'dict', return_value='{}')
    def test_response(self, dict_mock):
        response = self.simple_response.as_response(None)
        self.assertIsInstance(response, HTTPResponse)
        self.assertEqual(response.status_code, 200)

    def test_message(self):
        response = Response(l10n.Message('{abc}123', 'KEY', abc='abc')).dict(self.ctx)
        self.assertEqual(response['text'], 'abc123')
        self.assertEqual(response['type'], 'TELL')
        self.assertEqual(response['result']['data'],
                         {'key': 'KEY', 'value': '{abc}123', 'args': (), 'kwargs': {'abc': 'abc'}})

    def test_dict_simple_result_is_none(self):
        """ Make sure the optional fields are stripped off if empty
        """
        response = self.simple_response.dict(self.ctx)
        self.assertEqual(response['session'], {'attributes': {'key-1': 'value-1', 'key-2': 'value-2'}})
        self.assertNotIn('result', response)
        self.assertNotIn('card', response)
        self.assertNotIn('pushNotification', response)
        # For the coverage sake:
        request = SimpleNamespace()
        request.headers = {}
        request.json = {
            "context": {
                "attributes": {...},
                "intent": "TELEKOM_Clock_GetTime",
                "locale": "de",
                "tokens": {},
                "clientAttributes": {}
            },
            "version": 1
        }
        ctx = Context(request)
        self.assertNotIn('session', self.simple_response.dict(ctx))

    def test_tell(self):
        """ Check if responses.tell returns Response(type_=RESPONSE_TYPE_TELL)
        """
        r = tell('Hello')
        self.assertIsInstance(r, Response)
        self.assertEqual(r.type_, RESPONSE_TYPE_TELL)

    def test_ask(self):
        """ Check is responses.ask returns Response(type_=RESPONSE_TYPE_ASK)
        """
        r = ask('Question')
        self.assertIsInstance(r, Response)
        self.assertEqual(r.type_, RESPONSE_TYPE_ASK)

    def test_ask_freetext(self):
        """ Check is responses.ask returns Response(type_=RESPONSE_TYPE_ASK_FREETEXT)
        """
        r = ask_freetext('Question')
        self.assertIsInstance(r, Response)
        self.assertEqual(r.type_, RESPONSE_TYPE_ASK_FREETEXT)

    def test_reprompt_response(self):
        """ Test responses.Reprompt response
        """
        self.assertIsInstance(Reprompt('abc123'), Response)
        response = Reprompt('abc123').dict(self.ctx)
        self.assertEqual(response['session']['attributes']['TELEKOM_Clock_GetTime_reprompt_count'], '1')
        self.assertEqual(response['text'], 'abc123')
        self.assertEqual(response['type'], 'ASK')
        with patch.dict(self.ctx.session, {'TELEKOM_Clock_GetTime_reprompt_count': '1'}):
            response = Reprompt('abc123').dict(self.ctx)
            self.assertEqual(response['session']['attributes']['TELEKOM_Clock_GetTime_reprompt_count'], '2')
            self.assertEqual(response['text'], 'abc123')
            self.assertEqual(response['type'], 'ASK')
            response = Reprompt('abc123', '321cba', 2).dict(self.ctx)
            self.assertNotIn('TELEKOM_Clock_GetTime_reprompt_count', response['session']['attributes'])
            self.assertEqual(response['text'], '321cba')
            self.assertEqual(response['type'], 'TELL')
        with patch.dict(self.ctx.session, {'TELEKOM_Clock_GetTime_reprompt_count': 'not a number'}):
            response = Reprompt('abc123').dict(self.ctx)
            self.assertEqual(response['session']['attributes']['TELEKOM_Clock_GetTime_reprompt_count'], '1')
        response = Reprompt('abc123', entity='Time').dict(self.ctx)
        self.assertEqual(response['session']['attributes']['TELEKOM_Clock_GetTime_reprompt_count'], '1')
        self.assertEqual(response['session']['attributes']['TELEKOM_Clock_GetTime_Time_reprompt_count'], '1')

    def test_response_repr(self):
        """ Test Response representation
        """
        response = Response('Hola', RESPONSE_TYPE_ASK)
        self.assertEqual("{'text': 'Hola', 'type_': 'ASK', 'card': None, "
                         "'push_notification': None, 'result': {'data': {}, 'local': True}}", repr(response))
示例#9
0
 def test_init_bad_type(self):
     with self.assertRaises(ValueError):
         Response('abc123', 'TEL')
示例#10
0
class TestIntent(unittest.TestCase):
    def setUp(self):
        request = SimpleNamespace()
        request.json = {
            "context": {
                "attributes": {},
                "intent": "TELEKOM_Demo_Intent",
                "locale": "de",
                "tokens": {}
            },
            "session": {
                "new": True,
                "id": "12345",
                "attributes": {
                    "key-1": "value-1",
                    "key-2": "value-2"
                }
            },
        }
        request.headers = {}
        self.ctx = Context(request)
        self.ctx.tracer = Tracer(request)

    @patch.object(logging.Logger, 'warning')
    def test_init_exceptions(self, warn_mock):
        with self.assertRaises(TypeError):
            Intent({})
        with self.assertRaises(ValueError):
            Intent('', None)
        with self.assertRaises(ValueError):
            Intent('demo_intent', 'random.does_not_exist')

    @patch('random.randint', return_value=1)
    def test_call_bad_return_type(self, mock_gde):
        mock_gde.__name__ = 'mock_gde'
        intent = Intent('TELEKOM_Demo_Intent', random.randint)
        with self.assertRaises(ValueError):
            intent(self.ctx).dict(self.ctx)

    @patch('random.randint', return_value=ErrorResponse(999, 'some error'))
    def test_call_error_999(self, mock_gde):
        mock_gde.__name__ = 'mock_gde'
        intent = Intent('TELEKOM_Demo_Intent', random.randint)
        self.assertIsInstance(intent(self.ctx), ErrorResponse)

    @patch('random.randint', side_effect=RequestException())
    def test_call_requests_error(self, mock_gde):
        mock_gde.__name__ = 'mock_gde'
        intent = Intent('TELEKOM_Demo_Intent', random.randint)
        response = intent(self.ctx)
        self.assertIsInstance(response, Response)
        self.assertEqual(response.text, 'GENERIC_HTTP_ERROR_RESPONSE')

    @patch('random.randint', side_effect=CircuitBreakerError(CircuitBreaker()))
    def test_call_circuit_breaker_open(self, mock_gde):
        mock_gde.__name__ = 'mock_gde'
        intent = Intent('TELEKOM_Demo_Intent', random.randint)
        response = intent(self.ctx)
        self.assertIsInstance(response, Response)
        self.assertEqual(response.text, 'GENERIC_HTTP_ERROR_RESPONSE')

    @patch('random.randint',
           return_value=Response(text='some text', type_=RESPONSE_TYPE_TELL))
    def test_append_push_messages_empty(self, mock_gde):
        mock_gde.__name__ = 'mock_gde'
        context = create_context('TELEKOM_Demo_Intent')
        intent = Intent('TELEKOM_Demo_Intent', random.randint)
        response = intent(context)
        response = intent._append_push_messages(context, response)
        self.assertEqual(response.push_notification, None)

    @patch('random.randint',
           return_value=Response(text='some text', type_=RESPONSE_TYPE_TELL))
    def test_append_push_messages_one(self, mock_gde):
        mock_gde.__name__ = 'mock_gde'
        context = create_context('TELEKOM_Demo_Intent')
        intent = Intent('TELEKOM_Demo_Intent', random.randint)
        response = intent(context)
        context.push_messages = {'device': [{'payload': 1}]}
        response = intent._append_push_messages(context, response)
        self.assertEqual(response.push_notification, {
            'targetName': 'device',
            'messagePayload': {
                'payload': 1
            }
        })

    @patch('random.randint',
           return_value=Response(text='some text', type_=RESPONSE_TYPE_TELL))
    def test_append_push_messages_two_messages(self, mock_gde):
        mock_gde.__name__ = 'mock_gde'
        context = create_context('TELEKOM_Demo_Intent')
        intent = Intent('TELEKOM_Demo_Intent', random.randint)
        response = intent(context)
        context.push_messages = {'device': [{'payload': 1}, {'payload': 2}]}
        with self.assertRaises(ValueError):
            _ = intent._append_push_messages(context, response)

    @patch('random.randint',
           return_value=Response(text='some text', type_=RESPONSE_TYPE_TELL))
    def test_append_push_messages_two_devices(self, mock_gde):
        mock_gde.__name__ = 'mock_gde'
        context = create_context('TELEKOM_Demo_Intent')
        intent = Intent('TELEKOM_Demo_Intent', random.randint)
        response = intent(context)
        context.push_messages = {
            'device': [{
                'payload': 1
            }],
            'device2': [{
                'payload': 2
            }]
        }
        with self.assertRaises(ValueError):
            _ = intent._append_push_messages(context, response)

    def test_repr(self):
        self.assertIn('TELEKOM_Demo_Intent',
                      repr(Intent('TELEKOM_Demo_Intent', random.randint)))

    def test_response_returns_message(self):
        """ Test if context._ returns l10n.Message
        """
        l10n.translations = {'de': l10n.Translations()}
        context = create_context('TELEKOM_Demo_Intent')
        with patch('random.randint',
                   return_value=Response(
                       text=context._('some text'))) as mock_gde:
            mock_gde.__name__ = 'mock_gde'
            intent = Intent('TELEKOM_Demo_Intent', random.randint)
            response = intent(context)
            self.assertIsInstance(response.text, l10n.Message)
示例#11
0
 def test_init_bad_type(self):
     with self.assertRaises(ValueError):
         Response("abc123", "TEL")
示例#12
0
class TestResponse(unittest.TestCase):
    def setUp(self):
        self.simple_response = Response("abc123", ResponseType.TELL)
        self.ask_response = Response("abc123", ResponseType.ASK)
        c = Card("SIMPLE", title_text="cardtitle", text="cardtext")
        self.card_response = Response(
            "abc123", ResponseType.TELL, card=c, result={"code": 22}
        )
        self.ctx = create_context("TELEKOM_Clock_GetTime")

    def test_init_text(self):
        self.assertEqual(self.simple_response.text, "abc123")
        self.assertEqual(self.simple_response.type, "TELL")

    def test_init_full(self):
        self.assertEqual(self.card_response.text, "abc123")
        self.assertEqual(self.card_response.type, "TELL")
        self.assertEqual(self.card_response.card.title_text, "cardtitle")
        self.assertEqual(self.card_response.result.data["code"], 22)
        self.assertEqual(self.card_response.push_notification, None)

    def test_init_bad_type(self):
        with self.assertRaises(ValueError):
            Response("abc123", "TEL")

    def test_dict_ask(self):
        response = self.ask_response.dict()
        self.assertEqual("abc123", response["text"])
        self.assertEqual("ASK", response["type"])

    def test_dict_simple(self):
        response = self.simple_response.dict()
        self.assertEqual("abc123", response["text"])
        self.assertEqual("TELL", response["type"])
        self.assertNotIn("pushNotification", response)

    def test_dict_card(self):
        response = self.card_response.dict()
        self.assertEqual(response["text"], "abc123")
        self.assertEqual(response["type"], "TELL")
        self.assertEqual(response["card"]["data"]["titleText"], "cardtitle")
        self.assertEqual(response["result"]["data"]["code"], 22)

    def test_response_with_card(self):
        response = (
            tell("Hola")
            .with_card(
                title_text="Title",
                text="Text",
                action=CardAction.INTERNAL_RESPONSE_TEXT,
            )
            .dict()
        )

        self.assertEqual(
            {
                "type": "TELL",
                "text": "Hola",
                "card": {
                    "type": "GENERIC_DEFAULT",
                    "version": 1,
                    "data": {
                        "titleText": "Title",
                        "text": "Text",
                        "action": "internal://showResponseText",
                    },
                },
            },
            response,
        )

    def test_response_with_command(self):
        response = tell("Hola").with_command(AudioPlayer.play_stream("URL")).dict()
        self.assertEqual(
            {
                "text": "Hola",
                "type": "TELL",
                "result": {
                    "data": {
                        "use_kit": {
                            "kit_name": "audio_player",
                            "action": "play_stream",
                            "parameters": {"url": "URL"},
                        }
                    },
                    "local": True,
                },
            },
            response,
        )

    def test_response_with_session(self):
        response = ask("Hola?").with_session(
            attr1="attr-1",
            attr2="attr-2",
        )
        self.assertEqual(
            {
                "text": "Hola?",
                "type": "ASK",
                "session": {"attributes": {"attr1": "attr-1", "attr2": "attr-2"}},
            },
            response.dict(),
        )
        with self.assertRaises(ValidationError):
            tell("Hola").with_session(
                attr1="attr-1",
                attr2="attr-2",
            )

    def test_tell(self):
        r = tell("Hello")
        self.assertIsInstance(r, Response)
        self.assertEqual("TELL", r.type)

    def test_ask(self):
        r = ask("Question")
        self.assertIsInstance(r, Response)
        self.assertEqual("ASK", r.type)

    def test_ask_freetext(self):
        r = ask_freetext("Question")
        self.assertIsInstance(r, Response)
        self.assertEqual("ASK_FREETEXT", r.type)

    def test_init_push_notification(self):
        response = self.simple_response.with_notification(
            target_name="device", message_payload="payload"
        ).dict()
        self.assertEqual("abc123", response["text"])
        self.assertEqual("TELL", response["type"])
        self.assertEqual(
            {"messagePayload": "payload", "targetName": "device"},
            response["pushNotification"],
        )

    #
    # TODO: double check if this functionality requested by skills, remove if not needed
    #
    """