def test_process_crash(self): """ Test a script which simulates a crash """ temp_folder = tempfile.mkdtemp() script_file = os.path.join(temp_folder, 'crash_process.sh') with open(script_file, 'wt') as f: f.write('kill $$') os.chmod(script_file, 0o775) def std_out(ba): std_out.val += ba.data().decode('UTF-8') std_out.val = '' def std_err(ba): std_err.val += ba.data().decode('UTF-8') std_err.val = '' p = QgsBlockingProcess('sh', [script_file]) p.setStdOutHandler(std_out) p.setStdErrHandler(std_err) f = QgsFeedback() self.assertNotEqual(p.run(f), 0) self.assertEqual(p.exitStatus(), QProcess.CrashExit)
def test_process_err(self): def std_out(ba): std_out.val += ba.data().decode('UTF-8') std_out.val = '' def std_err(ba): std_err.val += ba.data().decode('UTF-8') std_err.val = '' p = QgsBlockingProcess('ogrinfo', []) p.setStdOutHandler(std_out) p.setStdErrHandler(std_err) f = QgsFeedback() self.assertEqual(p.run(f), 1) self.assertEqual(p.exitStatus(), QProcess.NormalExit) self.assertIn('Usage', std_out.val) self.assertIn('FAILURE', std_err.val)
def test_process_ok(self): def std_out(ba): std_out.val += ba.data().decode('UTF-8') std_out.val = '' def std_err(ba): std_err.val += ba.data().decode('UTF-8') std_err.val = '' p = QgsBlockingProcess('ogrinfo', ['--version']) p.setStdOutHandler(std_out) p.setStdErrHandler(std_err) f = QgsFeedback() self.assertEqual(p.run(f), 0) self.assertIn('GDAL', std_out.val) self.assertEqual(std_err.val, '')
def runGdal(commands, feedback=None): if feedback is None: feedback = QgsProcessingFeedback() envval = os.getenv('PATH') # We need to give some extra hints to get things picked up on OS X isDarwin = False try: isDarwin = platform.system() == 'Darwin' except IOError: # https://travis-ci.org/m-kuhn/QGIS#L1493-L1526 pass if isDarwin and os.path.isfile(os.path.join(QgsApplication.prefixPath(), "bin", "gdalinfo")): # Looks like there's a bundled gdal. Let's use it. os.environ['PATH'] = "{}{}{}".format(os.path.join(QgsApplication.prefixPath(), "bin"), os.pathsep, envval) os.environ['DYLD_LIBRARY_PATH'] = os.path.join(QgsApplication.prefixPath(), "lib") else: # Other platforms should use default gdal finder codepath settings = QgsSettings() path = settings.value('/GdalTools/gdalPath', '') if not path.lower() in envval.lower().split(os.pathsep): envval += '{}{}'.format(os.pathsep, path) os.putenv('PATH', envval) fused_command = ' '.join([str(c) for c in commands]) QgsMessageLog.logMessage(fused_command, 'Processing', Qgis.Info) feedback.pushInfo(GdalUtils.tr('GDAL command:')) feedback.pushCommandInfo(fused_command) feedback.pushInfo(GdalUtils.tr('GDAL command output:')) loglines = [GdalUtils.tr('GDAL execution console output')] def on_stdout(ba): val = ba.data().decode('UTF-8') # catch progress reports if val == '100 - done.': on_stdout.progress = 100 feedback.setProgress(on_stdout.progress) elif val in ('0', '10', '20', '30', '40', '50', '60', '70', '80', '90'): on_stdout.progress = int(val) feedback.setProgress(on_stdout.progress) elif val == '.': on_stdout.progress += 2.5 feedback.setProgress(on_stdout.progress) on_stdout.buffer += val if on_stdout.buffer.endswith('\n') or on_stdout.buffer.endswith('\r'): # flush buffer feedback.pushConsoleInfo(on_stdout.buffer.rstrip()) loglines.append(on_stdout.buffer.rstrip()) on_stdout.buffer = '' on_stdout.progress = 0 on_stdout.buffer = '' def on_stderr(ba): val = ba.data().decode('UTF-8') on_stderr.buffer += val if on_stderr.buffer.endswith('\n') or on_stderr.buffer.endswith('\r'): # flush buffer feedback.reportError(on_stderr.buffer.rstrip()) loglines.append(on_stderr.buffer.rstrip()) on_stderr.buffer = '' on_stderr.buffer = '' command, *arguments = QgsRunProcess.splitCommand(fused_command) proc = QgsBlockingProcess(command, arguments) proc.setStdOutHandler(on_stdout) proc.setStdErrHandler(on_stderr) res = proc.run(feedback) if feedback.isCanceled() and res != 0: feedback.pushInfo(GdalUtils.tr('Process was canceled and did not complete')) elif not feedback.isCanceled() and proc.exitStatus() == QProcess.CrashExit: raise QgsProcessingException(GdalUtils.tr('Process was unexpectedly terminated')) elif res == 0: feedback.pushInfo(GdalUtils.tr('Process completed successfully')) elif proc.processError() == QProcess.FailedToStart: raise QgsProcessingException(GdalUtils.tr('Process {} failed to start. Either {} is missing, or you may have insufficient permissions to run the program.').format(command, command)) else: feedback.reportError(GdalUtils.tr('Process returned error code {}').format(res)) return loglines
def test_process_env(self): """ Test that process inherits system environment correctly """ temp_folder = tempfile.mkdtemp() script_file = os.path.join(temp_folder, 'process_env.sh') with open(script_file, 'wt') as f: f.write('echo $my_var') os.chmod(script_file, 0o775) def std_out(ba): std_out.val += ba.data().decode('UTF-8') std_out.val = '' def std_err(ba): std_err.val += ba.data().decode('UTF-8') std_err.val = '' # environment variable not set: p = QgsBlockingProcess('sh', [script_file]) p.setStdOutHandler(std_out) p.setStdErrHandler(std_err) f = QgsFeedback() self.assertEqual(p.run(f), 0) self.assertEqual(p.exitStatus(), QProcess.NormalExit) self.assertFalse(std_out.val.strip()) self.assertFalse(std_err.val.strip()) # set environment variable os.environ['my_var'] = 'my test variable' std_out.val = '' std_err.val = '' p = QgsBlockingProcess('sh', [script_file]) p.setStdOutHandler(std_out) p.setStdErrHandler(std_err) f = QgsFeedback() self.assertEqual(p.run(f), 0) self.assertEqual(p.exitStatus(), QProcess.NormalExit) self.assertEqual(std_out.val.strip(), 'my test variable') self.assertFalse(std_err.val.strip()) # test python changing path script_file = os.path.join(temp_folder, 'process_env_path.sh') with open(script_file, 'wt') as f: f.write('echo $PATH') prev_path_val = os.getenv('PATH') new_path = "{}{}{}".format('/my_test/folder', os.pathsep, prev_path_val) os.environ['PATH'] = new_path std_out.val = '' std_err.val = '' p = QgsBlockingProcess('sh', [script_file]) p.setStdOutHandler(std_out) p.setStdErrHandler(std_err) f = QgsFeedback() self.assertEqual(p.run(f), 0) self.assertEqual(p.exitStatus(), QProcess.NormalExit) self.assertEqual(std_out.val.strip(), new_path) self.assertFalse(std_err.val.strip())