(root)/
Python-3.12.0/
Lib/
lib2to3/
fixes/
fix_next.py
       1  """Fixer for it.next() -> next(it), per PEP 3114."""
       2  # Author: Collin Winter
       3  
       4  # Things that currently aren't covered:
       5  #   - listcomp "next" names aren't warned
       6  #   - "with" statement targets aren't checked
       7  
       8  # Local imports
       9  from ..pgen2 import token
      10  from ..pygram import python_symbols as syms
      11  from .. import fixer_base
      12  from ..fixer_util import Name, Call, find_binding
      13  
      14  bind_warning = "Calls to builtin next() possibly shadowed by global binding"
      15  
      16  
      17  class ESC[4;38;5;81mFixNext(ESC[4;38;5;149mfixer_baseESC[4;38;5;149m.ESC[4;38;5;149mBaseFix):
      18      BM_compatible = True
      19      PATTERN = """
      20      power< base=any+ trailer< '.' attr='next' > trailer< '(' ')' > >
      21      |
      22      power< head=any+ trailer< '.' attr='next' > not trailer< '(' ')' > >
      23      |
      24      classdef< 'class' any+ ':'
      25                suite< any*
      26                       funcdef< 'def'
      27                                name='next'
      28                                parameters< '(' NAME ')' > any+ >
      29                       any* > >
      30      |
      31      global=global_stmt< 'global' any* 'next' any* >
      32      """
      33  
      34      order = "pre" # Pre-order tree traversal
      35  
      36      def start_tree(self, tree, filename):
      37          super(FixNext, self).start_tree(tree, filename)
      38  
      39          n = find_binding('next', tree)
      40          if n:
      41              self.warning(n, bind_warning)
      42              self.shadowed_next = True
      43          else:
      44              self.shadowed_next = False
      45  
      46      def transform(self, node, results):
      47          assert results
      48  
      49          base = results.get("base")
      50          attr = results.get("attr")
      51          name = results.get("name")
      52  
      53          if base:
      54              if self.shadowed_next:
      55                  attr.replace(Name("__next__", prefix=attr.prefix))
      56              else:
      57                  base = [n.clone() for n in base]
      58                  base[0].prefix = ""
      59                  node.replace(Call(Name("next", prefix=node.prefix), base))
      60          elif name:
      61              n = Name("__next__", prefix=name.prefix)
      62              name.replace(n)
      63          elif attr:
      64              # We don't do this transformation if we're assigning to "x.next".
      65              # Unfortunately, it doesn't seem possible to do this in PATTERN,
      66              #  so it's being done here.
      67              if is_assign_target(node):
      68                  head = results["head"]
      69                  if "".join([str(n) for n in head]).strip() == '__builtin__':
      70                      self.warning(node, bind_warning)
      71                  return
      72              attr.replace(Name("__next__"))
      73          elif "global" in results:
      74              self.warning(node, bind_warning)
      75              self.shadowed_next = True
      76  
      77  
      78  ### The following functions help test if node is part of an assignment
      79  ###  target.
      80  
      81  def is_assign_target(node):
      82      assign = find_assign(node)
      83      if assign is None:
      84          return False
      85  
      86      for child in assign.children:
      87          if child.type == token.EQUAL:
      88              return False
      89          elif is_subtree(child, node):
      90              return True
      91      return False
      92  
      93  def find_assign(node):
      94      if node.type == syms.expr_stmt:
      95          return node
      96      if node.type == syms.simple_stmt or node.parent is None:
      97          return None
      98      return find_assign(node.parent)
      99  
     100  def is_subtree(root, node):
     101      if root == node:
     102          return True
     103      return any(is_subtree(c, node) for c in root.children)