Пример #1
0
    def _read_commands(self):
        "works in separate thread"

        while True:
            line = sys.stdin.readline()
            if line == "":
                logger.info("Read stdin EOF")
                sys.exit()
            cmd = parse_message(line)
            self._command_queue.put(cmd)
Пример #2
0
        def publish_as_msg(data):
            msg = parse_message(data)
            if "cwd" in msg:
                self.cwd = msg["cwd"]
            message_queue.append(msg)

            while len(message_queue) > 100:
                # Probably backend runs an infinite/long print loop.
                # Throttle message thougput in order to keep GUI thread responsive.
                sleep(0.1)
Пример #3
0
 def _read_one_incoming_message(self):
     line = self._read_incoming_msg_line()
     if line == "":
         return False
     msg = parse_message(line)
     if isinstance(msg, ImmediateCommand):
         # This will be handled right away
         self._handle_immediate_command(msg)
     else:
         self._incoming_message_queue.put(msg)
     return True
Пример #4
0
 def _read_incoming_messages(self):
     # works in a separate thread
     while self._should_keep_going():
         line = self._read_incoming_msg_line()
         if line == "":
             break
         msg = parse_message(line)
         if isinstance(msg, ImmediateCommand):
             # This will be handled right away
             self._handle_immediate_command(msg)
         else:
             self._incoming_message_queue.put(msg)
Пример #5
0
    def _read_commands(self):
        "works in separate thread"

        while True:
            line = sys.stdin.readline()
            if line == "":
                logger.info("Read stdin EOF")
                sys.exit()
            cmd = parse_message(line)
            if isinstance(cmd, InterruptCommand):
                # This is a priority command and will be handled right away
                self._interrupt_in_command_reading_thread()
            else:
                self._command_queue.put(cmd)
Пример #6
0
 def _listen_stdout(self):
     #debug("... started listening to stdout")
     # will be called from separate thread
     while True:
         data = self._proc.stdout.readline()
         #debug("... read some stdout data", repr(data))
         if data == '':
             break
         else:
             msg = parse_message(data)
             if "cwd" in msg:
                 self.cwd = msg["cwd"]
                 
             with self._state_lock:
                 self._message_queue.append(msg)
Пример #7
0
 def _listen_stdout(self):
     #debug("... started listening to stdout")
     # will be called from separate thread
     while True:
         data = self._proc.stdout.readline().decode(COMMUNICATION_ENCODING)
         #debug("... read some stdout data", repr(data))
         if data == '':
             break
         else:
             #print("MSG", data)
             msg = parse_message(data)
             if hasattr(msg, "cwd"):
                 self.cwd = msg.cwd
             with self._state_lock:
                 self._message_queue.append(msg)
                 if isinstance(msg, PauseMessage):
                     self._current_pause_msg = msg
Пример #8
0
    def _listen_stdout(self):
        #debug("... started listening to stdout")
        # will be called from separate thread
        while True:
            data = self._proc.stdout.readline()
            #debug("... read some stdout data", repr(data))
            if data == '':
                break
            else:
                msg = parse_message(data)
                if "cwd" in msg:
                    self.cwd = msg["cwd"]

                # TODO: it was "with self._state_lock:". Is it necessary?
                self._message_queue.append(msg)

                if len(self._message_queue) > 100:
                    # Probably backend runs an infinite/long print loop.
                    # Throttle message thougput in order to keep GUI thread responsive.
                    sleep(0.1)
Пример #9
0
    def _start_new_process(self, cmd=None):
        # deque, because in one occasion I need to put messages back
        self._message_queue = collections.deque()

        # prepare environment
        my_env = get_environment_for_python_subprocess(self._executable)
        # variables controlling communication with the back-end process
        my_env["PYTHONIOENCODING"] = "utf-8"

        # Let back-end know about plug-ins
        my_env["THONNY_USER_DIR"] = THONNY_USER_DIR

        if get_workbench().in_debug_mode():
            my_env["THONNY_DEBUG"] = "1"
        elif "THONNY_DEBUG" in my_env:
            del my_env["THONNY_DEBUG"]

        if not os.path.exists(self._executable):
            raise UserError(
                "Interpreter (%s) not found. Please recheck corresponding option!"
                % self._executable)

        import thonny.backend_launcher

        cmd_line = [
            self._executable,
            "-u",  # unbuffered IO
            "-B",  # don't write pyo/pyc files
            # (to avoid problems when using different Python versions without write permissions)
            thonny.backend_launcher.__file__,
        ]

        if hasattr(cmd, "filename"):
            cmd_line.append(cmd.filename)
            if hasattr(cmd, "args"):
                cmd_line.extend(cmd.args)

        if hasattr(cmd, "environment"):
            my_env.update(cmd.environment)

        creationflags = 0
        if running_on_windows():
            creationflags = subprocess.CREATE_NEW_PROCESS_GROUP

        debug("Starting the backend: %s %s", cmd_line,
              get_workbench().get_local_cwd())
        self._proc = subprocess.Popen(
            cmd_line,
            # bufsize=0,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            cwd=get_workbench().get_local_cwd(),
            env=my_env,
            universal_newlines=True,
            creationflags=creationflags,
        )

        # send init message
        self._send_msg({"frontend_sys_path": sys.path})

        if cmd:
            # Consume the ready message, cmd will get its own result message
            ready_line = self._proc.stdout.readline()
            if ready_line == "":  # There was some problem
                error_msg = self._proc.stderr.read()
                raise Exception("Error starting backend process: " + error_msg)
            self._store_state_info(parse_message(ready_line))

        # setup asynchronous output listeners
        Thread(target=self._listen_stdout, daemon=True).start()
        Thread(target=self._listen_stderr, daemon=True).start()
Пример #10
0
 def _fetch_command(self):
     line = self._original_stdin.readline()
     if line == "":
         sys.exit()
     cmd = parse_message(line)
     return cmd
Пример #11
0
    def _start_new_process(self, cmd):
        self._message_queue = collections.deque()
    
        # create new backend process
        my_env = {}
        for name in os.environ:
            if ("python" not in name.lower() # skip python vars, because we may use different Python version
                and name not in ["TK_LIBRARY", "TCL_LIBRARY"]): # They tend to point to frontend Python installation 
                my_env[name] = os.environ[name]
        
        # TODO: take care of SSL_CERT_FILE
        # Unset when we're in builtin python and target python is external
                
        my_env["PYTHONIOENCODING"] = "ASCII" 
        my_env["PYTHONUNBUFFERED"] = "1" 
        
        if not os.path.exists(self._executable):
            raise UserError("Interpreter (%s) not found. Please recheck corresponding option!"
                            % self._executable)
        
        
        if is_private_interpreter(self._executable):
            # in gui environment make "pip install"
            # use a folder outside thonny installation
            # in order to keep packages after reinstalling Thonny 
            my_env["PIP_USER"] = "******"
            my_env["PYTHONUSERBASE"] = THONNY_USER_DIR
        
        backend_launcher = os.path.join(get_workbench().get_package_dir(), 
                                        "backend_private",
                                        "thonny_backend.py") 
        
        if not os.path.exists(backend_launcher):
            # in dev machine use the main source
            backend_launcher = os.path.realpath(
                os.path.join(get_workbench().get_package_dir(), 
                             "..",
                             "thonny_backend.py")
            ) 
             
        
        cmd_line = [
            self._executable, 
            '-u', # unbuffered IO (neccessary in Python 3.1)
            '-B', # don't write pyo/pyc files 
                  # (to avoid problems when using different Python versions without write permissions)
            backend_launcher
        ]
        

        if hasattr(cmd, "filename"):
            cmd_line.append(cmd.filename)
            if hasattr(cmd, "args"):
                cmd_line.extend(cmd.args)
        
        if hasattr(cmd, "environment"):
            my_env.update(cmd.environment)            
        
        debug("Starting the backend: %s %s", cmd_line, self.cwd)
        self._proc = subprocess.Popen (
            cmd_line,
            #bufsize=0,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            cwd=self.cwd,
            env=my_env,
            universal_newlines=True
        )
        
        ready_line = self._proc.stdout.readline()
        if ready_line == "": # There was some problem
            error_msg = self._proc.stderr.read()
            raise Exception("Error starting backend process: " + error_msg)
        
        ready_msg = parse_message(ready_line)
        debug("Backend ready: %s", ready_msg)
        get_workbench().event_generate("BackendReady", **ready_msg)
        
        # setup asynchronous output listeners
        start_new_thread(self._listen_stdout, ())
        start_new_thread(self._listen_stderr, ())