Coverage for src/makefun/_main_legacy_py.py: 0%
30 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-09-26 12:39 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-09-26 12:39 +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
8from makefun.main import wraps
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`
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
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
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"""