Repository: asottile/pyupgrade

Issue:
IndexError with pytest's fixtures.py
```
% pyupgrade --py3-only --keep-percent-format src/_pytest/fixtures.py
Traceback (most recent call last):
  File "…/Vcs/pytest/.venv/bin/pyupgrade", line 11, in <module>
    sys.exit(main())
  File "…/Vcs/pytest/.venv/lib/python3.7/site-packages/pyupgrade.py", line 1428, in main
    ret |= fix_file(filename, args)
  File "…/Vcs/pytest/.venv/lib/python3.7/site-packages/pyupgrade.py", line 1402, in fix_file
    contents_text = _fix_py3_plus(contents_text)
  File "…/Vcs/pytest/.venv/lib/python3.7/site-packages/pyupgrade.py", line 1244, in _fix_py3_plus
    _replace_call(tokens, i, end, func_args, template)
  File "…/Vcs/pytest/.venv/lib/python3.7/site-packages/pyupgrade.py", line 1171, in _replace_call
    src = tmpl.format(args=arg_strs, rest=rest)
IndexError: list index out of range
```
`print(repr(tmpl), repr(arg_strs), repr(rest))` shows:

> 'raise {args[1]}.with_traceback({args[2]})' ['*err'] ''

Discussion:

Patch:
diff --git a/pyupgrade.py b/pyupgrade.py
index 31a603e..b3c6f9c 100644
--- a/pyupgrade.py
+++ b/pyupgrade.py
@@ -1001,7 +1001,8 @@ class FindPy3Plus(ast.NodeVisitor):
         if (
                 len(node.bases) == 1 and
                 isinstance(node.bases[0], ast.Call) and
-                self._is_six(node.bases[0].func, ('with_metaclass',))
+                self._is_six(node.bases[0].func, ('with_metaclass',)) and
+                not _starargs(node.bases[0])
         ):
             self.six_with_metaclass.add(_ast_to_offset(node.bases[0]))
 
@@ -1047,11 +1048,12 @@ class FindPy3Plus(ast.NodeVisitor):
             self.six_type_ctx[_ast_to_offset(node.args[1])] = node.args[1]
         elif self._is_six(node.func, ('b',)):
             self.six_b.add(_ast_to_offset(node))
-        elif self._is_six(node.func, SIX_CALLS):
+        elif self._is_six(node.func, SIX_CALLS) and not _starargs(node):
             self.six_calls[_ast_to_offset(node)] = node
         elif (
                 isinstance(self._previous_node, ast.Expr) and
-                self._is_six(node.func, SIX_RAISES)
+                self._is_six(node.func, SIX_RAISES) and
+                not _starargs(node)
         ):
             self.six_raises[_ast_to_offset(node)] = node
         elif (


Test patch:
diff --git a/tests/pyupgrade_test.py b/tests/pyupgrade_test.py
index 102e7b9..fcdb2ea 100644
--- a/tests/pyupgrade_test.py
+++ b/tests/pyupgrade_test.py
@@ -1098,6 +1098,9 @@ def test_fix_classes(s, expected):
         'print(six.b(   "123"))',
         # intentionally not handling this case due to it being a bug (?)
         'class C(six.with_metaclass(Meta, B), D): pass',
+        # cannot determine args to rewrite them
+        'six.reraise(*err)', 'six.b(*a)', 'six.u(*a)',
+        'class C(six.with_metaclass(*a)): pass',
     )
 )
 def test_fix_six_noop(s):