(root)/
Python-3.12.0/
Lib/
lib2to3/
fixes/
fix_except.py
       1  """Fixer for except statements with named exceptions.
       2  
       3  The following cases will be converted:
       4  
       5  - "except E, T:" where T is a name:
       6  
       7      except E as T:
       8  
       9  - "except E, T:" where T is not a name, tuple or list:
      10  
      11          except E as t:
      12              T = t
      13  
      14      This is done because the target of an "except" clause must be a
      15      name.
      16  
      17  - "except E, T:" where T is a tuple or list literal:
      18  
      19          except E as t:
      20              T = t.args
      21  """
      22  # Author: Collin Winter
      23  
      24  # Local imports
      25  from .. import pytree
      26  from ..pgen2 import token
      27  from .. import fixer_base
      28  from ..fixer_util import Assign, Attr, Name, is_tuple, is_list, syms
      29  
      30  def find_excepts(nodes):
      31      for i, n in enumerate(nodes):
      32          if n.type == syms.except_clause:
      33              if n.children[0].value == 'except':
      34                  yield (n, nodes[i+2])
      35  
      36  class ESC[4;38;5;81mFixExcept(ESC[4;38;5;149mfixer_baseESC[4;38;5;149m.ESC[4;38;5;149mBaseFix):
      37      BM_compatible = True
      38  
      39      PATTERN = """
      40      try_stmt< 'try' ':' (simple_stmt | suite)
      41                    cleanup=(except_clause ':' (simple_stmt | suite))+
      42                    tail=(['except' ':' (simple_stmt | suite)]
      43                          ['else' ':' (simple_stmt | suite)]
      44                          ['finally' ':' (simple_stmt | suite)]) >
      45      """
      46  
      47      def transform(self, node, results):
      48          syms = self.syms
      49  
      50          tail = [n.clone() for n in results["tail"]]
      51  
      52          try_cleanup = [ch.clone() for ch in results["cleanup"]]
      53          for except_clause, e_suite in find_excepts(try_cleanup):
      54              if len(except_clause.children) == 4:
      55                  (E, comma, N) = except_clause.children[1:4]
      56                  comma.replace(Name("as", prefix=" "))
      57  
      58                  if N.type != token.NAME:
      59                      # Generate a new N for the except clause
      60                      new_N = Name(self.new_name(), prefix=" ")
      61                      target = N.clone()
      62                      target.prefix = ""
      63                      N.replace(new_N)
      64                      new_N = new_N.clone()
      65  
      66                      # Insert "old_N = new_N" as the first statement in
      67                      #  the except body. This loop skips leading whitespace
      68                      #  and indents
      69                      #TODO(cwinter) suite-cleanup
      70                      suite_stmts = e_suite.children
      71                      for i, stmt in enumerate(suite_stmts):
      72                          if isinstance(stmt, pytree.Node):
      73                              break
      74  
      75                      # The assignment is different if old_N is a tuple or list
      76                      # In that case, the assignment is old_N = new_N.args
      77                      if is_tuple(N) or is_list(N):
      78                          assign = Assign(target, Attr(new_N, Name('args')))
      79                      else:
      80                          assign = Assign(target, new_N)
      81  
      82                      #TODO(cwinter) stopgap until children becomes a smart list
      83                      for child in reversed(suite_stmts[:i]):
      84                          e_suite.insert_child(0, child)
      85                      e_suite.insert_child(i, assign)
      86                  elif N.prefix == "":
      87                      # No space after a comma is legal; no space after "as",
      88                      # not so much.
      89                      N.prefix = " "
      90  
      91          #TODO(cwinter) fix this when children becomes a smart list
      92          children = [c.clone() for c in node.children[:3]] + try_cleanup + tail
      93          return pytree.Node(node.type, children)