(root)/
Python-3.12.0/
Lib/
lib2to3/
fixes/
fix_raise.py
       1  """Fixer for 'raise E, V, T'
       2  
       3  raise         -> raise
       4  raise E       -> raise E
       5  raise E, V    -> raise E(V)
       6  raise E, V, T -> raise E(V).with_traceback(T)
       7  raise E, None, T -> raise E.with_traceback(T)
       8  
       9  raise (((E, E'), E''), E'''), V -> raise E(V)
      10  raise "foo", V, T               -> warns about string exceptions
      11  
      12  
      13  CAVEATS:
      14  1) "raise E, V" will be incorrectly translated if V is an exception
      15     instance. The correct Python 3 idiom is
      16  
      17          raise E from V
      18  
      19     but since we can't detect instance-hood by syntax alone and since
      20     any client code would have to be changed as well, we don't automate
      21     this.
      22  """
      23  # Author: Collin Winter
      24  
      25  # Local imports
      26  from .. import pytree
      27  from ..pgen2 import token
      28  from .. import fixer_base
      29  from ..fixer_util import Name, Call, Attr, ArgList, is_tuple
      30  
      31  class ESC[4;38;5;81mFixRaise(ESC[4;38;5;149mfixer_baseESC[4;38;5;149m.ESC[4;38;5;149mBaseFix):
      32  
      33      BM_compatible = True
      34      PATTERN = """
      35      raise_stmt< 'raise' exc=any [',' val=any [',' tb=any]] >
      36      """
      37  
      38      def transform(self, node, results):
      39          syms = self.syms
      40  
      41          exc = results["exc"].clone()
      42          if exc.type == token.STRING:
      43              msg = "Python 3 does not support string exceptions"
      44              self.cannot_convert(node, msg)
      45              return
      46  
      47          # Python 2 supports
      48          #  raise ((((E1, E2), E3), E4), E5), V
      49          # as a synonym for
      50          #  raise E1, V
      51          # Since Python 3 will not support this, we recurse down any tuple
      52          # literals, always taking the first element.
      53          if is_tuple(exc):
      54              while is_tuple(exc):
      55                  # exc.children[1:-1] is the unparenthesized tuple
      56                  # exc.children[1].children[0] is the first element of the tuple
      57                  exc = exc.children[1].children[0].clone()
      58              exc.prefix = " "
      59  
      60          if "val" not in results:
      61              # One-argument raise
      62              new = pytree.Node(syms.raise_stmt, [Name("raise"), exc])
      63              new.prefix = node.prefix
      64              return new
      65  
      66          val = results["val"].clone()
      67          if is_tuple(val):
      68              args = [c.clone() for c in val.children[1:-1]]
      69          else:
      70              val.prefix = ""
      71              args = [val]
      72  
      73          if "tb" in results:
      74              tb = results["tb"].clone()
      75              tb.prefix = ""
      76  
      77              e = exc
      78              # If there's a traceback and None is passed as the value, then don't
      79              # add a call, since the user probably just wants to add a
      80              # traceback. See issue #9661.
      81              if val.type != token.NAME or val.value != "None":
      82                  e = Call(exc, args)
      83              with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])]
      84              new = pytree.Node(syms.simple_stmt, [Name("raise")] + with_tb)
      85              new.prefix = node.prefix
      86              return new
      87          else:
      88              return pytree.Node(syms.raise_stmt,
      89                                 [Name("raise"), Call(exc, args)],
      90                                 prefix=node.prefix)