|
@@
-1,92
+1,91
b''
|
|
1
|
import inspect
|
|
1
|
import inspect
|
|
2
|
import logging
|
|
2
|
import logging
|
|
3
|
|
|
3
|
|
|
4
|
from pyramid.config import Configurator
|
|
4
|
from pyramid.config import Configurator
|
|
5
|
|
|
5
|
|
|
6
|
log = logging.getLogger(__name__)
|
|
6
|
log = logging.getLogger(__name__)
|
|
7
|
|
|
7
|
|
|
8
|
class InspectProxy(object):
|
|
8
|
class InspectProxy(object):
|
|
9
|
"""
|
|
9
|
"""
|
|
10
|
Proxy to the `inspect` module that allows us to use the pyramid include
|
|
10
|
Proxy to the `inspect` module that allows us to use the pyramid include
|
|
11
|
mechanism for cythonized modules without source file.
|
|
11
|
mechanism for cythonized modules without source file.
|
|
12
|
"""
|
|
12
|
"""
|
|
13
|
|
|
13
|
|
|
14
|
def _get_cyfunction_func_code(self, cyfunction):
|
|
14
|
def _get_cyfunction_func_code(self, cyfunction):
|
|
15
|
"""
|
|
15
|
"""
|
|
16
|
Unpack the `func_code` attribute of a cython function.
|
|
16
|
Unpack the `func_code` attribute of a cython function.
|
|
17
|
"""
|
|
17
|
"""
|
|
18
|
if inspect.ismethod(cyfunction):
|
|
18
|
if inspect.ismethod(cyfunction):
|
|
19
|
cyfunction = cyfunction.im_func
|
|
19
|
cyfunction = cyfunction.im_func
|
|
20
|
return getattr(cyfunction, 'func_code')
|
|
20
|
return getattr(cyfunction, 'func_code')
|
|
21
|
|
|
21
|
|
|
22
|
def getmodule(self, *args, **kwds):
|
|
22
|
def getmodule(self, *args, **kwds):
|
|
23
|
"""
|
|
23
|
"""
|
|
24
|
Simple proxy to `inspect.getmodule`.
|
|
24
|
Simple proxy to `inspect.getmodule`.
|
|
25
|
"""
|
|
25
|
"""
|
|
26
|
return inspect.getmodule(*args, **kwds)
|
|
26
|
return inspect.getmodule(*args, **kwds)
|
|
27
|
|
|
27
|
|
|
28
|
def getsourcefile(self, obj):
|
|
28
|
def getsourcefile(self, obj):
|
|
29
|
"""
|
|
29
|
"""
|
|
30
|
Proxy to `inspect.getsourcefile` or `inspect.getfile` depending on if
|
|
30
|
Proxy to `inspect.getsourcefile` or `inspect.getfile` depending on if
|
|
31
|
it's called to look up the source file that contains the magic pyramid
|
|
31
|
it's called to look up the source file that contains the magic pyramid
|
|
32
|
`includeme` callable.
|
|
32
|
`includeme` callable.
|
|
33
|
|
|
33
|
|
|
34
|
For cythonized modules the source file may be deleted. Therefore we
|
|
34
|
For cythonized modules the source file may be deleted. Therefore we
|
|
35
|
return the result of `inspect.getfile` instead. In the case of the
|
|
35
|
return the result of `inspect.getfile` instead. In the case of the
|
|
36
|
`configurator.include` method this is OK, because the result is passed
|
|
36
|
`configurator.include` method this is OK, because the result is passed
|
|
37
|
to `os.path.dirname` which strips the file name. So it doesn't matter
|
|
37
|
to `os.path.dirname` which strips the file name. So it doesn't matter
|
|
38
|
if we return the path to the source file or another file in the same
|
|
38
|
if we return the path to the source file or another file in the same
|
|
39
|
directory.
|
|
39
|
directory.
|
|
40
|
"""
|
|
40
|
"""
|
|
41
|
# Check if it's called to look up the source file that contains the
|
|
41
|
# Check if it's called to look up the source file that contains the
|
|
42
|
# magic pyramid `includeme` callable.
|
|
42
|
# magic pyramid `includeme` callable.
|
|
43
|
if getattr(obj, '__name__') == 'includeme':
|
|
43
|
if getattr(obj, '__name__') == 'includeme':
|
|
44
|
try:
|
|
44
|
try:
|
|
45
|
return inspect.getfile(obj)
|
|
45
|
return inspect.getfile(obj)
|
|
46
|
except TypeError as e:
|
|
46
|
except TypeError as e:
|
|
47
|
# Cython functions are not recognized as functions by the
|
|
47
|
# Cython functions are not recognized as functions by the
|
|
48
|
# inspect module. We have to unpack the func_code attribute
|
|
48
|
# inspect module. We have to unpack the func_code attribute
|
|
49
|
# ourself.
|
|
49
|
# ourself.
|
|
50
|
if 'cyfunction' in e.message:
|
|
50
|
if 'cyfunction' in e.message:
|
|
51
|
obj = self._get_cyfunction_func_code(obj)
|
|
51
|
obj = self._get_cyfunction_func_code(obj)
|
|
52
|
return inspect.getfile(obj)
|
|
52
|
return inspect.getfile(obj)
|
|
53
|
raise
|
|
53
|
raise
|
|
54
|
else:
|
|
54
|
else:
|
|
55
|
return inspect.getsourcefile(obj)
|
|
55
|
return inspect.getsourcefile(obj)
|
|
56
|
|
|
56
|
|
|
57
|
|
|
57
|
|
|
58
|
class CythonCompatConfigurator(Configurator):
|
|
58
|
class CythonCompatConfigurator(Configurator):
|
|
59
|
"""
|
|
59
|
"""
|
|
60
|
Customized configurator to replace the inspect class attribute with
|
|
60
|
Customized configurator to replace the inspect class attribute with
|
|
61
|
a custom one that is cython compatible.
|
|
61
|
a custom one that is cython compatible.
|
|
62
|
"""
|
|
62
|
"""
|
|
63
|
inspect = InspectProxy()
|
|
63
|
inspect = InspectProxy()
|
|
64
|
|
|
64
|
|
|
65
|
|
|
65
|
|
|
66
|
def register_appenlight_plugin(config, plugin_name, plugin_config):
|
|
66
|
def register_appenlight_plugin(config, plugin_name, plugin_config):
|
|
67
|
def register():
|
|
67
|
def register():
|
|
68
|
log.warning('Registering plugin: {}'.format(plugin_name))
|
|
68
|
log.warning('Registering plugin: {}'.format(plugin_name))
|
|
69
|
if plugin_name not in config.registry.appenlight_plugins:
|
|
69
|
if plugin_name not in config.registry.appenlight_plugins:
|
|
70
|
config.registry.appenlight_plugins[plugin_name] = {
|
|
70
|
config.registry.appenlight_plugins[plugin_name] = {
|
|
71
|
'javascript': None,
|
|
71
|
'javascript': None,
|
|
72
|
'static': None,
|
|
72
|
'static': None,
|
|
73
|
'css': None,
|
|
73
|
'css': None,
|
|
74
|
'top_nav': None,
|
|
|
|
|
75
|
'celery_tasks': None,
|
|
74
|
'celery_tasks': None,
|
|
76
|
'celery_beats': None,
|
|
75
|
'celery_beats': None,
|
|
77
|
'fulltext_indexer': None,
|
|
76
|
'fulltext_indexer': None,
|
|
78
|
'sqlalchemy_migrations': None,
|
|
77
|
'sqlalchemy_migrations': None,
|
|
79
|
'default_values_setter': None,
|
|
78
|
'default_values_setter': None,
|
|
80
|
'resource_types': [],
|
|
79
|
'resource_types': [],
|
|
81
|
'url_gen': None
|
|
80
|
'url_gen': None
|
|
82
|
}
|
|
81
|
}
|
|
83
|
config.registry.appenlight_plugins[plugin_name].update(
|
|
82
|
config.registry.appenlight_plugins[plugin_name].update(
|
|
84
|
plugin_config)
|
|
83
|
plugin_config)
|
|
85
|
# inform AE what kind of resource types we have available
|
|
84
|
# inform AE what kind of resource types we have available
|
|
86
|
# so we can avoid failing when a plugin is removed but data
|
|
85
|
# so we can avoid failing when a plugin is removed but data
|
|
87
|
# is still present in the db
|
|
86
|
# is still present in the db
|
|
88
|
if plugin_config.get('resource_types'):
|
|
87
|
if plugin_config.get('resource_types'):
|
|
89
|
config.registry.resource_types.extend(
|
|
88
|
config.registry.resource_types.extend(
|
|
90
|
plugin_config['resource_types'])
|
|
89
|
plugin_config['resource_types'])
|
|
91
|
|
|
90
|
|
|
92
|
config.action('appenlight_plugin={}'.format(plugin_name), register)
|
|
91
|
config.action('appenlight_plugin={}'.format(plugin_name), register)
|