| 69 | |
| 70 | |
| 71 | class TreeTransform(GenericASTTraversal, object): |
| 72 | def __init__( |
| 73 | self, |
| 74 | version: tuple, |
| 75 | is_pypy=False, |
| 76 | show_ast: Optional[dict] = None, |
| 77 | ): |
| 78 | self.version = version |
| 79 | self.showast = show_ast |
| 80 | self.is_pypy = is_pypy |
| 81 | return |
| 82 | |
| 83 | def maybe_show_tree(self, tree): |
| 84 | if isinstance(self.showast, dict) and ( |
| 85 | self.showast.get("before") or self.showast.get("after") |
| 86 | ): |
| 87 | maybe_show_tree(self, tree) |
| 88 | |
| 89 | def preorder(self, node=None): |
| 90 | """Walk the tree in roughly 'preorder' (a bit of a lie explained below). |
| 91 | For each node with typestring name *name* if the |
| 92 | node has a method called n_*name*, call that before walking |
| 93 | children. |
| 94 | |
| 95 | In typical use a node with children can call "preorder" in any |
| 96 | order it wants which may skip children or order then in ways |
| 97 | other than first to last. In fact, this this happens. So in |
| 98 | this sense this function not strictly preorder. |
| 99 | """ |
| 100 | if node is None: |
| 101 | node = self.ast |
| 102 | |
| 103 | try: |
| 104 | name = "n_" + self.typestring(node) |
| 105 | if hasattr(self, name): |
| 106 | func = getattr(self, name) |
| 107 | node = func(node) |
| 108 | except GenericASTTraversalPruningException: |
| 109 | return |
| 110 | |
| 111 | for i, kid in enumerate(node): |
| 112 | node[i] = self.preorder(kid) |
| 113 | return node |
| 114 | |
| 115 | def n_mkfunc(self, node): |
| 116 | """If the function has a docstring (this is found in the code |
| 117 | constants), pull that out and make it part of the syntax |
| 118 | tree. When generating the source string that AST node rather |
| 119 | than the code field is seen and used. |
| 120 | """ |
| 121 | |
| 122 | if self.version >= (3, 7): |
| 123 | code_index = -3 |
| 124 | else: |
| 125 | code_index = -2 |
| 126 | |
| 127 | code = find_code_node(node, code_index).attr |
| 128 | |