diff --git a/bugbear.py b/bugbear.py index 873fc10..974e5cb 100644 --- a/bugbear.py +++ b/bugbear.py @@ -124,8 +124,10 @@ def _to_name_str(node): # "pkg.mod.error", handling any depth of attribute accesses. if isinstance(node, ast.Name): return node.id - assert isinstance(node, ast.Attribute) - return _to_name_str(node.value) + "." + node.attr + try: + return _to_name_str(node.value) + "." + node.attr + except AttributeError: + return _to_name_str(node.value) def _typesafe_issubclass(cls, class_or_tuple): diff --git a/tests/test_bugbear.py b/tests/test_bugbear.py index ccce9da..c755fb9 100644 --- a/tests/test_bugbear.py +++ b/tests/test_bugbear.py @@ -340,6 +340,20 @@ def test_does_not_crash_on_site_code(self): if f.endswith(".py"): BugBearChecker(filename=str(Path(dirname) / f)) + def test_does_not_crash_on_tuple_expansion_in_except_statement(self): + # akin to test_does_not_crash_on_any_valid_code + # but targets a rare case that's not covered by hypothesmith.from_grammar + # see https://github.com/PyCQA/flake8-bugbear/issues/153 + syntax_tree = ast.parse( + "grey_list = (ValueError,)\n" + "black_list = (TypeError,)\n" + "try:\n" + " int('1e3')\n" + "except (*grey_list, *black_list):\n" + " print('error caught')" + ) + BugBearVisitor(filename="", lines=[]).visit(syntax_tree) + if __name__ == "__main__": unittest.main()