Skip to content

Commit 0ca2874

Browse files
committed
version 1.15.0
1 parent ad7117b commit 0ca2874

File tree

10 files changed

+150
-120
lines changed

10 files changed

+150
-120
lines changed

docs/api-docs/slack_bolt/app/app.html

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,21 +1234,25 @@ <h1 class="title">Module <code>slack_bolt.app.app</code></h1>
12341234
def _init_context(self, req: BoltRequest):
12351235
req.context[&#34;logger&#34;] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
12361236
req.context[&#34;token&#34;] = self._token
1237-
if self._token is not None:
1238-
# This WebClient instance can be safely singleton
1239-
req.context[&#34;client&#34;] = self._client
1240-
else:
1241-
# Set a new dedicated instance for this request
1242-
client_per_request: WebClient = WebClient(
1243-
token=None, # the token will be set later
1244-
base_url=self._client.base_url,
1245-
timeout=self._client.timeout,
1246-
ssl=self._client.ssl,
1247-
proxy=self._client.proxy,
1248-
headers=self._client.headers,
1249-
team_id=req.context.team_id,
1250-
)
1251-
req.context[&#34;client&#34;] = client_per_request
1237+
# Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
1238+
# The intention was to avoid creating a new instance per request
1239+
# in the interest of runtime performance/memory footprint optimization.
1240+
# However, developers may want to replace the token held by req.context.client in some situations.
1241+
# In this case, this behavior can result in thread-unsafe data modification on `self._client`.
1242+
# (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
1243+
# Thus, we&#39;ve changed the behavior to create a new instance per request regardless of token argument
1244+
# in the App initialization starting v1.15.
1245+
# The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
1246+
client_per_request: WebClient = WebClient(
1247+
token=self._token, # this can be None, and it can be set later on
1248+
base_url=self._client.base_url,
1249+
timeout=self._client.timeout,
1250+
ssl=self._client.ssl,
1251+
proxy=self._client.proxy,
1252+
headers=self._client.headers,
1253+
team_id=req.context.team_id,
1254+
)
1255+
req.context[&#34;client&#34;] = client_per_request
12521256

12531257
@staticmethod
12541258
def _to_listener_functions(
@@ -2653,21 +2657,25 @@ <h2 id="args">Args</h2>
26532657
def _init_context(self, req: BoltRequest):
26542658
req.context[&#34;logger&#34;] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
26552659
req.context[&#34;token&#34;] = self._token
2656-
if self._token is not None:
2657-
# This WebClient instance can be safely singleton
2658-
req.context[&#34;client&#34;] = self._client
2659-
else:
2660-
# Set a new dedicated instance for this request
2661-
client_per_request: WebClient = WebClient(
2662-
token=None, # the token will be set later
2663-
base_url=self._client.base_url,
2664-
timeout=self._client.timeout,
2665-
ssl=self._client.ssl,
2666-
proxy=self._client.proxy,
2667-
headers=self._client.headers,
2668-
team_id=req.context.team_id,
2669-
)
2670-
req.context[&#34;client&#34;] = client_per_request
2660+
# Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
2661+
# The intention was to avoid creating a new instance per request
2662+
# in the interest of runtime performance/memory footprint optimization.
2663+
# However, developers may want to replace the token held by req.context.client in some situations.
2664+
# In this case, this behavior can result in thread-unsafe data modification on `self._client`.
2665+
# (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
2666+
# Thus, we&#39;ve changed the behavior to create a new instance per request regardless of token argument
2667+
# in the App initialization starting v1.15.
2668+
# The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
2669+
client_per_request: WebClient = WebClient(
2670+
token=self._token, # this can be None, and it can be set later on
2671+
base_url=self._client.base_url,
2672+
timeout=self._client.timeout,
2673+
ssl=self._client.ssl,
2674+
proxy=self._client.proxy,
2675+
headers=self._client.headers,
2676+
team_id=req.context.team_id,
2677+
)
2678+
req.context[&#34;client&#34;] = client_per_request
26712679

26722680
@staticmethod
26732681
def _to_listener_functions(

docs/api-docs/slack_bolt/app/async_app.html

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,23 +1268,27 @@ <h1 class="title">Module <code>slack_bolt.app.async_app</code></h1>
12681268
def _init_context(self, req: AsyncBoltRequest):
12691269
req.context[&#34;logger&#34;] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
12701270
req.context[&#34;token&#34;] = self._token
1271-
if self._token is not None:
1272-
# This AsyncWebClient instance can be safely singleton
1273-
req.context[&#34;client&#34;] = self._async_client
1274-
else:
1275-
# Set a new dedicated instance for this request
1276-
client_per_request: AsyncWebClient = AsyncWebClient(
1277-
token=None, # the token will be set later
1278-
base_url=self._async_client.base_url,
1279-
timeout=self._async_client.timeout,
1280-
ssl=self._async_client.ssl,
1281-
proxy=self._async_client.proxy,
1282-
session=self._async_client.session,
1283-
trust_env_in_session=self._async_client.trust_env_in_session,
1284-
headers=self._async_client.headers,
1285-
team_id=req.context.team_id,
1286-
)
1287-
req.context[&#34;client&#34;] = client_per_request
1271+
# Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
1272+
# The intention was to avoid creating a new instance per request
1273+
# in the interest of runtime performance/memory footprint optimization.
1274+
# However, developers may want to replace the token held by req.context.client in some situations.
1275+
# In this case, this behavior can result in thread-unsafe data modification on `self._client`.
1276+
# (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
1277+
# Thus, we&#39;ve changed the behavior to create a new instance per request regardless of token argument
1278+
# in the App initialization starting v1.15.
1279+
# The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
1280+
client_per_request: AsyncWebClient = AsyncWebClient(
1281+
token=self._token, # this can be None, and it can be set later on
1282+
base_url=self._async_client.base_url,
1283+
timeout=self._async_client.timeout,
1284+
ssl=self._async_client.ssl,
1285+
proxy=self._async_client.proxy,
1286+
session=self._async_client.session,
1287+
trust_env_in_session=self._async_client.trust_env_in_session,
1288+
headers=self._async_client.headers,
1289+
team_id=req.context.team_id,
1290+
)
1291+
req.context[&#34;client&#34;] = client_per_request
12881292

12891293
@staticmethod
12901294
def _to_listener_functions(
@@ -2583,23 +2587,27 @@ <h2 id="args">Args</h2>
25832587
def _init_context(self, req: AsyncBoltRequest):
25842588
req.context[&#34;logger&#34;] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
25852589
req.context[&#34;token&#34;] = self._token
2586-
if self._token is not None:
2587-
# This AsyncWebClient instance can be safely singleton
2588-
req.context[&#34;client&#34;] = self._async_client
2589-
else:
2590-
# Set a new dedicated instance for this request
2591-
client_per_request: AsyncWebClient = AsyncWebClient(
2592-
token=None, # the token will be set later
2593-
base_url=self._async_client.base_url,
2594-
timeout=self._async_client.timeout,
2595-
ssl=self._async_client.ssl,
2596-
proxy=self._async_client.proxy,
2597-
session=self._async_client.session,
2598-
trust_env_in_session=self._async_client.trust_env_in_session,
2599-
headers=self._async_client.headers,
2600-
team_id=req.context.team_id,
2601-
)
2602-
req.context[&#34;client&#34;] = client_per_request
2590+
# Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
2591+
# The intention was to avoid creating a new instance per request
2592+
# in the interest of runtime performance/memory footprint optimization.
2593+
# However, developers may want to replace the token held by req.context.client in some situations.
2594+
# In this case, this behavior can result in thread-unsafe data modification on `self._client`.
2595+
# (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
2596+
# Thus, we&#39;ve changed the behavior to create a new instance per request regardless of token argument
2597+
# in the App initialization starting v1.15.
2598+
# The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
2599+
client_per_request: AsyncWebClient = AsyncWebClient(
2600+
token=self._token, # this can be None, and it can be set later on
2601+
base_url=self._async_client.base_url,
2602+
timeout=self._async_client.timeout,
2603+
ssl=self._async_client.ssl,
2604+
proxy=self._async_client.proxy,
2605+
session=self._async_client.session,
2606+
trust_env_in_session=self._async_client.trust_env_in_session,
2607+
headers=self._async_client.headers,
2608+
team_id=req.context.team_id,
2609+
)
2610+
req.context[&#34;client&#34;] = client_per_request
26032611

26042612
@staticmethod
26052613
def _to_listener_functions(

docs/api-docs/slack_bolt/app/index.html

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,21 +1281,25 @@ <h2 id="args">Args</h2>
12811281
def _init_context(self, req: BoltRequest):
12821282
req.context[&#34;logger&#34;] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
12831283
req.context[&#34;token&#34;] = self._token
1284-
if self._token is not None:
1285-
# This WebClient instance can be safely singleton
1286-
req.context[&#34;client&#34;] = self._client
1287-
else:
1288-
# Set a new dedicated instance for this request
1289-
client_per_request: WebClient = WebClient(
1290-
token=None, # the token will be set later
1291-
base_url=self._client.base_url,
1292-
timeout=self._client.timeout,
1293-
ssl=self._client.ssl,
1294-
proxy=self._client.proxy,
1295-
headers=self._client.headers,
1296-
team_id=req.context.team_id,
1297-
)
1298-
req.context[&#34;client&#34;] = client_per_request
1284+
# Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
1285+
# The intention was to avoid creating a new instance per request
1286+
# in the interest of runtime performance/memory footprint optimization.
1287+
# However, developers may want to replace the token held by req.context.client in some situations.
1288+
# In this case, this behavior can result in thread-unsafe data modification on `self._client`.
1289+
# (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
1290+
# Thus, we&#39;ve changed the behavior to create a new instance per request regardless of token argument
1291+
# in the App initialization starting v1.15.
1292+
# The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
1293+
client_per_request: WebClient = WebClient(
1294+
token=self._token, # this can be None, and it can be set later on
1295+
base_url=self._client.base_url,
1296+
timeout=self._client.timeout,
1297+
ssl=self._client.ssl,
1298+
proxy=self._client.proxy,
1299+
headers=self._client.headers,
1300+
team_id=req.context.team_id,
1301+
)
1302+
req.context[&#34;client&#34;] = client_per_request
12991303

13001304
@staticmethod
13011305
def _to_listener_functions(

docs/api-docs/slack_bolt/async_app.html

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,23 +1421,27 @@ <h2 id="args">Args</h2>
14211421
def _init_context(self, req: AsyncBoltRequest):
14221422
req.context[&#34;logger&#34;] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
14231423
req.context[&#34;token&#34;] = self._token
1424-
if self._token is not None:
1425-
# This AsyncWebClient instance can be safely singleton
1426-
req.context[&#34;client&#34;] = self._async_client
1427-
else:
1428-
# Set a new dedicated instance for this request
1429-
client_per_request: AsyncWebClient = AsyncWebClient(
1430-
token=None, # the token will be set later
1431-
base_url=self._async_client.base_url,
1432-
timeout=self._async_client.timeout,
1433-
ssl=self._async_client.ssl,
1434-
proxy=self._async_client.proxy,
1435-
session=self._async_client.session,
1436-
trust_env_in_session=self._async_client.trust_env_in_session,
1437-
headers=self._async_client.headers,
1438-
team_id=req.context.team_id,
1439-
)
1440-
req.context[&#34;client&#34;] = client_per_request
1424+
# Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
1425+
# The intention was to avoid creating a new instance per request
1426+
# in the interest of runtime performance/memory footprint optimization.
1427+
# However, developers may want to replace the token held by req.context.client in some situations.
1428+
# In this case, this behavior can result in thread-unsafe data modification on `self._client`.
1429+
# (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
1430+
# Thus, we&#39;ve changed the behavior to create a new instance per request regardless of token argument
1431+
# in the App initialization starting v1.15.
1432+
# The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
1433+
client_per_request: AsyncWebClient = AsyncWebClient(
1434+
token=self._token, # this can be None, and it can be set later on
1435+
base_url=self._async_client.base_url,
1436+
timeout=self._async_client.timeout,
1437+
ssl=self._async_client.ssl,
1438+
proxy=self._async_client.proxy,
1439+
session=self._async_client.session,
1440+
trust_env_in_session=self._async_client.trust_env_in_session,
1441+
headers=self._async_client.headers,
1442+
team_id=req.context.team_id,
1443+
)
1444+
req.context[&#34;client&#34;] = client_per_request
14411445

14421446
@staticmethod
14431447
def _to_listener_functions(
@@ -3884,7 +3888,7 @@ <h3>Class variables</h3>
38843888
**kwargs,
38853889
)
38863890
elif isinstance(text_or_whole_response, dict):
3887-
message: dict = text_or_whole_response
3891+
message: dict = create_copy(text_or_whole_response)
38883892
if &#34;channel&#34; not in message:
38893893
message[&#34;channel&#34;] = channel or self.channel
38903894
return await self.client.chat_postMessage(**message)

docs/api-docs/slack_bolt/context/say/async_say.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ <h1 class="title">Module <code>slack_bolt.context.say.async_say</code></h1>
2929
<pre><code class="python">from typing import Optional, Union, Dict, Sequence
3030

3131
from slack_bolt.context.say.internals import _can_say
32+
from slack_bolt.util.utils import create_copy
3233
from slack_sdk.models.attachments import Attachment
3334
from slack_sdk.models.blocks import Block
3435
from slack_sdk.web.async_client import AsyncWebClient
@@ -73,7 +74,7 @@ <h1 class="title">Module <code>slack_bolt.context.say.async_say</code></h1>
7374
**kwargs,
7475
)
7576
elif isinstance(text_or_whole_response, dict):
76-
message: dict = text_or_whole_response
77+
message: dict = create_copy(text_or_whole_response)
7778
if &#34;channel&#34; not in message:
7879
message[&#34;channel&#34;] = channel or self.channel
7980
return await self.client.chat_postMessage(**message)
@@ -140,7 +141,7 @@ <h2 class="section-title" id="header-classes">Classes</h2>
140141
**kwargs,
141142
)
142143
elif isinstance(text_or_whole_response, dict):
143-
message: dict = text_or_whole_response
144+
message: dict = create_copy(text_or_whole_response)
144145
if &#34;channel&#34; not in message:
145146
message[&#34;channel&#34;] = channel or self.channel
146147
return await self.client.chat_postMessage(**message)

docs/api-docs/slack_bolt/context/say/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ <h2 class="section-title" id="header-classes">Classes</h2>
106106
**kwargs,
107107
)
108108
elif isinstance(text_or_whole_response, dict):
109-
message: dict = text_or_whole_response
109+
message: dict = create_copy(text_or_whole_response)
110110
if &#34;channel&#34; not in message:
111111
message[&#34;channel&#34;] = channel or self.channel
112112
return self.client.chat_postMessage(**message)

docs/api-docs/slack_bolt/context/say/say.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ <h1 class="title">Module <code>slack_bolt.context.say.say</code></h1>
3434
from slack_sdk.web import SlackResponse
3535

3636
from slack_bolt.context.say.internals import _can_say
37+
from slack_bolt.util.utils import create_copy
3738

3839

3940
class Say:
@@ -74,7 +75,7 @@ <h1 class="title">Module <code>slack_bolt.context.say.say</code></h1>
7475
**kwargs,
7576
)
7677
elif isinstance(text_or_whole_response, dict):
77-
message: dict = text_or_whole_response
78+
message: dict = create_copy(text_or_whole_response)
7879
if &#34;channel&#34; not in message:
7980
message[&#34;channel&#34;] = channel or self.channel
8081
return self.client.chat_postMessage(**message)
@@ -141,7 +142,7 @@ <h2 class="section-title" id="header-classes">Classes</h2>
141142
**kwargs,
142143
)
143144
elif isinstance(text_or_whole_response, dict):
144-
message: dict = text_or_whole_response
145+
message: dict = create_copy(text_or_whole_response)
145146
if &#34;channel&#34; not in message:
146147
message[&#34;channel&#34;] = channel or self.channel
147148
return self.client.chat_postMessage(**message)

0 commit comments

Comments
 (0)