Read about our upcoming Code of Conduct on this issue

Commit f3fd04bb authored by Pierre Augier's avatar Pierre Augier
Browse files

fluidpythran.pythran_class

--HG--
branch : dev
parent 6676e6de91d3
......@@ -8,7 +8,7 @@ except ImportError:
from .annotation import Array, NDim, Type, Shape
from .aheadoftime import FluidPythran, pythran_def, make_signature
from .aheadoftime import FluidPythran, pythran_def, pythran_class, make_signature
from .util import set_pythranize_at_import
from .pythranizer import wait_for_all_extensions
......@@ -17,6 +17,7 @@ __all__ = [
"__version__",
"FluidPythran",
"pythran_def",
"pythran_class",
"make_signature",
"path_data_tests",
"Array",
......
......@@ -221,6 +221,7 @@ class FluidPythran:
if is_transpiling:
self.functions = {}
self.classes = {}
self.signatures_func = {}
modules[module_name] = self
self.is_transpiled = False
......@@ -357,7 +358,14 @@ class FluidPythran:
"""
# FIXME methods?
signature = inspect.signature(func)
try:
is_method = next(iter(signature.parameters.keys())) == "self"
except StopIteration:
is_method = False
if is_method:
return self.pythran_def_method(func)
if is_transpiling:
self.functions[func.__name__] = func
......@@ -377,6 +385,25 @@ class FluidPythran:
return func_tmp
def pythran_def_method(self, func):
"""Decorator used for methods
Parameters
----------
func: a function
"""
if is_transpiling:
func.__fluidpythran__ = "pythran_def_method"
return func
if not self.is_transpiled:
return func
return FluidPythranTemporaryMethod(func)
def pythran_class(self, cls: type):
"""Decorator used for classes
......@@ -394,7 +421,26 @@ class FluidPythran:
if not self.is_transpiled:
return cls
# FIXME
cls_name = cls.__name__
for key, value in cls.__dict__.items():
if not isinstance(value, FluidPythranTemporaryMethod):
continue
func = value.func
func_name = func.__name__
name_pythran_func = f"__for_method__{cls_name}__{func_name}"
name_var_code_new_method = f"__code_new_method__{cls_name}__{func_name}"
try:
pythran_func = getattr(self.module_pythran, name_pythran_func)
code_new_method = getattr(self.module_pythran, name_var_code_new_method)
except AttributeError:
logger.warning("Pythran file does not seem to be up-to-date.")
else:
namespace = {"pythran_func": pythran_func}
exec(code_new_method, namespace)
setattr(cls, key, functools.wraps(func)(namespace["new_method"]))
return cls
......@@ -469,3 +515,11 @@ class FluidPythran:
if func.__name__ not in self.signatures_func:
self.signatures_func[func.__name__] = []
self.signatures_func[func.__name__].extend(signatures)
class FluidPythranTemporaryMethod:
def __init__(self, func):
self.func = func
def __call__(self, self_bis, *args, **kwargs):
raise RuntimeError("Do not call this function!")
\ No newline at end of file
......@@ -13,6 +13,7 @@ from fluidpythran.annotation import compute_pythran_types_from_valued_types
def pythran_def_method(func):
func.__fluidpythran__ = "pythran_def_method"
return func
......@@ -35,14 +36,34 @@ class Transmitter:
"""My docstring"""
return inp * np.exp(np.arange(len(inp)) * self.freq * 1j)
@pythran_def_method
def call_with_print(self, inp: A):
"""call + print"""
print("call_with_print")
return inp * np.exp(np.arange(len(inp)) * self.freq * 1j)
def produce_pythran_code_class(cls, func_name):
func = cls.__dict__[func_name]
cls_name = cls.__name__
def produce_pythran_code_class(cls):
pythran_code = ""
for key, value in cls.__dict__.items():
if (
hasattr(value, "__fluidpythran__")
and value.__fluidpythran__ == "pythran_def_method"
):
pythran_code += produce_pythran_code_class_func(cls, key)
return pythran_code
def produce_pythran_code_class_func(cls, func_name):
cls_name = cls.__name__
cls_annotations = cls.__annotations__
func = cls.__dict__[func_name]
signature = inspect.signature(func)
types_func = [param.annotation for param in signature.parameters.values()][1:]
args_func = list(signature.parameters.keys())[1:]
......@@ -133,11 +154,11 @@ def produce_pythran_code_class(cls, func_name):
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"""'
'\n\n"""\n'
)
return pythran_code
func = pythran_code = produce_pythran_code_class(Transmitter, "__call__")
pythran_code = produce_pythran_code_class(Transmitter)
print(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