mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
3.2 KiB
87 lines
3.2 KiB
# -*- coding: utf-8 -*- |
|
""" |
|
jinja2.visitor |
|
~~~~~~~~~~~~~~ |
|
|
|
This module implements a visitor for the nodes. |
|
|
|
:copyright: (c) 2010 by the Jinja Team. |
|
:license: BSD. |
|
""" |
|
from jinja2.nodes import Node |
|
|
|
|
|
class NodeVisitor(object): |
|
"""Walks the abstract syntax tree and call visitor functions for every |
|
node found. The visitor functions may return values which will be |
|
forwarded by the `visit` method. |
|
|
|
Per default the visitor functions for the nodes are ``'visit_'`` + |
|
class name of the node. So a `TryFinally` node visit function would |
|
be `visit_TryFinally`. This behavior can be changed by overriding |
|
the `get_visitor` function. If no visitor function exists for a node |
|
(return value `None`) the `generic_visit` visitor is used instead. |
|
""" |
|
|
|
def get_visitor(self, node): |
|
"""Return the visitor function for this node or `None` if no visitor |
|
exists for this node. In that case the generic visit function is |
|
used instead. |
|
""" |
|
method = 'visit_' + node.__class__.__name__ |
|
return getattr(self, method, None) |
|
|
|
def visit(self, node, *args, **kwargs): |
|
"""Visit a node.""" |
|
f = self.get_visitor(node) |
|
if f is not None: |
|
return f(node, *args, **kwargs) |
|
return self.generic_visit(node, *args, **kwargs) |
|
|
|
def generic_visit(self, node, *args, **kwargs): |
|
"""Called if no explicit visitor function exists for a node.""" |
|
for node in node.iter_child_nodes(): |
|
self.visit(node, *args, **kwargs) |
|
|
|
|
|
class NodeTransformer(NodeVisitor): |
|
"""Walks the abstract syntax tree and allows modifications of nodes. |
|
|
|
The `NodeTransformer` will walk the AST and use the return value of the |
|
visitor functions to replace or remove the old node. If the return |
|
value of the visitor function is `None` the node will be removed |
|
from the previous location otherwise it's replaced with the return |
|
value. The return value may be the original node in which case no |
|
replacement takes place. |
|
""" |
|
|
|
def generic_visit(self, node, *args, **kwargs): |
|
for field, old_value in node.iter_fields(): |
|
if isinstance(old_value, list): |
|
new_values = [] |
|
for value in old_value: |
|
if isinstance(value, Node): |
|
value = self.visit(value, *args, **kwargs) |
|
if value is None: |
|
continue |
|
elif not isinstance(value, Node): |
|
new_values.extend(value) |
|
continue |
|
new_values.append(value) |
|
old_value[:] = new_values |
|
elif isinstance(old_value, Node): |
|
new_node = self.visit(old_value, *args, **kwargs) |
|
if new_node is None: |
|
delattr(node, field) |
|
else: |
|
setattr(node, field, new_node) |
|
return node |
|
|
|
def visit_list(self, node, *args, **kwargs): |
|
"""As transformers may return lists in some places this method |
|
can be used to enforce a list as return value. |
|
""" |
|
rv = self.visit(node, *args, **kwargs) |
|
if not isinstance(rv, list): |
|
rv = [rv] |
|
return rv
|
|
|