Example #1
0
class ProcessThread(QObject):
    _ProcssOutput = pyqtSignal(object)

    def __init__(self, cmd, directory_exec=None):
        QObject.__init__(self)
        self.directory_exec = directory_exec
        self.cmd = cmd

    def getNameThread(self):
        return '[New Thread {} ({})]'.format(self.procThread.pid(),
                                             self.objectName())

    @pyqtSlot()
    def readProcessOutput(self):
        self.data = str(self.procThread.readAllStandardOutput())
        self._ProcssOutput.emit(self.data)

    def start(self):
        self.procThread = QProcess(self)
        self.procThread.setProcessChannelMode(QProcess.MergedChannels)
        if self.directory_exec:
            self.procThread.setWorkingDirectory(self.directory_exec)
        QObject.connect(self.procThread, SIGNAL('readyReadStandardOutput()'),
                        self, SLOT('readProcessOutput()'))
        self.procThread.start(self.cmd.keys()[0], self.cmd[self.cmd.keys()[0]])
        print '[New Thread {} ({})]'.format(self.procThread.pid(),
                                            self.objectName())

    def stop(self):
        print 'Thread::[{}] successfully stopped.'.format(self.objectName())
        if hasattr(self, 'procThread'):
            self.procThread.terminate()
            self.procThread.waitForFinished()
            self.procThread.kill()
Example #2
0
class ProcessThread(QObject):
    _ProcssOutput = pyqtSignal(object)
    def __init__(self,cmd ,directory_exec=None):
        QObject.__init__(self)
        self.directory_exec = directory_exec
        self.cmd = cmd

    def getNameThread(self):
        return '[New Thread {} ({})]'.format(self.procThread.pid(),self.objectName())

    @pyqtSlot()
    def readProcessOutput(self):
        self.data = str(self.procThread.readAllStandardOutput())
        self._ProcssOutput.emit(self.data)

    def start(self):
        self.procThread = QProcess(self)
        self.procThread.setProcessChannelMode(QProcess.MergedChannels)
        if self.directory_exec:
            self.procThread.setWorkingDirectory(self.directory_exec)
        QObject.connect(self.procThread, SIGNAL('readyReadStandardOutput()'), self, SLOT('readProcessOutput()'))
        self.procThread.start(self.cmd.keys()[0],self.cmd[self.cmd.keys()[0]])
        print '[New Thread {} ({})]'.format(self.procThread.pid(),self.objectName())

    def stop(self):
        print 'Thread::[{}] successfully stopped.'.format(self.objectName())
        if hasattr(self,'procThread'):
            self.procThread.terminate()
            self.procThread.waitForFinished()
            self.procThread.kill()
Example #3
0
class BatchFileSync(SyncProvider):
    def __init__(self, name, **kwargs):
        super(BatchFileSync, self).__init__(name)
        self.cmd = kwargs['cmd']
        self.process = QProcess()
        variables = kwargs.get("variables", {})
        env = QProcessEnvironment.systemEnvironment()
        for varname, value in variables.iteritems():
            env.insert(varname, value)
        self.process.setProcessEnvironment(env)
        self.process.setWorkingDirectory(os.path.dirname(os.path.realpath(self.cmd)))
        self.process.finished.connect(self.complete)
        self.process.started.connect(self.syncStarted)
        self.process.readyReadStandardError.connect(self.error)
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self._output = ""
        self.haserror = False

    def start(self):
        self._output = ""
        self.process.start(self.cmd, [])
        
    @property
    def output(self):
        return self._output
    
    @output.setter   
    def output(self, value):
        self._output = value
        
    def error(self):
        self.haserror = True
        
    def complete(self, error, status):
        if error > 0:
            stderr = self.process.readAllStandardError().data()
            self.syncError.emit(stderr)
        else:
            self.syncComplete.emit()
        self.syncFinished.emit()
    
    def readOutput(self):
        output = str(self.process.readAll())
        self.syncMessage.emit(output)
Example #4
0
class InoProcess(QtCore.QThread):
	def __init__(self,project,command):
		QtCore.QThread.__init__(self,project.parent())
		self.project=project		
		self.command=command
		
	
	def run(self):
		self.project.newMessage.emit()
		self.project.addMessage.emit("# running: "+self.command+"\n")
		start_time=time.time()
		self.proc = QProcess(None)
		self.proc.readyReadStandardError.connect(self.stdErrReady)
		self.proc.readyReadStandardOutput.connect(self.stdOutReady) 
		self.proc.setWorkingDirectory(self.project.path)
		commands = self.command.split(' ')
		args=QStringList()
		for cmd in commands[1:]:
			args.append(cmd)
		self.proc.start(QString(commands[0]), args, mode=QIODevice.ReadOnly)
		self.proc.waitForFinished()
		
		end_time=time.time()
		if (self.proc.exitCode()==0):
			self.project.statusChanged.emit("SUCCESS")
			self.project.addMessage.emit("# \""+self.command+"\" finished in "+str(end_time-start_time)+"sec\n")
		else:
			self.project.statusChanged.emit("FAILED")
			self.project.addErrorMessage.emit("# \""+self.command+"\" finished in "+str(end_time-start_time)+ "sec with status:"+str(self.proc.exitCode())+"\n")
	
	def stop(self):
		if self.proc!=None and self.proc.state()!=QProcess.NotRunning:
			self.project.addErrorMessage.emit("# Received stop process command\n")
			self.proc.kill()
			
	def stdErrReady(self):
		#Reading possible errors
		errors=unicode(self.proc.readAllStandardError().data(),errors='ignore')
		if (errors!=None and len(errors)>0):
			self.project.addErrorMessage.emit(QString(errors))
	def stdOutReady(self):
		msg=unicode(self.proc.readAllStandardOutput().data(),errors='ignore')
		if (msg!=None and len(msg)>0):
			self.project.addMessage.emit(QString(msg))
Example #5
0
class BatchFileSync(SyncProvider):
    def __init__(self, name, cmd):
        super(BatchFileSync, self).__init__(name)
        self.cmd = cmd
        self.process = QProcess()
        self.process.setWorkingDirectory(
            os.path.dirname(os.path.realpath(self.cmd)))
        self.process.finished.connect(self.complete)
        self.process.started.connect(self.syncStarted)
        self.process.readyReadStandardError.connect(self.error)
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self._output = ""
        self.haserror = False

    def start(self):
        self._output = ""
        self.process.start(self.cmd, [])

    @property
    def output(self):
        return self._output

    @output.setter
    def output(self, value):
        self._output = value

    def error(self):
        self.haserror = True

    def complete(self, error, status):
        if error > 0:
            stderr = self.process.readAllStandardError().data()
            self.syncError.emit(stderr)
        else:
            self.syncComplete.emit()
        self.syncFinished.emit()

    def readOutput(self):
        output = str(self.process.readAll())
        self.syncMessage.emit(output)
Example #6
0
class BatchFileSync(SyncProvider):
    def __init__(self, name, cmd):
        super(BatchFileSync, self).__init__(name)
        self.cmd = cmd
        self.process = QProcess()
        self.process.setWorkingDirectory(os.path.dirname(os.path.realpath(self.cmd)))
        self.process.finished.connect(self.complete)
        self.process.started.connect(self.syncStarted)
        self.process.readyReadStandardError.connect(self.error)
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self._output = ""
        self.haserror = False

    def start(self):
        self._output = ""
        self.process.start(self.cmd, [])
        
    @property
    def output(self):
        return self._output
    
    @output.setter   
    def output(self, value):
        self._output = value
        
    def error(self):
        self.haserror = True
        
    def complete(self, error, status):
        if error > 0:
            stderr = self.process.readAllStandardError().data()
            self.syncError.emit(stderr)
        else:
            self.syncComplete.emit()
        self.syncFinished.emit()
    
    def readOutput(self):
        output = str(self.process.readAll())
        self.syncMessage.emit(output)
Example #7
0
    def run(self):
        if not self.settings.value("openfoam/path"):
            self.window.console.write_error("Path to OpenFOAM is not set")
            return

        if not self.case.path:
            self.window.console.write_error("Shampoo project is not saved")
            return

        self.case.save()

        path = os.path.join(self.settings.value("openfoam/path"), "etc/bashrc")
        commands = "source {0}\n{1}\n".format(
                path,
                "blockMesh")

        program_name = "/bin/bash"
        logging.info("Running %s", "blockMesh")
        process = QProcess()
        self.window.console.set_process(process)
        process.setWorkingDirectory(self.case.path)
        process.start(program_name)
        process.write(commands)
        process.closeWriteChannel()
class ExternalProcessWidget(QDockWidget):

    def __init__(self, command, working_dir=None, parent=None, keep_open=False):
        QDockWidget.__init__(self, parent=parent)
        # setup user interface
        ui_file = os.path.join(rp.get_path('roslab_ide'), 'resource', 'widgets', 'ExternalProcessWidget.ui')
        self.ui = loadUi(ui_file, self)
        # set command as window title
        self.setWindowTitle(command)
        # set working dir
        if not working_dir:
            working_dir = os.curdir

        # vars
        self._command = command
        self._process_finished = False

        if keep_open:
            args = [
                '-hold',
                '-into', str(self.ui.placeholderWidget.winId()),
                '-e', command
            ]
        else:
            args = [
                '-into', str(self.ui.placeholderWidget.winId()),
                '-e', command
            ]

        # print info
        print('starting "{}" in external terminal...'.format(self._command))
        if keep_open:
            print('(terminal will stay open after process has finished. you must close it yourself!)')
        else:
            print('(terminal will close after process has finished.)')

        self.process = QProcess()
        self.process.setWorkingDirectory(working_dir)
        self.process.start('xterm', args)

        # signals
        self.process.finished.connect(self.finished_process)

    def __del__(self):
        self.terminate_process()

    def save_settings(self):
        pass

    def load_settings(self):
        pass

    def terminate_process(self):
        print('terminating "{}" in external terminal...'.format(self._command))
        self.process.terminate()
        self.process.waitForFinished()
        del self.process
        self._process_finished = True
        self.process = None
        # print info
        print('...done!')

    def process_has_finished(self):
        return self._process_finished

    @pyqtSlot()
    def finished_process(self):
        print('...finished "{}" in external terminal.'.format(self._command))
        self._process_finished = True
        del self.process
        self.process = None
        self.close()

    def closeEvent(self, event):
        if not self._process_finished:
            self.terminate_process()
        event.accept()
Example #9
0
class IPOPProcess(QtCore.QObject):
    #Signals
    ipop_started = pyqtSignal()
    controller_started = pyqtSignal()
    ipop_stopped = pyqtSignal()
    controller_stopped = pyqtSignal()
    started = pyqtSignal()
    stopped = pyqtSignal()
    stop_this_inst = pyqtSignal()

    is_admingvpn = False

    def __init__(self):
        super(IPOPProcess, self).__init__()
        self.ipop_process = QProcess()
        self.controller_process = QProcess()
        self.ipop_kill_process = QProcess()
        self.running = False
        self.makeConnections()
        self.heartbeat = QTimer()
        self.heartbeat.timeout.connect(self.beat)

    def startIPOP(self):
        self.ipop_process.setWorkingDirectory(os.environ['WORKING_DIR'])
        self.ipop_process.start("sudo", ['./script.sh'])
        self.ipop_process.readyRead.connect(self.ipop_started.emit)
        self.ipoplogupdater = LogUpdater('ipop.log', 60)

    def startGVPN(self):
        self.controller_process.setWorkingDirectory(os.environ['WORKING_DIR'])
        #self.controller_process.setStandardOutputFile(os.environ['WORKING_DIR'] + 'LOG.txt')
        self.controller_process.setStandardErrorFile(
            os.environ['WORKING_DIR'] + 'gvpn.log')
        if self.is_admingvpn:
            self.controller_process.start("./admin_gvpn.py",
                                          ['-c', 'conff.json'])
        else:
            self.controller_process.start("./gvpn_controller.py",
                                          ['-c', 'conff.json'])
        self.controller_process.started.connect(self.controller_started.emit)
        self.controller_process.started.connect(self.started.emit)
        self.gvpnlogupdater = LogUpdater('gvpn.log', 60)
        self.heartbeat.start(HEARTBEAT_CYCLE)

    def beat(self):
        try:
            connect.instance.setStatus(connect.jid, connect.vpnname, 'running')
        except:
            return

    def start(self):
        self.startIPOP()
        self.running = True

    def stop(self):
        self.stopIPOP()

    def stopIPOP(self):
        self.ipop_kill_process.start("sudo", ['pkill', 'ipop-tincan-x86'])
        del self.ipoplogupdater
        self.ipop_kill_process.finished.connect(self.ipop_stopped.emit)

    def stopGVPN(self):
        self.controller_process.kill()
        self.controller_stopped.emit()
        try:
            del self.gvpnlogupdater
        except AttributeError:
            pass  # gives out error while restarting IPOP due to changed IP
        self.stopped.emit()
        self.running = False
        self.heartbeat.stop()

    def setAdminGVPN(self, is_admingvpn=False):
        self.is_admingvpn = is_admingvpn

    def makeConnections(self):
        self.connect(self, SIGNAL("ipop_started()"), self.startGVPN)
        self.connect(self, SIGNAL("ipop_stopped()"), self.stopGVPN)
        self.connect(self, SIGNAL("stop_this_inst()"), self.stop)
Example #10
0
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPythonShellWidget
    def __init__(self, parent=None, fname=None, wdir=None, commands=[],
                 interact=False, debug=False, path=[],
                 ipython=False, arguments=None, stand_alone=True,
                 umd_enabled=True, umd_namelist=[], umd_verbose=True):
        self.namespacebrowser = None # namespace browser widget!
        
        self.fname = startup.__file__ if fname is None else fname
        
        self.stand_alone = stand_alone
        
        self.umd_enabled = umd_enabled
        self.umd_namelist = umd_namelist
        self.umd_verbose = umd_verbose
        
        self.namespacebrowser_button = None
        self.cwd_button = None
        self.terminate_button = None
        
        ExternalShellBase.__init__(self, parent, wdir,
                                   history_filename='.history.py')

        self.nsb_timer = QTimer(self) # Namespace browser auto-refresh timer
        self.nsb_timer.setInterval(3000)
        
        if arguments is not None:
            assert isinstance(arguments, basestring)
            self.arguments = arguments
        
        self.ipython = ipython
        if self.ipython:
            interact = False
        
        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_action.setChecked(interact)
        self.debug_action.setChecked(debug)
        
        self.monitor_socket = None
        self.interpreter = fname is None
        
        if self.interpreter:
            self.terminate_button.hide()
        
        self.commands = ["import sys", "sys.path.insert(0, '')"] + commands
        
        # Additional python path list
        self.path = path
        
    def closeEvent(self, event):
        ExternalShellBase.closeEvent(self, event)
        self.disconnect(self.nsb_timer, SIGNAL("timeout()"),
                        self.namespacebrowser.refresh_table)
        
    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        if self.namespacebrowser_button is None and self.stand_alone:
            self.namespacebrowser_button = create_toolbutton(self,
                          get_icon('dictedit.png'), self.tr("Variables"),
                          tip=self.tr("Show/hide global variables explorer"),
                          toggled=self.toggle_globals_explorer)
        if self.cwd_button is None:
            self.cwd_button = create_toolbutton(self,
                          get_std_icon('DirOpenIcon'), self.tr("Working directory"),
                          tip=self.tr("Set current working directory"),
                          triggered=self.set_current_working_directory)
        if self.terminate_button is None:
            self.terminate_button = create_toolbutton(self,
                          get_icon('terminate.png'), self.tr("Terminate"),
                          tip=self.tr("Attempts to terminate the process.\n"
                                      "The process may not exit as a result of "
                                      "clicking this button\n"
                                      "(it is given the chance to prompt "
                                      "the user for any unsaved files, etc)."))        
        buttons = [self.cwd_button]
        if self.namespacebrowser_button is not None:
            buttons.append(self.namespacebrowser_button)
        buttons += [self.run_button, self.options_button,
                    self.terminate_button, self.kill_button]
        return buttons

    def get_options_menu(self):
        self.interact_action = create_action(self, self.tr("Interact"))
        self.interact_action.setCheckable(True)
        self.debug_action = create_action(self, self.tr("Debug"))
        self.debug_action.setCheckable(True)
        self.args_action = create_action(self, self.tr("Arguments..."),
                                         triggered=self.get_arguments)
        return [self.interact_action, self.debug_action, self.args_action]

    def is_interpreter(self):
        """Return True if shellwidget is a Python/IPython interpreter"""
        return self.interpreter
        
    def set_namespacebrowser(self, namespacebrowser):
        """Set namespace browser *widget*"""
        self.namespacebrowser = namespacebrowser
        
    def get_shell_widget(self):
        if self.stand_alone:
            self.namespacebrowser = NamespaceBrowser(self)
            self.namespacebrowser.set_shellwidget(self)
            self.connect(self.namespacebrowser, SIGNAL('collapse()'),
                         lambda: self.toggle_globals_explorer(False))
            # Shell splitter
            self.splitter = splitter = QSplitter(Qt.Vertical, self)
            self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                         self.splitter_moved)
            splitter.addWidget(self.shell)
            splitter.setCollapsible(0, False)
            splitter.addWidget(self.namespacebrowser)
            splitter.setStretchFactor(0, 1)
            splitter.setStretchFactor(1, 0)
            splitter.setHandleWidth(5)
            splitter.setSizes([2, 1])
            return splitter
        else:
            return self.shell
    
    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_action.setEnabled(not state and not self.interpreter)
        self.debug_action.setEnabled(not state and not self.interpreter)
        self.args_action.setEnabled(not state and
                                    (not self.interpreter or self.ipython))
        if state:
            if self.arguments:
                argstr = self.tr("Arguments: %1").arg(self.arguments)
            else:
                argstr = self.tr("No argument")
        else:
            argstr = self.tr("Arguments...")
        self.args_action.setText(argstr)
        self.terminate_button.setEnabled(state)
        if not state:
            self.toggle_globals_explorer(False)
        self.cwd_button.setEnabled(state)
        if self.namespacebrowser_button is not None:
            self.namespacebrowser_button.setEnabled(state)
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        if self.ipython:
            self.process.setProcessChannelMode(QProcess.MergedChannels)
        else:
            self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if self.interact_action.isChecked():
            p_args.append('-i')
        if self.debug_action.isChecked():
            p_args.extend(['-m', 'pdb'])
        if os.name == 'nt':
            # When calling pdb on Windows, one has to double the backslashes 
            # to help Python escaping these characters (otherwise, for example,
            # '\t' will be interpreted as a tabulation):
            p_args.append(self.fname.replace(os.sep, os.sep*2))
        else:
            p_args.append(self.fname)
        
        env = self.process.systemEnvironment()
        
        # Monitor
        env.append('SHELL_ID=%s' % id(self))
        from spyderlib.widgets.externalshell.monitor import start_server
        server, port = start_server()
        self.notification_thread = server.register(str(id(self)), self)
        self.connect(self.notification_thread, SIGNAL('refresh()'),
                     self.namespacebrowser.refresh_table)
        env.append('SPYDER_PORT=%d' % port)
        
        # Python init commands (interpreter only)
        if self.commands and self.interpreter:
            env.append('PYTHONINITCOMMANDS=%s' % ';'.join(self.commands))
            self.process.setEnvironment(env)
        
        # User Module Deleter
        if self.interpreter:
            env.append('UMD_ENABLED=%r' % self.umd_enabled)
            env.append('UMD_NAMELIST=%s' % ','.join(self.umd_namelist))
            env.append('UMD_VERBOSE=%r' % self.umd_verbose)
        
        # IPython related configuration
        if self.ipython:
            env.append('IPYTHON=True')
            # Do not call msvcrt.getch in IPython.genutils.page_more:
            env.append('TERM=emacs')
            
        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)
        
        # Adding Spyder path
        pathlist += self.path
        
        # Adding path list to PYTHONPATH environment variable
        add_pathlist_to_PYTHONPATH(env, pathlist)
        
        self.process.setEnvironment(env)
        #-------------------------Python specific-------------------------------
            
        if self.arguments:
            p_args.extend( self.arguments.split(' ') )
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     self.write_error)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        #-------------------------Python specific-------------------------------
        self.process.start(sys.executable, p_args)
        #-------------------------Python specific-------------------------------
            
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            self.connect(self.nsb_timer, SIGNAL("timeout()"),
                         self.namespacebrowser.auto_refresh)
            self.nsb_timer.start()
            
        return self.process
    
#===============================================================================
#    Input/Output
#===============================================================================
    def write_error(self):
        #---This is apparently necessary only on Windows (not sure though):
        #   emptying standard output buffer before writing error output
        self.process.setReadChannel(QProcess.StandardOutput)
        if self.process.waitForReadyRead(1):
            self.write_output()
            
        self.shell.write_error(self.get_stderr())
        QApplication.processEvents()
        
    def send_to_process(self, qstr):
        if not isinstance(qstr, QString):
            qstr = QString(qstr)
        if not qstr.endsWith('\n'):
            qstr.append('\n')
        self.process.write(qstr.toLocal8Bit())
        self.process.waitForBytesWritten(-1)
        
        # Eventually write prompt faster (when hitting Enter continuously)
        # -- necessary/working on Windows only:
        if os.name == 'nt':
            self.write_error()
        
    def keyboard_interrupt(self):
        communicate(self.monitor_socket, "thread.interrupt_main()")
            
#===============================================================================
#    Globals explorer
#===============================================================================
    def toggle_globals_explorer(self, state):
        if self.stand_alone:
            self.splitter.setSizes([1, 1 if state else 0])
            self.namespacebrowser_button.setChecked(state)
            if state:
                self.namespacebrowser.refresh_table()
        
    def splitter_moved(self, pos, index):
        self.namespacebrowser_button.setChecked( self.splitter.sizes()[1] )

#===============================================================================
#    Current working directory
#===============================================================================
    def set_current_working_directory(self):
        cwd = self.shell.get_cwd()
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        directory = QFileDialog.getExistingDirectory(self,
                                             self.tr("Select directory"), cwd)
        if not directory.isEmpty():
            self.shell.set_cwd(unicode(directory))
        self.emit(SIGNAL('redirect_stdio(bool)'), True)
Example #11
0
class BatchFileSync(SyncProvider):
    def __init__(self, name, project, **kwargs):
        super(BatchFileSync, self).__init__(name, project)
        self.cmd = kwargs['cmd']
        if self.project:
            self.rootfolder = os.path.abspath(self.project.folder)
        else:
            self.rootfolder = kwargs['rootfolder']

        self.project = project
        self.closeproject = kwargs.get("close_project", False)
        self.process = QProcess()
        self.parser = kwargs.get("parser", None)
        self.parsermodule = None
        variables = kwargs.get("variables", {})
        env = QProcessEnvironment.systemEnvironment()
        for varname, value in variables.iteritems():
            env.insert(varname, str(value))
        self.process.setProcessEnvironment(env)
        self.process.setWorkingDirectory(
            os.path.dirname(os.path.realpath(self.cmd)))
        self.process.finished.connect(self.complete)
        self.process.started.connect(self.syncStarted)
        self.process.readyReadStandardError.connect(self.error)
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self._output = ""
        self.haserror = False

    def import_parser_module(self):
        import imp
        name = self.parser
        module = imp.find_module(name, [self.rootfolder])
        module = imp.load_module(name, *module)
        self.parsermodule = module
        print self.parsermodule

    def start(self):
        if not self.parsermodule and self.parser:
            self.import_parser_module()

        self._output = ""
        self.haserror = False
        self.process.start(self.cmd, [])

    @property
    def output(self):
        return self._output

    @output.setter
    def output(self, value):
        self._output = value

    def error(self):
        self.haserror = True

    def complete(self, error, status):
        if error > 0 or self.haserror:
            stderr = self.process.readAllStandardError().data()
            self.syncError.emit(stderr)
        else:
            self.syncComplete.emit()
        self.syncFinished.emit()

    def readOutput(self):
        output = str(self.process.readAll())
        ok = True
        if self.parsermodule:
            ok, output = self.parsermodule.sync_output(output)

        if not ok:
            self.haserror = True
            self.process.kill()
            self.syncError.emit(output)
        else:
            if output:
                self.syncMessage.emit(output)
Example #12
0
class PylintWidget(QWidget):
    """
    Pylint widget
    """
    DATAPATH = get_conf_path('.pylint.results')
    VERSION = '1.0.2'

    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)

        self.output = None
        self.error_output = None

        self.max_entries = max_entries
        self.data = [self.VERSION]
        if osp.isfile(self.DATAPATH):
            try:
                data = cPickle.load(file(self.DATAPATH))
                if data[0] == self.VERSION:
                    self.data = data
            except EOFError:
                pass

        self.filecombo = PythonModulesComboBox(self)
        if self.data:
            self.remove_obsolete_items()
            self.filecombo.addItems(self.get_filenames())

        self.start_button = create_toolbutton(self,
                                              get_icon('run.png'),
                                              translate('Pylint', "Analyze"),
                                              tip=translate(
                                                  'Pylint', "Run analysis"),
                                              triggered=self.start)
        self.stop_button = create_toolbutton(self,
                                             get_icon('terminate.png'),
                                             translate('Pylint', "Stop"),
                                             tip=translate(
                                                 'Pylint',
                                                 "Stop current analysis"))
        self.connect(self.filecombo, SIGNAL('valid(bool)'),
                     self.start_button.setEnabled)
        self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)

        browse_button = create_toolbutton(self,
                                          get_icon('fileopen.png'),
                                          tip=translate(
                                              'Pylint',
                                              'Select Python script'),
                                          triggered=self.select_file)

        self.ratelabel = QLabel()
        self.datelabel = QLabel()
        self.log_button = create_toolbutton(self,
                                            get_icon('log.png'),
                                            translate('Pylint', "Output"),
                                            tip=translate(
                                                'Pylint',
                                                "Complete Pylint output"),
                                            triggered=self.show_log)
        self.treewidget = ResultsTree(self)

        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.ratelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)

        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.treewidget)
        self.setLayout(layout)

        self.process = None
        self.set_running_state(False)

        if not is_pylint_installed():
            for widget in (self.treewidget, self.filecombo, self.start_button,
                           self.stop_button):
                widget.setDisabled(True)
            text = translate('Pylint', 'Please install <b>pylint</b>:')
            url = 'http://www.logilab.fr'
            text += ' <a href=%s>%s</a>' % (url, url)
            self.ratelabel.setText(text)
        else:
            self.show_data()

    def analyze(self, filename):
        if not is_pylint_installed():
            return
        filename = unicode(filename)  # filename is a QString instance
        self.kill_if_running()
        index, _data = self.get_data(filename)
        if index is None:
            self.filecombo.addItem(filename)
            self.filecombo.setCurrentIndex(self.filecombo.count() - 1)
        else:
            self.filecombo.setCurrentIndex(index)
        self.filecombo.selected()
        if self.filecombo.is_valid():
            self.start()

    def select_file(self):
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        filename = QFileDialog.getOpenFileName(
            self, translate('Pylint', "Select Python script"), os.getcwdu(),
            translate('Pylint', "Python scripts") + " (*.py ; *.pyw)")
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        if filename:
            self.analyze(filename)

    def remove_obsolete_items(self):
        """Removing obsolete items"""
        self.data = [self.VERSION] + \
                    [(filename, data) for filename, data in self.data[1:]
                     if is_module_or_package(filename)]

    def get_filenames(self):
        return [filename for filename, _data in self.data[1:]]

    def get_data(self, filename):
        filename = osp.abspath(filename)
        for index, (fname, data) in enumerate(self.data[1:]):
            if fname == filename:
                return index, data
        else:
            return None, None

    def set_data(self, filename, data):
        filename = osp.abspath(filename)
        index, _data = self.get_data(filename)
        if index is not None:
            self.data.pop(index)
        self.data.append((filename, data))
        self.save()

    def set_max_entries(self, max_entries):
        self.max_entries = max_entries
        self.save()

    def save(self):
        while len(self.data) > self.max_entries + 1:
            self.data.pop(1)
        cPickle.dump(self.data, file(self.DATAPATH, 'w'))

    def show_log(self):
        if self.output:
            TextEditor(self.output,
                       title=translate('Pylint', "Pylint output"),
                       readonly=True,
                       size=(700, 500)).exec_()

    def start(self):
        filename = unicode(self.filecombo.currentText())

        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.process.setWorkingDirectory(osp.dirname(filename))
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.read_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     lambda: self.read_output(error=True))
        self.connect(self.process,
                     SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        self.connect(self.stop_button, SIGNAL("clicked()"), self.process.kill)

        self.output = ''
        self.error_output = ''
        p_args = [osp.basename(filename)]
        self.process.start(PYLINT_PATH, p_args)

        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(
                self, translate('Pylint', "Error"),
                translate('Pylint', "Process failed to start"))

    def set_running_state(self, state=True):
        self.start_button.setEnabled(not state)
        self.stop_button.setEnabled(state)

    def read_output(self, error=False):
        if error:
            self.process.setReadChannel(QProcess.StandardError)
        else:
            self.process.setReadChannel(QProcess.StandardOutput)
        bytes = QByteArray()
        while self.process.bytesAvailable():
            if error:
                bytes += self.process.readAllStandardError()
            else:
                bytes += self.process.readAllStandardOutput()
        text = unicode(QString.fromLocal8Bit(bytes.data()))
        if error:
            self.error_output += text
        else:
            self.output += text

    def finished(self):
        self.set_running_state(False)
        if not self.output:
            return

        # Convention, Refactor, Warning, Error
        results = {'C:': [], 'R:': [], 'W:': [], 'E:': []}
        txt_module = '************* Module '

        module = ''  # Should not be needed - just in case something goes wrong
        for line in self.output.splitlines():
            if line.startswith(txt_module):
                # New module
                module = line[len(txt_module):]
                continue
            for prefix in results:
                if line.startswith(prefix):
                    break
            else:
                continue
            i1 = line.find(':')
            if i1 == -1:
                continue
            i2 = line.find(':', i1 + 1)
            if i2 == -1:
                continue
            line_nb = line[i1 + 1:i2].strip()
            if not line_nb:
                continue
            line_nb = int(line_nb)
            message = line[i2 + 1:]
            item = (module, line_nb, message)
            results[line[:i1 + 1]].append(item)

        # Rate
        rate = None
        txt_rate = 'Your code has been rated at '
        i_rate = self.output.find(txt_rate)
        if i_rate > 0:
            i_rate_end = self.output.find('/10', i_rate)
            if i_rate_end > 0:
                rate = self.output[i_rate + len(txt_rate):i_rate_end]

        # Previous run
        previous = ''
        if rate is not None:
            txt_prun = 'previous run: '
            i_prun = self.output.find(txt_prun, i_rate_end)
            if i_prun > 0:
                i_prun_end = self.output.find('/10', i_prun)
                previous = self.output[i_prun + len(txt_prun):i_prun_end]

        filename = unicode(self.filecombo.currentText())
        self.set_data(filename, (time.localtime(), rate, previous, results))
        self.output = self.error_output + self.output
        self.show_data(justanalyzed=True)

    def kill_if_running(self):
        if self.process is not None:
            if self.process.state() == QProcess.Running:
                self.process.kill()
                self.process.waitForFinished()

    def show_data(self, justanalyzed=False):
        if not justanalyzed:
            self.output = None
        self.log_button.setEnabled(self.output is not None \
                                   and len(self.output) > 0)
        self.kill_if_running()
        filename = unicode(self.filecombo.currentText())
        if not filename:
            return

        _index, data = self.get_data(filename)
        if data is None:
            text = translate('Pylint', 'Source code has not been rated yet.')
            self.treewidget.clear()
            date_text = ''
        else:
            datetime, rate, previous_rate, results = data
            if rate is None:
                text = translate(
                    'Pylint', 'Analysis did not succeed '
                    '(see output for more details).')
                self.treewidget.clear()
                date_text = ''
            else:
                text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
                rate_style = "<span style=\'color: %s\'><b>%s</b></span>"
                prevrate_style = "<span style=\'color: #666666\'>%s</span>"
                color = "#FF0000"
                if float(rate) > 5.:
                    color = "#22AA22"
                elif float(rate) > 3.:
                    color = "#EE5500"
                text = translate('Pylint', 'Global evaluation:')
                text = (text_style % text) + (rate_style % (color,
                                                            ('%s/10' % rate)))
                if previous_rate:
                    text_prun = translate('Pylint', 'previous run:')
                    text_prun = ' (%s %s/10)' % (text_prun, previous_rate)
                    text += prevrate_style % text_prun
                self.treewidget.set_results(filename, results)
                date_text = text_style % time.strftime("%d %b %Y %H:%M",
                                                       datetime)

        self.ratelabel.setText(text)
        self.datelabel.setText(date_text)
Example #13
0
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPythonShellWidget
    def __init__(self, parent=None, fname=None, wdir=None,
                 interact=False, debug=False, path=[], python_args='',
                 ipykernel=False, arguments='', stand_alone=None,
                 umd_enabled=True, umd_namelist=[], umd_verbose=True,
                 pythonstartup=None, pythonexecutable=None,
                 monitor_enabled=True, mpl_patch_enabled=True,
                 mpl_backend=None, ets_backend='qt4', qt_api=None, pyqt_api=0,
                 install_qt_inputhook=True, ignore_sip_setapi_errors=False,
                 merge_output_channels=False, colorize_sys_stderr=False,
                 autorefresh_timeout=3000, autorefresh_state=True,
                 light_background=True, menu_actions=None,
                 show_buttons_inside=True, show_elapsed_time=True):

        assert qt_api in (None, 'pyqt', 'pyside')

        self.namespacebrowser = None # namespace browser widget!
        
        self.dialog_manager = DialogManager()
        
        self.stand_alone = stand_alone # stand alone settings (None: plugin)
        self.pythonstartup = pythonstartup
        self.pythonexecutable = pythonexecutable
        self.monitor_enabled = monitor_enabled
        self.mpl_patch_enabled = mpl_patch_enabled
        self.mpl_backend = mpl_backend
        self.ets_backend = ets_backend
        self.qt_api = qt_api
        self.pyqt_api = pyqt_api
        self.install_qt_inputhook = install_qt_inputhook
        self.ignore_sip_setapi_errors = ignore_sip_setapi_errors
        self.merge_output_channels = merge_output_channels
        self.colorize_sys_stderr = colorize_sys_stderr
        self.umd_enabled = umd_enabled
        self.umd_namelist = umd_namelist
        self.umd_verbose = umd_verbose
        self.autorefresh_timeout = autorefresh_timeout
        self.autorefresh_state = autorefresh_state
                
        self.namespacebrowser_button = None
        self.cwd_button = None
        self.env_button = None
        self.syspath_button = None
        self.terminate_button = None

        self.notification_thread = None
        
        ExternalShellBase.__init__(self, parent=parent, fname=fname, wdir=wdir,
                                   history_filename='.history.py',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)

        if self.pythonexecutable is None:
            self.pythonexecutable = get_python_executable()

        self.python_args = None
        if python_args:
            assert isinstance(python_args, basestring)
            self.python_args = python_args
        
        assert isinstance(arguments, basestring)
        self.arguments = arguments
        
        self.connection_file = None
        self.is_ipykernel = ipykernel
        if self.is_ipykernel:
            interact = False
            # Running our custom startup script for IPython kernels:
            # (see spyderlib/widgets/externalshell/start_ipython_kernel.py)
            self.fname = get_module_source_path(
                'SMlib.widgets.externalshell', 'start_ipython_kernel.py')
        
        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_action.setChecked(interact)
        self.debug_action.setChecked(debug)
        
        self.introspection_socket = None
        self.is_interpreter = fname is None
        
        if self.is_interpreter:
            self.terminate_button.hide()
        
        # Additional python path list
        self.path = path
        self.shell.path = path
        
    def set_introspection_socket(self, introspection_socket):
        self.introspection_socket = introspection_socket
        if self.namespacebrowser is not None:
            settings = self.namespacebrowser.get_view_settings()
            communicate(introspection_socket,
                        'set_remote_view_settings()', settings=[settings])
        
    def set_autorefresh_timeout(self, interval):
        if self.introspection_socket is not None:
            try:
                communicate(self.introspection_socket,
                            "set_monitor_timeout(%d)" % interval)
            except socket.error:
                pass
        
    def closeEvent(self, event):
        self.quit_monitor()
        ExternalShellBase.closeEvent(self, event)
        
    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        if self.namespacebrowser_button is None \
           and self.stand_alone is not None:
            self.namespacebrowser_button = create_toolbutton(self,
                  text=_("Variables"), icon=get_icon('dictedit.png'),
                  tip=_("Show/hide global variables explorer"),
                  toggled=self.toggle_globals_explorer, text_beside_icon=True)
        if self.terminate_button is None:
            self.terminate_button = create_toolbutton(self,
                  text=_("Terminate"), icon=get_icon('terminate.png'),
                  tip=_("""Attempts to terminate the process.
The process may not exit as a result of clicking this button
(it is given the chance to prompt the user for any unsaved files, etc)."""))
        buttons = []
        if self.namespacebrowser_button is not None:
            buttons.append(self.namespacebrowser_button)
        buttons += [self.run_button, self.options_button,
                    self.terminate_button, self.kill_button]
        return buttons

    def get_options_menu(self):
        ExternalShellBase.get_options_menu(self)
        self.interact_action = create_action(self, _("Interact"))
        self.interact_action.setCheckable(True)
        self.debug_action = create_action(self, _("Debug"))
        self.debug_action.setCheckable(True)
        self.args_action = create_action(self, _("Arguments..."),
                                         triggered=self.get_arguments)
        run_settings_menu = QMenu(_("Run settings"), self)
        add_actions(run_settings_menu,
                    (self.interact_action, self.debug_action, self.args_action))
        self.cwd_button = create_action(self, _("Working directory"),
                                icon=get_std_icon('DirOpenIcon'),
                                tip=_("Set current working directory"),
                                triggered=self.set_current_working_directory)
        self.env_button = create_action(self, _("Environment variables"),
                                        icon=get_icon('environ.png'),
                                        triggered=self.show_env)
        self.syspath_button = create_action(self,
                                            _("Show sys.path contents"),
                                            icon=get_icon('syspath.png'),
                                            triggered=self.show_syspath)
        actions = [run_settings_menu, self.show_time_action, None,
                   self.cwd_button, self.env_button, self.syspath_button]
        if self.menu_actions is not None:
            actions += [None]+self.menu_actions
        return actions

    def is_interpreter(self):
        """Return True if shellwidget is a Python interpreter"""
        return self.is_interpreter
        
    def get_shell_widget(self):
        if self.stand_alone is None:
            return self.shell
        else:
            self.namespacebrowser = NamespaceBrowser(self)
            settings = self.stand_alone
            self.namespacebrowser.set_shellwidget(self)
            self.namespacebrowser.setup(**settings)
            self.connect(self.namespacebrowser, SIGNAL('collapse()'),
                         lambda: self.toggle_globals_explorer(False))
            # Shell splitter
            self.splitter = splitter = QSplitter(Qt.Vertical, self)
            self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                         self.splitter_moved)
            splitter.addWidget(self.shell)
            splitter.setCollapsible(0, False)
            splitter.addWidget(self.namespacebrowser)
            splitter.setStretchFactor(0, 1)
            splitter.setStretchFactor(1, 0)
            splitter.setHandleWidth(5)
            splitter.setSizes([2, 1])
            return splitter
    
    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_action.setEnabled(not state and not self.is_interpreter)
        self.debug_action.setEnabled(not state and not self.is_interpreter)
        self.args_action.setEnabled(not state and not self.is_interpreter)
        if state:
            if self.arguments:
                argstr = _("Arguments: %s") % self.arguments
            else:
                argstr = _("No argument")
        else:
            argstr = _("Arguments...")
        self.args_action.setText(argstr)
        self.terminate_button.setVisible(not self.is_interpreter and state)
        if not state:
            self.toggle_globals_explorer(False)
        for btn in (self.cwd_button, self.env_button, self.syspath_button):
            btn.setEnabled(state and self.monitor_enabled)
        if self.namespacebrowser_button is not None:
            self.namespacebrowser_button.setEnabled(state)
    
    def set_namespacebrowser(self, namespacebrowser):
        """
        Set namespace browser *widget*
        Note: this method is not used in stand alone mode
        """
        self.namespacebrowser = namespacebrowser
        self.configure_namespacebrowser()
        
    def configure_namespacebrowser(self):
        """Connect the namespace browser to the notification thread"""
        if self.notification_thread is not None:
            self.connect(self.notification_thread,
                         SIGNAL('refresh_namespace_browser()'),
                         self.namespacebrowser.refresh_table)
            signal = self.notification_thread.sig_process_remote_view
            signal.connect(self.namespacebrowser.process_remote_view)
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        if self.merge_output_channels:
            self.process.setProcessChannelMode(QProcess.MergedChannels)
        else:
            self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if DEBUG >= 3:
            p_args += ['-v']
        p_args += get_python_args(self.fname, self.python_args,
                                  self.interact_action.isChecked(),
                                  self.debug_action.isChecked(),
                                  self.arguments)
        
        env = [unicode(_path) for _path in self.process.systemEnvironment()]

        if self.pythonstartup:
            env.append('PYTHONSTARTUP=%s' % self.pythonstartup)
        
        # Monitor
        if self.monitor_enabled:
            env.append('SPYDER_SHELL_ID=%s' % id(self))
            env.append('SPYDER_AR_TIMEOUT=%d' % self.autorefresh_timeout)
            env.append('SPYDER_AR_STATE=%r' % self.autorefresh_state)
            from SMlib.widgets.externalshell import introspection
            introspection_server = introspection.start_introspection_server()
            introspection_server.register(self)
            notification_server = introspection.start_notification_server()
            self.notification_thread = notification_server.register(self)
            self.connect(self.notification_thread, SIGNAL('pdb(QString,int)'),
                         lambda fname, lineno:
                         self.emit(SIGNAL('pdb(QString,int)'), fname, lineno))
            self.connect(self.notification_thread,
                         SIGNAL('new_ipython_kernel(QString)'),
                         lambda args:
                         self.emit(SIGNAL('create_ipython_client(QString)'),
                         args))
            self.connect(self.notification_thread,
                         SIGNAL('open_file(QString,int)'),
                         lambda fname, lineno:
                         self.emit(SIGNAL('open_file(QString,int)'),
                                   fname, lineno))
            if self.namespacebrowser is not None:
                self.configure_namespacebrowser()
            env.append('SPYDER_I_PORT=%d' % introspection_server.port)
            env.append('SPYDER_N_PORT=%d' % notification_server.port)
        
        # External modules options
        env.append('ETS_TOOLKIT=%s' % self.ets_backend)
        env.append('MATPLOTLIB_PATCH=%r' % self.mpl_patch_enabled)
        if self.mpl_backend:
            env.append('MATPLOTLIB_BACKEND=%s' % self.mpl_backend)
        if self.qt_api:
            env.append('QT_API=%s' % self.qt_api)
        env.append('INSTALL_QT_INPUTHOOK=%s' % self.install_qt_inputhook)
        env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr)
#        # Socket-based alternative (see input hook in sitecustomize.py):
#        if self.install_qt_inputhook:
#            from PyQt4.QtNetwork import QLocalServer
#            self.local_server = QLocalServer()
#            self.local_server.listen(str(id(self)))
        if self.pyqt_api:
            env.append('PYQT_API=%d' % self.pyqt_api)
        env.append('IGNORE_SIP_SETAPI_ERRORS=%s'
                   % self.ignore_sip_setapi_errors)
        
        # User Module Deleter
        if self.is_interpreter:
            env.append('UMD_ENABLED=%r' % self.umd_enabled)
            env.append('UMD_NAMELIST=%s' % ','.join(self.umd_namelist))
            env.append('UMD_VERBOSE=%r' % self.umd_verbose)

        # IPython kernel
        env.append('IPYTHON_KERNEL=%r' % self.is_ipykernel)
            
        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)
        
        # Adding Spyder path
        pathlist += self.path
        
        # Adding path list to PYTHONPATH environment variable
        add_pathlist_to_PYTHONPATH(env, pathlist)

        #-------------------------Python specific-------------------------------
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     self.write_error)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
                     
        self.connect(self, SIGNAL('finished()'), self.dialog_manager.close_all)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        #-------------------------Python specific-------------------------------
        # Fixes for our Mac app:
        # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app,
        #    but their values are messing sys.path for external interpreters
        #    (e.g. EPD) so we need to remove them from the environment.
        # 2. Add this file's dir to PYTHONPATH. This will make every external
        #    interpreter to use our sitecustomize script.
        # 3. Remove PYTHONOPTIMIZE from env so that we can have assert
        #    statements working with our interpreters (See Issue 1281)
        if sys.platform == 'darwin' and 'Spyder.app' in __file__:
            env.append('SPYDER_INTERPRETER=%s' % self.pythonexecutable)
            if 'Spyder.app' not in self.pythonexecutable:
                env = [p for p in env if not (p.startswith('PYTHONPATH') or \
                                              p.startswith('PYTHONHOME'))] # 1.

                env.append('PYTHONPATH=%s' % osp.dirname(__file__))        # 2.

            env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')]   # 3.

        self.process.setEnvironment(env)
        self.process.start(self.pythonexecutable, p_args)
        #-------------------------Python specific-------------------------------
            
        running = self.process.waitForStarted(3000)
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, _("Error"),
                             _("A Python or IPython Console failed to start!"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            
        return self.process

    def finished(self, exit_code, exit_status):
        """Reimplement ExternalShellBase method"""
        ExternalShellBase.finished(self, exit_code, exit_status)
        self.introspection_socket = None

    
#===============================================================================
#    Input/Output
#===============================================================================
    def write_error(self):
        if os.name == 'nt':
            #---This is apparently necessary only on Windows (not sure though):
            #   emptying standard output buffer before writing error output
            self.process.setReadChannel(QProcess.StandardOutput)
            if self.process.waitForReadyRead(1):
                self.write_output()
        self.shell.write_error(self.get_stderr())
        QApplication.processEvents()
        
    def send_to_process(self, text):
        if not self.is_running():
            return
            
        if not isinstance(text, basestring):
            text = unicode(text)
        if self.install_qt_inputhook and self.introspection_socket is not None:
            communicate(self.introspection_socket,
                        "toggle_inputhook_flag(True)")
#            # Socket-based alternative (see input hook in sitecustomize.py):
#            while self.local_server.hasPendingConnections():
#                self.local_server.nextPendingConnection().write('go!')
        if text.startswith(('%', '!')):
            text = 'evalsc(r"%s")\n' % text
        if not text.endswith('\n'):
            text += '\n'
        self.process.write(locale_codec.fromUnicode(text))
        self.process.waitForBytesWritten(-1)
        
        # Eventually write prompt faster (when hitting Enter continuously)
        # -- necessary/working on Windows only:
        if os.name == 'nt':
            self.write_error()
        
    def keyboard_interrupt(self):
        if self.introspection_socket is not None:
            communicate(self.introspection_socket, "thread.interrupt_main()")
        
    def quit_monitor(self):
        if self.introspection_socket is not None:
            try:
                write_packet(self.introspection_socket, "thread.exit()")
            except socket.error:
                pass
            
#===============================================================================
#    Globals explorer
#===============================================================================
    def toggle_globals_explorer(self, state):
        if self.stand_alone is not None:
            self.splitter.setSizes([1, 1 if state else 0])
            self.namespacebrowser_button.setChecked(state)
            if state and self.namespacebrowser is not None:
                self.namespacebrowser.refresh_table()
        
    def splitter_moved(self, pos, index):
        self.namespacebrowser_button.setChecked( self.splitter.sizes()[1] )

#===============================================================================
#    Misc.
#===============================================================================
    def set_current_working_directory(self):
        """Set current working directory"""
        cwd = self.shell.get_cwd()
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        directory = getexistingdirectory(self, _("Select directory"), cwd)
        if directory:
            self.shell.set_cwd(directory)
        self.emit(SIGNAL('redirect_stdio(bool)'), True)

    def show_env(self):
        """Show environment variables"""
        get_func = self.shell.get_env
        set_func = self.shell.set_env
        self.dialog_manager.show(RemoteEnvDialog(get_func, set_func))
        
    def show_syspath(self):
        """Show sys.path contents"""
        editor = DictEditor()
        editor.setup(self.shell.get_syspath(), title="sys.path", readonly=True,
                     width=600, icon='syspath.png')
        self.dialog_manager.show(editor)
class SvnChangeListsDialog(QDialog, Ui_SvnChangeListsDialog):
    """
    Class implementing a dialog to browse the change lists.
    """
    def __init__(self, vcs, parent=None):
        """
        Constructor
        
        @param vcs reference to the vcs object
        @param parent parent widget (QWidget)
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        
        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
        self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
        
        self.process = None
        self.vcs = vcs
        
        self.rx_status = \
            QRegExp('(.{8,9})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)\\s*')
            # flags (8 or 9 anything), revision, changed rev, author, path
        self.rx_status2 = \
            QRegExp('(.{8,9})\\s+(.+)\\s*')
            # flags (8 or 9 anything), path
        self.rx_changelist = \
            QRegExp('--- \\S+ .([\\w\\s]+).:\\s+')
            # three dashes, Changelist (translated), quote,
            # changelist name, quote, :
    
    @pyqtSignature("QListWidgetItem*, QListWidgetItem*")
    def on_changeLists_currentItemChanged(self, current, previous):
        """
        Private slot to handle the selection of a new item.
        
        @param current current item (QListWidgetItem)
        @param previous previous current item (QListWidgetItem)
        """
        self.filesList.clear()
        if current is not None:
            changelist = unicode(current.text())
            if changelist in self.changeListsDict:
                self.filesList.addItems(sorted(self.changeListsDict[changelist]))
    
    def start(self, path):
        """
        Public slot to populate the data.
        
        @param path directory name to show change lists for (string)
        """
        self.changeListsDict = {}
        
        self.filesLabel.setText(self.trUtf8("Files (relative to %1):").arg(path))
        
        self.errorGroup.hide()
        self.intercept = False
        
        self.path = path
        self.currentChangelist = ""
        
        self.process = QProcess()
        self.process.finished.connect(self.__procFinished)
        self.process.readyReadStandardOutput.connect(self.__readStdout)
        self.process.readyReadStandardError.connect(self.__readStderr)
        
        args = []
        args.append('status')
        self.vcs.addArguments(args, self.vcs.options['global'])
        self.vcs.addArguments(args, self.vcs.options['status'])
        if '--verbose' not in self.vcs.options['global'] and \
           '--verbose' not in self.vcs.options['status']:
            args.append('--verbose')
        if isinstance(path, list):
            self.dname, fnames = self.vcs.splitPathList(path)
            self.vcs.addArguments(args, fnames)
        else:
            self.dname, fname = self.vcs.splitPath(path)
            args.append(fname)
        
        self.process.setWorkingDirectory(self.dname)
        
        self.process.start('svn', args)
        procStarted = self.process.waitForStarted()
        if not procStarted:
            self.inputGroup.setEnabled(False)
            self.inputGroup.hide()
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    'The process %1 could not be started. '
                    'Ensure, that it is in the search path.'
                ).arg('svn'))
        else:
            self.inputGroup.setEnabled(True)
            self.inputGroup.show()
    
    def __finish(self):
        """
        Private slot called when the process finished or the user pressed
        the button.
        """
        if self.process is not None and \
           self.process.state() != QProcess.NotRunning:
            self.process.terminate()
            QTimer.singleShot(2000, self.process.kill)
            self.process.waitForFinished(3000)
        
        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
        self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
        
        self.inputGroup.setEnabled(False)
        self.inputGroup.hide()
        
        if len(self.changeListsDict) == 0:
            self.changeLists.addItem(self.trUtf8("No changelists found"))
            self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason)
        else:
            self.changeLists.addItems(sorted(self.changeListsDict.keys()))
            self.changeLists.setCurrentRow(0)
            self.changeLists.setFocus(Qt.OtherFocusReason)
    
    def on_buttonBox_clicked(self, button):
        """
        Private slot called by a button of the button box clicked.
        
        @param button button that was clicked (QAbstractButton)
        """
        if button == self.buttonBox.button(QDialogButtonBox.Close):
            self.close()
        elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
            self.__finish()
        
    def __procFinished(self, exitCode, exitStatus):
        """
        Private slot connected to the finished signal.
        
        @param exitCode exit code of the process (integer)
        @param exitStatus exit status of the process (QProcess.ExitStatus)
        """
        self.__finish()
        
    def __readStdout(self):
        """
        Private slot to handle the readyReadStandardOutput signal.
        
        It reads the output of the process, formats it and inserts it into
        the contents pane.
        """
        if self.process is not None:
            self.process.setReadChannel(QProcess.StandardOutput)
            
            while self.process.canReadLine():
                s = unicode(self.process.readLine(),
                            Preferences.getSystem("IOEncoding"),
                            'replace')
                if self.currentChangelist != "" and self.rx_status.exactMatch(s):
                    file = unicode(self.rx_status.cap(5)).strip()
                    filename = file.replace(self.path + os.sep, "")
                    if filename not in self.changeListsDict[self.currentChangelist]:
                        self.changeListsDict[self.currentChangelist].append(filename)
                elif self.currentChangelist != "" and self.rx_status2.exactMatch(s):
                    file = unicode(self.rx_status2.cap(2)).strip()
                    filename = file.replace(self.path + os.sep, "")
                    if filename not in self.changeListsDict[self.currentChangelist]:
                        self.changeListsDict[self.currentChangelist].append(filename)
                elif self.rx_changelist.exactMatch(s):
                    self.currentChangelist = unicode(self.rx_changelist.cap(1))
                    if self.currentChangelist not in self.changeListsDict:
                        self.changeListsDict[self.currentChangelist] = []
        
    def __readStderr(self):
        """
        Private slot to handle the readyReadStandardError signal.
        
        It reads the error output of the process and inserts it into the
        error pane.
        """
        if self.process is not None:
            self.errorGroup.show()
            s = QString(self.process.readAllStandardError())
            self.errors.insertPlainText(s)
            self.errors.ensureCursorVisible()
        
    def on_passwordCheckBox_toggled(self, isOn):
        """
        Private slot to handle the password checkbox toggled.
        
        @param isOn flag indicating the status of the check box (boolean)
        """
        if isOn:
            self.input.setEchoMode(QLineEdit.Password)
        else:
            self.input.setEchoMode(QLineEdit.Normal)
        
    @pyqtSignature("")
    def on_sendButton_clicked(self):
        """
        Private slot to send the input to the subversion process.
        """
        input = self.input.text()
        input += os.linesep
        
        if self.passwordCheckBox.isChecked():
            self.errors.insertPlainText(os.linesep)
            self.errors.ensureCursorVisible()
        else:
            self.errors.insertPlainText(input)
            self.errors.ensureCursorVisible()
        
        self.process.write(input)
        
        self.passwordCheckBox.setChecked(False)
        self.input.clear()
        
    def on_input_returnPressed(self):
        """
        Private slot to handle the press of the return key in the input field.
        """
        self.intercept = True
        self.on_sendButton_clicked()
        
    def keyPressEvent(self, evt):
        """
        Protected slot to handle a key press event.
        
        @param evt the key press event (QKeyEvent)
        """
        if self.intercept:
            self.intercept = False
            evt.accept()
            return
        QDialog.keyPressEvent(self, evt)
Example #15
0
class ScriptRunner(QObject):
    def __init__(self, caller, parent=None, env=None, addEnv=None):
        QObject.__init__(self, parent)
        self._proc = None
        self._caller = caller
        self._decode = None
        if env is None:
            env = os.environ.copy()
        self._env = env
        if addEnv:
            self._env.update(addEnv)

    def stop(self, kill=False):
        if self._proc is None:
            return

        if kill:
            self._proc.kill()
        else:
            self._proc.terminate()

    def run(self, scriptFile, args=None, env=None, wd=None):
        if self._proc:
            return

        self._proc = QProcess(self)

        if wd:
            self._proc.setWorkingDirectory(wd)

        if not env is None:
            self._env.update(env)
        envList = dict2qlst(self._env)

        if args is None:
            args = []

        script = quote(scriptFile)
        if not os.path.exists(script):
            script = find_script(script)

        if not script or not os.path.exists(script):
            raise PublishException("Script '%s' cannot be found" % script)

        self._caller.handleScriptOutput("%s %s" % (scriptFile,  ' '.join(args)))

        self._proc.setEnvironment(envList)
        self._proc.setProcessChannelMode(QProcess.MergedChannels)
        QObject.connect(self._proc, QtCore.SIGNAL("readyReadStandardOutput()"),
                        self.readScriptOutput)
        QObject.connect(self._proc, QtCore.SIGNAL("finished(int, " \
                                                  "QProcess::ExitStatus)"),
                        self.scriptFinished)

        self._proc.start(script, args, QIODevice.ReadOnly)

    def scriptFinished(self, exitCode, exitStatus):
        if self._caller:
            self.readScriptOutput()
            self._caller.scriptFinished(exitCode,
                                        exitStatus == QProcess.Crashed)
        self._proc = None

    def readScriptOutput(self):
        if self._proc is None:
            return

        qba = self._proc.readAllStandardOutput()
        if self._caller and qba.length():
            if not self._decode:
                lang, deflocale = locale.getdefaultlocale()
                self._decode = codecs.getdecoder(deflocale)
            data, datalen = self._decode(qba.data())
            self._caller.handleScriptOutput(data)
Example #16
0
class PyLint(Plugin, QObject):
    """ PyLint Plugin """
    capabilities = ['toolbarHook']
    __version__ = '0.5'
    thread = None
    
    def do_toolbarHook(self, widget):
        """ Hook to install the pylint toolbar button"""
        widget.addAction('PyLint', self.do_pylint)
        
        
    @pyqtSlot()
    def do_pylint(self):
        """ Launch the lint process and create the result window """
        print 'do_pylint'

        self.pylint_pross = QProcess()
        self.pylint_pross.setProcessChannelMode(QProcess.MergedChannels)
        self.pylint_pross.setWorkingDirectory( \
            os.path.dirname(str(self.parent.editor.filename)))
        self.pylint_pross.setReadChannel(QProcess.StandardOutput)

        self.connect(self.pylint_pross, \
            SIGNAL('finished(int)'), \
            self.finished)
        self.connect(self.pylint_pross, \
            SIGNAL('readyReadStandardOutput()'), \
            self.handle_stdout)
        self.connect(self.pylint_pross, \
            SIGNAL('readyReadStandardError()'), \
            self.handle_stderr)
        if (self.pylint_pross.start("pylint", \
                [self.parent.editor.filename,])):
            print 'Cannot start process'

        self.win = ResultWin()
        self.win.setWindowTitle("PyLint Results :" \
            + os.path.basename(str(self.parent.editor.filename)))
        self.win.show()
        if isMAEMO:
            self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, True)
            
        self.win.connect(self.win.list_view, \
            SIGNAL('doubleClicked(const QModelIndex&)'), \
            self.goto_line)

        self.pylint_pross.waitForStarted()
        
    def finished(self, _):
        """ Call back called when lint end """
        if isMAEMO:
            self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, False)
            
    def handle_stdout(self):
        """
        Private slot to handle the readyReadStdout
        signal of the pylint process.
        """
        result_list = []
        #regex = QRegExp('(\w)\S*:\S*(\d*):.*: (.*)')
        regex = QRegExp('(\w)\s*:\s*(\d*):(.*)')
        regex_score = \
            QRegExp('.*at.(\d.\d*)/10.*')
        while self.pylint_pross and self.pylint_pross.canReadLine():
            result = unicode(self.pylint_pross.readLine())
            if result != None:
                pos = 0
                while True:
                    pos = regex.indexIn(result, pos)
                    if pos < 0:
                        if regex_score.indexIn(result, 0) >= 0:
                            self.win.setWindowTitle( \
                                "PyLint Results :" \
                                + str(regex_score.cap(1)) \
                                + ':'                                
                                + os.path.basename(str(self.parent.editor.filename)))
                        break
                    result_list.append((regex.cap(1), regex.cap(2), regex.cap(3)))
                    #print 'Append : ',(regex.cap(1), regex.cap(2), regex.cap(3))
                    pos = pos + regex.matchedLength()
                    
        if len(result_list)>0:
            self.win.append_results(result_list)
        
    def goto_line(self, index):
        """ Callback called when a lint result is double clicked """
        line = int(self.win.list_model.items[index.row()][1])
        self.parent.do_gotoLine(line)
        
    def handle_stderr(self):
        """
        Private slot to handle the readyReadStderr
        signal of the pylint process. Currently not
        managed
        """
        print 'error stderr'
Example #17
0
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPythonShellWidget

    def __init__(self,
                 parent=None,
                 fname=None,
                 wdir=None,
                 interact=False,
                 debug=False,
                 path=[],
                 python_args='',
                 ipykernel=False,
                 arguments='',
                 stand_alone=None,
                 umd_enabled=True,
                 umd_namelist=[],
                 umd_verbose=True,
                 pythonstartup=None,
                 pythonexecutable=None,
                 monitor_enabled=True,
                 mpl_patch_enabled=True,
                 mpl_backend=None,
                 ets_backend='qt4',
                 qt_api=None,
                 pyqt_api=0,
                 install_qt_inputhook=True,
                 ignore_sip_setapi_errors=False,
                 merge_output_channels=False,
                 colorize_sys_stderr=False,
                 autorefresh_timeout=3000,
                 autorefresh_state=True,
                 light_background=True,
                 menu_actions=None,
                 show_buttons_inside=True,
                 show_elapsed_time=True):

        assert qt_api in (None, 'pyqt', 'pyside')

        self.namespacebrowser = None  # namespace browser widget!

        self.dialog_manager = DialogManager()

        self.stand_alone = stand_alone  # stand alone settings (None: plugin)
        self.pythonstartup = pythonstartup
        self.pythonexecutable = pythonexecutable
        self.monitor_enabled = monitor_enabled
        self.mpl_patch_enabled = mpl_patch_enabled
        self.mpl_backend = mpl_backend
        self.ets_backend = ets_backend
        self.qt_api = qt_api
        self.pyqt_api = pyqt_api
        self.install_qt_inputhook = install_qt_inputhook
        self.ignore_sip_setapi_errors = ignore_sip_setapi_errors
        self.merge_output_channels = merge_output_channels
        self.colorize_sys_stderr = colorize_sys_stderr
        self.umd_enabled = umd_enabled
        self.umd_namelist = umd_namelist
        self.umd_verbose = umd_verbose
        self.autorefresh_timeout = autorefresh_timeout
        self.autorefresh_state = autorefresh_state

        self.namespacebrowser_button = None
        self.cwd_button = None
        self.env_button = None
        self.syspath_button = None
        self.terminate_button = None

        self.notification_thread = None

        ExternalShellBase.__init__(self,
                                   parent=parent,
                                   fname=fname,
                                   wdir=wdir,
                                   history_filename='.history.py',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)

        if self.pythonexecutable is None:
            self.pythonexecutable = get_python_executable()

        self.python_args = None
        if python_args:
            assert isinstance(python_args, basestring)
            self.python_args = python_args

        assert isinstance(arguments, basestring)
        self.arguments = arguments

        self.connection_file = None
        self.is_ipykernel = ipykernel
        if self.is_ipykernel:
            interact = False
            # Running our custom startup script for IPython kernels:
            # (see spyderlib/widgets/externalshell/start_ipython_kernel.py)
            self.fname = get_module_source_path('SMlib.widgets.externalshell',
                                                'start_ipython_kernel.py')

        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_action.setChecked(interact)
        self.debug_action.setChecked(debug)

        self.introspection_socket = None
        self.is_interpreter = fname is None

        if self.is_interpreter:
            self.terminate_button.hide()

        # Additional python path list
        self.path = path
        self.shell.path = path

    def set_introspection_socket(self, introspection_socket):
        self.introspection_socket = introspection_socket
        if self.namespacebrowser is not None:
            settings = self.namespacebrowser.get_view_settings()
            communicate(introspection_socket,
                        'set_remote_view_settings()',
                        settings=[settings])

    def set_autorefresh_timeout(self, interval):
        if self.introspection_socket is not None:
            try:
                communicate(self.introspection_socket,
                            "set_monitor_timeout(%d)" % interval)
            except socket.error:
                pass

    def closeEvent(self, event):
        self.quit_monitor()
        ExternalShellBase.closeEvent(self, event)

    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        if self.namespacebrowser_button is None \
           and self.stand_alone is not None:
            self.namespacebrowser_button = create_toolbutton(
                self,
                text=_("Variables"),
                icon=get_icon('dictedit.png'),
                tip=_("Show/hide global variables explorer"),
                toggled=self.toggle_globals_explorer,
                text_beside_icon=True)
        if self.terminate_button is None:
            self.terminate_button = create_toolbutton(
                self,
                text=_("Terminate"),
                icon=get_icon('terminate.png'),
                tip=_("""Attempts to terminate the process.
The process may not exit as a result of clicking this button
(it is given the chance to prompt the user for any unsaved files, etc)."""))
        buttons = []
        if self.namespacebrowser_button is not None:
            buttons.append(self.namespacebrowser_button)
        buttons += [
            self.run_button, self.options_button, self.terminate_button,
            self.kill_button
        ]
        return buttons

    def get_options_menu(self):
        ExternalShellBase.get_options_menu(self)
        self.interact_action = create_action(self, _("Interact"))
        self.interact_action.setCheckable(True)
        self.debug_action = create_action(self, _("Debug"))
        self.debug_action.setCheckable(True)
        self.args_action = create_action(self,
                                         _("Arguments..."),
                                         triggered=self.get_arguments)
        run_settings_menu = QMenu(_("Run settings"), self)
        add_actions(
            run_settings_menu,
            (self.interact_action, self.debug_action, self.args_action))
        self.cwd_button = create_action(
            self,
            _("Working directory"),
            icon=get_std_icon('DirOpenIcon'),
            tip=_("Set current working directory"),
            triggered=self.set_current_working_directory)
        self.env_button = create_action(self,
                                        _("Environment variables"),
                                        icon=get_icon('environ.png'),
                                        triggered=self.show_env)
        self.syspath_button = create_action(self,
                                            _("Show sys.path contents"),
                                            icon=get_icon('syspath.png'),
                                            triggered=self.show_syspath)
        actions = [
            run_settings_menu, self.show_time_action, None, self.cwd_button,
            self.env_button, self.syspath_button
        ]
        if self.menu_actions is not None:
            actions += [None] + self.menu_actions
        return actions

    def is_interpreter(self):
        """Return True if shellwidget is a Python interpreter"""
        return self.is_interpreter

    def get_shell_widget(self):
        if self.stand_alone is None:
            return self.shell
        else:
            self.namespacebrowser = NamespaceBrowser(self)
            settings = self.stand_alone
            self.namespacebrowser.set_shellwidget(self)
            self.namespacebrowser.setup(**settings)
            self.connect(self.namespacebrowser, SIGNAL('collapse()'),
                         lambda: self.toggle_globals_explorer(False))
            # Shell splitter
            self.splitter = splitter = QSplitter(Qt.Vertical, self)
            self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                         self.splitter_moved)
            splitter.addWidget(self.shell)
            splitter.setCollapsible(0, False)
            splitter.addWidget(self.namespacebrowser)
            splitter.setStretchFactor(0, 1)
            splitter.setStretchFactor(1, 0)
            splitter.setHandleWidth(5)
            splitter.setSizes([2, 1])
            return splitter

    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_action.setEnabled(not state and not self.is_interpreter)
        self.debug_action.setEnabled(not state and not self.is_interpreter)
        self.args_action.setEnabled(not state and not self.is_interpreter)
        if state:
            if self.arguments:
                argstr = _("Arguments: %s") % self.arguments
            else:
                argstr = _("No argument")
        else:
            argstr = _("Arguments...")
        self.args_action.setText(argstr)
        self.terminate_button.setVisible(not self.is_interpreter and state)
        if not state:
            self.toggle_globals_explorer(False)
        for btn in (self.cwd_button, self.env_button, self.syspath_button):
            btn.setEnabled(state and self.monitor_enabled)
        if self.namespacebrowser_button is not None:
            self.namespacebrowser_button.setEnabled(state)

    def set_namespacebrowser(self, namespacebrowser):
        """
        Set namespace browser *widget*
        Note: this method is not used in stand alone mode
        """
        self.namespacebrowser = namespacebrowser
        self.configure_namespacebrowser()

    def configure_namespacebrowser(self):
        """Connect the namespace browser to the notification thread"""
        if self.notification_thread is not None:
            self.connect(self.notification_thread,
                         SIGNAL('refresh_namespace_browser()'),
                         self.namespacebrowser.refresh_table)
            signal = self.notification_thread.sig_process_remote_view
            signal.connect(self.namespacebrowser.process_remote_view)

    def create_process(self):
        self.shell.clear()

        self.process = QProcess(self)
        if self.merge_output_channels:
            self.process.setProcessChannelMode(QProcess.MergedChannels)
        else:
            self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))

        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if DEBUG >= 3:
            p_args += ['-v']
        p_args += get_python_args(self.fname, self.python_args,
                                  self.interact_action.isChecked(),
                                  self.debug_action.isChecked(),
                                  self.arguments)

        env = [unicode(_path) for _path in self.process.systemEnvironment()]

        if self.pythonstartup:
            env.append('PYTHONSTARTUP=%s' % self.pythonstartup)

        # Monitor
        if self.monitor_enabled:
            env.append('SPYDER_SHELL_ID=%s' % id(self))
            env.append('SPYDER_AR_TIMEOUT=%d' % self.autorefresh_timeout)
            env.append('SPYDER_AR_STATE=%r' % self.autorefresh_state)
            from SMlib.widgets.externalshell import introspection
            introspection_server = introspection.start_introspection_server()
            introspection_server.register(self)
            notification_server = introspection.start_notification_server()
            self.notification_thread = notification_server.register(self)
            self.connect(
                self.notification_thread,
                SIGNAL('pdb(QString,int)'), lambda fname, lineno: self.emit(
                    SIGNAL('pdb(QString,int)'), fname, lineno))
            self.connect(
                self.notification_thread,
                SIGNAL('new_ipython_kernel(QString)'), lambda args: self.emit(
                    SIGNAL('create_ipython_client(QString)'), args))
            self.connect(
                self.notification_thread, SIGNAL('open_file(QString,int)'),
                lambda fname, lineno: self.emit(
                    SIGNAL('open_file(QString,int)'), fname, lineno))
            if self.namespacebrowser is not None:
                self.configure_namespacebrowser()
            env.append('SPYDER_I_PORT=%d' % introspection_server.port)
            env.append('SPYDER_N_PORT=%d' % notification_server.port)

        # External modules options
        env.append('ETS_TOOLKIT=%s' % self.ets_backend)
        env.append('MATPLOTLIB_PATCH=%r' % self.mpl_patch_enabled)
        if self.mpl_backend:
            env.append('MATPLOTLIB_BACKEND=%s' % self.mpl_backend)
        if self.qt_api:
            env.append('QT_API=%s' % self.qt_api)
        env.append('INSTALL_QT_INPUTHOOK=%s' % self.install_qt_inputhook)
        env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr)
        #        # Socket-based alternative (see input hook in sitecustomize.py):
        #        if self.install_qt_inputhook:
        #            from PyQt4.QtNetwork import QLocalServer
        #            self.local_server = QLocalServer()
        #            self.local_server.listen(str(id(self)))
        if self.pyqt_api:
            env.append('PYQT_API=%d' % self.pyqt_api)
        env.append('IGNORE_SIP_SETAPI_ERRORS=%s' %
                   self.ignore_sip_setapi_errors)

        # User Module Deleter
        if self.is_interpreter:
            env.append('UMD_ENABLED=%r' % self.umd_enabled)
            env.append('UMD_NAMELIST=%s' % ','.join(self.umd_namelist))
            env.append('UMD_VERBOSE=%r' % self.umd_verbose)

        # IPython kernel
        env.append('IPYTHON_KERNEL=%r' % self.is_ipykernel)

        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)

        # Adding Spyder path
        pathlist += self.path

        # Adding path list to PYTHONPATH environment variable
        add_pathlist_to_PYTHONPATH(env, pathlist)

        #-------------------------Python specific-------------------------------

        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     self.write_error)
        self.connect(self.process,
                     SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self, SIGNAL('finished()'), self.dialog_manager.close_all)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"), self.process.kill)

        #-------------------------Python specific-------------------------------
        # Fixes for our Mac app:
        # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app,
        #    but their values are messing sys.path for external interpreters
        #    (e.g. EPD) so we need to remove them from the environment.
        # 2. Add this file's dir to PYTHONPATH. This will make every external
        #    interpreter to use our sitecustomize script.
        # 3. Remove PYTHONOPTIMIZE from env so that we can have assert
        #    statements working with our interpreters (See Issue 1281)
        if sys.platform == 'darwin' and 'Spyder.app' in __file__:
            env.append('SPYDER_INTERPRETER=%s' % self.pythonexecutable)
            if 'Spyder.app' not in self.pythonexecutable:
                env = [p for p in env if not (p.startswith('PYTHONPATH') or \
                                              p.startswith('PYTHONHOME'))] # 1.

                env.append('PYTHONPATH=%s' % osp.dirname(__file__))  # 2.

            env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')]  # 3.

        self.process.setEnvironment(env)
        self.process.start(self.pythonexecutable, p_args)
        #-------------------------Python specific-------------------------------

        running = self.process.waitForStarted(3000)
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(
                self, _("Error"),
                _("A Python or IPython Console failed to start!"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))

        return self.process

    def finished(self, exit_code, exit_status):
        """Reimplement ExternalShellBase method"""
        ExternalShellBase.finished(self, exit_code, exit_status)
        self.introspection_socket = None

#===============================================================================
#    Input/Output
#===============================================================================

    def write_error(self):
        if os.name == 'nt':
            #---This is apparently necessary only on Windows (not sure though):
            #   emptying standard output buffer before writing error output
            self.process.setReadChannel(QProcess.StandardOutput)
            if self.process.waitForReadyRead(1):
                self.write_output()
        self.shell.write_error(self.get_stderr())
        QApplication.processEvents()

    def send_to_process(self, text):
        if not self.is_running():
            return

        if not isinstance(text, basestring):
            text = unicode(text)
        if self.install_qt_inputhook and self.introspection_socket is not None:
            communicate(self.introspection_socket,
                        "toggle_inputhook_flag(True)")
#            # Socket-based alternative (see input hook in sitecustomize.py):
#            while self.local_server.hasPendingConnections():
#                self.local_server.nextPendingConnection().write('go!')
        if text.startswith(('%', '!')):
            text = 'evalsc(r"%s")\n' % text
        if not text.endswith('\n'):
            text += '\n'
        self.process.write(locale_codec.fromUnicode(text))
        self.process.waitForBytesWritten(-1)

        # Eventually write prompt faster (when hitting Enter continuously)
        # -- necessary/working on Windows only:
        if os.name == 'nt':
            self.write_error()

    def keyboard_interrupt(self):
        if self.introspection_socket is not None:
            communicate(self.introspection_socket, "thread.interrupt_main()")

    def quit_monitor(self):
        if self.introspection_socket is not None:
            try:
                write_packet(self.introspection_socket, "thread.exit()")
            except socket.error:
                pass

#===============================================================================
#    Globals explorer
#===============================================================================

    def toggle_globals_explorer(self, state):
        if self.stand_alone is not None:
            self.splitter.setSizes([1, 1 if state else 0])
            self.namespacebrowser_button.setChecked(state)
            if state and self.namespacebrowser is not None:
                self.namespacebrowser.refresh_table()

    def splitter_moved(self, pos, index):
        self.namespacebrowser_button.setChecked(self.splitter.sizes()[1])

#===============================================================================
#    Misc.
#===============================================================================

    def set_current_working_directory(self):
        """Set current working directory"""
        cwd = self.shell.get_cwd()
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        directory = getexistingdirectory(self, _("Select directory"), cwd)
        if directory:
            self.shell.set_cwd(directory)
        self.emit(SIGNAL('redirect_stdio(bool)'), True)

    def show_env(self):
        """Show environment variables"""
        get_func = self.shell.get_env
        set_func = self.shell.set_env
        self.dialog_manager.show(RemoteEnvDialog(get_func, set_func))

    def show_syspath(self):
        """Show sys.path contents"""
        editor = DictEditor()
        editor.setup(self.shell.get_syspath(),
                     title="sys.path",
                     readonly=True,
                     width=600,
                     icon='syspath.png')
        self.dialog_manager.show(editor)
Example #18
0
class PluginProcessBase(QObject):
	proc_list = []

	def __init__(self, wdir):
		QObject.__init__(self)
		
		PluginProcess.proc_list.append(self)
		self.is_rebuild = False
		self.is_query_fl = False

		self.sig = QuerySignal()

		self.proc = QProcess()
		self.proc.finished.connect(self._finished_cb)
		self.proc.error.connect(self._error_cb)

		self.proc.setWorkingDirectory(wdir)
		self.wdir = wdir

	def _cleanup(self):
		PluginProcess.proc_list.remove(self)
		if self.err_str != '':
			s = '<b>' + self.p_cmd + '</b><p>' + '<p>'.join(self.err_str.splitlines())
			QMessageBox.warning(None, "Seascope", s, QMessageBox.Ok)
		if self.res != '':
			s = '<b>' + self.p_cmd + '</b><p>Summary<p>' + self.res
			QMessageBox.information(None, "Seascope", s, QMessageBox.Ok)

	def _error_cb(self, err):
		err_dict = { 
			QProcess.FailedToStart:	'FailedToStart',
			QProcess.Crashed:	'Crashed',
			QProcess.Timedout:	'The last waitFor...() function timed out',
			QProcess.WriteError:	'An error occurred when attempting to write to the process',
			QProcess.ReadError:	'An error occurred when attempting to read from the process',
			QProcess.UnknownError:	'An unknown error occurred',
		}
		self.err_str = '<b>' + self.p_cmd + '</b><p>' + err_dict[err]
		self._cleanup()

	def _finished_cb(self, ret):
		res = str(self.proc.readAllStandardOutput())
		self.err_str = str(self.proc.readAllStandardError())
		
		#print 'output', res
		#print 'cmd:', self.p_cmd
		if self.is_rebuild:
			self.res = res
			self.sig.sig_rebuild.emit()
		elif self.is_query_fl:
			self.res = ''
			res = self.parse_query_fl(res)
			self.sig.sig_query_fl.emit(res)
		else:
			self.res = ''
			self.sig.sig_result_dbg.emit(self.p_cmd, res, self.err_str)
			try:
				res = self.parse_result(res, self.sig)
			except Exception as e:
				print e
				res = [['', '', '', 'error while parsing output of: ' + self.p_cmd]]
			if res != None:
				self.sig.emit_result(res)

		self._cleanup()

	def run_query_process(self, pargs, sym, rquery=None):
		self.sig.sym = sym
		self.sig.rquery = rquery
		self.p_cmd = ' '.join(pargs)
		if os.getenv('SEASCOPE_DEBUG'):
			print self.p_cmd
		self.proc.start(pargs[0], pargs[1:])
		if self.proc.waitForStarted() == False:
			return None
		self.proc.closeWriteChannel()
		return [self.sig.sig_result, self.sig.sig_result_dbg]

	def run_rebuild_process(self, pargs):
		self.is_rebuild = True
		self.p_cmd = ' '.join(pargs)
		self.proc.start(pargs[0], pargs[1:])
		if self.proc.waitForStarted() == False:
			return None
		#print 'cmd:', pargs
		self.sig.sig_rebuild.connect(CtagsCache.flush)
		return self.sig.sig_rebuild

	def run_query_fl(self, pargs):
		self.is_query_fl = True
		self.p_cmd = ' '.join(pargs)
		self.proc.start(pargs[0], pargs[1:])
		if self.proc.waitForStarted() == False:
			return None
		return self.sig.sig_query_fl

	def parse_query_fl(self, text):
		fl = []
		for f in re.split('\r?\n', text.strip()):
			if f == '':
				continue
			fl.append(os.path.join(self.wdir, f))
		return fl
Example #19
0
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPyQsciShell

    def __init__(self,
                 parent=None,
                 fname=None,
                 wdir=None,
                 commands=[],
                 interact=False,
                 debug=False,
                 path=[]):
        ExternalShellBase.__init__(self,
                                   parent,
                                   wdir,
                                   history_filename='.history_ec.py')

        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_check.setChecked(interact)
        self.debug_check.setChecked(debug)

        self.monitor_socket = None
        self.interpreter = fname is None
        self.fname = startup.__file__ if fname is None else fname

        if self.interpreter:
            self.interact_check.hide()
            self.debug_check.hide()
            self.terminate_button.hide()

        self.commands = ["import sys", "sys.path.insert(0, '')"] + commands

        # Additional python path list
        self.path = path

    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        self.globalsexplorer_button = create_toolbutton(
            self,
            get_icon('dictedit.png'),
            self.tr("Variables"),
            tip=self.tr("Show/hide global variables explorer"),
            toggled=self.toggle_globals_explorer)
        self.terminate_button = create_toolbutton(
            self,
            get_icon('terminate.png'),
            self.tr("Terminate"),
            tip=self.tr("Attempts to terminate the process.\n"
                        "The process may not exit as a result of clicking "
                        "this button\n(it is given the chance to prompt "
                        "the user for any unsaved files, etc)."))
        self.interact_check = QCheckBox(self.tr("Interact"), self)
        self.debug_check = QCheckBox(self.tr("Debug"), self)
        return [
            self.interact_check, self.debug_check, self.globalsexplorer_button,
            self.run_button, self.terminate_button, self.kill_button
        ]

    def get_shell_widget(self):
        # Globals explorer
        self.globalsexplorer = GlobalsExplorer(self)
        self.connect(self.globalsexplorer, SIGNAL('collapse()'),
                     lambda: self.toggle_globals_explorer(False))

        # Shell splitter
        self.splitter = splitter = QSplitter(Qt.Vertical, self)
        self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                     self.splitter_moved)
        splitter.addWidget(self.shell)
        splitter.setCollapsible(0, False)
        splitter.addWidget(self.globalsexplorer)
        splitter.setStretchFactor(0, 2)
        splitter.setStretchFactor(1, 1)
        return splitter

    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_check.setEnabled(not state)
        self.debug_check.setEnabled(not state)
        self.terminate_button.setEnabled(state)
        if not state:
            self.toggle_globals_explorer(False)
        self.globalsexplorer_button.setEnabled(state)

    def create_process(self):
        self.shell.clear()

        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))

        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if self.interact_check.isChecked():
            p_args.append('-i')
        if self.debug_check.isChecked():
            p_args.extend(['-m', 'pdb'])
        p_args.append(self.fname)

        env = self.process.systemEnvironment()

        # Monitor
        env.append('SHELL_ID=%s' % id(self))
        from spyderlib.widgets.externalshell.monitor import start_server
        server, port = start_server()
        self.notification_thread = server.register(str(id(self)), self)
        self.connect(self.notification_thread, SIGNAL('refresh()'),
                     self.globalsexplorer.refresh_table)
        env.append('SPYDER_PORT=%d' % port)

        # Python init commands (interpreter only)
        if self.commands and self.interpreter:
            env.append('PYTHONINITCOMMANDS=%s' % ';'.join(self.commands))
            self.process.setEnvironment(env)

        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)

        # Adding Spyder path
        pathlist += self.path

        # Adding path list to PYTHONPATH environment variable
        pypath = "PYTHONPATH"
        pathstr = os.pathsep.join(pathlist)
        if os.environ.get(pypath) is not None:
            env.replaceInStrings(pypath + '=',
                                 pypath + '=' + pathstr + os.pathsep,
                                 Qt.CaseSensitive)
        else:
            env.append(pypath + '=' + pathstr)
        self.process.setEnvironment(env)
        #-------------------------Python specific-------------------------------

        if self.arguments:
            p_args.extend(self.arguments.split(' '))

        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process,
                     SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"), self.process.kill)

        #-------------------------Python specific-------------------------------
        self.process.start(sys.executable, p_args)
        #-------------------------Python specific-------------------------------

        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))

        return self.process

#===============================================================================
#    Input/Output
#===============================================================================

    def _write_error(self, text, findstr):
        pos = text.find(findstr)
        if pos != -1:
            self.shell.write(text[:pos])
            if text.endswith(">>> "):
                self.shell.write_error(text[pos:-5])
                self.shell.write(text[-5:], flush=True)
            else:
                self.shell.write_error(text[pos:])
            return True
        return False

    def write_output(self):
        text = self.get_stdout()
        if not self._write_error(text, 'Traceback (most recent call last):') \
           and not self._write_error(text, 'File "<stdin>", line 1'):
            self.shell.write(text)
        QApplication.processEvents()

    def send_to_process(self, qstr):
        if not isinstance(qstr, QString):
            qstr = QString(qstr)
        if not qstr.endsWith('\n'):
            qstr.append('\n')
        self.process.write(qstr.toLocal8Bit())
        self.process.waitForBytesWritten(-1)

    def keyboard_interrupt(self):
        communicate(self.monitor_socket, "thread.interrupt_main()")

#===============================================================================
#    Globals explorer
#===============================================================================

    def toggle_globals_explorer(self, state):
        self.splitter.setSizes([1, 1 if state else 0])
        self.globalsexplorer_button.setChecked(state)
        if state:
            self.globalsexplorer.refresh_table()

    def splitter_moved(self, pos, index):
        self.globalsexplorer_button.setChecked(self.splitter.sizes()[1])
Example #20
0
class ProfilerWidget(QWidget):
    """
    Profiler widget
    """
    DATAPATH = get_conf_path('.profiler.results')
    VERSION = '0.0.1'
    
    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)
        
        self.setWindowTitle("Profiler")
        
        self.output = None
        self.error_output = None
        
        self.filecombo = PythonModulesComboBox(self)
        
        self.start_button = create_toolbutton(self, icon=get_icon('run.png'),
                                    text=translate('Profiler', "Profile"),
                                    tip=translate('Profiler', "Run profiler"),
                                    triggered=self.start, text_beside_icon=True)
        self.stop_button = create_toolbutton(self,
                                    icon=get_icon('terminate.png'),
                                    text=translate('Profiler', "Stop"),
                                    tip=translate('Profiler',
                                                  "Stop current profiling"),
                                    text_beside_icon=True)
        self.connect(self.filecombo, SIGNAL('valid(bool)'),
                     self.start_button.setEnabled)
        #self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
        # FIXME: The combobox emits this signal on almost any event
        #        triggering show_data() too early, too often. 

        browse_button = create_toolbutton(self, icon=get_icon('fileopen.png'),
                               tip=translate('Profiler', 'Select Python script'),
                               triggered=self.select_file)

        self.datelabel = QLabel()

        self.log_button = create_toolbutton(self, icon=get_icon('log.png'),
                                    text=translate('Profiler', "Output"),
                                    text_beside_icon=True,
                                    tip=translate('Profiler',
                                                  "Show program's output"),
                                    triggered=self.show_log)

        self.datatree = ProfilerDataTree(self)

        self.collapse_button = create_toolbutton(self, icon=get_icon('collapse.png'),
                                    triggered=lambda dD=-1:self.datatree.change_view(dD),
                                    tip='Collapse one level up')
        self.expand_button = create_toolbutton(self, icon=get_icon('expand.png'),
                                    triggered=lambda dD=1:self.datatree.change_view(dD),
                                    tip='Expand one level down')

        
        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.collapse_button)
        hlayout2.addWidget(self.expand_button)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)
        
        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.datatree)
        self.setLayout(layout)
        
        self.process = None
        self.set_running_state(False)
        
        if not is_profiler_installed():
            for widget in (self.datatree, self.filecombo,
                           self.start_button, self.stop_button):
                widget.setDisabled(True)
            if os.name == 'nt' \
               and programs.is_module_installed("profile"):
                # The following is a comment from the pylint plugin:
                # Module is installed but script is not in PATH
                # (AFAIK, could happen only on Windows)
                text = translate('Profiler',
                     'Profiler script was not found. Please add "%s" to PATH.')
                text = unicode(text) % os.path.join(sys.prefix, "Scripts")
            else:
                text = translate('Profiler',
                    ('Please install the modules '+
                     '<b>profile</b> and <b>pstats</b>:'))
                # FIXME: need the actual website
                url = 'http://www.python.org'
                text += ' <a href=%s>%s</a>' % (url, url)
            self.datelabel.setText(text)
        else:
            pass # self.show_data()
                
    def analyze(self, filename):
        if not is_profiler_installed():
            return
        filename = unicode(filename) # filename is a QString instance
        self.kill_if_running()
        #index, _data = self.get_data(filename)
        index=None # FIXME: storing data is not implemented yet
        if index is None:
            self.filecombo.addItem(filename)
            self.filecombo.setCurrentIndex(self.filecombo.count()-1)
        else:
            self.filecombo.setCurrentIndex(self.filecombo.findText(filename))
        self.filecombo.selected()
        if self.filecombo.is_valid():
            self.start()
            
    def select_file(self):
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        filename = QFileDialog.getOpenFileName(self,
                      translate('Profiler', "Select Python script"), os.getcwdu(),
                      translate('Profiler', "Python scripts")+" (*.py ; *.pyw)")
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        if filename:
            self.analyze(filename)
        
    def show_log(self):
        if self.output:
            TextEditor(self.output, title=translate('Profiler', "Profiler output"),
                       readonly=True, size=(700, 500)).exec_()
    
    def show_errorlog(self):
        if self.error_output:
            TextEditor(self.error_output, title=translate('Profiler', "Profiler output"),
                       readonly=True, size=(700, 500)).exec_()
        
    def start(self):
        self.datelabel.setText('Profiling, please wait...')
        filename = unicode(self.filecombo.currentText())
        
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.process.setWorkingDirectory(os.path.dirname(filename))
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.read_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     lambda: self.read_output(error=True))
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        self.connect(self.stop_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        self.output = ''
        self.error_output = ''
        p_args = [os.path.basename(filename)]
        
        # FIXME: Use the system path to 'python' as opposed to hardwired
        p_args = ['-m', PROFILER_PATH, '-o', self.DATAPATH, os.path.basename(filename)]
        self.process.start('python', p_args)
        
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, translate('Profiler', "Error"),
                                 translate('Profiler', "Process failed to start"))
    
    def set_running_state(self, state=True):
        self.start_button.setEnabled(not state)
        self.stop_button.setEnabled(state)
        
    def read_output(self, error=False):
        if error:
            self.process.setReadChannel(QProcess.StandardError)
        else:
            self.process.setReadChannel(QProcess.StandardOutput)
        bytes = QByteArray()
        while self.process.bytesAvailable():
            if error:
                bytes += self.process.readAllStandardError()
            else:
                bytes += self.process.readAllStandardOutput()
        text = unicode( QString.fromLocal8Bit(bytes.data()) )
        if error:
            self.error_output += text
        else:
            self.output += text
        
    def finished(self):
        self.set_running_state(False)
        self.show_errorlog()  # If errors occurred, show them.
        self.output = self.error_output + self.output
        # FIXME: figure out if show_data should be called here or
        #        as a signal from the combobox
        self.show_data(justanalyzed=True)
                
    def kill_if_running(self):
        if self.process is not None:
            if self.process.state() == QProcess.Running:
                self.process.kill()
                self.process.waitForFinished()
        
    def show_data(self, justanalyzed=False):
        if not justanalyzed:
            self.output = None
        self.log_button.setEnabled(self.output is not None \
                                   and len(self.output) > 0)
        self.kill_if_running()
        filename = unicode(self.filecombo.currentText())
        if not filename:
            return

        self.datatree.load_data(self.DATAPATH)
        self.datatree.show_tree()
            
        text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
        date_text = text_style % time.strftime("%d %b %Y %H:%M",time.localtime())
        self.datelabel.setText(date_text)
Example #21
0
class pat_toolbar:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        Args:
            iface (QgsInterface): An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        """

        # Save reference to the QGIS interface
        self.iface = iface

        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n', 'pat_plugin_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        self.actions = []

        # Look for the existing menu
        self.menuPrecAg = self.iface.mainWindow().findChild(QMenu, 'm{}Menu'.format(PLUGIN_SHORT))

        # If the menu does not exist, create it!
        if not self.menuPrecAg:
            self.menuPrecAg = QMenu('{}'.format(PLUGIN_SHORT), self.iface.mainWindow().menuBar())
            self.menuPrecAg.setObjectName('m{}Menu'.format(PLUGIN_SHORT))
            actions = self.iface.mainWindow().menuBar().actions()
            lastAction = actions[-1]
            self.iface.mainWindow().menuBar().insertMenu(lastAction, self.menuPrecAg)

        # create a toolbar
        self.toolbar = self.iface.addToolBar(u'{} Toolbar'.format(PLUGIN_SHORT))
        self.toolbar.setObjectName(u'm{}ToolBar'.format(PLUGIN_SHORT))

        # Load Defaults settings for First time...
        for eaKey in ['BASE_IN_FOLDER', 'BASE_OUT_FOLDER']:
            sFolder = read_setting(PLUGIN_NAME + '/' + eaKey)
            if sFolder is None or not os.path.exists(sFolder):
                sFolder = os.path.join(os.path.expanduser('~'), PLUGIN_NAME)

                if not os.path.exists(sFolder):
                    os.mkdir(sFolder)

                write_setting(PLUGIN_NAME + '/' + eaKey, os.path.join(os.path.expanduser('~'), PLUGIN_NAME))

        self.DEBUG = config.get_debug_mode()
        self.vesper_queue = []
        self.vesper_queue_showing = False
        self.processVesper = None
        self.vesper_exe = check_vesper_dependency(iface)

        if not os.path.exists(TEMPDIR):
            os.mkdir(TEMPDIR)

    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        Args:
            message (str, QString): String for translation.

        Returns:
            QString: Translated version of message.
        """

        return QCoreApplication.translate('pat', message)

    def add_action(self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True,
                   tool_tip=None, status_tip=None, whats_this=None, parent=None):
        """Add a toolbar icon to the toolbar.

                Args:
                    icon_path (str): Path to the icon for this action. Can be a resource
                         path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
                    text (str): Text that should be shown in menu items for this action.
                    callback (function): Function to be called when the action is triggered.
                    enabled_flag (bool): A flag indicating if the action should be enabled
                             by default. Defaults to True.
                    add_to_menu (bool): Flag indicating whether the action should also
                            be added to the menu. Defaults to True.
                    add_to_toolbar (bool): Flag indicating whether the action should also
                            be added to the toolbar. Defaults to True.
                    tool_tip (str):  Optional text to show in a popup when mouse pointer
                            hovers over the action.
                    status_tip (str):  Optional text to show in the status bar when mouse pointer
                            hovers over the action.
                    whats_this (QWidget): Parent widget for the new action. Defaults None.
                    parent (): Optional text to show in the status bar when the
                            mouse pointer hovers over the action.
                Returns:
                    QAction: The action that was created. Note that the action is also
                            added to self.actions list.
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if tool_tip is not None:
            action.setToolTip(tool_tip)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.menuPrecAg.addAction(action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        '''Create new menu item
            source:https://gis.stackexchange.com/questions/169869/adding-multiple-plugins-to-custom-pluginMenu-in-qgis/169880#169880
                  https://gis.stackexchange.com/questions/127150/how-to-customize-the-qgis-gui-using-python '''

        # Finally, add your action to the menu and toolbar
        self.add_action(
            icon_path=':/plugins/pat/icons/icon_blockGrid.svg',
            text=self.tr(u'Create block grid'),
            tool_tip=self.tr(u'Create raster and VESPER grids for block polygons.'),
            status_tip=self.tr(u'Create raster and VESPER grids for block polygons.'),
            callback=self.run_blockGrid,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_cleanTrimPoints.svg',
            text=self.tr(u'Clean, trim and normalise data points'),
            tool_tip=self.tr(u'Clean, trim and normalise data points'),
            status_tip=self.tr(u'Clean, trim and normalise data points'),
            callback=self.run_cleanTrimPoints,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_vesperKriging.svg',
            text=self.tr(u'Run kriging using VESPER'),
            tool_tip=self.tr(u'Run kriging using VESPER'),
            status_tip=self.tr(u'Run kriging using VESPER'),
            callback=self.run_preVesper,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_importVesperKriging.svg',
            text=self.tr(u'Import VESPER results'),
            tool_tip=self.tr(u'Import VESPER results'),
            status_tip=self.tr(u'Import VESPER results'),
            add_to_toolbar=False,
            callback=self.run_postVesper,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_pointTrailToPolygon.svg',
            text=self.tr(u'Create polygons from on-the-go GPS point trail'),
            tool_tip=self.tr(u'Create polygons from on-the-go GPS point trail'),
            status_tip=self.tr(u'Create polygons from on-the-go GPS point trail'),
            add_to_toolbar=False,
            callback=self.run_pointTrailToPolygon,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_rescaleNormalise.svg',
            text=self.tr(u'Rescale or normalise raster'),
            tool_tip=self.tr(u'Rescale or normalise raster'),
            status_tip=self.tr(u'Rescale or normalise raster'),
            add_to_toolbar=False,
            callback=self.run_rescaleNormalise,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_randomPixel.svg',
            text=self.tr(u'Generate random pixel selection'),
            tool_tip=self.tr(u'Generate random pixel selection'),
            status_tip=self.tr(u'Generate random pixel selection'),
            add_to_toolbar=True,
            callback=self.run_generateRandomPixels,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_gridExtract.svg',
            text=self.tr(u'Extract raster pixel statistics for points'),
            tool_tip=self.tr(u'Extract raster pixel statistics for points'),
            status_tip=self.tr(u'Extract raster pixel statistics for points'),
            add_to_toolbar=True,
            callback=self.run_gridExtract,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_calcImgIndices.svg',
            text=self.tr(u'Calculate image indices for blocks'),
            tool_tip=self.tr(u'Calculate image indices for blocks'),
            status_tip=self.tr(u'Calculate image indices for blocks'),
            add_to_toolbar=True,
            callback=self.run_calculateImageIndices,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_resampleToBlock.svg',
            text=self.tr(u'Resample image band to blocks'),
            tool_tip=self.tr(u'Resample image band to blocks'),
            status_tip=self.tr(u'Resample image band to blocks'),
            add_to_toolbar=True,
            callback=self.run_resampleImage2Block,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_kMeansCluster.svg',
            text=self.tr(u'Create zones with k-means clustering'),
            tool_tip=self.tr(u'Create zones with k-means clustering'),
            status_tip=self.tr(u'Create zones with k-means clustering'),
            add_to_toolbar=True,
            callback=self.run_kMeansClustering,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_stripTrialPoints.svg',
            text=self.tr(u'Create strip trial points'),
            tool_tip=self.tr(u'Create strip trial points'),
            status_tip=self.tr(u'Create strip trial points'),
            add_to_toolbar=True,
            callback=self.run_stripTrialPoints,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_t-test.svg',
            text=self.tr(u'Run strip trial t-test analysis'),
            tool_tip=self.tr(u'Run strip trial t-test analysis'),
            status_tip=self.tr(u'Run strip trial t-test analysis'),
            add_to_toolbar=True,
            callback=self.run_tTestAnalysis,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_wholeOfBlockExp.svg',
            text=self.tr(u'Whole-of-block analysis'),
            tool_tip=self.tr(u'Whole-of-block analysis using co-kriging'),
            status_tip=self.tr(u'Whole-of-block analysis using co-kriging'),
            add_to_toolbar=True,
            callback=self.run_wholeOfBlockAnalysis,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_persistor.svg',
            text=self.tr(u'Persistor'),
            tool_tip=self.tr(u'Persistence over years'),
            status_tip=self.tr(u'Persistence over years'),
            add_to_toolbar=True,
            callback=self.run_persistor,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_rasterSymbology.svg',
            text=self.tr(u'Apply Raster Symbology'),
            tool_tip=self.tr(u'Apply Raster Symbology'),
            status_tip=self.tr(u'Apply Raster Symbology'),
            add_to_toolbar=True,
            callback=self.run_rasterSymbology,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_help.svg',
            text=self.tr(u'Help'),
            tool_tip=self.tr(u'Help'),
            status_tip=self.tr(u'Help'),
            callback=self.run_help,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_settings.svg',
            text=self.tr(u'Settings'),
            tool_tip=self.tr(u'Settings'),
            add_to_toolbar=False,
            status_tip=self.tr(u'Settings'),
            callback=self.run_settings,
            parent=self.iface.mainWindow())

        self.add_action(
            icon_path=':/plugins/pat/icons/icon_about.svg',
            text=self.tr(u'About'),
            tool_tip=self.tr(u'About'),
            status_tip=self.tr(u'About'),
            add_to_toolbar=False,
            callback=self.run_about,
            parent=self.iface.mainWindow())

    @staticmethod
    def clear_modules():
        """Unload pyprecag functions and try to return QGIS.
        source: inasafe plugin
        """
        # next lets force remove any pyprecag related modules
        modules = []
        for module in sys.modules:
            if 'pyprecag' in module:
                LOGGER.debug('Removing: %s' % module)
                modules.append(module)

        for module in modules:
            del (sys.modules[module])

        # Lets also clean up all the path additions that were made
        package_path = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))
        LOGGER.debug('Path to remove: %s' % package_path)
        # We use a list comprehension to ensure duplicate entries are removed
        LOGGER.debug(sys.path)
        sys.path = [y for y in sys.path if package_path not in y]
        LOGGER.debug(sys.path)

    def unload(self):
        """Removes the plugin menu/toolbar item and icon from QGIS GUI and clean up temp folder"""

        if len(self.vesper_queue) > 0:
            replyQuit = QMessageBox.information(self.iface.mainWindow(),
                                                "Quit QGIS", "Quitting QGIS with {} tasks in the "
                                                "VESPER queue.\n\t{}".format(len(self.vesper_queue),
                                                '\n\t'.join([ea['control_file'] for ea in self.vesper_queue])),
                                                QMessageBox.Ok)

        stop_logging('pyprecag')

        layermap = QgsMapLayerRegistry.instance().mapLayers()
        RemoveLayers = []
        for name, layer in layermap.iteritems():
            if TEMPDIR in layer.source():
                RemoveLayers.append(layer.id())

        if len(RemoveLayers) > 0:
            QgsMapLayerRegistry.instance().removeMapLayers(RemoveLayers)

        # remove the PrecisionAg Temp Folder.
        try:
            if not self.DEBUG and os.path.exists(TEMPDIR):
                shutil.rmtree(TEMPDIR)

        except Exception as err:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            mess = str(traceback.format_exc())
            print(mess)

        self.menuPrecAg.clear()
        for action in self.actions:
            self.iface.removePluginMenu(u'{}Menu'.format(PLUGIN_SHORT), action)
            self.iface.removeToolBarIcon(action)

        # remove the toolbar
        del self.toolbar
        del self.menuPrecAg
        self.clear_modules()

    def queueAddTo(self, vesp_dict):
        """ Add a control file to the VESPER queue"""

        if next((x for x in self.vesper_queue if x['control_file'] == vesp_dict["control_file"])
                , None) is not None:

            self.iface.messageBar().pushMessage('Control file is already in the VESPER queue. {}'.format(
                vesp_dict['control_file']),level=QgsMessageBar.WARNING, duration=15)

            self.queueDisplay()

        else:
            self.vesper_queue.append(vesp_dict)
            message = 'Added control file to VESPER queue. The queue now contains {} tasks'.format(
                len(self.vesper_queue))
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.INFO, duration=15)

    def queueDisplay(self):
        """display the VESPER queue in the python console"""

        # open the python console
        try:
            pythonConsolePanel = self.iface.mainWindow().findChild(QDockWidget, 'PythonConsole')
            if not pythonConsolePanel.isVisible():
                self.iface.actionShowPythonDialog().trigger()
        except:
            # the above will bail if sitting on RecentProjects empty view.
            self.iface.actionShowPythonDialog().trigger()
            pythonConsolePanel = self.iface.mainWindow().findChild(QDockWidget, 'PythonConsole')

        ctrl_width = len(max([os.path.basename(ea['control_file']) for ea in self.vesper_queue], key=len))
        epsg_width = len(max([str(ea['epsg']) for ea in self.vesper_queue], key=len))

        header = '{:3}\t{:<{cw}}\t{:5}\t{:>{ew}} {}'.format(
            '#', 'Control File', 'Import', 'EPSG', 'Folder', cw=ctrl_width + 10, ew=epsg_width + 10)

        print('\n' + '-' * len(header))
        print(header)
        print('-' * len(header))
        for i, ea in enumerate(self.vesper_queue):
            print('{:3}\t{:<{cw}}\t{:5}\t{:>{ew}}\t{}'.format(
                i + 1, os.path.basename(ea['control_file']), str(bool(ea['epsg'] > 0)), ea['epsg'],
                os.path.dirname(ea['control_file']), cw=ctrl_width + 10, ew=epsg_width + 10))

        print('\n')

    def queueClear(self):
        """Clear the VESPER queue of all pending jobs"""
        # clear all but the one running.
        if self.processVesper is None:
            self.vesper_queue = []
            self.queueStatusBarHide()
        else:
            self.vesper_queue = self.vesper_queue[:1]
            self.lblVesperQueue.setText('{} tasks in VESPER queue'.format(len(self.vesper_queue)))

        self.queueDisplay()

    def queueStatusBarShow(self):
        """Add to QGIS status bar buttons to show and clear the VESPER queue"""
        # source: https://gis.stackexchange.com/a/153170
        # https://github.com/ActiveState/code/blob/master/recipes/Python/578692_QGstartscript_Change_display/recipe-578692.py

        if not self.vesper_queue_showing:  # it is not initiated
            self.iface.mainWindow().statusBar().setSizeGripEnabled(False)
            self.lblVesperQueue = QLabel()
            self.lblVesperQueue.setText('{} tasks in VESPER queue'.format(len(self.vesper_queue)))
            self.iface.mainWindow().statusBar().insertPermanentWidget(1, self.lblVesperQueue)

            self.btnShowQueue = QToolButton()  # QToolButton() takes up less room
            self.btnShowQueue.setToolButtonStyle(Qt.ToolButtonTextOnly)
            self.btnShowQueue.setText("Show")
            self.btnShowQueue.clicked.connect(self.queueDisplay)
            self.iface.mainWindow().statusBar().insertPermanentWidget(2, self.btnShowQueue)

            self.btnClearQueue = QToolButton()  # QPushButton()
            self.btnClearQueue.setToolButtonStyle(Qt.ToolButtonTextOnly)
            self.btnClearQueue.setText("Clear")
            self.btnClearQueue.pressed.connect(self.queueClear)
            self.iface.mainWindow().statusBar().insertPermanentWidget(3, self.btnClearQueue)
            self.vesper_queue_showing = True

    def queueStatusBarHide(self):
        """Remove VESPER queue information and buttons from the status bar"""
        for obj in [self.btnClearQueue, self.btnShowQueue, self.lblVesperQueue]:
            self.iface.mainWindow().statusBar().removeWidget(obj)
            del obj

        self.vesper_queue_showing = False

    def processRunVesper(self):
        """Run the next task in the VESPER queue"""

        # Queueing: http://www.qtforum.org/article/32172/qprocess-how-to-run-multiple-processes-in-a-loop.html

        self.vesper_run_time = time.time()
        if self.processVesper is None:
            self.processVesper = QProcess()
            # set a duration variable
            self.processVesper.started.connect(self.processStartedVesper)
            # sets a task for when finished.
            self.processVesper.finished.connect(self.processFinishedVesper)

        self.queueStatusBarShow()

        ctrl_file = self.vesper_queue[0]['control_file']
        self.processVesper.setWorkingDirectory(os.path.dirname(ctrl_file))

        # run and catch when finished: https://gist.github.com/justinfx/5174795     1)QProcess
        QTimer.singleShot(100, partial(self.processVesper.start, self.vesper_exe, [ctrl_file]))

    def processStartedVesper(self):  # connected to process.started slot
        self.vesper_run_time = time.time()

    def processFinishedVesper(self, exitCode, exitStatus):  # connected to process.finished slot
        """When VESPER is complete, import the results to TIFF and QGIS"""
        currentTask = self.vesper_queue[0]

        if exitCode == 0 and exitStatus == QProcess.NormalExit:
            self.processVesper.close()
            self.processVesper = None

            if currentTask['epsg'] > 0:
                try:
                    out_PredTif, out_SETif, out_CITxt = vesper_text_to_raster(currentTask['control_file'],
                                                                              currentTask['epsg'])

                    raster_sym = RASTER_SYMBOLOGY['Yield']

                    removeFileFromQGIS(out_PredTif)
                    rasterLyr = addRasterFileToQGIS(out_PredTif, atTop=False)
                    raster_apply_classified_renderer(rasterLyr,
                                    rend_type=raster_sym['type'],
                                    num_classes=raster_sym['num_classes'],
                                    color_ramp=raster_sym['colour_ramp'])

                    removeFileFromQGIS(out_SETif)
                    addRasterFileToQGIS(out_SETif, atTop=False)

                except Exception as err:
                    message = "Could not import from VESPER to raster TIFF possibly due to a " \
                              "VESPER error.\n{}".format(os.path.basename(currentTask['control_file']))

                    LOGGER.error(message)

            message = "Completed VESPER kriging for {}\t Duration H:M:SS - {dur}".format(
                        os.path.basename(currentTask['control_file']),
                        dur=datetime.timedelta(seconds=time.time() - self.vesper_run_time))
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.INFO, duration=15)
            LOGGER.info(message)

        else:
            message = "Error occurred with VESPER kriging for {}".format(currentTask['control_file'])
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.CRITICAL, duration=0)
            LOGGER.error(message)

        self.vesper_queue = self.vesper_queue[1:]  # remove the recently finished one which will always be at position 0

        self.lblVesperQueue.setText('{} tasks in VESPER queue'.format(len(self.vesper_queue)))

        if len(self.vesper_queue) > 0:
            self.vesper_run_time = time.time()
            self.processRunVesper()

        else:
            self.vesper_queue = []
            self.vesper_run_time = ''
            self.queueStatusBarHide()

        return

    def run_persistor(self):
        """Run method for the Persistor dialog"""

        if parse_version(pyprecag.__version__) < parse_version('0.2.0'):
            self.iface.messageBar().pushMessage("Persistor is not supported in "
                                                "pyprecag {}. Upgrade to version 0.3.0+".format(
                pyprecag.__version__), level=QgsMessageBar.WARNING, duration=15)
            return

        dlgPersistor = PersistorDialog(self.iface)

        # Show the dialog
        dlgPersistor.show()

        if dlgPersistor.exec_():
            message = 'Persistor completed successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            # LOGGER.info(message)

        # Close Dialog
        dlgPersistor.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_wholeOfBlockAnalysis(self):
        """Run method for the fit to block grid dialog"""
        # https://gis.stackexchange.com/a/160146

        result = check_R_dependency()
        if result is not True:
            self.iface.messageBar().pushMessage("R configuration", result,
                                                level=QgsMessageBar.WARNING, duration=15)
            return

        proc_alg_mess = ProcessingAlgMessages(self.iface)
        QgsMessageLog.instance().messageReceived.connect(proc_alg_mess.processingCatcher)

        # Then get the algorithm you're interested in (for instance, Join Attributes):
        alg = Processing.getAlgorithm("r:wholeofblockanalysis")
        if alg is None:
            self.iface.messageBar().pushMessage("Whole-of-block analysis algorithm could not"
                                                " be found", level=QgsMessageBar.CRITICAL)
            return
        # Instantiate the commander window and open the algorithm's interface
        cw = CommanderWindow(self.iface.mainWindow(), self.iface.mapCanvas())
        if alg is not None:
            cw.runAlgorithm(alg)

        # if proc_alg_mess.alg_name == '' then cancel was clicked

        if proc_alg_mess.error:
            self.iface.messageBar().pushMessage("Whole-of-block analysis", proc_alg_mess.error_msg,
                                                level=QgsMessageBar.CRITICAL, duration=0)
        elif proc_alg_mess.alg_name != '':
            data_column = proc_alg_mess.parameters['Data_Column']

            # load rasters into qgis as grouped layers.
            for key, val in proc_alg_mess.output_files.items():

                grplyr = os.path.join('Whole-of-block {}'.format(data_column),  val['title'])

                for ea_file in val['files']:
                    removeFileFromQGIS(ea_file)
                    raster_layer = addRasterFileToQGIS(ea_file, group_layer_name=grplyr, atTop=False)
                    if key in ['p_val']:
                        raster_apply_unique_value_renderer(raster_layer)

            self.iface.messageBar().pushMessage("Whole-of-block analysis Completed Successfully!",
                                                level=QgsMessageBar.INFO, duration=15)

        del proc_alg_mess

    def run_stripTrialPoints(self):

        if parse_version(pyprecag.__version__) < parse_version('0.2.0'):
            self.iface.messageBar().pushMessage(
                "Create strip trial points tool is not supported in pyprecag {}. "
                "Upgrade to version 0.2.0+".format(pyprecag.__version__),
                level=QgsMessageBar.WARNING, duration=15)
            return

        """Run method for the Strip trial points dialog"""
        dlgStripTrialPoints = StripTrialPointsDialog(self.iface)

        # Show the dialog
        dlgStripTrialPoints.show()

        if dlgStripTrialPoints.exec_():
            message = 'Strip trial points created successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            # LOGGER.info(message)

        # Close Dialog
        dlgStripTrialPoints.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_tTestAnalysis(self):
        if parse_version(pyprecag.__version__) < parse_version('0.3.0'):
            self.iface.messageBar().pushMessage("Create t-test analysis tool is not supported in "
                                                "pyprecag {}. Upgrade to version 0.3.0+".format(
                pyprecag.__version__), level=QgsMessageBar.WARNING, duration=15)
            return

        """Run method for the Strip trial points dialog"""
        dlg_tTestAnalysis = tTestAnalysisDialog(self.iface)

        # Show the dialog
        dlg_tTestAnalysis.show()

        if dlg_tTestAnalysis.exec_():
            output_folder = dlg_tTestAnalysis.lneOutputFolder.text()
            import webbrowser
            try:
                from urllib import pathname2url         # Python 2.x
            except:
                from urllib.request import pathname2url # Python 3.x

            def open_folder():
                url = 'file:{}'.format(pathname2url(os.path.abspath(output_folder)))
                webbrowser.open(url)

            message = 'Strip trial t-test analysis completed!'

            # Add hyperlink to messagebar - this works but it places the text on the right, not left.
            # variation of QGIS-master\python\plugins\db_manager\db_tree.py
            # msgLabel = QLabel(self.tr('{0} <a href="{1}">{1}</a>'.format(message, output_folder)), self.iface.messageBar())
            # msgLabel.linkActivated.connect(open_folder)
            # self.iface.messageBar().pushWidget(msgLabel,level=QgsMessageBar.SUCCESS, duration=15)

            # so use a button instead
            widget = self.iface.messageBar().createMessage('', message)
            button = QPushButton(widget)
            button.setText('Open Folder')
            button.pressed.connect(open_folder)
            widget.layout().addWidget(button)
            self.iface.messageBar().pushWidget(widget, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlg_tTestAnalysis.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_kMeansClustering(self):
        """Run method for the Calculate Image Indices dialog"""
        dlgKMeansCluster = KMeansClusterDialog(self.iface)

        # Show the dialog
        dlgKMeansCluster.show()

        if dlgKMeansCluster.exec_():
            message = 'Zones with k-means clusters completed successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            # LOGGER.info(message)

        # Close Dialog
        dlgKMeansCluster.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_calculateImageIndices(self):
        """Run method for the Calculate Image Indices dialog"""
        dlgCalcImgIndices = CalculateImageIndicesDialog(self.iface)

        # Show the dialog
        dlgCalcImgIndices.show()

        if dlgCalcImgIndices.exec_():
            message = 'Image indices calculated successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlgCalcImgIndices.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_resampleImage2Block(self):
        """Run method for the Resample image to block grid dialog"""
        dlgResample2Block = ResampleImageToBlockDialog(self.iface)

        # Show the dialog
        dlgResample2Block.show()

        if dlgResample2Block.exec_():
            message = 'Resample to block grid completed Successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlgResample2Block.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_gridExtract(self):
        """Run method for the Grid Extract dialog"""
        dlgGridExtract = GridExtractDialog(self.iface)

        # Show the dialog
        dlgGridExtract.show()

        if dlgGridExtract.exec_():
            output_file = dlgGridExtract.lneSaveCSVFile.text()

            import webbrowser
            try:
                from urllib import pathname2url  # Python 2.x
            except:
                from urllib.request import pathname2url  # Python 3.x

            def open_folder():
                url = 'file:{}'.format(pathname2url(os.path.abspath(output_file)))
                webbrowser.open(url)

            message = 'Raster statistics for points extracted successfully !'
            #add a button to open the file outside qgis
            widget = self.iface.messageBar().createMessage('', message)
            button = QPushButton(widget)
            button.setText('Open File')
            button.pressed.connect(open_folder)
            widget.layout().addWidget(button)
            self.iface.messageBar().pushWidget(widget, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlgGridExtract.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_generateRandomPixels(self):
        """Run method for the Generate random pixels dialog"""
        dlgGenRandomPixel = RandomPixelSelectionDialog(self.iface)

        # Show the dialog
        dlgGenRandomPixel.show()

        if dlgGenRandomPixel.exec_():
            message = 'Random pixel selection completed successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlgGenRandomPixel.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_rescaleNormalise(self):
        """Run method for the rescale/normalise dialog"""
        dlgRescaleNorm = RescaleNormaliseDialog(self.iface)

        # Show the dialog
        dlgRescaleNorm.show()

        if dlgRescaleNorm.exec_():
            message = 'Rescale/Normalise completed successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlgRescaleNorm.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_preVesper(self):
        """Run method for preVesper dialog"""

        dlgPreVesper = PreVesperDialog(self.iface)

        # show the dialog
        dlgPreVesper.show()

        if dlgPreVesper.exec_():
            if dlgPreVesper.gbRunVesper.isChecked():
                self.queueAddTo(dlgPreVesper.vesp_dict)
                self.processRunVesper()
                if len(self.vesper_queue) > 0:
                    self.lblVesperQueue.setText('{} tasks in VESPER queue'.format(len(self.vesper_queue)))

        # Close Dialog
        dlgPreVesper.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_postVesper(self):
        """Run method for importing VESPER results dialog"""
        dlgPostVesper = PostVesperDialog(self.iface)

        # show the dialog
        dlgPostVesper.show()

        if dlgPostVesper.exec_():
            if dlgPostVesper.chkRunVesper.isChecked():

                self.queueAddTo(dlgPostVesper.vesp_dict)
                # if this is the first in the queue then start the processing.
                self.processRunVesper()

                if len(self.vesper_queue) > 0:
                    self.lblVesperQueue.setText('{} tasks in VESPER queue'.format(len(self.vesper_queue)))

        # Close Dialog
        dlgPostVesper.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_cleanTrimPoints(self):
        """Run method for cleanTrimPoints dialog"""
        dlgCleanTrimPoints = CleanTrimPointsDialog(self.iface)

        # show the dialog
        dlgCleanTrimPoints.show()

        if dlgCleanTrimPoints.exec_():
            output_folder = os.path.dirname(dlgCleanTrimPoints.lneSaveCSVFile.text())
            import webbrowser
            try:
                from urllib import pathname2url  # Python 2.x
            except:
                from urllib.request import pathname2url  # Python 3.x

            def open_folder():
                url = 'file:{}'.format(pathname2url(os.path.abspath(output_folder)))
                webbrowser.open(url)

            message = 'Cleaned and trimmed points successfully !'

            widget = self.iface.messageBar().createMessage('', message)
            button = QPushButton(widget)
            button.setText('Open Folder')
            button.pressed.connect(open_folder)
            widget.layout().addWidget(button)

            self.iface.messageBar().pushWidget(widget, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlgCleanTrimPoints.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_blockGrid(self):
        """Run method for the block grid dialog"""
        dlgBlockGrid = BlockGridDialog(self.iface)

        # Show the dialog
        dlgBlockGrid.show()

        if dlgBlockGrid.exec_():
            message = 'Block grid completed successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlgBlockGrid.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()


    def run_pointTrailToPolygon(self):
        """Run method for pointTrailToPolygon dialog"""
        dlgPointTrailToPolygon = PointTrailToPolygonDialog(self.iface)

        # show the dialog
        dlgPointTrailToPolygon.show()

        if dlgPointTrailToPolygon.exec_():
            message = 'On-the-go point trail to polygon completed successfully !'
            self.iface.messageBar().pushMessage(message, level=QgsMessageBar.SUCCESS, duration=15)
            LOGGER.info(message)

        # Close Dialog
        dlgPointTrailToPolygon.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_rasterSymbology(self):
        """Run method for the Raster Symbology dialog"""
        dlgRasterSymbology = RasterSymbologyDialog(self.iface)

        # Show the dialog
        dlgRasterSymbology.show()

        if dlgRasterSymbology.exec_():
            pass

        # Close Dialog
        dlgRasterSymbology.deleteLater()

        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_help(self):
        """Open the help PDF"""
        webbrowser.open_new('file:///' + os.path.join(PLUGIN_DIR, 'PAT_User_Manual.pdf#pagemode=bookmarks'))

    def run_about(self):
        """Run method for the about dialog"""
        dlgAbout = AboutDialog()
        if dlgAbout.exec_():
            pass

        dlgAbout.deleteLater()
        # Refresh QGIS
        QCoreApplication.processEvents()

    def run_settings(self):
        """Run method for the about dialog"""
        dlgSettings = SettingsDialog()
        if dlgSettings.exec_():
            self.vesper_exe = dlgSettings.vesper_exe
            self.DEBUG = config.get_debug_mode()

        dlgSettings.deleteLater()
Example #22
0
class EjecutarWidget(QWidget):

    def __init__(self):
        super(EjecutarWidget, self).__init__()
        layoutV = QVBoxLayout(self)
        layoutV.setContentsMargins(0, 0, 0, 0)
        layoutV.setSpacing(0)
        self.output = output_compiler.SalidaCompilador(self)
        layoutV.addWidget(self.output)
        self.setLayout(layoutV)

        # Flag
        self._compilation_failed = False

        # Procesos
        self.build_process = QProcess(self)
        if not sys.platform.startswith('linux'):
            self._envgcc = QProcessEnvironment.systemEnvironment()
            self._envgcc.insert("PATH", ENV_GCC)
            self.build_process.setProcessEnvironment(self._envgcc)
        self.execution_process = QProcess(self)

        # Conexiones
        self.build_process.readyReadStandardError.connect(
            self.output.stderr_output)
        self.build_process.finished[int, QProcess.ExitStatus].connect(
            self._compilation_finished)
        self.build_process.error[QProcess.ProcessError].connect(
            self._compilation_error)
        self.execution_process.finished[int, QProcess.ExitStatus].connect(
            self._execution_finished)

    def _execution_finished(self, code, status):
        if status == QProcess.CrashExit:
            text = output_compiler.Item(
                self.tr("La ejecución se ha interrumpido"))
            text.setForeground(Qt.red)
            self.output.addItem(text)
        else:
            text = output_compiler.Item(
                self.tr("Ejecución Exitosa!"))
            text.setForeground(QColor("#7FE22A"))
            self.output.addItem(text)

    def run_compilation(self, sources):
        """ Se corre el comando gcc para la compilación """

        # Ejecutable
        filename, files = sources
        if not files:
            # No es un proyecto
            files = [filename]
        path = QDir.fromNativeSeparators(filename)
        self.exe = os.path.splitext(os.path.basename(path))[0]

        # Generar el ejecutable en el directorio del código fuente
        exe_path = os.path.dirname(path)
        self.build_process.setWorkingDirectory(exe_path)

        # Se limpia el QListWidget
        self.output.clear()

        flags = settings.COMPILER_FLAGS.split()
        params = ['-o', self.exe] + flags
        gcc = 'gcc'
        if not sys.platform.startswith("linux"):
            gcc = os.path.join(self._environment, 'gcc')

        item = output_compiler.Item(
            self.tr(">>> Compilando: {0} ( en directorio {1} )").format(
                    path.split('/')[-1], exe_path))
        self.output.addItem(item)
        self.output.addItem(output_compiler.Item(
            self.tr(">>> Comando: {0}").format(
                gcc + ' ' + ' '.join(params) + ' ' + ' '.join(files))))

        # Se inicia el proceso
        self.build_process.start(gcc, params + files)
        self.build_process.waitForFinished()

    def _compilation_finished(self, code, status):
        """
        Cuando la compilación termina @codigoError toma dos valores:
            0 = La compilación ha terminado de forma correcta
            1 = La compilación ha fallado

        """

        if status == QProcess.NormalExit and code == 0:
            self._compilation_failed = False
            item_ok = output_compiler.Item(
                self.tr("¡LA COMPILACIÓN HA SIDO EXITOSA!"))
            self.output.addItem(item_ok)
            item_ok.setForeground(QColor("#7FE22A"))
        else:
            self._compilation_failed = True
            item_error = output_compiler.Item(
                self.tr("¡LA COMPILACIÓN HA FALLADO!"))
            item_error.setForeground(QColor("#E20000"))
            self.output.addItem(item_error)
        syntax_ok = True if code == 0 else False
        self.emit(SIGNAL("updateSyntaxCheck(bool)"), syntax_ok)
        code_status = output_compiler.Item(
                self.tr("Proceso terminado con código: {0}").format(code),
                italic=True)
        self.output.addItem(code_status)
        count = self.output.count()
        self.output.setCurrentRow(count - 1, QItemSelectionModel.NoUpdate)

    def _compilation_error(self, error):
        """
        Éste método se ejecuta cuando el inicio del proceso de compilación
        falla. Una de las causas puede ser la ausencia del compilador.

        """

        text = output_compiler.Item(
            self.tr("Se ha producido un error. Compilador no encontrado."))
        text.setForeground(Qt.red)
        self.output.addItem(text)

    def run_program(self, sources):
        """ Ejecuta el binario generado por el compilador """

        path = os.path.dirname(sources[0])
        self.execution_process.setWorkingDirectory(path)
        # Path ejecutable
        path_exe = os.path.join(path, self.exe)
        if not settings.IS_LINUX:
            path_exe += '.exe'
        # Si no existe se termina el proceso
        if not self._check_file_exists(path_exe):
            text = output_compiler.Item(
                self.tr("El archivo no existe: {0}").format(path_exe))
            text.setForeground(Qt.red)
            self.output.addItem(text)
            return
        # Texto en la salida
        text = output_compiler.Item(
            self.tr("Ejecutando... {0}").format(path_exe))
        self.output.addItem(text)

        if settings.IS_LINUX:
            # Run !
            terminal = settings.get_setting('terminal')
            arguments = [os.path.join(paths.PATH, "tools",
                         "run_script.sh %s" % path_exe)]
            self.execution_process.start(terminal, ['-e'] + arguments)
        else:
            pauser = os.path.join(paths.PATH, "tools", "pauser",
                                  "system_pause.exe")
            process = [pauser] + ["\"%s\"" % path_exe]
            Popen(process, creationflags=CREATE_NEW_CONSOLE)

    def _check_file_exists(self, exe):
        """ Comprueba si el ejecutable existe """

        exists = True
        if not os.path.exists(exe):
            exists = False
        return exists

    @property
    def _environment(self):
        """ Devuelve la variable de entorno gcc """

        return self._envgcc.value("PATH", "")

    def build_and_run(self, archivo):
        self.run_compilation(archivo)
        if not self._compilation_failed:
            self.run_program(archivo)

    def clean(self, exe):
        """ Elimina el binario generado por la compilación """

        if exe is None:
            return
        binary = exe.split('.')[0]
        if not settings.IS_LINUX:
            binary += '.exe'
        os.remove(binary)

    def kill_process(self):
        """ Termina el proceso """

        self.execution_process.kill()
Example #23
0
class ExternalSystemShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = TerminalWidget
    def __init__(self, parent=None, wdir=None, path=[], light_background=True,
                 menu_actions=None, show_buttons_inside=True,
                 show_elapsed_time=True):
        ExternalShellBase.__init__(self, parent=parent, fname=None, wdir=wdir,
                                   history_filename='.history',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)
        
        # Additional python path list
        self.path = path
        
        # For compatibility with the other shells that can live in the external
        # console
        self.is_ipykernel = False
        self.connection_file = None

    def get_icon(self):
        return get_icon('cmdprompt.png')
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        
        # PYTHONPATH (in case we use Python in this terminal, e.g. py2exe)
        env = [unicode(_path) for _path in self.process.systemEnvironment()]
        add_pathlist_to_PYTHONPATH(env, self.path)
        self.process.setEnvironment(env)
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)
            
        # Shell arguments
        if os.name == 'nt':
            p_args = ['/Q']
        else:
            p_args = ['-i']
            
        if self.arguments:
            p_args.extend( shell_split(self.arguments) )
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        if os.name == 'nt':
            self.process.start('cmd.exe', p_args)
        else:
            # Using bash:
            self.process.start('bash', p_args)
            self.send_to_process("""PS1="\u@\h:\w> "\n""")
            
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, _("Error"),
                                 _("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            
        return self.process
    
#===============================================================================
#    Input/Output
#===============================================================================
    def transcode(self, bytes):
        if os.name == 'nt':
            return encoding.transcode(str(bytes.data()), 'cp850')
        else:
            return ExternalShellBase.transcode(self, bytes)
    
    def send_to_process(self, text):
        if not isinstance(text, basestring):
            text = unicode(text)
        if text[:-1] in ["clear", "cls", "CLS"]:
            self.shell.clear()
            self.send_to_process(os.linesep)
            return
        if not text.endswith('\n'):
            text += '\n'
        if os.name == 'nt':
            self.process.write(text.encode('cp850'))
        else:
            self.process.write(locale_codec.fromUnicode(text))
        self.process.waitForBytesWritten(-1)
        
    def keyboard_interrupt(self):
        # This does not work on Windows:
        # (unfortunately there is no easy way to send a Ctrl+C to cmd.exe)
        self.send_ctrl_to_process('c')

#        # The following code will soon be removed:
#        # (last attempt to send a Ctrl+C on Windows)
#        if os.name == 'nt':
#            pid = int(self.process.pid())
#            import ctypes, win32api, win32con
#            class _PROCESS_INFORMATION(ctypes.Structure):
#                _fields_ = [("hProcess", ctypes.c_int),
#                            ("hThread", ctypes.c_int),
#                            ("dwProcessID", ctypes.c_int),
#                            ("dwThreadID", ctypes.c_int)]
#            x = ctypes.cast( ctypes.c_void_p(pid),
#                             ctypes.POINTER(_PROCESS_INFORMATION) )
#            win32api.GenerateConsoleCtrlEvent(win32con.CTRL_C_EVENT,
#                                              x.dwProcessID)
#        else:
#            self.send_ctrl_to_process('c')
                
Example #24
0
class PylintWidget(QWidget):
    """
    Pylint widget
    """
    DATAPATH = get_conf_path('.pylint.results')
    VERSION = '1.0.2'
    
    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)
        
        self.output = None
        self.error_output = None
        
        self.max_entries = max_entries
        self.data = [self.VERSION]
        if osp.isfile(self.DATAPATH):
            try:
                data = cPickle.load(file(self.DATAPATH))
                if data[0] == self.VERSION:
                    self.data = data
            except EOFError:
                pass

        self.filecombo = PythonModulesComboBox(self)
        if self.data:
            self.remove_obsolete_items()
            self.filecombo.addItems(self.get_filenames())
        
        self.start_button = create_toolbutton(self, get_icon('run.png'),
                                    translate('Pylint', "Analyze"),
                                    tip=translate('Pylint', "Run analysis"),
                                    triggered=self.start)
        self.stop_button = create_toolbutton(self, get_icon('terminate.png'),
                                    translate('Pylint', "Stop"),
                                    tip=translate('Pylint',
                                                  "Stop current analysis"))
        self.connect(self.filecombo, SIGNAL('valid(bool)'),
                     self.start_button.setEnabled)
        self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)

        browse_button = create_toolbutton(self, get_icon('fileopen.png'),
                               tip=translate('Pylint', 'Select Python script'),
                               triggered=self.select_file)

        self.ratelabel = QLabel()
        self.datelabel = QLabel()
        self.log_button = create_toolbutton(self, get_icon('log.png'),
                                    translate('Pylint', "Output"),
                                    tip=translate('Pylint',
                                                  "Complete Pylint output"),
                                    triggered=self.show_log)
        self.treewidget = ResultsTree(self)
        
        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.ratelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)
        
        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.treewidget)
        self.setLayout(layout)
        
        self.process = None
        self.set_running_state(False)
        
        if not is_pylint_installed():
            for widget in (self.treewidget, self.filecombo,
                           self.start_button, self.stop_button):
                widget.setDisabled(True)
            text = translate('Pylint', 'Please install <b>pylint</b>:')
            url = 'http://www.logilab.fr'
            text += ' <a href=%s>%s</a>' % (url, url)
            self.ratelabel.setText(text)
        else:
            self.show_data()
        
    def analyze(self, filename):
        if not is_pylint_installed():
            return
        filename = unicode(filename) # filename is a QString instance
        self.kill_if_running()
        index, _data = self.get_data(filename)
        if index is None:
            self.filecombo.addItem(filename)
            self.filecombo.setCurrentIndex(self.filecombo.count()-1)
        else:
            self.filecombo.setCurrentIndex(index)
        self.filecombo.selected()
        if self.filecombo.is_valid():
            self.start()
            
    def select_file(self):
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        filename = QFileDialog.getOpenFileName(self,
                      translate('Pylint', "Select Python script"), os.getcwdu(),
                      translate('Pylint', "Python scripts")+" (*.py ; *.pyw)")
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        if filename:
            self.analyze(filename)
            
    def remove_obsolete_items(self):
        """Removing obsolete items"""
        self.data = [self.VERSION] + \
                    [(filename, data) for filename, data in self.data[1:]
                     if is_module_or_package(filename)]
        
    def get_filenames(self):
        return [filename for filename, _data in self.data[1:]]
    
    def get_data(self, filename):
        filename = osp.abspath(filename)
        for index, (fname, data) in enumerate(self.data[1:]):
            if fname == filename:
                return index, data
        else:
            return None, None
            
    def set_data(self, filename, data):
        filename = osp.abspath(filename)
        index, _data = self.get_data(filename)
        if index is not None:
            self.data.pop(index)
        self.data.append( (filename, data) )
        self.save()
        
    def set_max_entries(self, max_entries):
        self.max_entries = max_entries
        self.save()
        
    def save(self):
        while len(self.data) > self.max_entries+1:
            self.data.pop(1)
        cPickle.dump(self.data, file(self.DATAPATH, 'w'))
        
    def show_log(self):
        if self.output:
            TextEditor(self.output, title=translate('Pylint', "Pylint output"),
                       readonly=True, size=(700, 500)).exec_()
        
    def start(self):
        filename = unicode(self.filecombo.currentText())
        
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.process.setWorkingDirectory(osp.dirname(filename))
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.read_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     lambda: self.read_output(error=True))
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        self.connect(self.stop_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        self.output = ''
        self.error_output = ''
        p_args = [osp.basename(filename)]
        self.process.start(PYLINT_PATH, p_args)
        
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, translate('Pylint', "Error"),
                                 translate('Pylint', "Process failed to start"))
    
    def set_running_state(self, state=True):
        self.start_button.setEnabled(not state)
        self.stop_button.setEnabled(state)
        
    def read_output(self, error=False):
        if error:
            self.process.setReadChannel(QProcess.StandardError)
        else:
            self.process.setReadChannel(QProcess.StandardOutput)
        bytes = QByteArray()
        while self.process.bytesAvailable():
            if error:
                bytes += self.process.readAllStandardError()
            else:
                bytes += self.process.readAllStandardOutput()
        text = unicode( QString.fromLocal8Bit(bytes.data()) )
        if error:
            self.error_output += text
        else:
            self.output += text
        
    def finished(self):
        self.set_running_state(False)
        if not self.output:
            return
        
        # Convention, Refactor, Warning, Error
        results = {'C:': [], 'R:': [], 'W:': [], 'E:': []}
        txt_module = '************* Module '
        
        module = '' # Should not be needed - just in case something goes wrong
        for line in self.output.splitlines():
            if line.startswith(txt_module):
                # New module
                module = line[len(txt_module):]
                continue
            for prefix in results:
                if line.startswith(prefix):
                    break
            else:
                continue
            i1 = line.find(':')
            if i1 == -1:
                continue
            i2 = line.find(':', i1+1)
            if i2 == -1:
                continue
            line_nb = line[i1+1:i2].strip()
            if not line_nb:
                continue
            line_nb = int(line_nb)
            message = line[i2+1:]
            item = (module, line_nb, message)
            results[line[:i1+1]].append(item)                
            
        # Rate
        rate = None
        txt_rate = 'Your code has been rated at '
        i_rate = self.output.find(txt_rate)
        if i_rate > 0:
            i_rate_end = self.output.find('/10', i_rate)
            if i_rate_end > 0:
                rate = self.output[i_rate+len(txt_rate):i_rate_end]
        
        # Previous run
        previous = ''
        if rate is not None:
            txt_prun = 'previous run: '
            i_prun = self.output.find(txt_prun, i_rate_end)
            if i_prun > 0:
                i_prun_end = self.output.find('/10', i_prun)
                previous = self.output[i_prun+len(txt_prun):i_prun_end]
            
        
        filename = unicode(self.filecombo.currentText())
        self.set_data(filename, (time.localtime(), rate, previous, results))
        self.output = self.error_output + self.output
        self.show_data(justanalyzed=True)
        
    def kill_if_running(self):
        if self.process is not None:
            if self.process.state() == QProcess.Running:
                self.process.kill()
                self.process.waitForFinished()
        
    def show_data(self, justanalyzed=False):
        if not justanalyzed:
            self.output = None
        self.log_button.setEnabled(self.output is not None \
                                   and len(self.output) > 0)
        self.kill_if_running()
        filename = unicode(self.filecombo.currentText())
        if not filename:
            return
        
        _index, data = self.get_data(filename)
        if data is None:
            text = translate('Pylint', 'Source code has not been rated yet.')
            self.treewidget.clear()
            date_text = ''
        else:
            datetime, rate, previous_rate, results = data
            if rate is None:
                text = translate('Pylint', 'Analysis did not succeed '
                                           '(see output for more details).')
                self.treewidget.clear()
                date_text = ''
            else:
                text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
                rate_style = "<span style=\'color: %s\'><b>%s</b></span>"
                prevrate_style = "<span style=\'color: #666666\'>%s</span>"
                color = "#FF0000"
                if float(rate) > 5.:
                    color = "#22AA22"
                elif float(rate) > 3.:
                    color = "#EE5500"
                text = translate('Pylint', 'Global evaluation:')
                text = (text_style % text)+(rate_style % (color,
                                                          ('%s/10' % rate)))
                if previous_rate:
                    text_prun = translate('Pylint', 'previous run:')
                    text_prun = ' (%s %s/10)' % (text_prun, previous_rate)
                    text += prevrate_style % text_prun
                self.treewidget.set_results(filename, results)
                date_text = text_style % time.strftime("%d %b %Y %H:%M",
                                                       datetime)
            
        self.ratelabel.setText(text)
        self.datelabel.setText(date_text)
Example #25
0
class BatchFileSync(SyncProvider):
    def __init__(self, name, project, **kwargs):
        super(BatchFileSync, self).__init__(name, project)
        self.cmd = kwargs['cmd']
        if self.project:
            self.rootfolder = os.path.abspath(self.project.folder)
        else:
            self.rootfolder = kwargs['rootfolder']

        self.project = project
        self.closeproject = kwargs.get("close_project", False)
        self.process = QProcess()
        self.parser = kwargs.get("parser", None)
        self.parsermodule = None
        variables = kwargs.get("variables", {})
        env = QProcessEnvironment.systemEnvironment()
        for varname, value in variables.iteritems():
            env.insert(varname, str(value))
        self.process.setProcessEnvironment(env)
        self.process.setWorkingDirectory(os.path.dirname(os.path.realpath(self.cmd)))
        self.process.finished.connect(self.complete)
        self.process.started.connect(self.syncStarted)
        self.process.readyReadStandardError.connect(self.error)
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self._output = ""
        self.haserror = False

    def import_parser_module(self):
        import imp
        name = self.parser
        module = imp.find_module(name, [self.rootfolder])
        module = imp.load_module(name, *module)
        self.parsermodule = module
        print self.parsermodule

    def start(self):
        if not self.parsermodule and self.parser:
            self.import_parser_module()

        self._output = ""
        self.haserror = False
        self.process.start(self.cmd, [])

    @property
    def output(self):
        return self._output

    @output.setter
    def output(self, value):
        self._output = value

    def error(self):
        self.haserror = True

    def complete(self, error, status):
        if error > 0 or self.haserror:
            stderr = self.process.readAllStandardError().data()
            self.syncError.emit(stderr)
        else:
            self.syncComplete.emit()
        self.syncFinished.emit()

    def readOutput(self):
        output = str(self.process.readAll())
        ok = True
        if self.parsermodule:
            ok, output = self.parsermodule.sync_output(output)

        if not ok:
            self.haserror = True
            self.process.kill()
            self.syncError.emit(output)
        else:
            if output:
                self.syncMessage.emit(output)
Example #26
0
class serverwidget(QtGui.QFrame):
    def __init__(self, aname, apath):
        super(serverwidget, self).__init__()
        self.process = None
        self.path = apath
        self.name = aname
        self.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Sunken)
        title = QtGui.QLabel(self.name)
        startbutton = QtGui.QPushButton('START')
        killbutton = QtGui.QPushButton('TERMINATE')
        pingbutton = QtGui.QPushButton('PING')
        self.textfield = QtGui.QTextEdit()
        self.textfield.setReadOnly(True)
        startbutton.pressed.connect(self.start_server)
        killbutton.pressed.connect(self.kill_server)
        pingbutton.pressed.connect(self.ping_server)

        sublayout = QtGui.QVBoxLayout()
        sublayout.addWidget(title)
        sublayout.addWidget(startbutton)
        sublayout.addWidget(killbutton)
        sublayout.addWidget(pingbutton)
        sublayout.addWidget(self.textfield)
        self.setLayout(sublayout)

    def start_server(self):
        if self.process is None:
            self.process = QProcess()
            self.process.readyReadStandardOutput.connect(self.read_output)
            self.process.started.connect(
                lambda: self.write_message('Server started'))
            self.process.finished.connect(
                lambda: self.write_message('Server stopped'))
            self.process.setProcessChannelMode(QProcess.MergedChannels)
            self.process.setWorkingDirectory(os.path.dirname(self.path))
            self.process.start('python', [self.path])
        else:
            self.textfield.append(
                'Cannot start "{:}", as it is already running'.format(
                    self.name))

    def kill_server(self):
        if self.process is not None:
            self.process.terminate()
            self.process = None
        else:
            self.textfield.append(
                'Cannot terminate "{:}", as it is not running'.format(
                    self.name))

    def ping_server(self):
        if self.process is not None:
            state = self.process.state()
            msg = "PING: "
            if state == 0:
                msg += 'Process died'
            elif state == 1:
                msg += 'Process is starting up'
            elif state == 2:
                msg += 'Process is alive'
            self.textfield.append(msg)
            cnx = labrad.connect()
            labradserver = eval('cnx.{:}'.format(self.name))
            msg = 'PING: Labradserver is ' + labradserver.echo('alive')
            self.textfield.append(msg)
            cnx.disconnect()
        else:
            self.textfield.append('Cannot ping a server that is not started')

    def read_output(self):
        data = self.process.readAllStandardOutput()
        self.textfield.append(str(data))

    def write_message(self, message):
        self.textfield.append(message)
Example #27
0
class PluginProcessBase(QObject):
    proc_list = []

    def __init__(self, wdir):
        QObject.__init__(self)

        PluginProcess.proc_list.append(self)
        self.is_rebuild = False
        self.is_query_fl = False

        self.sig = QuerySignal()

        self.proc = QProcess()
        self.proc.finished.connect(self._finished_cb)
        self.proc.error.connect(self._error_cb)

        self.proc.setWorkingDirectory(wdir)
        self.wdir = wdir

    def _cleanup(self):
        PluginProcess.proc_list.remove(self)
        if self.err_str != '':
            s = '<b>' + self.p_cmd + '</b><p>' + '<p>'.join(
                self.err_str.splitlines())
            QMessageBox.warning(None, "Seascope", s, QMessageBox.Ok)
        if self.res != '':
            s = '<b>' + self.p_cmd + '</b><p>Summary<p>' + self.res
            QMessageBox.information(None, "Seascope", s, QMessageBox.Ok)

    def _error_cb(self, err):
        err_dict = {
            QProcess.FailedToStart: 'FailedToStart',
            QProcess.Crashed: 'Crashed',
            QProcess.Timedout: 'The last waitFor...() function timed out',
            QProcess.WriteError:
            'An error occurred when attempting to write to the process',
            QProcess.ReadError:
            'An error occurred when attempting to read from the process',
            QProcess.UnknownError: 'An unknown error occurred',
        }
        self.err_str = '<b>' + self.p_cmd + '</b><p>' + err_dict[err]
        self._cleanup()

    def _finished_cb(self, ret):
        res = str(self.proc.readAllStandardOutput())
        self.err_str = str(self.proc.readAllStandardError())

        #print 'output', res
        #print 'cmd:', self.p_cmd
        if self.is_rebuild:
            self.res = res
            self.sig.sig_rebuild.emit()
        elif self.is_query_fl:
            self.res = ''
            res = self.parse_query_fl(res)
            self.sig.sig_query_fl.emit(res)
        else:
            self.res = ''
            self.sig.sig_result_dbg.emit(self.p_cmd, res, self.err_str)
            try:
                res = self.parse_result(res, self.sig)
            except Exception as e:
                print e
                res = [[
                    '', '', '', 'error while parsing output of: ' + self.p_cmd
                ]]
            if res != None:
                self.sig.emit_result(res)

        self._cleanup()

    def run_query_process(self, pargs, sym, rquery=None):
        self.sig.sym = sym
        self.sig.rquery = rquery
        self.p_cmd = ' '.join(pargs)
        if os.getenv('SEASCOPE_DEBUG'):
            print self.p_cmd
        self.proc.start(pargs[0], pargs[1:])
        if self.proc.waitForStarted() == False:
            return None
        self.proc.closeWriteChannel()
        return [self.sig.sig_result, self.sig.sig_result_dbg]

    def run_rebuild_process(self, pargs):
        self.is_rebuild = True
        self.p_cmd = ' '.join(pargs)
        self.proc.start(pargs[0], pargs[1:])
        if self.proc.waitForStarted() == False:
            return None
        #print 'cmd:', pargs
        self.sig.sig_rebuild.connect(CtagsCache.flush)
        return self.sig.sig_rebuild

    def run_query_fl(self, pargs):
        self.is_query_fl = True
        self.p_cmd = ' '.join(pargs)
        self.proc.start(pargs[0], pargs[1:])
        if self.proc.waitForStarted() == False:
            return None
        return self.sig.sig_query_fl

    def parse_query_fl(self, text):
        fl = []
        for f in re.split('\r?\n', text.strip()):
            if f == '':
                continue
            fl.append(os.path.join(self.wdir, f))
        return fl
Example #28
0
class EjecutarWidget(QWidget):

    _script = '%s -e "bash -c ./%s;echo;echo;echo;echo -n Presione \<Enter\> '\
              'para salir.;read I"'

    def __init__(self):
        super(EjecutarWidget, self).__init__()
        self.compilado = False
        self.tiempo = 0.0
        layoutV = QVBoxLayout(self)
        layoutV.setContentsMargins(0, 0, 0, 0)
        layoutV.setSpacing(0)
        self.output = salida.SalidaCompilador(self)
        layoutV.addWidget(self.output)
        self.setLayout(layoutV)

        # Procesos
        self.proceso_compilacion = QProcess(self)
        self.proceso_ejecucion = QProcess(self)

        # Conexión
        self.output.ir_a_linea.connect(self._emitir_ir_a_linea)
        self.proceso_compilacion.readyReadStandardError.connect(
            self.output.parsear_salida_stderr)
        self.proceso_compilacion.finished[int, QProcess.ExitStatus].connect(
            self.ejecucion_terminada)
        self.proceso_compilacion.error[QProcess.ProcessError].connect(
            self._error_compilacion)
        self.proceso_ejecucion.error[QProcess.ProcessError].connect(
            self._ejecucion_terminada)

    def _emitir_ir_a_linea(self, linea):
        self.emit(SIGNAL("ir_a_linea(int)"), linea)

    def _ejecucion_terminada(self, codigo_error):
        """ Éste método es ejecutado cuando la ejecución es frenada por el
        usuario o algún otro error. """

        self.output.clear()
        if codigo_error == 1:
            error1 = salida.Item(self.tr("El proceso ha sido frenado"))
            error1.setForeground(Qt.blue)
            self.output.addItem(error1)
        else:
            error = salida.Item(self.tr("Ha ocurrido un error en la ejecución. "
                                "Código de error: %s" % codigo_error))
            error.setForeground(Qt.red)
            self.output.addItem(error)

    def correr_compilacion(self, nombre_archivo=''):
        """ Se corre el comando gcc para la compilación """

        # Ejecutable
        directorio = QDir.fromNativeSeparators(nombre_archivo)
        self.ejecutable = directorio.split('/')[-1].split('.')[0]

        # Generar el ejecutable en el directorio del código fuente
        directorio_ejecutable = os.path.dirname(directorio)
        self.proceso_compilacion.setWorkingDirectory(directorio_ejecutable)

        self.output.clear()
        item = salida.Item(self.tr(
                           "Compilando archivo: %s ( %s )" %
                           (directorio.split('/')[-1], nombre_archivo)))
        self.output.addItem(item)

        gcc = GCC
        parametros_gcc = ['-Wall', '-o']
        self.proceso_compilacion.start(gcc, parametros_gcc +
                                       [self.ejecutable] + [nombre_archivo])
        self.proceso_compilacion.waitForFinished()

    def ejecucion_terminada(self, codigoError, exitStatus):
        """
        Cuando la compilación termina @codigoError toma dos valores:
            0 = La compilación ha terminado de forma correcta
            1 = La compilación ha fallado

        """

        if exitStatus == QProcess.NormalExit and codigoError == 0:
            item_ok = salida.Item(self.tr("¡COMPILACIÓN EXITOSA!"))
            item_ok.setForeground(QColor("#0046cc"))
            self.output.addItem(item_ok)
        else:
            item_error = salida.Item(self.tr("¡LA COMPILACIÓN HA FALLADO!"))
            item_error.setForeground(Qt.red)
            self.output.addItem(item_error)
        count = self.output.count()
        self.output.setCurrentRow(count - 1, QItemSelectionModel.NoUpdate)

    def _error_compilacion(self, error):
        """
        Éste método se ejecuta cuando el inicio del proceso de compilación
        falla. Una de las causas puede ser la ausencia del compilador.

        """

        texto = salida.Item(self.tr("Ha ocurrido un error: quizás el compilador"
                            " no está instalado."))
        texto.setForeground(Qt.red)
        self.output.addItem(texto)

    def correr_programa(self, archivo):
        """ Ejecuta el binario generado por el compilador """

        #FIXME: Agregar terminal por defecto
        direc = os.path.dirname(archivo)
        self.proceso_ejecucion.setWorkingDirectory(direc)

        if configuracion.LINUX:
            proceso = 'xterm -T "%s" -e /usr/bin/cb_console_runner "%s"' \
                      % (self.ejecutable, os.path.join(direc, self.ejecutable))
            # Run !
            self.proceso_ejecucion.start(proceso)
        else:
            #FIXME: Usar QProcess
            Popen([os.path.join(direc, self.ejecutable)],
                  creationflags=CREATE_NEW_CONSOLE)

    def compilar_ejecutar(self, archivo):
        self.correr_compilacion(archivo)
        self.correr_programa(archivo)

    def limpiar(self, archivo):
        """ Elimina el binario generado por la compilación """

        if archivo is None:
            return
        binario = archivo.split('.')[0]
        if configuracion.WINDOWS:
            binario = binario + '.exe'
        os.remove(binario)

    def terminar_proceso(self):
        """ Termina el proceso """

        self.proceso_ejecucion.kill()
def __execute_PropertyBuilder_jar_using_QProcess(cwd, path_to_PropertyBuilder_jar, *args):
    from PyQt4.QtCore import QProcess, QString 
    process = QProcess()
    process.setWorkingDirectory(QString(cwd))
    process.start(QString('java -jar ' + path_to_PropertyBuilder_jar + ' ' + ' '.join(args)))
    process.waitForFinished(-1)
Example #30
0
class RunWidget(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        vbox = QVBoxLayout(self)
        vbox.setSpacing(0)
        vbox.setContentsMargins(0, 0, 0, 0)
        self.output = OutputWidget(self)
        hbox = QHBoxLayout()
        self.input = QLineEdit()
        self.lblInput = QLabel(self.tr("Input:"))
        vbox.addWidget(self.output)
        hbox.addWidget(self.lblInput)
        hbox.addWidget(self.input)
        vbox.addLayout(hbox)

        #process
        self._proc = QProcess(self)
        self.connect(self._proc, SIGNAL("readyReadStandardOutput()"),
            self.output._refresh_output)
        self.connect(self._proc, SIGNAL("readyReadStandardError()"),
            self.output._refresh_error)
        self.connect(self._proc, SIGNAL("finished(int, QProcess::ExitStatus)"),
            self.finish_execution)
        self.connect(self._proc, SIGNAL("error(QProcess::ProcessError)"),
            self.process_error)
        self.connect(self.input, SIGNAL("returnPressed()"), self.insert_input)

    def process_error(self, error):
        self.lblInput.hide()
        self.input.hide()
        self._proc.kill()
        format = QTextCharFormat()
        format.setAnchor(True)
        format.setForeground(Qt.red)
        if error == 0:
            self.output.textCursor().insertText(self.tr('Failed to start'),
                format)
        else:
            self.output.textCursor().insertText(
                self.tr('Error during execution, QProcess error: %d' % error),
                format)

    def finish_execution(self, exitCode, exitStatus):
        self.lblInput.hide()
        self.input.hide()
        format = QTextCharFormat()
        format.setAnchor(True)
        self.output.textCursor().insertText('\n\n')
        if exitStatus == QProcess.NormalExit:
            format.setForeground(Qt.green)
            self.output.textCursor().insertText(
                self.tr("Execution Successful!"), format)
        else:
            format.setForeground(Qt.red)
            self.output.textCursor().insertText(
                self.tr("Execution Interrupted"), format)

    def insert_input(self):
        text = self.input.text() + '\n'
        self._proc.writeData(text)
        self.input.setText("")

    def start_process(self, fileName, pythonPath=False, programParams=''):
        self.lblInput.show()
        self.input.show()
        self.output.setCurrentCharFormat(self.output.plain_format)
        self.output.setPlainText('Running: %s (%s)\n\n' % (fileName,
            unicode(time.ctime())))
        self.output.moveCursor(QTextCursor.Down)
        self.output.moveCursor(QTextCursor.Down)
        self.output.moveCursor(QTextCursor.Down)

        #runner.run_code_from_file(fileName)
        if not pythonPath:
            pythonPath = settings.PYTHON_PATH
        #change the working directory to the fileName dir
        file_directory = file_manager.get_folder(fileName)
        self._proc.setWorkingDirectory(file_directory)
        #force python to unbuffer stdin and stdout
        options = ['-u'] + settings.EXECUTION_OPTIONS.split()
        self._proc.start(pythonPath, options + [fileName] + \
            [p.strip() for p in programParams.split(',') if p])

    def kill_process(self):
        self._proc.kill()
#kill existing server
s = QSettings()
server_pid = s.value("X3DProcessing/server_pid")
if server_pid is not None:
    pid = int(server_pid)
    try:
        if sys.platform.startswith('win'):
            QProcess('TASKKILL /F /PID %s' % pid)
        else:
            os.kill(pid, 11)
    except:
        print('pid %s killed already' % pid)

p = QProcess()
p.setWorkingDirectory(root_folder)

http_server = ('SimpleHTTPServer', 'http.server')[sys.version_info.major == 3]
args = ('-m', http_server, str(port))

exec_dir = os.path.dirname(sys.executable)
executable = os.path.join(exec_dir,
                          ('python2',
                           'python-qgis.bat')[sys.platform.startswith('win')])

state, pid = p.startDetached(executable, args, root_folder)

print("webserver process started at pid %s, status %s" % (pid, state))

if state:
    s.setValue("X3DProcessing/server_pid", pid)
Example #32
0
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPyQsciShell
    def __init__(self, parent=None, fname=None, wdir=None, commands=[],
                 interact=False, debug=False, path=[]):
        ExternalShellBase.__init__(self, parent, wdir,
                                   history_filename='.history_ec.py')
        
        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_check.setChecked(interact)
        self.debug_check.setChecked(debug)
        
        self.monitor_socket = None
        self.interpreter = fname is None
        self.fname = startup.__file__ if fname is None else fname
        
        if self.interpreter:
            self.interact_check.hide()
            self.debug_check.hide()
            self.terminate_button.hide()
        
        self.commands = ["import sys", "sys.path.insert(0, '')"] + commands
        
        # Additional python path list
        self.path = path
        
    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        self.globalsexplorer_button = create_toolbutton(self,
                          get_icon('dictedit.png'), self.tr("Variables"),
                          tip=self.tr("Show/hide global variables explorer"),
                          toggled=self.toggle_globals_explorer)
        self.terminate_button = create_toolbutton(self,
              get_icon('terminate.png'), self.tr("Terminate"),
              tip=self.tr("Attempts to terminate the process.\n"
                          "The process may not exit as a result of clicking "
                          "this button\n(it is given the chance to prompt "
                          "the user for any unsaved files, etc)."))        
        self.interact_check = QCheckBox(self.tr("Interact"), self)
        self.debug_check = QCheckBox(self.tr("Debug"), self)
        return [self.interact_check, self.debug_check,
                self.globalsexplorer_button, self.run_button,
                self.terminate_button, self.kill_button]
        
    def get_shell_widget(self):
        # Globals explorer
        self.globalsexplorer = GlobalsExplorer(self)
        self.connect(self.globalsexplorer, SIGNAL('collapse()'),
                     lambda: self.toggle_globals_explorer(False))
        
        # Shell splitter
        self.splitter = splitter = QSplitter(Qt.Vertical, self)
        self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                     self.splitter_moved)
        splitter.addWidget(self.shell)
        splitter.setCollapsible(0, False)
        splitter.addWidget(self.globalsexplorer)
        splitter.setStretchFactor(0, 2)
        splitter.setStretchFactor(1, 1)
        return splitter
    
    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_check.setEnabled(not state)
        self.debug_check.setEnabled(not state)
        self.terminate_button.setEnabled(state)
        if not state:
            self.toggle_globals_explorer(False)
        self.globalsexplorer_button.setEnabled(state)
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if self.interact_check.isChecked():
            p_args.append('-i')
        if self.debug_check.isChecked():
            p_args.extend(['-m', 'pdb'])
        p_args.append(self.fname)
        
        env = self.process.systemEnvironment()
        
        # Monitor
        env.append('SHELL_ID=%s' % id(self))
        from spyderlib.widgets.externalshell.monitor import start_server
        server, port = start_server()
        self.notification_thread = server.register(str(id(self)), self)
        self.connect(self.notification_thread, SIGNAL('refresh()'),
                     self.globalsexplorer.refresh_table)
        env.append('SPYDER_PORT=%d' % port)
        
        # Python init commands (interpreter only)
        if self.commands and self.interpreter:
            env.append('PYTHONINITCOMMANDS=%s' % ';'.join(self.commands))
            self.process.setEnvironment(env)
            
        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)
        
        # Adding Spyder path
        pathlist += self.path
        
        # Adding path list to PYTHONPATH environment variable
        pypath = "PYTHONPATH"
        pathstr = os.pathsep.join(pathlist)
        if os.environ.get(pypath) is not None:
            env.replaceInStrings(pypath+'=', pypath+'='+pathstr+os.pathsep,
                                 Qt.CaseSensitive)
        else:
            env.append(pypath+'='+pathstr)
        self.process.setEnvironment(env)
        #-------------------------Python specific-------------------------------
            
        if self.arguments:
            p_args.extend( self.arguments.split(' ') )
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        #-------------------------Python specific-------------------------------
        self.process.start(sys.executable, p_args)
        #-------------------------Python specific-------------------------------
            
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            
        return self.process
    
#===============================================================================
#    Input/Output
#===============================================================================
    def _write_error(self, text, findstr):
        pos = text.find(findstr)
        if pos != -1:
            self.shell.write(text[:pos])
            if text.endswith(">>> "):
                self.shell.write_error(text[pos:-5])
                self.shell.write(text[-5:], flush=True)
            else:
                self.shell.write_error(text[pos:])
            return True
        return False
    
    def write_output(self):
        text = self.get_stdout()
        if not self._write_error(text, 'Traceback (most recent call last):') \
           and not self._write_error(text, 'File "<stdin>", line 1'):
            self.shell.write(text)
        QApplication.processEvents()
        
    def send_to_process(self, qstr):
        if not isinstance(qstr, QString):
            qstr = QString(qstr)
        if not qstr.endsWith('\n'):
            qstr.append('\n')
        self.process.write(qstr.toLocal8Bit())
        self.process.waitForBytesWritten(-1)
        
    def keyboard_interrupt(self):
        communicate(self.monitor_socket, "thread.interrupt_main()")
            
#===============================================================================
#    Globals explorer
#===============================================================================
    def toggle_globals_explorer(self, state):
        self.splitter.setSizes([1, 1 if state else 0])
        self.globalsexplorer_button.setChecked(state)
        if state:
            self.globalsexplorer.refresh_table()
        
    def splitter_moved(self, pos, index):
        self.globalsexplorer_button.setChecked( self.splitter.sizes()[1] )
Example #33
0
class ExternalSystemShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = TerminalWidget
    def __init__(self, parent=None, wdir=None):
        ExternalShellBase.__init__(self, parent, wdir,
                                   history_filename='.history_ec')

    def get_icon(self):
        return get_icon('cmdprompt.png')
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)
            
        # Shell arguments
        if os.name == 'nt':
            p_args = ['/Q']
        else:
            p_args = ['-i']
            
        if self.arguments:
            p_args.extend( self.arguments.split(' ') )
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        if os.name == 'nt':
            self.process.start('cmd.exe', p_args)
        else:
            # Using bash:
            self.process.start('bash', p_args)
            self.send_to_process("""PS1="\u@\h:\w> "\n""")
            
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            
        return self.process
    
#===============================================================================
#    Input/Output
#===============================================================================
    def transcode(self, bytes):
        if os.name == 'nt':
            return encoding.transcode(str(bytes.data()), 'cp850')
        else:
            return ExternalShellBase.transcode(self, bytes)
    
    def send_to_process(self, qstr):
        if not isinstance(qstr, QString):
            qstr = QString(qstr)
        if qstr[:-1] in ["clear", "cls", "CLS"]:
            self.shell.clear()
            self.send_to_process(QString(os.linesep))
            return
        if not qstr.endsWith('\n'):
            qstr.append('\n')
        if os.name == 'nt':
            self.process.write(unicode(qstr).encode('cp850'))
        else:
            self.process.write(qstr.toLocal8Bit())
        self.process.waitForBytesWritten(-1)
        
    def keyboard_interrupt(self):
        # This does not work on Windows:
        # (unfortunately there is no easy way to send a Ctrl+C to cmd.exe)
        self.send_ctrl_to_process('c')

#        # The following code will soon be removed:
#        # (last attempt to send a Ctrl+C on Windows)
#        if os.name == 'nt':
#            pid = int(self.process.pid())
#            import ctypes, win32api, win32con
#            class _PROCESS_INFORMATION(ctypes.Structure):
#                _fields_ = [("hProcess", ctypes.c_int),
#                            ("hThread", ctypes.c_int),
#                            ("dwProcessID", ctypes.c_int),
#                            ("dwThreadID", ctypes.c_int)]
#            x = ctypes.cast( ctypes.c_void_p(pid),
#                             ctypes.POINTER(_PROCESS_INFORMATION) )
#            win32api.GenerateConsoleCtrlEvent(win32con.CTRL_C_EVENT,
#                                              x.dwProcessID)
#        else:
#            self.send_ctrl_to_process('c')
                
Example #34
0
class RunWidget(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        vbox = QVBoxLayout(self)
        vbox.setSpacing(0)
        vbox.setContentsMargins(0, 0, 0, 0)
        self.output = OutputWidget(self)
        hbox = QHBoxLayout()
        self.input = QLineEdit()
        self.lblInput = QLabel(self.tr("Input:"))
        vbox.addWidget(self.output)
        hbox.addWidget(self.lblInput)
        hbox.addWidget(self.input)
        vbox.addLayout(hbox)

        #process
        self._proc = QProcess(self)
        self.connect(self._proc, SIGNAL("readyReadStandardOutput()"),
            self.output._refresh_output)
        self.connect(self._proc, SIGNAL("readyReadStandardError()"),
            self.output._refresh_error)
        self.connect(self._proc, SIGNAL("finished(int, QProcess::ExitStatus)"),
            self.finish_execution)
        self.connect(self.input, SIGNAL("returnPressed()"), self.insert_input)

    def finish_execution(self, exitCode, exitStatus):
        self.lblInput.hide()
        self.input.hide()
        format = QTextCharFormat()
        format.setAnchor(True)
        self.output.textCursor().insertText('\n\n')
        if exitStatus == QProcess.NormalExit:
            format.setForeground(Qt.green)
            self.output.textCursor().insertText(
                self.tr("Execution Successful!"), format)
        else:
            format.setForeground(Qt.red)
            self.output.textCursor().insertText(
                self.tr("Execution Interrupted"), format)

    def insert_input(self):
        text = self.input.text() + '\n'
        self._proc.writeData(text)
        self.input.setText("")

    def start_process(self, fileName, pythonPath=False, programParams=''):
        self.lblInput.show()
        self.input.show()
        self.output.setCurrentCharFormat(self.output.plain_format)
        self.output.setPlainText('Running: %s (%s)\n\n' % (fileName,
            unicode(time.ctime())))
        self.output.moveCursor(QTextCursor.Down)
        self.output.moveCursor(QTextCursor.Down)
        self.output.moveCursor(QTextCursor.Down)

        #runner.run_code_from_file(fileName)
        if not pythonPath:
            pythonPath = settings.PYTHON_PATH
        #change the working directory to the fileName dir
        file_directory = file_manager.get_folder(fileName)
        self._proc.setWorkingDirectory(file_directory)
        #force python to unbuffer stdin and stdout
        options = ['-u'] + settings.EXECUTION_OPTIONS.split()
        self._proc.start(pythonPath, options + [fileName] + \
            [p.strip() for p in programParams.split(',') if p])

    def kill_process(self):
        self._proc.kill()
Example #35
0
class PyLint(Plugin, QObject):
    """ PyLint Plugin """
    capabilities = ['toolbarHook']
    __version__ = '0.5'
    thread = None

    def do_toolbarHook(self, widget):
        """ Hook to install the pylint toolbar button"""
        widget.addAction('PyLint', self.do_pylint)

    @pyqtSlot()
    def do_pylint(self):
        """ Launch the lint process and create the result window """
        print 'do_pylint'

        self.pylint_pross = QProcess()
        self.pylint_pross.setProcessChannelMode(QProcess.MergedChannels)
        self.pylint_pross.setWorkingDirectory( \
            os.path.dirname(str(self.parent.editor.filename)))
        self.pylint_pross.setReadChannel(QProcess.StandardOutput)

        self.connect(self.pylint_pross, \
            SIGNAL('finished(int)'), \
            self.finished)
        self.connect(self.pylint_pross, \
            SIGNAL('readyReadStandardOutput()'), \
            self.handle_stdout)
        self.connect(self.pylint_pross, \
            SIGNAL('readyReadStandardError()'), \
            self.handle_stderr)
        if (self.pylint_pross.start("pylint", \
                [self.parent.editor.filename,])):
            print 'Cannot start process'

        self.win = ResultWin()
        self.win.setWindowTitle("PyLint Results :" \
            + os.path.basename(str(self.parent.editor.filename)))
        self.win.show()
        if isMAEMO:
            self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, True)

        self.win.connect(self.win.list_view, \
            SIGNAL('doubleClicked(const QModelIndex&)'), \
            self.goto_line)

        self.pylint_pross.waitForStarted()

    def finished(self, _):
        """ Call back called when lint end """
        if isMAEMO:
            self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, False)

    def handle_stdout(self):
        """
        Private slot to handle the readyReadStdout
        signal of the pylint process.
        """
        result_list = []
        #regex = QRegExp('(\w)\S*:\S*(\d*):.*: (.*)')
        regex = QRegExp('(\w)\s*:\s*(\d*):(.*)')
        regex_score = \
            QRegExp('.*at.(\d.\d*)/10.*')
        while self.pylint_pross and self.pylint_pross.canReadLine():
            result = unicode(self.pylint_pross.readLine())
            if result != None:
                pos = 0
                while True:
                    pos = regex.indexIn(result, pos)
                    if pos < 0:
                        if regex_score.indexIn(result, 0) >= 0:
                            self.win.setWindowTitle( \
                                "PyLint Results :" \
                                + str(regex_score.cap(1)) \
                                + ':'
                                + os.path.basename(str(self.parent.editor.filename)))
                        break
                    result_list.append(
                        (regex.cap(1), regex.cap(2), regex.cap(3)))
                    #print 'Append : ',(regex.cap(1), regex.cap(2), regex.cap(3))
                    pos = pos + regex.matchedLength()

        if len(result_list) > 0:
            self.win.append_results(result_list)

    def goto_line(self, index):
        """ Callback called when a lint result is double clicked """
        line = int(self.win.list_model.items[index.row()][1])
        self.parent.do_gotoLine(line)

    def handle_stderr(self):
        """
        Private slot to handle the readyReadStderr
        signal of the pylint process. Currently not
        managed
        """
        print 'error stderr'
Example #36
0
class RunWidget(QWidget):

    """Widget that show the execution output in the MiscContainer."""

    def __init__(self):
        QWidget.__init__(self)
        vbox = QVBoxLayout(self)
        vbox.setSpacing(0)
        vbox.setContentsMargins(0, 0, 0, 0)
        self.output = OutputWidget(self)
        hbox = QHBoxLayout()
        self.input = QLineEdit()
        self.lblInput = QLabel(self.tr("Input:"))
        vbox.addWidget(self.output)
        hbox.addWidget(self.lblInput)
        hbox.addWidget(self.input)
        vbox.addLayout(hbox)

        #process
        self.currentProcess = None
        self.__preScriptExecuted = False
        self._proc = QProcess(self)
        self._preExecScriptProc = QProcess(self)
        self._postExecScriptProc = QProcess(self)
        self.connect(self._proc, SIGNAL("readyReadStandardOutput()"),
            self.output._refresh_output)
        self.connect(self._proc, SIGNAL("readyReadStandardError()"),
            self.output._refresh_error)
        self.connect(self._proc, SIGNAL("finished(int, QProcess::ExitStatus)"),
            self.finish_execution)
        self.connect(self._proc, SIGNAL("error(QProcess::ProcessError)"),
            self.process_error)
        self.connect(self.input, SIGNAL("returnPressed()"), self.insert_input)
        self.connect(self._preExecScriptProc,
            SIGNAL("finished(int, QProcess::ExitStatus)"),
            self.__main_execution)
        self.connect(self._preExecScriptProc,
            SIGNAL("readyReadStandardOutput()"), self.output._refresh_output)
        self.connect(self._preExecScriptProc,
            SIGNAL("readyReadStandardError()"), self.output._refresh_error)
        self.connect(self._postExecScriptProc,
            SIGNAL("finished(int, QProcess::ExitStatus)"),
            self.__post_execution_message)
        self.connect(self._postExecScriptProc,
            SIGNAL("readyReadStandardOutput()"), self.output._refresh_output)
        self.connect(self._postExecScriptProc,
            SIGNAL("readyReadStandardError()"), self.output._refresh_error)

    def process_error(self, error):
        """Listen to the error signals from the running process."""
        self.lblInput.hide()
        self.input.hide()
        self._proc.kill()
        format_ = QTextCharFormat()
        format_.setAnchor(True)
        format_.setForeground(Qt.red)
        if error == 0:
            self.output.textCursor().insertText(self.tr('Failed to start'),
                format_)
        else:
            self.output.textCursor().insertText(
                self.tr('Error during execution, QProcess error: %d' % error),
                format_)

    def finish_execution(self, exitCode, exitStatus):
        """Print a message and hide the input line when the execution ends."""
        self.lblInput.hide()
        self.input.hide()
        format_ = QTextCharFormat()
        format_.setAnchor(True)
        self.output.textCursor().insertText('\n\n')
        if exitStatus == QProcess.NormalExit:
            format_.setForeground(Qt.green)
            self.output.textCursor().insertText(
                self.tr("Execution Successful!"), format_)
        else:
            format_.setForeground(Qt.red)
            self.output.textCursor().insertText(
                self.tr("Execution Interrupted"), format_)
        self.output.textCursor().insertText('\n\n')
        self.__post_execution()

    def insert_input(self):
        """Take the user input and send it to the process."""
        text = self.input.text() + '\n'
        self._proc.writeData(text)
        self.output.textCursor().insertText(text, self.output.plain_format)
        self.input.setText("")

    def start_process(self, fileName, pythonPath=False, PYTHONPATH=None,
        programParams='', preExec='', postExec=''):

        """Prepare the output widget and start the process."""
        self.lblInput.show()
        self.input.show()
        self.fileName = fileName
        self.pythonPath = pythonPath  # FIXME, this is python interpreter
        self.programParams = programParams
        self.preExec = preExec
        self.postExec = postExec
        self.PYTHONPATH = PYTHONPATH

        self.__pre_execution()

    def __main_execution(self):
        """Execute the project."""
        self.output.setCurrentCharFormat(self.output.plain_format)
        message = ''
        if self.__preScriptExecuted:
            self.__preScriptExecuted = False
            message = self.tr(
                "Pre Execution Script Successfully executed.\n\n")
        self.output.setPlainText(message + 'Running: %s (%s)\n\n' %
            (self.fileName, time.ctime()))
        self.output.moveCursor(QTextCursor.Down)
        self.output.moveCursor(QTextCursor.Down)
        self.output.moveCursor(QTextCursor.Down)

        #runner.run_code_from_file(fileName)
        if not self.pythonPath:
            self.pythonPath = settings.PYTHON_PATH
        #change the working directory to the fileName dir
        file_directory = file_manager.get_folder(self.fileName)
        self._proc.setWorkingDirectory(file_directory)
        #force python to unbuffer stdin and stdout
        options = ['-u'] + settings.EXECUTION_OPTIONS.split()
        self.currentProcess = self._proc

        if self.PYTHONPATH:
            envpaths = [path for path in self.PYTHONPATH.splitlines()]
            env = QProcessEnvironment()
            system_environemnt = self._proc.systemEnvironment()
            for e in system_environemnt:
                key, value = e.split('=', 1)
                env.insert(key, value)
            for path in envpaths:
                env.insert('PYTHONPATH', path)
            self._proc.setProcessEnvironment(env)

        self._proc.start(self.pythonPath, options + [self.fileName] +
            [p.strip() for p in self.programParams.split(',') if p])

    def __pre_execution(self):
        """Execute a script before executing the project."""
        filePreExec = QFile(self.preExec)
        if filePreExec.exists() and \
          bool(QFile.ExeUser & filePreExec.permissions()):
            ext = file_manager.get_file_extension(self.preExec)
            if not self.pythonPath:
                self.pythonPath = settings.PYTHON_PATH
            self.currentProcess = self._preExecScriptProc
            self.__preScriptExecuted = True
            if ext == 'py':
                self._preExecScriptProc.start(self.pythonPath, [self.preExec])
            else:
                self._preExecScriptProc.start(self.preExec)
        else:
            self.__main_execution()

    def __post_execution(self):
        """Execute a script after executing the project."""
        filePostExec = QFile(self.postExec)
        if filePostExec.exists() and \
          bool(QFile.ExeUser & filePostExec.permissions()):
            ext = file_manager.get_file_extension(self.postExec)
            if not self.pythonPath:
                self.pythonPath = settings.PYTHON_PATH
            self.currentProcess = self._postExecScriptProc
            if ext == 'py':
                self._postExecScriptProc.start(self.pythonPath,
                    [self.postExec])
            else:
                self._postExecScriptProc.start(self.postExec)

    def __post_execution_message(self):
        """Print post execution message."""
        self.output.textCursor().insertText('\n\n')
        format_ = QTextCharFormat()
        format_.setAnchor(True)
        format_.setForeground(Qt.green)
        self.output.textCursor().insertText(
            self.tr("Post Execution Script Successfully executed."), format_)

    def kill_process(self):
        """Kill the running process."""
        self._proc.kill()
Example #37
0
class ExternalSystemShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = TerminalWidget

    def __init__(self,
                 parent=None,
                 wdir=None,
                 path=[],
                 light_background=True,
                 menu_actions=None,
                 show_buttons_inside=True,
                 show_elapsed_time=True):
        ExternalShellBase.__init__(self,
                                   parent=parent,
                                   fname=None,
                                   wdir=wdir,
                                   history_filename='.history',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)

        # Additional python path list
        self.path = path

        # For compatibility with the other shells that can live in the external
        # console
        self.is_ipykernel = False
        self.connection_file = None

    def get_icon(self):
        return get_icon('cmdprompt.png')

    def create_process(self):
        self.shell.clear()

        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)

        # PYTHONPATH (in case we use Python in this terminal, e.g. py2exe)
        env = [unicode(_path) for _path in self.process.systemEnvironment()]
        add_pathlist_to_PYTHONPATH(env, self.path)
        self.process.setEnvironment(env)

        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        # Shell arguments
        if os.name == 'nt':
            p_args = ['/Q']
        else:
            p_args = ['-i']

        if self.arguments:
            p_args.extend(shell_split(self.arguments))

        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process,
                     SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self.kill_button, SIGNAL("clicked()"), self.process.kill)

        if os.name == 'nt':
            self.process.start('cmd.exe', p_args)
        else:
            # Using bash:
            self.process.start('bash', p_args)
            self.send_to_process("""PS1="\u@\h:\w> "\n""")

        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, _("Error"),
                                 _("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))

        return self.process

#===============================================================================
#    Input/Output
#===============================================================================

    def transcode(self, bytes):
        if os.name == 'nt':
            return encoding.transcode(str(bytes.data()), 'cp850')
        else:
            return ExternalShellBase.transcode(self, bytes)

    def send_to_process(self, text):
        if not isinstance(text, basestring):
            text = unicode(text)
        if text[:-1] in ["clear", "cls", "CLS"]:
            self.shell.clear()
            self.send_to_process(os.linesep)
            return
        if not text.endswith('\n'):
            text += '\n'
        if os.name == 'nt':
            self.process.write(text.encode('cp850'))
        else:
            self.process.write(locale_codec.fromUnicode(text))
        self.process.waitForBytesWritten(-1)

    def keyboard_interrupt(self):
        # This does not work on Windows:
        # (unfortunately there is no easy way to send a Ctrl+C to cmd.exe)
        self.send_ctrl_to_process('c')
Example #38
0
class RunWidget(QWidget):

    """Widget that show the execution output in the MiscContainer."""

    def __init__(self):
        QWidget.__init__(self)
        vbox = QVBoxLayout(self)
        vbox.setSpacing(0)
        vbox.setContentsMargins(0, 0, 0, 0)
        self.output = OutputWidget(self)
        hbox = QHBoxLayout()
        self.input = QLineEdit()
        self.lblInput = QLabel(self.tr("Input:"))
        vbox.addWidget(self.output)
        hbox.addWidget(self.lblInput)
        hbox.addWidget(self.input)
        vbox.addLayout(hbox)

        #process
        self.currentProcess = None
        self.__preScriptExecuted = False
        self._proc = QProcess(self)
        self._preExecScriptProc = QProcess(self)
        self._postExecScriptProc = QProcess(self)
        self.connect(self._proc, SIGNAL("readyReadStandardOutput()"),
            self.output._refresh_output)
        self.connect(self._proc, SIGNAL("readyReadStandardError()"),
            self.output._refresh_error)
        self.connect(self._proc, SIGNAL("finished(int, QProcess::ExitStatus)"),
            self.finish_execution)
        self.connect(self._proc, SIGNAL("error(QProcess::ProcessError)"),
            self.process_error)
        self.connect(self.input, SIGNAL("returnPressed()"), self.insert_input)
        self.connect(self._preExecScriptProc,
            SIGNAL("finished(int, QProcess::ExitStatus)"),
            self.__main_execution)
        self.connect(self._preExecScriptProc,
            SIGNAL("readyReadStandardOutput()"), self.output._refresh_output)
        self.connect(self._preExecScriptProc,
            SIGNAL("readyReadStandardError()"), self.output._refresh_error)
        self.connect(self._postExecScriptProc,
            SIGNAL("finished(int, QProcess::ExitStatus)"),
            self.__post_execution_message)
        self.connect(self._postExecScriptProc,
            SIGNAL("readyReadStandardOutput()"), self.output._refresh_output)
        self.connect(self._postExecScriptProc,
            SIGNAL("readyReadStandardError()"), self.output._refresh_error)

    def process_error(self, error):
        """Listen to the error signals from the running process."""
        self.lblInput.hide()
        self.input.hide()
        self._proc.kill()
        format_ = QTextCharFormat()
        format_.setAnchor(True)
        format_.setForeground(Qt.red)
        if error == 0:
            self.output.textCursor().insertText(self.tr('Failed to start'),
                format_)
        else:
            self.output.textCursor().insertText(
                self.tr('Error during execution, QProcess error: %d' % error),
                format_)

    def finish_execution(self, exitCode, exitStatus):
        """Print a message and hide the input line when the execution ends."""
        self.lblInput.hide()
        self.input.hide()
        format_ = QTextCharFormat()
        format_.setAnchor(True)
        self.output.textCursor().insertText('\n\n')
        if exitStatus == QProcess.NormalExit:
            format_.setForeground(Qt.green)
            self.output.textCursor().insertText(
                self.tr("Execution Successful!"), format_)
        else:
            format_.setForeground(Qt.red)
            self.output.textCursor().insertText(
                self.tr("Execution Interrupted"), format_)
        self.output.textCursor().insertText('\n\n')
        self.__post_execution()

    def insert_input(self):
        """Take the user input and send it to the process."""
        text = self.input.text() + '\n'
        self._proc.writeData(text)
        self.output.textCursor().insertText(text, self.output.plain_format)
        self.input.setText("")

    def start_process(self, fileName, pythonPath=False, PYTHONPATH=None,
        programParams='', preExec='', postExec=''):

        """Prepare the output widget and start the process."""
        self.lblInput.show()
        self.input.show()
        self.fileName = fileName
        self.pythonPath = pythonPath  # FIXME, this is python interpreter
        self.programParams = programParams
        self.preExec = preExec
        self.postExec = postExec
        self.PYTHONPATH = PYTHONPATH

        self.__pre_execution()

    def __main_execution(self):
        """Execute the project."""
        self.output.setCurrentCharFormat(self.output.plain_format)
        message = ''
        if self.__preScriptExecuted:
            self.__preScriptExecuted = False
            message = self.tr(
                "Pre Execution Script Successfully executed.\n\n")
        self.output.setPlainText(message + 'Running: %s (%s)\n\n' %
            (self.fileName, unicode(time.ctime())))
        self.output.moveCursor(QTextCursor.Down)
        self.output.moveCursor(QTextCursor.Down)
        self.output.moveCursor(QTextCursor.Down)

        #runner.run_code_from_file(fileName)
        if not self.pythonPath:
            self.pythonPath = settings.PYTHON_PATH
        #change the working directory to the fileName dir
        file_directory = file_manager.get_folder(self.fileName)
        self._proc.setWorkingDirectory(file_directory)
        #force python to unbuffer stdin and stdout
        options = ['-u'] + settings.EXECUTION_OPTIONS.split()
        self.currentProcess = self._proc

        if self.PYTHONPATH:
            envpaths = [path for path in self.PYTHONPATH.splitlines()]
            env = QProcessEnvironment()
            system_environemnt = self._proc.systemEnvironment()
            for e in system_environemnt:
                key, value = unicode(e).split('=', 1)
                env.insert(key, value)
            for path in envpaths:
                env.insert('PYTHONPATH', path)
            self._proc.setProcessEnvironment(env)

        self._proc.start(self.pythonPath, options + [self.fileName] +
            [p.strip() for p in self.programParams.split(',') if p])

    def __pre_execution(self):
        """Execute a script before executing the project."""
        filePreExec = QFile(self.preExec)
        if filePreExec.exists() and \
          bool(QFile.ExeUser & filePreExec.permissions()):
            ext = file_manager.get_file_extension(self.preExec)
            if not self.pythonPath:
                self.pythonPath = settings.PYTHON_PATH
            self.currentProcess = self._preExecScriptProc
            self.__preScriptExecuted = True
            if ext == 'py':
                self._preExecScriptProc.start(self.pythonPath, [self.preExec])
            else:
                self._preExecScriptProc.start(self.preExec)
        else:
            self.__main_execution()

    def __post_execution(self):
        """Execute a script after executing the project."""
        filePostExec = QFile(self.postExec)
        if filePostExec.exists() and \
          bool(QFile.ExeUser & filePostExec.permissions()):
            ext = file_manager.get_file_extension(self.postExec)
            if not self.pythonPath:
                self.pythonPath = settings.PYTHON_PATH
            self.currentProcess = self._postExecScriptProc
            if ext == 'py':
                self._postExecScriptProc.start(self.pythonPath,
                    [self.postExec])
            else:
                self._postExecScriptProc.start(self.postExec)

    def __post_execution_message(self):
        """Print post execution message."""
        self.output.textCursor().insertText('\n\n')
        format_ = QTextCharFormat()
        format_.setAnchor(True)
        format_.setForeground(Qt.green)
        self.output.textCursor().insertText(
            self.tr("Post Execution Script Successfully executed."), format_)

    def kill_process(self):
        """Kill the running process."""
        self._proc.kill()
Example #39
0
class EjecutarWidget(QWidget):
    def __init__(self):
        super(EjecutarWidget, self).__init__()
        layoutV = QVBoxLayout(self)
        layoutV.setContentsMargins(0, 0, 0, 0)
        layoutV.setSpacing(0)
        self.output = output_compiler.SalidaCompilador(self)
        layoutV.addWidget(self.output)
        self.setLayout(layoutV)

        # Flag
        self._compilation_failed = False

        # Procesos
        self.build_process = QProcess(self)
        if not sys.platform.startswith('linux'):
            self._envgcc = QProcessEnvironment.systemEnvironment()
            self._envgcc.insert("PATH", ENV_GCC)
            self.build_process.setProcessEnvironment(self._envgcc)
        self.execution_process = QProcess(self)

        # Conexiones
        self.build_process.readyReadStandardError.connect(
            self.output.stderr_output)
        self.build_process.finished[int, QProcess.ExitStatus].connect(
            self._compilation_finished)
        self.build_process.error[QProcess.ProcessError].connect(
            self._compilation_error)
        self.execution_process.finished[int, QProcess.ExitStatus].connect(
            self._execution_finished)

    def _execution_finished(self, code, status):
        if status == QProcess.CrashExit:
            text = output_compiler.Item(
                self.tr("La ejecución se ha interrumpido"))
            text.setForeground(Qt.red)
            self.output.addItem(text)
        else:
            text = output_compiler.Item(self.tr("Ejecución Exitosa!"))
            text.setForeground(QColor("#7FE22A"))
            self.output.addItem(text)

    def run_compilation(self, sources):
        """ Se corre el comando gcc para la compilación """

        # Ejecutable
        filename, files = sources
        if not files:
            # No es un proyecto
            files = [filename]
        path = QDir.fromNativeSeparators(filename)
        self.exe = os.path.splitext(os.path.basename(path))[0]

        # Generar el ejecutable en el directorio del código fuente
        exe_path = os.path.dirname(path)
        self.build_process.setWorkingDirectory(exe_path)

        # Se limpia el QListWidget
        self.output.clear()

        flags = settings.COMPILER_FLAGS.split()
        params = ['-o', self.exe] + flags
        gcc = 'gcc'
        if not sys.platform.startswith("linux"):
            gcc = os.path.join(self._environment, 'gcc')

        item = output_compiler.Item(
            self.tr(">>> Compilando: {0} ( en directorio {1} )").format(
                path.split('/')[-1], exe_path))
        self.output.addItem(item)
        self.output.addItem(
            output_compiler.Item(
                self.tr(">>> Comando: {0}").format(gcc + ' ' +
                                                   ' '.join(params) + ' ' +
                                                   ' '.join(files))))

        # Se inicia el proceso
        self.build_process.start(gcc, params + files)
        self.build_process.waitForFinished()

    def _compilation_finished(self, code, status):
        """
        Cuando la compilación termina @codigoError toma dos valores:
            0 = La compilación ha terminado de forma correcta
            1 = La compilación ha fallado

        """

        if status == QProcess.NormalExit and code == 0:
            self._compilation_failed = False
            item_ok = output_compiler.Item(
                self.tr("¡LA COMPILACIÓN HA SIDO EXITOSA!"))
            self.output.addItem(item_ok)
            item_ok.setForeground(QColor("#7FE22A"))
        else:
            self._compilation_failed = True
            item_error = output_compiler.Item(
                self.tr("¡LA COMPILACIÓN HA FALLADO!"))
            item_error.setForeground(QColor("#E20000"))
            self.output.addItem(item_error)
        syntax_ok = True if code == 0 else False
        self.emit(SIGNAL("updateSyntaxCheck(bool)"), syntax_ok)
        code_status = output_compiler.Item(
            self.tr("Proceso terminado con código: {0}").format(code),
            italic=True)
        self.output.addItem(code_status)
        count = self.output.count()
        self.output.setCurrentRow(count - 1, QItemSelectionModel.NoUpdate)

    def _compilation_error(self, error):
        """
        Éste método se ejecuta cuando el inicio del proceso de compilación
        falla. Una de las causas puede ser la ausencia del compilador.

        """

        text = output_compiler.Item(
            self.tr("Se ha producido un error. Compilador no encontrado."))
        text.setForeground(Qt.red)
        self.output.addItem(text)

    def run_program(self, sources):
        """ Ejecuta el binario generado por el compilador """

        path = os.path.dirname(sources[0])
        self.execution_process.setWorkingDirectory(path)
        # Path ejecutable
        path_exe = os.path.join(path, self.exe)
        if not settings.IS_LINUX:
            path_exe += '.exe'
        # Si no existe se termina el proceso
        if not self._check_file_exists(path_exe):
            text = output_compiler.Item(
                self.tr("El archivo no existe: {0}").format(path_exe))
            text.setForeground(Qt.red)
            self.output.addItem(text)
            return
        # Texto en la salida
        text = output_compiler.Item(
            self.tr("Ejecutando... {0}").format(path_exe))
        self.output.addItem(text)

        if settings.IS_LINUX:
            # Run !
            terminal = settings.get_setting('terminal')
            arguments = [
                os.path.join(paths.PATH, "tools",
                             "run_script.sh %s" % path_exe)
            ]
            self.execution_process.start(terminal, ['-e'] + arguments)
        else:
            pauser = os.path.join(paths.PATH, "tools", "pauser",
                                  "system_pause.exe")
            process = [pauser] + ["\"%s\"" % path_exe]
            Popen(process, creationflags=CREATE_NEW_CONSOLE)

    def _check_file_exists(self, exe):
        """ Comprueba si el ejecutable existe """

        exists = True
        if not os.path.exists(exe):
            exists = False
        return exists

    @property
    def _environment(self):
        """ Devuelve la variable de entorno gcc """

        return self._envgcc.value("PATH", "")

    def build_and_run(self, archivo):
        self.run_compilation(archivo)
        if not self._compilation_failed:
            self.run_program(archivo)

    def clean(self, exe):
        """ Elimina el binario generado por la compilación """

        if exe is None:
            return
        binary = exe.split('.')[0]
        if not settings.IS_LINUX:
            binary += '.exe'
        os.remove(binary)

    def kill_process(self):
        """ Termina el proceso """

        self.execution_process.kill()
Example #40
0
	def newProject(path):
		initProcess=QProcess(None)
		initProcess.setWorkingDirectory(path)
		initProcess.start("ino",['init'])
		initProcess.waitForFinished()
		return initProcess.exitCode()==0
 def _performMonitor(self):
     """
     Protected method implementing the monitoring action.
     
     This method populates the statusList member variable
     with a list of strings giving the status in the first column and the
     path relative to the project directory starting with the third column.
     The allowed status flags are:
     <ul>
         <li>"A" path was added but not yet comitted</li>
         <li>"M" path has local changes</li>
         <li>"O" path was removed</li>
         <li>"R" path was deleted and then re-added</li>
         <li>"U" path needs an update</li>
         <li>"Z" path contains a conflict</li>
         <li>" " path is back at normal</li>
     </ul>
     
     @return tuple of flag indicating successful operation (boolean) and 
         a status message in case of non successful operation (QString)
     """
     self.shouldUpdate = False
     
     process = QProcess()
     args = QStringList()
     args.append('status')
     if not Preferences.getVCS("MonitorLocalStatus"):
         args.append('--show-updates')
     args.append('--non-interactive')
     args.append('.')
     process.setWorkingDirectory(self.projectDir)
     process.start('svn', args)
     procStarted = process.waitForStarted()
     if procStarted:
         finished = process.waitForFinished(300000)
         if finished and process.exitCode() == 0:
             output = \
                 unicode(process.readAllStandardOutput(), self.__ioEncoding, 'replace')
             states = {}
             for line in output.splitlines():
                 if self.rx_status1.exactMatch(line):
                     flags = str(self.rx_status1.cap(1))
                     path = self.rx_status1.cap(3).trimmed()
                 elif self.rx_status2.exactMatch(line):
                     flags = str(self.rx_status2.cap(1))
                     path = self.rx_status2.cap(5).trimmed()
                 else:
                     continue
                 if flags[0] in "ACDMR" or \
                    (flags[0] == " " and flags[-1] == "*"):
                     if flags[-1] == "*":
                         status = "U"
                     else:
                         status = flags[0]
                     if status == "C":
                         status = "Z"    # give it highest priority
                     elif status == "D":
                         status = "O"
                     if status == "U":
                         self.shouldUpdate = True
                     name = unicode(path)
                     states[name] = status
                     try:
                         if self.reportedStates[name] != status:
                             self.statusList.append("%s %s" % (status, name))
                     except KeyError:
                         self.statusList.append("%s %s" % (status, name))
             for name in self.reportedStates.keys():
                 if name not in states:
                     self.statusList.append("  %s" % name)
             self.reportedStates = states
             return True, \
                    self.trUtf8("Subversion status checked successfully (using svn)")
         else:
             process.kill()
             process.waitForFinished()
             return False, QString(process.readAllStandardError())
     else:
         process.kill()
         process.waitForFinished()
         return False, self.trUtf8("Could not start the Subversion process.")