8
8
provides infrastructure to write your own refactoring tool.
9
9
"""
10
10
11
+ from __future__ import with_statement
12
+
11
13
__author__ = "Guido van Rossum <guido@python.org>"
12
14
13
15
@@ -122,13 +124,14 @@ def _to_system_newlines(input):
122
124
_to_system_newlines = _identity
123
125
124
126
125
- def _detect_future_print (source ):
127
+ def _detect_future_features (source ):
126
128
have_docstring = False
127
129
gen = tokenize .generate_tokens (io .StringIO (source ).readline )
128
130
def advance ():
129
131
tok = next (gen )
130
132
return tok [0 ], tok [1 ]
131
133
ignore = frozenset ((token .NEWLINE , tokenize .NL , token .COMMENT ))
134
+ features = set ()
132
135
try :
133
136
while True :
134
137
tp , value = advance ()
@@ -140,26 +143,25 @@ def advance():
140
143
have_docstring = True
141
144
elif tp == token .NAME and value == "from" :
142
145
tp , value = advance ()
143
- if tp != token .NAME and value != "__future__" :
146
+ if tp != token .NAME or value != "__future__" :
144
147
break
145
148
tp , value = advance ()
146
- if tp != token .NAME and value != "import" :
149
+ if tp != token .NAME or value != "import" :
147
150
break
148
151
tp , value = advance ()
149
152
if tp == token .OP and value == "(" :
150
153
tp , value = advance ()
151
154
while tp == token .NAME :
152
- if value == "print_function" :
153
- return True
155
+ features .add (value )
154
156
tp , value = advance ()
155
- if tp != token .OP and value != "," :
157
+ if tp != token .OP or value != "," :
156
158
break
157
159
tp , value = advance ()
158
160
else :
159
161
break
160
162
except StopIteration :
161
163
pass
162
- return False
164
+ return frozenset ( features )
163
165
164
166
165
167
class FixerError (Exception ):
@@ -341,7 +343,8 @@ def refactor_string(self, data, name):
341
343
An AST corresponding to the refactored input stream; None if
342
344
there were errors during the parse.
343
345
"""
344
- if _detect_future_print (data ):
346
+ features = _detect_future_features (data )
347
+ if "print_function" in features :
345
348
self .driver .grammar = pygram .python_grammar_no_print_statement
346
349
try :
347
350
tree = self .driver .parse_string (data )
@@ -351,6 +354,7 @@ def refactor_string(self, data, name):
351
354
return
352
355
finally :
353
356
self .driver .grammar = self .grammar
357
+ tree .future_features = features
354
358
self .log_debug ("Refactoring %s" , name )
355
359
self .refactor_tree (tree , name )
356
360
return tree
@@ -605,6 +609,7 @@ class MultiprocessRefactoringTool(RefactoringTool):
605
609
def __init__ (self , * args , ** kwargs ):
606
610
super (MultiprocessRefactoringTool , self ).__init__ (* args , ** kwargs )
607
611
self .queue = None
612
+ self .output_lock = None
608
613
609
614
def refactor (self , items , write = False , doctests_only = False ,
610
615
num_processes = 1 ):
@@ -618,6 +623,7 @@ def refactor(self, items, write=False, doctests_only=False,
618
623
if self .queue is not None :
619
624
raise RuntimeError ("already doing multiple processes" )
620
625
self .queue = multiprocessing .JoinableQueue ()
626
+ self .output_lock = multiprocessing .Lock ()
621
627
processes = [multiprocessing .Process (target = self ._child )
622
628
for i in range (num_processes )]
623
629
try :
0 commit comments