def start_channel(source_name, modulename, serveraddr, start_type='channel'): # setup logging setup_logging(modulename) # setup logger for module logger = getLogger(modulename) logger = getLogger(__name__) logger.info("start_channel for %s", modulename) # change proccess title try: import setproctitle setproctitle.setproctitle('%s nvim-completion-manager' % modulename) except: pass try: # connect neovim and setup python environment nvim = setup_neovim(serveraddr) if start_type == 'core': import cm_core nvim.vars['_cm_channel_id'] = nvim.channel_id handler = cm_core.CoreHandler(nvim) logger.info('starting core, enter event loop') run_event_loop('core', logger, nvim, handler) elif start_type == 'channel': nvim.call('cm#_channel_started', source_name, nvim.channel_id) if sys.version_info.major == 2: # python2 doesn't support namespace package # use load_source as a workaround import imp file = modulename.replace('.', '/') exp = 'globpath(&rtp,"pythonx/%s.py",1)' % file path = nvim.eval(exp).strip() logger.info('python2 file path: %s, exp: %s', path, exp) m = imp.load_source(modulename, path) else: m = importlib.import_module(modulename) handler = m.Source(nvim) logger.info('handler created, entering event loop') run_event_loop('channel', logger, nvim, handler) except Exception as ex: logger.exception('Exception when running %s: %s', modulename, ex) exit(1) finally: # terminate here exit(0)
def start_and_run_channel(channel_type, serveraddr, source_name, modulename): # connect neovim and setup python environment nvim = setup_neovim(serveraddr) if channel_type == 'core': import cm_core handler = cm_core.CoreHandler(nvim) logger.info('starting core, enter event loop') elif channel_type == 'channel': if sys.version_info.major == 2: # python2 doesn't support namespace package # use load_source as a workaround import imp file = modulename.replace('.', '/') exp = 'globpath(&rtp,"pythonx/%s.py",1)' % file path = nvim.eval(exp).strip() logger.info('<%s> python2 file path: %s, exp: %s', source_name, path, exp) m = imp.load_source(modulename, path) # the previous module load may be hacked before, by register_source if not hasattr(m, 'Source'): m = imp.reload(m) else: m = importlib.import_module(modulename) # the previous module load may be hacked before, by register_source if not hasattr(m, 'Source'): m = importlib.reload(m) handler = m.Source(nvim) nvim.call('cm#_channel_started', source_name, nvim.channel_id, async=True) logger.info('<%s> handler created, entering event loop', source_name) handler.cm_running_ = False handler.cm_msgs_ = [] def on_request(method, args): logger.error('method: %s not implemented, ignore this request', method) def on_notification(method, args): # A trick to get rid of the greenlet coroutine without using the # next_message API. handler.cm_msgs_.append((method, args)) if handler.cm_running_: logger.info("delay notification handling, method[%s]", method) return handler.cm_running_ = True while handler.cm_msgs_: method, args = handler.cm_msgs_.pop(0) try: logger.debug('%s method: %s, args: %s', channel_type, method, args) if channel_type == 'channel' and method == 'cm_refresh': ctx = args[1] # The refresh calculation may be heavy, and the notification queue # may have outdated refresh events, it would be meaningless to # process these event if nvim.call('cm#context_changed', ctx): logger.info('context_changed, ignoring context: %s', ctx) continue func = getattr(handler, method, None) if func is None: logger.info( 'method: %s not implemented, ignore this message', method) continue func(*args) logger.debug('%s method %s completed', channel_type, method) except Exception as ex: logger.exception("Failed processing method: %s, args: %s", method, args) handler.cm_running_ = False def on_setup(): on_notification('cm_setup', []) try: logger.info("<%s> entering event loop", source_name) # Use next_message is simpler, as a handler doesn't need to deal with # concurrent issue, but it has serious issue, # https://github.com/roxma/nvim-completion-manager/issues/35#issuecomment-284049103 nvim.run_loop(on_request, on_notification, on_setup) except Exception as ex: logger.exception("nvim.run_loop failed, %s", ex) finally: # use at_exit to ensure the calling of cm_shutdown func = getattr(handler, 'cm_shutdown', None) if func: func() if channel_type == 'core': exit(0)