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

FunctionMaker.create() fails when given a function definition with a return type annotation. #138

Open
amitaiirron opened this issue Dec 26, 2021 · 1 comment

Comments

@amitaiirron
Copy link

amitaiirron commented Dec 26, 2021

I think I may have found an issue with FunctionMaker.create(). When you try to pass a string containing a return type annotation, it breaks this function. Consider this example:

from decorator import FunctionMaker

def add(a: int, b: int) -> int:
    return a + b

add2 = FunctionMaker.create("add2(a: int, b: int)", "return add(a, b)", evaldict={"add": add}) # No problem
assert add2(6, 8) == add(6, 8) # add2 does the same as add

add3 = FunctionMaker.create("add3(a: int, b: int) -> int", "return add(a, b)", evaldict={"add": add}) # ERROR

I get a message like this:

  File "/nfs/iil/proj/dt/prv08/airon/git/socb_client/venv/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3457, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)

  File "<ipython-input-9-5d5ad6515055>", line 9, in <module>
    add3 = FunctionMaker.create("add3(a: int, b: int) -> int", "return add(a, b)", evaldict={"add": add})

  File "/nfs/iil/proj/dt/prv08/airon/git/socb_client/venv/lib/python3.9/site-packages/decorator.py", line 222, in create
    return self.make(body, evaldict, addsource, **attrs)

  File "/nfs/iil/proj/dt/prv08/airon/git/socb_client/venv/lib/python3.9/site-packages/decorator.py", line 184, in make
    code = compile(src, filename, 'single')

  File "<decorator-gen-123>", line 1
    def add3(a: int, b: int) -> in):
                                ^
SyntaxError: invalid syntax

It seems like the code that decomposes the signature at

name, rest = obj.strip().split('(', 1)

assumes the end of the signature is always a right parenthesis, which is not the case when we specify a return type annotation.

Then, the code at

body = 'def %(name)s(%(signature)s):\n' + ibody
unconditionally adds the right parenthesis that was (actually or supposedly) removed previously.

I could fix this issue in my own environment, but the fix is kind of dirty, and has not gone through all your testing, obviously.

@micheles
Copy link
Owner

This is a known issue: #114
It is tricky and not particularly high priority for the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants