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
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)
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
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