File tree 2 files changed +71
-4
lines changed
tests/unit/mixed/async_compat 2 files changed +71
-4
lines changed Original file line number Diff line number Diff line change @@ -100,10 +100,14 @@ async def _acquire_non_blocking(self, me):
100
100
# Hence, we flag this task as cancelled again, so that the next
101
101
# `await` will raise the CancelledError.
102
102
asyncio .current_task ().cancel ()
103
- if task .done () and task .exception () is None :
104
- self ._owner = me
105
- self ._count = 1
106
- return True
103
+ if task .done ():
104
+ exception = task .exception ()
105
+ if exception is None :
106
+ self ._owner = me
107
+ self ._count = 1
108
+ return True
109
+ else :
110
+ raise exception
107
111
task .cancel ()
108
112
return False
109
113
Original file line number Diff line number Diff line change @@ -168,6 +168,69 @@ async def waiter():
168
168
assert lock .locked () # waiter_non_blocking still owns it!
169
169
170
170
171
+ @pytest .mark .asyncio
172
+ async def test_async_r_lock_acquire_non_blocking_exception (mocker ):
173
+ lock = AsyncRLock ()
174
+ exc = RuntimeError ("it broke!" )
175
+
176
+ assert not lock .locked ()
177
+
178
+ # Not sure asyncio.Lock.acquire is even fallible, but should it be or ever
179
+ # become, our AsyncRLock should re-raise the exception.
180
+ acquire_mock = mocker .patch ("asyncio.Lock.acquire" , autospec = True ,
181
+ side_effect = asyncio .Lock .acquire )
182
+ awaits = 0
183
+
184
+ async def blocker ():
185
+ nonlocal awaits
186
+
187
+ assert awaits == 0
188
+ awaits += 1
189
+ assert await lock .acquire ()
190
+
191
+ assert awaits == 1
192
+ awaits += 1
193
+ await asyncio .sleep (0 )
194
+
195
+ assert awaits == 3
196
+ awaits += 1
197
+ await asyncio .sleep (0 )
198
+
199
+ assert awaits == 5
200
+ awaits += 1
201
+ await asyncio .sleep (0 )
202
+
203
+ assert awaits == 7
204
+ lock .release ()
205
+
206
+ async def waiter_non_blocking ():
207
+ nonlocal awaits
208
+ nonlocal acquire_mock
209
+
210
+ assert awaits == 2
211
+ acquire_mock .side_effect = exc
212
+ coro = lock .acquire (blocking = False )
213
+ fut = asyncio .ensure_future (coro )
214
+ assert not fut .done ()
215
+ awaits += 1
216
+ await asyncio .sleep (0 )
217
+
218
+ assert awaits == 4
219
+ assert not fut .done ()
220
+ awaits += 1
221
+ await asyncio .sleep (0 )
222
+
223
+ assert awaits == 6
224
+ assert fut .done ()
225
+ assert fut .exception () is exc
226
+ awaits += 1
227
+
228
+
229
+ assert not lock .locked ()
230
+ await asyncio .gather (blocker (), waiter_non_blocking ())
231
+ assert not lock .locked ()
232
+
233
+
171
234
@pytest .mark .parametrize ("waits" , range (1 , 10 ))
172
235
@pytest .mark .asyncio
173
236
async def test_async_r_lock_acquire_cancellation (waits ):
You can’t perform that action at this time.
0 commit comments