def do_oop(self, subcmd, opts): """Run the out-of-process (OOP) driver. ${cmd_usage} ${cmd_option_list} """ import atexit from codeintel2.oop import Driver old_sys_path = set(os.path.abspath(os.path.join(p)) for p in sys.path) for relpath in opts.import_path: import_path = os.path.abspath(os.path.join(__path__, relpath)) if import_path not in old_sys_path: sys.path.append(import_path) if opts.tcp: host, _, port = opts.tcp.partition(':') port = int(port) self.log.info("Connecting to: %s:%s", host, port) try: conn = socket.create_connection((host, port)) fd_in = conn.makefile('rb', 0) fd_out = conn.makefile('wb', 0) except Exception as ex: self.log.exception("Failed to connect with client: %s", ex) return elif opts.server: host, _, port = opts.server.partition(':') if not port: host, port = '0.0.0.0', host port = int(port) self.log.info("Server listening on: %s:%s", host, port) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind((host, port)) sock.listen(0) conn = sock.accept() self.log.info("Client accepted!") fd_in = conn[0].makefile('rb', 0) fd_out = conn[0].makefile('wb', 0) elif opts.pipe and opts.pipe not in ('-', 'stdin', '/dev/stdin'): pipe = opts.pipe self.log.info("Connecting to pipe: %s", pipe) try: if sys.platform.startswith('win'): # using Win32 pipes from win32_named_pipe import Win32Pipe fd_out = fd_in = Win32Pipe(name=pipe, client=True) else: # Open the write end first, so the parent doesn't hang fd_out = open(os.path.join(pipe, 'out'), 'wb', 0) fd_in = open(os.path.join(pipe, 'in'), 'rb', 0) except Exception as ex: self.log.exception("Failed to pipe with client: %s", ex) return else: # force binary unbuffered stdin and stdout fd_in = os.fdopen(sys.stdin.fileno(), 'rb', 0) fd_out = os.fdopen(sys.stdout.fileno(), 'wb', 0) if not os.path.exists(opts.database_dir): os.makedirs(opts.database_dir) driver = Driver(db_base_dir=opts.database_dir, fd_in=fd_in, fd_out=fd_out) atexit.register(driver.finalize) driver.start()
def main(argv=[]): global log # Don't redirect output os.environ["KOMODO_VERBOSE"] = "1" parser = argparse.ArgumentParser() parser.description = "Komodo out-of-process codeintel driver" parser.add_argument("--database-dir", default=os.path.expanduser("~/.codeintel"), help="The base directory for the codeintel database.") parser.add_argument("--log-level", action="append", default=[], help="<log name>:<level> Set log level") parser.add_argument("--log-file", default=None, help="The name of the file to log to") parser.add_argument("--connect", default=None, help="Connect over TCP instead of using stdin/stdout") parser.add_argument("--import-path", action="append", default=["", "../lib"], help="Paths to add to the Python import path") args = parser.parse_args() if args.log_file: if args.log_file in ("stdout", "stderr"): stream = getattr(sys, args.log_file) else: stream = open(args.log_file, "w", 0) logging.basicConfig(stream=stream) # XXX marky horrible ugly hack sys.stderr = stream sys.stdout = stream else: logging.basicConfig(stream=DummyStream()) for log_level in args.log_level: if ":" in log_level: name, level = log_level.rsplit(":", 1) else: name, level = ["", log_level] try: level = int(level, 10) except ValueError: try: level = getattr(logging, level) except AttributeError: pass if isinstance(level, int): logging.getLogger(name).setLevel(level) log = logging.getLogger("codeintel.oop.executable") try: set_process_limits() except: log.exception("Failed to set process memory/CPU limits") try: set_idle_priority() except: log.exception("Failed to set process CPU priority") old_sys_path = set(abspath(join(p)) for p in sys.path) for relpath in args.import_path: import_path = abspath(join(dirname(__file__), relpath)) if import_path not in old_sys_path: sys.path.append(import_path) # importing codeintel imports pyxpcom, which seems to break logging; # work around it for now by putting the original handler back handler = logging.root.handlers[0] from codeintel2.oop import Driver logging.root.handlers[0] = handler try: if args.connect: if args.connect.startswith("pipe:"): pipe_name = args.connect.split(":", 1)[1] log.debug("connecting to pipe: %s", pipe_name) if sys.platform.startswith("win"): # using Win32 pipes from win32_named_pipe import Win32Pipe fd_out = fd_in = Win32Pipe(name=pipe_name, client=True) else: # Open the write end first, so the parent doesn't hang fd_out = open(join(pipe_name, "out"), "wb", 0) fd_in = open(join(pipe_name, "in"), "rb", 0) log.debug("opened: %r", fd_in) else: log.debug("connecting to port: %s", args.connect) conn = socket.create_connection(args.connect.rsplit(":", 1)) fd_in = conn.makefile("r+b", 0) fd_out = fd_in else: # force unbuffered stdout fd_in = sys.stdin fd_out = os.fdopen(sys.stdout.fileno(), "wb", 0) except Exception as ex: log.exception("Failed to connect to Komodo: %s", ex) raise driver = Driver(db_base_dir=args.database_dir, fd_in=fd_in, fd_out=fd_out) driver.start()
def oop_driver(database_dir, connect=None, log_levels=[], log_file=None, import_path=[]): """ Starts OOP CodeIntel driver Args: :param database_dir: Directory where CodeIntel database is. :param connect: Connect using a socket to this 'IP:port'. It can also be an output file, for example 'stdin' :param log_levels: List of logger:LEVEL, where logger can be, for example, "codeintel.db" and level "DEBUG": ['codeintel:WARNING', 'codeintel.db:DEBUG'] :param log_file: File where logs will be written. It can be 'stdout' or 'stderr', for example """ # Don't redirect output os.environ["KOMODO_VERBOSE"] = "1" if log_file: if log_file in ('stdout', 'stderr', '/dev/stdout', '/dev/stderr'): stream = getattr(sys, log_file) else: log_dir = os.path.dirname(log_file) if not os.path.exists(log_dir): os.makedirs(log_dir) stream = open(log_file, 'w', 0) logging.basicConfig(stream=stream) # XXX marky horrible ugly hack sys.stderr = stream sys.stdout = stream else: logging.basicConfig(stream=DummyStream()) logger = logging.getLogger('codeintel') logger.setLevel(logging.INFO) for log_level in log_levels: name, _, level = log_level.rpartition(':') try: level = int(level) except ValueError: level = getattr(logging, level.upper(), logging.ERROR) logging.getLogger(name).setLevel(level) log = logging.getLogger('codeintel.oop.executable') try: set_process_limits(log) except: log.exception("Failed to set process memory/CPU limits") try: set_idle_priority(log) except: log.exception("Failed to set process CPU priority") old_sys_path = set(os.path.abspath(os.path.join(p)) for p in sys.path) for relpath in import_path: import_path = os.path.abspath(os.path.join(__path__, relpath)) if import_path not in old_sys_path: sys.path.append(import_path) try: if connect and connect not in ('-', 'stdin', '/dev/stdin'): if connect.startswith('pipe:'): pipe_name = connect.split(':', 1)[1] log.debug("connecting to pipe: %s", pipe_name) if sys.platform.startswith('win'): # using Win32 pipes from win32_named_pipe import Win32Pipe fd_out = fd_in = Win32Pipe(name=pipe_name, client=True) else: # Open the write end first, so the parent doesn't hang fd_out = open(os.path.join(pipe_name, 'out'), 'wb', 0) fd_in = open(os.path.join(pipe_name, 'in'), 'rb', 0) log.debug("opened: %r", fd_in) else: host, _, port = connect.partition(':') port = int(port) log.debug("connecting to: %s:%s", host, port) conn = socket.create_connection((host, port)) fd_in = conn.makefile('r+b', 0) fd_out = fd_in else: # force unbuffered stdout fd_in = sys.stdin fd_out = os.fdopen(sys.stdout.fileno(), 'wb', 0) except Exception as ex: log.exception("Failed to connect with client: %s", ex) raise if not os.path.exists(database_dir): os.makedirs(database_dir) from codeintel2.oop import Driver driver = Driver(db_base_dir=database_dir, fd_in=fd_in, fd_out=fd_out) try: driver.start() except KeyboardInterrupt: pass