def _run_esqloc(self, file_path): """ Run the esqloc process and returns it's exit code and output (both stderr and stdout). :param file_path: .sqb path. :return: int, str, str """ path = os.path.dirname(file_path) source = os.path.split(file_path)[1] destination = os.path.splitext(source)[0] + '.cob' pgm, options = self.make_command(source, destination) process = QtCore.QProcess() process.setWorkingDirectory(path) process.setProcessChannelMode(QtCore.QProcess.MergedChannels) cmd = '%s %s' % (pgm, ' '.join(options)) _logger().info('command: %s', cmd) _logger().debug('working directory: %s', path) _logger().debug('system environment: %s', process.systemEnvironment()) process.start(pgm, options) self.started.emit(cmd) process.waitForFinished() status = process.exitCode() try: output = process.readAllStandardOutput().data().decode( locale.getpreferredencoding()) except UnicodeDecodeError: output = 'Failed to decode esqloc output with encoding: ' % \ locale.getpreferredencoding() self.output_available.emit(output) return output, status, destination
def _run_command(pgm, args): if ' ' in pgm: pgm = '"%s"' % pgm p = QtCore.QProcess() p.setProcessChannelMode(QtCore.QProcess.MergedChannels) p.setProcessEnvironment(GnuCobolCompiler.setup_process_environment()) p.start(pgm, args) p.waitForFinished() # determine exit code (handle crashed processes) if p.exitStatus() != p.Crashed: status = p.exitCode() else: status = 139 # get compiler output try: output = p.readAllStandardOutput().data().decode( locale.getpreferredencoding()).replace('\r\n', '\n') except UnicodeDecodeError: output = 'Failed to decode compiler output with encoding %s' % \ locale.getpreferredencoding() return status, output
def _check_compiler(self, *_): self.apply() pth = self.lineEditCompilerPath.text() if os.path.exists(pth) or system.which(pth) is not None: p = QtCore.QProcess() p.start(pth, ['--version']) p.waitForFinished() output = bytes(p.readAllStandardOutput()).decode( locale.getpreferredencoding()) DlgCheckCompiler.check(self, pth, output) else: QtWidgets.QMessageBox.warning( self, 'Invalid compiler path', 'Not a valid compiler path, path does not exists: %s!' % pth)
def lint(request_data): """ Performs linting of a COBOL document. This method will perform on the pyqode backend. :param request_data: work request data (dict) :return: status, messages """ print('running open_cobol_ide.linter.lint') code = request_data['code'] path = request_data['path'] extension = os.path.splitext(path)[1] print(('valid compiler extensions: %r' % settings.Settings().cobc_extensions)) messages = [] if extension.lower() in settings.Settings().cobc_extensions: # code might not have been saved yet, run cobc on a tmp file # we use a time stamp to avoid overwriting the file another cobc # instance might be compiling. file_name = os.path.split(path)[1] file_name, ext = os.path.splitext(file_name) tmp_name = '%s.%s%s' % (file_name, str(int(time.time())), ext) tmp_pth = os.path.join(tempfile.gettempdir(), tmp_name) print(('writing code to temporary file: %r' % tmp_pth)) with open(tmp_pth, 'w') as f: f.write(code) compiler = GnuCobolCompiler() pgm, args = make_linter_command(tmp_name, path) print(('linter command: %s %s' % (pgm, ' '.join(args)))) process = QtCore.QProcess() process.setProcessEnvironment( GnuCobolCompiler.setup_process_environment()) process.setWorkingDirectory(os.path.dirname(tmp_pth)) process.setProcessChannelMode(QtCore.QProcess.MergedChannels) print('running compiler process') print(('working directory: %s' % process.workingDirectory())) process.start(pgm, args) print('waiting for compilation to finish...') process.waitForFinished() output = process.readAllStandardOutput().data().decode( locale.getpreferredencoding()) print(('linter raw output: %s' % output)) messages = compiler.parse_output(output, process.workingDirectory()) print(('linter parsed output: %r' % messages)) print('removing temporary file...') os.remove(tmp_pth) return messages
def check_compiler(cls, compiler): if Settings().vcvars32: try: VisualStudioWrapperBatch.generate() except OSError as e: _logger().exception('failed to generate visual studio wrapper ' 'batch') return str(e), 1 compiler = VisualStudioWrapperBatch.path() from open_cobol_ide.view.dialogs.preferences import DEFAULT_TEMPLATE cbl_path = os.path.join(tempfile.gettempdir(), 'test.cbl') with open(cbl_path, 'w') as f: f.write(DEFAULT_TEMPLATE) dest = os.path.join(tempfile.gettempdir(), 'test' + ('.exe' if system.windows else '')) p = QtCore.QProcess() args = ['-x', '-o', dest, cbl_path] p.start(compiler, args) _logger().debug('check compiler') _logger().debug('process environment: %r', p.processEnvironment().toStringList()) _logger().debug('command: %s %s', compiler, ' '.join(args)) p.waitForFinished() try: stdout = bytes(p.readAllStandardOutput()).decode( locale.getpreferredencoding()) stderr = bytes(p.readAllStandardError()).decode( locale.getpreferredencoding()) except UnicodeDecodeError: # something is wrong in the output, the compiler might be broker output = None else: output = stderr + stdout if p.exitStatus() == p.Crashed or output is None: exit_code = 139 else: exit_code = p.exitCode() _logger().debug('process output: %r', output) _logger().debug('process exit code: %r', exit_code) _logger().info('GnuCOBOL compiler check: %s', 'success' if exit_code == 0 else 'fail') try: os.remove(dest) os.remove(cbl_path) except OSError: pass return output, p.exitCode()
def run_pip_command(self, interpreter, worker_function, package, operation): """ Run a pip command. The command is run on the backend for the current interpreter. :param interpreter: Interpreter which is going to run the backend :param worker_function: The worker function to execute. :param package: The list of packages to install, as a string where each item is separated by a space. :param operation: Operation title (used for the info label) """ self.stop_backend() self.ui.lblInfos.setText(operation) self._worker = worker_function self._package = package self.stop_backend() self.backend = BackendManager(self) process = BackendProcess(self.parent()) process.finished.connect(self._on_process_finished) self.backend._process = process server_script = server.__file__.replace('.pyc', '.py') port = self.backend.pick_free_port() self.backend._port = port if LINUX and self._need_root_perms(interpreter): _logger().info('running pip command with root privileges') auth = get_authentication_program() if 'kdesu' in auth: # no quotes around command when using kdesu cmd = '%s %s %s %s --syspath %s' else: # gksu requires quotes around command cmd = '%s "%s %s %s --syspath %s"' cmd = cmd % (auth, interpreter, server_script, str(port), get_library_zip_path()) process.start(cmd) elif DARWIN and self._need_root_perms(interpreter): cmd = 'sudo %s %s %s --syspath %s' % ( interpreter, server_script, str(port), get_library_zip_path()) auth_process = QtCore.QProcess() auth_process.start('pseudo') auth_process.waitForFinished() process.start(cmd) else: self.backend.start(server.__file__, interpreter=interpreter, args=['-s'] + [get_library_zip_path()]) QtCore.QTimer.singleShot(100, self._run_command)
def _check_compiler(self, *_): from open_cobol_ide.app import Application self.apply() Application.init_env() pth = self.lineEditCompilerPath.text() if os.path.exists(pth): p = QtCore.QProcess() p.start(pth, ['--version']) p.waitForFinished() output = bytes(p.readAllStandardOutput()).decode( locale.getpreferredencoding()) DlgCheckCompiler.check(self, pth, output) else: QtWidgets.QMessageBox.warning( self, 'Invalid compiler path', 'Not a valid compiler path, path does not exists: %s!' % pth)
def run_command(pgm, args, working_dir=''): if ' ' in pgm: pgm = '"%s"' % pgm path_cpy = os.environ['PATH'] p_env = GnuCobolCompiler.setup_process_environment() os.environ['PATH'] = p_env.value('PATH') p = QtCore.QProcess() p.setProcessChannelMode(QtCore.QProcess.MergedChannels) if working_dir: p.setWorkingDirectory(working_dir) p.setProcessEnvironment(p_env) _logger().debug('command: %s', ' '.join([pgm] + args)) _logger().debug('working directory: %s', working_dir) _logger().debug('environment: %s', p.processEnvironment().toStringList()) p.start(pgm, args) print(' '.join([pgm] + args)) p.waitForFinished() # determine exit code (handle crashed processes) if p.exitStatus() != p.Crashed: status = p.exitCode() else: status = 139 # get compiler output raw_output = p.readAllStandardOutput().data() try: output = raw_output.decode(locale.getpreferredencoding()) except UnicodeDecodeError: # This is a hack to get a meaningful output when compiling a file # from UNC path using a batch file on some systems, see # https://github.com/OpenCobolIDE/OpenCobolIDE/issues/188 output = str(raw_output).replace("b'", '')[:-1].replace( '\\r\\n', '\n').replace('\\\\', '\\') _logger().debug('output: %r', output) _logger().debug('exit code: %r', status) os.environ['PATH'] = path_cpy print(output) return status, output
def run_command(pgm, args, working_dir=''): if ' ' in pgm: pgm = '"%s"' % pgm path_cpy = os.environ['PATH'] p_env = GnuCobolCompiler.setup_process_environment() os.environ['PATH'] = p_env.value('PATH') p = QtCore.QProcess() p.setProcessChannelMode(QtCore.QProcess.MergedChannels) if working_dir: p.setWorkingDirectory(working_dir) p.setProcessEnvironment(p_env) _logger().debug('command: %s', ' '.join([pgm] + args)) _logger().debug('working directory: %s', working_dir) _logger().debug('environment: %s', p.processEnvironment().toStringList()) p.start(pgm, args) p.waitForFinished() # determine exit code (handle crashed processes) if p.exitStatus() != p.Crashed: status = p.exitCode() else: status = 139 # get compiler output raw_output = p.readAllStandardOutput().data() try: output = raw_output.decode(locale.getpreferredencoding()).replace( '\r\n', '\n') except UnicodeDecodeError: output = 'Failed to decode compiler output with encoding %s' % \ locale.getpreferredencoding() _logger().exception('failed to decode compiler output: %r' % raw_output) _logger().debug('output: %r', output) _logger().debug('exit code: %r', status) os.environ['PATH'] = path_cpy return status, output
def compile(self, file_path, file_type): """ Compiles a file. This is a blocking function, it returns only when the compiler process finished. :param file_path: Path of the file to compile. :param file_type: File type (exe or dll) :return: status, list of checker messages """ _logger().info('compiling %s' % file_path) path, filename = os.path.split(file_path) # ensure bin dir exists self.make_bin_dir(path) # run command using qt process api, this is blocking. pgm, options = self.make_command(filename, file_type) process = QtCore.QProcess() process.setWorkingDirectory(path) process.setProcessChannelMode(QtCore.QProcess.MergedChannels) _logger().info('command: %s %s', pgm, ' '.join(options)) _logger().debug('working directory: %s', path) _logger().debug('system environment: %s', process.systemEnvironment()) process.start(pgm, options) process.waitForFinished() status = process.exitCode() output = process.readAllStandardOutput().data().decode('utf-8') messages = self.parse_output(output, file_path) _logger().info('output: %s', output) if status != 0 and not len(messages): # compilation failed but the parser failed to extract cobol related # messages, there might be an issue at the C level or at the # linker level messages.append((output, CheckerMessages.ERROR, - 1, 0, None, None, file_path)) _logger().debug('compile results: %r - %r', status, messages) return status, messages
def compile(self, file_path, file_type, object_files=None, additional_options=None, output_dir=None): """ Compiles a file. This is a blocking function, it returns only when the compiler process finished. :param file_path: Path of the file to compile. :param file_type: File type (exe or dll) :param output_dir: Output directory, if None, the directory set in the application directory will be used. :return: status, list of checker messages """ _logger().info('compiling %s' % file_path) path, filename = os.path.split(file_path) if output_dir is None: output_dir = Settings().output_directory if not os.path.isabs(output_dir): output_dir = os.path.abspath(os.path.join(path, output_dir)) # run command using qt process api, this is blocking. if object_files: inputs = [filename] + object_files else: inputs = [filename] # ensure bin dir exists output_full_path = os.path.join( output_dir, self._get_output_filename(inputs, file_type)) if os.path.exists(output_full_path) and \ os.path.getmtime(file_path) <= \ os.path.getmtime(output_full_path): desc = 'compilation skipped, up to date...' self.output_available.emit('%s: %s' % (file_path, desc)) msg = (desc, CheckerMessages.INFO, -1, 0, None, None, file_path) return 0, [msg] self.prepare_bin_dir(output_dir, output_full_path) pgm, options = self.make_command(inputs, file_type, output_dir, additional_options) process = QtCore.QProcess() process.setWorkingDirectory(path) process.setProcessChannelMode(QtCore.QProcess.MergedChannels) process.setProcessEnvironment(self.setup_process_environment()) cmd = '%s %s' % (pgm, ' '.join(options)) _logger().info('command: %s', cmd) _logger().debug('working directory: %s', path) _logger().debug('system environment: %s', process.systemEnvironment()) process.start(pgm, options) self.started.emit(cmd) process.waitForFinished() if process.exitStatus() != process.Crashed: status = process.exitCode() else: status = 139 raw_output = process.readAllStandardOutput().data() try: output = raw_output.decode( locale.getpreferredencoding()).replace('\r', '\n') except UnicodeDecodeError: output = 'Failed to decode compiler output with encoding %s' % \ locale.getpreferredencoding() _logger().exception('failed to decode compiler output: %r' % raw_output) self.output_available.emit(output) messages = self.parse_output(output, process.workingDirectory()) binary_created = os.path.exists(output_full_path) _logger().info('compiler process exit code: %d', status) _logger().info('compiler process output: %s', output) _logger().info('binary file (%s) created: %r', output_full_path, binary_created) if not len(messages) and (status != 0 or not binary_created): # compilation failed but the parser failed to extract COBOL related # messages, there might be an issue at the C level or at the # linker level messages.append((output, CheckerMessages.ERROR, - 1, 0, None, None, file_path)) _logger().debug('compile results: %r - %r', status, messages) return status, messages