Beispiel #1
0
def _star_star_dict(evaluator, array, expression_list, func):
    dct = {}
    from jedi.evaluate.representation import Instance
    if isinstance(array, Instance) and array.name.get_code() == 'dict':
        # For now ignore this case. In the future add proper iterators and just
        # make one call without crazy isinstance checks.
        return {}

    if isinstance(array, iterable.Array) and array.type == pr.Array.DICT:
        for key_stmt, value_stmt in array.items():
            # first index, is the key if syntactically correct
            call = key_stmt.expression_list()[0]
            if isinstance(call, pr.Name):
                key = call
            elif isinstance(call, pr.Call):
                key = call.name
            else:
                debug.warning('Ignored complicated **kwargs stmt %s' % call)
                continue  # We ignore complicated statements here, for now.

            # If the string is a duplicate, we don't care it's illegal Python
            # anyway.
            dct[str(key)] = key, value_stmt
    else:
        if expression_list:
            m = "TypeError: %s argument after ** must be a mapping, not %s" \
                % (func.name.get_code(), array)
            analysis.add(evaluator, 'type-error-star-star',
                         expression_list[0], message=m)
    return dct
Beispiel #2
0
    def find(self, scopes, attribute_lookup):
        """
        :params bool attribute_lookup: Tell to logic if we're accessing the
            attribute or the contents of e.g. a function.
        """
        # TODO rename scopes to names_dicts

        names = self.filter_name(scopes)
        if self._found_predefined_if_name is not None:
            return self._found_predefined_if_name

        types = self._names_to_types(names, attribute_lookup)

        if (
            not names
            and not types
            and not (isinstance(self.name_str, tree.Name) and isinstance(self.name_str.parent.parent, tree.Param))
        ):
            if not isinstance(self.name_str, (str, unicode)):  # TODO Remove?
                if attribute_lookup:
                    analysis.add_attribute_error(self._evaluator, self.scope, self.name_str)
                else:
                    message = "NameError: name '%s' is not defined." % self.name_str
                    analysis.add(self._evaluator, "name-error", self.name_str, message)

        debug.dbg("finder._names_to_types: %s -> %s", names, types)
        return types
Beispiel #3
0
def _element_calculate(evaluator, left, operator, right):
    from jedi.evaluate import iterable, representation as er
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or _is_string(left):
            return [left]
        elif isinstance(right, iterable.Array) or _is_string(right):
            return [right]
    elif operator == '+':
        if l_is_num and r_is_num or _is_string(left) and _is_string(right):
            return [create(evaluator, left.obj + right.obj)]
        elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
            return [iterable.MergedArray(evaluator, (left, right))]
    elif operator == '-':
        if l_is_num and r_is_num:
            return [create(evaluator, left.obj - right.obj)]
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return [left]

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, er.Instance) and obj.name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(evaluator, 'type-error-operation', operator,
                     message % (left, right))

    return [left, right]
Beispiel #4
0
def unpack_tuple_to_dict(evaluator, types, exprlist):
    """
    Unpacking tuple assignments in for statements and expr_stmts.
    """
    if exprlist.type == 'name':
        return {exprlist.value: types}
    elif exprlist.type == 'atom' and exprlist.children[0] in '([':
        return unpack_tuple_to_dict(evaluator, types, exprlist.children[1])
    elif exprlist.type in ('testlist', 'testlist_comp', 'exprlist',
                           'testlist_star_expr'):
        dct = {}
        parts = iter(exprlist.children[::2])
        n = 0
        for iter_types in py__iter__(evaluator, types, exprlist):
            n += 1
            try:
                part = next(parts)
            except StopIteration:
                analysis.add(evaluator, 'value-error-too-many-values', part,
                             message="ValueError: too many values to unpack (expected %s)" % n)
            else:
                dct.update(unpack_tuple_to_dict(evaluator, iter_types, part))
        has_parts = next(parts, None)
        if types and has_parts is not None:
            analysis.add(evaluator, 'value-error-too-few-values', has_parts,
                         message="ValueError: need more than %s values to unpack" % n)
        return dct
    elif exprlist.type == 'power' or exprlist.type == 'atom_expr':
        # Something like ``arr[x], var = ...``.
        # This is something that is not yet supported, would also be difficult
        # to write into a dict.
        return {}
    raise NotImplementedError
Beispiel #5
0
    def find(self, filters, attribute_lookup):
        """
        :params bool attribute_lookup: Tell to logic if we're accessing the
            attribute or the contents of e.g. a function.
        """
        names = self.filter_name(filters)
        if self._found_predefined_types is not None and names:
            check = flow_analysis.reachability_check(
                self._context, self._context.tree_node, self._name)
            if check is flow_analysis.UNREACHABLE:
                return set()
            return self._found_predefined_types

        types = self._names_to_types(names, attribute_lookup)

        if not names and not types \
                and not (isinstance(self._name, tree.Name) and
                         isinstance(self._name.parent.parent, tree.Param)):
            if isinstance(self._name, tree.Name):
                if attribute_lookup:
                    analysis.add_attribute_error(
                        self._name_context, self._context, self._name)
                else:
                    message = ("NameError: name '%s' is not defined."
                               % self._string_name)
                    analysis.add(self._name_context, 'name-error', self._name, message)

        return types
Beispiel #6
0
def builtins_isinstance(evaluator, objects, types, arguments):
    bool_results = set([])
    for o in objects:
        try:
            mro_func = o.py__class__().py__mro__
        except AttributeError:
            # This is temporary. Everything should have a class attribute in
            # Python?! Maybe we'll leave it here, because some numpy objects or
            # whatever might not.
            return set([compiled.create(True), compiled.create(False)])

        mro = mro_func()

        for cls_or_tup in types:
            if cls_or_tup.is_class():
                bool_results.add(cls_or_tup in mro)
            elif cls_or_tup.name.string_name == 'tuple' \
                    and cls_or_tup.get_root_context() == evaluator.BUILTINS:
                # Check for tuples.
                classes = unite(
                    lazy_context.infer()
                    for lazy_context in cls_or_tup.py__iter__()
                )
                bool_results.add(any(cls in mro for cls in classes))
            else:
                _, lazy_context = list(arguments.unpack())[1]
                if isinstance(lazy_context, LazyTreeContext):
                    node = lazy_context.data
                    message = 'TypeError: isinstance() arg 2 must be a ' \
                              'class, type, or tuple of classes and types, ' \
                              'not %s.' % cls_or_tup
                    analysis.add(lazy_context._context, 'type-error-isinstance', node, message)

    return set(compiled.create(evaluator, x) for x in bool_results)
Beispiel #7
0
def _eval_comparison_part(evaluator, context, left, operator, right):
    l_is_num = is_number(left)
    r_is_num = is_number(right)
    if isinstance(operator, unicode):
        str_operator = operator
    else:
        str_operator = force_unicode(str(operator.value))

    if str_operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Sequence) or is_string(left):
            return ContextSet(left)
        elif isinstance(right, iterable.Sequence) or is_string(right):
            return ContextSet(right)
    elif str_operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return ContextSet(left.execute_operation(right, str_operator))
        elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
            return ContextSet(iterable.MergedArray(evaluator, (left, right)))
    elif str_operator == '-':
        if l_is_num and r_is_num:
            return ContextSet(left.execute_operation(right, str_operator))
    elif str_operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return ContextSet(left)
    elif str_operator in COMPARISON_OPERATORS:
        if is_compiled(left) and is_compiled(right):
            # Possible, because the return is not an option. Just compare.
            try:
                return ContextSet(left.execute_operation(right, str_operator))
            except TypeError:
                # Could be True or False.
                pass
        else:
            if str_operator in ('is', '!=', '==', 'is not'):
                operation = COMPARISON_OPERATORS[str_operator]
                bool_ = operation(left, right)
                return ContextSet(_bool_to_context(evaluator, bool_))

        return ContextSet(_bool_to_context(evaluator, True), _bool_to_context(evaluator, False))
    elif str_operator == 'in':
        return NO_CONTEXTS

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, CompiledInstance) and \
            obj.name.string_name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if str_operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(context, 'type-error-operation', operator,
                     message % (left, right))

    return ContextSet(left, right)
Beispiel #8
0
def _add_error(context, name, message=None):
    # Should be a name, not a string!
    if message is None:
        name_str = str(name.value) if isinstance(name, tree.Name) else name
        message = 'No module named ' + name_str
    if hasattr(name, 'parent'):
        analysis.add(context, 'import-error', name, message)
    else:
        debug.warning('ImportError without origin: ' + message)
Beispiel #9
0
def _add_error(context, name, message=None):
    # Should be a name, not a string!
    if message is None:
        name_str = str(name.value) if isinstance(name, tree.Name) else name
        message = 'No module named ' + name_str
    if hasattr(name, 'parent'):
        analysis.add(context, 'import-error', name, message)
    else:
        debug.warning('ImportError without origin: ' + message)
Beispiel #10
0
    def follow(self, is_goto=False):
        if self._evaluator.recursion_detector.push_stmt(self.import_stmt):
            # check recursion
            return []

        try:
            if self.import_path:
                try:
                    module, rest = self._importer.follow_file_system()
                except ModuleNotFound as e:
                    analysis.add(self._evaluator, 'import-error', e.name_part)
                    return []

                if module is None:
                    return []

                if self.import_stmt.is_nested() and not self.nested_resolve:
                    scopes = [NestedImportModule(module, self.import_stmt)]
                else:
                    scopes = [module]

                star_imports = remove_star_imports(self._evaluator, module)
                if star_imports:
                    scopes = [StarImportModule(scopes[0], star_imports)]

                # goto only accepts `Name`
                if is_goto and not rest:
                    scopes = [s.name for s in scopes]

                # follow the rest of the import (not FS -> classes, functions)
                if len(rest) > 1 or rest and self.is_like_search:
                    scopes = []
                    if ('os', 'path') == self.import_path[:2] \
                            and not self._is_relative_import():
                        # This is a huge exception, we follow a nested import
                        # ``os.path``, because it's a very important one in Python
                        # that is being achieved by messing with ``sys.modules`` in
                        # ``os``.
                        scopes = self._evaluator.follow_path(iter(rest), [module], module)
                elif rest:
                    if is_goto:
                        scopes = list(chain.from_iterable(
                            self._evaluator.find_types(s, rest[0], is_goto=True)
                            for s in scopes))
                    else:
                        scopes = list(chain.from_iterable(
                            self._evaluator.follow_path(iter(rest), [s], s)
                            for s in scopes))
            else:
                scopes = [ImportWrapper.GlobalNamespace]
            debug.dbg('after import: %s', scopes)
            if not scopes:
                analysis.add(self._evaluator, 'import-error',
                             self._importer.import_path[-1])
        finally:
            self._evaluator.recursion_detector.pop_stmt()
        return scopes
 def py__getitem__(self, index_context_set, contextualized_node):
     from jedi.evaluate import analysis
     # TODO this context is probably not right.
     analysis.add(
         contextualized_node.context,
         'type-error-not-subscriptable',
         contextualized_node.node,
         message="TypeError: '%s' object is not subscriptable" % self
     )
     return NO_CONTEXTS
Beispiel #12
0
def py__getitem__(evaluator, types, trailer):
    from jedi.evaluate.representation import Class
    result = set()

    trailer_op, node, trailer_cl = trailer.children
    assert trailer_op == "["
    assert trailer_cl == "]"

    # special case: PEP0484 typing module, see
    # https://github.com/davidhalter/jedi/issues/663
    for typ in list(types):
        if isinstance(typ, Class):
            typing_module_types = \
                pep0484.get_types_for_typing_module(evaluator, typ, node)
            if typing_module_types is not None:
                types.remove(typ)
                result |= typing_module_types

    if not types:
        # all consumed by special cases
        return result

    for index in create_index_types(evaluator, node):
        if isinstance(index, (compiled.CompiledObject, Slice)):
            index = index.obj

        if type(index) not in (float, int, str, unicode, slice):
            # If the index is not clearly defined, we have to get all the
            # possiblities.
            for typ in list(types):
                if isinstance(typ, Array) and typ.type == 'dict':
                    types.remove(typ)
                    result |= typ.dict_values()
            return result | 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',
                    trailer_op,
                    message="TypeError: '%s' object is not subscriptable" %
                    typ)
            else:
                try:
                    result |= getitem(index)
                except IndexError:
                    result |= py__iter__types(evaluator, set([typ]))
                except KeyError:
                    # Must be a dict. Lists don't raise KeyErrors.
                    result |= typ.dict_values()
    return result
Beispiel #13
0
def _element_calculate(evaluator, context, left, operator, right):
    from jedi.evaluate import iterable, instance
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.AbstractSequence) or is_string(left):
            return set([left])
        elif isinstance(right, iterable.AbstractSequence) or is_string(right):
            return set([right])
    elif operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return set([create(evaluator, left.obj + right.obj)])
        elif _is_tuple(left) and _is_tuple(right) or _is_list(
                left) and _is_list(right):
            return set([iterable.MergedArray(evaluator, (left, right))])
    elif operator == '-':
        if l_is_num and r_is_num:
            return set([create(evaluator, left.obj - right.obj)])
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return set([left])
    elif operator in COMPARISON_OPERATORS:
        operation = COMPARISON_OPERATORS[operator]
        if isinstance(left, CompiledObject) and isinstance(
                right, CompiledObject):
            # Possible, because the return is not an option. Just compare.
            left = left.obj
            right = right.obj

        try:
            result = operation(left, right)
        except TypeError:
            # Could be True or False.
            return set([create(evaluator, True), create(evaluator, False)])
        else:
            return set([create(evaluator, result)])
    elif operator == 'in':
        return set()

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, instance.CompiledInstance) and \
            obj.name.string_name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(context, 'type-error-operation', operator,
                     message % (left, right))

    return set([left, right])
Beispiel #14
0
def _iterate_star_args(context, array, input_node, funcdef=None):
    try:
        iter_ = array.py__iter__
    except AttributeError:
        if funcdef is not None:
            # TODO this funcdef should not be needed.
            m = "TypeError: %s() argument after * must be a sequence, not %s" \
                % (funcdef.name.value, array)
            analysis.add(context, 'type-error-star', input_node, message=m)
    else:
        for lazy_context in iter_():
            yield lazy_context
Beispiel #15
0
def _iterate_star_args(context, array, input_node, funcdef=None):
    try:
        iter_ = array.py__iter__
    except AttributeError:
        if funcdef is not None:
            # TODO this funcdef should not be needed.
            m = "TypeError: %s() argument after * must be a sequence, not %s" \
                % (funcdef.name.value, array)
            analysis.add(context, 'type-error-star', input_node, message=m)
    else:
        for lazy_context in iter_():
            yield lazy_context
Beispiel #16
0
def _element_calculate(evaluator, context, left, operator, right):
    from jedi.evaluate import iterable, instance
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.AbstractSequence) or is_string(left):
            return set([left])
        elif isinstance(right, iterable.AbstractSequence) or is_string(right):
            return set([right])
    elif operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return set([create(evaluator, left.obj + right.obj)])
        elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
            return set([iterable.MergedArray(evaluator, (left, right))])
    elif operator == '-':
        if l_is_num and r_is_num:
            return set([create(evaluator, left.obj - right.obj)])
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return set([left])
    elif operator in COMPARISON_OPERATORS:
        operation = COMPARISON_OPERATORS[operator]
        if isinstance(left, CompiledObject) and isinstance(right, CompiledObject):
            # Possible, because the return is not an option. Just compare.
            left = left.obj
            right = right.obj

        try:
            result = operation(left, right)
        except TypeError:
            # Could be True or False.
            return set([create(evaluator, True), create(evaluator, False)])
        else:
            return set([create(evaluator, result)])
    elif operator == 'in':
        return set()

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, instance.CompiledInstance) and \
            obj.name.string_name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(context, 'type-error-operation', operator,
                     message % (left, right))

    return set([left, right])
Beispiel #17
0
def _element_calculate(evaluator, left, operator, right):
    from jedi.evaluate import iterable, representation as er
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or is_string(left):
            return [left]
        elif isinstance(right, iterable.Array) or is_string(right):
            return [right]
    elif operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return [create(evaluator, left.obj + right.obj)]
        elif _is_tuple(left) and _is_tuple(right) or _is_list(
                left) and _is_list(right):
            return [iterable.MergedArray(evaluator, (left, right))]
    elif operator == '-':
        if l_is_num and r_is_num:
            return [create(evaluator, left.obj - right.obj)]
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return [left]
    elif operator in COMPARISON_OPERATORS:
        operation = COMPARISON_OPERATORS[operator]
        if isinstance(left, CompiledObject) and isinstance(
                right, CompiledObject):
            # Possible, because the return is not an option. Just compare.
            left = left.obj
            right = right.obj

        try:
            return [keyword_from_value(operation(left, right))]
        except TypeError:
            # Could be True or False.
            return [true_obj, false_obj]
    elif operator == 'in':
        return []

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(
            obj, er.Instance) and obj.name.get_code() in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(evaluator, 'type-error-operation', operator,
                     message % (left, right))

    return [left, right]
Beispiel #18
0
def py__getitem__(evaluator, context, types, trailer):
    from jedi.evaluate.representation import ClassContext
    from jedi.evaluate.instance import TreeInstance
    result = set()

    trailer_op, node, trailer_cl = trailer.children
    assert trailer_op == "["
    assert trailer_cl == "]"

    # special case: PEP0484 typing module, see
    # https://github.com/davidhalter/jedi/issues/663
    for typ in list(types):
        if isinstance(typ, (ClassContext, TreeInstance)):
            typing_module_types = pep0484.py__getitem__(context, typ, node)
            if typing_module_types is not None:
                types.remove(typ)
                result |= typing_module_types

    if not types:
        # all consumed by special cases
        return result

    for index in create_index_types(evaluator, context, node):
        if isinstance(index, (compiled.CompiledObject, Slice)):
            index = index.obj

        if type(index) not in (float, int, str, unicode, slice):
            # If the index is not clearly defined, we have to get all the
            # possiblities.
            for typ in list(types):
                if isinstance(typ, AbstractSequence) and typ.array_type == 'dict':
                    types.remove(typ)
                    result |= typ.dict_values()
            return result | py__iter__types(evaluator, types)

        for typ in types:
            # The actual getitem call.
            try:
                getitem = typ.py__getitem__
            except AttributeError:
                # TODO this context is probably not right.
                analysis.add(context, 'type-error-not-subscriptable', trailer_op,
                             message="TypeError: '%s' object is not subscriptable" % typ)
            else:
                try:
                    result |= getitem(index)
                except IndexError:
                    result |= py__iter__types(evaluator, set([typ]))
                except KeyError:
                    # Must be a dict. Lists don't raise KeyErrors.
                    result |= typ.dict_values()
    return result
Beispiel #19
0
def _star_star_dict(context, array, input_node, funcdef):
    from jedi.evaluate.context.instance import CompiledInstance
    if isinstance(array, CompiledInstance) and array.name.string_name == 'dict':
        # For now ignore this case. In the future add proper iterators and just
        # make one call without crazy isinstance checks.
        return {}
    elif isinstance(array, iterable.AbstractIterable) and array.array_type == 'dict':
        return array.exact_key_items()
    else:
        if funcdef is not None:
            m = "TypeError: %s argument after ** must be a mapping, not %s" \
                % (funcdef.name.value, array)
            analysis.add(context, 'type-error-star-star', input_node, message=m)
        return {}
Beispiel #20
0
def _star_star_dict(context, array, input_node, funcdef):
    from jedi.evaluate.instance import CompiledInstance
    if isinstance(array, CompiledInstance) and array.name.string_name == 'dict':
        # For now ignore this case. In the future add proper iterators and just
        # make one call without crazy isinstance checks.
        return {}
    elif isinstance(array, iterable.AbstractSequence) and array.array_type == 'dict':
        return array.exact_key_items()
    else:
        if funcdef is not None:
            m = "TypeError: %s argument after ** must be a mapping, not %s" \
                % (funcdef.name.value, array)
            analysis.add(context, 'type-error-star-star', input_node, message=m)
        return {}
Beispiel #21
0
def _element_calculate(evaluator, left, operator, right):
    from jedi.evaluate import iterable, representation as er
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or is_string(left):
            return [left]
        elif isinstance(right, iterable.Array) or is_string(right):
            return [right]
    elif operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return [create(evaluator, left.obj + right.obj)]
        elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
            return [iterable.MergedArray(evaluator, (left, right))]
    elif operator == '-':
        if l_is_num and r_is_num:
            return [create(evaluator, left.obj - right.obj)]
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return [left]
    elif operator in COMPARISON_OPERATORS:
        operation = COMPARISON_OPERATORS[operator]
        if isinstance(left, CompiledObject) and isinstance(right, CompiledObject):
            # Possible, because the return is not an option. Just compare.
            left = left.obj
            right = right.obj

        try:
            return [keyword_from_value(operation(left, right))]
        except TypeError:
            # Could be True or False.
            return [true_obj, false_obj]
    elif operator == 'in':
        return []

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, er.Instance) and obj.name.get_code() in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(evaluator, 'type-error-operation', operator,
                     message % (left, right))

    return [left, right]
Beispiel #22
0
 def iterate(self, contextualized_node=None):
     debug.dbg('iterate')
     try:
         iter_method = self.py__iter__
     except AttributeError:
         if contextualized_node is not None:
             from jedi.evaluate import analysis
             analysis.add(
                 contextualized_node.context,
                 'type-error-not-iterable',
                 contextualized_node.node,
                 message="TypeError: '%s' object is not iterable" % self)
         return iter([])
     else:
         return iter_method()
Beispiel #23
0
def _iterate_star_args(evaluator, array, input_node, func=None):
    from jedi.evaluate.representation import Instance
    if isinstance(array, iterable.Array):
        for field_stmt in array:  # yield from plz!
            yield field_stmt
    elif isinstance(array, iterable.Generator):
        for field_stmt in array.iter_content():
            yield iterable.AlreadyEvaluated([field_stmt])
    elif isinstance(array, Instance) and array.name.get_code() == 'tuple':
        debug.warning('Ignored a tuple *args input %s' % array)
    else:
        if func is not None:
            m = "TypeError: %s() argument after * must be a sequence, not %s" \
                % (func.name.value, array)
            analysis.add(evaluator, 'type-error-star', input_node, message=m)
Beispiel #24
0
def _iterate_star_args(evaluator, array, input_node, func=None):
    from jedi.evaluate.representation import Instance
    if isinstance(array, iterable.Array):
        for field_stmt in array:  # yield from plz!
            yield field_stmt
    elif isinstance(array, iterable.Generator):
        for field_stmt in array.iter_content():
            yield iterable.AlreadyEvaluated([field_stmt])
    elif isinstance(array, Instance) and array.name.get_code() == 'tuple':
        debug.warning('Ignored a tuple *args input %s' % array)
    else:
        if func is not None:
            m = "TypeError: %s() argument after * must be a sequence, not %s" \
                % (func.name.value, array)
            analysis.add(evaluator, 'type-error-star', input_node, message=m)
Beispiel #25
0
 def iterate(self, contextualized_node=None):
     debug.dbg('iterate')
     try:
         iter_method = self.py__iter__
     except AttributeError:
         if contextualized_node is not None:
             from jedi.evaluate import analysis
             analysis.add(contextualized_node.context,
                          'type-error-not-iterable',
                          contextualized_node.node,
                          message="TypeError: '%s' object is not iterable" %
                          self)
         return iter([])
     else:
         return iter_method()
    def get_item(self, index_contexts, contextualized_node):
        from jedi.evaluate.compiled import CompiledObject
        from jedi.evaluate.context.iterable import Slice, Sequence
        result = ContextSet()

        for index in index_contexts:
            if isinstance(index, Slice):
                index = index.obj
            if isinstance(index, CompiledObject):
                try:
                    index = index.get_safe_value()
                except ValueError:
                    pass

            if type(index) not in (float, int, str, unicode, slice, bytes):
                # If the index is not clearly defined, we have to get all the
                # possiblities.
                if isinstance(self, Sequence) and self.array_type == 'dict':
                    result |= self.dict_values()
                else:
                    result |= iterate_contexts(ContextSet(self))
                continue

            # The actual getitem call.
            try:
                getitem = self.py__getitem__
            except AttributeError:
                from jedi.evaluate import analysis
                # TODO this context is probably not right.
                analysis.add(
                    contextualized_node.context,
                    'type-error-not-subscriptable',
                    contextualized_node.node,
                    message="TypeError: '%s' object is not subscriptable" %
                    self)
            else:
                try:
                    result |= getitem(index)
                except EvaluatorIndexError:
                    result |= iterate_contexts(ContextSet(self))
                except EvaluatorKeyError:
                    # Must be a dict. Lists don't raise KeyErrors.
                    result |= self.dict_values()
                except EvaluatorTypeError:
                    # The type is wrong and therefore it makes no sense to do
                    # anything anymore.
                    result = NO_CONTEXTS
        return result
Beispiel #27
0
    def get_item(self, index_contexts, contextualized_node):
        from jedi.evaluate.compiled import CompiledObject
        from jedi.evaluate.context.iterable import Slice, Sequence
        result = ContextSet()

        for index in index_contexts:
            if isinstance(index, Slice):
                index = index.obj
            if isinstance(index, CompiledObject):
                try:
                    index = index.get_safe_value()
                except ValueError:
                    pass

            if type(index) not in (float, int, str, unicode, slice, bytes):
                # If the index is not clearly defined, we have to get all the
                # possiblities.
                if isinstance(self, Sequence) and self.array_type == 'dict':
                    result |= self.dict_values()
                else:
                    result |= iterate_contexts(ContextSet(self))
                continue

            # The actual getitem call.
            try:
                getitem = self.py__getitem__
            except AttributeError:
                from jedi.evaluate import analysis
                # TODO this context is probably not right.
                analysis.add(
                    contextualized_node.context,
                    'type-error-not-subscriptable',
                    contextualized_node.node,
                    message="TypeError: '%s' object is not subscriptable" % self
                )
            else:
                try:
                    result |= getitem(index)
                except EvaluatorIndexError:
                    result |= iterate_contexts(ContextSet(self))
                except EvaluatorKeyError:
                    # Must be a dict. Lists don't raise KeyErrors.
                    result |= self.dict_values()
                except EvaluatorTypeError:
                    # The type is wrong and therefore it makes no sense to do
                    # anything anymore.
                    result = NO_CONTEXTS
        return result
Beispiel #28
0
    def _analysis(self):
        #statements = set(chain(*self._parser.module().used_names.values()))
        stmts, imps = analysis.get_module_statements(self._parser.module())
        # Sort the statements so that the results are reproducible.
        for i in imps:
            iw = imports.ImportWrapper(self._evaluator, i,
                                       nested_resolve=True).follow()
            if i.is_nested() and any(not isinstance(i, pr.Module) for i in iw):
                analysis.add(self._evaluator, 'import-error', i.namespace.names[-1])
        for stmt in sorted(stmts, key=lambda obj: obj.start_pos):
            if not (isinstance(stmt.parent, pr.ForFlow)
                    and stmt.parent.set_stmt == stmt):
                self._evaluator.eval_statement(stmt)

        ana = [a for a in self._evaluator.analysis if self.path == a.path]
        return sorted(set(ana), key=lambda x: x.line)
Beispiel #29
0
def _iterate_star_args(evaluator, array, input_node, func=None):
    from jedi.evaluate.representation import Instance
    if isinstance(array, iterable.Array):
        # TODO ._items is not the call we want here. Replace in the future. id:131 gh:132
        for node in array._items():
            yield node
    elif isinstance(array, iterable.Generator):
        for types in array.py__iter__():
            yield iterable.AlreadyEvaluated(types)
    elif isinstance(array, Instance) and array.name.get_code() == 'tuple':
        debug.warning('Ignored a tuple *args input %s' % array)
    else:
        if func is not None:
            m = "TypeError: %s() argument after * must be a sequence, not %s" \
                % (func.name.value, array)
            analysis.add(evaluator, 'type-error-star', input_node, message=m)
Beispiel #30
0
def _iterate_star_args(evaluator, array, expression_list, func):
    from jedi.evaluate.representation import Instance
    if isinstance(array, iterable.Array):
        for field_stmt in array:  # yield from plz!
            yield field_stmt
    elif isinstance(array, iterable.Generator):
        for field_stmt in array.iter_content():
            yield helpers.FakeStatement([field_stmt])
    elif isinstance(array, Instance) and array.name == 'tuple':
        pass
    else:
        if expression_list:
            m = "TypeError: %s() argument after * must be a sequence, not %s" \
                % (func.name, array)
            analysis.add(evaluator, 'type-error-star',
                         expression_list[0], message=m)
def _iterate_star_args(evaluator, array, input_node, func=None):
    from jedi.evaluate.representation import Instance
    if isinstance(array, iterable.Array):
        # TODO ._items is not the call we want here. Replace in the future.
        for node in array._items():
            yield node
    elif isinstance(array, iterable.Generator):
        for types in array.py__iter__():
            yield iterable.AlreadyEvaluated(types)
    elif isinstance(array, Instance) and array.name.get_code() == 'tuple':
        debug.warning('Ignored a tuple *args input %s' % array)
    else:
        if func is not None:
            m = "TypeError: %s() argument after * must be a sequence, not %s" \
                % (func.name.value, array)
            analysis.add(evaluator, 'type-error-star', input_node, message=m)
Beispiel #32
0
def _iterate_star_args(evaluator, array, expression_list, func):
    from jedi.evaluate.representation import Instance
    if isinstance(array, iterable.Array):
        for field_stmt in array:  # yield from plz!
            yield field_stmt
    elif isinstance(array, iterable.Generator):
        for field_stmt in array.iter_content():
            yield helpers.FakeStatement([field_stmt])
    elif isinstance(array, Instance) and array.name.get_code() == 'tuple':
        debug.warning('Ignored a tuple *args input %s' % array)
    else:
        if expression_list:
            m = "TypeError: %s() argument after * must be a sequence, not %s" \
                % (func.name.get_code(), array)
            analysis.add(evaluator, 'type-error-star',
                         expression_list[0], message=m)
Beispiel #33
0
def unpack_tuple_to_dict(evaluator, types, exprlist):
    """
    Unpacking tuple assignments in for statements and expr_stmts.
    """
    if exprlist.type == 'name':
        return {exprlist.value: types}
    elif exprlist.type == 'atom' and exprlist.children[0] in '([':
        return unpack_tuple_to_dict(evaluator, types, exprlist.children[1])
    elif exprlist.type in ('testlist', 'testlist_comp', 'exprlist',
                           'testlist_star_expr'):
        dct = {}
        parts = iter(exprlist.children[::2])
        n = 0
        for lazy_context in py__iter__(evaluator, types, exprlist):
            n += 1
            try:
                part = next(parts)
            except StopIteration:
                # TODO this context is probably not right.
                analysis.add(
                    next(iter(types)),
                    'value-error-too-many-values',
                    part,
                    message=
                    "ValueError: too many values to unpack (expected %s)" % n)
            else:
                dct.update(
                    unpack_tuple_to_dict(evaluator, lazy_context.infer(),
                                         part))
        has_parts = next(parts, None)
        if types and has_parts is not None:
            # TODO this context is probably not right.
            analysis.add(
                next(iter(types)),
                'value-error-too-few-values',
                has_parts,
                message="ValueError: need more than %s values to unpack" % n)
        return dct
    elif exprlist.type == 'power' or exprlist.type == 'atom_expr':
        # Something like ``arr[x], var = ...``.
        # This is something that is not yet supported, would also be difficult
        # to write into a dict.
        return {}
    elif exprlist.type == 'star_expr':  # `a, *b, c = x` type unpackings
        # Currently we're not supporting them.
        return {}
    raise NotImplementedError
Beispiel #34
0
    def follow(self, is_goto=False):
        if self._evaluator.recursion_detector.push_stmt(self._import):
            # check recursion
            return []

        try:
            module = self._import.get_parent_until()
            import_path = self._import.path_for_name(self._name)
            importer = get_importer(self._evaluator, tuple(import_path),
                                    module, self._import.level)
            try:
                module, rest = importer.follow_file_system()
            except ModuleNotFound as e:
                analysis.add(self._evaluator, 'import-error', e.name)
                return []

            if module is None:
                return []

            #if self._import.is_nested() and not self.nested_resolve:
            #    scopes = [NestedImportModule(module, self._import)]
            scopes = [module]

            # goto only accepts `Name`
            if is_goto and not rest:
                scopes = [s.name for s in scopes]

            # follow the rest of the import (not FS -> classes, functions)
            if rest:
                if is_goto:
                    scopes = list(
                        chain.from_iterable(
                            self._evaluator.find_types(
                                s, rest[0], is_goto=True) for s in scopes))
                else:
                    if self._import.type == 'import_from' \
                            or importer.str_import_path == ('os', 'path'):
                        scopes = importer.follow_rest(scopes[0], rest)
                    else:
                        scopes = []
            debug.dbg('after import: %s', scopes)
            if not scopes:
                analysis.add(self._evaluator, 'import-error',
                             importer.import_path[-1])
        finally:
            self._evaluator.recursion_detector.pop_stmt()
        return scopes
Beispiel #35
0
    def _analysis(self):
        #statements = set(chain(*self._parser.module().used_names.values()))
        stmts, imps = analysis.get_module_statements(self._parser.module())
        # Sort the statements so that the results are reproducible.
        for i in imps:
            iw = imports.ImportWrapper(self._evaluator, i,
                                       nested_resolve=True).follow()
            if i.is_nested() and any(not isinstance(i, pr.Module) for i in iw):
                analysis.add(self._evaluator, 'import-error',
                             i.namespace.names[-1])
        for stmt in sorted(stmts, key=lambda obj: obj.start_pos):
            if not (isinstance(stmt.parent, pr.ForFlow)
                    and stmt.parent.set_stmt == stmt):
                self._evaluator.eval_statement(stmt)

        ana = [a for a in self._evaluator.analysis if self.path == a.path]
        return sorted(set(ana), key=lambda x: x.line)
Beispiel #36
0
def py__iter__(evaluator, types, node=None):
    debug.dbg('py__iter__')
    type_iters = []
    for typ in types:
        try:
            iter_method = typ.py__iter__
        except AttributeError:
            if node is not None:
                analysis.add(evaluator, 'type-error-not-iterable', node,
                             message="TypeError: '%s' object is not iterable" % typ)
        else:
            type_iters.append(iter_method())
            #for result in iter_method():
                #yield result

    for t in zip_longest(*type_iters, fillvalue=set()):
        yield unite(t)
Beispiel #37
0
    def follow(self, is_goto=False):
        if self._evaluator.recursion_detector.push_stmt(self._import):
            # check recursion
            return []

        try:
            module = self._import.get_parent_until()
            import_path = self._import.path_for_name(self._name)
            importer = get_importer(self._evaluator, tuple(import_path),
                                    module, self._import.level)
            try:
                module, rest = importer.follow_file_system()
            except ModuleNotFound as e:
                analysis.add(self._evaluator, 'import-error', e.name)
                return []

            if module is None:
                return []

            #if self._import.is_nested() and not self.nested_resolve:
            #    scopes = [NestedImportModule(module, self._import)]
            scopes = [module]

            # goto only accepts `Name`
            if is_goto and not rest:
                scopes = [s.name for s in scopes]

            # follow the rest of the import (not FS -> classes, functions)
            if rest:
                if is_goto:
                    scopes = list(chain.from_iterable(
                        self._evaluator.find_types(s, rest[0], is_goto=True)
                        for s in scopes))
                else:
                    if self._import.type == 'import_from' \
                            or importer.str_import_path == ('os', 'path'):
                        scopes = importer.follow_rest(scopes[0], rest)
                    else:
                        scopes = []
            debug.dbg('after import: %s', scopes)
            if not scopes:
                analysis.add(self._evaluator, 'import-error', importer.import_path[-1])
        finally:
            self._evaluator.recursion_detector.pop_stmt()
        return scopes
Beispiel #38
0
def py__iter__(evaluator, types, node=None):
    debug.dbg('py__iter__')
    type_iters = []
    for typ in types:
        try:
            iter_method = typ.py__iter__
        except AttributeError:
            if node is not None:
                # TODO this context is probably not right.
                analysis.add(typ, 'type-error-not-iterable', node,
                             message="TypeError: '%s' object is not iterable" % typ)
        else:
            type_iters.append(iter_method())

    for lazy_contexts in zip_longest(*type_iters):
        yield context.get_merged_lazy_context(
            [l for l in lazy_contexts if l is not None]
        )
Beispiel #39
0
def py__iter__(evaluator, types, contextualized_node=None):
    debug.dbg('py__iter__')
    type_iters = []
    for typ in types:
        try:
            iter_method = typ.py__iter__
        except AttributeError:
            if contextualized_node is not None:
                analysis.add(contextualized_node.context,
                             'type-error-not-iterable',
                             contextualized_node._node,
                             message="TypeError: '%s' object is not iterable" %
                             typ)
        else:
            type_iters.append(iter_method())

    for lazy_contexts in zip_longest(*type_iters):
        yield context.get_merged_lazy_context(
            [l for l in lazy_contexts if l is not None])
Beispiel #40
0
    def find(self, scopes, search_global=False):
        names = self.filter_name(scopes)
        types = self._names_to_types(names, search_global)

        if not names and not types \
                and not (isinstance(self.name_str, pr.Name)
                         and isinstance(self.name_str.parent.parent, pr.Param)):
            if not isinstance(self.name_str, (str, unicode)):  # TODO Remove?
                if search_global:
                    message = ("NameError: name '%s' is not defined."
                               % self.name_str)
                    analysis.add(self._evaluator, 'name-error', self.name_str,
                                 message)
                else:
                    analysis.add_attribute_error(self._evaluator,
                                                 self.scope, self.name_str)

        debug.dbg('finder._names_to_types: %s -> %s', names, types)
        return types
Beispiel #41
0
    def find(self, scopes, resolve_decorator=True, search_global=False):
        names = self.filter_name(scopes)
        types = self._names_to_types(names, resolve_decorator)

        if not names and not types \
                and not (isinstance(self.name_str, pr.Name)
                         and isinstance(self.name_str.parent.parent, pr.Param)):
            if not isinstance(self.name_str, (str, unicode)):  # TODO Remove?
                if search_global:
                    message = ("NameError: name '%s' is not defined."
                               % self.name_str)
                    analysis.add(self._evaluator, 'name-error', self.name_str,
                                 message)
                else:
                    analysis.add_attribute_error(self._evaluator,
                                                 self.scope, self.name_str)

        debug.dbg('finder._names_to_types: %s -> %s', names, types)
        return self._resolve_descriptors(types)
Beispiel #42
0
def py__iter__(evaluator, types, node=None):
    debug.dbg('py__iter__')
    type_iters = []
    for typ in types:
        try:
            iter_method = typ.py__iter__
        except AttributeError:
            if node is not None:
                analysis.add(evaluator,
                             'type-error-not-iterable',
                             node,
                             message="TypeError: '%s' object is not iterable" %
                             typ)
        else:
            type_iters.append(iter_method())
            #for result in iter_method():
            #yield result

    for t in zip_longest(*type_iters, fillvalue=set()):
        yield unite(t)
Beispiel #43
0
    def get_item(self, index_contexts, contextualized_node):
        from jedi.evaluate.compiled import CompiledObject
        from jedi.evaluate.context.iterable import Slice, AbstractIterable
        result = ContextSet()

        for index in index_contexts:
            if isinstance(index, (CompiledObject, Slice)):
                index = index.obj

            if type(index) not in (float, int, str, unicode, slice,
                                   type(Ellipsis)):
                # If the index is not clearly defined, we have to get all the
                # possiblities.
                if isinstance(self,
                              AbstractIterable) and self.array_type == 'dict':
                    result |= self.dict_values()
                else:
                    result |= iterate_contexts(ContextSet(self))
                continue

            # The actual getitem call.
            try:
                getitem = self.py__getitem__
            except AttributeError:
                from jedi.evaluate import analysis
                # TODO this context is probably not right.
                analysis.add(
                    contextualized_node.context,
                    'type-error-not-subscriptable',
                    contextualized_node.node,
                    message="TypeError: '%s' object is not subscriptable" %
                    self)
            else:
                try:
                    result |= getitem(index)
                except IndexError:
                    result |= iterate_contexts(ContextSet(self))
                except KeyError:
                    # Must be a dict. Lists don't raise KeyErrors.
                    result |= self.dict_values()
        return result
Beispiel #44
0
def builtins_isinstance(evaluator, objects, types, arguments):
    bool_results = set()
    for o in objects:
        cls = o.py__class__()
        try:
            mro_func = cls.py__mro__
        except AttributeError:
            # This is temporary. Everything should have a class attribute in
            # Python?! Maybe we'll leave it here, because some numpy objects or
            # whatever might not.
            bool_results = set([True, False])
            break

        mro = mro_func()

        for cls_or_tup in types:
            if cls_or_tup.is_class():
                bool_results.add(cls_or_tup in mro)
            elif cls_or_tup.name.string_name == 'tuple' \
                    and cls_or_tup.get_root_context() == evaluator.builtins_module:
                # Check for tuples.
                classes = ContextSet.from_sets(
                    lazy_context.infer()
                    for lazy_context in cls_or_tup.iterate()
                )
                bool_results.add(any(cls in mro for cls in classes))
            else:
                _, lazy_context = list(arguments.unpack())[1]
                if isinstance(lazy_context, LazyTreeContext):
                    node = lazy_context.data
                    message = 'TypeError: isinstance() arg 2 must be a ' \
                              'class, type, or tuple of classes and types, ' \
                              'not %s.' % cls_or_tup
                    analysis.add(lazy_context._context, 'type-error-isinstance', node, message)

    return ContextSet.from_iterable(
        compiled.builtin_from_name(evaluator, force_unicode(str(b)))
        for b in bool_results
    )
Beispiel #45
0
    def get_item(self, index_contexts, contextualized_node):
        from jedi.evaluate.compiled import CompiledObject
        from jedi.evaluate.context.iterable import Slice, AbstractIterable
        result = ContextSet()

        for index in index_contexts:
            if isinstance(index, (CompiledObject, Slice)):
                index = index.obj

            if type(index) not in (float, int, str, unicode, slice, type(Ellipsis)):
                # If the index is not clearly defined, we have to get all the
                # possiblities.
                if isinstance(self, AbstractIterable) and self.array_type == 'dict':
                    result |= self.dict_values()
                else:
                    result |= iterate_contexts(ContextSet(self))
                continue

            # The actual getitem call.
            try:
                getitem = self.py__getitem__
            except AttributeError:
                from jedi.evaluate import analysis
                # TODO this context is probably not right.
                analysis.add(
                    contextualized_node.context,
                    'type-error-not-subscriptable',
                    contextualized_node.node,
                    message="TypeError: '%s' object is not subscriptable" % self
                )
            else:
                try:
                    result |= getitem(index)
                except IndexError:
                    result |= iterate_contexts(ContextSet(self))
                except KeyError:
                    # Must be a dict. Lists don't raise KeyErrors.
                    result |= self.dict_values()
        return result
Beispiel #46
0
def builtins_isinstance(objects, types, arguments, evaluator):
    bool_results = set()
    for o in objects:
        cls = o.py__class__()
        try:
            cls.py__bases__
        except AttributeError:
            # This is temporary. Everything should have a class attribute in
            # Python?! Maybe we'll leave it here, because some numpy objects or
            # whatever might not.
            bool_results = set([True, False])
            break

        mro = list(cls.py__mro__())

        for cls_or_tup in types:
            if cls_or_tup.is_class():
                bool_results.add(cls_or_tup in mro)
            elif cls_or_tup.name.string_name == 'tuple' \
                    and cls_or_tup.get_root_context() == evaluator.builtins_module:
                # Check for tuples.
                classes = ContextSet.from_sets(
                    lazy_context.infer()
                    for lazy_context in cls_or_tup.iterate()
                )
                bool_results.add(any(cls in mro for cls in classes))
            else:
                _, lazy_context = list(arguments.unpack())[1]
                if isinstance(lazy_context, LazyTreeContext):
                    node = lazy_context.data
                    message = 'TypeError: isinstance() arg 2 must be a ' \
                              'class, type, or tuple of classes and types, ' \
                              'not %s.' % cls_or_tup
                    analysis.add(lazy_context.context, 'type-error-isinstance', node, message)

    return ContextSet(
        compiled.builtin_from_name(evaluator, force_unicode(str(b)))
        for b in bool_results
    )
Beispiel #47
0
def _star_star_dict(evaluator, array, input_node, func):
    dct = defaultdict(lambda: [])
    from jedi.evaluate.representation import Instance
    if isinstance(array, Instance) and array.name.get_code() == 'dict':
        # For now ignore this case. In the future add proper iterators and just
        # make one call without crazy isinstance checks.
        return {}

    if isinstance(array, iterable.FakeDict):
        return array._dct
    elif isinstance(array, iterable.Array) and array.type == 'dict':
        # TODO bad call to non-public API
        for key_node, values in array._items():
            for key in evaluator.eval_element(key_node):
                if precedence.is_string(key):
                    dct[key.obj] += values

    else:
        if func is not None:
            m = "TypeError: %s argument after ** must be a mapping, not %s" \
                % (func.name.value, array)
            analysis.add(evaluator, 'type-error-star-star', input_node, message=m)
    return dict(dct)
Beispiel #48
0
def _star_star_dict(evaluator, array, input_node, func):
    dct = defaultdict(lambda: [])
    from jedi.evaluate.representation import Instance
    if isinstance(array, Instance) and array.name.get_code() == 'dict':
        # For now ignore this case. In the future add proper iterators and just
        # make one call without crazy isinstance checks.
        return {}

    if isinstance(array, iterable.FakeDict):
        return array._dct
    elif isinstance(array, iterable.Array) and array.type == 'dict':
        # TODO bad call to non-public API id:610 gh:611
        for key_node, values in array._items():
            for key in evaluator.eval_element(key_node):
                if precedence.is_string(key):
                    dct[key.obj] += values

    else:
        if func is not None:
            m = "TypeError: %s argument after ** must be a mapping, not %s" \
                % (func.name.value, array)
            analysis.add(evaluator, 'type-error-star-star', input_node, message=m)
    return dict(dct)
Beispiel #49
0
    def find(self, scopes, search_global=False):
        # TODO rename scopes to names_dicts

        names = self.filter_name(scopes)
        if self._found_predefined_if_name is not None:
            return self._found_predefined_if_name

        types = self._names_to_types(names, search_global)

        if (
            not names
            and not types
            and not (isinstance(self.name_str, tree.Name) and isinstance(self.name_str.parent.parent, tree.Param))
        ):
            if not isinstance(self.name_str, (str, unicode)):  # TODO Remove?
                if search_global:
                    message = "NameError: name '%s' is not defined." % self.name_str
                    analysis.add(self._evaluator, "name-error", self.name_str, message)
                else:
                    analysis.add_attribute_error(self._evaluator, self.scope, self.name_str)

        debug.dbg("finder._names_to_types: %s -> %s", names, types)
        return types
Beispiel #50
0
def _element_calculate(evaluator, left, operator, right):
    from jedi.evaluate import iterable, representation as er
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or _is_string(left):
            return [left]
        elif isinstance(right, iterable.Array) or _is_string(right):
            return [right]
    elif operator == '+':
        if l_is_num and r_is_num or _is_string(left) and _is_string(right):
            return [create(evaluator, left.obj + right.obj)]
        elif _is_tuple(left) and _is_tuple(right) or _is_list(
                left) and _is_list(right):
            return [iterable.MergedArray(evaluator, (left, right))]
    elif operator == '-':
        if l_is_num and r_is_num:
            return [create(evaluator, left.obj - right.obj)]
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return [left]

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, er.Instance) and obj.name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(evaluator, 'type-error-operation', operator,
                     message % (left, right))

    return [left, right]
Beispiel #51
0
    def find(self, scopes, resolve_decorator=True, search_global=False):
        if unicode(self.name_str) == 'None':
            # Filter None, because it's really just a keyword, nobody wants to
            # access it.
            return []

        names = self.filter_name(scopes)
        types = self._names_to_types(names, resolve_decorator)

        if not names and not types \
                and not (isinstance(self.name_str, pr.NamePart)
                         and isinstance(self.name_str.parent.parent, pr.Param)):
            if not isinstance(self.name_str, (str, unicode)):  # TODO Remove?
                if search_global:
                    message = ("NameError: name '%s' is not defined."
                               % self.name_str)
                    analysis.add(self._evaluator, 'name-error', self.name_str,
                                 message)
                else:
                    analysis.add_attribute_error(self._evaluator,
                                                 self.scope, self.name_str)

        debug.dbg('finder._names_to_types: %s -> %s', names, types)
        return self._resolve_descriptors(types)
Beispiel #52
0
def _add_error(evaluator, name, message=None):
    if hasattr(name, 'parent'):
        # Should be a name, not a string!
        analysis.add(evaluator, 'import-error', name, message)
Beispiel #53
0
def get_params(execution_context, var_args):
    result_params = []
    param_dict = {}
    funcdef = execution_context.tree_node
    parent_context = execution_context.parent_context

    for param in funcdef.get_params():
        param_dict[param.name.value] = param
    unpacked_va = list(var_args.unpack(funcdef))
    var_arg_iterator = PushBackIterator(iter(unpacked_va))

    non_matching_keys = defaultdict(lambda: [])
    keys_used = {}
    keys_only = False
    had_multiple_value_error = False
    for param in funcdef.get_params():
        # The value and key can both be null. There, the defaults apply.
        # args / kwargs will just be empty arrays / dicts, respectively.
        # Wrong value count is just ignored. If you try to test cases that are
        # not allowed in Python, Jedi will maybe not show any completions.
        key, argument = next(var_arg_iterator, (None, None))
        while key is not None:
            keys_only = True
            try:
                key_param = param_dict[key]
            except KeyError:
                non_matching_keys[key] = argument
            else:
                if key in keys_used:
                    had_multiple_value_error = True
                    m = (
                        "TypeError: %s() got multiple values for keyword argument '%s'."
                        % (funcdef.name, key))
                    for node in var_args.get_calling_nodes():
                        analysis.add(parent_context,
                                     'type-error-multiple-values',
                                     node,
                                     message=m)
                else:
                    keys_used[key] = ExecutedParam(execution_context,
                                                   key_param, argument)
            key, argument = next(var_arg_iterator, (None, None))

        try:
            result_params.append(keys_used[param.name.value])
            continue
        except KeyError:
            pass

        if param.star_count == 1:
            # *args param
            lazy_context_list = []
            if argument is not None:
                lazy_context_list.append(argument)
                for key, argument in var_arg_iterator:
                    # Iterate until a key argument is found.
                    if key:
                        var_arg_iterator.push_back((key, argument))
                        break
                    lazy_context_list.append(argument)
            seq = iterable.FakeSequence(execution_context.evaluator, u'tuple',
                                        lazy_context_list)
            result_arg = LazyKnownContext(seq)
        elif param.star_count == 2:
            # **kwargs param
            dct = iterable.FakeDict(execution_context.evaluator,
                                    dict(non_matching_keys))
            result_arg = LazyKnownContext(dct)
            non_matching_keys = {}
        else:
            # normal param
            if argument is None:
                # No value: Return an empty container
                if param.default is None:
                    result_arg = LazyUnknownContext()
                    if not keys_only:
                        for node in var_args.get_calling_nodes():
                            m = _error_argument_count(funcdef,
                                                      len(unpacked_va))
                            analysis.add(parent_context,
                                         'type-error-too-few-arguments',
                                         node,
                                         message=m)
                else:
                    result_arg = LazyTreeContext(parent_context, param.default)
            else:
                result_arg = argument

        result_params.append(
            ExecutedParam(execution_context, param, result_arg))
        if not isinstance(result_arg, LazyUnknownContext):
            keys_used[param.name.value] = result_params[-1]

    if keys_only:
        # All arguments should be handed over to the next function. It's not
        # about the values inside, it's about the names. Jedi needs to now that
        # there's nothing to find for certain names.
        for k in set(param_dict) - set(keys_used):
            param = param_dict[k]

            if not (non_matching_keys or had_multiple_value_error
                    or param.star_count or param.default):
                # add a warning only if there's not another one.
                for node in var_args.get_calling_nodes():
                    m = _error_argument_count(funcdef, len(unpacked_va))
                    analysis.add(parent_context,
                                 'type-error-too-few-arguments',
                                 node,
                                 message=m)

    for key, lazy_context in non_matching_keys.items():
        m = "TypeError: %s() got an unexpected keyword argument '%s'." \
            % (funcdef.name, key)
        _add_argument_issue(parent_context,
                            'type-error-keyword-argument',
                            lazy_context,
                            message=m)

    remaining_arguments = list(var_arg_iterator)
    if remaining_arguments:
        m = _error_argument_count(funcdef, len(unpacked_va))
        # Just report an error for the first param that is not needed (like
        # cPython).
        first_key, lazy_context = remaining_arguments[0]
        if var_args.get_calling_nodes():
            # There might not be a valid calling node so check for that first.
            _add_argument_issue(parent_context,
                                'type-error-too-many-arguments',
                                lazy_context,
                                message=m)
    return result_params
Beispiel #54
0
def _add_argument_issue(parent_context, error_name, lazy_context, message):
    if isinstance(lazy_context, LazyTreeContext):
        node = lazy_context.data
        if node.parent.type == 'argument':
            node = node.parent
        analysis.add(parent_context, error_name, node, message)
Beispiel #55
0
def get_params(evaluator, func, var_args):
    param_names = []
    param_dict = {}
    for param in func.params:
        param_dict[str(param.get_name())] = param
    unpacked_va = list(var_args.unpack(func))
    from jedi.evaluate.representation import InstanceElement
    if isinstance(func, InstanceElement):
        # Include self at this place.
        unpacked_va.insert(
            0, (None, [iterable.AlreadyEvaluated([func.instance])]))
    var_arg_iterator = common.PushBackIterator(iter(unpacked_va))

    non_matching_keys = defaultdict(lambda: [])
    keys_used = {}
    keys_only = False
    had_multiple_value_error = False
    for param in func.params:
        # The value and key can both be null. There, the defaults apply.
        # args / kwargs will just be empty arrays / dicts, respectively.
        # Wrong value count is just ignored. If you try to test cases that are
        # not allowed in Python, Jedi will maybe not show any completions.
        default = [] if param.default is None else [param.default]
        key, va_values = next(var_arg_iterator, (None, default))
        while key is not None:
            keys_only = True
            k = unicode(key)
            try:
                key_param = param_dict[unicode(key)]
            except KeyError:
                non_matching_keys[key] += va_values
            else:
                param_names.append(
                    ExecutedParam(key_param, var_args, va_values).name)

            if k in keys_used:
                had_multiple_value_error = True
                m = (
                    "TypeError: %s() got multiple values for keyword argument '%s'."
                    % (func.name, k))
                calling_va = _get_calling_var_args(evaluator, var_args)
                if calling_va is not None:
                    analysis.add(evaluator,
                                 'type-error-multiple-values',
                                 calling_va,
                                 message=m)
            else:
                try:
                    keys_used[k] = param_names[-1]
                except IndexError:
                    # TODO this is wrong stupid and whatever.
                    pass
            key, va_values = next(var_arg_iterator, (None, ()))

        values = []
        if param.stars == 1:
            # *args param
            lst_values = [iterable.MergedNodes(va_values)] if va_values else []
            for key, va_values in var_arg_iterator:
                # Iterate until a key argument is found.
                if key:
                    var_arg_iterator.push_back((key, va_values))
                    break
                if va_values:
                    lst_values.append(iterable.MergedNodes(va_values))
            seq = iterable.FakeSequence(evaluator, lst_values, 'tuple')
            values = [iterable.AlreadyEvaluated([seq])]
        elif param.stars == 2:
            # **kwargs param
            dct = iterable.FakeDict(evaluator, dict(non_matching_keys))
            values = [iterable.AlreadyEvaluated([dct])]
            non_matching_keys = {}
        else:
            # normal param
            if va_values:
                values = va_values
            else:
                # No value: Return an empty container
                values = []
                if not keys_only:
                    calling_va = var_args.get_calling_var_args()
                    if calling_va is not None:
                        m = _error_argument_count(func, len(unpacked_va))
                        analysis.add(evaluator,
                                     'type-error-too-few-arguments',
                                     calling_va,
                                     message=m)

        # Now add to result if it's not one of the previously covered cases.
        if (not keys_only or param.stars == 2):
            param_names.append(ExecutedParam(param, var_args, values).name)
            keys_used[unicode(param.get_name())] = param_names[-1]

    if keys_only:
        # All arguments should be handed over to the next function. It's not
        # about the values inside, it's about the names. Jedi needs to now that
        # there's nothing to find for certain names.
        for k in set(param_dict) - set(keys_used):
            param = param_dict[k]
            values = [] if param.default is None else [param.default]
            param_names.append(ExecutedParam(param, var_args, values).name)

            if not (non_matching_keys or had_multiple_value_error
                    or param.stars or param.default):
                # add a warning only if there's not another one.
                calling_va = _get_calling_var_args(evaluator, var_args)
                if calling_va is not None:
                    m = _error_argument_count(func, len(unpacked_va))
                    analysis.add(evaluator,
                                 'type-error-too-few-arguments',
                                 calling_va,
                                 message=m)

    for key, va_values in non_matching_keys.items():
        m = "TypeError: %s() got an unexpected keyword argument '%s'." \
            % (func.name, key)
        for value in va_values:
            analysis.add(evaluator,
                         'type-error-keyword-argument',
                         value.parent,
                         message=m)

    remaining_params = list(var_arg_iterator)
    if remaining_params:
        m = _error_argument_count(func, len(unpacked_va))
        # Just report an error for the first param that is not needed (like
        # cPython).
        first_key, first_values = remaining_params[0]
        for v in first_values:
            if first_key is not None:
                # Is a keyword argument, return the whole thing instead of just
                # the value node.
                v = v.parent
                try:
                    non_kw_param = keys_used[first_key]
                except KeyError:
                    pass
                else:
                    origin_args = non_kw_param.parent.var_args.argument_node
                    # TODO  calculate the var_args tree and check if it's in
                    # the tree (if not continue).
                    # print('\t\tnonkw', non_kw_param.parent.var_args.argument_node, )
                    if origin_args not in [
                            f.parent.parent for f in first_values
                    ]:
                        continue
            analysis.add(evaluator,
                         'type-error-too-many-arguments',
                         v,
                         message=m)
    return param_names
Beispiel #56
0
def get_params(execution_context, var_args):
    result_params = []
    param_dict = {}
    funcdef = execution_context.tree_node
    parent_context = execution_context.parent_context

    for param in funcdef.params:
        param_dict[param.name.value] = param
    unpacked_va = list(var_args.unpack(funcdef))
    var_arg_iterator = common.PushBackIterator(iter(unpacked_va))

    non_matching_keys = defaultdict(lambda: [])
    keys_used = {}
    keys_only = False
    had_multiple_value_error = False
    for param in funcdef.params:
        # The value and key can both be null. There, the defaults apply.
        # args / kwargs will just be empty arrays / dicts, respectively.
        # Wrong value count is just ignored. If you try to test cases that are
        # not allowed in Python, Jedi will maybe not show any completions.
        key, argument = next(var_arg_iterator, (None, None))
        while key is not None:
            keys_only = True
            try:
                key_param = param_dict[key]
            except KeyError:
                non_matching_keys[key] = argument
            else:
                if key in keys_used:
                    had_multiple_value_error = True
                    m = ("TypeError: %s() got multiple values for keyword argument '%s'."
                         % (funcdef.name, key))
                    for node in var_args.get_calling_nodes():
                        analysis.add(parent_context, 'type-error-multiple-values',
                                     node, message=m)
                else:
                    keys_used[key] = ExecutedParam(execution_context, key_param, argument)
            key, argument = next(var_arg_iterator, (None, None))

        try:
            result_params.append(keys_used[param.name.value])
            continue
        except KeyError:
            pass

        if param.star_count == 1:
            # *args param
            lazy_context_list = []
            if argument is not None:
                lazy_context_list.append(argument)
                for key, argument in var_arg_iterator:
                    # Iterate until a key argument is found.
                    if key:
                        var_arg_iterator.push_back((key, argument))
                        break
                    lazy_context_list.append(argument)
            seq = iterable.FakeSequence(execution_context.evaluator, 'tuple', lazy_context_list)
            result_arg = context.LazyKnownContext(seq)
        elif param.star_count == 2:
            # **kwargs param
            dct = iterable.FakeDict(execution_context.evaluator, dict(non_matching_keys))
            result_arg = context.LazyKnownContext(dct)
            non_matching_keys = {}
        else:
            # normal param
            if argument is None:
                # No value: Return an empty container
                if param.default is None:
                    result_arg = context.LazyUnknownContext()
                    if not keys_only:
                        for node in var_args.get_calling_nodes():
                            m = _error_argument_count(funcdef, len(unpacked_va))
                            analysis.add(parent_context, 'type-error-too-few-arguments',
                                         node, message=m)
                else:
                    result_arg = context.LazyTreeContext(parent_context, param.default)
            else:
                result_arg = argument

        result_params.append(ExecutedParam(execution_context, param, result_arg))
        if not isinstance(result_arg, context.LazyUnknownContext):
            keys_used[param.name.value] = result_params[-1]

    if keys_only:
        # All arguments should be handed over to the next function. It's not
        # about the values inside, it's about the names. Jedi needs to now that
        # there's nothing to find for certain names.
        for k in set(param_dict) - set(keys_used):
            param = param_dict[k]

            if not (non_matching_keys or had_multiple_value_error or
                    param.star_count or param.default):
                # add a warning only if there's not another one.
                for node in var_args.get_calling_nodes():
                    m = _error_argument_count(funcdef, len(unpacked_va))
                    analysis.add(parent_context, 'type-error-too-few-arguments',
                                 node, message=m)

    for key, lazy_context in non_matching_keys.items():
        m = "TypeError: %s() got an unexpected keyword argument '%s'." \
            % (funcdef.name, key)
        add_argument_issue(
            parent_context,
            'type-error-keyword-argument',
            lazy_context,
            message=m
        )

    remaining_arguments = list(var_arg_iterator)
    if remaining_arguments:
        m = _error_argument_count(funcdef, len(unpacked_va))
        # Just report an error for the first param that is not needed (like
        # cPython).
        first_key, lazy_context = remaining_arguments[0]
        if var_args.get_calling_nodes():
            # There might not be a valid calling node so check for that first.
            add_argument_issue(parent_context, 'type-error-too-many-arguments', lazy_context, message=m)
    return result_params
Beispiel #57
0
def add_argument_issue(parent_context, error_name, lazy_context, message):
    if isinstance(lazy_context, context.LazyTreeContext):
        node = lazy_context.data
        if node.parent.type == 'argument':
            node = node.parent
        analysis.add(parent_context, error_name, node, message)
Beispiel #58
0
 def get_index_types(self, evaluator, index_array):
     #debug.warning('Tried to get array access on a generator: %s', self)
     analysis.add(self._evaluator, 'type-error-generator', index_array)
     return []
Beispiel #59
0
def _eval_comparison_part(evaluator, context, left, operator, right):
    l_is_num = is_number(left)
    r_is_num = is_number(right)
    if isinstance(operator, unicode):
        str_operator = operator
    else:
        str_operator = force_unicode(str(operator.value))

    if str_operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Sequence) or is_string(left):
            return ContextSet([left])
        elif isinstance(right, iterable.Sequence) or is_string(right):
            return ContextSet([right])
    elif str_operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return ContextSet([left.execute_operation(right, str_operator)])
        elif _is_tuple(left) and _is_tuple(right) or _is_list(
                left) and _is_list(right):
            return ContextSet([iterable.MergedArray(evaluator, (left, right))])
    elif str_operator == '-':
        if l_is_num and r_is_num:
            return ContextSet([left.execute_operation(right, str_operator)])
    elif str_operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return ContextSet([left])
    elif str_operator in COMPARISON_OPERATORS:
        if left.is_compiled() and right.is_compiled():
            # Possible, because the return is not an option. Just compare.
            try:
                return ContextSet(
                    [left.execute_operation(right, str_operator)])
            except TypeError:
                # Could be True or False.
                pass
        else:
            if str_operator in ('is', '!=', '==', 'is not'):
                operation = COMPARISON_OPERATORS[str_operator]
                bool_ = operation(left, right)
                return ContextSet([_bool_to_context(evaluator, bool_)])

            if isinstance(left, VersionInfo):
                version_info = _get_tuple_ints(right)
                if version_info is not None:
                    bool_result = compiled.access.COMPARISON_OPERATORS[
                        operator](evaluator.environment.version_info,
                                  tuple(version_info))
                    return ContextSet(
                        [_bool_to_context(evaluator, bool_result)])

        return ContextSet([
            _bool_to_context(evaluator, True),
            _bool_to_context(evaluator, False)
        ])
    elif str_operator == 'in':
        return NO_CONTEXTS

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, TreeInstance) and \
            obj.name.string_name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if str_operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(context, 'type-error-operation', operator,
                     message % (left, right))

    result = ContextSet([left, right])
    debug.dbg('Used operator %s resulting in %s', operator, result)
    return result
Beispiel #60
0
def _add_error(context, name, message=None):
    # Should be a name, not a string!
    if hasattr(name, 'parent'):
        analysis.add(context, 'import-error', name, message)