diff --git a/astroid/builder.py b/astroid/builder.py index ac71093d65..34bde0a126 100644 --- a/astroid/builder.py +++ b/astroid/builder.py @@ -32,6 +32,8 @@ from astroid import nodes from astroid import util +objects = util.lazy_import("objects") + # The name of the transient function that is used to # wrap expressions to be extracted when calling # extract_node. @@ -224,14 +226,15 @@ def delayed_assattr(self, node): if inferred is util.Uninferable: continue try: - if inferred.__class__ is bases.Instance: + cls = inferred.__class__ + if cls is bases.Instance or cls is objects.ExceptionInstance: inferred = inferred._proxied iattrs = inferred.instance_attrs if not _can_assign_attr(inferred, node.attrname): continue elif isinstance(inferred, bases.Instance): - # Const, Tuple, ... we may be wrong, may be not, but - # anyway we don't want to pollute builtin's namespace + # Const, Tuple or other containers that inherit from + # `Instance` continue elif inferred.is_function: iattrs = inferred.instance_attrs diff --git a/tests/unittest_inference.py b/tests/unittest_inference.py index e8f9980799..f8dc7a64d7 100644 --- a/tests/unittest_inference.py +++ b/tests/unittest_inference.py @@ -42,6 +42,8 @@ from astroid import objects from astroid import test_utils from astroid import util +from astroid.objects import ExceptionInstance + from . import resources @@ -5348,5 +5350,25 @@ def __init__(*args, **kwargs): assert inferred_data.as_string() == "{1: 2}" +def test_infer_exception_instance_attributes(): + code = """ + class UnsupportedFormatCharacter(Exception): + def __init__(self, index): + Exception.__init__(self, index) + self.index = index + + try: + 1/0 + except UnsupportedFormatCharacter as exc: + exc #@ + """ + node = extract_node(code) + inferred = next(node.infer()) + assert isinstance(inferred, ExceptionInstance) + index = inferred.getattr("index") + assert len(index) == 1 + assert isinstance(index[0], nodes.AssignAttr) + + if __name__ == "__main__": unittest.main()