summaryrefslogtreecommitdiff
path: root/astroid/objects.py
diff options
context:
space:
mode:
authorCeridwen <ceridwenv@gmail.com>2015-11-02 00:10:54 -0500
committerCeridwen <ceridwenv@gmail.com>2015-11-02 00:10:54 -0500
commit1ba0f2d96fbc45ff0b6014b12db98716183e8277 (patch)
tree54b7c4d3ecad6fcda1211ea3a8e5f11f6b407287 /astroid/objects.py
parent83f6c45c343cae87f415268959b1056030a5e74c (diff)
downloadastroid-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.py43
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))