File: visitors.rst

package info (click to toggle)
python-libcst 1.8.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,240 kB
  • sloc: python: 78,096; makefile: 15; sh: 2
file content (144 lines) | stat: -rw-r--r-- 5,369 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
.. _libcst-visitors:

Visitors
========

.. autoclass:: libcst.CSTVisitor
.. autoclass:: libcst.CSTTransformer
.. autofunction:: libcst.RemoveFromParent
.. autoclass:: libcst.RemovalSentinel
.. autoclass:: libcst.FlattenSentinel

Visit and Leave Helper Functions
--------------------------------

While it is possible to subclass from :class:`~libcst.CSTVisitor` or :class:`~libcst.CSTTransformer`
and override the ``on_visit``/``on_leave``/``on_visit_attribute``/``on_leave_attribute`` functions
directly, it is not recommended. The default implementation for both visitors will look up any
``visit_<Type[CSTNode]>``, ``leave_<Type[CSTNode]>``, ``visit_<Type[CSTNode]>_<attribute>`` and
``leave_<Type[CSTNode]>_<attribute>`` method on the visitor subclass and call them directly.
If such a function exists for the node in question, the visitor base class will call the relevant
function, respecting the above outlined semantics. If the function does not exist, the visitor base
class will assume that you do not care about that node and visit its children for you without
requiring a default implementation.

Much like ``on_visit``, ``visit_<Type[CSTNode]>`` return a boolean specifying whether or not LibCST
should visit a node's children. As a convenience, you can return ``None`` instead of a boolean value
from your ``visit_<Type[CSTNode]>`` functions. Returning a ``None`` value is treated as a request for
default behavior, which causes the visitor to traverse children. It is equivalent to returning
``True``, but requires no explicit return.

For example, the below visitor will visit every function definition, traversing to its children only
if the function name doesn't include the word "foo". Notice that we don't need to provide our own
``on_visit`` or ``on_leave`` function, nor do we need to provide visit and leave functions for the
rest of the nodes which we do not care about. This will have the effect of visiting all strings not
inside of functions that have "foo" in the name. Note that we take advantage of default behavior when
we decline to return a value in ``visit_SimpleString``.

.. code-block:: python

    class FooingAround(libcst.CSTVisitor):
        def visit_FunctionDef(self, node: libcst.FunctionDef) -> bool:
            return "foo" not in node.name.value

        def visit_SimpleString(self, node: libcst.SimpleString) -> None:
            print(node.value)

An example Python REPL using the above visitor is as follows::

    >>> import libcst
    >>> demo = libcst.parse_module("'abc'\n'123'\ndef foo():\n    'not printed'")
    >>> _ = demo.visit(FooingAround())
    'abc'
    '123'

.. _libcst-visitor-traversal:

Traversal Order
---------------

Traversal of any parsed tree directly matches the order that tokens appear in the source which
was parsed. LibCST will first call ``on_visit`` for the node. Then, for each of the node's
child attributes, LibCST will call ``on_visit_attribute`` for the node's attribute, followed
by running the same visit algorithm on each child node in the node's attribute. Then,
``on_leave_attribute`` is called. After each attribute has been fully traversed, LibCST will
call ``on_leave`` for the node. Note that LibCST will only call ``on_visit_attribute`` and
``on_leave_attribute`` for attributes in which there might be a LibCST node as a child. It
will not call attribute visitors for attributes which are built-in python types.

For example, take the following simple tree generated by calling ``parse_expression("1+2")``.

.. code-block:: python

    BinaryOperation(
        left=Integer(
            value='1',
            lpar=[],
            rpar=[],
        ),
        operator=Add(
            whitespace_before=SimpleWhitespace(
                value='',
            ),
            whitespace_after=SimpleWhitespace(
                value='',
            ),
        ),
        right=Integer(
            value='2',
            lpar=[],
            rpar=[],
        ),
        lpar=[],
        rpar=[],
    )

Assuming you have a visitor that overrides every convenience helper method available,
methods will be called in this order:

.. code-block:: python

    visit_BinaryOperation
    visit_BinaryOperation_lpar
    leave_BinaryOperation_lpar
    visit_BinaryOperation_left
    visit_Integer
    visit_Integer_lpar
    leave_Integer_lpar
    visit_Integer_rpar
    leave_Integer_rpar
    leave_Integer
    leave_BinaryOperation_left
    visit_BinaryOperation_operator
    visit_Add
    visit_Add_whitespace_before
    visit_SimpleWhitespace
    leave_SimpleWhitespace
    leave_Add_whitespace_before
    visit_Add_whitespace_after
    visit_SimpleWhitespace
    leave_SimpleWhitespace
    leave_Add_whitespace_after
    leave_Add
    leave_BinaryOperation_operator
    visit_BinaryOperation_right
    visit_Integer
    visit_Integer_lpar
    leave_Integer_lpar
    visit_Integer_rpar
    leave_Integer_rpar
    leave_Integer
    leave_BinaryOperation_right
    visit_BinaryOperation_rpar
    leave_BinaryOperation_rpar
    leave_BinaryOperation

Batched Visitors
----------------

A batchable visitor class is provided to facilitate performing operations that
can be performed in parallel in a single traversal over a CST. An example of this
is :ref:`metadata computation<libcst-metadata>`.

.. autoclass:: libcst.BatchableCSTVisitor
.. autofunction:: libcst.visit_batched