]>
git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.2/Lib/lib2to3/fixes/fix_metaclass.py
1 """Fixer for __metaclass__ = X -> (metaclass=X) methods.
3 The various forms of classef (inherits nothing, inherits once, inherints
4 many) don't parse the same in the CST so we look at ALL classes for
5 a __metaclass__ and if we find one normalize the inherits to all be
8 For one-liner classes ('class X: pass') there is no indent/dedent so
9 we normalize those into having a suite.
11 Moving the __metaclass__ into the classdef can also cause the class
12 body to be empty so there is some special casing for that as well.
14 This fixer also tries very hard to keep original indenting and spacing
15 in all those corner cases.
18 # Author: Jack Diederich
21 from .. import fixer_base
22 from ..pygram
import token
23 from ..fixer_util
import Name
, syms
, Node
, Leaf
26 def has_metaclass(parent
):
27 """ we have to check the cls_node without changing it.
28 There are two possiblities:
29 1) clsdef => suite => simple_stmt => expr_stmt => Leaf('__meta')
30 2) clsdef => simple_stmt => expr_stmt => Leaf('__meta')
32 for node
in parent
.children
:
33 if node
.type == syms
.suite
:
34 return has_metaclass(node
)
35 elif node
.type == syms
.simple_stmt
and node
.children
:
36 expr_node
= node
.children
[0]
37 if expr_node
.type == syms
.expr_stmt
and expr_node
.children
:
38 left_side
= expr_node
.children
[0]
39 if isinstance(left_side
, Leaf
) and \
40 left_side
.value
== '__metaclass__':
45 def fixup_parse_tree(cls_node
):
46 """ one-line classes don't get a suite in the parse tree so we add
47 one to normalize the tree
49 for node
in cls_node
.children
:
50 if node
.type == syms
.suite
:
51 # already in the preferred format, do nothing
54 # !%@#! oneliners have no suite node, we have to fake one up
55 for i
, node
in enumerate(cls_node
.children
):
56 if node
.type == token
.COLON
:
59 raise ValueError("No class suite and no ':'!")
61 # move everything into a suite node
62 suite
= Node(syms
.suite
, [])
63 while cls_node
.children
[i
+1:]:
64 move_node
= cls_node
.children
[i
+1]
65 suite
.append_child(move_node
.clone())
67 cls_node
.append_child(suite
)
71 def fixup_simple_stmt(parent
, i
, stmt_node
):
72 """ if there is a semi-colon all the parts count as part of the same
73 simple_stmt. We just want the __metaclass__ part so we move
74 everything efter the semi-colon into its own simple_stmt node
76 for semi_ind
, node
in enumerate(stmt_node
.children
):
77 if node
.type == token
.SEMI
: # *sigh*
82 node
.remove() # kill the semicolon
83 new_expr
= Node(syms
.expr_stmt
, [])
84 new_stmt
= Node(syms
.simple_stmt
, [new_expr
])
85 while stmt_node
.children
[semi_ind
:]:
86 move_node
= stmt_node
.children
[semi_ind
]
87 new_expr
.append_child(move_node
.clone())
89 parent
.insert_child(i
, new_stmt
)
90 new_leaf1
= new_stmt
.children
[0].children
[0]
91 old_leaf1
= stmt_node
.children
[0].children
[0]
92 new_leaf1
.prefix
= old_leaf1
.prefix
95 def remove_trailing_newline(node
):
96 if node
.children
and node
.children
[-1].type == token
.NEWLINE
:
97 node
.children
[-1].remove()
100 def find_metas(cls_node
):
101 # find the suite node (Mmm, sweet nodes)
102 for node
in cls_node
.children
:
103 if node
.type == syms
.suite
:
106 raise ValueError("No class suite!")
108 # look for simple_stmt[ expr_stmt[ Leaf('__metaclass__') ] ]
109 for i
, simple_node
in list(enumerate(node
.children
)):
110 if simple_node
.type == syms
.simple_stmt
and simple_node
.children
:
111 expr_node
= simple_node
.children
[0]
112 if expr_node
.type == syms
.expr_stmt
and expr_node
.children
:
113 # Check if the expr_node is a simple assignment.
114 left_node
= expr_node
.children
[0]
115 if isinstance(left_node
, Leaf
) and \
116 left_node
.value
== u
'__metaclass__':
117 # We found a assignment to __metaclass__.
118 fixup_simple_stmt(node
, i
, simple_node
)
119 remove_trailing_newline(simple_node
)
120 yield (node
, i
, simple_node
)
123 def fixup_indent(suite
):
124 """ If an INDENT is followed by a thing with a prefix then nuke the prefix
125 Otherwise we get in trouble when removing __metaclass__ at suite start
127 kids
= suite
.children
[::-1]
128 # find the first indent
131 if node
.type == token
.INDENT
:
134 # find the first Leaf
137 if isinstance(node
, Leaf
) and node
.type != token
.DEDENT
:
142 kids
.extend(node
.children
[::-1])
145 class FixMetaclass(fixer_base
.BaseFix
):
152 def transform(self
, node
, results
):
153 if not has_metaclass(node
):
156 fixup_parse_tree(node
)
158 # find metaclasses, keep the last one
159 last_metaclass
= None
160 for suite
, i
, stmt
in find_metas(node
):
161 last_metaclass
= stmt
164 text_type
= node
.children
[0].type # always Leaf(nnn, 'class')
166 # figure out what kind of classdef we have
167 if len(node
.children
) == 7:
168 # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
170 if node
.children
[3].type == syms
.arglist
:
171 arglist
= node
.children
[3]
172 # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
174 parent
= node
.children
[3].clone()
175 arglist
= Node(syms
.arglist
, [parent
])
176 node
.set_child(3, arglist
)
177 elif len(node
.children
) == 6:
178 # Node(classdef, ['class', 'name', '(', ')', ':', suite])
180 arglist
= Node(syms
.arglist
, [])
181 node
.insert_child(3, arglist
)
182 elif len(node
.children
) == 4:
183 # Node(classdef, ['class', 'name', ':', suite])
185 arglist
= Node(syms
.arglist
, [])
186 node
.insert_child(2, Leaf(token
.RPAR
, u
')'))
187 node
.insert_child(2, arglist
)
188 node
.insert_child(2, Leaf(token
.LPAR
, u
'('))
190 raise ValueError("Unexpected class definition")
192 # now stick the metaclass in the arglist
193 meta_txt
= last_metaclass
.children
[0].children
[0]
194 meta_txt
.value
= 'metaclass'
195 orig_meta_prefix
= meta_txt
.prefix
198 arglist
.append_child(Leaf(token
.COMMA
, u
','))
199 meta_txt
.prefix
= u
' '
201 meta_txt
.prefix
= u
''
203 # compact the expression "metaclass = Meta" -> "metaclass=Meta"
204 expr_stmt
= last_metaclass
.children
[0]
205 assert expr_stmt
.type == syms
.expr_stmt
206 expr_stmt
.children
[1].prefix
= u
''
207 expr_stmt
.children
[2].prefix
= u
''
209 arglist
.append_child(last_metaclass
)
213 # check for empty suite
214 if not suite
.children
:
215 # one-liner that was just __metaclass_
217 pass_leaf
= Leaf(text_type
, u
'pass')
218 pass_leaf
.prefix
= orig_meta_prefix
219 node
.append_child(pass_leaf
)
220 node
.append_child(Leaf(token
.NEWLINE
, u
'\n'))
222 elif len(suite
.children
) > 1 and \
223 (suite
.children
[-2].type == token
.INDENT
and
224 suite
.children
[-1].type == token
.DEDENT
):
225 # there was only one line in the class body and it was __metaclass__
226 pass_leaf
= Leaf(text_type
, u
'pass')
227 suite
.insert_child(-1, pass_leaf
)
228 suite
.insert_child(-1, Leaf(token
.NEWLINE
, u
'\n'))