Read about our upcoming Code of Conduct on this issue

Commit 60690c44 authored by Pierre Blanc-fatin's avatar Pierre Blanc-fatin
Browse files

Factorize backends code in super Class

parent 43bfb83063b4
......@@ -251,7 +251,6 @@ def filter_external_code(module: object, names: list):
lines_code.append(str(extast.unparse(node)))
if isinstance(node, ast.ClassDef):
if node.name == extast.unparse(name).rstrip("\n\r"):
print_dumped(node)
lines_code.append(str(extast.unparse(node)))
return code_dependance_annotations + "\n".join(lines_code)
......
from pathlib import Path
from tokenize import tokenize, untokenize, NAME, OP
from io import BytesIO
from transonic.util import TypeHintRemover, format_str
from transonic.analyses import extast
from transonic.log import logger
from transonic.util import (
has_to_build,
get_source_without_decorator,
format_str,
write_if_has_to_write,
)
class Backend:
def __init__(self):
pass
def __init__(self, backend_name):
self.backend_name = backend_name
def prepare_backend_file(self, path_py, force=False, log_level=None):
if log_level is not None:
logger.set_level(log_level)
path_py = Path(path_py)
if not path_py.exists():
raise FileNotFoundError(f"Input file {path_py} not found")
if path_py.absolute().parent.name == "__" + self.backend_name + "__":
logger.debug(f"skip file {path_py}")
return None, None, None
if not path_py.name.endswith(".py"):
raise ValueError(
"transonic only processes Python file. Cannot process {path_py}"
)
path_dir = path_py.parent / str("__" + self.backend_name + "__")
path_backend = path_dir / path_py.name
if not has_to_build(path_backend, path_py) and not force:
logger.warning(f"File {path_backend} already up-to-date.")
return None, None, None
return path_py, path_dir, path_backend
def write_code(self, code_backend, code_ext, path_dir, path_backend, force):
for file_name, code in code_ext["function"].items():
path_ext_file = path_dir / (file_name + ".py")
write_if_has_to_write(path_ext_file, code, logger.info)
if self.backend_name == "pythran":
for file_name, code in code_ext["classe"].items():
path_ext_file = (
path_dir.parent / "__pythran__" / (file_name + ".py")
)
write_if_has_to_write(path_ext_file, code, logger.info)
code_pythran_old = ""
if path_backend.exists() and not force:
with open(path_backend) as file:
code_pythran_old = file.read()
if code_pythran_old == code_backend:
logger.warning(f"Code in file {path_backend} already up-to-date.")
return False
logger.debug(f"code_{self.backend_name}:\n{code_backend}")
path_dir.mkdir(exist_ok=True)
with open(path_backend, "w") as file:
file.write("".join(code_backend))
logger.info(f"File {path_backend} written")
return True
def get_code_function(self, fdef):
......
......@@ -23,46 +23,27 @@ from .backend import Backend
class CythonBackend(Backend):
def __init__(self):
pass
super().__init__("cython")
def make_backend_file(self, path_py, analyse, force=None):
def make_backend_file(self, path_py, analyse, force=False, log_level=None):
"""Create a Python file from a Python file (if necessary)"""
# if log_level is not None:
# logger.set_level(log_level)
path_py = Path(path_py)
if not path_py.exists():
raise FileNotFoundError(f"Input file {path_py} not found")
path_py, path_dir, _ = super().prepare_backend_file(
path_py, force, log_level
)
if path_py.absolute().parent.name == "__pythran__":
logger.debug(f"skip file {path_py}")
return
if not path_py.name.endswith(".py"):
raise ValueError(
"transonic only processes Python file. Cannot process {path_py}"
)
if not analyse:
with open(path_py) as f:
code = f.read()
analyse = analyse_aot(code, path_py)
path_dir = path_py.parent / "__cython__"
path_cython = (path_dir / path_py.name).with_suffix(".pyx")
if not has_to_build(path_cython, path_py): # and not force:
logger.warning(f"File {path_cython} already up-to-date.")
return
code_cython, code_ext = self.make_cython_code(path_py, analyse)
if not code_cython:
return
for file_name, code in code_ext["function"].items():
path_ext_file = path_dir / (file_name + ".py")
write_if_has_to_write(path_ext_file, code, logger.info)
path_dir.mkdir(exist_ok=True)
with open(path_cython, "w") as file:
file.write("".join(code_cython))
super().write_code(code_cython, code_ext, path_dir, path_cython, force)
def make_cython_code(self, path_py, analyse):
......@@ -76,7 +57,6 @@ class CythonBackend(Backend):
code = ["\n" + code_dependance + "\n"]
for func_name, fdef in boosted_dicts["functions"].items():
signatures_func = set()
try:
ann = annotations["functions"][func_name]
......@@ -91,19 +71,17 @@ class CythonBackend(Backend):
# )
anns = annotations["comments"][func_name]
print_dumped(fdef.decorator_list)
# change annotations
if fdef.decorator_list:
for name in fdef.args.args:
if name.annotation:
name.id = name.annotation.id + " " + name.id
# change type hints into cdef
for index, node in enumerate(fdef.body):
if isinstance(node, ast.AnnAssign):
cdef = "cdef " + node.annotation.id + " " + node.target.id
fdef.body[index] = extast.CommentLine(s=cdef)
code.append(extast.unparse(fdef))
for name in fdef.args.args:
if name.annotation:
name.id = name.annotation.id + " " + name.id
# change type hints into cdef
for index, node in enumerate(fdef.body):
if isinstance(node, ast.AnnAssign):
cdef = "cdef " + node.annotation.id + " " + node.target.id
fdef.body[index] = extast.CommentLine(s=cdef)
code.append(extast.unparse(fdef))
return code, code_ext
......@@ -39,7 +39,7 @@ from transonic.util import (
class PythranBackend(Backend):
def __init__(self):
pass
super().__init__("pythran")
def make_backend_files(
self,
......@@ -90,70 +90,34 @@ class PythranBackend(Backend):
):
"""Create a Python file from a Python file (if necessary)"""
if log_level is not None:
logger.set_level(log_level)
path_py, path_dir, path_pythran = super().prepare_backend_file(
path_py, force, log_level
)
path_py = Path(path_py)
if path_dir is None:
return
if not analyse:
with open(path_py) as f:
code = f.read()
analyse = analyse_aot(code, path_py)
if not path_py.exists():
raise FileNotFoundError(f"Input file {path_py} not found")
if path_py.absolute().parent.name == "__pythran__":
logger.debug(f"skip file {path_py}")
return
if not path_py.name.endswith(".py"):
raise ValueError(
"transonic only processes Python file. Cannot process {path_py}"
)
path_dir = path_py.parent / "__pythran__"
path_pythran = path_dir / path_py.name
if not has_to_build(path_pythran, path_py) and not force:
logger.warning(f"File {path_pythran} already up-to-date.")
return
code_pythran, code_ext = self.make_pythran_code(path_py, analyse)
if not code_pythran:
return
for file_name, code in code_ext["function"].items():
path_ext_file = path_dir / (file_name + ".py")
write_if_has_to_write(path_ext_file, code, logger.info)
for file_name, code in code_ext["classe"].items():
path_ext_file = path_dir.parent / "__pythran__" / (file_name + ".py")
write_if_has_to_write(path_ext_file, code, logger.info)
if path_pythran.exists() and not force:
with open(path_pythran) as file:
code_pythran_old = file.read()
if code_pythran_old == code_pythran:
logger.warning(f"Code in file {path_pythran} already up-to-date.")
return
logger.debug(f"code_pythran:\n{code_pythran}")
path_dir.mkdir(exist_ok=True)
with open(path_pythran, "w") as file:
file.write(code_pythran)
status = super().write_code(
code_pythran, code_ext, path_dir, path_pythran, force
)
logger.info(f"File {path_pythran} written")
if status is False:
return
return path_pythran
def make_pythran_code(self, path_py, analyse):
"""Create a pythran code from a Python file"""
with open(path_py) as file:
code_module = file.read()
boosted_dicts, code_dependance, annotations, blocks, code_ext = analyse
......
......@@ -136,7 +136,6 @@ def make_backends_files(
code = f.read()
analyse = analyse_aot(code, path)
for name, backend in backends.items():
print(backend)
path_out = backend.make_backend_file(path, analyse, force=force)
if path_out:
paths_out.append(path_out)
......
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