-
Notifications
You must be signed in to change notification settings - Fork 353
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
FunctionBuilder.from_func
not working
#301
Comments
I'd propose something like the following. Should I do a pull request? from boltons.funcutils import FunctionBuilder, _inspect_iscoroutinefunction
import functools
class MyFunctionBuilder(FunctionBuilder):
@classmethod
def from_func(cls, func):
"""Create a new FunctionBuilder instance based on an existing
function. The original function will not be stored or
modified.
"""
# TODO: copy_body? gonna need a good signature regex.
# TODO: might worry about __closure__?
if not callable(func):
raise TypeError('expected callable object, not %r' % (func,))
if isinstance(func, functools.partial):
if _IS_PY2:
raise ValueError('Cannot build FunctionBuilder instances from partials in python 2.')
kwargs = {'name': func.func.__name__,
'doc': func.func.__doc__,
'module': getattr(func.func, '__module__', None), # e.g., method_descriptor
'annotations': getattr(func.func, "__annotations__", {}),
'body': get_function_body(func.func), # <-- NEW: add body
'dict': getattr(func.func, '__dict__', {})}
else:
kwargs = {'name': func.__name__,
'doc': func.__doc__,
'module': getattr(func, '__module__', None), # e.g., method_descriptor
'annotations': getattr(func, "__annotations__", {}),
'body': get_function_body(func), # <-- NEW: add body
'dict': getattr(func, '__dict__', {})}
kwargs.update(cls._argspec_to_dict(func))
if _inspect_iscoroutinefunction(func):
kwargs['is_async'] = True
return cls(**kwargs)
# We'll need a `get_function_body` function for this, something like:
import inspect
from itertools import dropwhile
def get_function_body(func):
source_lines = next(iter(inspect.getsourcelines(func)), None)
if source_lines is None:
raise ValueError(f"No source lines found func: {func}")
source_lines = dropwhile(lambda x: x.startswith('@'), source_lines)
def_line = next(source_lines).strip()
if def_line.startswith('def ') and def_line.endswith(':'):
first_line = next(source_lines)
indentation = len(first_line) - len(first_line.lstrip())
return ''.join([first_line[indentation:]] + [line[indentation:] for line in source_lines])
else:
return def_line.rsplit(':')[-1].strip()
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FunctionBuilder.from_func
doesn't seem to work.Actually
f(20)
returnsNone
.I looked into the code and see that the
body
isn't extracted and specified when making the function.The text was updated successfully, but these errors were encountered: