@@ -142,89 +142,65 @@ def get_element_text(self, element):
142142 text = ''
143143 return text
144144
145- class JythonImageProcess :
146- '''Class to manage communicating with a remote process. We could eventually have multiple instances going at once.'''
147- running_re = re .compile (r'^:RUNNING:(.+)$' )
148- success_re = re .compile (r'^:SUCCESS:$' )
149- failure_re = re .compile (r'^:FAILURE:$' )
150-
151- @staticmethod
152- def make_jython_command (processing_py_jar = "./processing-py.jar" ,
153- javabin = "java" ):
154- return [javabin , '-cp' , processing_py_jar , 'org.python.util.jython' ]
155-
156- @staticmethod
157- def create_args (processing_py_jar , jython_dir , workitems ):
158- command = JythonImageProcess .make_jython_command (processing_py_jar )
159- jython_script = os .path .join (jython_dir , 'generate_images.py' )
160- if not os .path .exists (jython_script ):
161- raise IOError ("Can't find jython script to run..." )
162- command += [jython_script ]
163- command += ['--todo' ] + ['{}:{}:{}' .format (ex ['name' ], ex ['scriptfile' ], ex ['imagefile' ]) for ex in workitems .itervalues ()]
164- return command
165-
166- def __init__ (self , processing_py_jar , jython_dir , workitems ):
167- self .current = None
168- self .generated = {}
169- self .failed = {}
170- self .workitems = workitems
171- args = JythonImageProcess .create_args (processing_py_jar , jython_dir , workitems )
172- print (args , file = sys .stderr )
173- self .popen = subprocess .Popen (args , stdout = subprocess .PIPE , stderr = subprocess .STDOUT , bufsize = 1 ) # line-buffered
174- self .comthread = threading .Thread (target = self .consume_communication , args = ())
175- self .comthread .start ()
176-
177- def consume_communication (self ):
178- for line in iter (self .popen .stdout .readline , '' ):
179- running = JythonImageProcess .running_re .match (line )
180- if running :
181- self .current = self .workitems [running .group (1 )]
182- print ("{} ... RUNNING: {}" .format (self .desc , self .current ['name' ]))
183- continue
184- success = JythonImageProcess .success_re .match (line )
185- if success :
186- print ("{} ... SUCCESS: " .format (self .desc ), end = '' )
187- print_success ("{} -> {}" .format (self .current ['name' ], self .current ['imagefile' ]))
188- self .generated [self .current ['name' ]] = self .current
189- self .current = None
190- continue
191- failure = JythonImageProcess .failure_re .match (line )
192- if failure :
193- print ("{} ... FAILURE: " .format (self .desc ), end = '' )
194- print_error (self .current ['name' ])
195- self .failed [self .current ['name' ]] = self .current
196- self .current = None
197- continue
198- # Not a success or failure, must be debug messages
199- print ("{} ... DEBUG: {}" .format (self .desc , line ), end = '' )
200-
201- def is_complete (self ):
202- return self .popen .poll () != None
203-
204- def exited_well (self ):
205- return self .popen .returncode == 0
206-
207- def print_debug (self ):
208- print ("Debug from {}:" .format (self .desc ()))
209- for line in self .err_blob :
210- print ("{}: {}" .format (self .desc (), line ))
211-
212- @property
213- def desc (self ):
214- return 'Image Process'
215-
216145export_image_postlude = r'''
217146save('{imagefile}')
218147exit()
219148'''
220149
221- def generate_images (items_dict , to_update , src_dir , processing_py_jar , target_image_dir ):
150+ # run an instance of generate_images.py, capturing and recording its output.
151+ # base_cmd should be a list-formatted command-line to run the
152+ # generate_images.py script, suitable for passing to subprocess.Popen;
153+ # workitems should be a list of dictionaries describing the scripts to be run.
154+ def image_worker (base_cmd , workitems ):
155+
156+ workitems_cmdline_param = ['{}:{}:{}' .format (ex ['name' ], ex ['scriptfile' ], ex ['imagefile' ]) \
157+ for ex in workitems .itervalues ()]
158+ process = subprocess .Popen (base_cmd + workitems_cmdline_param , stdout = subprocess .PIPE ,
159+ stderr = subprocess .STDOUT , bufsize = 1 )
160+ generated = {}
161+ failed = {}
162+ current = None
163+
164+ for line in iter (process .stdout .readline , '' ):
165+ m = re .search (r'^:RUNNING:(.+)$' , line )
166+ if m :
167+ current = workitems [m .group (1 )]
168+ print ("{} ... RUNNING: {}" .format ('Image process' , current ['name' ]))
169+ continue
170+ m = re .search (r'^:SUCCESS:$' , line )
171+ if m :
172+ print ("{} ... SUCCESS: " .format ('Image process' ), end = '' )
173+ print_success ("{} -> {}" .format (current ['name' ], current ['imagefile' ]))
174+ generated [current ['name' ]] = current
175+ current = None
176+ continue
177+ m = re .search (r'^:FAILURE:$' , line )
178+ if m :
179+ print ("{} ... FAILURE: " .format ('Image process' ), end = '' )
180+ print_error (current ['name' ])
181+ failed [current ['name' ]] = current
182+ current = None
183+ continue
184+ # Not a success or failure, must be debug messages
185+ print ("{} ... DEBUG: {}" .format ('Image process' , line ), end = '' )
186+
187+ process .wait ()
188+ if process .returncode == 0 :
189+ print ("Image process terminated successfully." )
190+ else :
191+ print_error ("Image process terminated unsuccessfully." )
192+ if current :
193+ failed [current ['name' ]] = current
194+ return generated , failed
195+
196+ def generate_images (items_dict , to_update , src_dir , processing_py_jar ,
197+ target_image_dir , javabin = "java" ):
222198 '''Generate images from examples and return the number of failures.'''
223199 workitems = {} # Examples to run
224200 work_dir = tempfile .mkdtemp (prefix = 'processing-py-site-build' )
225- jython_dir = os .path .join (src_dir , 'jython' )
226- if not os .path .exists (jython_dir ):
227- raise IOError ("{} doesn't exist; can't generate images." .format (jython_dir ))
201+ generate_img_script = os .path .join (src_dir , 'jython' , 'generate_images.py ' )
202+ if not os .path .exists (generate_img_script ):
203+ raise IOError ("{} doesn't exist; can't generate images." .format (generate_img_script ))
228204
229205 for name in to_update :
230206 item = items_dict [name ]
@@ -245,31 +221,12 @@ def generate_images(items_dict, to_update, src_dir, processing_py_jar, target_im
245221 print ("Skipping image generation, everything up to date" )
246222 return 0
247223
248- process = None
249- generated = {}
250- failed = {}
251-
252- while workitems :
253- if not process :
254- print ("Starting image process" )
255- process = JythonImageProcess (processing_py_jar , jython_dir , workitems )
224+ base_cmd = [javabin , "-cp" , processing_py_jar , "org.python.util.jython" ,
225+ generate_img_script , '--todo' ]
256226
257- if process .is_complete ():
258- if process .exited_well ():
259- print ("{} terminated successfully." .format (process .desc ))
260- else :
261- print_error ("{} terminated unsuccessfully." .format (process .desc ))
262- if process .current :
263- process .failed [process .current ['name' ]] = process .current
264- for workitem in process .generated .itervalues ():
265- generated [workitem ['name' ]] = workitem
266- del workitems [workitem ['name' ]]
267- for workitem in process .failed .itervalues ():
268- failed [workitem ['name' ]] = workitem
269- del workitems [workitem ['name' ]]
270- process = None
271-
272- time .sleep (0.2 )
227+ # TODO: use the multiprocessing module's Pool class to run multiple
228+ # instances of this at once
229+ generated , failed = image_worker (base_cmd , workitems )
273230
274231 print ("Generated images:" )
275232 for workitem in generated .itervalues ():
0 commit comments