def _split_arguments(self, arglist): res = None for i, arg in enumerate(arglist.children): if arg.type == token.COMMA: res = i break remaining_args = [] if res is not None: first_arg = [String(arg) for arg in arglist.children[:res]] if len(first_arg) >= 2: if first_arg[0].value == 'path' and first_arg[1].value == '=': first_arg = first_arg[2:] for i, z in enumerate(arglist.children[res + 1:]): if i <= 1: z.prefix = "" else: z.prefix = " " remaining_args.append(String(z)) else: arg = String(arglist) # Drop `path=` if isinstance(arg, Leaf) and len( arg.value.children ) >= 3 and arg.value.children[0].value == 'path': arg.value.children = arg.value.children[2:] first_arg = [arg] return first_arg, remaining_args
def transform(self, node, results): method = results['method'][0].value explain = None if method in TWO_ARGS: assert len(results['args'][0].children) in (3, 5) left, _, right = results['args'][0].children[:3] left.prefix = ' ' left.changed() right.prefix = ' ' right.changed() comparasion = String(TWO_ARGS[method]) comparasion.prefix = ' ' if len(results['args'][0].children) > 3: explain = results['args'][0].children[4] output = [left, comparasion, right] elif method in ONE_ARG: if results['args'][0].type != syms.arglist: # Only one argument passed args = [results['args'][0]] else: args = results['args'][0].children args[0].prefix = ' ' args[0].changed() if method == 'assertTrue': output = [args[0]] elif method == 'assertFalse': output = [String(' not'), args[0]] elif method == 'assert200': output = [args[0], String('.status_code == 200')] elif method == 'assert400': output = [args[0], String('.status_code == 400')] elif method == 'assertIsNotNone': output = [args[0], String(' is not None')] elif method == 'assertIsNone': output = [args[0], String(' is None')] if len(args) > 1: explain = args[2] if explain: explain.prefix = ' ' explain.changed() output += [String(','), explain] return [String(results['node'].prefix + 'assert')] + output
def transform(self, node, results): params_rawlist = results[u"params"] for i, item in enumerate(params_rawlist): if item.type == token.STAR: params_rawlist = params_rawlist[i:] break else: return # params is guaranteed to be a list starting with *. # if fixing is needed, there will be at least 3 items in this list: # [STAR, COMMA, NAME] is the minimum that we need to worry about. new_kwargs = needs_fixing(params_rawlist) # new_kwargs is the name of the kwargs dictionary. if not new_kwargs: return suitify(node) # At this point, params_rawlist is guaranteed to be a list # beginning with a star that includes at least one keyword-only param # e.g., [STAR, NAME, COMMA, NAME, COMMA, DOUBLESTAR, NAME] or # [STAR, COMMA, NAME], or [STAR, COMMA, NAME, COMMA, DOUBLESTAR, NAME] # Anatomy of a funcdef: ['def', 'name', parameters, ':', suite] # Anatomy of that suite: [NEWLINE, INDENT, first_stmt, all_other_stmts] # We need to insert our new stuff before the first_stmt and change the # first_stmt's prefix. suite = node.children[4] first_stmt = suite.children[2] ident = indentation(first_stmt) for name, default_value in gen_params(params_rawlist): if default_value is None: suite.insert_child(2, Newline()) suite.insert_child(2, String(_assign_template %{u'name':name, u'kwargs':new_kwargs}, prefix=ident)) else: suite.insert_child(2, Newline()) suite.insert_child(2, String(_else_template %{u'name':name, u'default':default_value}, prefix=ident)) suite.insert_child(2, Newline()) suite.insert_child(2, String(_if_template %{u'assign':_assign_template %{u'name':name, u'kwargs':new_kwargs}, u'name':name, u'kwargs':new_kwargs}, prefix=ident)) first_stmt.prefix = ident suite.children[2].prefix = u"" # Now, we need to fix up the list of params. must_add_kwargs = remove_params(params_rawlist) if must_add_kwargs: arglist = results[u'arglist'] if len(arglist.children) > 0 and arglist.children[-1].type != token.COMMA: arglist.append_child(Comma()) arglist.append_child(DoubleStar(prefix=u" ")) arglist.append_child(Name(new_kwargs))
def transform(self, node, results): singleton = results.get("one_dec") classdef = results["cls"] decs = [results["one_dec"] ] if results.get("one_dec") is not None else results["decs"] dec_strings = [str(dec).strip()[1:] for dec in decs] assign = "" for dec in dec_strings: assign += dec assign += "(" assign += results["name"].value for dec in dec_strings: assign += ")" assign = String(results["name"].value + " = " + assign) assign_statement = Node( syms.simple_stmt, [assign, Newline(), Newline()]) prefix = None for dec in decs: if prefix is None: prefix = dec.prefix dec.remove() classdef.prefix = prefix i = indentation(node) pos = node.children.index(classdef) + 1 if classdef.children[-1].children[-1].type == token.DEDENT: del classdef.children[-1].children[-1] node.insert_child(pos, Leaf(token.INDENT, i)) node.insert_child(pos, assign_statement) node.insert_child(pos, Leaf(token.INDENT, i))
def transform(self, node, results): if 'object' in results: # If dotted access: unc.uarray() args = node.children[2] else: args = node.children[1] if 'args' in results: # Non-tuple argument # A star will be inserted in from of the single argument: # ! The following keeps spaces in front of the argument, # if any (but this is safer than adding forcefully a star # in front of the value of the argument: the argument can # be a name (where it works), but also anything else, # including a lib2to3.pytree.Node that has no value.) This # is OK, as the syntax f(* (2, 1)) is valid. args_node = results['args'] # We must make sure that there is a single argument: if args_node.type == syms.arglist: return # Nothing modified # Single argument (in position 1): new_args = [String('*'), args.children[1].clone()] else: # Tuple argument # New arguments: new_args = [results['arg0'].clone(), Comma(), results['arg1'].clone()] # Argument list update: args.replace(ArgList(new_args))
def transform(self, node, results): u""" Call __builtins__.long() with the value and the base of the value. This works because 0b10 is int("10", 2), 0o10 is int("10", 8), etc. """ val = node.value base_ = base(val) if base_ == 8: assert val.strip().startswith(u"0o") or \ val.strip().startswith( u"0O"), u"Invalid format for octal literal" node.changed() node.value = u"".join((u"0", val[2:])) elif base_ == 2: assert val.startswith(u"0") and val[1] in u"bB", \ u"Invalid format for binary literal" # __builtins__.long func_name = Node(syms.power, Attr(Name(u"__builtins__"), Name(u"long"))) # ("...", 2) func_args = [ String(u"".join((u"\"", val.strip()[2:], u"\""))), Comma(), Number(2, prefix=u" ") ] new_node = Call(func_name, func_args, node.prefix) return new_node
def transform(self, node, results): assert results bare_print = results.get("bare") if bare_print: # Special-case print all by itself. bare_print.replace( Call(Name(u"print"), [], prefix=bare_print.prefix)) # The "from __future__ import print_function"" declaration is added # by the fix_print_with_import fixer, so we skip it here. # add_future(node, u'print_function') return assert node.children[0] == Name(u"print") args = node.children[1:] if len(args) == 1 and parend_expr.match(args[0]): # We don't want to keep sticking parens around an # already-parenthesised expression. return sep = end = file = None if args and args[-1] == Comma(): args = args[:-1] end = " " if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, u">>"): assert len(args) >= 2 file = args[1].clone() args = args[3:] # Strip a possible comma after the file expression # Now synthesize a print(args, sep=..., end=..., file=...) node. l_args = [arg.clone() for arg in args] if l_args: l_args[0].prefix = u"" if sep is not None or end is not None or file is not None: if sep is not None: self.add_kwarg(l_args, u"sep", String(repr(sep))) if end is not None: self.add_kwarg(l_args, u"end", String(repr(end))) if file is not None: self.add_kwarg(l_args, u"file", file) n_stmt = Call(Name(u"print"), l_args) n_stmt.prefix = node.prefix # Note that there are corner cases where adding this future-import is # incorrect, for example when the file also has a 'print ()' statement # that was intended to print "()". # add_future(node, u'print_function') return n_stmt
def transform(self, func_node, results): #new = func_node.clone() new = func_node _debug('transform(): Started for function ' + lined(self.def_name)) indent = "" if len(self.comments) == 0: self.reset_state() return new for child in new.children: if child.type == self.syms.suite: suite_node = child _debug("Found suite! Indent is |" + indent + "|") found_ind = False for cc2 in suite_node.children: # Need to skip first NEWLINE token if found_ind is False: if cc2.type == token.INDENT: indent = cc2.value # Preserve correct indent _debug("In suite.children! Updated indent to |" + indent + "|") found_ind = True else: func_name = self.get_func_name(func_node) comm_struct = self.comments[0] curr_comments = comm_struct.comments if func_name not in comm_struct.no_funcs: if self.re_hash_space.search(curr_comments): indented_text = curr_comments.replace( '# ', indent) else: indented_text = curr_comments.replace( '\n ', '\n' + indent) indented_text = self.format_docstring( func_name, indented_text, indent) comments = (indent + '""" ' + indented_text + '\n' + indent + '"""') suite_children = [String(comments), Newline()] suite_node.insert_child( 1, pytree.Node(syms.simple_stmt, suite_children)) self.comments.pop(0) else: # If comment was found after current func, we want # to keep it for the next function, else restore if comm_struct.func_name != func_name: self.restore_last_comment() self.reset_state() return func_node break _debug("Breaking outer for-loop after suite") break _debug("New node would be |" + str(new) + "|") self.reset_state() return new
def transform(self, node, results): func = results['func'] touch_import(None, 'collections', node=node) args = [func.clone(), String(', ')] args.extend(Attr(Name('collections'), Name('Callable'))) return Call(Name('isinstance'), args, prefix=node.prefix)
def _handle_import(self, node, results): y = node if len(node.children) >= 1 and node.children[1]: if isinstance(results['imp'], Leaf) and results['imp'].value in ['os', 'os.path']: y.append_child(String("\nfrom pathlib import Path")) return y
def _handle_no_args(self, node, method_name): if method_name == "getcwd": method_name = "cwd" if method_name == "listdir": return Call(Name('list'), [Call(Name('Path(".").glob'), args=[String('"*"')])], prefix=node.prefix) return Call(Name('Path.{}'.format(method_name)), prefix=node.prefix)
def transform(self, node, results): syms = self.syms exc = results['exc'].clone() if 'exc' in results else None val = results['val'].clone() if 'val' in results else None tb = results['tb'].clone() if 'tb' in results else None exc.prefix = ' ' #Change Error() to Error, if there are no arguments to pass in. try: if len(exc.children[1].children) == 2: exc = String(exc.children[0]) except IndexError: pass if tb and val: exc.prefix = '' args = [exc] args.append(String(", ")) args.append(val) args.append(String(", ")) args.append(tb) raise_stmt = Call(Name("six.reraise"), args) raise_stmt.prefix = node.prefix return raise_stmt elif val: val.prefix = '' val = [val] raise_stmt = pytree.Node(syms.raise_stmt, [Name("raise"), Call(exc, val)]) else: raise_stmt = pytree.Node(syms.raise_stmt, [Name("raise"), String(exc)]) raise_stmt.prefix = node.prefix return raise_stmt
def transform(self, node, results): assert results bare_print = results.get("bare") if bare_print: # Special-case print all by itself bare_print.replace( Call(Name(u"print"), [], prefix=bare_print.prefix)) return assert node.children[0] == Name(u"print") args = node.children[1:] if len(args) == 1 and parend_expr.match(args[0]): # We don't want to keep sticking parens around an # already-parenthesised expression. return sep = end = file = None if args and args[-1] == Comma(): args = args[:-1] end = " " if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, u">>"): assert len(args) >= 2 file = args[1].clone() args = args[3:] # Strip a possible comma after the file expression # Now synthesize a print(args, sep=..., end=..., file=...) node. l_args = [arg.clone() for arg in args] if l_args: l_args[0].prefix = u"" if sep is not None or end is not None or file is not None: if sep is not None: self.add_kwarg(l_args, u"sep", String(repr(sep))) if end is not None: self.add_kwarg(l_args, u"end", String(repr(end))) if file is not None: self.add_kwarg(l_args, u"file", file) n_stmt = Call(Name(u"print"), l_args) n_stmt.prefix = node.prefix add_future(node, u'print_function') return n_stmt
def RaisesOp(context, exceptionClass, indent, kws, arglist, node): exceptionClass.prefix = "" args = [exceptionClass] # Add match keyword arg to with statement if an expected regex was provided. # In py27 the keyword is `expected_regexp`, in py3 is `expected_regex` if 'expected_regex' in kws or 'expected_regexp' in kws: expected_regex = kws.get('expected_regex', kws.get('expected_regexp')).clone() expected_regex.prefix = '' args.append(String(', ')) args.append(KeywordArg(Name('match'), expected_regex)) with_item = Call(Name(context), args) with_item.prefix = " " args = [] arglist = [a.clone() for a in arglist.children[4:]] if arglist: arglist[0].prefix = "" func = None # :fixme: this uses hardcoded parameter names, which may change if 'callableObj' in kws: func = kws['callableObj'] elif 'callable_obj' in kws: func = kws['callable_obj'] elif kws['args']: # any arguments assigned to `*args` func = kws['args'][0] else: func = None if func is None: # Context manager return Node(syms.with_stmt, [with_item]) if func.type == syms.lambdef: suite = func.children[-1].clone() else: # TODO: Newlines within arguments are not handled yet. # If argment prefix contains a newline, all whitespace around this # ought to be replaced by indent plus 4+1+len(func) spaces. suite = Call(func, arglist) suite.prefix = indent + (4 * " ") return Node( syms.with_stmt, [Name('with'), with_item, Name(':'), Newline(), suite])
def finish_tree(self, tree, filename): if not self._names: return names = [Leaf(token.LBRACE, "[", prefix=" "), Newline()] for name in self._names: names.append(String('"' + name + '"', prefix=" ")) names.append(Comma()) names.append(Newline()) names.append(Leaf(token.LBRACE, "]", prefix="")) tree.append_child(Assign(Name("__all__"), names)) tree.append_child(Newline()) super(FixAllAttribute, self).finish_tree(tree, filename)
def transform(self, node, results): assert results syms = self.syms anchor = results["anchor"] # There are 2 types of nodes in the AST - Node and Leaf. # Leaf nodes have a prefix and suffix that are meant for whitespaces and comments. # It usually suffices to use the prefix only as the prefix of a node is the suffix # of its previous node. prefix = node.prefix # before is the identifier that precedes the '.' before the 'None'. before = [n.clone() for n in results["before"]] if len(before) == 1: before = before[0] else: before = pytree.Node(syms.power, before) noneKeywd = String(repr("None")) l_args = [before, Comma(), noneKeywd] if l_args: l_args[0].prefix = u"" l_args[2].prefix = u" " new = Call(Name(u"getattr"), l_args) new.prefix = prefix return new
def _create_logging_call(self, log_call_args, node): try: len_log_call_args = len(log_call_args) if (len_log_call_args == 1 and log_call_args[0].type == syms.atom and log_call_args[0].children[0].type == token.LPAR and log_call_args[0].children[2].type == token.RPAR): candidate = log_call_args[0].children[1] log_call_args = candidate.children if \ candidate.type == syms.testlist_gexp else [candidate] len_log_call_args = len(log_call_args) string_args = self._literal_string_args(log_call_args) len_log_call_args = len(log_call_args) if not string_args and len_log_call_args > 1: log_call_args.extend( [Leaf(token.COMMA, ','), Leaf(token.STRING, "''")]) string_args = self._literal_string_args(log_call_args) if string_args: aggregation_string_args = deque() index, leaf = string_args[0] if leaf.type == syms.term: string_args = leaf.children[2] if is_tuple(string_args): _string_args = [ c for c in string_args.children[1].children ] aggregation_string_args.extend( [Leaf(token.COMMA, ',')] + _string_args) else: aggregation_string_args.extend( [Leaf(token.COMMA, ','), string_args]) leaf = leaf.children[0] lead, aggregation_string, trail = _get_string_contents( leaf.value) aggregation_string = _thingy(aggregation_string, aggregation_string_args, log_call_args[index + 1:]) aggregation_string = _thingy(aggregation_string, aggregation_string_args, log_call_args[:index], prepend=True) if (len(aggregation_string_args) > 2 and token.COMMA == aggregation_string_args[-1].type): aggregation_string_args.pop() for arg in aggregation_string_args: arg.prefix = ' ' if arg.type != token.COMMA else '' log_call_args = [ String(''.join([lead, aggregation_string, trail])) ] + [a.clone() for a in aggregation_string_args] new_node = Call(Name(u"%s.info" % LOGGER_NAME), [a.clone() for a in log_call_args], prefix=node.prefix) touch_import(None, 'logging', node) add_global_assignment_after_imports(LOGGER_NAME, LOGGER_GET.clone(), node) except Exception: logger.exception('Node is:%s', node) raise return new_node
def transform(self, node, results): arg = results["arg"] node.replace(String('u' + arg.value, prefix=node.prefix))
def transform(self, node, results): if not has_metaclass(node): return fixup_parse_tree(node) # find metaclasses, keep the last one last_metaclass = None for suite, i, stmt in find_metas(node): last_metaclass = stmt stmt.remove() text_type = node.children[0].type # always Leaf(nnn, 'class') # figure out what kind of classdef we have if len(node.children) == 7: # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite]) # 0 1 2 3 4 5 6 if node.children[3].type == syms.arglist: arglist = node.children[3] # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite]) else: parent = node.children[3].clone() arglist = Node(syms.arglist, [parent]) node.set_child(3, arglist) elif len(node.children) == 6: # Node(classdef, ['class', 'name', '(', ')', ':', suite]) # 0 1 2 3 4 5 arglist = Node(syms.arglist, []) node.insert_child(3, arglist) elif len(node.children) == 4: # Node(classdef, ['class', 'name', ':', suite]) # 0 1 2 3 arglist = Node(syms.arglist, []) node.insert_child(2, Leaf(token.RPAR, u')')) node.insert_child(2, arglist) node.insert_child(2, Leaf(token.LPAR, u'(')) else: raise ValueError("Unexpected class definition") # now stick the metaclass in the arglist meta_txt = last_metaclass.children[0].children[0] meta_txt.value = 'metaclass' orig_meta_prefix = meta_txt.prefix # Was: touch_import(None, u'future.utils', node) touch_import(u'future.utils', u'with_metaclass', node) metaclass = last_metaclass.children[0].children[2].clone() metaclass.prefix = u'' arguments = [metaclass] if arglist.children: if len(arglist.children) == 1: base = arglist.children[0].clone() base.prefix = u' ' else: # Unfortunately six.with_metaclass() only allows one base # class, so we have to dynamically generate a base class if # there is more than one. bases = parenthesize(arglist.clone()) bases.prefix = u' ' base = Call(Name('type'), [ String("'NewBase'"), Comma(), bases, Comma(), Node(syms.atom, [Leaf(token.LBRACE, u'{'), Leaf(token.RBRACE, u'}')], prefix=u' ') ], prefix=u' ') arguments.extend([Comma(), base]) arglist.replace( Call(Name(u'with_metaclass', prefix=arglist.prefix), arguments)) fixup_indent(suite) # check for empty suite if not suite.children: # one-liner that was just __metaclass_ suite.remove() pass_leaf = Leaf(text_type, u'pass') pass_leaf.prefix = orig_meta_prefix node.append_child(pass_leaf) node.append_child(Leaf(token.NEWLINE, u'\n')) elif len(suite.children) > 1 and \ (suite.children[-2].type == token.INDENT and suite.children[-1].type == token.DEDENT): # there was only one line in the class body and it was __metaclass__ pass_leaf = Leaf(text_type, u'pass') suite.insert_child(-1, pass_leaf) suite.insert_child(-1, Leaf(token.NEWLINE, u'\n'))
def transform(self, node: LN, capture: Capture) -> None: method_name = capture["method_name"].value if method_name in METHOD_RENAMES: should_warn = False # the basic usage is the same, but there are a number of kwargs # that are totally different. we'll just warn about those. if capture["args"]: assert len(capture["args"]) == 1 arg = capture["args"][0] if arg.type == syms.argument: # captureException(foo=bar) arg_name = arg.children[0] if arg_name.value in ARG_RENAMES: arg_name.replace( Name(ARG_RENAMES[arg_name.value], prefix=arg_name.prefix)) else: should_warn = True elif arg.type == syms.arglist: # captureException(a, b, ...) positional_argument_count = 0 for child in arg.children: if child.type == syms.argument: arg_name = child.children[0] if arg_name.value in ARG_RENAMES: arg_name.replace( Name( ARG_RENAMES[arg_name.value], prefix=arg_name.prefix, )) else: should_warn = True elif child.type == token.COMMA: pass else: positional_argument_count += 1 if positional_argument_count > 1: should_warn = True else: # captureException("foo") pass capture["method_name"].replace( Name(METHOD_RENAMES[method_name], prefix=capture["method_name"].prefix)) if not should_warn: return elif method_name.endswith("_context"): name, sep, _ = method_name.partition("_") if name in ("user", "http", "extra", "tags"): context_name = "request" if name == "http" else name args = [String(f'"{context_name}"'), Comma()] if capture["args"]: orig_args = capture["args"] assert len(orig_args) == 1 if orig_args[0].type == syms.arglist: orig_args = capture["args"][0].children args.extend(arg.clone() for arg in orig_args) if not args[2].prefix: args[2].prefix = " " capture["method_name"].replace( Name("set_context", prefix=capture["method_name"].prefix)) capture["arglist"].replace(ArgList(args)) return self.warn(node, "Update uses of Sentry APIs. See https://git.io/Jtc5C")
def transform(self, node: Node, results): if "imp" in results: return self._handle_import(node, results) else: if "buildin" in results: method_name = results["buildin"].value return self._handle_buildin(node, method_name) if isinstance(results['method'], Leaf): method_name = results["method"].value else: method_name = results["method"][0].value if "obj" not in results: # Prefix: Path. return self._handle_no_args(node, method_name) else: obj = results["obj"] argname = obj.clone() if "submod" in results: if method_name == "join" and len(argname.children) >= 1: first_arg, remaining_args = self._split_arguments( argname) x = Call(Name("Path"), first_arg, prefix=node.prefix) if len(remaining_args) > 0 and all( a.type in [token.COMMA, token.STRING] for a in remaining_args): if str(remaining_args[0].value).startswith('*'): x.append_child( Call(Name('joinpath', prefix=""), remaining_args, prefix=".")) return x x.append_child(Slash) for i, e in enumerate(remaining_args): if isinstance(e.value, Node): val = e.value elif isinstance(e.value, Leaf): val = e.value.value else: continue if e.type == token.STRING and val != ",": # if self.split_strings and "/" in e.value: # # TODO: get more robust e.value without quotes # parts = re.split('(/|\\\\)', e.value[1:-1]) # for part in parts: # if part in ["/", "\\"]: # x.append_child(Slash) # else: # x.append_child(String('"{}"'.format(part), prefix=" ")) # else: if i < 1: p = " " else: p = "" x.append_child(String(e, prefix=p)) else: x.append_child(Slash) return x else: first_arg, remaining_args = self._split_arguments( argname) x = Call(Name("Path"), first_arg, prefix=node.prefix) new_names = { "isabs": "is_absolute", "isdir": "is_dir", "isfile": "is_file", "islink": "is_symlink", "abspath": "resolve", "realpath": "resolve", "normpath": "resolve", "same": "samefile", } new_attribs = { "basename": "name", "dirname": "parent", "getsize": "stat().st_size", } if method_name in new_names: x.append_child( Call(Name(new_names[method_name], prefix=""), remaining_args, prefix=".")) elif method_name in new_attribs: x.append_child( String(new_attribs[method_name], prefix=".")) else: x.append_child( Call(Name(method_name, prefix=""), remaining_args, prefix=".")) return x else: arglist = argname first_arg, remaining_args = self._split_arguments(arglist) x = Call(Name("Path"), first_arg, prefix=node.prefix) if method_name == "remove": method_name = "unlink" if method_name == "listdir": x.append_child(String('glob("*")', prefix=".")) x.prefix = "" return Call(Name('list'), [x], prefix=node.prefix) elif method_name == 'makedirs': if len(remaining_args) > 0: children = [ Leaf(12, ','), Leaf(1, 'parents', prefix=' '), Leaf(22, '='), Leaf(3, 'True') ] remaining_args += [ Node(type=260, children=children) ] else: remaining_args = [ Leaf(1, 'parents', prefix=''), Leaf(22, '='), Leaf(3, 'True') ] x.append_child( Call(Name("mkdir"), remaining_args, prefix=".")) else: x.append_child( Call(Name(method_name), remaining_args, prefix=".")) return x
def _handle_type2abc(self, node, results, module, abc): touch_import(None, module, node) obj = results["obj"] args = [obj.clone(), String(", " + ".".join([module, abc]))] return Call(Name("isinstance"), args, prefix=node.prefix)
def _isCallable(self, node, results): obj = results["obj"] args = [obj.clone(), String(", "), String("'__call__'")] return Call(Name("hasattr"), args, prefix=node.prefix)
def _handle_type2abc(self, node, results, module, abc): touch_import(None, module, node) obj = results['obj'] args = [obj.clone(), String(u', ' + u'.'.join([module, abc]))] return Call(Name(u'isinstance'), args, prefix=node.prefix)
def _isCallable(self, node, results): obj = results['obj'] args = [obj.clone(), String(u', '), String(u"'__call__'")] return Call(Name(u'hasattr'), args, prefix=node.prefix)