Python ast 模块,NodeVisitor() 实例源码

我们从Python开源项目中,提取了以下49个代码示例,用于说明如何使用ast.NodeVisitor()

项目:bothub-sdk-python    作者:bothub-studio    | 项目源码 | 文件源码
def get_decorators(cls):
    decorators = {}

    def visit_FunctionDef(node):
        decorators[node.name] = []
        for n in node.decorator_list:
            name = ''
            if isinstance(n, ast.Call):
                name = n.func.attr if isinstance(n.func, ast.Attribute) else n.func.id
            else:
                name = n.attr if isinstance(n, ast.Attribute) else n.id

            args = [a.s for a in n.args] if hasattr(n, 'args') else []
            decorators[node.name].append((name, args))

    node_iter = ast.NodeVisitor()
    node_iter.visit_FunctionDef = visit_FunctionDef
    _cls = cls if inspect.isclass(cls) else cls.__class__
    node_iter.visit(ast.parse(inspect.getsource(_cls)))
    return decorators
项目:cancer    作者:yancz1989    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].

    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name and full_name.startswith("tf."):
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:dlbench    作者:hclhkbu    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].

    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name and full_name.startswith("tf."):
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:Stacked_LSTMS_Highway_Residual_On_TimeSeries_Datasets    作者:praveendareddy21    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].

    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name and full_name.startswith("tf."):
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:crc-diagram    作者:IuryAlves    | 项目源码 | 文件源码
def parse(self):
        """
        The main functionality. It parses a tree from :py:data:`self.path_or_stream`
        and uses :py:data:`ast.NodeVisitor` to iterate over the tree.

        :returns: self
        """
        self.stream.seek(0)
        try:
            with closing(self.stream) as stream:
                tree = ast.parse(stream.read())
        except (SyntaxError,):
            raise ParserException('File {file_} is not a python file'.format(
                file_=self.stream.name
            ))
        else:
            self.visit(tree)
        return self
项目:dnn-quant    作者:euclidjda    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].

    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name and full_name.startswith("tf."):
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:visual_mpc    作者:febert    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].

    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name:
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:ram_modified    作者:jtkim-kaist    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].

    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name and full_name.startswith("tf."):
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:TerpreT    作者:51alg    | 项目源码 | 文件源码
def get_set_vars(root):
    class GetSetVarsVisitor(ast.NodeVisitor):
        def __init__(self):
            self.set_vars = set()

        def visit_Call(self, node):
            if u.is_set_to_call(node):
                self.set_vars.add(get_var_name(node.func.value))

    vis = GetSetVarsVisitor()
    if isinstance(root, list):
        for stmt in root:
            vis.visit(stmt)
    else:
        vis.visit(root)
    return vis.set_vars
项目:pymake    作者:dtrckd    | 项目源码 | 文件源码
def get_decorators(cls):
    target = cls
    decorators = {}

    def visit_FunctionDef(node):
        decorators[node.name] = []
        for n in node.decorator_list:
            name = ''
            if isinstance(n, ast.Call):
                name = n.func.attr if isinstance(n.func, ast.Attribute) else n.func.id
            else:
                name = n.attr if isinstance(n, ast.Attribute) else n.id

            decorators[node.name].append(name)

    node_iter = ast.NodeVisitor()
    node_iter.visit_FunctionDef = visit_FunctionDef
    node_iter.visit(ast.parse(inspect.getsource(target)))
    return decorators
项目:Tensorflow-Turitors    作者:Xls1994    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].

    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name and full_name.startswith("tf."):
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:viper    作者:ethereum    | 项目源码 | 文件源码
def decorate_ast_with_source(_ast, code):

    class MyVisitor(ast.NodeVisitor):
        def visit(self, node):
            self.generic_visit(node)
            node.source_code = code

    MyVisitor().visit(_ast)
项目:cancer    作者:yancz1989    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:dlbench    作者:hclhkbu    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:ML-Project    作者:Shiam-Chowdhury    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:ML-Project    作者:Shiam-Chowdhury    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].
    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name:
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:Stacked_LSTMS_Highway_Residual_On_TimeSeries_Datasets    作者:praveendareddy21    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:chalice    作者:aws    | 项目源码 | 文件源码
def visit(self, node):
        # type: (ast.AST) -> None
        inferred_type = self._binder.get_type_for_node(node)
        if isinstance(inferred_type, Boto3ClientMethodCallType):
            self.api_calls.setdefault(inferred_type.service_name, set()).add(
                inferred_type.method_name)
        ast.NodeVisitor.visit(self, node)
项目:chalice    作者:aws    | 项目源码 | 文件源码
def visit(self, node):
        # type: (Any) -> None
        return ast.NodeVisitor.visit(self, node)
项目:tdoc    作者:Ryanb58    | 项目源码 | 文件源码
def parse_file(file_base, file_path, file_name):
    """Parse a python's files contents to extract API documentation."""
    src_path = os.path.join(file_base, file_path, file_name)
    print(src_path)

    with open(src_path) as fp:
        source = fp.read()
        tree = ast.parse(source)

        output_folder = "./docs/"
        dst_path = os.path.join(output_folder, file_path, file_name + ".md")

        os.makedirs(os.path.join(output_folder, file_path), exist_ok=True)

        with open(dst_path, "w") as output_file:

            class FuncLister(ast.NodeVisitor):
                def visit_FunctionDef(self, node):
                    """Function Visitor"""
                    output_file.write(get_function_markdown(node))
                    self.generic_visit(node)

                def visit_ClassDef(self, node):
                    """Class Visitor"""
                    output_file.write(get_class_markdown(node))
                    self.generic_visit(node)

            FuncLister().visit(tree)
项目:ipython-autoimport    作者:anntzer    | 项目源码 | 文件源码
def _get_import_cache(ipython):
    """Load a mapping of names to import statements from the IPython history.
    """

    import_cache = {}

    def _format_alias(alias):
        return ("import {0.name} as {0.asname}" if alias.asname
                else "import {0.name}").format(alias)

    class Visitor(ast.NodeVisitor):
        def visit_Import(self, node):
            for alias in node.names:
                (import_cache.setdefault(alias.asname or alias.name, set())
                 .add(_format_alias(alias)))

        def visit_ImportFrom(self, node):
            if node.level:  # Skip relative imports.
                return
            for alias in node.names:
                (import_cache.setdefault(alias.asname or alias.name, set())
                 .add("from {} {}".format(node.module, _format_alias(alias))))

    for _, _, entry in (
            ipython.history_manager.get_tail(
                ipython.history_load_length, raw=False)):
        try:
            parsed = ast.parse(entry)
        except SyntaxError:
            continue
        Visitor().visit(parsed)

    return import_cache
项目:dnn-quant    作者:euclidjda    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:visual_mpc    作者:febert    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:atom-tracer    作者:OmarShehata    | 项目源码 | 文件源码
def visit_Assign(self, node):
        for target in node.targets:
            if(isinstance(target,ast.Tuple)):#this is to handle variables declared on the same line
                for el in target.elts:
                    self.grabVar(el)
            else:
                self.grabVar(target)

        ast.NodeVisitor.generic_visit(self, node)#Make sure to run the original method so the AST module can do its thing
项目:atom-tracer    作者:OmarShehata    | 项目源码 | 文件源码
def visit_For(self,node):
        #Iterator variables don't get picked up in the Assign nodes, so we have to find them by looking at for loops
        self.grabVar(node.target)
        #We also keep track of where this for loop starts and ends
        self.forLoops[node.lineno] = {'start':node.lineno,'end':node.body[len(node.body)-1].lineno,'is_arg':False}

        ast.NodeVisitor.generic_visit(self, node)
项目:atom-tracer    作者:OmarShehata    | 项目源码 | 文件源码
def visit_FunctionDef(self,node):
        funcStart = node.lineno
        funcEnd = node.body[len(node.body)-1].lineno
        self.functions[node.name] = {'start':funcStart,'end':funcEnd}
        #Grab the arguments
        argList = node.args.args
        for argNode in argList:
            argName = argNode.arg
            varObj = {'name':argName,'line':node.lineno,'start':node.lineno,'col':-1,'end':funcEnd,'is_arg':True}
            self.varList.append(varObj)

        ast.NodeVisitor.generic_visit(self, node)
项目:atom-tracer    作者:OmarShehata    | 项目源码 | 文件源码
def visit_ClassDef(self, node):
        classStart = node.lineno
        classEnd = node.body[len(node.body)-1].lineno
        self.classes[node.name] = {'start':classStart,'end':classEnd}

        ast.NodeVisitor.generic_visit(self, node)
项目:atom-tracer    作者:OmarShehata    | 项目源码 | 文件源码
def visit_Assign(self, node):
        for target in node.targets:
            if(isinstance(target,ast.Tuple)):#this is to handle variables declared on the same line
                for el in target.elts:
                    self.grabVar(el)
            else:
                self.grabVar(target)
        ast.NodeVisitor.generic_visit(self, node)#Make sure to run the original method so the AST module can do its thing
项目:atom-tracer    作者:OmarShehata    | 项目源码 | 文件源码
def visit_FunctionDef(self,node):
        funcStart = node.lineno
        funcEnd = node.body[len(node.body)-1].lineno
        self.functions[node.name] = {'start':funcStart,'end':funcEnd}
        #Grab the arguments
        argList = node.args.args
        for argNode in argList:
            argName = argNode.arg
            varObj = {'name':argName,'line':node.lineno,'start':node.lineno,'col':-1,'end':funcEnd,'is_arg':True}
            self.varList.append(varObj)
        ast.NodeVisitor.generic_visit(self, node)
项目:python-langserver    作者:sourcegraph    | 项目源码 | 文件源码
def visit_ImportFrom(self, node):
        if node.module and node.module.split(".")[0] == self.name:
            self.result = True

    # Based on ast.NodeVisitor.visit
项目:python-langserver    作者:sourcegraph    | 项目源码 | 文件源码
def visit(self, node):
        # One change from ast.NodeVisitor.visit: do not fallback to generic_visit (we only care about top-level)
        method = 'visit_' + node.__class__.__name__
        visitor = getattr(self, method, None)
        if visitor is not None:
            visitor(node)
项目:Tensorflow-SegNet    作者:tkuanlun350    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:Tensorflow-SegNet    作者:tkuanlun350    | 项目源码 | 文件源码
def visit_Attribute(self, node):  # pylint: disable=invalid-name
    """Handle bare Attributes i.e. [tf.foo, tf.bar].
    Args:
      node: Node that is of type ast.Attribute
    """
    full_name = self._get_attribute_full_path(node)
    if full_name and full_name.startswith("tf."):
      self._rename_functions(node, full_name)
    if full_name in self._api_change_spec.change_to_function:
      if not hasattr(node, "is_function_for_call"):
        new_text = full_name + "()"
        self._file_edit.add("Changed %r to %r"%(full_name, new_text),
                            node.lineno, node.col_offset, full_name, new_text)

    ast.NodeVisitor.generic_visit(self, node)
项目:ram_modified    作者:jtkim-kaist    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:TerpreT    作者:51alg    | 项目源码 | 文件源码
def ast_uses_varset(root, varset):
    class UsesVarsetVisitor(ast.NodeVisitor):
        def __init__(self):
            self.uses_varset = False

        def visit_Name(self, node):
            if node.id in varset:
                self.uses_varset = True

    vis = UsesVarsetVisitor()
    vis.visit(root)
    return vis.uses_varset
项目:TerpreT    作者:51alg    | 项目源码 | 文件源码
def get_method_by_name(module_node, name):
    class Visitor(ast.NodeVisitor):
        def visit_Module(self, node):
            self.result = None
            self.generic_visit(node)

        def visit_FunctionDef(self, node):
            if node.name == name:
                assert self.result is None, "More than one result in module"
                self.result = node
    v = Visitor()
    v.visit(module_node)
    return v.result
项目:TerpreT    作者:51alg    | 项目源码 | 文件源码
def get_class_node(module_node):
    class Visitor(ast.NodeVisitor):
        def visit_Module(self, node):
            self.result = None
            self.generic_visit(node)

        def visit_ClassDef(self, node):
            assert self.result is None, "More than one class in module"
            self.result = node
    v = Visitor()
    v.visit(module_node)
    return v.result
项目:TerpreT    作者:51alg    | 项目源码 | 文件源码
def get_variables(root):
    class Visitor(ast.NodeVisitor):
        def __init__(self):
            self.vars = set()

        def visit_Name(self, node):
            self.vars.add(node.id)

    var_visitor = Visitor()
    var_visitor.visit(root)
    return var_visitor.vars
项目:TerpreT    作者:51alg    | 项目源码 | 文件源码
def split_params_from_model(self, root):
        class CollectParamsVisitor(ast.NodeVisitor):
            def visit_Module(self_c, node):
                self_c.param_statements = []
                self_c.param_dict = None
                self_c.generic_visit(node)

            def visit_Assign(self_c, node):
                if u.is_param_declaration(node):
                    self_c.param_statements.append(node)
                elif u.is_self_params_assignment(node):
                    self_c.param_dict = node
        cpv = CollectParamsVisitor()
        cpv.visit(root)

        class RemoveParamsTransformer(self.MyTransformer):
            def visit_FunctionDef(self_r, node):
                """ Don't recurse into user defined functions """
                return node

            def visit_Assign(self_r, node):
                if u.is_param_declaration(node):
                    return []
                elif u.is_self_params_assignment(node):
                    return []
                else:
                    return node
        rpt = RemoveParamsTransformer()
        root = rpt.visit(root)

        return root, cpv.param_statements, cpv.param_dict
项目:empyrion-python-api    作者:huhlig    | 项目源码 | 文件源码
def scan_opcodes_cli(self, co):
        import ast
        with open(co.co_filename, 'rU') as f:
            nodes = ast.parse(f.read(), co.co_filename)

        items = []

        class ModuleFinderVisitor(ast.NodeVisitor):
            def visit_Assign(self, node):
                for x in node.targets:
                    if isinstance(x, ast.Subscript):
                        if isinstance(x.value, ast.Name):
                            items.append(("store", (x.value.id, )))
                        elif isinstance(x.value, ast.Attribute):
                            items.append(("store", (x.value.attr, )))
                        else:
                            print 'Unknown in store: %s' % type(x.value).__name__
                    elif isinstance(x, ast.Name):
                        items.append(("store", (x.id, )))

            def visit_Import(self, node):
                items.extend([("import", (None, x.name)) for x in node.names])

            def visit_ImportFrom(self, node):
                if node.level == 1:
                    items.append(("relative_import", (node.level, [x.name for x in node.names], node.module)))
                else:
                    items.extend([("import", ([x.name for x in node.names], node.module))])

        v = ModuleFinderVisitor()
        v.visit(nodes)

        for what, args in items:
            yield what, args
项目:offshoot    作者:SerpentAI    | 项目源码 | 文件源码
def _find_decorators(cls):
        result = dict()

        def visit_FunctionDef(node):
            result[node.name] = [ast.dump(e) for e in node.decorator_list]

        v = ast.NodeVisitor()

        v.visit_FunctionDef = visit_FunctionDef
        v.visit(compile(inspect.getsource(cls), '?', 'exec', ast.PyCF_ONLY_AST))

        return result
项目:deliver    作者:orchestor    | 项目源码 | 文件源码
def visit_Attribute(self, node):
            ast.NodeVisitor.generic_visit(self, node)
            self.ls.append(node.attr)
项目:deliver    作者:orchestor    | 项目源码 | 文件源码
def visit_Call(self, node):
            p = ParseCall()
            p.visit(node.func)
            ast.NodeVisitor.generic_visit(self, node)

            if p.ls[-1] == 'simplefilter' or p.ls[-1] == 'filterwarnings':
                if node.args[0].s == "ignore":
                    raise AssertionError(
                        "ignore filter should not be used; found in "
                        "{} on line {}".format(self.__filename, node.lineno))

            if p.ls[-1] == 'warn' and (
                    len(p.ls) == 1 or p.ls[-2] == 'warnings'):

                if "testing/tests/test_warnings.py" is self.__filename:
                    # This file
                    return

                # See if stacklevel exists:
                if len(node.args) == 3:
                    return
                args = {kw.arg for kw in node.keywords}
                if "stacklevel" in args:
                    return
                raise AssertionError(
                    "warnings should have an appropriate stacklevel; found in "
                    "{} on line {}".format(self.__filename, node.lineno))
项目:OpenMDAO    作者:OpenMDAO    | 项目源码 | 文件源码
def __init__(self, fname, cache):
        ast.NodeVisitor.__init__(self)
        self.fname = fname
        self.cache = cache
        self.class_stack = []
项目:Tensorflow-Turitors    作者:Xls1994    | 项目源码 | 文件源码
def generic_visit(self, node):
    ast.NodeVisitor.generic_visit(self, node)
项目:raincoat    作者:peopledoc    | 项目源码 | 文件源码
def visit_node(self, node):
        self.path.append(node.name)
        node_name = ".".join(self.path)
        if node_name in self.filters:
            self.nodes[node_name] = node
        ast.NodeVisitor.generic_visit(self, node)
        self.path.pop()
        self.ended_nodes.append(node)
项目:PyValentina    作者:FabriceSalvaire    | 项目源码 | 文件源码
def __init__(self, calculator):

        super(NodeVisitor, self).__init__()
        self._calculator = calculator
        self._dependencies = []

    ##############################################
项目:PyValentina    作者:FabriceSalvaire    | 项目源码 | 文件源码
def dependencies(self):
        return self._dependencies

    ##############################################

    # def visit(self, node):

    #     print(node)
    #     super(NodeVisitor, self).visit(node)

    ##############################################
项目:PyValentina    作者:FabriceSalvaire    | 项目源码 | 文件源码
def _compile(self):

        expression = self._expression
        self._logger.info("expression '{}'".format(expression))

        # Python don't accept identifier starting with @
        # https://docs.python.org/3.5/reference/lexical_analysis.html#identifiers
        if '@' in expression:
            custom_measurements = []
            start = 0
            while True:
                name, start = self._find_name('@', start)
                if name is None:
                    break
                else:
                    custom_measurements.append(name)
            for measurement in custom_measurements:
                expression = self.expression.replace(measurement, self._calculator.measurements[measurement].name)

        functions = []
        for function in (
                'Angle1Spl_',
                'Angle2Spl_',
                'AngleLine_',
                'CurrentLength',
                'C1LengthSpl_',
                'C2LengthSpl_',
                'Line_',
                'Spl_',
        ):
            start = 0
            while True:
                name, start = self._find_name(function, start)
                if name is None:
                    break
                else:
                    functions.append(name)
        # self._logger.info('Functions ' + str(functions))
        for function_call in functions:
            parts = function_call.split('_')
            function = parts[0]
            args = parts[1:]
            pythonised_function = '__calculator__._function_' + function + '(' + ', '.join(["'{}'".format(x) for x in args]) + ')'
            # self._logger.info('Function {} {} -> {}'.format(function, args, pythonised_function))
            expression = expression.replace(function_call, pythonised_function)

        self._logger.info("Pythonised expression '{}'".format(expression))

        # Fixme: What is the (supported) grammar ?
        # http://beltoforion.de/article.php?a=muparser
        # http://beltoforion.de/article.php?a=muparserx
        self._ast = ast.parse(expression, mode='eval')
        node_visitor = NodeVisitor(self._calculator)
        node_visitor.generic_visit(self._ast)
        self._dependencies = node_visitor.dependencies
        self._code = compile(self._ast, '<string>', mode='eval')
        # print('AST', astunparse.dump(self._ast))
        # print('AST -> Python', astunparse.unparse(self._ast))
        ## print('AST -> Python', astor.to_source(self._ast.body))

    ##############################################