def is_async_fn(node): code_node = node[0][0] for n in node[0]: if hasattr(n, "attr") and iscode(n.attr): code_node = n break pass pass is_code = hasattr(code_node, "attr") and iscode(code_node.attr) return is_code and co_flags_is_async(code_node.attr.co_flags)
def listcomp_closure3(node): """List comprehensions in Python 3 when handled as a closure. See if we can combine code. """ p = self.prec self.prec = 27 code_obj = node[1].attr assert iscode(code_obj) code = Code(code_obj, self.scanner, self.currentclass) ast = self.build_ast(code._tokens, code._customize) self.customize(code._customize) # skip over: sstmt, stmt, return, ret_expr # and other singleton derivations while len(ast) == 1 or (ast in ("sstmt", "return") and ast[-1] in ("RETURN_LAST", "RETURN_VALUE")): self.prec = 100 ast = ast[0] n = ast[1] # collections is the name of the expression(s) we are iterating over collections = [node[-3]] list_ifs = [] if self.version == 3.0 and n != "list_iter": # FIXME 3.0 is a snowflake here. We need # special code for this. Not sure if this is totally # correct. stores = [ast[3]] assert ast[4] == "comp_iter" n = ast[4] # Find the list comprehension body. It is the inner-most # node that is not comp_.. . while n == "comp_iter": if n[0] == "comp_for": n = n[0] stores.append(n[2]) n = n[3] elif n[0] in ("comp_if", "comp_if_not"): n = n[0] # FIXME: just a guess if n[0].kind == "expr": list_ifs.append(n) else: list_ifs.append([1]) n = n[2] pass else: break pass # Skip over n[0] which is something like: _[1] self.preorder(n[1]) else: assert n == "list_iter" stores = [] # Find the list comprehension body. It is the inner-most # node that is not list_.. . while n == "list_iter": # recurse one step n = n[0] if n == "list_for": stores.append(n[2]) n = n[3] if n[0] == "list_for": # Dog-paddle down largely singleton reductions # to find the collection (expr) c = n[0][0] if c == "expr": c = c[0] # FIXME: grammar is wonky here? Is this really an attribute? if c == "attribute": c = c[0] collections.append(c) pass elif n in ("list_if", "list_if_not"): # FIXME: just a guess if n[0].kind == "expr": list_ifs.append(n) else: list_ifs.append([1]) n = n[2] pass elif n == "list_if37": list_ifs.append(n) n = n[-1] pass elif n == "list_afor": collections.append(n[0][0]) n = n[1] stores.append(n[1][0]) n = n[3] pass assert n == "lc_body", ast self.preorder(n[0]) # FIXME: add indentation around "for"'s and "in"'s n_colls = len(collections) for i, store in enumerate(stores): if i >= n_colls: break if collections[i] == "LOAD_DEREF" and co_flags_is_async( code_obj.co_flags): self.write(" async") pass self.write(" for ") self.preorder(store) self.write(" in ") self.preorder(collections[i]) if i < len(list_ifs): self.preorder(list_ifs[i]) pass pass self.prec = p