def transform(self, node, results): FIXME name, val, trc = ( results.get(u"name"), results.get(u"val"), results.get(u"trc"), ) chain = results.get(u"chain") if chain is not None: self.warning( node, u"explicit exception chaining is not supported in Python 2") chain.prev_sibling.remove() chain.remove() if trc is not None: val = val[0] if val else Leaf(token.NAME, u"None") val.prefix = trc.prefix = u" " kids = [ Leaf(token.NAME, u"raise"), name.clone(), Comma(), val.clone(), Comma(), trc.clone(), ] raise_stmt = Node(syms.raise_stmt, kids) node.replace(raise_stmt)
def add_sep_part(sep, pos, lst): if sep is not None and not isNone(sep) and \ not (sep.type == token.STRING and sep.value in ("' '", '" "')): temp = [] for arg in pos: temp.append(_unicode(arg.clone())) if sys.version_info >= (2, 6): warnings.warn( "Calling unicode() on what may be a bytes object") temp.append(Comma()) del temp[-1] sep = sep.clone() sep.prefix = " " args = Node(syms.listmaker, temp) new_list = Node(syms.atom, [Leaf(token.LSQB, "["), args, Leaf(token.RSQB, "]")]) join_arg = Node(syms.trailer, [LParen(), new_list, RParen()]) sep_join = Node(syms.power, [sep, Node(syms.trailer, [Dot(), Name("join")])]) lst.append(sep_join) lst.append(join_arg) else: if pos: pos[0].prefix = " " for arg in pos: lst.append(arg.clone()) lst.append(Comma()) del lst[-1]
def transform(self, node, results): if self.filename in blacklist: return elif self.filename == 'mercurial/util.py': touch_import('.', 'py3kcompat', node=node) formatstr = results['formatstr'].clone() data = results['data'].clone() formatstr.prefix = '' # remove spaces from start if isnumberremainder(formatstr, data): return # We have two possibilities: # 1- An identifier or name is passed, it is going to be a leaf, thus, we # just need to copy its value as an argument to the formatter; # 2- A tuple is explicitly passed. In this case, we're gonna explode it # to pass to the formatter # TODO: Check for normal strings. They don't need to be translated if is_tuple(data): args = [formatstr, Comma().clone()] + \ [c.clone() for c in data.children[:]] else: args = [formatstr, Comma().clone(), data] call = Call(Name('bytesformatter', prefix=' '), args) return call
def transform(self, node, results): syms = self.syms exc, val, trc = (results[u"exc"], results[u"val"], results[u"trc"]) val = val[0] if val else Leaf(token.NAME, u"None") val.prefix = trc.prefix = u" " kids = [exc.clone(), Comma(), val.clone(), Comma(), trc.clone()] args = results[u"args"] args.children = kids
def new_future_import(self, old): new = FromImport("__future__", [ Name("absolute_import", prefix=" "), Comma(), Name("division", prefix=" "), Comma(), Name("print_function", prefix=" ") ]) if old is not None: new.prefix = old.prefix return new
def transform(self, node, results): exc = results["exc"].clone() val = results["val"].clone() tb = results["tb"].clone() exc.prefix = u"" val.prefix = tb.prefix = u" " touch_import(None, u'six', node) return Call(Name(u"six.reraise"), [exc, Comma(), val, Comma(), tb], prefix=node.prefix)
def add_on_delete_cascade(node: LN, capture: Capture, filename: Filename) -> Optional[LN]: arguments = capture.get("function_arguments")[0] new_on_delete_node = KeywordArg(Name(" on_delete"), Name("models.CASCADE")) if isinstance( arguments, Leaf ): # Node is a leaf and so we need to replace it with a list of things we want instead. arguments.replace([arguments.clone(), Comma(), new_on_delete_node]) else: arguments.append_child(Comma()) arguments.append_child(new_on_delete_node) return node
def transform(self, node, results): if 'sys_import' in results: if self.sys_import is None: self.sys_import = results['sys_import'] return else: func = results['func'].clone() func.prefix = u'' register = pytree.Node(syms.power, Attr(Name(u'atexit'), Name(u'register'))) call = Call(register, [func], node.prefix) node.replace(call) if self.sys_import is None: self.warning(node, "Can't find sys import; Please add an atexit import at the top of your file.") return names = self.sys_import.children[1] if names.type == syms.dotted_as_names: names.append_child(Comma()) names.append_child(Name(u'atexit', u' ')) else: containing_stmt = self.sys_import.parent position = containing_stmt.children.index(self.sys_import) stmt_container = containing_stmt.parent new_import = pytree.Node(syms.import_name, [Name(u'import'), Name(u'atexit', u' ')]) new = pytree.Node(syms.simple_stmt, [new_import]) containing_stmt.insert_child(position + 1, Newline()) containing_stmt.insert_child(position + 2, new) return
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: LN, capture: Capture) -> None: if node.type == syms.simple_stmt: trust_trace_headers_value = None header_trust_handler_seen = False for prev_argument, argument in pairwise(capture["arguments"]): if argument.type == syms.argument: if argument.children[0].value == "trust_trace_headers": assert argument.children[1].value == "=" trust_trace_headers_value = argument.children[2].clone() argument.remove() if prev_argument.type == token.COMMA: prev_argument.remove() elif argument.children[0].value == "header_trust_handler": header_trust_handler_seen = True if trust_trace_headers_value and not header_trust_handler_seen: capture["arglist"].append_child(Comma()) handler_kwarg = KeywordArg( Name("trust_headers"), trust_trace_headers_value ) handler = Call(Name("StaticTrustHandler"), args=[handler_kwarg]) kwarg = KeywordArg(Name("header_trust_handler"), handler) kwarg.prefix = " " capture["arglist"].append_child(kwarg) self.added_static_trust_handler = True
def match(self, node): u""" Since the tree needs to be fixed once and only once if and only if it matches, we can start discarding matches after the first. """ if node.type == self.syms.term: matched = False skip = False children = [] for child in node.children: if skip: skip = False continue if match_division(child) and not is_floaty(child): matched = True # Strip any leading space for the first number: children[0].prefix = u'' children = [ wrap_in_fn_call( "old_div", children + [Comma(), child.next_sibling.clone()], prefix=node.prefix) ] skip = True else: children.append(child.clone()) if matched: return Node(node.type, children, fixers_applied=node.fixers_applied) return False
def name_import_replacement(name, attr): children = [Name("import")] for c in all_candidates(name.value, attr.value): children.append(Name(c, prefix=" ")) children.append(Comma()) children.pop() replacement = Node(syms.import_name, children) return replacement
def transform_import(self, node, results): import_mod = results.get('module') pref = import_mod.prefix names = [] for name in MAPPING[import_mod.value][:-1]: names.extend([Name(name[0], prefix=pref), Comma()]) names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref)) import_mod.replace(names)
def _Call(self, name, args=None, prefix=None): """Help the next test""" children = [] if isinstance(args, list): for arg in args: children.append(arg) children.append(Comma()) children.pop() return Call(Name(name), children, prefix)
def add_kwarg(self, l_nodes, s_kwd, n_expr): # XXX All this prefix-setting may lose comments (though rarely) n_expr.prefix = u"" n_argument = pytree.Node( self.syms.argument, (Name(s_kwd), pytree.Leaf(token.EQUAL, u"="), n_expr)) if l_nodes: l_nodes.append(Comma()) n_argument.prefix = u" " l_nodes.append(n_argument)
def add_request_param(node: LN, capture: Capture, filename: Filename) -> Optional[LN]: arguments = capture.get("function_arguments") if arguments: arguments = arguments[0] # Insert request parameter at start arguments.insert_child(0, Name("request")) arguments.insert_child(1, Comma()) arguments.children[2].prefix = " " return node
def commatize(leafs): """ Accepts/turns: (Name, Name, ..., Name, Name) Returns/into: (Name, Comma, Name, Comma, ..., Name, Comma, Name) """ new_leafs = [] for leaf in leafs: new_leafs.append(leaf) new_leafs.append(Comma()) del new_leafs[-1] return new_leafs
def AlmostOp(places_op, delta_op, first, second, kws): first.prefix = "" second.prefix = "" approx_args = [second] if kws.get('delta', None) is not None: kws['delta'].prefix = "" abs_arg = KeywordArg(Name('abs'), kws['delta']) abs_arg.prefix = " " approx_args.extend([Comma(), abs_arg]) approx_op = Call(Name("pytest.approx"), approx_args) return CompOp(places_op, first, approx_op, {})
def clone_div_operands(node, div_idx): children = [] for i, child in enumerate(node.children): if i == div_idx: children.append(Comma()) else: children.append(child.clone()) # Strip any leading space for the first number: children[0].prefix = u"" return children
def transform_import(self, node, results): """Transform for the basic import case. Replaces the old import name with a comma separated list of its replacements. """ import_mod = results.get('module') pref = import_mod.prefix names = [] for name in MAPPING[import_mod.value][:-1]: names.extend([Name(name[0], prefix=pref), Comma()]) names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref)) import_mod.replace(names)
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 fix_explicit_context(self, node, results): pre, name, post, source = (results.get(n) for n in (u"pre", u"name", u"post", u"source")) pre = [n.clone() for n in pre if n.type == token.NAME] name.prefix = u" " post = [n.clone() for n in post if n.type == token.NAME] target = [n.clone() for n in commatize(pre + [name.clone()] + post)] # to make the special-case fix for "*z, = ..." correct with the least # amount of modification, make the left-side into a guaranteed tuple target.append(Comma()) source.prefix = u"" setup_line = Assign(Name(self.LISTNAME), Call(Name(u"list"), [source.clone()])) power_line = Assign(target, assignment_source(len(pre), len(post), self.LISTNAME, self.ITERNAME)) return setup_line, power_line
def transform(self, node, results): # Handling of the first argument: if 'string' in results: # String as first argument new_func_name = 'ufloat_fromstr' # New arguments: new_args = [results['string'].clone()] else: # Tuple as first argument new_func_name = 'ufloat' # New arguments: new_args = [ results['arg0'].clone(), Comma(), results['arg1'].clone() ] # Handling of the second argument (call with a tag): if 'tag' in results: new_args.extend([Comma(), results['tag'].clone()]) if 'object' in results: # If dotted access: unc.ufloat() func_name = node.children[1].children[1] args = node.children[2] else: func_name = node.children[0] args = node.children[1] # Function name update: func_name.value = new_func_name #! func_name.changed() # Necessary when only .value is changed # Argument list update: args.replace(ArgList(new_args))
def Args(*args, **kwargs): r = [] if args: r.append(maybe_name(args[0], prefix="")) for x in args[1:]: r.append(Comma()) r.append(maybe_name(x)) if kwargs: sorted_items = sorted(kwargs.items()) if args: r.append(Comma()) prefix = " " else: prefix = "" r.append(maybe_name(sorted_items[0][0], prefix=prefix)) r.append(Leaf(token.EQUAL, "=")) r.append(sorted_items[0][1]) for k, v in sorted_items[1:]: r.append(Comma()) r.append(maybe_name(k)) r.append(Leaf(token.EQUAL, "=")) r.append(v) return Node(syms.typedargslist, r)
def transform(self, node, results): self.count += 1 if 'arg_2' in results: logger.debug("found 2 [%s %s]" % (results['arg_1'], results['arg_2'])) error_no = results['arg_1'] error_no.replace(Leaf(type=2, value=self.count)) else: logger.debug("found 1 [%s]" % results['arg_1']) siblings_list = results['arg_1'].parent.children siblings_list.insert(1, Leaf(type=2, value=self.count)) siblings_list.insert(2, Comma()) siblings_list[3].prefix = " " return node
def AlmostOp(places_op, delta_op, first, second, kws): first.prefix = "" second.prefix = "" abs_op = Call(Name('abs'), [Node(syms.factor, [first, Name('-'), second])]) if kws.get('delta', None) is not None: # delta return CompOp(delta_op, abs_op, kws['delta'], {}) else: # `7` is the default in unittest.TestCase.asserAlmostEqual places = kws['places'] or Number(7) places.prefix = " " round_op = Call(Name('round'), (abs_op, Comma(), places)) return CompOp(places_op, round_op, Number(0), {})
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 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 wrap_in_fn_call(fn_name, args, prefix=None): """ Example: >>> wrap_in_fn_call("oldstr", (arg,)) oldstr(arg) >>> wrap_in_fn_call("olddiv", (arg1, arg2)) olddiv(arg1, arg2) """ assert len(args) > 0 if len(args) == 1: newargs = args elif len(args) == 2: expr1, expr2 = args newargs = [expr1, Comma(), expr2] else: assert NotImplementedError('write me') return Call(Name(fn_name), newargs, prefix=prefix)