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' )
|
||||
def SetUserOptions():
|
||||
global SERVER_STATE
|
||||
|
||||
LOGGER.info( 'Received user options POST request')
|
||||
data = request.json
|
||||
SERVER_STATE = server_state.ServerState( data )
|
||||
user_options_store.SetAll( data )
|
||||
_SetUserOptions( request.json )
|
||||
|
||||
|
||||
@app.post( '/filetype_completion_available')
|
||||
@ -139,6 +135,13 @@ def _ServerShutdown():
|
||||
SERVER_STATE.Shutdown()
|
||||
|
||||
|
||||
def _SetUserOptions( options ):
|
||||
global SERVER_STATE
|
||||
|
||||
SERVER_STATE = server_state.ServerState( options )
|
||||
user_options_store.SetAll( options )
|
||||
|
||||
|
||||
def Main():
|
||||
global LOGGER
|
||||
parser = argparse.ArgumentParser()
|
||||
@ -149,8 +152,13 @@ def Main():
|
||||
parser.add_argument( '--log', type = str, default = 'info',
|
||||
help='log level, one of '
|
||||
'[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()
|
||||
|
||||
if args.options_file:
|
||||
_SetUserOptions( json.load( open( args.options_file, 'r' ) ) )
|
||||
|
||||
numeric_level = getattr( logging, args.log.upper(), None )
|
||||
if not isinstance( numeric_level, int ):
|
||||
raise ValueError( 'Invalid log level: %s' % args.log )
|
||||
|
@ -21,8 +21,8 @@ import os
|
||||
import vim
|
||||
import ycm_core
|
||||
import subprocess
|
||||
import threading
|
||||
from ycm.retries import retries
|
||||
import tempfile
|
||||
import json
|
||||
from ycm import vimsupport
|
||||
from ycm import utils
|
||||
from ycm.completers.all.omni_completer import OmniCompleter
|
||||
@ -43,57 +43,43 @@ class YouCompleteMe( object ):
|
||||
self._server_stderr = None
|
||||
self._server_popen = None
|
||||
self._filetypes_with_keywords_loaded = set()
|
||||
self._options_thread = None
|
||||
self._temp_options_filename = None
|
||||
self._SetupServer()
|
||||
|
||||
|
||||
def _SetupServer( self ):
|
||||
server_port = SERVER_PORT_RANGE_START + os.getpid()
|
||||
command = ''.join( [ 'python ',
|
||||
_PathToServerScript(),
|
||||
' --port=',
|
||||
str( server_port ),
|
||||
' --log=',
|
||||
self._user_options[ 'server_log_level' ] ] )
|
||||
with tempfile.NamedTemporaryFile( delete = False ) as options_file:
|
||||
self._temp_options_filename = options_file.name
|
||||
json.dump( dict( self._user_options ), options_file )
|
||||
command = ''.join( [ 'python ',
|
||||
_PathToServerScript(),
|
||||
' --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' ]:
|
||||
self._server_popen = subprocess.Popen( command, shell = True )
|
||||
else:
|
||||
filename_format = os.path.join( utils.PathToTempDir(),
|
||||
'server_{port}_{std}.log' )
|
||||
if self._user_options[ 'server_use_vim_stdout' ]:
|
||||
self._server_popen = subprocess.Popen( command, shell = True )
|
||||
else:
|
||||
filename_format = os.path.join( utils.PathToTempDir(),
|
||||
'server_{port}_{std}.log' )
|
||||
|
||||
self._server_stdout = filename_format.format( port = server_port,
|
||||
std = 'stdout' )
|
||||
self._server_stderr = filename_format.format( port = server_port,
|
||||
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()
|
||||
self._server_stdout = filename_format.format( port = server_port,
|
||||
std = 'stdout' )
|
||||
self._server_stderr = filename_format.format( port = server_port,
|
||||
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 = False )
|
||||
|
||||
|
||||
def CreateCompletionRequest( self ):
|
||||
@ -165,6 +151,7 @@ class YouCompleteMe( object ):
|
||||
|
||||
def OnVimLeave( self ):
|
||||
self._server_popen.terminate()
|
||||
os.remove( self._temp_options_filename )
|
||||
|
||||
|
||||
def OnCurrentIdentifierFinished( self ):
|
||||
|
Loading…
Reference in New Issue
Block a user