##// END OF EJS Templates
plugins: allow more custom keys into js configs
plugins: allow more custom keys into js configs

File last commit:

r98:2a8560e8
r98:2a8560e8
Show More
configurator.py
92 lines | 3.4 KiB | text/x-python | PythonLexer
import inspect
import logging
from pyramid.config import Configurator
log = logging.getLogger(__name__)
class InspectProxy(object):
"""
Proxy to the `inspect` module that allows us to use the pyramid include
mechanism for cythonized modules without source file.
"""
def _get_cyfunction_func_code(self, cyfunction):
"""
Unpack the `func_code` attribute of a cython function.
"""
if inspect.ismethod(cyfunction):
cyfunction = cyfunction.im_func
return getattr(cyfunction, 'func_code')
def getmodule(self, *args, **kwds):
"""
Simple proxy to `inspect.getmodule`.
"""
return inspect.getmodule(*args, **kwds)
def getsourcefile(self, obj):
"""
Proxy to `inspect.getsourcefile` or `inspect.getfile` depending on if
it's called to look up the source file that contains the magic pyramid
`includeme` callable.
For cythonized modules the source file may be deleted. Therefore we
return the result of `inspect.getfile` instead. In the case of the
`configurator.include` method this is OK, because the result is passed
to `os.path.dirname` which strips the file name. So it doesn't matter
if we return the path to the source file or another file in the same
directory.
"""
# Check if it's called to look up the source file that contains the
# magic pyramid `includeme` callable.
if getattr(obj, '__name__') == 'includeme':
try:
return inspect.getfile(obj)
except TypeError as e:
# Cython functions are not recognized as functions by the
# inspect module. We have to unpack the func_code attribute
# ourself.
if 'cyfunction' in e.message:
obj = self._get_cyfunction_func_code(obj)
return inspect.getfile(obj)
raise
else:
return inspect.getsourcefile(obj)
class CythonCompatConfigurator(Configurator):
"""
Customized configurator to replace the inspect class attribute with
a custom one that is cython compatible.
"""
inspect = InspectProxy()
def register_appenlight_plugin(config, plugin_name, plugin_config):
def register():
log.warning('Registering plugin: {}'.format(plugin_name))
if plugin_name not in config.registry.appenlight_plugins:
config.registry.appenlight_plugins[plugin_name] = {
'javascript': None,
'static': None,
'css': None,
'celery_tasks': None,
'celery_beats': None,
'fulltext_indexer': None,
'sqlalchemy_migrations': None,
'default_values_setter': None,
'header_html': None,
'resource_types': [],
'url_gen': None
}
config.registry.appenlight_plugins[plugin_name].update(
plugin_config)
# inform AE what kind of resource types we have available
# so we can avoid failing when a plugin is removed but data
# is still present in the db
if plugin_config.get('resource_types'):
config.registry.resource_types.extend(
plugin_config['resource_types'])
config.action('appenlight_plugin={}'.format(plugin_name), register)