1. Joe Amenta
  2. lib3to2

Commits

Joe Amenta  committed d7bd8a3

Added real support for finding the indentation of a node and moved the suitify() function to fixer_util

  • Participants
  • Parent commits 8d84907
  • Branches default

Comments (0)

Files changed (2)

File lib3to2/fixer_util.py

View file
 
 def indentation(node):
     """
-    Recursively checks every previous sibling for token.INDENT
-
-    Returns empty string if not found, or the indentation if it is.
+    Returns the indentation for this node
+    Iff a node is in a suite, then it has indentation.
     """
-    prev_sibling = node.prev_sibling
+    while node.parent is not None and node.parent.type != syms.suite:
+        node = node.parent
+    if node.parent is None:
+        return ""
+    # The first three children of a suite are NEWLINE, INDENT, (some other node)
+    # INDENT.value contains the indentation for this suite
+    # anything after (some other node) has the indentation as its prefix.
     if node.type == token.INDENT:
         return node.value
+    elif node.prev_sibling is not None and node.prev_sibling.type == token.INDENT:
+        return node.prev_sibling.value
+    elif node.prev_sibling is None:
+        return node.next_sibling.value
     else:
-        return indentation(prev_sibling) if prev_sibling is not None else ""
+        return node.prefix
+
+def indentation_step(node):
+    """
+    Dirty little trick to get the difference between each indentation level
+    Implemented by finding the shortest indentation string
+    (technically, the "least" of all of the indentation strings, but
+    tabs and spaces mixed won't get this far, so those are synonymous.)
+    """
+    r = find_root(node)
+    # Collect all indentations into one set.
+    all_indents = set(i.value for i in r.pre_order() if i.type == token.INDENT)
+    if not all_indents:
+        # nothing is indented anywhere, so we get to pick what we want
+        return "    " # four spaces is a popular convention
+    else:
+        return min(all_indents)
+
+def suitify(parent):
+    """
+    Turn the stuff after the first colon in parent's children
+    into a suite, if it wasn't already
+    """
+    for node in parent.children:
+        if node.type == syms.suite:
+            # already in the prefered format, do nothing
+            return
+
+    # One-liners have no suite node, we have to fake one up
+    for i, node in enumerate(parent.children):
+        if node.type == token.COLON:
+            break
+    else:
+        raise ValueError("No class suite and no ':'!")
+    # Move everything into a suite node
+    suite = Node(syms.suite, [Newline(), Leaf(token.INDENT, indentation(node) + indentation_step(node))])
+    one_node = parent.children[i+1]
+    one_node.remove()
+    one_node.prefix = ''
+    suite.append_child(one_node)
+    parent.append_child(suite)
 
 def NameImport(package, as_name=None, prefix=None):
     """

File lib3to2/fixes/fix_metaclass.py

View file
 Some semantics (see PEP 3115) may be altered in the translation."""
 
 from lib2to3 import fixer_base
-from lib2to3.fixer_util import Name, syms, Node, Leaf, Newline, find_root
+from ..fixer_util import Name, syms, Node, Leaf, Newline, find_root, indentation, suitify
 from lib2to3.pygram import token
 
-def suitify(parent, ident='    '):
-    """Make sure we have a suite to add our stmt_node"""
-    for node in parent.children:
-        if node.type == syms.suite:
-            # already in the prefered format, do nothing
-            return
-
-    # One-liners have no suite node, we have to fake one up
-    for i, node in enumerate(parent.children):
-        if node.type == token.COLON:
-            break
-    else:
-        raise ValueError("No class suite and no ':'!")
-    # Move everything into a suite node
-    suite = Node(syms.suite, [Newline(), Leaf(token.INDENT, ident)])
-    while parent.children[i+1:]:
-        move_node = parent.children[i+1]
-        move_node.prefix = ''
-        suite.append_child(move_node.clone())
-        move_node.remove()
-    parent.append_child(suite)
-
-def indentation(node):
-    for child in find_root(node).pre_order():
-        if child.type == token.INDENT:
-            break
-    else:
-        return '    '
-    return child.value
-
 def has_metaclass(parent):
     results = None
     for node in parent.children:
         name = meta
         name.prefix = " "
         stmt_node = Node(syms.atom, [target, equal, name])
-        suitify(node, ident=indentation(node))
+        
+        suitify(node)
         for item in node.children:
             if item.type == syms.suite:
                 for stmt in item.children: