From f714ace4cbafe7bd053f5cec78f895aa22e1ead2 Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Fri, 6 Mar 2020 14:40:43 -0800 Subject: [PATCH 1/7] change DeliveryMode bufferedReplies to expectsReply --- .../botbuilder-core/botbuilder/core/bot_framework_adapter.py | 2 +- .../botbuilder/core/bot_framework_http_client.py | 2 +- libraries/botbuilder-core/botbuilder/core/turn_context.py | 4 ++-- libraries/botbuilder-core/tests/test_bot_framework_adapter.py | 4 ++-- .../botbuilder/schema/_connector_client_enums.py | 2 +- .../experimental/skills-buffered/parent/bots/parent_bot.py | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py b/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py index ffe81ec7d..b0ef89422 100644 --- a/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py +++ b/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py @@ -460,7 +460,7 @@ async def process_activity_with_identity( # Return the buffered activities in the response. In this case, the invoker # should deserialize accordingly: # activities = [Activity().deserialize(activity) for activity in response.body] - if context.activity.delivery_mode == DeliveryModes.buffered_replies: + if context.activity.delivery_mode == DeliveryModes.expects_reply: serialized_activities = [ activity.serialize() for activity in context.buffered_replies ] diff --git a/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py b/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py index 963cf8bd4..de38aba91 100644 --- a/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py +++ b/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py @@ -110,7 +110,7 @@ async def post_buffered_activity( ) -> [Activity]: """ Helper method to return a list of activities when an Activity is being - sent with DeliveryMode == bufferedReplies. + sent with DeliveryMode == expectsReply. """ response = await self.post_activity( from_bot_id, to_bot_id, to_url, service_url, conversation_id, activity diff --git a/libraries/botbuilder-core/botbuilder/core/turn_context.py b/libraries/botbuilder-core/botbuilder/core/turn_context.py index b3ec326c8..1b3b1d994 100644 --- a/libraries/botbuilder-core/botbuilder/core/turn_context.py +++ b/libraries/botbuilder-core/botbuilder/core/turn_context.py @@ -51,7 +51,7 @@ def __init__(self, adapter_or_context, request: Activity = None): self._turn_state = {} - # A list of activities to send when `context.Activity.DeliveryMode == 'bufferedReplies'` + # A list of activities to send when `context.Activity.DeliveryMode == 'expectsReply'` self.buffered_replies = [] @property @@ -198,7 +198,7 @@ def activity_validator(activity: Activity) -> Activity: async def logic(): nonlocal sent_non_trace_activity - if self.activity.delivery_mode == DeliveryModes.buffered_replies: + if self.activity.delivery_mode == DeliveryModes.expects_reply: responses = [] for activity in output: self.buffered_replies.append(activity) diff --git a/libraries/botbuilder-core/tests/test_bot_framework_adapter.py b/libraries/botbuilder-core/tests/test_bot_framework_adapter.py index 871e616a1..bdc8a6b41 100644 --- a/libraries/botbuilder-core/tests/test_bot_framework_adapter.py +++ b/libraries/botbuilder-core/tests/test_bot_framework_adapter.py @@ -578,7 +578,7 @@ async def callback(context: TurnContext): refs, callback, claims_identity=skills_identity, audience=skill_2_app_id ) - async def test_delivery_mode_buffered_replies(self): + async def test_delivery_mode_expects_reply(self): mock_credential_provider = unittest.mock.create_autospec(CredentialProvider) settings = BotFrameworkAdapterSettings( @@ -595,7 +595,7 @@ async def callback(context: TurnContext): type=ActivityTypes.message, channel_id="emulator", service_url="http://tempuri.org/whatever", - delivery_mode=DeliveryModes.buffered_replies, + delivery_mode=DeliveryModes.expects_reply, text="hello world", ) diff --git a/libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py b/libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py index 68aab5ecf..2da7cc2de 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py +++ b/libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py @@ -99,7 +99,7 @@ class DeliveryModes(str, Enum): normal = "normal" notification = "notification" - buffered_replies = "bufferedReplies" + expects_reply = "expectsReply" class ContactRelationUpdateActionTypes(str, Enum): diff --git a/samples/experimental/skills-buffered/parent/bots/parent_bot.py b/samples/experimental/skills-buffered/parent/bots/parent_bot.py index 91b85b654..3df2c58f4 100644 --- a/samples/experimental/skills-buffered/parent/bots/parent_bot.py +++ b/samples/experimental/skills-buffered/parent/bots/parent_bot.py @@ -26,7 +26,7 @@ async def on_message_activity(self, turn_context: TurnContext): TurnContext.apply_conversation_reference( activity, TurnContext.get_conversation_reference(turn_context.activity) ) - activity.delivery_mode = DeliveryModes.buffered_replies + activity.delivery_mode = DeliveryModes.expects_reply activities = await self.client.post_buffered_activity( None, From 4a2140144c8bad8e974d3ff94b504e0f023e327d Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Fri, 6 Mar 2020 18:43:08 -0800 Subject: [PATCH 2/7] change to expectedReplies --- .../botbuilder/core/bot_framework_adapter.py | 4 ++-- .../botbuilder/core/bot_framework_http_client.py | 2 +- libraries/botbuilder-core/botbuilder/core/turn_context.py | 8 ++++---- .../botbuilder-core/tests/test_bot_framework_adapter.py | 4 ++-- .../botbuilder/schema/_connector_client_enums.py | 2 +- libraries/botbuilder-schema/botbuilder/schema/_models.py | 2 +- .../botbuilder-schema/botbuilder/schema/_models_py3.py | 2 +- libraries/swagger/ConnectorAPI.json | 3 ++- .../skills-buffered/parent/bots/parent_bot.py | 2 +- 9 files changed, 15 insertions(+), 14 deletions(-) diff --git a/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py b/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py index b0ef89422..5c127bef1 100644 --- a/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py +++ b/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py @@ -460,9 +460,9 @@ async def process_activity_with_identity( # Return the buffered activities in the response. In this case, the invoker # should deserialize accordingly: # activities = [Activity().deserialize(activity) for activity in response.body] - if context.activity.delivery_mode == DeliveryModes.expects_reply: + if context.activity.delivery_mode == DeliveryModes.expect_replies: serialized_activities = [ - activity.serialize() for activity in context.buffered_replies + activity.serialize() for activity in context.buffered_reply_activties ] return InvokeResponse(status=200, body=serialized_activities) diff --git a/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py b/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py index de38aba91..987668b79 100644 --- a/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py +++ b/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py @@ -110,7 +110,7 @@ async def post_buffered_activity( ) -> [Activity]: """ Helper method to return a list of activities when an Activity is being - sent with DeliveryMode == expectsReply. + sent with DeliveryMode == expectReplies. """ response = await self.post_activity( from_bot_id, to_bot_id, to_url, service_url, conversation_id, activity diff --git a/libraries/botbuilder-core/botbuilder/core/turn_context.py b/libraries/botbuilder-core/botbuilder/core/turn_context.py index 1b3b1d994..c22bd4fa4 100644 --- a/libraries/botbuilder-core/botbuilder/core/turn_context.py +++ b/libraries/botbuilder-core/botbuilder/core/turn_context.py @@ -51,8 +51,8 @@ def __init__(self, adapter_or_context, request: Activity = None): self._turn_state = {} - # A list of activities to send when `context.Activity.DeliveryMode == 'expectsReply'` - self.buffered_replies = [] + # A list of activities to send when `context.Activity.DeliveryMode == 'expectReplies'` + self.buffered_reply_activties = [] @property def turn_state(self) -> Dict[str, object]: @@ -198,10 +198,10 @@ def activity_validator(activity: Activity) -> Activity: async def logic(): nonlocal sent_non_trace_activity - if self.activity.delivery_mode == DeliveryModes.expects_reply: + if self.activity.delivery_mode == DeliveryModes.expect_replies: responses = [] for activity in output: - self.buffered_replies.append(activity) + self.buffered_reply_activties.append(activity) responses.append(ResourceResponse()) if sent_non_trace_activity: diff --git a/libraries/botbuilder-core/tests/test_bot_framework_adapter.py b/libraries/botbuilder-core/tests/test_bot_framework_adapter.py index bdc8a6b41..62041b7db 100644 --- a/libraries/botbuilder-core/tests/test_bot_framework_adapter.py +++ b/libraries/botbuilder-core/tests/test_bot_framework_adapter.py @@ -578,7 +578,7 @@ async def callback(context: TurnContext): refs, callback, claims_identity=skills_identity, audience=skill_2_app_id ) - async def test_delivery_mode_expects_reply(self): + async def test_delivery_mode_expect_replies(self): mock_credential_provider = unittest.mock.create_autospec(CredentialProvider) settings = BotFrameworkAdapterSettings( @@ -595,7 +595,7 @@ async def callback(context: TurnContext): type=ActivityTypes.message, channel_id="emulator", service_url="http://tempuri.org/whatever", - delivery_mode=DeliveryModes.expects_reply, + delivery_mode=DeliveryModes.expect_replies, text="hello world", ) diff --git a/libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py b/libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py index 2da7cc2de..ba33d9c00 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py +++ b/libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py @@ -99,7 +99,7 @@ class DeliveryModes(str, Enum): normal = "normal" notification = "notification" - expects_reply = "expectsReply" + expect_replies = "expectReplies" class ContactRelationUpdateActionTypes(str, Enum): diff --git a/libraries/botbuilder-schema/botbuilder/schema/_models.py b/libraries/botbuilder-schema/botbuilder/schema/_models.py index 2cb85d663..042c9e0bd 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/_models.py +++ b/libraries/botbuilder-schema/botbuilder/schema/_models.py @@ -133,7 +133,7 @@ class Activity(Model): :param delivery_mode: A delivery hint to signal to the recipient alternate delivery paths for the activity. The default delivery mode is "default". Possible values include: 'normal', - 'notification' + 'notification', 'expectReplies' :type delivery_mode: str or ~botframework.connector.models.DeliveryModes :param listen_for: List of phrases and references that speech and language priming systems should listen for diff --git a/libraries/botbuilder-schema/botbuilder/schema/_models_py3.py b/libraries/botbuilder-schema/botbuilder/schema/_models_py3.py index fe583a9b8..f079ac383 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/_models_py3.py +++ b/libraries/botbuilder-schema/botbuilder/schema/_models_py3.py @@ -133,7 +133,7 @@ class Activity(Model): :param delivery_mode: A delivery hint to signal to the recipient alternate delivery paths for the activity. The default delivery mode is "default". Possible values include: 'normal', - 'notification' + 'notification', 'expectReplies' :type delivery_mode: str or ~botframework.connector.models.DeliveryModes :param listen_for: List of phrases and references that speech and language priming systems should listen for diff --git a/libraries/swagger/ConnectorAPI.json b/libraries/swagger/ConnectorAPI.json index f3a5b6e49..bae96e716 100644 --- a/libraries/swagger/ConnectorAPI.json +++ b/libraries/swagger/ConnectorAPI.json @@ -2293,7 +2293,8 @@ "description": "Values for deliveryMode field", "enum": [ "normal", - "notification" + "notification", + "expectReplies" ], "type": "string", "properties": {}, diff --git a/samples/experimental/skills-buffered/parent/bots/parent_bot.py b/samples/experimental/skills-buffered/parent/bots/parent_bot.py index 3df2c58f4..1aa077624 100644 --- a/samples/experimental/skills-buffered/parent/bots/parent_bot.py +++ b/samples/experimental/skills-buffered/parent/bots/parent_bot.py @@ -26,7 +26,7 @@ async def on_message_activity(self, turn_context: TurnContext): TurnContext.apply_conversation_reference( activity, TurnContext.get_conversation_reference(turn_context.activity) ) - activity.delivery_mode = DeliveryModes.expects_reply + activity.delivery_mode = DeliveryModes.expect_replies activities = await self.client.post_buffered_activity( None, From 7f54b35353baa2893ea60dfee11569b8ec98438b Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Fri, 6 Mar 2020 19:18:30 -0800 Subject: [PATCH 3/7] spelling --- .../botbuilder-core/botbuilder/core/bot_framework_adapter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py b/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py index 5c127bef1..f53aa8d98 100644 --- a/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py +++ b/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py @@ -462,7 +462,7 @@ async def process_activity_with_identity( # activities = [Activity().deserialize(activity) for activity in response.body] if context.activity.delivery_mode == DeliveryModes.expect_replies: serialized_activities = [ - activity.serialize() for activity in context.buffered_reply_activties + activity.serialize() for activity in context.buffered_reply_activities ] return InvokeResponse(status=200, body=serialized_activities) From a78d4523bf4830fd937d95104329dc48e6a1f6e3 Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Fri, 6 Mar 2020 19:19:12 -0800 Subject: [PATCH 4/7] spelling --- libraries/botbuilder-core/botbuilder/core/turn_context.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/botbuilder-core/botbuilder/core/turn_context.py b/libraries/botbuilder-core/botbuilder/core/turn_context.py index c22bd4fa4..00bdf5d43 100644 --- a/libraries/botbuilder-core/botbuilder/core/turn_context.py +++ b/libraries/botbuilder-core/botbuilder/core/turn_context.py @@ -52,7 +52,7 @@ def __init__(self, adapter_or_context, request: Activity = None): self._turn_state = {} # A list of activities to send when `context.Activity.DeliveryMode == 'expectReplies'` - self.buffered_reply_activties = [] + self.buffered_reply_activities = [] @property def turn_state(self) -> Dict[str, object]: @@ -201,7 +201,7 @@ async def logic(): if self.activity.delivery_mode == DeliveryModes.expect_replies: responses = [] for activity in output: - self.buffered_reply_activties.append(activity) + self.buffered_reply_activities.append(activity) responses.append(ResourceResponse()) if sent_non_trace_activity: From 7494bc0a9810ad760f8087797098dbd779166011 Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Sun, 8 Mar 2020 10:25:16 -0700 Subject: [PATCH 5/7] Add ExpectedReplies --- .../botbuilder/core/bot_framework_adapter.py | 11 ++++++----- .../botbuilder/core/bot_framework_http_client.py | 4 ++-- .../botbuilder/schema/__init__.py | 3 +++ .../botbuilder/schema/_models.py | 15 +++++++++++++++ .../botbuilder/schema/_models_py3.py | 15 +++++++++++++++ 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py b/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py index f53aa8d98..1a4407895 100644 --- a/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py +++ b/libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py @@ -37,6 +37,7 @@ ConversationAccount, ConversationParameters, ConversationReference, + ExpectedReplies, TokenResponse, ResourceResponse, DeliveryModes, @@ -459,12 +460,12 @@ async def process_activity_with_identity( # Return the buffered activities in the response. In this case, the invoker # should deserialize accordingly: - # activities = [Activity().deserialize(activity) for activity in response.body] + # activities = ExpectedReplies().deserialize(response.body).activities if context.activity.delivery_mode == DeliveryModes.expect_replies: - serialized_activities = [ - activity.serialize() for activity in context.buffered_reply_activities - ] - return InvokeResponse(status=200, body=serialized_activities) + expected_replies = ExpectedReplies( + activities=context.buffered_reply_activities + ).serialize() + return InvokeResponse(status=200, body=expected_replies) return None diff --git a/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py b/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py index 987668b79..dc9dd1a9e 100644 --- a/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py +++ b/libraries/botbuilder-core/botbuilder/core/bot_framework_http_client.py @@ -6,7 +6,7 @@ from logging import Logger import aiohttp -from botbuilder.schema import Activity +from botbuilder.schema import Activity, ExpectedReplies from botframework.connector.auth import ( ChannelProvider, CredentialProvider, @@ -117,7 +117,7 @@ async def post_buffered_activity( ) if not response or (response.status / 100) != 2: return [] - return [Activity().deserialize(activity) for activity in response.body] + return ExpectedReplies().deserialize(response.body).activities async def _get_app_credentials( self, app_id: str, oauth_scope: str diff --git a/libraries/botbuilder-schema/botbuilder/schema/__init__.py b/libraries/botbuilder-schema/botbuilder/schema/__init__.py index bb3e7d75f..5fcb88ed7 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/__init__.py +++ b/libraries/botbuilder-schema/botbuilder/schema/__init__.py @@ -27,6 +27,7 @@ from ._models_py3 import ConversationReference from ._models_py3 import ConversationResourceResponse from ._models_py3 import ConversationsResult + from ._models_py3 import ExpectedReplies from ._models_py3 import Entity from ._models_py3 import Error from ._models_py3 import ErrorResponse, ErrorResponseException @@ -74,6 +75,7 @@ from ._models import ConversationReference from ._models import ConversationResourceResponse from ._models import ConversationsResult + from ._models import ExpectedReplies from ._models import Entity from ._models import Error from ._models import ErrorResponse, ErrorResponseException @@ -136,6 +138,7 @@ "ConversationReference", "ConversationResourceResponse", "ConversationsResult", + "ExpectedReplies", "Entity", "Error", "ErrorResponse", diff --git a/libraries/botbuilder-schema/botbuilder/schema/_models.py b/libraries/botbuilder-schema/botbuilder/schema/_models.py index 042c9e0bd..31e1a3f31 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/_models.py +++ b/libraries/botbuilder-schema/botbuilder/schema/_models.py @@ -806,6 +806,21 @@ def __init__(self, **kwargs): self.conversations = kwargs.get("conversations", None) +class ExpectedReplies(Model): + """ExpectedReplies. + + :param activities: A collection of Activities that conforms to the + ExpectedReplies schema. + :type activities: list[~botframework.connector.models.Activity] + """ + + _attribute_map = {"activities": {"key": "activities", "type": "[Activity]"}} + + def __init__(self, **kwargs): + super(ExpectedReplies, self).__init__(**kwargs) + self.activities = kwargs.get("activities", None) + + class Entity(Model): """Metadata object pertaining to an activity. diff --git a/libraries/botbuilder-schema/botbuilder/schema/_models_py3.py b/libraries/botbuilder-schema/botbuilder/schema/_models_py3.py index f079ac383..792ab6c13 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/_models_py3.py +++ b/libraries/botbuilder-schema/botbuilder/schema/_models_py3.py @@ -978,6 +978,21 @@ def __init__( self.conversations = conversations +class ExpectedReplies(Model): + """ExpectedReplies. + + :param activities: A collection of Activities that conforms to the + ExpectedReplies schema. + :type activities: list[~botframework.connector.models.Activity] + """ + + _attribute_map = {"activities": {"key": "activities", "type": "[Activity]"}} + + def __init__(self, *, activities=None, **kwargs) -> None: + super(ExpectedReplies, self).__init__(**kwargs) + self.activities = activities + + class Entity(Model): """Metadata object pertaining to an activity. From 807b15cf9f6aa7f04fa8c15bea52c90e18ac0035 Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Sun, 8 Mar 2020 10:34:51 -0700 Subject: [PATCH 6/7] fix test --- libraries/botbuilder-core/tests/test_bot_framework_adapter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/botbuilder-core/tests/test_bot_framework_adapter.py b/libraries/botbuilder-core/tests/test_bot_framework_adapter.py index 62041b7db..8493814fc 100644 --- a/libraries/botbuilder-core/tests/test_bot_framework_adapter.py +++ b/libraries/botbuilder-core/tests/test_bot_framework_adapter.py @@ -20,6 +20,7 @@ ConversationResourceResponse, ChannelAccount, DeliveryModes, + ExpectedReplies, ) from botframework.connector.aio import ConnectorClient from botframework.connector.auth import ( @@ -613,7 +614,7 @@ async def callback(context: TurnContext): ) assert invoke_response assert invoke_response.status == 200 - activities = invoke_response.body + activities = ExpectedReplies().deserialize(invoke_response.body).activities assert len(activities) == 3 assert activities[0]["text"] == "activity 1" assert activities[1]["text"] == "activity 2" From cea0e58882ef4fdc1742eb94e0519e5363e7757c Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Sun, 8 Mar 2020 10:46:10 -0700 Subject: [PATCH 7/7] fix expectReplies unit test --- .../botbuilder-core/tests/test_bot_framework_adapter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/botbuilder-core/tests/test_bot_framework_adapter.py b/libraries/botbuilder-core/tests/test_bot_framework_adapter.py index 8493814fc..891ecdeb5 100644 --- a/libraries/botbuilder-core/tests/test_bot_framework_adapter.py +++ b/libraries/botbuilder-core/tests/test_bot_framework_adapter.py @@ -616,9 +616,9 @@ async def callback(context: TurnContext): assert invoke_response.status == 200 activities = ExpectedReplies().deserialize(invoke_response.body).activities assert len(activities) == 3 - assert activities[0]["text"] == "activity 1" - assert activities[1]["text"] == "activity 2" - assert activities[2]["text"] == "activity 3" + assert activities[0].text == "activity 1" + assert activities[1].text == "activity 2" + assert activities[2].text == "activity 3" assert ( adapter.connector_client_mock.conversations.send_to_conversation.call_count == 0