Coverage for src/makefun/_main_legacy_py.py: 0%

30 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-03-12 17:34 +0000

1# Authors: Sylvain MARIE <sylvain.marie@se.com> 

2# + All contributors to <https://github.com/smarie/python-makefun> 

3# 

4# License: 3-clause BSD, <https://github.com/smarie/python-makefun/blob/master/LICENSE> 

5import sys 

6from itertools import chain 

7 

8from makefun.main import wraps 

9 

10 

11def make_partial_using_yield(new_sig, f, *preset_pos_args, **preset_kwargs): 

12 """ 

13 Makes a 'partial' when f is a generator and python is new enough to support `yield from` 

14 

15 :param new_sig: 

16 :param f: 

17 :param preset_pos_args: 

18 :param preset_kwargs: 

19 :return: 

20 """ 

21 @wraps(f, new_sig=new_sig) 

22 def partial_f(*args, **kwargs): 

23 # since the signature does the checking for us, no need to check for redundancy. 

24 kwargs.update(preset_kwargs) 

25 gen = f(*chain(preset_pos_args, args), **kwargs) 

26 _i = iter(gen) # initialize the generator 

27 _y = next(_i) # first iteration 

28 while 1: 

29 try: 

30 _s = yield _y # yield the first output and retrieve the new input 

31 except GeneratorExit as _e: # ---generator exit error--- 

32 try: 

33 _m = _i.close # if there is a close method 

34 except AttributeError: 

35 pass 

36 else: 

37 _m() # use it first 

38 raise _e # then re-raise exception 

39 except BaseException as _e: # ---other exception 

40 _x = sys.exc_info() # if captured exception, grab info 

41 try: 

42 _m = _i.throw # if there is a throw method 

43 except AttributeError: 

44 raise _e # otherwise re-raise 

45 else: 

46 _y = _m(*_x) # use it 

47 else: # --- nominal case: the new input was received 

48 # if _s is None: 

49 # _y = next(_i) 

50 # else: 

51 _y = _i.send(_s) # let the implementation decide if None means "no new input" or "new input = None" 

52 return partial_f 

53 

54 

55def get_legacy_py_generator_body_template(): 

56 """ 

57 In Python 2 we cannot use `yield from` in the generated function body. 

58 This is a replacement, from PEP380 - see https://www.python.org/dev/peps/pep-0380/#formal-semantics 

59 

60 note: we removed a few lines so that `StopIteration` exceptions are re-raised 

61 :return: 

62 """ 

63 return """def %s 

64 _i = iter(_func_impl_(%s)) # initialize the generator 

65 _y = next(_i) # first iteration 

66 while 1: 

67 try: 

68 _s = yield _y # yield the first output and retrieve the new input 

69 except GeneratorExit as _e: # ---generator exit error--- 

70 try: 

71 _m = _i.close # if there is a close method 

72 except AttributeError: 

73 pass 

74 else: 

75 _m() # use it first 

76 raise _e # then re-raise exception 

77 except BaseException as _e: # ---other exception 

78 _x = sys.exc_info() # if captured exception, grab info 

79 try: 

80 _m = _i.throw # if there is a throw method 

81 except AttributeError: 

82 raise _e # otherwise re-raise 

83 else: 

84 _y = _m(*_x) # use it 

85 else: # --- nominal case: the new input was received 

86 # if _s is None: 

87 # _y = next(_i) 

88 # else: 

89 _y = _i.send(_s) # let the implementation decide if None means "no new input" or "new input = None" 

90"""