Submit
Path:
~
/
/
proc
/
thread-self
/
root
/
opt
/
alt
/
python27
/
lib
/
python2.7
/
site-packages
/
libfuturize
/
fixes
/
File Content:
fix_metaclass.py
# coding: utf-8 """Fixer for __metaclass__ = X -> (future.utils.with_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. """ # This is a derived work of Lib/lib2to3/fixes/fix_metaclass.py under the # copyright of the Python Software Foundation, licensed under the Python # Software Foundation License 2. # # Copyright notice: # # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013 Python Software Foundation. All rights reserved. # # Full license text: http://docs.python.org/3.4/license.html # Author: Jack Diederich, Daniel Neuhäuser # Local imports from lib2to3 import fixer_base from lib2to3.pygram import token from lib2to3.fixer_util import Name, syms, Node, Leaf, touch_import, Call, \ String, Comma, parenthesize 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 # Was: touch_import(None, u'future.utils', node) touch_import(u'future.utils', u'with_metaclass', node) metaclass = last_metaclass.children[0].children[2].clone() metaclass.prefix = u'' arguments = [metaclass] if arglist.children: if len(arglist.children) == 1: base = arglist.children[0].clone() base.prefix = u' ' else: # Unfortunately six.with_metaclass() only allows one base # class, so we have to dynamically generate a base class if # there is more than one. bases = parenthesize(arglist.clone()) bases.prefix = u' ' base = Call(Name('type'), [ String("'NewBase'"), Comma(), bases, Comma(), Node( syms.atom, [Leaf(token.LBRACE, u'{'), Leaf(token.RBRACE, u'}')], prefix=u' ' ) ], prefix=u' ') arguments.extend([Comma(), base]) arglist.replace(Call( Name(u'with_metaclass', prefix=arglist.prefix), arguments )) 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'))
Edit
Rename
Chmod
Delete
FILE
FOLDER
Name
Size
Permission
Action
__init__.py
5141 bytes
0644
__init__.pyc
2406 bytes
0644
__init__.pyo
2406 bytes
0644
fix_UserDict.py
3840 bytes
0644
fix_UserDict.pyc
2903 bytes
0644
fix_UserDict.pyo
2903 bytes
0644
fix_absolute_import.py
3140 bytes
0644
fix_absolute_import.pyc
3022 bytes
0644
fix_absolute_import.pyo
3022 bytes
0644
fix_add__future__imports_except_unicode_literals.py
662 bytes
0644
fix_add__future__imports_except_unicode_literals.pyc
1336 bytes
0644
fix_add__future__imports_except_unicode_literals.pyo
1336 bytes
0644
fix_basestring.py
394 bytes
0644
fix_basestring.pyc
1007 bytes
0644
fix_basestring.pyo
1007 bytes
0644
fix_bytes.py
685 bytes
0644
fix_bytes.pyc
1311 bytes
0644
fix_bytes.pyo
1311 bytes
0644
fix_cmp.py
701 bytes
0644
fix_cmp.pyc
1321 bytes
0644
fix_cmp.pyo
1321 bytes
0644
fix_division.py
228 bytes
0644
fix_division.pyc
438 bytes
0644
fix_division.pyo
438 bytes
0644
fix_division_safe.py
3460 bytes
0644
fix_division_safe.pyc
4468 bytes
0644
fix_division_safe.pyo
4468 bytes
0644
fix_execfile.py
921 bytes
0644
fix_execfile.pyc
1556 bytes
0644
fix_execfile.pyo
1556 bytes
0644
fix_future_builtins.py
2027 bytes
0644
fix_future_builtins.pyc
1957 bytes
0644
fix_future_builtins.pyo
1957 bytes
0644
fix_future_standard_library.py
733 bytes
0644
fix_future_standard_library.pyc
1256 bytes
0644
fix_future_standard_library.pyo
1256 bytes
0644
fix_future_standard_library_urllib.py
1001 bytes
0644
fix_future_standard_library_urllib.pyc
1342 bytes
0644
fix_future_standard_library_urllib.pyo
1342 bytes
0644
fix_metaclass.py
9568 bytes
0644
fix_metaclass.pyc
7373 bytes
0644
fix_metaclass.pyo
7373 bytes
0644
fix_next_call.py
3158 bytes
0644
fix_next_call.pyc
3736 bytes
0644
fix_next_call.pyo
3703 bytes
0644
fix_object.py
407 bytes
0644
fix_object.pyc
997 bytes
0644
fix_object.pyo
997 bytes
0644
fix_oldstr_wrap.py
1214 bytes
0644
fix_oldstr_wrap.pyc
1728 bytes
0644
fix_oldstr_wrap.pyo
1728 bytes
0644
fix_order___future__imports.py
829 bytes
0644
fix_order___future__imports.pyc
1247 bytes
0644
fix_order___future__imports.pyo
1247 bytes
0644
fix_print.py
3384 bytes
0644
fix_print.pyc
2879 bytes
0644
fix_print.pyo
2782 bytes
0644
fix_print_with_import.py
735 bytes
0644
fix_print_with_import.pyc
1129 bytes
0644
fix_print_with_import.pyo
1129 bytes
0644
fix_raise.py
2167 bytes
0644
fix_raise.pyc
2126 bytes
0644
fix_raise.pyo
2126 bytes
0644
fix_remove_old__future__imports.py
851 bytes
0644
fix_remove_old__future__imports.pyc
1479 bytes
0644
fix_remove_old__future__imports.pyo
1479 bytes
0644
fix_unicode_keep_u.py
779 bytes
0644
fix_unicode_keep_u.pyc
1413 bytes
0644
fix_unicode_keep_u.pyo
1413 bytes
0644
fix_unicode_literals_import.py
367 bytes
0644
fix_unicode_literals_import.pyc
1029 bytes
0644
fix_unicode_literals_import.pyo
1029 bytes
0644
fix_xrange_with_import.py
479 bytes
0644
fix_xrange_with_import.pyc
1060 bytes
0644
fix_xrange_with_import.pyo
1060 bytes
0644
N4ST4R_ID | Naxtarrr