| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import cPickle as pickle
- import marshal
- import os
- import socket
- import subprocess
- import sys
- import tempfile
- import threading
- class PythonFileRunner(object):
- """A class for running python project files"""
- def __init__(self, pycore, file_, args=None, stdin=None,
- stdout=None, analyze_data=None):
- self.pycore = pycore
- self.file = file_
- self.analyze_data = analyze_data
- self.observers = []
- self.args = args
- self.stdin = stdin
- self.stdout = stdout
- def run(self):
- """Execute the process"""
- env = dict(os.environ)
- file_path = self.file.real_path
- path_folders = self.pycore.get_source_folders() + \
- self.pycore.get_python_path_folders()
- env['PYTHONPATH'] = os.pathsep.join(folder.real_path
- for folder in path_folders)
- runmod_path = self.pycore.find_module('rope.base.oi.runmod').real_path
- self.receiver = None
- self._init_data_receiving()
- send_info = '-'
- if self.receiver:
- send_info = self.receiver.get_send_info()
- args = [sys.executable, runmod_path, send_info,
- self.pycore.project.address, self.file.real_path]
- if self.analyze_data is None:
- del args[1:4]
- if self.args is not None:
- args.extend(self.args)
- self.process = subprocess.Popen(
- executable=sys.executable, args=args, env=env,
- cwd=os.path.split(file_path)[0], stdin=self.stdin,
- stdout=self.stdout, stderr=self.stdout, close_fds=os.name != 'nt')
- def _init_data_receiving(self):
- if self.analyze_data is None:
- return
- # Disabling FIFO data transfer due to blocking when running
- # unittests in the GUI.
- # XXX: Handle FIFO data transfer for `rope.ui.testview`
- if True or os.name == 'nt':
- self.receiver = _SocketReceiver()
- else:
- self.receiver = _FIFOReceiver()
- self.receiving_thread = threading.Thread(target=self._receive_information)
- self.receiving_thread.setDaemon(True)
- self.receiving_thread.start()
- def _receive_information(self):
- #temp = open('/dev/shm/info', 'w')
- for data in self.receiver.receive_data():
- self.analyze_data(data)
- #temp.write(str(data) + '\n')
- #temp.close()
- for observer in self.observers:
- observer()
- def wait_process(self):
- """Wait for the process to finish"""
- self.process.wait()
- if self.analyze_data:
- self.receiving_thread.join()
- def kill_process(self):
- """Stop the process"""
- if self.process.poll() is not None:
- return
- try:
- if hasattr(self.process, 'terminate'):
- self.process.terminate()
- elif os.name != 'nt':
- os.kill(self.process.pid, 9)
- else:
- import ctypes
- handle = int(self.process._handle)
- ctypes.windll.kernel32.TerminateProcess(handle, -1)
- except OSError:
- pass
- def add_finishing_observer(self, observer):
- """Notify this observer when execution finishes"""
- self.observers.append(observer)
- class _MessageReceiver(object):
- def receive_data(self):
- pass
- def get_send_info(self):
- pass
- class _SocketReceiver(_MessageReceiver):
- def __init__(self):
- self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.data_port = 3037
- while self.data_port < 4000:
- try:
- self.server_socket.bind(('', self.data_port))
- break
- except socket.error, e:
- self.data_port += 1
- self.server_socket.listen(1)
- def get_send_info(self):
- return str(self.data_port)
- def receive_data(self):
- conn, addr = self.server_socket.accept()
- self.server_socket.close()
- my_file = conn.makefile('r')
- while True:
- try:
- yield pickle.load(my_file)
- except EOFError:
- break
- my_file.close()
- conn.close()
- class _FIFOReceiver(_MessageReceiver):
- def __init__(self):
- # XXX: this is insecure and might cause race conditions
- self.file_name = self._get_file_name()
- os.mkfifo(self.file_name)
- def _get_file_name(self):
- prefix = tempfile.gettempdir() + '/__rope_'
- i = 0
- while os.path.exists(prefix + str(i).rjust(4, '0')):
- i += 1
- return prefix + str(i).rjust(4, '0')
- def get_send_info(self):
- return self.file_name
- def receive_data(self):
- my_file = open(self.file_name, 'rb')
- while True:
- try:
- yield marshal.load(my_file)
- except EOFError:
- break
- my_file.close()
- os.remove(self.file_name)
|