mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
Start creating py__getitem__.
This commit is contained in:
@@ -147,7 +147,7 @@ class Evaluator(object):
|
|||||||
types = self.eval_element(rhs)
|
types = self.eval_element(rhs)
|
||||||
|
|
||||||
if seek_name:
|
if seek_name:
|
||||||
types = finder.check_tuple_assignments(types, seek_name)
|
types = finder.check_tuple_assignments(self, types, seek_name)
|
||||||
|
|
||||||
first_operation = stmt.first_operation()
|
first_operation = stmt.first_operation()
|
||||||
if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement): # TODO don't check for this.
|
if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement): # TODO don't check for this.
|
||||||
@@ -352,21 +352,18 @@ class Evaluator(object):
|
|||||||
trailer_op, node = trailer.children[:2]
|
trailer_op, node = trailer.children[:2]
|
||||||
if node == ')': # `arglist` is optional.
|
if node == ')': # `arglist` is optional.
|
||||||
node = ()
|
node = ()
|
||||||
|
|
||||||
new_types = set()
|
new_types = set()
|
||||||
for typ in types:
|
if trailer_op == '[':
|
||||||
debug.dbg('eval_trailer: %s in scope %s', trailer, typ)
|
for trailer_typ in self.eval_element(node):
|
||||||
if trailer_op == '.':
|
new_types |= iterable.py__getitem__(self, types, trailer_typ, trailer_op)
|
||||||
new_types |= self.find_types(typ, node)
|
else:
|
||||||
elif trailer_op == '(':
|
for typ in types:
|
||||||
new_types |= self.execute(typ, node, trailer)
|
debug.dbg('eval_trailer: %s in scope %s', trailer, typ)
|
||||||
elif trailer_op == '[':
|
if trailer_op == '.':
|
||||||
try:
|
new_types |= self.find_types(typ, node)
|
||||||
get = typ.get_index_types
|
elif trailer_op == '(':
|
||||||
except AttributeError:
|
new_types |= self.execute(typ, node, trailer)
|
||||||
debug.warning("TypeError: '%s' object is not subscriptable"
|
|
||||||
% typ)
|
|
||||||
else:
|
|
||||||
new_types |= get(self, node)
|
|
||||||
return new_types
|
return new_types
|
||||||
|
|
||||||
def execute_evaluated(self, obj, *args):
|
def execute_evaluated(self, obj, *args):
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ CODES = {
|
|||||||
'type-error-operation': (11, TypeError, None),
|
'type-error-operation': (11, TypeError, None),
|
||||||
'type-error-not-iterable': (12, TypeError, None),
|
'type-error-not-iterable': (12, TypeError, None),
|
||||||
'type-error-isinstance': (13, TypeError, None),
|
'type-error-isinstance': (13, TypeError, None),
|
||||||
|
'type-error-not-subscriptable': (13, TypeError, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ def _name_to_types(evaluator, name, scope):
|
|||||||
if typ.isinstance(tree.ForStmt, tree.CompFor):
|
if typ.isinstance(tree.ForStmt, tree.CompFor):
|
||||||
container_types = evaluator.eval_element(typ.children[3])
|
container_types = evaluator.eval_element(typ.children[3])
|
||||||
for_types = iterable.py__iter__types(evaluator, container_types, typ.children[3])
|
for_types = iterable.py__iter__types(evaluator, container_types, typ.children[3])
|
||||||
types = check_tuple_assignments(for_types, name)
|
types = check_tuple_assignments(evaluator, for_types, name)
|
||||||
elif isinstance(typ, tree.Param):
|
elif isinstance(typ, tree.Param):
|
||||||
types = _eval_param(evaluator, typ, scope)
|
types = _eval_param(evaluator, typ, scope)
|
||||||
elif typ.isinstance(tree.ExprStmt):
|
elif typ.isinstance(tree.ExprStmt):
|
||||||
@@ -542,26 +542,20 @@ def global_names_dict_generator(evaluator, scope, position):
|
|||||||
yield names_dict, None
|
yield names_dict, None
|
||||||
|
|
||||||
|
|
||||||
def check_tuple_assignments(types, name):
|
def check_tuple_assignments(evaluator, types, name):
|
||||||
"""
|
"""
|
||||||
Checks if tuples are assigned.
|
Checks if tuples are assigned.
|
||||||
"""
|
"""
|
||||||
for index in name.assignment_indexes():
|
for index, node in name.assignment_indexes():
|
||||||
new_types = set()
|
iterated = iterable.py__iter__(evaluator, types, node)
|
||||||
for r in types:
|
all_types = set()
|
||||||
|
for _ in range(index + 1):
|
||||||
try:
|
try:
|
||||||
func = r.get_exact_index_types
|
types = next(iterated)
|
||||||
except AttributeError:
|
all_types |= types
|
||||||
debug.warning("Invalid tuple lookup #%s of result %s in %s",
|
except StopIteration:
|
||||||
index, types, name)
|
types = all_types
|
||||||
else:
|
break
|
||||||
if isinstance(r, iterable.Array) and r.type == 'dict':
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
new_types |= func(index)
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
types = new_types
|
|
||||||
return types
|
return types
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,13 +23,12 @@ It is important to note that:
|
|||||||
from jedi.common import unite, ignored, safe_property
|
from jedi.common import unite, ignored, safe_property
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi._compatibility import use_metaclass, is_py3, unicode
|
from jedi._compatibility import use_metaclass, unicode
|
||||||
from jedi.parser import tree
|
from jedi.parser import tree
|
||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
from jedi.evaluate import helpers
|
from jedi.evaluate import helpers
|
||||||
from jedi.evaluate.cache import CachedMetaClass, memoize_default
|
from jedi.evaluate.cache import CachedMetaClass, memoize_default
|
||||||
from jedi.evaluate import analysis
|
from jedi.evaluate import analysis
|
||||||
from jedi.evaluate.precedence import literals_to_types
|
|
||||||
|
|
||||||
|
|
||||||
class IterableWrapper(tree.Base):
|
class IterableWrapper(tree.Base):
|
||||||
@@ -269,8 +268,8 @@ class Array(IterableWrapper, ArrayMixin):
|
|||||||
result |= check_array_additions(self._evaluator, self)
|
result |= check_array_additions(self._evaluator, self)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_exact_index_types(self, mixed_index):
|
def py__getitem__(self, index):
|
||||||
""" Here the index is an int/str. Raises IndexError/KeyError """
|
"""Here the index is an int/str. Raises IndexError/KeyError."""
|
||||||
if self.type == 'dict':
|
if self.type == 'dict':
|
||||||
for key, values in self._items():
|
for key, values in self._items():
|
||||||
# Because we only want the key to be a string.
|
# Because we only want the key to be a string.
|
||||||
@@ -278,13 +277,13 @@ class Array(IterableWrapper, ArrayMixin):
|
|||||||
|
|
||||||
for k in keys:
|
for k in keys:
|
||||||
if isinstance(k, compiled.CompiledObject) \
|
if isinstance(k, compiled.CompiledObject) \
|
||||||
and mixed_index == k.obj:
|
and index == k.obj:
|
||||||
for value in values:
|
for value in values:
|
||||||
return self._evaluator.eval_element(value)
|
return self._evaluator.eval_element(value)
|
||||||
raise KeyError('No key found in dictionary %s.' % self)
|
raise KeyError('No key found in dictionary %s.' % self)
|
||||||
|
|
||||||
# Can raise an IndexError
|
# Can raise an IndexError
|
||||||
return self._evaluator.eval_element(self._items()[mixed_index])
|
return self._evaluator.eval_element(self._items()[index])
|
||||||
|
|
||||||
def iter_content(self):
|
def iter_content(self):
|
||||||
return self.values()
|
return self.values()
|
||||||
@@ -466,19 +465,20 @@ def unpack_tuple_to_dict(evaluator, types, exprlist):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
def py__iter__(evaluator, types, node):
|
def py__iter__(evaluator, types, node=None):
|
||||||
debug.dbg('py__iter__')
|
debug.dbg('py__iter__')
|
||||||
for typ in types:
|
for typ in types:
|
||||||
try:
|
try:
|
||||||
iter_method = typ.py__iter__
|
iter_method = typ.py__iter__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
analysis.add(evaluator, 'type-error-not-iterable', node)
|
if node is not None:
|
||||||
|
analysis.add(evaluator, 'type-error-not-iterable', node)
|
||||||
else:
|
else:
|
||||||
for result in iter_method():
|
for result in iter_method():
|
||||||
yield result
|
yield result
|
||||||
|
|
||||||
|
|
||||||
def py__iter__types(evaluator, types, node):
|
def py__iter__types(evaluator, types, node=None):
|
||||||
"""
|
"""
|
||||||
Calls `py__iter__`, but ignores the ordering in the end and just returns
|
Calls `py__iter__`, but ignores the ordering in the end and just returns
|
||||||
all types that it contains.
|
all types that it contains.
|
||||||
@@ -486,6 +486,33 @@ def py__iter__types(evaluator, types, node):
|
|||||||
return unite(py__iter__(evaluator, types, node))
|
return unite(py__iter__(evaluator, types, node))
|
||||||
|
|
||||||
|
|
||||||
|
def py__getitem__(evaluator, types, index, node):
|
||||||
|
result = set()
|
||||||
|
|
||||||
|
# Index handling.
|
||||||
|
if isinstance(index, compiled.CompiledObject):
|
||||||
|
pure_index = index.obj
|
||||||
|
elif not type(index) in (float, int, str, unicode):
|
||||||
|
pure_index = index
|
||||||
|
else:
|
||||||
|
# If the index is not clearly defined, we have to get all the
|
||||||
|
# possiblities.
|
||||||
|
return py__iter__types(evaluator, types)
|
||||||
|
|
||||||
|
for typ in types:
|
||||||
|
# The actual getitem call.
|
||||||
|
try:
|
||||||
|
getitem = typ.py__getitem__
|
||||||
|
except AttributeError:
|
||||||
|
analysis.add(evaluator, 'type-error-not-subscriptable', node)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
result |= getitem(pure_index)
|
||||||
|
except IndexError:
|
||||||
|
return py__iter__types(evaluator, set([typ]))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def check_array_additions(evaluator, array):
|
def check_array_additions(evaluator, array):
|
||||||
""" Just a mapper function for the internal _check_array_additions """
|
""" Just a mapper function for the internal _check_array_additions """
|
||||||
if array.type not in ('list', 'set'):
|
if array.type not in ('list', 'set'):
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ py__bool__() Returns True/False/None; None means that
|
|||||||
there's no certainty.
|
there's no certainty.
|
||||||
py__bases__(evaluator) Returns a list of base classes.
|
py__bases__(evaluator) Returns a list of base classes.
|
||||||
py__mro__(evaluator) Returns a list of classes (the mro).
|
py__mro__(evaluator) Returns a list of classes (the mro).
|
||||||
|
py__iter__() Returns a generator of a set of types.
|
||||||
|
py__getitem__(index: int/str) Returns a a set of types of the index.
|
||||||
|
Can raise an IndexError/KeyError.
|
||||||
py__getattribute__(evaluator, name) Returns a list of attribute values. The
|
py__getattribute__(evaluator, name) Returns a list of attribute values. The
|
||||||
name can be str or Name.
|
name can be str or Name.
|
||||||
====================================== ========================================
|
====================================== ========================================
|
||||||
|
|||||||
@@ -319,14 +319,14 @@ class Name(Leaf):
|
|||||||
|
|
||||||
def assignment_indexes(self):
|
def assignment_indexes(self):
|
||||||
"""
|
"""
|
||||||
Returns an array of ints of the indexes that are used in tuple
|
Returns an array of tuple(int, node) of the indexes that are used in
|
||||||
assignments.
|
tuple assignments.
|
||||||
|
|
||||||
For example if the name is ``y`` in the following code::
|
For example if the name is ``y`` in the following code::
|
||||||
|
|
||||||
x, (y, z) = 2, ''
|
x, (y, z) = 2, ''
|
||||||
|
|
||||||
would result in ``[1, 0]``.
|
would result in ``[(1, xyz_node), (0, yz_node)]``.
|
||||||
"""
|
"""
|
||||||
indexes = []
|
indexes = []
|
||||||
node = self.parent
|
node = self.parent
|
||||||
@@ -335,7 +335,7 @@ class Name(Leaf):
|
|||||||
if is_node(node, 'testlist_comp', 'testlist_star_expr', 'exprlist'):
|
if is_node(node, 'testlist_comp', 'testlist_star_expr', 'exprlist'):
|
||||||
for i, child in enumerate(node.children):
|
for i, child in enumerate(node.children):
|
||||||
if child == compare:
|
if child == compare:
|
||||||
indexes.insert(0, int(i / 2))
|
indexes.insert(0, (int(i / 2), node))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise LookupError("Couldn't find the assignment.")
|
raise LookupError("Couldn't find the assignment.")
|
||||||
|
|||||||
@@ -209,6 +209,15 @@ dic2[r'as' 'd' u'f']
|
|||||||
#? int() str()
|
#? int() str()
|
||||||
dic2['just_something']
|
dic2['just_something']
|
||||||
|
|
||||||
|
# unpacking
|
||||||
|
a, b = dic2
|
||||||
|
#? str()
|
||||||
|
a
|
||||||
|
a, b = {1: 'x', 2.0: 1j}
|
||||||
|
#? int() float()
|
||||||
|
a
|
||||||
|
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
""" github #83 """
|
""" github #83 """
|
||||||
r = {}
|
r = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user