Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed SyntaxError happening when the name of a native coroutine function to create contains 'return'. #97

Merged
merged 1 commit into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

### 1.15.2 - bugfix

- Fixed `SyntaxError` happening when the name of a native coroutine function to create contains `'return'`.
Fixes [#96](https://github.com/smarie/python-makefun/issues/96).

### 1.15.1 - bugfixes

- Fixed `ValueError: Invalid co_name` happening on python 2 when the name of a function to create starts or ends with
Expand Down
2 changes: 1 addition & 1 deletion src/makefun/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def create_function(func_signature, # type: Union[str, Signature]
body = "def %s\n return _func_impl_(%s)\n" % (func_signature_str, params_str)

if iscoroutinefunction(func_impl):
body = ("async " + body).replace('return', 'return await')
body = ("async " + body).replace('return _func_impl_', 'return await _func_impl_')

# create the function by compiling code, mapping the `_func_impl_` symbol to `func_impl`
protect_eval_dict(evaldict, func_name, params_names)
Expand Down
22 changes: 22 additions & 0 deletions tests/test_generators_coroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,25 @@ def test_native_coroutine():
from asyncio import get_event_loop
out = get_event_loop().run_until_complete(dynamic_fun(0.1))
assert out == 0.1


@pytest.mark.skipif(sys.version_info < (3, 5), reason="native coroutines with async/await require python3.6 or higher")
def test_issue_96():
"""Same as `test_native_coroutine` but tests that we can use 'return' in the coroutine name"""

# define the handler that should be called
from tests._test_py35 import make_native_coroutine_handler
my_native_coroutine_handler = make_native_coroutine_handler()

# create the dynamic function
dynamic_fun = create_function("foo_returns_bar(sleep_time=2)", my_native_coroutine_handler)

# check that this is a coroutine for inspect and for asyncio
assert iscoroutinefunction(dynamic_fun)
from asyncio import iscoroutinefunction as is_native_co
assert is_native_co(dynamic_fun)

# verify that the new function is a native coroutine and behaves correctly
from asyncio import get_event_loop
out = get_event_loop().run_until_complete(dynamic_fun(0.1))
assert out == 0.1
Loading