diff --git a/ChangeLog b/ChangeLog index bf964afe83..a6646b3f9a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,8 @@ What's New in astroid 2.2.0? Release Date: TBA +* Add a registry for builtin exception models. Close PyCQA/pylint#1432 + * Add brain tips for `http.client`. Close PyCQA/pylint#2687 * Prevent crashing when processing ``enums`` with mixed single and double quotes. diff --git a/astroid/interpreter/objectmodel.py b/astroid/interpreter/objectmodel.py index 65e9c64193..746f6ba62f 100644 --- a/astroid/interpreter/objectmodel.py +++ b/astroid/interpreter/objectmodel.py @@ -601,6 +601,9 @@ def py__dict__(self): return _dunder_dict(self._instance, self._instance.instance_attrs) +# Exception instances + + class ExceptionInstanceModel(InstanceModel): @property def pyargs(self): @@ -616,6 +619,15 @@ def py__traceback__(self): return traceback_type.instantiate_class() +class SyntaxErrorInstanceModel(ExceptionInstanceModel): + @property + def pytext(self): + return node_classes.Const("") + + +BUILTIN_EXCEPTIONS = {"builtins.SyntaxError": SyntaxErrorInstanceModel} + + class DictModel(ObjectModel): @property def py__class__(self): diff --git a/astroid/objects.py b/astroid/objects.py index 367f650e8d..1a071b2cad 100644 --- a/astroid/objects.py +++ b/astroid/objects.py @@ -210,10 +210,13 @@ class ExceptionInstance(bases.Instance): the case of .args. """ - # pylint: disable=unnecessary-lambda - special_attributes = util.lazy_descriptor( - lambda: objectmodel.ExceptionInstanceModel() - ) + @decorators.cachedproperty + def special_attributes(self): + qname = self.qname() + instance = objectmodel.BUILTIN_EXCEPTIONS.get( + qname, objectmodel.ExceptionInstanceModel + ) + return instance() class DictInstance(bases.Instance): diff --git a/astroid/tests/unittest_object_model.py b/astroid/tests/unittest_object_model.py index 496cd47988..0923389be1 100644 --- a/astroid/tests/unittest_object_model.py +++ b/astroid/tests/unittest_object_model.py @@ -585,6 +585,18 @@ def test_model_py3(self): with self.assertRaises(exceptions.InferenceError): next(ast_nodes[2].infer()) + def test_syntax_error(self): + ast_node = builder.extract_node( + """ + try: + x[42] + except SyntaxError as err: + err.text #@ + """ + ) + inferred = next(ast_node.infer()) + assert isinstance(inferred, astroid.Const) + class DictObjectModelTest(unittest.TestCase): def test__class__(self):