diff options
| author | Claudiu Popa <pcmanticore@gmail.com> | 2016-12-03 14:45:56 +0200 |
|---|---|---|
| committer | Claudiu Popa <pcmanticore@gmail.com> | 2016-12-30 13:25:20 +0200 |
| commit | c96049a10b0ff58ed0688eb2d83cc546fd6a67d0 (patch) | |
| tree | b24b63da970dcf57f439446633e97b312b3ed9d4 /astroid | |
| parent | e9e5c7fc61748b8b7cc73c948556fc9a830c162c (diff) | |
| download | astroid-git-c96049a10b0ff58ed0688eb2d83cc546fd6a67d0.tar.gz | |
Let the type error propagate as an AstroidTypeError.
Diffstat (limited to 'astroid')
| -rw-r--r-- | astroid/exceptions.py | 8 | ||||
| -rw-r--r-- | astroid/inference.py | 3 | ||||
| -rw-r--r-- | astroid/protocols.py | 8 | ||||
| -rw-r--r-- | astroid/tree/node_classes.py | 62 |
4 files changed, 53 insertions, 28 deletions
diff --git a/astroid/exceptions.py b/astroid/exceptions.py index 9dc80710..3b34ae54 100644 --- a/astroid/exceptions.py +++ b/astroid/exceptions.py @@ -206,6 +206,14 @@ class _NonDeducibleTypeHierarchy(Exception): """Raised when is_subtype / is_supertype can't deduce the relation between two types.""" +class AstroidIndexError(AstroidError): + """Raised when an Indexable / Mapping does not have an index / key.""" + + +class AstroidTypeError(AstroidError): + """Raised when a TypeError would be expected in Python code.""" + + # Backwards-compatibility aliases OperationError = util.BadOperationMessage UnaryOperationError = util.BadUnaryOperationMessage diff --git a/astroid/inference.py b/astroid/inference.py index f87adc9d..aeb06baf 100644 --- a/astroid/inference.py +++ b/astroid/inference.py @@ -254,7 +254,8 @@ def infer_subscript(self, context=None): try: assigned = value.getitem(index_value, context) - except (IndexError, TypeError) as exc: + except (exceptions.AstroidTypeError, + exceptions.AstroidIndexError) as exc: util.reraise(exceptions.InferenceError(node=self, error=exc, context=context)) diff --git a/astroid/protocols.py b/astroid/protocols.py index e72ea69b..cb071a02 100644 --- a/astroid/protocols.py +++ b/astroid/protocols.py @@ -247,9 +247,9 @@ def _resolve_looppart(parts, assign_path, context, nodes): index_node = nodes.Const(index) try: assigned = stmt.getitem(index_node, context) - except (AttributeError, IndexError): - continue - except TypeError: # stmt is unsubscriptable Const + except (AttributeError, + exceptions.AstroidTypeError, + exceptions.AstroidIndexError): continue if not assign_path: # we achieved to resolved the assignment path, @@ -404,7 +404,7 @@ def _resolve_asspart(parts, assign_path, context, nodes): assigned = part.getitem(index_node, context) # XXX raise a specific exception to avoid potential hiding of # unexpected exception ? - except (TypeError, IndexError): + except (exceptions.AstroidTypeError, exceptions.AstroidIndexError): return if not assign_path: # we achieved to resolved the assignment path, don't infer the diff --git a/astroid/tree/node_classes.py b/astroid/tree/node_classes.py index a9460337..05f11a82 100644 --- a/astroid/tree/node_classes.py +++ b/astroid/tree/node_classes.py @@ -76,16 +76,27 @@ def _infer_slice(node, context=None): def _container_getitem(instance, elts, index, context=None): """Get a slice or an item, using the given *index*, for the given sequence.""" - if isinstance(index, Slice): - index_slice = _infer_slice(index, context=context) - new_cls = instance.__class__() - new_cls.elts = elts[index_slice] - new_cls.parent = instance.parent - return new_cls - elif isinstance(index, Const): - return elts[index.value] - - raise TypeError('Could not use %s as subscript index' % index) + try: + if isinstance(index, Slice): + index_slice = _infer_slice(index, context=context) + new_cls = instance.__class__() + new_cls.elts = elts[index_slice] + new_cls.parent = instance.parent + return new_cls + elif isinstance(index, Const): + return elts[index.value] + except IndexError: + util.reraise(exceptions.AstroidIndexError( + message='Index {index!s} out of range', + node=instance, index=index, context=context)) + except TypeError as exc: + util.reraise(exceptions.AstroidIndexError( + message='Type error {error!r}', error=exc, + node=instance, index=index, context=context)) + + raise exceptions.AstroidTypeError( + 'Could not use %s as subscript index' % index + ) @util.register_implementation(treeabc.Statement) class Statement(base.NodeNG): @@ -553,19 +564,26 @@ class Const(base.NodeNG, objects.BaseInstance): elif isinstance(index, Slice): index_value = _infer_slice(index, context=context) else: - raise TypeError( + raise exceptions.AstroidTypeError( 'Could not use type {} as subscript index'.format(type(index)) ) - if isinstance(self.value, six.string_types): - return Const(self.value[index_value]) - if isinstance(self.value, bytes) and six.PY3: - # Bytes aren't instances of six.string_types - # on Python 3. Also, indexing them should return - # integers. - return Const(self.value[index_value]) + try: + if isinstance(self.value, six.string_types): + return Const(self.value[index_value]) + if isinstance(self.value, bytes) and six.PY3: + # Bytes aren't instances of six.string_types + # on Python 3. Also, indexing them should return + # integers. + return Const(self.value[index_value]) + except TypeError: + # The object does not support this operation, let the + # following error be raised instead. + pass - raise TypeError('%r (value=%s)' % (self, self.value)) + raise exceptions.AstroidTypeError( + '%r (value=%s)' % (self, self.value) + ) def has_dynamic_getattr(self): return False @@ -699,7 +717,7 @@ class Dict(base.NodeNG, objects.DictInstance): if isinstance(key, DictUnpack): try: return value.getitem(lookup_key, context) - except IndexError: + except (exceptions.AstroidTypeError, exceptions.AstroidIndexError): continue for inferredkey in key.infer(context): if inferredkey is util.Uninferable: @@ -707,9 +725,7 @@ class Dict(base.NodeNG, objects.DictInstance): if isinstance(inferredkey, Const) and isinstance(lookup_key, Const): if inferredkey.value == lookup_key.value: return value - # This should raise KeyError, but all call sites only catch - # IndexError. Let's leave it like that for now. - raise IndexError(lookup_key) + raise exceptions.AstroidIndexError(index) def bool_value(self): return bool(self.keys) |
