These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			229 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			229 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """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.
 | |
| 
 | |
| """
 | |
| # Author: Jack Diederich
 | |
| 
 | |
| # Local imports
 | |
| from .. import fixer_base
 | |
| from ..pygram import token
 | |
| from ..fixer_util import Name, syms, Node, Leaf
 | |
| 
 | |
| 
 | |
| def has_metaclass(parent):
 | |
|     """ 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')
 | |
|     """
 | |
|     for node in parent.children:
 | |
|         if node.type == syms.suite:
 | |
|             return has_metaclass(node)
 | |
|         elif node.type == syms.simple_stmt and node.children:
 | |
|             expr_node = node.children[0]
 | |
|             if expr_node.type == syms.expr_stmt and expr_node.children:
 | |
|                 left_side = expr_node.children[0]
 | |
|                 if isinstance(left_side, Leaf) and \
 | |
|                         left_side.value == '__metaclass__':
 | |
|                     return True
 | |
|     return False
 | |
| 
 | |
| 
 | |
| def fixup_parse_tree(cls_node):
 | |
|     """ one-line classes don't get a suite in the parse tree so we add
 | |
|         one to normalize the tree
 | |
|     """
 | |
|     for node in cls_node.children:
 | |
|         if node.type == syms.suite:
 | |
|             # already in the preferred format, do nothing
 | |
|             return
 | |
| 
 | |
|     # !%@#! oneliners have no suite node, we have to fake one up
 | |
|     for i, node in enumerate(cls_node.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, [])
 | |
|     while cls_node.children[i+1:]:
 | |
|         move_node = cls_node.children[i+1]
 | |
|         suite.append_child(move_node.clone())
 | |
|         move_node.remove()
 | |
|     cls_node.append_child(suite)
 | |
|     node = suite
 | |
| 
 | |
| 
 | |
| def 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
 | |
|     """
 | |
|     for semi_ind, node in enumerate(stmt_node.children):
 | |
|         if node.type == token.SEMI: # *sigh*
 | |
|             break
 | |
|     else:
 | |
|         return
 | |
| 
 | |
|     node.remove() # kill the semicolon
 | |
|     new_expr = Node(syms.expr_stmt, [])
 | |
|     new_stmt = Node(syms.simple_stmt, [new_expr])
 | |
|     while stmt_node.children[semi_ind:]:
 | |
|         move_node = stmt_node.children[semi_ind]
 | |
|         new_expr.append_child(move_node.clone())
 | |
|         move_node.remove()
 | |
|     parent.insert_child(i, new_stmt)
 | |
|     new_leaf1 = new_stmt.children[0].children[0]
 | |
|     old_leaf1 = stmt_node.children[0].children[0]
 | |
|     new_leaf1.prefix = old_leaf1.prefix
 | |
| 
 | |
| 
 | |
| def remove_trailing_newline(node):
 | |
|     if node.children and node.children[-1].type == token.NEWLINE:
 | |
|         node.children[-1].remove()
 | |
| 
 | |
| 
 | |
| def find_metas(cls_node):
 | |
|     # find the suite node (Mmm, sweet nodes)
 | |
|     for node in cls_node.children:
 | |
|         if node.type == syms.suite:
 | |
|             break
 | |
|     else:
 | |
|         raise ValueError("No class suite!")
 | |
| 
 | |
|     # look for simple_stmt[ expr_stmt[ Leaf('__metaclass__') ] ]
 | |
|     for i, simple_node in list(enumerate(node.children)):
 | |
|         if simple_node.type == syms.simple_stmt and simple_node.children:
 | |
|             expr_node = simple_node.children[0]
 | |
|             if expr_node.type == syms.expr_stmt and expr_node.children:
 | |
|                 # Check if the expr_node is a simple assignment.
 | |
|                 left_node = expr_node.children[0]
 | |
|                 if isinstance(left_node, Leaf) and \
 | |
|                         left_node.value == u'__metaclass__':
 | |
|                     # We found a assignment to __metaclass__.
 | |
|                     fixup_simple_stmt(node, i, simple_node)
 | |
|                     remove_trailing_newline(simple_node)
 | |
|                     yield (node, i, simple_node)
 | |
| 
 | |
| 
 | |
| def fixup_indent(suite):
 | |
|     """ 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
 | |
|     """
 | |
|     kids = suite.children[::-1]
 | |
|     # find the first indent
 | |
|     while kids:
 | |
|         node = kids.pop()
 | |
|         if node.type == token.INDENT:
 | |
|             break
 | |
| 
 | |
|     # find the first Leaf
 | |
|     while kids:
 | |
|         node = kids.pop()
 | |
|         if isinstance(node, Leaf) and node.type != token.DEDENT:
 | |
|             if node.prefix:
 | |
|                 node.prefix = u''
 | |
|             return
 | |
|         else:
 | |
|             kids.extend(node.children[::-1])
 | |
| 
 | |
| 
 | |
| class FixMetaclass(fixer_base.BaseFix):
 | |
|     BM_compatible = True
 | |
| 
 | |
|     PATTERN = """
 | |
|     classdef<any*>
 | |
|     """
 | |
| 
 | |
|     def transform(self, node, results):
 | |
|         if not has_metaclass(node):
 | |
|             return
 | |
| 
 | |
|         fixup_parse_tree(node)
 | |
| 
 | |
|         # find metaclasses, keep the last one
 | |
|         last_metaclass = None
 | |
|         for suite, i, stmt in find_metas(node):
 | |
|             last_metaclass = stmt
 | |
|             stmt.remove()
 | |
| 
 | |
|         text_type = node.children[0].type # always Leaf(nnn, 'class')
 | |
| 
 | |
|         # figure out what kind of classdef we have
 | |
|         if len(node.children) == 7:
 | |
|             # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
 | |
|             #                 0        1       2    3        4    5    6
 | |
|             if node.children[3].type == syms.arglist:
 | |
|                 arglist = node.children[3]
 | |
|             # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
 | |
|             else:
 | |
|                 parent = node.children[3].clone()
 | |
|                 arglist = Node(syms.arglist, [parent])
 | |
|                 node.set_child(3, arglist)
 | |
|         elif len(node.children) == 6:
 | |
|             # Node(classdef, ['class', 'name', '(',  ')', ':', suite])
 | |
|             #                 0        1       2     3    4    5
 | |
|             arglist = Node(syms.arglist, [])
 | |
|             node.insert_child(3, arglist)
 | |
|         elif len(node.children) == 4:
 | |
|             # Node(classdef, ['class', 'name', ':', suite])
 | |
|             #                 0        1       2    3
 | |
|             arglist = Node(syms.arglist, [])
 | |
|             node.insert_child(2, Leaf(token.RPAR, u')'))
 | |
|             node.insert_child(2, arglist)
 | |
|             node.insert_child(2, Leaf(token.LPAR, u'('))
 | |
|         else:
 | |
|             raise ValueError("Unexpected class definition")
 | |
| 
 | |
|         # now stick the metaclass in the arglist
 | |
|         meta_txt = last_metaclass.children[0].children[0]
 | |
|         meta_txt.value = 'metaclass'
 | |
|         orig_meta_prefix = meta_txt.prefix
 | |
| 
 | |
|         if arglist.children:
 | |
|             arglist.append_child(Leaf(token.COMMA, u','))
 | |
|             meta_txt.prefix = u' '
 | |
|         else:
 | |
|             meta_txt.prefix = u''
 | |
| 
 | |
|         # compact the expression "metaclass = Meta" -> "metaclass=Meta"
 | |
|         expr_stmt = last_metaclass.children[0]
 | |
|         assert expr_stmt.type == syms.expr_stmt
 | |
|         expr_stmt.children[1].prefix = u''
 | |
|         expr_stmt.children[2].prefix = u''
 | |
| 
 | |
|         arglist.append_child(last_metaclass)
 | |
| 
 | |
|         fixup_indent(suite)
 | |
| 
 | |
|         # check for empty suite
 | |
|         if not suite.children:
 | |
|             # one-liner that was just __metaclass_
 | |
|             suite.remove()
 | |
|             pass_leaf = Leaf(text_type, u'pass')
 | |
|             pass_leaf.prefix = orig_meta_prefix
 | |
|             node.append_child(pass_leaf)
 | |
|             node.append_child(Leaf(token.NEWLINE, u'\n'))
 | |
| 
 | |
|         elif len(suite.children) > 1 and \
 | |
|                  (suite.children[-2].type == token.INDENT and
 | |
|                   suite.children[-1].type == token.DEDENT):
 | |
|             # there was only one line in the class body and it was __metaclass__
 | |
|             pass_leaf = Leaf(text_type, u'pass')
 | |
|             suite.insert_child(-1, pass_leaf)
 | |
|             suite.insert_child(-1, Leaf(token.NEWLINE, u'\n'))
 |