Correctly handling ycm_extra_conf files now
The user is asked about loading unknown extra conf files, as they were before.
This commit is contained in:
parent
f0650ddc7f
commit
3d55748400
@ -24,15 +24,11 @@ from retries import retries
|
|||||||
from requests_futures.sessions import FuturesSession
|
from requests_futures.sessions import FuturesSession
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from ycm import vimsupport
|
from ycm import vimsupport
|
||||||
|
from ycm.server.responses import ServerError, UnknownExtraConf
|
||||||
|
|
||||||
HEADERS = {'content-type': 'application/json'}
|
HEADERS = {'content-type': 'application/json'}
|
||||||
EXECUTOR = ThreadPoolExecutor( max_workers = 4 )
|
EXECUTOR = ThreadPoolExecutor( max_workers = 4 )
|
||||||
|
|
||||||
class ServerError( Exception ):
|
|
||||||
def __init__( self, message ):
|
|
||||||
super( ServerError, self ).__init__( message )
|
|
||||||
|
|
||||||
|
|
||||||
class BaseRequest( object ):
|
class BaseRequest( object ):
|
||||||
def __init__( self ):
|
def __init__( self ):
|
||||||
pass
|
pass
|
||||||
@ -103,7 +99,7 @@ def BuildRequestData( start_column = None, query = None ):
|
|||||||
def JsonFromFuture( future ):
|
def JsonFromFuture( future ):
|
||||||
response = future.result()
|
response = future.result()
|
||||||
if response.status_code == requests.codes.server_error:
|
if response.status_code == requests.codes.server_error:
|
||||||
raise ServerError( response.json()[ 'message' ] )
|
_RaiseExceptionForData( response.json() )
|
||||||
|
|
||||||
# We let Requests handle the other status types, we only handle the 500
|
# We let Requests handle the other status types, we only handle the 500
|
||||||
# error code.
|
# error code.
|
||||||
@ -137,3 +133,10 @@ def _CheckServerIsHealthyWithCache():
|
|||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _RaiseExceptionForData( data ):
|
||||||
|
if data[ 'exception' ][ 'TYPE' ] == UnknownExtraConf.__name__:
|
||||||
|
raise UnknownExtraConf( data[ 'exception' ][ 'extra_conf_file' ] )
|
||||||
|
|
||||||
|
raise ServerError( '{0}: {1}'.format( data[ 'exception' ][ 'TYPE' ],
|
||||||
|
data[ 'message' ] ) )
|
||||||
|
@ -57,7 +57,7 @@ class CompletionRequest( BaseRequest ):
|
|||||||
for x in JsonFromFuture( self._response_future ) ]
|
for x in JsonFromFuture( self._response_future ) ]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
vimsupport.PostVimMessage( str( e ) )
|
vimsupport.PostVimMessage( str( e ) )
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def _ConvertCompletionDataToVimData( completion_data ):
|
def _ConvertCompletionDataToVimData( completion_data ):
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ycm import vimsupport
|
from ycm import vimsupport
|
||||||
|
from ycm.server.responses import UnknownExtraConf
|
||||||
from ycm.client.base_request import ( BaseRequest, BuildRequestData,
|
from ycm.client.base_request import ( BaseRequest, BuildRequestData,
|
||||||
JsonFromFuture )
|
JsonFromFuture )
|
||||||
|
|
||||||
|
|
||||||
class EventNotification( BaseRequest ):
|
class EventNotification( BaseRequest ):
|
||||||
def __init__( self, event_name, extra_data = None ):
|
def __init__( self, event_name, extra_data = None ):
|
||||||
super( EventNotification, self ).__init__()
|
super( EventNotification, self ).__init__()
|
||||||
@ -51,10 +53,13 @@ class EventNotification( BaseRequest ):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._cached_response = JsonFromFuture( self._response_future )
|
try:
|
||||||
|
self._cached_response = JsonFromFuture( self._response_future )
|
||||||
|
except UnknownExtraConf as e:
|
||||||
|
if vimsupport.Confirm( str( e ) ):
|
||||||
|
_LoadExtraConfFile( e.extra_conf_file )
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
vimsupport.PostVimMessage( str( e ) )
|
vimsupport.PostVimMessage( str( e ) )
|
||||||
return []
|
|
||||||
|
|
||||||
if not self._cached_response:
|
if not self._cached_response:
|
||||||
return []
|
return []
|
||||||
@ -83,3 +88,6 @@ def SendEventNotificationAsync( event_name, extra_data = None ):
|
|||||||
event = EventNotification( event_name, extra_data )
|
event = EventNotification( event_name, extra_data )
|
||||||
event.Start()
|
event.Start()
|
||||||
|
|
||||||
|
def _LoadExtraConfFile( filepath ):
|
||||||
|
BaseRequest.PostDataToHandler( { 'filepath': filepath },
|
||||||
|
'load_extra_conf_file' )
|
||||||
|
@ -79,6 +79,9 @@ class ClangCompleter( Completer ):
|
|||||||
|
|
||||||
if self._completer.UpdatingTranslationUnit( ToUtf8IfNeeded( filename ) ):
|
if self._completer.UpdatingTranslationUnit( ToUtf8IfNeeded( filename ) ):
|
||||||
self._logger.info( PARSING_FILE_MESSAGE )
|
self._logger.info( PARSING_FILE_MESSAGE )
|
||||||
|
# TODO: For this exception and the NO_COMPILE_FLAGS one, use a special
|
||||||
|
# exception class so that the client can be more silent about these
|
||||||
|
# messages.
|
||||||
raise RuntimeError( PARSING_FILE_MESSAGE )
|
raise RuntimeError( PARSING_FILE_MESSAGE )
|
||||||
|
|
||||||
flags = self._FlagsForRequest( request_data )
|
flags = self._FlagsForRequest( request_data )
|
||||||
|
@ -37,6 +37,7 @@ class Flags( object ):
|
|||||||
# It's caches all the way down...
|
# It's caches all the way down...
|
||||||
self.flags_for_file = {}
|
self.flags_for_file = {}
|
||||||
self.special_clang_flags = _SpecialClangIncludes()
|
self.special_clang_flags = _SpecialClangIncludes()
|
||||||
|
self.no_extra_conf_file_warning_posted = False
|
||||||
|
|
||||||
|
|
||||||
def FlagsForFile( self, filename, add_special_clang_flags = True ):
|
def FlagsForFile( self, filename, add_special_clang_flags = True ):
|
||||||
@ -45,7 +46,10 @@ class Flags( object ):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
module = extra_conf_store.ModuleForSourceFile( filename )
|
module = extra_conf_store.ModuleForSourceFile( filename )
|
||||||
if not module:
|
if not module:
|
||||||
raise RuntimeError( NO_EXTRA_CONF_FILENAME_MESSAGE )
|
if not self.no_extra_conf_file_warning_posted:
|
||||||
|
self.no_extra_conf_file_warning_posted = True
|
||||||
|
raise RuntimeError( NO_EXTRA_CONF_FILENAME_MESSAGE )
|
||||||
|
return None
|
||||||
|
|
||||||
results = module.FlagsForFile( filename )
|
results = module.FlagsForFile( filename )
|
||||||
|
|
||||||
|
@ -24,27 +24,29 @@ import imp
|
|||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
|
from threading import Lock
|
||||||
from ycm import user_options_store
|
from ycm import user_options_store
|
||||||
|
from ycm.server.responses import UnknownExtraConf
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
YCM_EXTRA_CONF_FILENAME = '.ycm_extra_conf.py'
|
YCM_EXTRA_CONF_FILENAME = '.ycm_extra_conf.py'
|
||||||
CONFIRM_CONF_FILE_MESSAGE = ('Found {0}. Load? \n\n(Question can be turned '
|
|
||||||
'off with options, see YCM docs)')
|
|
||||||
|
|
||||||
# Singleton variables
|
# Singleton variables
|
||||||
_module_for_module_file = {}
|
_module_for_module_file = {}
|
||||||
|
_module_for_module_file_lock = Lock()
|
||||||
_module_file_for_source_file = {}
|
_module_file_for_source_file = {}
|
||||||
|
_module_file_for_source_file_lock = Lock()
|
||||||
|
|
||||||
class UnknownExtraConf( Exception ):
|
|
||||||
def __init__( self, extra_conf_file ):
|
def Reset():
|
||||||
message = CONFIRM_CONF_FILE_MESSAGE.format( extra_conf_file )
|
global _module_for_module_file, _module_file_for_source_file
|
||||||
super( UnknownExtraConf, self ).__init__( message )
|
_module_for_module_file = {}
|
||||||
self.extra_conf_file = extra_conf_file
|
_module_file_for_source_file = {}
|
||||||
|
|
||||||
|
|
||||||
def ModuleForSourceFile( filename ):
|
def ModuleForSourceFile( filename ):
|
||||||
return _Load( ModuleFileForSourceFile( filename ) )
|
return Load( ModuleFileForSourceFile( filename ) )
|
||||||
|
|
||||||
|
|
||||||
def ModuleFileForSourceFile( filename ):
|
def ModuleFileForSourceFile( filename ):
|
||||||
@ -52,11 +54,12 @@ def ModuleFileForSourceFile( filename ):
|
|||||||
order and return the filename of the first module that was allowed to load.
|
order and return the filename of the first module that was allowed to load.
|
||||||
If no module was found or allowed to load, None is returned."""
|
If no module was found or allowed to load, None is returned."""
|
||||||
|
|
||||||
if not filename in _module_file_for_source_file:
|
with _module_file_for_source_file_lock:
|
||||||
for module_file in _ExtraConfModuleSourceFilesForFile( filename ):
|
if not filename in _module_file_for_source_file:
|
||||||
if _Load( module_file ):
|
for module_file in _ExtraConfModuleSourceFilesForFile( filename ):
|
||||||
_module_file_for_source_file[ filename ] = module_file
|
if Load( module_file ):
|
||||||
break
|
_module_file_for_source_file[ filename ] = module_file
|
||||||
|
break
|
||||||
|
|
||||||
return _module_file_for_source_file.setdefault( filename )
|
return _module_file_for_source_file.setdefault( filename )
|
||||||
|
|
||||||
@ -84,7 +87,8 @@ def _CallExtraConfMethod( function_name ):
|
|||||||
|
|
||||||
def _Disable( module_file ):
|
def _Disable( module_file ):
|
||||||
"""Disables the loading of a module for the current session."""
|
"""Disables the loading of a module for the current session."""
|
||||||
_module_for_module_file[ module_file ] = None
|
with _module_for_module_file_lock:
|
||||||
|
_module_for_module_file[ module_file ] = None
|
||||||
|
|
||||||
|
|
||||||
def _ShouldLoad( module_file ):
|
def _ShouldLoad( module_file ):
|
||||||
@ -102,10 +106,15 @@ def _ShouldLoad( module_file ):
|
|||||||
if _MatchesGlobPattern( module_file, glob.lstrip('!') ):
|
if _MatchesGlobPattern( module_file, glob.lstrip('!') ):
|
||||||
return not is_blacklisted
|
return not is_blacklisted
|
||||||
|
|
||||||
|
# We disable the file if it's unknown so that we don't ask the user about it
|
||||||
|
# repeatedly. Raising UnknownExtraConf should result in the client sending
|
||||||
|
# another request to load the module file if the user explicitly chooses to do
|
||||||
|
# that.
|
||||||
|
_Disable( module_file )
|
||||||
raise UnknownExtraConf( module_file )
|
raise UnknownExtraConf( module_file )
|
||||||
|
|
||||||
|
|
||||||
def _Load( module_file, force = False ):
|
def Load( module_file, force = False ):
|
||||||
"""Load and return the module contained in a file.
|
"""Load and return the module contained in a file.
|
||||||
Using force = True the module will be loaded regardless
|
Using force = True the module will be loaded regardless
|
||||||
of the criteria in _ShouldLoad.
|
of the criteria in _ShouldLoad.
|
||||||
@ -115,11 +124,13 @@ def _Load( module_file, force = False ):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
if not force:
|
if not force:
|
||||||
if module_file in _module_for_module_file:
|
with _module_for_module_file_lock:
|
||||||
return _module_for_module_file[ module_file ]
|
if module_file in _module_for_module_file:
|
||||||
|
return _module_for_module_file[ module_file ]
|
||||||
|
|
||||||
if not _ShouldLoad( module_file ):
|
if not _ShouldLoad( module_file ):
|
||||||
return _Disable( module_file )
|
_Disable( module_file )
|
||||||
|
return None
|
||||||
|
|
||||||
# This has to be here because a long time ago, the ycm_extra_conf.py files
|
# This has to be here because a long time ago, the ycm_extra_conf.py files
|
||||||
# used to import clang_helpers.py from the cpp folder. This is not needed
|
# used to import clang_helpers.py from the cpp folder. This is not needed
|
||||||
@ -129,7 +140,8 @@ def _Load( module_file, force = False ):
|
|||||||
module = imp.load_source( _RandomName(), module_file )
|
module = imp.load_source( _RandomName(), module_file )
|
||||||
del sys.path[ 0 ]
|
del sys.path[ 0 ]
|
||||||
|
|
||||||
_module_for_module_file[ module_file ] = module
|
with _module_for_module_file_lock:
|
||||||
|
_module_for_module_file[ module_file ] = module
|
||||||
return module
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +19,21 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
CONFIRM_CONF_FILE_MESSAGE = ('Found {0}. Load? \n\n(Question can be turned '
|
||||||
|
'off with options, see YCM docs)')
|
||||||
|
|
||||||
|
class ServerError( Exception ):
|
||||||
|
def __init__( self, message ):
|
||||||
|
super( ServerError, self ).__init__( message )
|
||||||
|
|
||||||
|
|
||||||
|
class UnknownExtraConf( ServerError ):
|
||||||
|
def __init__( self, extra_conf_file ):
|
||||||
|
message = CONFIRM_CONF_FILE_MESSAGE.format( extra_conf_file )
|
||||||
|
super( UnknownExtraConf, self ).__init__( message )
|
||||||
|
self.extra_conf_file = extra_conf_file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def BuildGoToResponse( filepath, line_num, column_num, description = None ):
|
def BuildGoToResponse( filepath, line_num, column_num, description = None ):
|
||||||
response = {
|
response = {
|
||||||
@ -80,9 +95,10 @@ def BuildDiagnosticData( filepath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def BuildExceptionResponse( error_message, traceback ):
|
def BuildExceptionResponse( exception, traceback ):
|
||||||
return {
|
return {
|
||||||
'message': error_message,
|
'exception': exception,
|
||||||
|
'message': str( exception ),
|
||||||
'traceback': traceback
|
'traceback': traceback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,11 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import httplib
|
||||||
from webtest import TestApp
|
from webtest import TestApp
|
||||||
from .. import ycmd
|
from .. import ycmd
|
||||||
from ..responses import BuildCompletionData
|
from ..responses import BuildCompletionData, UnknownExtraConf
|
||||||
from nose.tools import ok_, eq_, with_setup
|
from nose.tools import ok_, eq_, with_setup
|
||||||
from hamcrest import ( assert_that, has_items, has_entry, contains,
|
from hamcrest import ( assert_that, has_items, has_entry, contains,
|
||||||
contains_string, has_entries )
|
contains_string, has_entries )
|
||||||
@ -73,6 +75,15 @@ def Setup():
|
|||||||
ycmd.SetServerStateToDefaults()
|
ycmd.SetServerStateToDefaults()
|
||||||
|
|
||||||
|
|
||||||
|
def PathToTestDataDir():
|
||||||
|
dir_of_current_script = os.path.dirname( os.path.abspath( __file__ ) )
|
||||||
|
return os.path.join( dir_of_current_script, 'testdata' )
|
||||||
|
|
||||||
|
|
||||||
|
def PathToTestFile( test_basename ):
|
||||||
|
return os.path.join( PathToTestDataDir(), test_basename )
|
||||||
|
|
||||||
|
|
||||||
@with_setup( Setup )
|
@with_setup( Setup )
|
||||||
def GetCompletions_IdentifierCompleter_Works_test():
|
def GetCompletions_IdentifierCompleter_Works_test():
|
||||||
app = TestApp( ycmd.app )
|
app = TestApp( ycmd.app )
|
||||||
@ -91,7 +102,7 @@ def GetCompletions_IdentifierCompleter_Works_test():
|
|||||||
|
|
||||||
|
|
||||||
@with_setup( Setup )
|
@with_setup( Setup )
|
||||||
def GetCompletions_ClangCompleter_Works_test():
|
def GetCompletions_ClangCompleter_WorksWithExplicitFlags_test():
|
||||||
app = TestApp( ycmd.app )
|
app = TestApp( ycmd.app )
|
||||||
contents = """
|
contents = """
|
||||||
struct Foo {
|
struct Foo {
|
||||||
@ -122,6 +133,45 @@ int main()
|
|||||||
CompletionEntryMatcher( 'y' ) ) )
|
CompletionEntryMatcher( 'y' ) ) )
|
||||||
|
|
||||||
|
|
||||||
|
@with_setup( Setup )
|
||||||
|
def GetCompletions_ClangCompleter_UnknownExtraConfException_test():
|
||||||
|
app = TestApp( ycmd.app )
|
||||||
|
filepath = PathToTestFile( 'basic.cpp' )
|
||||||
|
completion_data = BuildRequest( filepath = filepath,
|
||||||
|
filetype = 'cpp',
|
||||||
|
contents = open( filepath ).read(),
|
||||||
|
force_semantic = True )
|
||||||
|
|
||||||
|
response = app.post_json( '/completions',
|
||||||
|
completion_data,
|
||||||
|
expect_errors = True )
|
||||||
|
|
||||||
|
eq_( response.status_code, httplib.INTERNAL_SERVER_ERROR )
|
||||||
|
assert_that( response.json,
|
||||||
|
has_entry( 'exception',
|
||||||
|
has_entry( 'TYPE', UnknownExtraConf.__name__ ) ) )
|
||||||
|
|
||||||
|
|
||||||
|
@with_setup( Setup )
|
||||||
|
def GetCompletions_ClangCompleter_WorksWhenExtraConfExplicitlyAllowed_test():
|
||||||
|
app = TestApp( ycmd.app )
|
||||||
|
app.post_json( '/load_extra_conf_file',
|
||||||
|
{ 'filepath': PathToTestFile( '.ycm_extra_conf.py' ) } )
|
||||||
|
|
||||||
|
filepath = PathToTestFile( 'basic.cpp' )
|
||||||
|
completion_data = BuildRequest( filepath = filepath,
|
||||||
|
filetype = 'cpp',
|
||||||
|
contents = open( filepath ).read(),
|
||||||
|
line_num = 10,
|
||||||
|
column_num = 6,
|
||||||
|
start_column = 6 )
|
||||||
|
|
||||||
|
results = app.post_json( '/completions', completion_data ).json
|
||||||
|
assert_that( results, has_items( CompletionEntryMatcher( 'c' ),
|
||||||
|
CompletionEntryMatcher( 'x' ),
|
||||||
|
CompletionEntryMatcher( 'y' ) ) )
|
||||||
|
|
||||||
|
|
||||||
@with_setup( Setup )
|
@with_setup( Setup )
|
||||||
def GetCompletions_ForceSemantic_Works_test():
|
def GetCompletions_ForceSemantic_Works_test():
|
||||||
app = TestApp( ycmd.app )
|
app = TestApp( ycmd.app )
|
||||||
|
13
python/ycm/server/tests/testdata/basic.cpp
vendored
Normal file
13
python/ycm/server/tests/testdata/basic.cpp
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
struct Foo {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
char c;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Foo foo;
|
||||||
|
// The location after the dot is line 11, col 7
|
||||||
|
foo.
|
||||||
|
}
|
||||||
|
|
@ -36,17 +36,19 @@ utils.AddThirdPartyFoldersToSysPath()
|
|||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import bottle
|
import bottle
|
||||||
|
import argparse
|
||||||
|
import httplib
|
||||||
from bottle import run, request, response
|
from bottle import run, request, response
|
||||||
import server_state
|
import server_state
|
||||||
from ycm import user_options_store
|
from ycm import user_options_store
|
||||||
from ycm.server.responses import BuildExceptionResponse
|
from ycm.server.responses import BuildExceptionResponse
|
||||||
import argparse
|
from ycm import extra_conf_store
|
||||||
import httplib
|
|
||||||
|
|
||||||
# num bytes for the request body buffer; request.json only works if the request
|
# num bytes for the request body buffer; request.json only works if the request
|
||||||
# size is less than this
|
# size is less than this
|
||||||
bottle.Request.MEMFILE_MAX = 300 * 1024
|
bottle.Request.MEMFILE_MAX = 300 * 1024
|
||||||
|
|
||||||
|
# TODO: rename these to _lower_case
|
||||||
SERVER_STATE = None
|
SERVER_STATE = None
|
||||||
LOGGER = None
|
LOGGER = None
|
||||||
app = bottle.Bottle()
|
app = bottle.Bottle()
|
||||||
@ -72,7 +74,6 @@ def EventNotification():
|
|||||||
return _JsonResponse( response_data )
|
return _JsonResponse( response_data )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.post( '/run_completer_command' )
|
@app.post( '/run_completer_command' )
|
||||||
def RunCompleterCommand():
|
def RunCompleterCommand():
|
||||||
LOGGER.info( 'Received command request' )
|
LOGGER.info( 'Received command request' )
|
||||||
@ -141,6 +142,13 @@ def GetDetailedDiagnostic():
|
|||||||
return _JsonResponse( completer.GetDetailedDiagnostic( request_data ) )
|
return _JsonResponse( completer.GetDetailedDiagnostic( request_data ) )
|
||||||
|
|
||||||
|
|
||||||
|
@app.post( '/load_extra_conf_file' )
|
||||||
|
def LoadExtraConfFile():
|
||||||
|
LOGGER.info( 'Received extra conf load request' )
|
||||||
|
request_data = request.json
|
||||||
|
extra_conf_store.Load( request_data[ 'filepath' ], force = True )
|
||||||
|
|
||||||
|
|
||||||
@app.post( '/debug_info' )
|
@app.post( '/debug_info' )
|
||||||
def DebugInfo():
|
def DebugInfo():
|
||||||
# This can't be at the top level because of possible extra conf preload
|
# This can't be at the top level because of possible extra conf preload
|
||||||
@ -167,13 +175,19 @@ def DebugInfo():
|
|||||||
# The type of the param is Bottle.HTTPError
|
# The type of the param is Bottle.HTTPError
|
||||||
@app.error( httplib.INTERNAL_SERVER_ERROR )
|
@app.error( httplib.INTERNAL_SERVER_ERROR )
|
||||||
def ErrorHandler( httperror ):
|
def ErrorHandler( httperror ):
|
||||||
return _JsonResponse( BuildExceptionResponse( str( httperror.exception ),
|
return _JsonResponse( BuildExceptionResponse( httperror.exception,
|
||||||
httperror.traceback ) )
|
httperror.traceback ) )
|
||||||
|
|
||||||
|
|
||||||
def _JsonResponse( data ):
|
def _JsonResponse( data ):
|
||||||
response.set_header( 'Content-Type', 'application/json' )
|
response.set_header( 'Content-Type', 'application/json' )
|
||||||
return json.dumps( data )
|
return json.dumps( data, default = _UniversalSerialize )
|
||||||
|
|
||||||
|
|
||||||
|
def _UniversalSerialize( obj ):
|
||||||
|
serialized = obj.__dict__.copy()
|
||||||
|
serialized[ 'TYPE' ] = type( obj ).__name__
|
||||||
|
return serialized
|
||||||
|
|
||||||
|
|
||||||
def _GetCompleterForRequestData( request_data ):
|
def _GetCompleterForRequestData( request_data ):
|
||||||
@ -205,6 +219,7 @@ def SetServerStateToDefaults():
|
|||||||
LOGGER = logging.getLogger( __name__ )
|
LOGGER = logging.getLogger( __name__ )
|
||||||
user_options_store.LoadDefaults()
|
user_options_store.LoadDefaults()
|
||||||
SERVER_STATE = server_state.ServerState( user_options_store.GetAll() )
|
SERVER_STATE = server_state.ServerState( user_options_store.GetAll() )
|
||||||
|
extra_conf_store.Reset()
|
||||||
|
|
||||||
|
|
||||||
def Main():
|
def Main():
|
||||||
|
Loading…
Reference in New Issue
Block a user