@@ -330,8 +330,30 @@ async def use_agen_simple(*args, delay=delay):
330330 results .append (i )
331331 return results
332332
333+ def has_refcount_bug ():
334+ """
335+ Apparently 3.12 introduced a refcount bug involving async
336+ generators (CPython issue GH-100964), which is *finally*
337+ patched in CPython GitHub PR #141112.
338+ As such, we have to check the patch versions to determine
339+ whether refcount inconsistencies are to be expected;
340+ alternatively, inspect `test.test_generators.FinalizationTest`
341+ for the test method `.test_exhausted_generator_frame_cycle()`;
342+ but that seems even more fragile than checking the versions...
343+ """
344+ version = sys .version_info [:2 ]
345+ patch = sys .version_info [2 ]
346+ if version == (3 , 12 ): # 3.12.x all bugged
347+ return True
348+ if version == (3 , 13 ): # Fix backported to 3.13.12...
349+ return patch < 12
350+ if version == (3 , 14 ): # ... and 3.14.3
351+ return patch < 3
352+ return False
353+
333354 profile = LineProfiler ()
334355 ag_wrapped = profile (ag )
356+ xfail_refcount = has_refcount_bug () and not gc
335357 assert inspect .isasyncgenfunction (ag_wrapped )
336358 assert ag in profile .functions
337359
@@ -341,12 +363,8 @@ async def use_agen_simple(*args, delay=delay):
341363 assert profile .enable_count == 0
342364 assert asyncio .run (use_agen_simple (1 , 2 , 3 )) == [0 , 1 , 3 , 6 ]
343365 assert profile .enable_count == 0
344- # FIXME: why does `use_agen_complex()` need the `gc.collect()` to
345- # not fail in Python 3.12+? Doesn't seem to matter which
346- # ${LINE_PROFILER_CORE} we're using either...
347366 with contextlib .ExitStack () as stack :
348- xfail_312 = hasattr (sys , 'monitoring' ) and not gc
349- if xfail_312 : # Python 3.12+
367+ if xfail_refcount :
350368 excinfo = stack .enter_context (
351369 pytest .raises (AssertionError , match = r'ag\(\): ref count' )
352370 )
@@ -358,7 +376,7 @@ async def use_agen_simple(*args, delay=delay):
358376 assert profile .enable_count == 0
359377 assert asyncio .run (use_agen_complex (1 , 2 , 3 , None , 4 )) == [0 , 1 , 3 , 6 ]
360378 assert profile .enable_count == 0
361- if xfail_312 :
379+ if xfail_refcount :
362380 pytest .xfail (
363381 '\n sys.version={!r}..., gc={}:\n {}' .format (
364382 sys .version .strip ().split ()[0 ], gc , excinfo .getrepr (style = 'no' )
0 commit comments