diff options
author | Ceridwen <ceridwenv@gmail.com> | 2015-11-02 00:10:54 -0500 |
---|---|---|
committer | Ceridwen <ceridwenv@gmail.com> | 2015-11-02 00:10:54 -0500 |
commit | 1ba0f2d96fbc45ff0b6014b12db98716183e8277 (patch) | |
tree | 54b7c4d3ecad6fcda1211ea3a8e5f11f6b407287 /astroid/objects.py | |
parent | 83f6c45c343cae87f415268959b1056030a5e74c (diff) | |
download | astroid-1ba0f2d96fbc45ff0b6014b12db98716183e8277.tar.gz |
This bookmark adds structured exceptions to astroid.
Major changes:
* AstroidError has an __init__ that accepts arbitrary keyword-only
arguments for adding information to exceptions, and a __str__ that
lazily uses exception attributes to generate a message. The first
positional argument to an exception is assigned to .message. The new
API should be fully backwards compatible in general.
* Some exceptions are combined or renamed; the old names are still
available.
* The OperationErrors used by pylint are now BadOperationMessages and
located in util.py.
* The AstroidBuildingException in _data_build stores the SyntaxError
in its .error attribute rather than args[0].
* Many places where exceptions are raised have new, hopefully more
useful error messages.
The only major issue remaining is how to propagate information into decorators.
Diffstat (limited to 'astroid/objects.py')
-rw-r--r-- | astroid/objects.py | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/astroid/objects.py b/astroid/objects.py index 3ab0a65..c880a4d 100644 --- a/astroid/objects.py +++ b/astroid/objects.py @@ -86,8 +86,9 @@ class Super(node_classes.NodeNG): def super_mro(self): """Get the MRO which will be used to lookup attributes in this super.""" if not isinstance(self.mro_pointer, scoped_nodes.ClassDef): - raise exceptions.SuperArgumentTypeError( - "The first super argument must be type.") + raise exceptions.SuperError( + "The first argument to super must be a subtype of " + "type, not {mro_pointer}.", super_=self) if isinstance(self.type, scoped_nodes.ClassDef): # `super(type, type)`, most likely in a class method. @@ -96,18 +97,20 @@ class Super(node_classes.NodeNG): else: mro_type = getattr(self.type, '_proxied', None) if not isinstance(mro_type, (bases.Instance, scoped_nodes.ClassDef)): - raise exceptions.SuperArgumentTypeError( - "super(type, obj): obj must be an " - "instance or subtype of type") + raise exceptions.SuperError( + "The second argument to super must be an " + "instance or subtype of type, not {type}.", + super_=self) if not mro_type.newstyle: - raise exceptions.SuperError("Unable to call super on old-style classes.") + raise exceptions.SuperError("Unable to call super on old-style classes.", super_=self) mro = mro_type.mro() if self.mro_pointer not in mro: - raise exceptions.SuperArgumentTypeError( - "super(type, obj): obj must be an " - "instance or subtype of type") + raise exceptions.SuperError( + "The second argument to super must be an " + "instance or subtype of type, not {type}.", + super_=self) index = mro.index(self.mro_pointer) return mro[index + 1:] @@ -138,11 +141,19 @@ class Super(node_classes.NodeNG): try: mro = self.super_mro() - except (exceptions.MroError, exceptions.SuperError) as exc: - # Don't let invalid MROs or invalid super calls - # to leak out as is from this function. - util.reraise(exceptions.NotFoundError(*exc.args)) - + # Don't let invalid MROs or invalid super calls + # leak out as is from this function. + except exceptions.SuperError as exc: + util.reraise(exceptions.AttributeInferenceError( + ('Lookup for {name} on {target!r} because super call {super!r} ' + 'is invalid.'), + target=self, attribute=name, context=context, super_=exc.super_)) + except exceptions.MroError as exc: + util.reraise(exceptions.AttributeInferenceError( + ('Lookup for {name} on {target!r} failed because {cls!r} has an ' + 'invalid MRO.'), + target=self, attribute=name, context=context, mros=exc.mros, + cls=exc.cls)) found = False for cls in mro: if name not in cls.locals: @@ -166,7 +177,9 @@ class Super(node_classes.NodeNG): yield bases.BoundMethod(inferred, cls) if not found: - raise exceptions.NotFoundError(name) + raise exceptions.AttributeInferenceError(target=self, + attribute=name, + context=context) def getattr(self, name, context=None): return list(self.igetattr(name, context=context)) |