mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 06:44:46 +08:00
assert isinstance checks
This commit is contained in:
@@ -60,14 +60,13 @@ Jedi supports many of the widely used Python features:
|
|||||||
- class decorators (py3k feature, are being ignored too, until I find a use
|
- class decorators (py3k feature, are being ignored too, until I find a use
|
||||||
case, that doesn't work with Jedi)
|
case, that doesn't work with Jedi)
|
||||||
- simple/usual ``sys.path`` modifications
|
- simple/usual ``sys.path`` modifications
|
||||||
- ``isinstance`` checks for if/while
|
- ``isinstance`` checks for if/while/assert
|
||||||
|
|
||||||
However, it does not yet support (and probably will in future versions, because
|
However, it does not yet support (and probably will in future versions, because
|
||||||
they are on my todo list):
|
they are on my todo list):
|
||||||
|
|
||||||
- manipulations of instances outside the instance variables, without using
|
- manipulations of instances outside the instance variables, without using
|
||||||
functions
|
functions
|
||||||
- assert
|
|
||||||
|
|
||||||
It does not support (and most probably will not in future versions):
|
It does not support (and most probably will not in future versions):
|
||||||
|
|
||||||
|
|||||||
@@ -494,18 +494,32 @@ class RelatedName(BaseOutput):
|
|||||||
return hash((self.start_pos, self.module_path))
|
return hash((self.start_pos, self.module_path))
|
||||||
|
|
||||||
|
|
||||||
def check_flow_information(flow, search_name):
|
def check_flow_information(flow, search_name, pos):
|
||||||
""" Try to find out the type of a variable just with the information that
|
""" Try to find out the type of a variable just with the information that
|
||||||
is given by the flows: e.g.
|
is given by the flows: e.g. It is also responsible for assert checks.
|
||||||
>>> if isinstance(k, str):
|
>>> if isinstance(k, str):
|
||||||
>>> k. # <- completion here
|
>>> k. # <- completion here
|
||||||
|
|
||||||
ensures that `k` is a string.
|
ensures that `k` is a string.
|
||||||
"""
|
"""
|
||||||
|
result = []
|
||||||
|
if isinstance(flow, parsing.Scope) and not result:
|
||||||
|
for ass in reversed(flow.asserts):
|
||||||
|
if ass.start_pos > pos:
|
||||||
|
continue
|
||||||
|
result = check_statement_information(ass, search_name)
|
||||||
|
if result:
|
||||||
|
break
|
||||||
|
|
||||||
|
if isinstance(flow, parsing.Flow) and not result:
|
||||||
|
if flow.command in ['if', 'while'] and len(flow.inits) == 1:
|
||||||
|
result = check_statement_information(flow.inits[0], search_name)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def check_statement_information(stmt, search_name):
|
||||||
try:
|
try:
|
||||||
assert flow.command in ['if', 'while']
|
ass = stmt.get_assignment_calls()
|
||||||
assert len(flow.inits) == 1
|
|
||||||
ass = flow.inits[0].get_assignment_calls()
|
|
||||||
assert len(ass.values) == 1 and len(ass.values[0]) == 1
|
assert len(ass.values) == 1 and len(ass.values[0]) == 1
|
||||||
call = ass.values[0][0]
|
call = ass.values[0][0]
|
||||||
assert type(call) == parsing.Call and str(call.name) == 'isinstance'
|
assert type(call) == parsing.Call and str(call.name) == 'isinstance'
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ class Instance(use_metaclass(CachedMetaClass, Executable)):
|
|||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'name', 'get_imports',
|
if name not in ['start_pos', 'end_pos', 'name', 'get_imports',
|
||||||
'docstr']:
|
'docstr', 'asserts']:
|
||||||
raise AttributeError("Instance %s: Don't touch this (%s)!"
|
raise AttributeError("Instance %s: Don't touch this (%s)!"
|
||||||
% (self, name))
|
% (self, name))
|
||||||
return getattr(self.base, name)
|
return getattr(self.base, name)
|
||||||
@@ -386,7 +386,7 @@ class Class(use_metaclass(CachedMetaClass, parsing.Base)):
|
|||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'parent', 'subscopes',
|
if name not in ['start_pos', 'end_pos', 'parent', 'subscopes',
|
||||||
'get_imports', 'get_parent_until', 'docstr']:
|
'get_imports', 'get_parent_until', 'docstr', 'asserts']:
|
||||||
raise AttributeError("Don't touch this (%s)!" % name)
|
raise AttributeError("Don't touch this (%s)!" % name)
|
||||||
return getattr(self.base, name)
|
return getattr(self.base, name)
|
||||||
|
|
||||||
@@ -726,6 +726,11 @@ class Execution(Executable):
|
|||||||
def returns(self):
|
def returns(self):
|
||||||
return self.copy_properties('returns')
|
return self.copy_properties('returns')
|
||||||
|
|
||||||
|
@property
|
||||||
|
@memoize_default()
|
||||||
|
def asserts(self):
|
||||||
|
return self.copy_properties('asserts')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def statements(self):
|
def statements(self):
|
||||||
@@ -1148,10 +1153,13 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False,
|
|||||||
if result:
|
if result:
|
||||||
break
|
break
|
||||||
|
|
||||||
while flow_scope and flow_scope.isinstance(parsing.Flow):
|
while flow_scope:
|
||||||
result = dynamic.check_flow_information(flow_scope, name_str)
|
result = dynamic.check_flow_information(flow_scope, name_str,
|
||||||
|
position)
|
||||||
if result:
|
if result:
|
||||||
break
|
break
|
||||||
|
if flow_scope == nscope:
|
||||||
|
break
|
||||||
flow_scope = flow_scope.parent()
|
flow_scope = flow_scope.parent()
|
||||||
flow_scope = nscope
|
flow_scope = nscope
|
||||||
if result:
|
if result:
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class ExecutionRecursionDecorator(object):
|
|||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def __call__(self, execution, evaluate_generator=False):
|
def __call__(self, execution, evaluate_generator=False):
|
||||||
debug.dbg('Execution recursions: ', execution, self.recursion_level,
|
debug.dbg('Execution recursions: %s' % execution, self.recursion_level,
|
||||||
self.execution_count, len(self.execution_funcs))
|
self.execution_count, len(self.execution_funcs))
|
||||||
if self.check_recursion(execution, evaluate_generator):
|
if self.check_recursion(execution, evaluate_generator):
|
||||||
result = []
|
result = []
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ class Scope(Simple):
|
|||||||
self.imports = []
|
self.imports = []
|
||||||
self.statements = []
|
self.statements = []
|
||||||
self.docstr = docstr
|
self.docstr = docstr
|
||||||
|
self.asserts = []
|
||||||
|
|
||||||
def add_scope(self, sub, decorators):
|
def add_scope(self, sub, decorators):
|
||||||
sub.parent = weakref.ref(self)
|
sub.parent = weakref.ref(self)
|
||||||
@@ -1416,7 +1417,7 @@ class PyFuzzyParser(object):
|
|||||||
string += ".".join(n.names)
|
string += ".".join(n.names)
|
||||||
continue
|
continue
|
||||||
elif token_type == tokenize.NAME:
|
elif token_type == tokenize.NAME:
|
||||||
if tok in ['return', 'yield', 'del', 'raise', 'assert']:
|
if tok in ['return', 'yield', 'del', 'raise']:
|
||||||
if len(tok_list) > 1:
|
if len(tok_list) > 1:
|
||||||
# this happens, when a statement has opening
|
# this happens, when a statement has opening
|
||||||
# brackets, which are not closed again, here I just
|
# brackets, which are not closed again, here I just
|
||||||
@@ -1751,6 +1752,10 @@ class PyFuzzyParser(object):
|
|||||||
decorators.append(stmt)
|
decorators.append(stmt)
|
||||||
elif tok == 'pass':
|
elif tok == 'pass':
|
||||||
continue
|
continue
|
||||||
|
elif tok == 'assert':
|
||||||
|
stmt, tok = self._parse_statement()
|
||||||
|
stmt.parent = weakref.ref(self.scope)
|
||||||
|
self.scope.asserts.append(stmt)
|
||||||
# default
|
# default
|
||||||
elif token_type in [tokenize.NAME, tokenize.STRING,
|
elif token_type in [tokenize.NAME, tokenize.STRING,
|
||||||
tokenize.NUMBER] \
|
tokenize.NUMBER] \
|
||||||
|
|||||||
@@ -17,3 +17,14 @@ if not isinstance(k, (str, int)):
|
|||||||
while not isinstance(k, (str, int)):
|
while not isinstance(k, (str, int)):
|
||||||
#?
|
#?
|
||||||
k
|
k
|
||||||
|
|
||||||
|
assert isinstance(ass, int):
|
||||||
|
#? int()
|
||||||
|
ass
|
||||||
|
|
||||||
|
assert isinstance(ass, str):
|
||||||
|
assert not isinstance(ass, int):
|
||||||
|
|
||||||
|
if 2:
|
||||||
|
#? str()
|
||||||
|
ass
|
||||||
|
|||||||
Reference in New Issue
Block a user