Provide an easier way to wrap a function whatever its mode (regular, generator, or generator coroutine)
In many cases when we create function wrappers, we would like to have a single way to write the wrapper rather than handling both generator and regular modes with a if/else.
A good illustration is provided below:
https://github.com/smarie/python-pytest-harvest/blob/master/pytest_harvest/fixture_cache.py#L193
Maybe we could add a multi_mode_handler flag ? Setting it to True would require the handler to be written in a way that is independent from the wrapped mode (to be found... maybe a coroutine ?).
I propose to add a mode argument instead, and to provide a helper companion as_generator function.
def create_wrapper(f):
# use the helper to always have a generator
genf = as_generator(f)
@with_signature(f, mode=f)
def my_handler( *args, **kwargs):
# <init code>
gen = genf(*args, **kwargs)
for res in gen:
# <intermediate code>
yield res # or yield anything else
# <termination code>
return my_handler
This would do the trick.
mode=findicates that the generated function has the same mode thanf(generator if generator, etc.). In that case the handler has to be itself a generator (nothing else is supported).as_generator(f)is used to turn f into a generator if it is not already the case
The code above would work if foo is a normal function or a generator:
def foo(a):
return "hello"
create_wrapper(foo) # should be a normal function
def foo_g(a):
yield "hello"
yield "again"
create_wrapper(foo) # should be a generator