mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Added isinstance type checks in the linter.
This commit is contained in:
@@ -19,6 +19,7 @@ CODES = {
|
||||
'type-error-star': (10, TypeError, None),
|
||||
'type-error-operation': (11, TypeError, None),
|
||||
'type-error-not-iterable': (12, TypeError, None),
|
||||
'type-error-isinstance': (13, TypeError, None),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -208,8 +208,8 @@ class CompiledObject(Base):
|
||||
# Get rid of side effects, we won't call custom `__getitem__`s.
|
||||
return
|
||||
|
||||
for obj in self.obj:
|
||||
yield set([CompiledObject(obj)])
|
||||
for part in self.obj:
|
||||
yield set([CompiledObject(part)])
|
||||
return actual
|
||||
|
||||
@property
|
||||
|
||||
@@ -12,8 +12,13 @@ from jedi.evaluate.helpers import FakeName
|
||||
from jedi.cache import underscore_memoization
|
||||
|
||||
|
||||
def try_iter_content(types):
|
||||
def try_iter_content(types, depth=0):
|
||||
"""Helper method for static analysis."""
|
||||
if depth > 10:
|
||||
# It's possible that a loop has references on itself (especially with
|
||||
# CompiledObject). Therefore don't loop infinitely.
|
||||
return
|
||||
|
||||
for typ in types:
|
||||
try:
|
||||
f = typ.py__iter__
|
||||
@@ -21,7 +26,7 @@ def try_iter_content(types):
|
||||
pass
|
||||
else:
|
||||
for iter_types in f():
|
||||
try_iter_content(iter_types)
|
||||
try_iter_content(iter_types, depth + 1)
|
||||
|
||||
|
||||
class Arguments(tree.Base):
|
||||
|
||||
@@ -19,6 +19,7 @@ from jedi.parser import tree
|
||||
from jedi import debug
|
||||
from jedi.evaluate import precedence
|
||||
from jedi.evaluate import param
|
||||
from jedi.evaluate import analysis
|
||||
|
||||
|
||||
class NotInStdLib(LookupError):
|
||||
@@ -40,9 +41,11 @@ def execute(evaluator, obj, arguments):
|
||||
|
||||
# for now we just support builtin functions.
|
||||
try:
|
||||
return _implemented[module_name][obj_name](evaluator, obj, arguments)
|
||||
func = _implemented[module_name][obj_name]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
return func(evaluator, obj, arguments)
|
||||
raise NotInStdLib()
|
||||
|
||||
|
||||
@@ -186,12 +189,15 @@ def builtins_isinstance(evaluator, objects, types, arguments):
|
||||
for cls_or_tup in types:
|
||||
if cls_or_tup.is_class():
|
||||
bool_results.add(cls_or_tup in mro)
|
||||
else:
|
||||
# TODO Actually we should check for non iterables here (the
|
||||
# type should be object or tuple of object)
|
||||
elif str(cls_or_tup.name) == 'tuple' \
|
||||
and cls_or_tup.get_parent_scope() == compiled.builtin:
|
||||
# Check for tuples.
|
||||
classes = iterable.py__iter__types(evaluator, set([cls_or_tup]))
|
||||
classes = unite(cls_or_tup.py__iter__())
|
||||
bool_results.add(any(cls in mro for cls in classes))
|
||||
else:
|
||||
_, nodes = list(arguments.unpack())[1]
|
||||
for node in nodes:
|
||||
analysis.add(evaluator, 'type-error-isinstance', node)
|
||||
|
||||
return set(compiled.keyword_from_value(x) for x in bool_results)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user