Read about our upcoming Code of Conduct on this issue

Commit 8f3bd1d2 authored by Pierre Augier's avatar Pierre Augier
Browse files

More pythran_def for methods

parent 2aafd7774324
......@@ -10,6 +10,8 @@ doc/**.zip
**/.ipynb_checkpoints/*
*.so
build/*
dist/*.tar.gz
dist*
......
......@@ -100,6 +100,18 @@ def has_to_build(output_file: Path, input_file: Path):
def get_source_without_decorator(func: Callable):
"""Get the source of a function without its decorator"""
src = inspect.getsource(func)
# de-indent the code
nb_spaces = 0
for c in src:
if not c.isspace():
break
nb_spaces += 1
if nb_spaces > 0:
lines = [line[nb_spaces:] for line in src.split("\n")]
src = "\n".join(lines)
return strip_typehints(re.sub(r"@.*?\sdef\s", "def ", src))
......
import numpy as np
# pythran export __method__Transmitter____call__(float, float[])
# pythran export __for_method__Transmitter____call__(float, float[:])
# pythran export __for_method__Transmitter____call__(float, int[:])
# pythran export __for_method__Transmitter____call__(float, float[:, :])
# pythran export __for_method__Transmitter____call__(float, int[:, :])
def __for_method__Transmitter____call__(self_freq, inp):
return inp * np.exp(np.arange(len(inp))*self_freq*1j)
"My docstring"
print("__for_method...")
return inp * np.exp(((np.arange(len(inp)) * self_freq) * 1j))
# pythran export __code_new_method__Transmitter____call__
__code_new_method__Transmitter____call__ = """
def new_method(self, inp):
print("new_method")
return pythran_func(self.freq, inp)
"""
......@@ -4,13 +4,6 @@ import numpy as np
import pythran_manual
code = """
def new_method(self, inp):
return pythran_func(self.freq, inp)
"""
class FluidPythranTemporaryMethod:
def __init__(self, func):
......@@ -37,8 +30,11 @@ def pythran_class(cls):
name_pythran_func = f"__for_method__{cls_name}__{func_name}"
pythran_func = pythran_manual.__dict__[name_pythran_func]
name_var_code_new_method = f"__code_new_method__{cls_name}__{func_name}"
code_new_method = pythran_manual.__dict__[name_var_code_new_method]
namespace = {"pythran_func": pythran_func}
exec(code, namespace)
exec(code_new_method, namespace)
setattr(cls, key, wraps(func)(namespace["new_method"]))
return cls
......@@ -56,3 +52,9 @@ class Transmitter:
def __call__(self, inp: "float[]"):
"""My docstring"""
return inp * np.exp(np.arange(len(inp)) * self.freq * 1j)
if __name__ == "__main__":
inp = np.ones(2)
trans = Transmitter(1.)
trans(inp)
......@@ -43,11 +43,8 @@ def produce_pythran_code_class(cls, func_name):
signature = inspect.signature(func)
types_func = [param.annotation for param in signature.parameters.values()][1:]
# args_func = list(signature.parameters.keys())[1:]
args_func = list(signature.parameters.keys())[1:]
return func
# bug IndentationError (util.strip_typehints)
src = get_source_without_decorator(func)
tokens = []
......@@ -88,12 +85,12 @@ def produce_pythran_code_class(cls, func_name):
types_attrs = [cls_annotations[attr] for attr in attributes]
attributes = ["self_" + attr for attr in attributes]
attributes_self = ["self_" + attr for attr in attributes]
index_self = tokens.index((NAME, "self"))
tokens_attr = []
for ind, attr in enumerate(attributes):
for ind, attr in enumerate(attributes_self):
tokens_attr.append((NAME, attr))
tokens_attr.append((OP, ","))
......@@ -123,6 +120,20 @@ def produce_pythran_code_class(cls, func_name):
)
pythran_code = pythran_signatures + "\n" + new_code
name_var_code_new_method = f"__code_new_method__{cls_name}__{func_name}"
str_self_dot_attributes = ", ".join("self." + attr for attr in attributes)
str_args_func = ", ".join(args_func)
pythran_code += (
f"\n# pythran export {name_var_code_new_method}\n"
f'\n{name_var_code_new_method} = """\n\n'
f"def new_method(self, {str_args_func}):\n"
f" return pythran_func({str_self_dot_attributes}, {str_args_func})"
'\n\n"""'
)
return pythran_code
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment