class_docstr: Base class for general-purpose Python-to-Python code transformation.
  
  This is an extension of ast.NodeTransformer that provides the additional
  functions offered by NodeStateTracker.
class_docstr_tok: ["Base","class","for","general-purpose","Python-to-Python","code","transformation",".","This","is","an","extension","of","ast.NodeTransformer","that","provides","the","additional","functions","offered","by","NodeStateTracker","."]
code: def visit(self, node):
      if not isinstance(node, gast.AST):
          # This is not that uncommon a mistake: various node bodies are lists, for
          # example, posing a land mine for transformers that need to recursively
          # call `visit`.  The error needs to be raised before the exception handler
          # below is installed, because said handler will mess up if `node` is not,
          # in fact, a node.
          msg = (
              'invalid value for "node": expected "ast.AST", got "{}"; to'
              ' visit lists of nodes, use "visit_block" instead'
          ).format(type(node))
          raise ValueError(msg)
  
      if anno.hasanno(node, anno.Basic.SKIP_PROCESSING):
          return node
  
      parent_origin = self.ctx.current_origin
      if anno.hasanno(node, anno.Basic.ORIGIN):
          self.ctx.current_origin = anno.getanno(
              node, anno.Basic.ORIGIN
          )
  
      try:
          processing_expr_node = isinstance(node, gast.Expr)
          if processing_expr_node:
              entry_expr_value = node.value
  
          result = super(Base, self).visit(node)
  
          # Adjust for consistency: replacing the value of an Expr with
          # an Assign node removes the need for the Expr node.
          if (
              processing_expr_node
              and isinstance(result, gast.Expr)
              and (result.value is not entry_expr_value)
          ):
              # When the replacement is a list, it is assumed that the list came
              # from a template that contained a number of statements, which
              # themselves are standalone and don't require an enclosing Expr.
              if isinstance(
                  result.value,
                  (list, tuple, gast.Assign, gast.AugAssign),
              ):
                  result = result.value
  
          # By default, all replacements receive the origin info of the replaced
          # node.
          if result is not node and result is not None:
              inherited_origin = anno.getanno(
                  node, anno.Basic.ORIGIN, default=parent_origin
              )
              if inherited_origin is not None:
                  nodes_to_adjust = result
                  if isinstance(result, (list, tuple)):
                      nodes_to_adjust = result
                  else:
                      nodes_to_adjust = (result,)
                  for n in nodes_to_adjust:
                      if not anno.hasanno(n, anno.Basic.ORIGIN):
                          anno.setanno(
                              n, anno.Basic.ORIGIN, inherited_origin
                          )
      finally:
          self.ctx.current_origin = parent_origin
  
      return result
  
imports: import collections
  import enum
  import gast
  from nvidia.dali._autograph.pyct import anno
  from nvidia.dali._autograph.pyct import parser
  from nvidia.dali._autograph.pyct import pretty_printer
  from nvidia.dali._autograph.pyct import templates
label_desc: Use image node_id 3 for calling the Base obj's underlying member method code with example usage: obj.visit(node) and returns: result, node