Commits

Joe Amenta  committed 8d84907

Properly getting the name of the kwargs dict and adding templates for later fixes.

  • Participants
  • Parent commits 53ccf1e

Comments (0)

Files changed (2)

File lib3to2/fixes/fix_kwargs.py

 Fixer for Python 3 function parameter syntax
 """
 
+# Note: "relevant" parameters are parameters following the first STAR in the list.
+
 from lib2to3 import fixer_base
 from ..fixer_util import token
 
-def needs_fixing(after_star):
+_if_template = "if '%(name)s' in %(kwargs)s: %(name)s = %(kwargs)s['%(name)s']"
+_else_template = "else: %(name)s = %(default)s"
+
+def needs_fixing(relevant_params):
     """
-    Returns string with the name of the kwargs dict if the args after the first star need fixing
+    Returns string with the name of the kwargs dict if the params after the first star need fixing
     Otherwise returns empty string
     """
-    if after_star[0].type == token.STAR:
-        return ''
     found_kwargs = False
     needs_fix = False
 
-    for t in after_star[1:]:
+    for t in relevant_params:
         if t.type == token.COMMA:
             # Commas are irrelevant at this stage.
             continue
         elif t.type == token.NAME and found_kwargs:
             # Return 'foobar' of **foobar, if needed.
             return t.value if needs_fix else ''
-        elif t.type == token.STAR:
+        elif t.type == token.DOUBLESTAR:
             # Found either '*' from **foobar.
             found_kwargs = True
     else:
 
     explicit = True # not sufficiently tested
     
-    PATTERN = "funcdef< 'def' NAME parameters< '(' typedargslist< any* first_star='*' after_star=any* > ')' > ':' suite=any >"
+    PATTERN = "funcdef< 'def' NAME parameters< '(' typedargslist< params=any* > ')' > ':' suite=any >"
 
     def transform(self, node, results):
-        after_star = results["after_star"]
-        new_kwargs = needs_fixing(after_star)
+        params = results["params"]
+        for i, item in enumerate(params):
+            if item.type == token.STAR:
+                relevant_params = params[i:]
+                break
+        else:
+            return
+        # relevant_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(relevant_params)
+        # new_kwargs is the name of the kwargs dictionary.
         if not new_kwargs:
             return
-        else:
-            print("Placeholder!")
+
+        # At this point, relevant_params 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]
+
+        

File lib3to2/tests/test_kwargs.py

         def spam(ham, *args, eggs, monkeys):
             funky()"""
         a = """
-        def spam(ham, *args, **kwargs):
-            eggs = kwargs['eggs']
-            monkeys = kwargs['monkeys']
+        def spam(ham, *args, **_3to2kwargs):
+            eggs = _3to2kwargs['eggs']
+            monkeys = _3to2kwargs['monkeys']
             funky()"""
         self.check(b, a)
 
         a = """
         def spam(ham, **_3to2kwargs):
             dinosaurs = _3to2kwargs['dinosaurs']
-            if 'eggs' in _3to2kwargs:
-                eggs = _3to2kwargs['eggs']
-            else:
-                eggs = 3
-            if 'monkeys' in _3to2kwargs:
-                monkeys = _3to2kwargs['monkeys']
-            else:
-                monkeys = 2
+            if 'eggs' in _3to2kwargs: eggs = _3to2kwargs['eggs']
+            else: eggs = 3
+            if 'monkeys' in _3to2kwargs: monkeys = _3to2kwargs['monkeys']
+            else: monkeys = 2
             funky()"""
         self.check(b, a)
 
         a = """
         def spam(ham, **stuff):
             dinosaurs = stuff['dinosaurs']
-            if 'eggs' in stuff:
-                eggs = stuff['eggs']
-            else:
-                eggs = 3
-            if 'monkeys' in stuff:
-                monkeys = stuff['monkeys']
-            else:
-                monkeys = 2
+            if 'eggs' in stuff: eggs = stuff['eggs']
+            else: eggs = 3
+            if 'monkeys' in stuff: monkeys = stuff['monkeys']
+            else: monkeys = 2
             funky()"""
         self.check(b, a)