We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
exit code not correct if importing ycm_core in global config fails
Hi,

I am not sure this is a real bug, but I encountered this while implementing handling of exit code in `emacs-ycmd`.

I had a `import ycm_core` in my global config. If importing fails there the line with `code = CompatibleWithCurrentCore()` in `__main__.py` will never be reached to return the correct exit code and then I just get an exit code 1.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ycmd/extra_conf_store.py`
Content:
```
1 # Copyright (C) 2011, 2012 Google Inc.
2 #
3 # This file is part of ycmd.
4 #
5 # ycmd is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # ycmd is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with ycmd.  If not, see <http://www.gnu.org/licenses/>.
17 
18 # NOTE: This module is used as a Singleton
19 
20 from __future__ import unicode_literals
21 from __future__ import print_function
22 from __future__ import division
23 from __future__ import absolute_import
24 from future import standard_library
25 standard_library.install_aliases()
26 from builtins import *  # noqa
27 
28 import os
29 import random
30 import string
31 import sys
32 import logging
33 from threading import Lock
34 from ycmd import user_options_store
35 from ycmd.responses import UnknownExtraConf, YCM_EXTRA_CONF_FILENAME
36 from ycmd.utils import LoadPythonSource, PathsToAllParentFolders
37 from fnmatch import fnmatch
38 
39 
40 # Singleton variables
41 _module_for_module_file = {}
42 _module_for_module_file_lock = Lock()
43 _module_file_for_source_file = {}
44 _module_file_for_source_file_lock = Lock()
45 
46 
47 def Reset():
48   global _module_for_module_file, _module_file_for_source_file
49   _module_for_module_file = {}
50   _module_file_for_source_file = {}
51 
52 
53 def ModuleForSourceFile( filename ):
54   return Load( ModuleFileForSourceFile( filename ) )
55 
56 
57 def ModuleFileForSourceFile( filename ):
58   """This will try all files returned by _ExtraConfModuleSourceFilesForFile in
59   order and return the filename of the first module that was allowed to load.
60   If no module was found or allowed to load, None is returned."""
61 
62   with _module_file_for_source_file_lock:
63     if filename not in _module_file_for_source_file:
64       for module_file in _ExtraConfModuleSourceFilesForFile( filename ):
65         if Load( module_file ):
66           _module_file_for_source_file[ filename ] = module_file
67           break
68 
69   return _module_file_for_source_file.setdefault( filename )
70 
71 
72 def CallGlobalExtraConfYcmCorePreloadIfExists():
73   _CallGlobalExtraConfMethod( 'YcmCorePreload' )
74 
75 
76 def Shutdown():
77   # VimClose is for the sake of backwards compatibility; it's a no-op when it
78   # doesn't exist.
79   _CallGlobalExtraConfMethod( 'VimClose' )
80   _CallGlobalExtraConfMethod( 'Shutdown' )
81 
82 
83 def _CallGlobalExtraConfMethod( function_name ):
84   logger = _Logger()
85   global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()
86   if not ( global_ycm_extra_conf and
87            os.path.exists( global_ycm_extra_conf ) ):
88     logger.debug( 'No global extra conf, not calling method ' + function_name )
89     return
90 
91   module = Load( global_ycm_extra_conf, force = True )
92   if not module or not hasattr( module, function_name ):
93     logger.debug( 'Global extra conf not loaded or no function ' +
94                   function_name )
95     return
96 
97   logger.info( 'Calling global extra conf method {0} on conf file {1}'.format(
98       function_name, global_ycm_extra_conf ) )
99   getattr( module, function_name )()
100 
101 
102 def Disable( module_file ):
103   """Disables the loading of a module for the current session."""
104   with _module_for_module_file_lock:
105     _module_for_module_file[ module_file ] = None
106 
107 
108 def _ShouldLoad( module_file ):
109   """Checks if a module is safe to be loaded. By default this will try to
110   decide using a white-/blacklist and ask the user for confirmation as a
111   fallback."""
112 
113   if ( module_file == _GlobalYcmExtraConfFileLocation() or
114        not user_options_store.Value( 'confirm_extra_conf' ) ):
115     return True
116 
117   globlist = user_options_store.Value( 'extra_conf_globlist' )
118   for glob in globlist:
119     is_blacklisted = glob[0] == '!'
120     if _MatchesGlobPattern( module_file, glob.lstrip('!') ):
121       return not is_blacklisted
122 
123   raise UnknownExtraConf( module_file )
124 
125 
126 def Load( module_file, force = False ):
127   """Load and return the module contained in a file.
128   Using force = True the module will be loaded regardless
129   of the criteria in _ShouldLoad.
130   This will return None if the module was not allowed to be loaded."""
131 
132   if not module_file:
133     return None
134 
135   if not force:
136     with _module_for_module_file_lock:
137       if module_file in _module_for_module_file:
138         return _module_for_module_file[ module_file ]
139 
140     if not _ShouldLoad( module_file ):
141       Disable( module_file )
142       return None
143 
144   # This has to be here because a long time ago, the ycm_extra_conf.py files
145   # used to import clang_helpers.py from the cpp folder. This is not needed
146   # anymore, but there are a lot of old ycm_extra_conf.py files that we don't
147   # want to break.
148   sys.path.insert( 0, _PathToCppCompleterFolder() )
149 
150   # By default, the Python interpreter compiles source files into bytecode to
151   # load them faster next time they are run. These *.pyc files are generated
152   # along the source files prior to Python 3.2 or in a __pycache__ folder for
153   # newer versions. We disable the generation of these files when loading
154   # ycm_extra_conf.py files as users do not want them inside their projects.
155   # The drawback is negligible since ycm_extra_conf.py files are generally small
156   # files thus really fast to compile and only loaded once by editing session.
157   old_dont_write_bytecode = sys.dont_write_bytecode
158   sys.dont_write_bytecode = True
159   try:
160     module = LoadPythonSource( _RandomName(), module_file )
161   finally:
162     sys.dont_write_bytecode = old_dont_write_bytecode
163 
164   del sys.path[ 0 ]
165 
166   with _module_for_module_file_lock:
167     _module_for_module_file[ module_file ] = module
168   return module
169 
170 
171 def _MatchesGlobPattern( filename, glob ):
172   """Returns true if a filename matches a given pattern. A '~' in glob will be
173   expanded to the home directory and checking will be performed using absolute
174   paths. See the documentation of fnmatch for the supported patterns."""
175 
176   abspath = os.path.abspath( filename )
177   return fnmatch( abspath, os.path.abspath( os.path.expanduser( glob ) ) )
178 
179 
180 def _ExtraConfModuleSourceFilesForFile( filename ):
181   """For a given filename, search all parent folders for YCM_EXTRA_CONF_FILENAME
182   files that will compute the flags necessary to compile the file.
183   If _GlobalYcmExtraConfFileLocation() exists it is returned as a fallback."""
184 
185   for folder in PathsToAllParentFolders( filename ):
186     candidate = os.path.join( folder, YCM_EXTRA_CONF_FILENAME )
187     if os.path.exists( candidate ):
188       yield candidate
189   global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()
190   if ( global_ycm_extra_conf
191        and os.path.exists( global_ycm_extra_conf ) ):
192     yield global_ycm_extra_conf
193 
194 
195 def _PathToCppCompleterFolder():
196   """Returns the path to the 'cpp' completer folder. This is necessary
197   because ycm_extra_conf files need it on the path."""
198   return os.path.join( _DirectoryOfThisScript(), 'completers', 'cpp' )
199 
200 
201 def _DirectoryOfThisScript():
202   return os.path.dirname( os.path.abspath( __file__ ) )
203 
204 
205 def _RandomName():
206   """Generates a random module name."""
207   return ''.join( random.choice( string.ascii_lowercase ) for x in range( 15 ) )
208 
209 
210 def _GlobalYcmExtraConfFileLocation():
211   return os.path.expanduser(
212     user_options_store.Value( 'global_ycm_extra_conf' ) )
213 
214 
215 def _Logger():
216   return logging.getLogger( __name__ )
217
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ycmd/extra_conf_store.py b/ycmd/extra_conf_store.py
--- a/ycmd/extra_conf_store.py
+++ b/ycmd/extra_conf_store.py
@@ -1,4 +1,5 @@
-# Copyright (C) 2011, 2012 Google Inc.
+# Copyright (C) 2011-2012 Google Inc.
+#               2016      ycmd contributors
 #
 # This file is part of ycmd.
 #
@@ -37,6 +38,8 @@
 from fnmatch import fnmatch
 
 
+_logger = logging.getLogger( __name__ )
+
 # Singleton variables
 _module_for_module_file = {}
 _module_for_module_file_lock = Lock()
@@ -81,22 +84,34 @@
 
 
 def _CallGlobalExtraConfMethod( function_name ):
-  logger = _Logger()
   global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()
   if not ( global_ycm_extra_conf and
            os.path.exists( global_ycm_extra_conf ) ):
-    logger.debug( 'No global extra conf, not calling method ' + function_name )
+    _logger.debug( 'No global extra conf, '
+                   'not calling method {0}'.format( function_name ) )
+    return
+
+  try:
+    module = Load( global_ycm_extra_conf, force = True )
+  except Exception:
+    _logger.exception( 'Error occurred while loading '
+                       'global extra conf {0}'.format( global_ycm_extra_conf ) )
     return
 
-  module = Load( global_ycm_extra_conf, force = True )
   if not module or not hasattr( module, function_name ):
-    logger.debug( 'Global extra conf not loaded or no function ' +
-                  function_name )
+    _logger.debug( 'Global extra conf not loaded or no function ' +
+                   function_name )
     return
 
-  logger.info( 'Calling global extra conf method {0} on conf file {1}'.format(
-      function_name, global_ycm_extra_conf ) )
-  getattr( module, function_name )()
+  try:
+    _logger.info(
+      'Calling global extra conf method {0} '
+      'on conf file {1}'.format( function_name, global_ycm_extra_conf ) )
+    getattr( module, function_name )()
+  except Exception:
+    _logger.exception(
+      'Error occurred while calling global extra conf method {0} '
+      'on conf file {1}'.format( function_name, global_ycm_extra_conf ) )
 
 
 def Disable( module_file ):
@@ -210,7 +225,3 @@
 def _GlobalYcmExtraConfFileLocation():
   return os.path.expanduser(
     user_options_store.Value( 'global_ycm_extra_conf' ) )
-
-
-def _Logger():
-  return logging.getLogger( __name__ )

{"golden_diff": "diff --git a/ycmd/extra_conf_store.py b/ycmd/extra_conf_store.py\n--- a/ycmd/extra_conf_store.py\n+++ b/ycmd/extra_conf_store.py\n@@ -1,4 +1,5 @@\n-# Copyright (C) 2011, 2012 Google Inc.\n+# Copyright (C) 2011-2012 Google Inc.\n+#               2016      ycmd contributors\n #\n # This file is part of ycmd.\n #\n@@ -37,6 +38,8 @@\n from fnmatch import fnmatch\n \n \n+_logger = logging.getLogger( __name__ )\n+\n # Singleton variables\n _module_for_module_file = {}\n _module_for_module_file_lock = Lock()\n@@ -81,22 +84,34 @@\n \n \n def _CallGlobalExtraConfMethod( function_name ):\n-  logger = _Logger()\n   global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()\n   if not ( global_ycm_extra_conf and\n            os.path.exists( global_ycm_extra_conf ) ):\n-    logger.debug( 'No global extra conf, not calling method ' + function_name )\n+    _logger.debug( 'No global extra conf, '\n+                   'not calling method {0}'.format( function_name ) )\n+    return\n+\n+  try:\n+    module = Load( global_ycm_extra_conf, force = True )\n+  except Exception:\n+    _logger.exception( 'Error occurred while loading '\n+                       'global extra conf {0}'.format( global_ycm_extra_conf ) )\n     return\n \n-  module = Load( global_ycm_extra_conf, force = True )\n   if not module or not hasattr( module, function_name ):\n-    logger.debug( 'Global extra conf not loaded or no function ' +\n-                  function_name )\n+    _logger.debug( 'Global extra conf not loaded or no function ' +\n+                   function_name )\n     return\n \n-  logger.info( 'Calling global extra conf method {0} on conf file {1}'.format(\n-      function_name, global_ycm_extra_conf ) )\n-  getattr( module, function_name )()\n+  try:\n+    _logger.info(\n+      'Calling global extra conf method {0} '\n+      'on conf file {1}'.format( function_name, global_ycm_extra_conf ) )\n+    getattr( module, function_name )()\n+  except Exception:\n+    _logger.exception(\n+      'Error occurred while calling global extra conf method {0} '\n+      'on conf file {1}'.format( function_name, global_ycm_extra_conf ) )\n \n \n def Disable( module_file ):\n@@ -210,7 +225,3 @@\n def _GlobalYcmExtraConfFileLocation():\n   return os.path.expanduser(\n     user_options_store.Value( 'global_ycm_extra_conf' ) )\n-\n-\n-def _Logger():\n-  return logging.getLogger( __name__ )\n", "issue": "exit code not correct if importing ycm_core in global config fails\nHi,\n\nI am not sure this is a real bug, but I encountered this while implementing handling of exit code in `emacs-ycmd`.\n\nI had a `import ycm_core` in my global config. If importing fails there the line with `code = CompatibleWithCurrentCore()` in `__main__.py` will never be reached to return the correct exit code and then I just get an exit code 1.\n\n", "before_files": [{"content": "# Copyright (C) 2011, 2012 Google Inc.\n#\n# This file is part of ycmd.\n#\n# ycmd is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# ycmd is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with ycmd.  If not, see <http://www.gnu.org/licenses/>.\n\n# NOTE: This module is used as a Singleton\n\nfrom __future__ import unicode_literals\nfrom __future__ import print_function\nfrom __future__ import division\nfrom __future__ import absolute_import\nfrom future import standard_library\nstandard_library.install_aliases()\nfrom builtins import *  # noqa\n\nimport os\nimport random\nimport string\nimport sys\nimport logging\nfrom threading import Lock\nfrom ycmd import user_options_store\nfrom ycmd.responses import UnknownExtraConf, YCM_EXTRA_CONF_FILENAME\nfrom ycmd.utils import LoadPythonSource, PathsToAllParentFolders\nfrom fnmatch import fnmatch\n\n\n# Singleton variables\n_module_for_module_file = {}\n_module_for_module_file_lock = Lock()\n_module_file_for_source_file = {}\n_module_file_for_source_file_lock = Lock()\n\n\ndef Reset():\n  global _module_for_module_file, _module_file_for_source_file\n  _module_for_module_file = {}\n  _module_file_for_source_file = {}\n\n\ndef ModuleForSourceFile( filename ):\n  return Load( ModuleFileForSourceFile( filename ) )\n\n\ndef ModuleFileForSourceFile( filename ):\n  \"\"\"This will try all files returned by _ExtraConfModuleSourceFilesForFile in\n  order and return the filename of the first module that was allowed to load.\n  If no module was found or allowed to load, None is returned.\"\"\"\n\n  with _module_file_for_source_file_lock:\n    if filename not in _module_file_for_source_file:\n      for module_file in _ExtraConfModuleSourceFilesForFile( filename ):\n        if Load( module_file ):\n          _module_file_for_source_file[ filename ] = module_file\n          break\n\n  return _module_file_for_source_file.setdefault( filename )\n\n\ndef CallGlobalExtraConfYcmCorePreloadIfExists():\n  _CallGlobalExtraConfMethod( 'YcmCorePreload' )\n\n\ndef Shutdown():\n  # VimClose is for the sake of backwards compatibility; it's a no-op when it\n  # doesn't exist.\n  _CallGlobalExtraConfMethod( 'VimClose' )\n  _CallGlobalExtraConfMethod( 'Shutdown' )\n\n\ndef _CallGlobalExtraConfMethod( function_name ):\n  logger = _Logger()\n  global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()\n  if not ( global_ycm_extra_conf and\n           os.path.exists( global_ycm_extra_conf ) ):\n    logger.debug( 'No global extra conf, not calling method ' + function_name )\n    return\n\n  module = Load( global_ycm_extra_conf, force = True )\n  if not module or not hasattr( module, function_name ):\n    logger.debug( 'Global extra conf not loaded or no function ' +\n                  function_name )\n    return\n\n  logger.info( 'Calling global extra conf method {0} on conf file {1}'.format(\n      function_name, global_ycm_extra_conf ) )\n  getattr( module, function_name )()\n\n\ndef Disable( module_file ):\n  \"\"\"Disables the loading of a module for the current session.\"\"\"\n  with _module_for_module_file_lock:\n    _module_for_module_file[ module_file ] = None\n\n\ndef _ShouldLoad( module_file ):\n  \"\"\"Checks if a module is safe to be loaded. By default this will try to\n  decide using a white-/blacklist and ask the user for confirmation as a\n  fallback.\"\"\"\n\n  if ( module_file == _GlobalYcmExtraConfFileLocation() or\n       not user_options_store.Value( 'confirm_extra_conf' ) ):\n    return True\n\n  globlist = user_options_store.Value( 'extra_conf_globlist' )\n  for glob in globlist:\n    is_blacklisted = glob[0] == '!'\n    if _MatchesGlobPattern( module_file, glob.lstrip('!') ):\n      return not is_blacklisted\n\n  raise UnknownExtraConf( module_file )\n\n\ndef Load( module_file, force = False ):\n  \"\"\"Load and return the module contained in a file.\n  Using force = True the module will be loaded regardless\n  of the criteria in _ShouldLoad.\n  This will return None if the module was not allowed to be loaded.\"\"\"\n\n  if not module_file:\n    return None\n\n  if not force:\n    with _module_for_module_file_lock:\n      if module_file in _module_for_module_file:\n        return _module_for_module_file[ module_file ]\n\n    if not _ShouldLoad( module_file ):\n      Disable( module_file )\n      return None\n\n  # This has to be here because a long time ago, the ycm_extra_conf.py files\n  # used to import clang_helpers.py from the cpp folder. This is not needed\n  # anymore, but there are a lot of old ycm_extra_conf.py files that we don't\n  # want to break.\n  sys.path.insert( 0, _PathToCppCompleterFolder() )\n\n  # By default, the Python interpreter compiles source files into bytecode to\n  # load them faster next time they are run. These *.pyc files are generated\n  # along the source files prior to Python 3.2 or in a __pycache__ folder for\n  # newer versions. We disable the generation of these files when loading\n  # ycm_extra_conf.py files as users do not want them inside their projects.\n  # The drawback is negligible since ycm_extra_conf.py files are generally small\n  # files thus really fast to compile and only loaded once by editing session.\n  old_dont_write_bytecode = sys.dont_write_bytecode\n  sys.dont_write_bytecode = True\n  try:\n    module = LoadPythonSource( _RandomName(), module_file )\n  finally:\n    sys.dont_write_bytecode = old_dont_write_bytecode\n\n  del sys.path[ 0 ]\n\n  with _module_for_module_file_lock:\n    _module_for_module_file[ module_file ] = module\n  return module\n\n\ndef _MatchesGlobPattern( filename, glob ):\n  \"\"\"Returns true if a filename matches a given pattern. A '~' in glob will be\n  expanded to the home directory and checking will be performed using absolute\n  paths. See the documentation of fnmatch for the supported patterns.\"\"\"\n\n  abspath = os.path.abspath( filename )\n  return fnmatch( abspath, os.path.abspath( os.path.expanduser( glob ) ) )\n\n\ndef _ExtraConfModuleSourceFilesForFile( filename ):\n  \"\"\"For a given filename, search all parent folders for YCM_EXTRA_CONF_FILENAME\n  files that will compute the flags necessary to compile the file.\n  If _GlobalYcmExtraConfFileLocation() exists it is returned as a fallback.\"\"\"\n\n  for folder in PathsToAllParentFolders( filename ):\n    candidate = os.path.join( folder, YCM_EXTRA_CONF_FILENAME )\n    if os.path.exists( candidate ):\n      yield candidate\n  global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()\n  if ( global_ycm_extra_conf\n       and os.path.exists( global_ycm_extra_conf ) ):\n    yield global_ycm_extra_conf\n\n\ndef _PathToCppCompleterFolder():\n  \"\"\"Returns the path to the 'cpp' completer folder. This is necessary\n  because ycm_extra_conf files need it on the path.\"\"\"\n  return os.path.join( _DirectoryOfThisScript(), 'completers', 'cpp' )\n\n\ndef _DirectoryOfThisScript():\n  return os.path.dirname( os.path.abspath( __file__ ) )\n\n\ndef _RandomName():\n  \"\"\"Generates a random module name.\"\"\"\n  return ''.join( random.choice( string.ascii_lowercase ) for x in range( 15 ) )\n\n\ndef _GlobalYcmExtraConfFileLocation():\n  return os.path.expanduser(\n    user_options_store.Value( 'global_ycm_extra_conf' ) )\n\n\ndef _Logger():\n  return logging.getLogger( __name__ )\n", "path": "ycmd/extra_conf_store.py"}], "after_files": [{"content": "# Copyright (C) 2011-2012 Google Inc.\n#               2016      ycmd contributors\n#\n# This file is part of ycmd.\n#\n# ycmd is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# ycmd is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with ycmd.  If not, see <http://www.gnu.org/licenses/>.\n\n# NOTE: This module is used as a Singleton\n\nfrom __future__ import unicode_literals\nfrom __future__ import print_function\nfrom __future__ import division\nfrom __future__ import absolute_import\nfrom future import standard_library\nstandard_library.install_aliases()\nfrom builtins import *  # noqa\n\nimport os\nimport random\nimport string\nimport sys\nimport logging\nfrom threading import Lock\nfrom ycmd import user_options_store\nfrom ycmd.responses import UnknownExtraConf, YCM_EXTRA_CONF_FILENAME\nfrom ycmd.utils import LoadPythonSource, PathsToAllParentFolders\nfrom fnmatch import fnmatch\n\n\n_logger = logging.getLogger( __name__ )\n\n# Singleton variables\n_module_for_module_file = {}\n_module_for_module_file_lock = Lock()\n_module_file_for_source_file = {}\n_module_file_for_source_file_lock = Lock()\n\n\ndef Reset():\n  global _module_for_module_file, _module_file_for_source_file\n  _module_for_module_file = {}\n  _module_file_for_source_file = {}\n\n\ndef ModuleForSourceFile( filename ):\n  return Load( ModuleFileForSourceFile( filename ) )\n\n\ndef ModuleFileForSourceFile( filename ):\n  \"\"\"This will try all files returned by _ExtraConfModuleSourceFilesForFile in\n  order and return the filename of the first module that was allowed to load.\n  If no module was found or allowed to load, None is returned.\"\"\"\n\n  with _module_file_for_source_file_lock:\n    if filename not in _module_file_for_source_file:\n      for module_file in _ExtraConfModuleSourceFilesForFile( filename ):\n        if Load( module_file ):\n          _module_file_for_source_file[ filename ] = module_file\n          break\n\n  return _module_file_for_source_file.setdefault( filename )\n\n\ndef CallGlobalExtraConfYcmCorePreloadIfExists():\n  _CallGlobalExtraConfMethod( 'YcmCorePreload' )\n\n\ndef Shutdown():\n  # VimClose is for the sake of backwards compatibility; it's a no-op when it\n  # doesn't exist.\n  _CallGlobalExtraConfMethod( 'VimClose' )\n  _CallGlobalExtraConfMethod( 'Shutdown' )\n\n\ndef _CallGlobalExtraConfMethod( function_name ):\n  global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()\n  if not ( global_ycm_extra_conf and\n           os.path.exists( global_ycm_extra_conf ) ):\n    _logger.debug( 'No global extra conf, '\n                   'not calling method {0}'.format( function_name ) )\n    return\n\n  try:\n    module = Load( global_ycm_extra_conf, force = True )\n  except Exception:\n    _logger.exception( 'Error occurred while loading '\n                       'global extra conf {0}'.format( global_ycm_extra_conf ) )\n    return\n\n  if not module or not hasattr( module, function_name ):\n    _logger.debug( 'Global extra conf not loaded or no function ' +\n                   function_name )\n    return\n\n  try:\n    _logger.info(\n      'Calling global extra conf method {0} '\n      'on conf file {1}'.format( function_name, global_ycm_extra_conf ) )\n    getattr( module, function_name )()\n  except Exception:\n    _logger.exception(\n      'Error occurred while calling global extra conf method {0} '\n      'on conf file {1}'.format( function_name, global_ycm_extra_conf ) )\n\n\ndef Disable( module_file ):\n  \"\"\"Disables the loading of a module for the current session.\"\"\"\n  with _module_for_module_file_lock:\n    _module_for_module_file[ module_file ] = None\n\n\ndef _ShouldLoad( module_file ):\n  \"\"\"Checks if a module is safe to be loaded. By default this will try to\n  decide using a white-/blacklist and ask the user for confirmation as a\n  fallback.\"\"\"\n\n  if ( module_file == _GlobalYcmExtraConfFileLocation() or\n       not user_options_store.Value( 'confirm_extra_conf' ) ):\n    return True\n\n  globlist = user_options_store.Value( 'extra_conf_globlist' )\n  for glob in globlist:\n    is_blacklisted = glob[0] == '!'\n    if _MatchesGlobPattern( module_file, glob.lstrip('!') ):\n      return not is_blacklisted\n\n  raise UnknownExtraConf( module_file )\n\n\ndef Load( module_file, force = False ):\n  \"\"\"Load and return the module contained in a file.\n  Using force = True the module will be loaded regardless\n  of the criteria in _ShouldLoad.\n  This will return None if the module was not allowed to be loaded.\"\"\"\n\n  if not module_file:\n    return None\n\n  if not force:\n    with _module_for_module_file_lock:\n      if module_file in _module_for_module_file:\n        return _module_for_module_file[ module_file ]\n\n    if not _ShouldLoad( module_file ):\n      Disable( module_file )\n      return None\n\n  # This has to be here because a long time ago, the ycm_extra_conf.py files\n  # used to import clang_helpers.py from the cpp folder. This is not needed\n  # anymore, but there are a lot of old ycm_extra_conf.py files that we don't\n  # want to break.\n  sys.path.insert( 0, _PathToCppCompleterFolder() )\n\n  # By default, the Python interpreter compiles source files into bytecode to\n  # load them faster next time they are run. These *.pyc files are generated\n  # along the source files prior to Python 3.2 or in a __pycache__ folder for\n  # newer versions. We disable the generation of these files when loading\n  # ycm_extra_conf.py files as users do not want them inside their projects.\n  # The drawback is negligible since ycm_extra_conf.py files are generally small\n  # files thus really fast to compile and only loaded once by editing session.\n  old_dont_write_bytecode = sys.dont_write_bytecode\n  sys.dont_write_bytecode = True\n  try:\n    module = LoadPythonSource( _RandomName(), module_file )\n  finally:\n    sys.dont_write_bytecode = old_dont_write_bytecode\n\n  del sys.path[ 0 ]\n\n  with _module_for_module_file_lock:\n    _module_for_module_file[ module_file ] = module\n  return module\n\n\ndef _MatchesGlobPattern( filename, glob ):\n  \"\"\"Returns true if a filename matches a given pattern. A '~' in glob will be\n  expanded to the home directory and checking will be performed using absolute\n  paths. See the documentation of fnmatch for the supported patterns.\"\"\"\n\n  abspath = os.path.abspath( filename )\n  return fnmatch( abspath, os.path.abspath( os.path.expanduser( glob ) ) )\n\n\ndef _ExtraConfModuleSourceFilesForFile( filename ):\n  \"\"\"For a given filename, search all parent folders for YCM_EXTRA_CONF_FILENAME\n  files that will compute the flags necessary to compile the file.\n  If _GlobalYcmExtraConfFileLocation() exists it is returned as a fallback.\"\"\"\n\n  for folder in PathsToAllParentFolders( filename ):\n    candidate = os.path.join( folder, YCM_EXTRA_CONF_FILENAME )\n    if os.path.exists( candidate ):\n      yield candidate\n  global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()\n  if ( global_ycm_extra_conf\n       and os.path.exists( global_ycm_extra_conf ) ):\n    yield global_ycm_extra_conf\n\n\ndef _PathToCppCompleterFolder():\n  \"\"\"Returns the path to the 'cpp' completer folder. This is necessary\n  because ycm_extra_conf files need it on the path.\"\"\"\n  return os.path.join( _DirectoryOfThisScript(), 'completers', 'cpp' )\n\n\ndef _DirectoryOfThisScript():\n  return os.path.dirname( os.path.abspath( __file__ ) )\n\n\ndef _RandomName():\n  \"\"\"Generates a random module name.\"\"\"\n  return ''.join( random.choice( string.ascii_lowercase ) for x in range( 15 ) )\n\n\ndef _GlobalYcmExtraConfFileLocation():\n  return os.path.expanduser(\n    user_options_store.Value( 'global_ycm_extra_conf' ) )\n", "path": "ycmd/extra_conf_store.py"}]}