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