Back to index

python3.2  3.2.2
Classes | Functions
lib2to3.fixes.fix_metaclass Namespace Reference

Classes

class  FixMetaclass

Functions

def has_metaclass
def fixup_parse_tree
def fixup_simple_stmt
def remove_trailing_newline
def find_metas
def fixup_indent

Detailed Description

Fixer for __metaclass__ = X -> (metaclass=X) methods.

   The various forms of classef (inherits nothing, inherits once, inherints
   many) don't parse the same in the CST so we look at ALL classes for
   a __metaclass__ and if we find one normalize the inherits to all be
   an arglist.

   For one-liner classes ('class X: pass') there is no indent/dedent so
   we normalize those into having a suite.

   Moving the __metaclass__ into the classdef can also cause the class
   body to be empty so there is some special casing for that as well.

   This fixer also tries very hard to keep original indenting and spacing
   in all those corner cases.

Function Documentation

Definition at line 100 of file fix_metaclass.py.

00100 
00101 def find_metas(cls_node):
00102     # find the suite node (Mmm, sweet nodes)
00103     for node in cls_node.children:
00104         if node.type == syms.suite:
00105             break
00106     else:
00107         raise ValueError("No class suite!")
00108 
00109     # look for simple_stmt[ expr_stmt[ Leaf('__metaclass__') ] ]
00110     for i, simple_node in list(enumerate(node.children)):
00111         if simple_node.type == syms.simple_stmt and simple_node.children:
00112             expr_node = simple_node.children[0]
00113             if expr_node.type == syms.expr_stmt and expr_node.children:
00114                 # Check if the expr_node is a simple assignment.
00115                 left_node = expr_node.children[0]
00116                 if isinstance(left_node, Leaf) and \
00117                         left_node.value == '__metaclass__':
00118                     # We found a assignment to __metaclass__.
00119                     fixup_simple_stmt(node, i, simple_node)
00120                     remove_trailing_newline(simple_node)
00121                     yield (node, i, simple_node)
00122 

Here is the call graph for this function:

Here is the caller graph for this function:

If an INDENT is followed by a thing with a prefix then nuke the prefix
    Otherwise we get in trouble when removing __metaclass__ at suite start

Definition at line 123 of file fix_metaclass.py.

00123 
00124 def fixup_indent(suite):
00125     """ If an INDENT is followed by a thing with a prefix then nuke the prefix
00126         Otherwise we get in trouble when removing __metaclass__ at suite start
00127     """
00128     kids = suite.children[::-1]
00129     # find the first indent
00130     while kids:
00131         node = kids.pop()
00132         if node.type == token.INDENT:
00133             break
00134 
00135     # find the first Leaf
00136     while kids:
00137         node = kids.pop()
00138         if isinstance(node, Leaf) and node.type != token.DEDENT:
00139             if node.prefix:
00140                 node.prefix = ''
00141             return
00142         else:
00143             kids.extend(node.children[::-1])
00144 

Here is the caller graph for this function:

one-line classes don't get a suite in the parse tree so we add
    one to normalize the tree

Definition at line 45 of file fix_metaclass.py.

00045 
00046 def fixup_parse_tree(cls_node):
00047     """ one-line classes don't get a suite in the parse tree so we add
00048         one to normalize the tree
00049     """
00050     for node in cls_node.children:
00051         if node.type == syms.suite:
00052             # already in the preferred format, do nothing
00053             return
00054 
00055     # !%@#! oneliners have no suite node, we have to fake one up
00056     for i, node in enumerate(cls_node.children):
00057         if node.type == token.COLON:
00058             break
00059     else:
00060         raise ValueError("No class suite and no ':'!")
00061 
00062     # move everything into a suite node
00063     suite = Node(syms.suite, [])
00064     while cls_node.children[i+1:]:
00065         move_node = cls_node.children[i+1]
00066         suite.append_child(move_node.clone())
00067         move_node.remove()
00068     cls_node.append_child(suite)
00069     node = suite
00070 

Here is the call graph for this function:

Here is the caller graph for this function:

def lib2to3.fixes.fix_metaclass.fixup_simple_stmt (   parent,
  i,
  stmt_node 
)
if there is a semi-colon all the parts count as part of the same
    simple_stmt.  We just want the __metaclass__ part so we move
    everything efter the semi-colon into its own simple_stmt node

Definition at line 71 of file fix_metaclass.py.

00071 
00072 def fixup_simple_stmt(parent, i, stmt_node):
00073     """ if there is a semi-colon all the parts count as part of the same
00074         simple_stmt.  We just want the __metaclass__ part so we move
00075         everything efter the semi-colon into its own simple_stmt node
00076     """
00077     for semi_ind, node in enumerate(stmt_node.children):
00078         if node.type == token.SEMI: # *sigh*
00079             break
00080     else:
00081         return
00082 
00083     node.remove() # kill the semicolon
00084     new_expr = Node(syms.expr_stmt, [])
00085     new_stmt = Node(syms.simple_stmt, [new_expr])
00086     while stmt_node.children[semi_ind:]:
00087         move_node = stmt_node.children[semi_ind]
00088         new_expr.append_child(move_node.clone())
00089         move_node.remove()
00090     parent.insert_child(i, new_stmt)
00091     new_leaf1 = new_stmt.children[0].children[0]
00092     old_leaf1 = stmt_node.children[0].children[0]
00093     new_leaf1.prefix = old_leaf1.prefix
00094 

Here is the call graph for this function:

Here is the caller graph for this function:

we have to check the cls_node without changing it.
    There are two possiblities:
      1)  clsdef => suite => simple_stmt => expr_stmt => Leaf('__meta')
      2)  clsdef => simple_stmt => expr_stmt => Leaf('__meta')

Definition at line 26 of file fix_metaclass.py.

00026 
00027 def has_metaclass(parent):
00028     """ we have to check the cls_node without changing it.
00029         There are two possiblities:
00030           1)  clsdef => suite => simple_stmt => expr_stmt => Leaf('__meta')
00031           2)  clsdef => simple_stmt => expr_stmt => Leaf('__meta')
00032     """
00033     for node in parent.children:
00034         if node.type == syms.suite:
00035             return has_metaclass(node)
00036         elif node.type == syms.simple_stmt and node.children:
00037             expr_node = node.children[0]
00038             if expr_node.type == syms.expr_stmt and expr_node.children:
00039                 left_side = expr_node.children[0]
00040                 if isinstance(left_side, Leaf) and \
00041                         left_side.value == '__metaclass__':
00042                     return True
00043     return False
00044 

Here is the caller graph for this function:

Definition at line 95 of file fix_metaclass.py.

00095 
00096 def remove_trailing_newline(node):
00097     if node.children and node.children[-1].type == token.NEWLINE:
00098         node.children[-1].remove()
00099 

Here is the call graph for this function:

Here is the caller graph for this function: