10000 add BotContextServiceCollection functionality and tests · openvelora/botbuilder-python@36f3415 · GitHub
[go: up one dir, main page]

Skip to content

Commit 36f3415

Browse files
committed
add BotContextServiceCollection functionality and tests
1 parent 2f7e15a commit 36f3415

File tree

3 files changed

+71
-34
lines changed

3 files changed

+71
-34
lines changed

libraries/botbuilder-core/botbuilder/core/bot_context.py

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typing import List, Callable, Iterable, Tuple
99
from botbuilder.schema import Activity, ActivityTypes, ConversationReference, ResourceResponse
1010

11+
from .bot_context_service_collection import BotContextServiceCollection
1112
# from .bot_adapter import BotAdapter
1213

1314

@@ -21,42 +22,12 @@ def __init__(self, adapter, activity: Activity):
2122
self.adapter = adapter
2223
self.activity: Activity = activity
2324
self.responses: List[Activity] = []
24-
self._services: dict = {}
25+
self._services: BotContextServiceCollection = BotContextServiceCollection()
2526
self._responded: bool = False
2627
self._on_send_activity: Callable[[]] = []
2728
self._on_update_activity: Callable[[]] = []
2829
self._on_delete_activity: Callable[[]] = []
2930

30-
def get(self, key: str) -> object:
31-
if not key or not isinstance(key, str):
32-
raise TypeError('"key" must be a valid string.')
33-
try:
34-
return self._services[key]
35-
except KeyError:
36-
raise KeyError('%s not found in BotContext._services.' % key)
37-
38-
def has(self, key: str) -> bool:
39-
"""
40-
Returns True is set() has been called for a key. The cached value may be of type 'None'.
41-
:param key:
42-
:return:
43-
"""
44-
if key in self._services:
45-
return True
46-
return False
47-
48-
def set(self, key: str, value: object) -> None:
49-
"""
50-
Caches a value for the lifetime of the current turn.
51-
:param key:
52-
:param value:
53-
:return:
54-
"""
55-
if not key or not isinstance(key, str):
56-
raise KeyError('"key" must be a valid string.')
57-
58-
self._services[key] = value
59-
6031
async def send_activity(self, *activity_or_text: Tuple[Activity, str]):
6132
reference = BotContext.get_conversation_reference(self.activity)
6233
output = [BotContext.apply_conversation_reference(
Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
33

4-
from typing import Any
4+
from typing import Any, Dict
55

66

77
class BotContextServiceCollection(object):
8-
_services = {}
8+
"""
9+
Represents a set of collection of services associated with the BotContext.
10+
"""
11+
12+
def __init__(self):
13+
self._services = {}
914

1015
def get(self, key: str) -> Any:
16+
"""
17+
Get a service by its key.
18+
:param key:
19+
:return:
20+
"""
1121
if key is None:
1222
raise TypeError('BotContextServiceCollection.get(): the provided "key" cannot be of type None.')
1323
try:
@@ -18,12 +28,32 @@ def get(self, key: str) -> Any:
1828
raise e
1929

2030
def add(self, key: str, service: Any) -> None:
31+
"""
32+
Add a service with a specified key.
33+
:param key:
34+
:param service:
35+
:return:
36+
"""
2137
if key is None:
2238
raise TypeError('BotContextServiceCollection.get(): the provided "key" cannot be of type None.')
2339
if service is None:
2440
raise TypeError('BotContextServiceCollection.get(): the provided "service" cannot be of type None.')
25-
41+
if key in self._services:
42+
raise ValueError(f'A service is already registered with the specified key: "{key}".')
2643
try:
2744
self._services[key] = service
2845
except BaseException as e:
2946
raise e
47+
48+
def get_services(self, type: Any) -> Dict[str, Any]:
49+
"""
50+
Returns all entries in the collection of a specified type.
51+
:param type:
52+
:return:
53+
"""
54+
mapping = {}
55+
for key in self._services:
56+
if isinstance(self._services[key], type):
57+
mapping[key] = self._services[key]
58+
59+
return mapping

libraries/botbuilder-core/tests/test_bot_context_service_collection.py

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

4+
from typing import Callable
45
from botbuilder.core import BotContextServiceCollection
56

67

@@ -55,3 +56,38 @@ def test_get_on_missing_key_should_fail(self):
5556
pass
5657
else:
5758
raise AssertionError('Should not have successfully retrieved service for missing key.')
59+
60+
def test_adding_a_duplicate_key_should_fail(self):
61+
services = BotContextServiceCollection()
62+
services.add('key', lambda x: x * 1)
63+
64+
try:
65+
services.add('key', lambda x: x * 2)
66+
except ValueError:
67+
pass
68+
else:
69+
raise AssertionError('Should not have added duplicate key.')
70+
71+
def test_get_services_should_return_dict_with_two_services(self):
72+
services = BotContextServiceCollection()
73+
services.add('key', lambda x: x * 1)
74+
services.add('key_2', lambda x: x)
75+
76+
callable_services = services.get_services(Callable)
77+
number_of_services = 0
78+
for key in callable_services:
79+
number_of_services += 1
80+
81+
assert number_of_services == 2
82+
83+
def test_get_services_should_return_dict_with_no_services(self):
84+
services = BotContextServiceCollection()
85+
services.add('key', lambda x: x * 1)
86+
services.add('key_2', lambda x: x)
87+
88+
callable_services = services.get_services(int)
89+
number_of_services = 0
90+
for key in callable_services:
91+
number_of_services += 1
92+
93+
assert number_of_services == 0

0 commit comments

Comments
 (0)
290E
0