Repository: python/mypy

Issue:
RuntimeError: 'ExceptHandler(...)' has non-Name name.
```python
try:
    raise IOError(12, 'asdf')
except IOError as (errno, msg):
    print errno, msg
```

```sh-session
$ python2 --version
Python 2.7.11+
$ python2 asdf.py
12 asdf
```

```sh-session
$ mypy --version
mypy 0.521
$ mypy --show-traceback -2 asdf.py
asdf.py: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.521
Traceback (most recent call last):
  File "/home/d/.local/bin/mypy", line 11, in <module>
    sys.exit(console_entry())
  File "/home/d/.local/lib/python3.5/site-packages/mypy/__main__.py", line 7, in console_entry
    main(None)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/main.py", line 50, in main
    res = type_check_only(sources, bin_dir, options)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/main.py", line 97, in type_check_only
    options=options)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/build.py", line 196, in build
    graph = dispatch(sources, manager)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/build.py", line 1793, in dispatch
    graph = load_graph(sources, manager)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/build.py", line 1876, in load_graph
    root_source=True)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/build.py", line 1440, in __init__
    self.parse_file()
  File "/home/d/.local/lib/python3.5/site-packages/mypy/build.py", line 1632, in parse_file
    self.ignore_all or self.options.ignore_errors)
  File "/usr/lib/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/build.py", line 1528, in wrap_context
    yield
  File "/home/d/.local/lib/python3.5/site-packages/mypy/build.py", line 1632, in parse_file
    self.ignore_all or self.options.ignore_errors)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/build.py", line 571, in parse_file
    tree = parse(source, path, self.errors, options=self.options)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/parse.py", line 31, in parse
    options=options)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/fastparse2.py", line 95, in parse
    ).visit(ast)
  File "/home/d/.local/lib/python3.5/site-packages/typed_ast/ast27.py", line 255, in visit
    return visitor(node)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/fastparse2.py", line 268, in visit_Module
    body = self.fix_function_overloads(self.translate_stmt_list(mod.body))
  File "/home/d/.local/lib/python3.5/site-packages/mypy/fastparse2.py", line 166, in translate_stmt_list
    stmt = self.visit(e)
  File "/home/d/.local/lib/python3.5/site-packages/typed_ast/ast27.py", line 255, in visit
    return visitor(node)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/fastparse2.py", line 112, in wrapper
    node = f(self, ast)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/fastparse2.py", line 559, in visit_TryExcept
    return self.try_handler(n.body, n.handlers, n.orelse, [], n.lineno)
  File "/home/d/.local/lib/python3.5/site-packages/mypy/fastparse2.py", line 582, in try_handler
    vs = [produce_name(h) for h in handlers]
  File "/home/d/.local/lib/python3.5/site-packages/mypy/fastparse2.py", line 582, in <listcomp>
    vs = [produce_name(h) for h in handlers]
  File "/home/d/.local/lib/python3.5/site-packages/mypy/fastparse2.py", line 580, in produce_name
    raise RuntimeError("'{}' has non-Name name.".format(ast27.dump(item)))
RuntimeError: 'ExceptHandler(type=Name(id='IOError', ctx=Load()), name=Tuple(elts=[Name(id='errno', ctx=Store()), Name(id='msg', ctx=Store())], ctx=Store()), body=[Print(dest=None, values=[Name(id='errno', ctx=Load()), Name(id='msg', ctx=Load())], nl=True)])' has non-Name name.
asdf.py: note: use --pdb to drop into pdb
```


Discussion:
FWIW this syntax is no longer supported in Python 3 (and I have never before seen in in Python 2 :-).
> FWIW this syntax is no longer supported in Python 3 (and I have never before seen in in Python 2 :-).

I think in any case it is better to give a normal error and not crash.

Resolving patch:
diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py
--- a/mypy/fastparse2.py
+++ b/mypy/fastparse2.py
@@ -586,15 +586,16 @@ def try_handler(self,
                     orelse: List[ast27.stmt],
                     finalbody: List[ast27.stmt],
                     lineno: int) -> TryStmt:
-        def produce_name(item: ast27.ExceptHandler) -> Optional[NameExpr]:
+        vs = []  # type: List[Optional[NameExpr]]
+        for item in handlers:
             if item.name is None:
-                return None
+                vs.append(None)
             elif isinstance(item.name, ast27.Name):
-                return NameExpr(item.name.id)
+                vs.append(NameExpr(item.name.id))
             else:
-                raise RuntimeError("'{}' has non-Name name.".format(ast27.dump(item)))
-
-        vs = [produce_name(h) for h in handlers]
+                self.fail("Sorry, `except <expr>, <anything but a name>` is not supported",
+                          item.lineno, item.col_offset)
+                vs.append(None)
         types = [self.visit(h.type) for h in handlers]
         handlers_ = [self.as_required_block(h.body, h.lineno) for h in handlers]
 


Test patch:
diff --git a/test-data/unit/check-python2.test b/test-data/unit/check-python2.test
--- a/test-data/unit/check-python2.test
+++ b/test-data/unit/check-python2.test
@@ -77,6 +77,21 @@ except BaseException, e:
     e() # E: "BaseException" not callable
 [builtins_py2 fixtures/exception.pyi]
 
+[case testTryExceptUnsupported]
+try:
+    pass
+except BaseException, (e, f):  # E: Sorry, `except <expr>, <anything but a name>` is not supported
+    pass
+try:
+    pass
+except BaseException, [e, f, g]:  # E: Sorry, `except <expr>, <anything but a name>` is not supported
+    pass
+try:
+    pass
+except BaseException, e[0]:  # E: Sorry, `except <expr>, <anything but a name>` is not supported
+    pass
+[builtins_py2 fixtures/exception.pyi]
+
 [case testAlternateNameSuggestions]
 class Foo(object):
     def say_hello(self):