Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add missing docstrings, have decorators error when used incorrectly
  • Loading branch information
nchammas committed Jul 14, 2025
commit a383d4d6cc30626af508c1b41fa7531354a25159
53 changes: 47 additions & 6 deletions lark/visitors.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,11 +417,16 @@ class Interpreter(_Decoratable, ABC, Generic[_Leaf_T, _Return_T]):
"""

def visit(self, tree: Tree[_Leaf_T]) -> _Return_T:
"Visit the tree, starting with the root and finally the leaves (top-down)."
# There are no guarantees on the type of the value produced by calling a user func for a
# child will produce. So only annotate the public method and use an internal method when
# visiting child trees.
return self._visit_tree(tree)

def visit_topdown(self, tree: Tree[_Leaf_T]):
"Interpreters only work top-down. This method is identical to `visit()`."
return self.visit(tree)

def _visit_tree(self, tree: Tree[_Leaf_T]):
f = getattr(self, tree.data)
wrapper = getattr(f, 'visit_wrapper', None)
Expand All @@ -431,22 +436,45 @@ def _visit_tree(self, tree: Tree[_Leaf_T]):
return f(tree)

def visit_children(self, tree: Tree[_Leaf_T]) -> List:
return [self._visit_tree(child) if isinstance(child, Tree) else child
for child in tree.children]
"Visit all the children of this tree and return the results as a list."
return [
self._visit_tree(child)
if isinstance(child, Tree)
else child
for child in tree.children
]

def __getattr__(self, name):
return self.__default__

def __default__(self, tree):
"""
Default function that is called if there is no attribute matching ``tree.data``.

Can be overridden. Defaults to visiting all the tree's children.
"""
return self.visit_children(tree)


_InterMethod = Callable[[Type[Interpreter], _Return_T], _R]

def visit_children_decor(func: _InterMethod) -> _InterMethod:
"See Interpreter"
"""
A wrapper around Interpreter methods. It makes the wrapped node method automatically visit the
node's children before proceeding with the logic you have defined for that node.

Example:
::

class ProcessQuery(Interpreter):
@visit_children_decor
def query(self, tree):
pass
"""
@wraps(func)
def inner(cls, tree):
if not isinstance(cls, Interpreter):
raise TypeError("visit_children_decor can only be applied to Interpreter methods.")
values = cls.visit_children(tree)
return func(cls, values)
return inner
Expand Down Expand Up @@ -511,11 +539,12 @@ def _vargs_tree(f, data, children, meta):


def v_args(inline: bool = False, meta: bool = False, tree: bool = False, wrapper: Optional[Callable] = None) -> Callable[[_DECORATED], _DECORATED]:
"""A convenience decorator factory for modifying the behavior of user-supplied callback methods of ``Transformer`` classes.
"""A convenience decorator factory for modifying the behavior of user-supplied callback methods
of ``Transformer`` or ``Interpreter`` classes.

By default, transformer callback methods accept one argument - a list of the node's children.
By default, the callback methods for these classes accept one argument - a list of the node's children.

``v_args`` can modify this behavior. When used on a ``Transformer`` class definition, it applies to
``v_args`` can modify this behavior. When used on the class definition, it applies to
all the callback methods inside it.

``v_args`` can be applied to a single method, or to an entire class. When applied to both,
Expand Down Expand Up @@ -567,6 +596,18 @@ def tree_node(self, tree):
func = wrapper

def _visitor_args_dec(obj):
from inspect import isclass
if isclass(obj) and issubclass(obj, Visitor):
raise TypeError("v_args cannot be applied to Visitor classes.")
if callable(obj) and not isclass(obj):
@wraps(obj)
def method_wrapper(*args, **kwargs):
if args:
self_instance = args[0]
if isinstance(self_instance, Visitor):
raise TypeError("v_args cannot be applied to Visitor methods.")
return obj(*args, **kwargs)
return _apply_v_args(method_wrapper, func)
Comment on lines +595 to +606
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect in at least one way: We want this to error out on any classes other than Transformer and Interpreter (or their subclasses), not just Visitor. But I am struggling to fix this without causing other tests to fail; I don't really follow this code well to begin with, and would be OK just stripping it out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erezsh - Would you like me to remove this new logic as well, or do you have a suggestion as to how we could make it better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erezsh - Checking in again here. Happy to cut this PR back to just documentation changes if you prefer that.

return _apply_v_args(obj, func)
return _visitor_args_dec

Expand Down