Passing user options as file to server
This is a much better idea than starting the server in a default state, and then resetting the state with a POST request.
This commit is contained in:
parent
10469d318d
commit
dd2445db06
@ -1,80 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# Copyright 2012 by Jeff Laughlin Consulting LLC
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in
|
|
||||||
# all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
# Source: https://gist.github.com/n1ywb/2570004
|
|
||||||
|
|
||||||
def example_exc_handler(tries_remaining, exception, delay):
|
|
||||||
"""Example exception handler; prints a warning to stderr.
|
|
||||||
|
|
||||||
tries_remaining: The number of tries remaining.
|
|
||||||
exception: The exception instance which was raised.
|
|
||||||
"""
|
|
||||||
print >> sys.stderr, "Caught '%s', %d tries remaining, sleeping for %s seconds" % (exception, tries_remaining, delay)
|
|
||||||
|
|
||||||
|
|
||||||
def retries(max_tries, delay=1, backoff=2, exceptions=(Exception,), hook=None):
|
|
||||||
"""Function decorator implementing retrying logic.
|
|
||||||
|
|
||||||
delay: Sleep this many seconds * backoff * try number after failure
|
|
||||||
backoff: Multiply delay by this factor after each failure
|
|
||||||
exceptions: A tuple of exception classes; default (Exception,)
|
|
||||||
hook: A function with the signature myhook(tries_remaining, exception);
|
|
||||||
default None
|
|
||||||
|
|
||||||
The decorator will call the function up to max_tries times if it raises
|
|
||||||
an exception.
|
|
||||||
|
|
||||||
By default it catches instances of the Exception class and subclasses.
|
|
||||||
This will recover after all but the most fatal errors. You may specify a
|
|
||||||
custom tuple of exception classes with the 'exceptions' argument; the
|
|
||||||
function will only be retried if it raises one of the specified
|
|
||||||
exceptions.
|
|
||||||
|
|
||||||
Additionally you may specify a hook function which will be called prior
|
|
||||||
to retrying with the number of remaining tries and the exception instance;
|
|
||||||
see given example. This is primarily intended to give the opportunity to
|
|
||||||
log the failure. Hook is not called after failure if no retries remain.
|
|
||||||
"""
|
|
||||||
def dec(func):
|
|
||||||
def f2(*args, **kwargs):
|
|
||||||
mydelay = delay
|
|
||||||
tries = range(max_tries)
|
|
||||||
tries.reverse()
|
|
||||||
for tries_remaining in tries:
|
|
||||||
try:
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
except exceptions as e:
|
|
||||||
if tries_remaining > 0:
|
|
||||||
if hook is not None:
|
|
||||||
hook(tries_remaining, e, mydelay)
|
|
||||||
sleep(mydelay)
|
|
||||||
mydelay = mydelay * backoff
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
return f2
|
|
||||||
return dec
|
|
@ -114,12 +114,8 @@ def GetUserOptions():
|
|||||||
|
|
||||||
@app.post( '/user_options' )
|
@app.post( '/user_options' )
|
||||||
def SetUserOptions():
|
def SetUserOptions():
|
||||||
global SERVER_STATE
|
|
||||||
|
|
||||||
LOGGER.info( 'Received user options POST request')
|
LOGGER.info( 'Received user options POST request')
|
||||||
data = request.json
|
_SetUserOptions( request.json )
|
||||||
SERVER_STATE = server_state.ServerState( data )
|
|
||||||
user_options_store.SetAll( data )
|
|
||||||
|
|
||||||
|
|
||||||
@app.post( '/filetype_completion_available')
|
@app.post( '/filetype_completion_available')
|
||||||
@ -139,6 +135,13 @@ def _ServerShutdown():
|
|||||||
SERVER_STATE.Shutdown()
|
SERVER_STATE.Shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
def _SetUserOptions( options ):
|
||||||
|
global SERVER_STATE
|
||||||
|
|
||||||
|
SERVER_STATE = server_state.ServerState( options )
|
||||||
|
user_options_store.SetAll( options )
|
||||||
|
|
||||||
|
|
||||||
def Main():
|
def Main():
|
||||||
global LOGGER
|
global LOGGER
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
@ -149,8 +152,13 @@ def Main():
|
|||||||
parser.add_argument( '--log', type = str, default = 'info',
|
parser.add_argument( '--log', type = str, default = 'info',
|
||||||
help='log level, one of '
|
help='log level, one of '
|
||||||
'[debug|info|warning|error|critical]')
|
'[debug|info|warning|error|critical]')
|
||||||
|
parser.add_argument( '--options_file', type = str, default = '',
|
||||||
|
help='file with user options, in JSON format')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.options_file:
|
||||||
|
_SetUserOptions( json.load( open( args.options_file, 'r' ) ) )
|
||||||
|
|
||||||
numeric_level = getattr( logging, args.log.upper(), None )
|
numeric_level = getattr( logging, args.log.upper(), None )
|
||||||
if not isinstance( numeric_level, int ):
|
if not isinstance( numeric_level, int ):
|
||||||
raise ValueError( 'Invalid log level: %s' % args.log )
|
raise ValueError( 'Invalid log level: %s' % args.log )
|
||||||
|
@ -21,8 +21,8 @@ import os
|
|||||||
import vim
|
import vim
|
||||||
import ycm_core
|
import ycm_core
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import tempfile
|
||||||
from ycm.retries import retries
|
import json
|
||||||
from ycm import vimsupport
|
from ycm import vimsupport
|
||||||
from ycm import utils
|
from ycm import utils
|
||||||
from ycm.completers.all.omni_completer import OmniCompleter
|
from ycm.completers.all.omni_completer import OmniCompleter
|
||||||
@ -43,57 +43,43 @@ class YouCompleteMe( object ):
|
|||||||
self._server_stderr = None
|
self._server_stderr = None
|
||||||
self._server_popen = None
|
self._server_popen = None
|
||||||
self._filetypes_with_keywords_loaded = set()
|
self._filetypes_with_keywords_loaded = set()
|
||||||
self._options_thread = None
|
self._temp_options_filename = None
|
||||||
self._SetupServer()
|
self._SetupServer()
|
||||||
|
|
||||||
|
|
||||||
def _SetupServer( self ):
|
def _SetupServer( self ):
|
||||||
server_port = SERVER_PORT_RANGE_START + os.getpid()
|
server_port = SERVER_PORT_RANGE_START + os.getpid()
|
||||||
command = ''.join( [ 'python ',
|
with tempfile.NamedTemporaryFile( delete = False ) as options_file:
|
||||||
_PathToServerScript(),
|
self._temp_options_filename = options_file.name
|
||||||
' --port=',
|
json.dump( dict( self._user_options ), options_file )
|
||||||
str( server_port ),
|
command = ''.join( [ 'python ',
|
||||||
' --log=',
|
_PathToServerScript(),
|
||||||
self._user_options[ 'server_log_level' ] ] )
|
' --port=',
|
||||||
|
str( server_port ),
|
||||||
|
' --options_file=',
|
||||||
|
options_file.name,
|
||||||
|
' --log=',
|
||||||
|
self._user_options[ 'server_log_level' ] ] )
|
||||||
|
|
||||||
BaseRequest.server_location = 'http://localhost:' + str( server_port )
|
BaseRequest.server_location = 'http://localhost:' + str( server_port )
|
||||||
|
|
||||||
if self._user_options[ 'server_use_vim_stdout' ]:
|
if self._user_options[ 'server_use_vim_stdout' ]:
|
||||||
self._server_popen = subprocess.Popen( command, shell = True )
|
self._server_popen = subprocess.Popen( command, shell = True )
|
||||||
else:
|
else:
|
||||||
filename_format = os.path.join( utils.PathToTempDir(),
|
filename_format = os.path.join( utils.PathToTempDir(),
|
||||||
'server_{port}_{std}.log' )
|
'server_{port}_{std}.log' )
|
||||||
|
|
||||||
self._server_stdout = filename_format.format( port = server_port,
|
self._server_stdout = filename_format.format( port = server_port,
|
||||||
std = 'stdout' )
|
std = 'stdout' )
|
||||||
self._server_stderr = filename_format.format( port = server_port,
|
self._server_stderr = filename_format.format( port = server_port,
|
||||||
std = 'stderr' )
|
std = 'stderr' )
|
||||||
|
|
||||||
with open( self._server_stderr, 'w' ) as fstderr:
|
|
||||||
with open( self._server_stdout, 'w' ) as fstdout:
|
|
||||||
self._server_popen = subprocess.Popen( command,
|
|
||||||
stdout = fstdout,
|
|
||||||
stderr = fstderr,
|
|
||||||
shell = True )
|
|
||||||
|
|
||||||
self._StartOptionsThread()
|
|
||||||
|
|
||||||
|
|
||||||
def _StartOptionsThread( self ):
|
|
||||||
def OptionsThreadMain( options ):
|
|
||||||
@retries( 5, delay = 0.5 )
|
|
||||||
def PostOptionsToServer():
|
|
||||||
BaseRequest.PostDataToHandler( options, 'user_options' )
|
|
||||||
|
|
||||||
PostOptionsToServer()
|
|
||||||
|
|
||||||
self._options_thread = threading.Thread(
|
|
||||||
target = OptionsThreadMain,
|
|
||||||
args = ( dict( self._user_options ), ) )
|
|
||||||
|
|
||||||
self._options_thread.daemon = True
|
|
||||||
self._options_thread.start()
|
|
||||||
|
|
||||||
|
with open( self._server_stderr, 'w' ) as fstderr:
|
||||||
|
with open( self._server_stdout, 'w' ) as fstdout:
|
||||||
|
self._server_popen = subprocess.Popen( command,
|
||||||
|
stdout = fstdout,
|
||||||
|
stderr = fstderr,
|
||||||
|
shell = False )
|
||||||
|
|
||||||
|
|
||||||
def CreateCompletionRequest( self ):
|
def CreateCompletionRequest( self ):
|
||||||
@ -165,6 +151,7 @@ class YouCompleteMe( object ):
|
|||||||
|
|
||||||
def OnVimLeave( self ):
|
def OnVimLeave( self ):
|
||||||
self._server_popen.terminate()
|
self._server_popen.terminate()
|
||||||
|
os.remove( self._temp_options_filename )
|
||||||
|
|
||||||
|
|
||||||
def OnCurrentIdentifierFinished( self ):
|
def OnCurrentIdentifierFinished( self ):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user