| Index: third_party/google-endpoints/libpasteurize/fixes/fix_kwargs.py
|
| diff --git a/third_party/google-endpoints/libpasteurize/fixes/fix_kwargs.py b/third_party/google-endpoints/libpasteurize/fixes/fix_kwargs.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..59a3043befec1eba9553139cf58d4d0446542535
|
| --- /dev/null
|
| +++ b/third_party/google-endpoints/libpasteurize/fixes/fix_kwargs.py
|
| @@ -0,0 +1,148 @@
|
| +u"""
|
| +Fixer for Python 3 function parameter syntax
|
| +This fixer is rather sensitive to incorrect py3k syntax.
|
| +"""
|
| +
|
| +# Note: "relevant" parameters are parameters following the first STAR in the list.
|
| +
|
| +from lib2to3 import fixer_base
|
| +from lib2to3.fixer_util import token, String, Newline, Comma, Name
|
| +from libfuturize.fixer_util import indentation, suitify, DoubleStar
|
| +
|
| +_assign_template = u"%(name)s = %(kwargs)s['%(name)s']; del %(kwargs)s['%(name)s']"
|
| +_if_template = u"if '%(name)s' in %(kwargs)s: %(assign)s"
|
| +_else_template = u"else: %(name)s = %(default)s"
|
| +_kwargs_default_name = u"_3to2kwargs"
|
| +
|
| +def gen_params(raw_params):
|
| + u"""
|
| + Generator that yields tuples of (name, default_value) for each parameter in the list
|
| + If no default is given, then it is default_value is None (not Leaf(token.NAME, 'None'))
|
| + """
|
| + assert raw_params[0].type == token.STAR and len(raw_params) > 2
|
| + curr_idx = 2 # the first place a keyword-only parameter name can be is index 2
|
| + max_idx = len(raw_params)
|
| + while curr_idx < max_idx:
|
| + curr_item = raw_params[curr_idx]
|
| + prev_item = curr_item.prev_sibling
|
| + if curr_item.type != token.NAME:
|
| + curr_idx += 1
|
| + continue
|
| + if prev_item is not None and prev_item.type == token.DOUBLESTAR:
|
| + break
|
| + name = curr_item.value
|
| + nxt = curr_item.next_sibling
|
| + if nxt is not None and nxt.type == token.EQUAL:
|
| + default_value = nxt.next_sibling
|
| + curr_idx += 2
|
| + else:
|
| + default_value = None
|
| + yield (name, default_value)
|
| + curr_idx += 1
|
| +
|
| +def remove_params(raw_params, kwargs_default=_kwargs_default_name):
|
| + u"""
|
| + Removes all keyword-only args from the params list and a bare star, if any.
|
| + Does not add the kwargs dict if needed.
|
| + Returns True if more action is needed, False if not
|
| + (more action is needed if no kwargs dict exists)
|
| + """
|
| + assert raw_params[0].type == token.STAR
|
| + if raw_params[1].type == token.COMMA:
|
| + raw_params[0].remove()
|
| + raw_params[1].remove()
|
| + kw_params = raw_params[2:]
|
| + else:
|
| + kw_params = raw_params[3:]
|
| + for param in kw_params:
|
| + if param.type != token.DOUBLESTAR:
|
| + param.remove()
|
| + else:
|
| + return False
|
| + else:
|
| + return True
|
| +
|
| +def needs_fixing(raw_params, kwargs_default=_kwargs_default_name):
|
| + u"""
|
| + Returns string with the name of the kwargs dict if the params after the first star need fixing
|
| + Otherwise returns empty string
|
| + """
|
| + found_kwargs = False
|
| + needs_fix = False
|
| +
|
| + for t in raw_params[2:]:
|
| + if t.type == token.COMMA:
|
| + # Commas are irrelevant at this stage.
|
| + continue
|
| + elif t.type == token.NAME and not found_kwargs:
|
| + # Keyword-only argument: definitely need to fix.
|
| + needs_fix = True
|
| + elif t.type == token.NAME and found_kwargs:
|
| + # Return 'foobar' of **foobar, if needed.
|
| + return t.value if needs_fix else u''
|
| + elif t.type == token.DOUBLESTAR:
|
| + # Found either '*' from **foobar.
|
| + found_kwargs = True
|
| + else:
|
| + # Never found **foobar. Return a synthetic name, if needed.
|
| + return kwargs_default if needs_fix else u''
|
| +
|
| +class FixKwargs(fixer_base.BaseFix):
|
| +
|
| + run_order = 7 # Run after function annotations are removed
|
| +
|
| + PATTERN = u"funcdef< 'def' NAME parameters< '(' arglist=typedargslist< params=any* > ')' > ':' suite=any >"
|
| +
|
| + 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))
|
| +
|
|
|