Пример #1
0
def eval_subscript_list(evaluator, context, index):
    """
    Handles slices in subscript nodes.
    """
    if index == ':':
        # Like array[:]
        return ContextSet([iterable.Slice(context, None, None, None)])

    elif index.type == 'subscript' and not index.children[0] == '.':
        # subscript basically implies a slice operation, except for Python 2's
        # Ellipsis.
        # e.g. array[:3]
        result = []
        for el in index.children:
            if el == ':':
                if not result:
                    result.append(None)
            elif el.type == 'sliceop':
                if len(el.children) == 2:
                    result.append(el.children[1])
            else:
                result.append(el)
        result += [None] * (3 - len(result))

        return ContextSet([iterable.Slice(context, *result)])
    elif index.type == 'subscriptlist':
        return ContextSet(
            [iterable.SequenceLiteralContext(evaluator, context, index)])

    # No slices
    return context.eval_node(index)
Пример #2
0
def eval_node(context, element):
    debug.dbg('eval_node %s@%s in %s', element, element.start_pos, context)
    evaluator = context.evaluator
    typ = element.type
    if typ in ('name', 'number', 'string', 'atom', 'strings', 'keyword',
               'fstring'):
        return eval_atom(context, element)
    elif typ == 'lambdef':
        return ContextSet([FunctionContext.from_context(context, element)])
    elif typ == 'expr_stmt':
        return eval_expr_stmt(context, element)
    elif typ in ('power', 'atom_expr'):
        first_child = element.children[0]
        children = element.children[1:]
        had_await = False
        if first_child.type == 'keyword' and first_child.value == 'await':
            had_await = True
            first_child = children.pop(0)

        context_set = context.eval_node(first_child)
        for (i, trailer) in enumerate(children):
            if trailer == '**':  # has a power operation.
                right = context.eval_node(children[i + 1])
                context_set = _eval_comparison(evaluator, context, context_set,
                                               trailer, right)
                break
            context_set = eval_trailer(context, context_set, trailer)

        if had_await:
            return context_set.py__await__().py__stop_iteration_returns()
        return context_set
    elif typ in (
            'testlist_star_expr',
            'testlist',
    ):
        # The implicit tuple in statements.
        return ContextSet(
            [iterable.SequenceLiteralContext(evaluator, context, element)])
    elif typ in ('not_test', 'factor'):
        context_set = context.eval_node(element.children[-1])
        for operator in element.children[:-1]:
            context_set = eval_factor(context_set, operator)
        return context_set
    elif typ == 'test':
        # `x if foo else y` case.
        return (context.eval_node(element.children[0])
                | context.eval_node(element.children[-1]))
    elif typ == 'operator':
        # Must be an ellipsis, other operators are not evaluated.
        # In Python 2 ellipsis is coded as three single dot tokens, not
        # as one token 3 dot token.
        if element.value not in ('.', '...'):
            origin = element.parent
            raise AssertionError("unhandled operator %s in %s " %
                                 (repr(element.value), origin))
        return ContextSet([compiled.builtin_from_name(evaluator, u'Ellipsis')])
    elif typ == 'dotted_name':
        context_set = eval_atom(context, element.children[0])
        for next_name in element.children[2::2]:
            # TODO add search_global=True?
            context_set = context_set.py__getattribute__(next_name,
                                                         name_context=context)
        return context_set
    elif typ == 'eval_input':
        return eval_node(context, element.children[0])
    elif typ == 'annassign':
        return annotation.eval_annotation(context, element.children[1]) \
            .execute_annotation()
    elif typ == 'yield_expr':
        if len(element.children) and element.children[1].type == 'yield_arg':
            # Implies that it's a yield from.
            element = element.children[1].children[1]
            generators = context.eval_node(element) \
                .py__getattribute__('__iter__').execute_evaluated()
            return generators.py__stop_iteration_returns()

        # Generator.send() is not implemented.
        return NO_CONTEXTS
    elif typ == 'namedexpr_test':
        return eval_node(context, element.children[2])
    else:
        return eval_or_test(context, element)
Пример #3
0
def eval_atom(context, atom):
    """
    Basically to process ``atom`` nodes. The parser sometimes doesn't
    generate the node (because it has just one child). In that case an atom
    might be a name or a literal as well.
    """
    if atom.type == 'name':
        if atom.value in ('True', 'False', 'None'):
            # Python 2...
            return ContextSet(
                [compiled.builtin_from_name(context.evaluator, atom.value)])

        # This is the first global lookup.
        stmt = tree.search_ancestor(atom, 'expr_stmt', 'lambdef') or atom
        if stmt.type == 'lambdef':
            stmt = atom
        position = stmt.start_pos
        if _is_annotation_name(atom):
            # Since Python 3.7 (with from __future__ import annotations),
            # annotations are essentially strings and can reference objects
            # that are defined further down in code. Therefore just set the
            # position to None, so the finder will not try to stop at a certain
            # position in the module.
            position = None
        return context.py__getattribute__(name_or_str=atom,
                                          position=position,
                                          search_global=True)
    elif atom.type == 'keyword':
        # For False/True/None
        if atom.value in ('False', 'True', 'None'):
            return ContextSet(
                [compiled.builtin_from_name(context.evaluator, atom.value)])
        elif atom.value == 'print':
            # print e.g. could be evaluated like this in Python 2.7
            return NO_CONTEXTS
        elif atom.value == 'yield':
            # Contrary to yield from, yield can just appear alone to return a
            # value when used with `.send()`.
            return NO_CONTEXTS
        assert False, 'Cannot evaluate the keyword %s' % atom

    elif isinstance(atom, tree.Literal):
        string = context.evaluator.compiled_subprocess.safe_literal_eval(
            atom.value)
        return ContextSet(
            [compiled.create_simple_object(context.evaluator, string)])
    elif atom.type == 'strings':
        # Will be multiple string.
        context_set = eval_atom(context, atom.children[0])
        for string in atom.children[1:]:
            right = eval_atom(context, string)
            context_set = _eval_comparison(context.evaluator, context,
                                           context_set, u'+', right)
        return context_set
    elif atom.type == 'fstring':
        return compiled.get_string_context_set(context.evaluator)
    else:
        c = atom.children
        # Parentheses without commas are not tuples.
        if c[0] == '(' and not len(c) == 2 \
                and not(c[1].type == 'testlist_comp' and
                        len(c[1].children) > 1):
            return context.eval_node(c[1])

        try:
            comp_for = c[1].children[1]
        except (IndexError, AttributeError):
            pass
        else:
            if comp_for == ':':
                # Dict comprehensions have a colon at the 3rd index.
                try:
                    comp_for = c[1].children[3]
                except IndexError:
                    pass

            if comp_for.type in ('comp_for', 'sync_comp_for'):
                return ContextSet([
                    iterable.comprehension_from_atom(context.evaluator,
                                                     context, atom)
                ])

        # It's a dict/list/tuple literal.
        array_node = c[1]
        try:
            array_node_c = array_node.children
        except AttributeError:
            array_node_c = []
        if c[0] == '{' and (array_node == '}' or ':' in array_node_c
                            or '**' in array_node_c):
            context = iterable.DictLiteralContext(context.evaluator, context,
                                                  atom)
        else:
            context = iterable.SequenceLiteralContext(context.evaluator,
                                                      context, atom)
        return ContextSet([context])
Пример #4
0
def eval_node(context, element):
    debug.dbg('eval_element %s@%s', element, element.start_pos)
    evaluator = context.evaluator
    typ = element.type
    if typ in ('name', 'number', 'string', 'atom'):
        return eval_atom(context, element)
    elif typ == 'keyword':
        # For False/True/None
        if element.value in ('False', 'True', 'None'):
            return ContextSet(
                compiled.builtin_from_name(evaluator, element.value))
        # else: print e.g. could be evaluated like this in Python 2.7
        return NO_CONTEXTS
    elif typ == 'lambdef':
        return ContextSet(FunctionContext(evaluator, context, element))
    elif typ == 'expr_stmt':
        return eval_expr_stmt(context, element)
    elif typ in ('power', 'atom_expr'):
        first_child = element.children[0]
        if not (first_child.type == 'keyword'
                and first_child.value == 'await'):
            context_set = eval_atom(context, first_child)
            for trailer in element.children[1:]:
                if trailer == '**':  # has a power operation.
                    right = evaluator.eval_element(context,
                                                   element.children[2])
                    context_set = _eval_comparison(evaluator, context,
                                                   context_set, trailer, right)
                    break
                context_set = eval_trailer(context, context_set, trailer)
            return context_set
        return NO_CONTEXTS
    elif typ in (
            'testlist_star_expr',
            'testlist',
    ):
        # The implicit tuple in statements.
        return ContextSet(
            iterable.SequenceLiteralContext(evaluator, context, element))
    elif typ in ('not_test', 'factor'):
        context_set = context.eval_node(element.children[-1])
        for operator in element.children[:-1]:
            context_set = eval_factor(context_set, operator)
        return context_set
    elif typ == 'test':
        # `x if foo else y` case.
        return (context.eval_node(element.children[0])
                | context.eval_node(element.children[-1]))
    elif typ == 'operator':
        # Must be an ellipsis, other operators are not evaluated.
        # In Python 2 ellipsis is coded as three single dot tokens, not
        # as one token 3 dot token.
        assert element.value in ('.', '...')
        return ContextSet(compiled.create(evaluator, Ellipsis))
    elif typ == 'dotted_name':
        context_set = eval_atom(context, element.children[0])
        for next_name in element.children[2::2]:
            # TODO add search_global=True? id:489 gh:490
            context_set = context_set.py__getattribute__(next_name,
                                                         name_context=context)
        return context_set
    elif typ == 'eval_input':
        return eval_node(context, element.children[0])
    elif typ == 'annassign':
        return pep0484._evaluate_for_annotation(context, element.children[1])
    else:
        return eval_or_test(context, element)
Пример #5
0
def eval_atom(context, atom):
    """
    Basically to process ``atom`` nodes. The parser sometimes doesn't
    generate the node (because it has just one child). In that case an atom
    might be a name or a literal as well.
    """
    if atom.type == 'name':
        # This is the first global lookup.
        stmt = tree.search_ancestor(atom, 'expr_stmt', 'lambdef') or atom
        if stmt.type == 'lambdef':
            stmt = atom
        return context.py__getattribute__(name_or_str=atom,
                                          position=stmt.start_pos,
                                          search_global=True)

    elif isinstance(atom, tree.Literal):
        string = parser_utils.safe_literal_eval(atom.value)
        return ContextSet(compiled.create(context.evaluator, string))
    else:
        c = atom.children
        if c[0].type == 'string':
            # Will be one string.
            context_set = eval_atom(context, c[0])
            for string in c[1:]:
                right = eval_atom(context, string)
                context_set = _eval_comparison(context.evaluator, context,
                                               context_set, '+', right)
            return context_set
        # Parentheses without commas are not tuples.
        elif c[0] == '(' and not len(c) == 2 \
                and not(c[1].type == 'testlist_comp' and
                        len(c[1].children) > 1):
            return context.eval_node(c[1])

        try:
            comp_for = c[1].children[1]
        except (IndexError, AttributeError):
            pass
        else:
            if comp_for == ':':
                # Dict comprehensions have a colon at the 3rd index.
                try:
                    comp_for = c[1].children[3]
                except IndexError:
                    pass

            if comp_for.type == 'comp_for':
                return ContextSet(
                    iterable.Comprehension.from_atom(context.evaluator,
                                                     context, atom))

        # It's a dict/list/tuple literal.
        array_node = c[1]
        try:
            array_node_c = array_node.children
        except AttributeError:
            array_node_c = []
        if c[0] == '{' and (array_node == '}' or ':' in array_node_c):
            context = iterable.DictLiteralContext(context.evaluator, context,
                                                  atom)
        else:
            context = iterable.SequenceLiteralContext(context.evaluator,
                                                      context, atom)
        return ContextSet(context)
Пример #6
0
def eval_node(context, element):
    debug.dbg('eval_element %s@%s', element, element.start_pos)
    evaluator = context.evaluator
    typ = element.type
    if typ in ('name', 'number', 'string', 'atom'):
        return eval_atom(context, element)
    elif typ == 'keyword':
        # For False/True/None
        if element.value in ('False', 'True', 'None'):
            return ContextSet(compiled.builtin_from_name(evaluator, element.value))
        # else: print e.g. could be evaluated like this in Python 2.7
        return NO_CONTEXTS
    elif typ == 'lambdef':
        return ContextSet(FunctionContext(evaluator, context, element))
    elif typ == 'expr_stmt':
        return eval_expr_stmt(context, element)
    elif typ in ('power', 'atom_expr'):
        first_child = element.children[0]
        children = element.children[1:]
        had_await = False
        if first_child.type == 'keyword' and first_child.value == 'await':
            had_await = True
            first_child = children.pop(0)

        context_set = eval_atom(context, first_child)
        for trailer in children:
            if trailer == '**':  # has a power operation.
                right = evaluator.eval_element(context, children[1])
                context_set = _eval_comparison(
                    evaluator,
                    context,
                    context_set,
                    trailer,
                    right
                )
                break
            context_set = eval_trailer(context, context_set, trailer)

        if had_await:
            await_context_set = context_set.py__getattribute__(u"__await__")
            if not await_context_set:
                debug.warning('Tried to run py__await__ on context %s', context)
            context_set = ContextSet()
            return _py__stop_iteration_returns(await_context_set.execute_evaluated())
        return context_set
    elif typ in ('testlist_star_expr', 'testlist',):
        # The implicit tuple in statements.
        return ContextSet(iterable.SequenceLiteralContext(evaluator, context, element))
    elif typ in ('not_test', 'factor'):
        context_set = context.eval_node(element.children[-1])
        for operator in element.children[:-1]:
            context_set = eval_factor(context_set, operator)
        return context_set
    elif typ == 'test':
        # `x if foo else y` case.
        return (context.eval_node(element.children[0]) |
                context.eval_node(element.children[-1]))
    elif typ == 'operator':
        # Must be an ellipsis, other operators are not evaluated.
        # In Python 2 ellipsis is coded as three single dot tokens, not
        # as one token 3 dot token.
        assert element.value in ('.', '...'), "The unhandled operator %s" % repr(element.value)
        return ContextSet(compiled.builtin_from_name(evaluator, u'Ellipsis'))
    elif typ == 'dotted_name':
        context_set = eval_atom(context, element.children[0])
        for next_name in element.children[2::2]:
            # TODO add search_global=True?
            context_set = context_set.py__getattribute__(next_name, name_context=context)
        return context_set
    elif typ == 'eval_input':
        return eval_node(context, element.children[0])
    elif typ == 'annassign':
        return pep0484._evaluate_for_annotation(context, element.children[1])
    elif typ == 'yield_expr':
        if len(element.children) and element.children[1].type == 'yield_arg':
            # Implies that it's a yield from.
            element = element.children[1].children[1]
            generators = context.eval_node(element)
            return _py__stop_iteration_returns(generators)

        # Generator.send() is not implemented.
        return NO_CONTEXTS
    else:
        return eval_or_test(context, element)
Пример #7
0
def eval_atom(context, atom):
    """
    Basically to process ``atom`` nodes. The parser sometimes doesn't
    generate the node (because it has just one child). In that case an atom
    might be a name or a literal as well.
    """
    if atom.type == 'name':
        # This is the first global lookup.
        stmt = tree.search_ancestor(atom, 'expr_stmt', 'lambdef') or atom
        if stmt.type == 'lambdef':
            stmt = atom
        return context.py__getattribute__(name_or_str=atom,
                                          position=stmt.start_pos,
                                          search_global=True)
    elif atom.type == 'keyword':
        # For False/True/None
        if atom.value in ('False', 'True', 'None'):
            return ContextSet(
                compiled.builtin_from_name(context.evaluator, atom.value))
        if atom.value == 'print':
            # print e.g. could be evaluated like this in Python 2.7
            return NO_CONTEXTS
        assert False, 'Cannot evaluate the keyword %s' % atom

    elif isinstance(atom, tree.Literal):
        string = context.evaluator.compiled_subprocess.safe_literal_eval(
            atom.value)
        return ContextSet(
            compiled.create_simple_object(context.evaluator, string))
    elif atom.type == 'strings':
        # Will be multiple string.
        context_set = eval_atom(context, atom.children[0])
        for string in atom.children[1:]:
            right = eval_atom(context, string)
            context_set = _eval_comparison(context.evaluator, context,
                                           context_set, u'+', right)
        return context_set
    else:
        c = atom.children
        # Parentheses without commas are not tuples.
        if c[0] == '(' and not len(c) == 2 \
                and not(c[1].type == 'testlist_comp' and
                        len(c[1].children) > 1):
            return context.eval_node(c[1])

        try:
            comp_for = c[1].children[1]
        except (IndexError, AttributeError):
            pass
        else:
            if comp_for == ':':
                # Dict comprehensions have a colon at the 3rd index.
                try:
                    comp_for = c[1].children[3]
                except IndexError:
                    pass

            if comp_for.type == 'comp_for':
                return ContextSet(
                    iterable.comprehension_from_atom(context.evaluator,
                                                     context, atom))

        # It's a dict/list/tuple literal.
        array_node = c[1]
        try:
            array_node_c = array_node.children
        except AttributeError:
            array_node_c = []
        if c[0] == '{' and (array_node == '}' or ':' in array_node_c):
            context = iterable.DictLiteralContext(context.evaluator, context,
                                                  atom)
        else:
            context = iterable.SequenceLiteralContext(context.evaluator,
                                                      context, atom)
        return ContextSet(context)