Path: blob/master/elisp/emacs-for-python/rope-dist/rope/base/oi/doa.py
1428 views
import cPickle as pickle1import marshal2import os3import socket4import subprocess5import sys6import tempfile7import threading8910class PythonFileRunner(object):11"""A class for running python project files"""1213def __init__(self, pycore, file_, args=None, stdin=None,14stdout=None, analyze_data=None):15self.pycore = pycore16self.file = file_17self.analyze_data = analyze_data18self.observers = []19self.args = args20self.stdin = stdin21self.stdout = stdout2223def run(self):24"""Execute the process"""25env = dict(os.environ)26file_path = self.file.real_path27path_folders = self.pycore.get_source_folders() + \28self.pycore.get_python_path_folders()29env['PYTHONPATH'] = os.pathsep.join(folder.real_path30for folder in path_folders)31runmod_path = self.pycore.find_module('rope.base.oi.runmod').real_path32self.receiver = None33self._init_data_receiving()34send_info = '-'35if self.receiver:36send_info = self.receiver.get_send_info()37args = [sys.executable, runmod_path, send_info,38self.pycore.project.address, self.file.real_path]39if self.analyze_data is None:40del args[1:4]41if self.args is not None:42args.extend(self.args)43self.process = subprocess.Popen(44executable=sys.executable, args=args, env=env,45cwd=os.path.split(file_path)[0], stdin=self.stdin,46stdout=self.stdout, stderr=self.stdout, close_fds=os.name != 'nt')4748def _init_data_receiving(self):49if self.analyze_data is None:50return51# Disabling FIFO data transfer due to blocking when running52# unittests in the GUI.53# XXX: Handle FIFO data transfer for `rope.ui.testview`54if True or os.name == 'nt':55self.receiver = _SocketReceiver()56else:57self.receiver = _FIFOReceiver()58self.receiving_thread = threading.Thread(target=self._receive_information)59self.receiving_thread.setDaemon(True)60self.receiving_thread.start()6162def _receive_information(self):63#temp = open('/dev/shm/info', 'w')64for data in self.receiver.receive_data():65self.analyze_data(data)66#temp.write(str(data) + '\n')67#temp.close()68for observer in self.observers:69observer()7071def wait_process(self):72"""Wait for the process to finish"""73self.process.wait()74if self.analyze_data:75self.receiving_thread.join()7677def kill_process(self):78"""Stop the process"""79if self.process.poll() is not None:80return81try:82if hasattr(self.process, 'terminate'):83self.process.terminate()84elif os.name != 'nt':85os.kill(self.process.pid, 9)86else:87import ctypes88handle = int(self.process._handle)89ctypes.windll.kernel32.TerminateProcess(handle, -1)90except OSError:91pass9293def add_finishing_observer(self, observer):94"""Notify this observer when execution finishes"""95self.observers.append(observer)969798class _MessageReceiver(object):99100def receive_data(self):101pass102103def get_send_info(self):104pass105106107class _SocketReceiver(_MessageReceiver):108109def __init__(self):110self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)111self.data_port = 3037112while self.data_port < 4000:113try:114self.server_socket.bind(('', self.data_port))115break116except socket.error, e:117self.data_port += 1118self.server_socket.listen(1)119120def get_send_info(self):121return str(self.data_port)122123def receive_data(self):124conn, addr = self.server_socket.accept()125self.server_socket.close()126my_file = conn.makefile('r')127while True:128try:129yield pickle.load(my_file)130except EOFError:131break132my_file.close()133conn.close()134135136class _FIFOReceiver(_MessageReceiver):137138def __init__(self):139# XXX: this is insecure and might cause race conditions140self.file_name = self._get_file_name()141os.mkfifo(self.file_name)142143def _get_file_name(self):144prefix = tempfile.gettempdir() + '/__rope_'145i = 0146while os.path.exists(prefix + str(i).rjust(4, '0')):147i += 1148return prefix + str(i).rjust(4, '0')149150def get_send_info(self):151return self.file_name152153def receive_data(self):154my_file = open(self.file_name, 'rb')155while True:156try:157yield marshal.load(my_file)158except EOFError:159break160my_file.close()161os.remove(self.file_name)162163164