@@ -197,6 +197,7 @@ def _mutmut_trampoline(orig, mutants, *args, **kwargs):
197197 return mutants[mutant_name](*args, **kwargs)
198198
199199"""
200+ yield_from_trampoline_impl = trampoline_impl .replace ('return ' , 'yield from ' ).replace ('_mutmut_trampoline' , '_mutmut_yield_from_trampoline' )
200201
201202
202203def create_mutants ():
@@ -297,7 +298,7 @@ def write_all_mutants_to_file(*, out, source, filename):
297298 return mutant_names , hash_by_function_name
298299
299300
300- def build_trampoline (orig_name , mutants , class_name = None ):
301+ def build_trampoline (* , orig_name , mutants , class_name , is_generator ):
301302 assert orig_name not in NEVER_MUTATE_FUNCTION_NAMES
302303
303304 mangled_name = mangle_function_name (name = orig_name , class_name = class_name )
@@ -309,11 +310,18 @@ def build_trampoline(orig_name, mutants, class_name=None):
309310 access_prefix = f'object.__getattribute__(self, "'
310311 access_suffix = '")'
311312
313+ if is_generator :
314+ return_or_yield_statement = 'yield from'
315+ trampoline_name = '_mutmut_yield_from_trampoline'
316+ else :
317+ return_or_yield_statement = 'return'
318+ trampoline_name = '_mutmut_trampoline'
319+
312320 return f"""
313321{ mutants_dict }
314322
315323def { orig_name } ({ 'self, ' if class_name is not None else '' } *args, **kwargs):
316- return _mutmut_trampoline ({ access_prefix } { mangled_name } __mutmut_orig{ access_suffix } , { access_prefix } { mangled_name } __mutmut_mutants{ access_suffix } , *args, **kwargs)
324+ { return_or_yield_statement } { trampoline_name } ({ access_prefix } { mangled_name } __mutmut_orig{ access_suffix } , { access_prefix } { mangled_name } __mutmut_mutants{ access_suffix } , *args, **kwargs)
317325
318326{ orig_name } .__signature__ = _mutmut_signature({ mangled_name } __mutmut_orig)
319327{ mangled_name } __mutmut_orig.__name__ = '{ mangled_name } '
@@ -447,6 +455,23 @@ def is_inside_dict_synonym_call(self):
447455 return False
448456
449457
458+ def is_generator (node ):
459+ assert node .type == 'funcdef'
460+
461+ def _is_generator (n ):
462+ if n is not node and n .type in ('funcdef' , 'classdef' ):
463+ return False
464+
465+ if n .type == 'keyword' and n .value == 'yield' :
466+ return True
467+
468+ for c in getattr (n , 'children' , []):
469+ if _is_generator (c ):
470+ return True
471+ return False
472+ return _is_generator (node )
473+
474+
450475def yield_mutants_for_function (node , * , class_name = None , no_mutate_lines ):
451476 assert node .type == 'funcdef'
452477
@@ -481,7 +506,7 @@ def yield_mutants_for_function(node, *, class_name=None, no_mutate_lines):
481506 finally :
482507 context .stack .pop ()
483508
484- trampoline = build_trampoline (node .name .value , context .mutants , class_name = class_name )
509+ trampoline = build_trampoline (orig_name = node .name .value , mutants = context .mutants , class_name = class_name , is_generator = is_generator ( node ) )
485510 if class_name is not None :
486511 trampoline = indent (trampoline , ' ' )
487512 yield 'trampoline' , trampoline , None , None
@@ -530,6 +555,7 @@ def yield_mutants_for_module(node, no_mutate_lines):
530555 yield from yield_future_imports (node )
531556
532557 yield 'trampoline_impl' , trampoline_impl , None , None
558+ yield 'trampoline_impl' , yield_from_trampoline_impl , None , None
533559 yield 'filler' , '\n ' , None , None
534560 for child_node in node .children :
535561 if child_node .type == 'funcdef' :
0 commit comments