Repository: asottile/add-trailing-comma

Issue:
"IndexError: pop from empty list" when processing valid file
(Wasn't sure how to describe this scenario better, sorry for the lame title.)

Here's a fairly minimal example:

```python
(
    a
).thing(b)
```

Produces an error when processing with add-trailing-comma v0.2.0:

```python
Traceback (most recent call last):
  File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/bin/add-trailing-comma", line 9, in <module>
    load_entry_point('add-trailing-comma==0.2.0', 'console_scripts', 'add-trailing-comma')()
  File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 269, in main
    ret |= fix_file(filename, args)
  File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 249, in fix_file
    contents_text = _fix_commas(contents_text, args.py35_plus)
  File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 232, in _fix_commas
    _fix_call(call, i, tokens)
  File "/nail/home/ckuehl/.pre-commit/repojgy42wl2/py_env-python2.7/local/lib/python2.7/site-packages/add_trailing_comma.py", line 189, in _fix_call
    paren_stack.pop()
IndexError: pop from empty list
```

Discussion:

Patch:
diff --git a/add_trailing_comma.py b/add_trailing_comma.py
index 9efea83..736fa7d 100644
--- a/add_trailing_comma.py
+++ b/add_trailing_comma.py
@@ -179,13 +179,16 @@ def _fix_call(call, i, tokens):
     #
     #     func_name(arg, arg, arg)
     #              ^ outer paren
+    brace_start, brace_end = '(', ')'
     first_paren = None
     paren_stack = []
     for i in range(i, len(tokens)):
         token = tokens[i]
-        if token.src == '(':
+        if token.src == brace_start:
             paren_stack.append(i)
-        elif token.src == ')':
+        # the ast lies to us about the beginning of parenthesized functions.
+        # See #3. (why we make sure there's something to pop here)
+        elif token.src == brace_end and paren_stack:
             paren_stack.pop()
 
         if (token.line, token.utf8_byte_offset) in call.arg_offsets:
@@ -194,7 +197,7 @@ def _fix_call(call, i, tokens):
     else:
         raise AssertionError('Past end?')
 
-    _fix_inner('(', ')', first_paren, tokens)
+    _fix_inner(brace_start, brace_end, first_paren, tokens)
 
 
 def _fix_literal(literal, i, tokens):


Test patch:
diff --git a/tests/add_trailing_comma_test.py b/tests/add_trailing_comma_test.py
index ddc0bc3..5d1c798 100644
--- a/tests/add_trailing_comma_test.py
+++ b/tests/add_trailing_comma_test.py
@@ -42,6 +42,10 @@ xfailif_lt_py35 = pytest.mark.xfail(sys.version_info < (3, 5), reason='py35+')
         'x((\n'
         '    1,\n'
         '))',
+        # regression test for #3
+        '(\n'
+        '    a\n'
+        ').f(b)',
     ),
 )
 def test_fix_calls_noops(src):