Zine

open source content publishing system


source: scripts/build-event-map @ 1279:088d2f519391

Revision 1279:088d2f519391, 3.9 KB checked in by Georg Brandl <georg@…>, 2 years ago (diff)

Update copyright notices.

  • Property exe set to *
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3"""
4    Build the Event-Map
5    ~~~~~~~~~~~~~~~~~~~
6
7    Lists all the events send in a given Zine installation.
8
9    :copyright: (c) 2010 by the Zine Team, see AUTHORS for more details.
10    :license: BSD, see LICENSE for more details.
11"""
12import sys
13import os
14import linecache
15from optparse import OptionParser
16
17
18sys.path.append(os.path.dirname(__file__))
19from _init_zine import find_instance
20import zine
21
22
23try:
24    import _ast
25except ImportError:
26    can_build_eventmap = False
27else:
28    can_build_eventmap = True
29
30
31def build_eventmap(instance_folder):
32    app = zine.setup(instance_folder)
33    zine_root = os.path.realpath(os.path.dirname(zine.__file__))
34    searchpath = [(zine_root, '__builtin__')]
35
36    for plugin in app.plugins.itervalues():
37        path = os.path.realpath(plugin.path)
38        if os.path.commonprefix([zine_root, path]) != zine_root:
39            searchpath.append((plugin.path, plugin.name))
40
41    def walk_ast(ast):
42        if isinstance(ast, _ast.Call) and \
43           isinstance(ast.func, _ast.Name) and \
44           ast.func.id in ('emit_event', 'iter_listeners') and \
45           ast.args and \
46           isinstance(ast.args[0], _ast.Str):
47            yield ast.args[0].s, ast.func.lineno
48        for field in ast._fields or ():
49            value = getattr(ast, field)
50            if isinstance(value, (tuple, list)):
51                for node in value:
52                    if isinstance(node, _ast.AST):
53                        for item in walk_ast(node):
54                            yield item
55            elif isinstance(value, _ast.AST):
56                for item in walk_ast(value):
57                    yield item
58
59    def find_help(filename, lineno):
60        help_lines = []
61        lineno -= 1
62        while lineno > 0:
63            line = linecache.getline(filename, lineno).strip()
64            if line.startswith('#!'):
65                line = line[2:]
66                if line and line[0] == ' ':
67                    line = line[1:]
68                help_lines.append(line)
69            elif line:
70                break
71            lineno -= 1
72        return '\n'.join(reversed(help_lines)).decode('utf-8')
73
74    result = {}
75    for folder, prefix in searchpath:
76        offset = len(folder)
77        for dirpath, dirnames, filenames in os.walk(folder):
78            for filename in filenames:
79                if not filename.endswith('.py'):
80                    continue
81                filename = os.path.join(dirpath, filename)
82                shortname = filename[offset:]
83                ast = compile(''.join(linecache.getlines(filename)),
84                              filename, 'exec', 0x400)
85
86                for event, lineno in walk_ast(ast):
87                    help = find_help(filename, lineno)
88                    result.setdefault(event, []).append((prefix, shortname,
89                                                         lineno, help))
90
91    return result
92
93
94def main():
95    parser = OptionParser(usage='%prog')
96    parser.add_option('--instance', '-I', dest='instance',
97                      help='Use the path provided as Zine instance.')
98    options, args = parser.parse_args()
99    if args:
100        parser.error('incorrect number of arguments')
101    if not can_build_eventmap:
102        parser.error('This script requires Python 2.5')
103    instance = options.instance or find_instance()
104    if instance is None:
105        parser.error('instance not found.  Specify path to instance')
106
107    sys.stdout.write('Building Eventmap...')
108    sys.stdout.flush()
109    results = build_eventmap(instance)
110    sys.stdout.write('\rEvents emitted in %s:\n' % instance)
111
112    for event, occurrences in results.iteritems():
113        print
114        print '  ' + event
115        for prefix, filename, line, help in occurrences:
116            print '    in %s:%d (%s)' % (filename, line, prefix)
117            for line in help.splitlines():
118                print '      ' + line
119
120
121if __name__ == '__main__':
122    main()
Note: See TracBrowser for help on using the repository browser.