@@ -117,3 +117,73 @@ async def async2(say):
117117 assert response .status == 200
118118 await asyncio .sleep (1 ) # wait a bit
119119 assert self .mock_received_requests ["/chat.postMessage" ] == 2
120+
121+ @pytest .mark .asyncio
122+ async def test_issue_545_context_copy_failure (self ):
123+ async def just_ack (ack ):
124+ await ack ()
125+
126+ async def async1 (context , say ):
127+ assert context .get ("foo" ) == "FOO"
128+ assert context .get ("ssl_context" ) is None
129+ await asyncio .sleep (0.3 )
130+ await say (text = "lazy function 1" )
131+
132+ async def async2 (context , say ):
133+ assert context .get ("foo" ) == "FOO"
134+ assert context .get ("ssl_context" ) is None
135+ await asyncio .sleep (0.5 )
136+ await say (text = "lazy function 2" )
137+
138+ app = AsyncApp (
139+ client = self .web_client ,
140+ signing_secret = self .signing_secret ,
141+ )
142+
143+ @app .middleware
144+ async def set_ssl_context (context , next_ ):
145+ from ssl import SSLContext
146+
147+ context ["foo" ] = "FOO"
148+ # This causes an error when starting lazy listener executions
149+ context ["ssl_context" ] = SSLContext ()
150+ await next_ ()
151+
152+ # 2021-12-13 11:52:46 ERROR Failed to run a middleware function (error: cannot pickle 'SSLContext' object)
153+ # Traceback (most recent call last):
154+ # File "/path/to/bolt-python/slack_bolt/app/async_app.py", line 585, in async_dispatch
155+ # ] = await self._async_listener_runner.run(
156+ # File "/path/to/bolt-python/slack_bolt/listener/asyncio_runner.py", line 167, in run
157+ # self._start_lazy_function(lazy_func, request)
158+ # File "/path/to/bolt-python/slack_bolt/listener/asyncio_runner.py", line 194, in _start_lazy_function
159+ # copied_request = self._build_lazy_request(request, func_name)
160+ # File "/path/to/bolt-python/slack_bolt/listener/asyncio_runner.py", line 201, in _build_lazy_request
161+ # copied_request = create_copy(request)
162+ # File "/path/to/bolt-python/slack_bolt/util/utils.py", line 48, in create_copy
163+ # return copy.deepcopy(original)
164+ # File "/path/to/python/lib/python3.9/copy.py", line 172, in deepcopy
165+ # y = _reconstruct(x, memo, *rv)
166+ # File "/path/to/python/lib/python3.9/copy.py", line 270, in _reconstruct
167+ # state = deepcopy(state, memo)
168+ # File "/path/to/python/lib/python3.9/copy.py", line 146, in deepcopy
169+ # y = copier(x, memo)
170+ # File "/path/to/python/lib/python3.9/copy.py", line 230, in _deepcopy_dict
171+ # y[deepcopy(key, memo)] = deepcopy(value, memo)
172+ # File "/path/to/python/lib/python3.9/copy.py", line 172, in deepcopy
173+ # y = _reconstruct(x, memo, *rv)
174+ # File "/path/to/python/lib/python3.9/copy.py", line 296, in _reconstruct
175+ # value = deepcopy(value, memo)
176+ # File "/path/to/python/lib/python3.9/copy.py", line 161, in deepcopy
177+ # rv = reductor(4)
178+ # TypeError: cannot pickle 'SSLContext' object
179+
180+ app .action ("a" )(
181+ ack = just_ack ,
182+ lazy = [async1 , async2 ],
183+ )
184+
185+ request = self .build_valid_request ()
186+ response = await app .async_dispatch (request )
187+ assert response .status == 200
188+ await asyncio .sleep (1 ) # wait a bit
189+ assert self .mock_received_requests ["/chat.postMessage" ] == 2
0 commit comments