@@ -251,15 +251,8 @@ def _preprocess_async_fixtures(
251
251
or default_loop_scope
252
252
or fixturedef .scope
253
253
)
254
- if scope == "function" :
255
- event_loop_fixture_id : Optional [str ] = "event_loop"
256
- else :
257
- event_loop_node = _retrieve_scope_root (collector , scope )
258
- event_loop_fixture_id = event_loop_node .stash .get (
259
- # Type ignored because of non-optimal mypy inference.
260
- _event_loop_fixture_id , # type: ignore[arg-type]
261
- None ,
262
- )
254
+ if scope == "function" and "event_loop" not in fixturedef .argnames :
255
+ fixturedef .argnames += ("event_loop" ,)
263
256
_make_asyncio_fixture_function (func , scope )
264
257
function_signature = inspect .signature (func )
265
258
if "event_loop" in function_signature .parameters :
@@ -271,58 +264,35 @@ def _preprocess_async_fixtures(
271
264
f"instead."
272
265
)
273
266
)
274
- assert event_loop_fixture_id
275
- _inject_fixture_argnames (
276
- fixturedef ,
277
- event_loop_fixture_id ,
278
- )
279
- _synchronize_async_fixture (
280
- fixturedef ,
281
- event_loop_fixture_id ,
282
- )
267
+ if "request" not in fixturedef .argnames :
268
+ fixturedef .argnames += ("request" ,)
269
+ _synchronize_async_fixture (fixturedef )
283
270
assert _is_asyncio_fixture_function (fixturedef .func )
284
271
processed_fixturedefs .add (fixturedef )
285
272
286
273
287
- def _inject_fixture_argnames (
288
- fixturedef : FixtureDef , event_loop_fixture_id : str
289
- ) -> None :
290
- """
291
- Ensures that `request` and `event_loop` are arguments of the specified fixture.
292
- """
293
- to_add = []
294
- for name in ("request" , event_loop_fixture_id ):
295
- if name not in fixturedef .argnames :
296
- to_add .append (name )
297
- if to_add :
298
- fixturedef .argnames += tuple (to_add )
299
-
300
-
301
- def _synchronize_async_fixture (
302
- fixturedef : FixtureDef , event_loop_fixture_id : str
303
- ) -> None :
274
+ def _synchronize_async_fixture (fixturedef : FixtureDef ) -> None :
304
275
"""
305
276
Wraps the fixture function of an async fixture in a synchronous function.
306
277
"""
307
278
if inspect .isasyncgenfunction (fixturedef .func ):
308
- _wrap_asyncgen_fixture (fixturedef , event_loop_fixture_id )
279
+ _wrap_asyncgen_fixture (fixturedef )
309
280
elif inspect .iscoroutinefunction (fixturedef .func ):
310
- _wrap_async_fixture (fixturedef , event_loop_fixture_id )
281
+ _wrap_async_fixture (fixturedef )
311
282
312
283
313
284
def _add_kwargs (
314
285
func : Callable [..., Any ],
315
286
kwargs : Dict [str , Any ],
316
- event_loop_fixture_id : str ,
317
287
event_loop : asyncio .AbstractEventLoop ,
318
288
request : FixtureRequest ,
319
289
) -> Dict [str , Any ]:
320
290
sig = inspect .signature (func )
321
291
ret = kwargs .copy ()
322
292
if "request" in sig .parameters :
323
293
ret ["request" ] = request
324
- if event_loop_fixture_id in sig .parameters :
325
- ret [event_loop_fixture_id ] = event_loop
294
+ if "event_loop" in sig .parameters :
295
+ ret ["event_loop" ] = event_loop
326
296
return ret
327
297
328
298
@@ -345,17 +315,19 @@ def _perhaps_rebind_fixture_func(
345
315
return func
346
316
347
317
348
- def _wrap_asyncgen_fixture (fixturedef : FixtureDef , event_loop_fixture_id : str ) -> None :
318
+ def _wrap_asyncgen_fixture (fixturedef : FixtureDef ) -> None :
349
319
fixture = fixturedef .func
350
320
351
321
@functools .wraps (fixture )
352
322
def _asyncgen_fixture_wrapper (request : FixtureRequest , ** kwargs : Any ):
353
323
unittest = fixturedef .unittest if hasattr (fixturedef , "unittest" ) else False
354
324
func = _perhaps_rebind_fixture_func (fixture , request .instance , unittest )
355
- event_loop = kwargs .pop (event_loop_fixture_id )
356
- gen_obj = func (
357
- ** _add_kwargs (func , kwargs , event_loop_fixture_id , event_loop , request )
325
+ event_loop_fixture_id = _get_event_loop_fixture_id_for_async_fixture (
326
+ request , func
358
327
)
328
+ event_loop = request .getfixturevalue (event_loop_fixture_id )
329
+ kwargs .pop (event_loop_fixture_id , None )
330
+ gen_obj = func (** _add_kwargs (func , kwargs , event_loop , request ))
359
331
360
332
async def setup ():
361
333
res = await gen_obj .__anext__ ()
@@ -383,26 +355,48 @@ async def async_finalizer() -> None:
383
355
fixturedef .func = _asyncgen_fixture_wrapper
384
356
385
357
386
- def _wrap_async_fixture (fixturedef : FixtureDef , event_loop_fixture_id : str ) -> None :
358
+ def _wrap_async_fixture (fixturedef : FixtureDef ) -> None :
387
359
fixture = fixturedef .func
388
360
389
361
@functools .wraps (fixture )
390
362
def _async_fixture_wrapper (request : FixtureRequest , ** kwargs : Any ):
391
363
unittest = False if pytest .version_tuple >= (8 , 2 ) else fixturedef .unittest
392
364
func = _perhaps_rebind_fixture_func (fixture , request .instance , unittest )
393
- event_loop = kwargs .pop (event_loop_fixture_id )
365
+ event_loop_fixture_id = _get_event_loop_fixture_id_for_async_fixture (
366
+ request , func
367
+ )
368
+ event_loop = request .getfixturevalue (event_loop_fixture_id )
369
+ kwargs .pop (event_loop_fixture_id , None )
394
370
395
371
async def setup ():
396
- res = await func (
397
- ** _add_kwargs (func , kwargs , event_loop_fixture_id , event_loop , request )
398
- )
372
+ res = await func (** _add_kwargs (func , kwargs , event_loop , request ))
399
373
return res
400
374
401
375
return event_loop .run_until_complete (setup ())
402
376
403
377
fixturedef .func = _async_fixture_wrapper
404
378
405
379
380
+ def _get_event_loop_fixture_id_for_async_fixture (
381
+ request : FixtureRequest , func : Any
382
+ ) -> str :
383
+ default_loop_scope = request .config .getini ("asyncio_default_fixture_loop_scope" )
384
+ loop_scope = (
385
+ getattr (func , "_loop_scope" , None ) or default_loop_scope or request .scope
386
+ )
387
+ if loop_scope == "function" :
388
+ event_loop_fixture_id = "event_loop"
389
+ else :
390
+ event_loop_node = _retrieve_scope_root (request ._pyfuncitem , loop_scope )
391
+ event_loop_fixture_id = event_loop_node .stash .get (
392
+ # Type ignored because of non-optimal mypy inference.
393
+ _event_loop_fixture_id , # type: ignore[arg-type]
394
+ "" ,
395
+ )
396
+ assert event_loop_fixture_id
397
+ return event_loop_fixture_id
398
+
399
+
406
400
class PytestAsyncioFunction (Function ):
407
401
"""Base class for all test functions managed by pytest-asyncio."""
408
402
0 commit comments