8000 Merge branch 'master' into trboehre/oauth_flow · TheCompuGuru/botbuilder-python@0e34a7f · GitHub
[go: up one dir, main page]

Skip to content

Commit 0e34a7f

Browse files
authored
Merge branch 'master' into trboehre/oauth_flow
2 parents e696264 + 0af971b commit 0e34a7f

File tree

19 files changed

+383
-33
lines changed

19 files changed

+383
-33
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ![Bot Framework SDK v4 Python](./doc/media/FrameWorkPython.png)
22

3-
### [Click here to find out what's new with Bot Framework](https://github.com/Microsoft/botframework/blob/master/whats-new.md#whats-new)
3+
### [Click here to find out what's new with Bot Framework](https://docs.microsoft.com/en-us/azure/bot-service/what-is-new?view=azure-bot-service-4.0)
44

55
# Bot Framework SDK v4 for Python
66
[![Build status](https://fuselabs.visualstudio.com/SDK_v4/_apis/build/status/Python/SDK_v4-Python-CI)](https://fuselabs.visualstudio.com/SDK_v4/_build/latest?definitionId=431)

ci-pr-pipeline.yml

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ variables:
66
COVERALLS_GIT_COMMIT: $(Build.SourceVersion)
77
COVERALLS_SERVICE_JOB_ID: $(Build.BuildId)
88
COVERALLS_SERVICE_NAME: python-ci
9-
python.version: 3.7.6
9+
python.36: 3.6.10
10+
python.37: 3.7.6
11+
python.38: 3.8.1
1012

1113

1214
jobs:
@@ -15,18 +17,26 @@ jobs:
1517
#Multi-configuration and multi-agent job options are not exported to YAML. Configure these options using documentation guidance: https://docs.microsoft.com/vsts/pipelines/process/phases
1618
pool:
1719
name: Hosted Ubuntu 1604
18-
#Your build pipeline references the ‘python.version’ variable, which you’ve selected to be settable at queue time. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab, and then select the option to make it settable at queue time. See https://go.microsoft.com/fwlink/?linkid=865971
19-
#Your build pipeline references the ‘python.version’ variable, which you’ve selected to be settable at queue time. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab, and then select the option to make it settable at queue time. See https://go.microsoft.com/fwlink/?linkid=865971
20+
21+
strategy:
22+
matrix:
23+
Python36:
24+
PYTHON_VERSION: '$(python.36)'
25+
Python37:
26+
PYTHON_VERSION: '$(python.37)'
27+
Python38:
28+
PYTHON_VERSION: '$(python.38)'
29+
maxParallel: 3
2030

2131
steps:
2232
- powershell: |
2333
Get-ChildItem env:* | sort-object name | Format-Table -Autosize -Wrap | Out-String -Width 120
2434
displayName: 'Get environment vars'
2535
2636
- task: UsePythonVersion@0
27-
displayName: 'Use Python $(python.version)'
37+
displayName: 'Use Python $(PYTHON_VERSION)'
2838
inputs:
29-
versionSpec: '$(python.version)'
39+
versionSpec: '$(PYTHON_VERSION)'
3040

3141
- script: 'sudo ln -s /opt/hostedtoolcache/Python/3.6.9/x64/lib/libpython3.6m.so.1.0 /usr/lib/libpython3.6m.so'
3242
displayName: libpython3.6m
@@ -53,21 +63,21 @@ jobs:
5363
pip install pytest
5464
pip install pytest-cov
5565
pip install coveralls
56-
pytest --junitxml=junit/test-results.xml --cov-config=.coveragerc --cov --cov-report=xml --cov-report=html
66+
pytest --junitxml=junit/test-results.$(PYTHON_VERSION).xml --cov-config=.coveragerc --cov --cov-report=xml --cov-report=html
5767
displayName: Pytest
5868
69+
- task: PublishTestResults@2
70+
displayName: 'Publish Test Results **/test-results.$(PYTHON_VERSION).xml'
71+
inputs:
72+
testResultsFiles: '**/test-results.$(PYTHON_VERSION).xml'
73+
testRunTitle: 'Python $(PYTHON_VERSION)'
74+
5975
- script: 'black --check libraries'
6076
displayName: 'Check Black compliant'
6177

6278
- script: 'pylint --rcfile=.pylintrc libraries'
6379
displayName: Pylint
6480

65-
- task: PublishTestResults@2
66-
displayName: 'Publish Test Results **/test-results.xml'
67-
inputs:
68-
testResultsFiles: '**/test-results.xml'
69-
testRunTitle: 'Python $(python.version)'
70-
7181
- script: 'COVERALLS_REPO_TOKEN=$(COVERALLS_TOKEN) coveralls'
7282
displayName: 'Push test results to coveralls https://coveralls.io/github/microsoft/botbuilder-python'
7383
continueOnError: true

libraries/botbuilder-adapters-slack/botbuilder/adapters/slack/slack_client.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99

1010
import aiohttp
1111
from aiohttp.web_request import Request
12-
from slack.web.client import WebClient
13-
from slack.web.slack_response import SlackResponse
1412

1513
from botbuilder.schema import Activity
1614
from botbuilder.adapters.slack import SlackAdapterOptions
1715
from botbuilder.adapters.slack.slack_message import SlackMessage
1816

17+
from slack.web.client import WebClient
18+
from slack.web.slack_response import SlackResponse
19+
1920
POST_MESSAGE_URL = "https://slack.com/api/chat.postMessage"
2021
POST_EPHEMERAL_MESSAGE_URL = "https://slack.com/api/chat.postEphemeral"
2122

libraries/botbuilder-adapters-slack/botbuilder/adapters/slack/slack_helper.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
from aiohttp.web_request import Request
88
from aiohttp.web_response import Response
9-
from slack.web.classes.attachments import Attachment
109

1110
from botbuilder.schema import (
1211
Activity,
@@ -15,6 +14,8 @@
1514
ActivityTypes,
1615
)
1716

17+
from slack.web.classes.attachments import Attachment
18+
1819
from .slack_message import SlackMessage
1920
from .slack_client import SlackClient
2021
from .slack_event import SlackEvent

libraries/botbuilder-adapters-slack/botbuilder/adapters/slack/slack_payload.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
from typing import Optional, List
55

6-
from slack.web.classes.actions import Action
7-
86
from botbuilder.adapters.slack.slack_message import SlackMessage
97

8+
from slack.web.classes.actions import Action
9+
1010

1111
class SlackPayload:
1212
def __init__(self, **kwargs):

libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,9 @@ async def create_conversation(
305305
)
306306
)
307307
client = await self.create_connector_client(reference.service_url)
308-
308+
resource_response = await client.conversations.create_conversation(
309+
parameters
310+
)
309311
# Mix in the tenant ID if specified. This is required for MS Teams.
310312
if reference.conversation is not None and reference.conversation.tenant_id:
311313
# Putting tenant_id in channel_data is a temporary while we wait for the Teams API to be updated
@@ -316,9 +318,6 @@ async def create_conversation(
316318
# Permanent solution is to put tenant_id in parameters.tenant_id
317319
parameters.tenant_id = reference.conversation.tenant_id
318320

319-
resource_response = await client.conversations.create_conversation(
320-
parameters
321-
)
322321
request = TurnContext.apply_conversation_reference(
323322
Activity(type=ActivityTypes.event, name="CreateConversation"),
324323
reference,

libraries/botbuilder-core/botbuilder/core/teams/teams_info.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
33

4-
from typing import List
5-
from botbuilder.core.turn_context import TurnContext
4+
from typing import List, Tuple
5+
from botbuilder.schema import ConversationParameters, ConversationReference
6+
from botbuilder.core.turn_context import Activity, TurnContext
67
from botbuilder.schema.teams import (
78
ChannelInfo,
89
TeamDetails,
@@ -14,6 +15,39 @@
1415

1516

1617
class TeamsInfo:
18+
@staticmethod
19+
async def send_message_to_teams_channel(
20+
turn_context: TurnContext, activity: Activity, teams_channel_id: str
21+
) -> Tuple[ConversationReference, str]:
22+
if not turn_context:
23+
raise ValueError("The turn_context cannot be None")
24+
if not turn_context.activity:
25+
raise ValueError("The turn_context.activity cannot be None")
26+
if not teams_channel_id:
27+
raise ValueError("The teams_channel_id cannot be None or empty")
28+
29+
old_ref = TurnContext.get_conversation_reference(turn_context.activity)
30+
conversation_parameters = ConversationParameters(
31+
is_group=True,
32+
channel_data={"channel": {"id": teams_channel_id}},
33+
activity=activity,
34+
)
35+
36+
result = await turn_context.adapter.create_conversation(
37+
old_ref, TeamsInfo._create_conversation_callback, conversation_parameters
38+
)
39+
return (result[0], result[1])
40+
41+
@staticmethod
42+
async def _create_conversation_callback(
43+
new_turn_context,
44+
) -> Tuple[ConversationReference, str]:
45+
new_activity_id = new_turn_context.activity.id
46+
conversation_reference = TurnContext.get_conversation_reference(
47+
new_turn_context.activity
48+
)
49+
return (conversation_reference, new_activity_id)
50+
1751
@staticmethod
1852
async def get_team_details(
1953
turn_context: TurnContext, team_id: str = ""

libraries/botbuilder-core/tests/simple_adapter.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,32 @@
22
# Licensed under the MIT License.
33

44
import unittest
5-
from typing import List
5+
from typing import List, Tuple, Awaitable, Callable
66
from botbuilder.core import BotAdapter, TurnContext
7-
from botbuilder.schema import Activity, ConversationReference, ResourceResponse
7+
from botbuilder.schema import (
8+
Activity,
9+
ConversationReference,
10+
ResourceResponse,
11+
ConversationParameters,
12+
)
813

914

1015
class SimpleAdapter(BotAdapter):
1116
# pylint: disable=unused-argument
1217

13-
def __init__(self, call_on_send=None, call_on_update=None, call_on_delete=None):
18+
def __init__(
19+
self,
20+
call_on_send=None,
21+
call_on_update=None,
22+
call_on_delete=None,
23+
call_create_conversation=None,
24+
):
1425
super(SimpleAdapter, self).__init__()
1526
self.test_aux = unittest.TestCase("__init__")
1627
self._call_on_send = call_on_send
1728
self._call_on_update = call_on_update
1829
self._call_on_delete = call_on_delete
30+
self._call_create_conversation = call_create_conversation
1931

2032
async def delete_activity(
2133
self, context: TurnContext, reference: ConversationReference
@@ -46,6 +58,15 @@ async def send_activities(
4658

4759
return responses
4860

61+
async def create_conversation(
62+
self,
63+
reference: ConversationReference,
64+
logic: Callable[[TurnContext], Awaitable] = None,
65+
conversation_parameters: ConversationParameters = None,
66+
) -> Tuple[ConversationReference, str]:
67+
if self._call_create_conversation is not None:
68+
self._call_create_conversation()
69+
4970
async def update_activity(self, context: TurnContext, activity: Activity):
5071
self.test_aux.assertIsNotNone(
5172
activity, "SimpleAdapter.update_activity: missing activity"

libraries/botbuilder-core/tests/teams/simple_adapter.py renamed to libraries/botbuilder-core/tests/teams/simple_adapter_with_create_conversation.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,32 @@
22
# Licensed under the MIT License.
33

44
import unittest
5-
from typing import List
5+
from typing import List, Tuple, Awaitable, Callable
66
from botbuilder.core import BotAdapter, TurnContext
7-
from botbuilder.schema import Activity, ConversationReference, ResourceResponse
7+
from botbuilder.schema import (
8+
Activity,
9+
ConversationReference,
10+
ResourceResponse,
11+
ConversationParameters,
12+
)
813

914

10-
class SimpleAdapter(BotAdapter):
15+
class SimpleAdapterWithCreateConversation(BotAdapter):
1116
# pylint: disable=unused-argument
1217

13-
def __init__(self, call_on_send=None, call_on_update=None, call_on_delete=None):
14-
super(SimpleAdapter, self).__init__()
18+
def __init__(
19+
self,
20+
call_on_send=None,
21+
call_on_update=None,
22+
call_on_delete=None,
23+
call_create_conversation=None,
24+
):
25+
super(SimpleAdapterWithCreateConversation, self).__init__()
1526
self.test_aux = unittest.TestCase("__init__")
1627
self._call_on_send = call_on_send
1728
self._call_on_update = call_on_update
1829
self._call_on_delete = call_on_delete
30+
self._call_create_conversation = call_create_conversation
1931

2032
async def delete_activity(
2133
self, context: TurnContext, reference: ConversationReference
@@ -46,6 +58,17 @@ async def send_activities(
4658

4759
return responses
4860

61+
async def create_conversation(
62+
self,
63+
reference: ConversationReference,
64+
logic: Callable[[TurnContext], Awaitable] = None,
65+
conversation_parameters: ConversationParameters = None,
66+
) -> Tuple[ConversationReference, str]:
67+
if self._call_create_conversation is not None:
68+
self._call_create_conversation()
69+
ref = ConversationReference(activity_id="new_conversation_id")
70+
return (ref, "reference123")
71+
4972
async def update_activity(self, context: TurnContext, activity: Activity):
5073
self.test_aux.assertIsNotNone(
5174
activity, "SimpleAdapter.update_activity: missing activity"
@@ -57,4 +80,4 @@ async def update_activity(self, context: TurnContext, activity: Activity):
5780

5881
async def process_request(self, activity, handler):
5982
context = TurnContext(self, activity)
60-
return self.run_pipeline(context, handler)
83+
return await self.run_pipeline(context, handler)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
import aiounittest
5+
6+
7+
from botbuilder.core import TurnContext, MessageFactory
8+
from botbuilder.core.teams import TeamsInfo, TeamsActivityHandler
9+
from botbuilder.schema import Activity
10+
from botbuilder.schema.teams import TeamsChannelData, TeamInfo
11+
from botframework.connector import Channels
12+
from simple_adapter_with_create_conversation import SimpleAdapterWithCreateConversation
13+
14+
15+
class TestTeamsInfo(aiounittest.AsyncTestCase):
16+
async def test_send_message_to_teams(self):
17+
def create_conversation():
18+
pass
19+
20+
adapter = SimpleAdapterWithCreateConversation(
21+
call_create_conversation=create_conversation
22+
)
23+
24+
activity = Activity(
25+
type="message",
26+
text="test_send_message_to_teams_channel",
27+
channel_id=Channels.ms_teams,
28+
service_url="https://example.org",
29+
channel_data=TeamsChannelData(team=TeamInfo(id="team-id")),
30+
)
31+
turn_context = TurnContext(adapter, activity)
32+
handler = TestTeamsActivityHandler()
33+
await handler.on_turn(turn_context)
34+
35+
36+
class TestTeamsActivityHandler(TeamsActivityHandler):
37+
async def on_turn(self, turn_context: TurnContext):
38+
super().on_turn(turn_context)
39+
40+
if turn_context.activity.text == "test_send_message_to_teams_channel":
41+
await self.call_send_message_to_teams(turn_context)
42+
43+
async def call_send_message_to_teams(self, turn_context: TurnContext):
44+
msg = MessageFactory.text("call_send_message_to_teams")
45+
channel_id = "teams_channel_123"
46+
reference = await TeamsInfo.send_message_to_teams_channel(
47+
turn_context, msg, channel_id
48+
)
49+
50+
assert reference[0].activity_id == "new_conversation_id"
51+
assert reference[1] == "reference123"
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# EchoBot
2+
3+
Bot Framework v4 echo bot sample.
4+
5+
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to create a simple bot that accepts input from the user and echoes it back.
6+
7+
## Running the sample
8+
- Clone the repository
9+
```bash
10+
git clone https://github.com/Microsoft/botbuilder-python.git
11+
```
12+
- Activate your desired virtual environment
13+
- Bring up a terminal, navigate to `botbuilder-python\samples\02.echo-bot` folder
14+
- In the terminal, type `pip install -r requirements.txt`
15+
- In the terminal, type `python app.py`
16+
17+
## Testing the bot using Bot Framework Emulator
18+
[Microsoft Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.
19+
20+
- Install the Bot Framework emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
21+
22+
### Connect to bot using Bot Framework Emulator
23+
- Launch Bot Framework Emulator
24+
- Paste this URL in the emulator window - http://localhost:3978/api/messages
25+
26+
## Further reading
27+
28+
- [Bot Framework Documentation](https://docs.botframework.com)
29+
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
30+
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)

0 commit comments

Comments
 (0)
0