예제 #1
0
def get_code_bits(code):
    atok = ASTTokens(code, parse=1)

    for node in ast.walk(atok.tree):
        if isinstance(node, ast.Name):
            if not atok.get_text(node):
                continue
            node_text = node.id
            assert atok.get_text(node) == node_text
            if node_text in builtins.__dict__ or len(node_text) == 1:
                continue
        elif isinstance(node,
                        (ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef)):
            for arg in node.args.args:
                if len(arg.arg) == 1:
                    continue
                yield arg, arg.arg
            node_text = node.name
        elif isinstance(node, (ast.Str, ast.JoinedStr)):
            node_text = atok.get_text(node)
            if not re.search(r"[a-zA-Z]", node_text) or re.match(
                    r"""^['"][a-zA-Z]['"]""", node_text):
                continue
        else:
            continue

        yield node, node_text
예제 #2
0
    def __init__(self, atok: asttokens.ASTTokens, node: ast.Lambda) -> None:
        """
        Initialize.

        :param atok: parsed AST tree and tokens with added positional properties
        :param node: lambda AST node corresponding to the condition
        """
        self.atok = atok
        self.node = node
        self.text = atok.get_text(node.body)
예제 #3
0
def _negate_compare_text(atok: asttokens.ASTTokens, node: ast.Compare) -> str:
    """
    Generate the text representing the negation of the comparison node.

    :param atok:
        parsing obtained with ``asttokens`` so that we can access the last tokens of a node.

        The standard ``ast`` module provides only the first token of an AST node. In lack of concrete syntax tree,
        getting text from first to last token is currently the simplest approach.
    :param node: AST node representing the comparison in a condition
    :return: text representation of the node's negation
    """
    assert len(
        node.ops) == 1, "A single comparison expected, but got: {}".format(
            len(node.ops))
    assert len(node.comparators
               ) == 1, "A single comparator expected, but got: {}".format(
                   len(node.comparators))

    operator = node.ops[0]
    left = node.left
    right = node.comparators[0]

    left_text = atok.get_text(node=left)
    right_text = atok.get_text(node=right)

    text = ''

    if isinstance(operator, ast.Eq):
        text = '{} != {}'.format(left_text, right_text)

    elif isinstance(operator, ast.NotEq):
        text = '{} == {}'.format(left_text, right_text)

    elif isinstance(operator, ast.Lt):
        text = '{} >= {}'.format(left_text, right_text)

    elif isinstance(operator, ast.LtE):
        text = '{} > {}'.format(left_text, right_text)

    elif isinstance(operator, ast.Gt):
        text = '{} <= {}'.format(left_text, right_text)

    elif isinstance(operator, ast.GtE):
        text = '{} < {}'.format(left_text, right_text)

    elif isinstance(operator, ast.Is):
        text = '{} is not {}'.format(left_text, right_text)

    elif isinstance(operator, ast.IsNot):
        text = '{} is {}'.format(left_text, right_text)

    elif isinstance(operator, ast.In):
        text = '{} not in {}'.format(left_text, right_text)

    elif isinstance(operator, ast.NotIn):
        text = '{} in {}'.format(left_text, right_text)

    else:
        raise NotImplementedError(
            "Unhandled comparison operator: {}".format(operator))

    return text
예제 #4
0
def get_all_objects(line, frame):
    """Given a (partial) line of code and a frame,
    obtains a dict containing all the relevant information about objects
    found on that line so that they can be formatted as part of the
    answer to "where()" or they can be used during the analysis
    of the cause of the exception.

    The dict returned has five keys.
    The first three, 'locals', 'globals', 'builtins',
    each containing a list of tuples, each tuple being of the form
    (name, repr(obj), obj) where name --> obj.

    The fourth key, 'expressions', contains a list of tuples of the form
    ('name', obj). It is only occasionally used in helping to make
    suggestions regarding the cause of some exception.
    """
    objects = {
        "locals": [],
        "globals": [],
        "builtins": [],
        "expressions": [],
        "name, obj": [],
    }

    scopes = (
        ("locals", frame.f_locals),  # always have locals before globals
        ("globals", frame.f_globals),
    )

    names = set()

    tokens = token_utils.get_significant_tokens(line)
    for tok in tokens:
        if tok.is_identifier():
            name = tok.string
            if name in names:
                continue
            for scope, scope_dict in scopes:
                if name in scope_dict:
                    names.add(name)
                    obj = scope_dict[name]
                    objects[scope].append((name, repr(obj), obj))
                    objects["name, obj"].append((name, obj))
                    break
            else:
                if name in dir(builtins):
                    names.add(name)
                    obj = getattr(builtins, name)
                    objects["builtins"].append((name, repr(obj), obj))
                    objects["name, obj"].append((name, obj))

    try:
        atok = ASTTokens(line, parse=True)
    except SyntaxError:  # this should not happen
        return objects

    if atok is not None:
        evaluator = Evaluator.from_frame(frame)
        for nodes, obj in group_expressions(
                pair for pair in evaluator.find_expressions(atok.tree)):
            name = atok.get_text(nodes[0])
            if name in names:
                continue
            names.add(name)
            objects["name, obj"].append((name, obj))
            try:
                # We're not interested in showing literals in the list of variables
                ast.literal_eval(name)
            except Exception:  # noqa
                objects["expressions"].append((name, obj))

    return objects
def get_all_objects(line, frame):
    """Given a (partial) line of code and a frame,
    obtains a dict containing all the relevant information about objects
    found on that line so that they can be formatted as part of the
    answer to "where()" or they can be used during the analysis
    of the cause of the exception.

    The dict returned has four keys.
    The first three, 'locals', 'globals', 'nonlocals',
    each containing a list of tuples, each tuple being of the form
    (name, repr(obj), obj) where name --> obj.

    The fourth key, 'literals', contains a list of tuples of the form
    ('name', obj). It is only occasionally used in helping to make
    suggestions regarding the cause of some exception.
    """
    objects = {
        "locals": [],
        "globals": [],
        "literals": [],
        "builtins": [],
        "name, obj": [],
    }

    scopes = (
        ("locals", frame.f_locals),  # always have locals before globals
        ("globals", frame.f_globals),
    )

    names = set([])
    try:
        atok = ASTTokens(line, parse=True)
    except SyntaxError:  # this should not happen
        atok = None

    if atok is not None:
        for scope, scope_dict in scopes:
            for nodes, obj in Evaluator(
                    scope_dict).interesting_expressions_grouped(atok.tree):
                name = atok.get_text(nodes[0])
                if name in names:
                    continue
                names.add(name)
                objects[scope].append((name, repr(obj), obj))
                objects["name, obj"].append((name, obj))

        Evaluator.literal_expressions_grouped = literal_expressions_grouped
        for nodes, obj in Evaluator({}).literal_expressions_grouped(
                atok.tree):  # noqa
            name = atok.get_text(nodes[0])
            objects["literals"].append((name, obj))
            objects["name, obj"].append((name, obj))

    tokens = token_utils.get_significant_tokens(line)
    for tok in tokens:
        if tok.is_identifier():
            name = tok.string
            if name in names:
                continue
            for scope, scope_dict in scopes:
                if name in scope_dict:
                    names.add(name)
                    obj = scope_dict[name]
                    objects[scope].append((name, repr(obj), obj))
                    objects["name, obj"].append((name, obj))
                    break
            else:
                if name in dir(builtins):
                    obj = getattr(builtins, name)
                    objects["builtins"].append((name, repr(obj), obj))
                    objects["name, obj"].append((name, obj))

    dotted_names = get_dotted_names(line)
    for name in dotted_names:
        for scope, scope_dict in scopes:
            if name not in scope_dict:
                continue
            obj = scope_dict[name]
            if (name, obj) not in objects["name, obj"]:
                objects[scope].append((name, repr(obj), obj))
                objects["name, obj"].append((name, obj))

    # TODO: check to see if this is still needed
    objects["nonlocals"] = get_nonlocal_objects(frame)
    return objects