~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/controllers/__init__.py

  • Committer: Robey Pointer
  • Date: 2006-12-24 06:44:26 UTC
  • Revision ID: robey@lag.net-20061224064426-bedaid2zrw69igfg
initial homepage

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# You should have received a copy of the GNU General Public License
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
#
18
19
 
 
20
import logging
19
21
import re
 
22
import sys
20
23
import time
21
24
 
22
 
from paste.request import path_info_pop, parse_querystring
 
25
from configobj import ConfigObj
 
26
 
 
27
import turbogears
 
28
from turbogears import controllers
 
29
from cherrypy import HTTPRedirect, NotFound
 
30
 
 
31
my_config = ConfigObj('loggerhead.conf', encoding='utf-8')
 
32
extra_path = my_config.get('bzrpath', None)
 
33
if extra_path:
 
34
    sys.path.insert(0, extra_path)
23
35
 
24
36
from loggerhead import util
25
 
from loggerhead.templatefunctions import templatefunctions
26
 
from loggerhead.zptsupport import load_template
27
 
 
28
 
class BufferingWriter(object):
29
 
 
30
 
    def __init__(self, writefunc, buf_limit):
31
 
        self.bytes = 0
32
 
        self.buf = []
33
 
        self.buflen = 0
34
 
        self.writefunc = writefunc
35
 
        self.bytes_saved = 0
36
 
        self.buf_limit = buf_limit
37
 
 
38
 
    def flush(self):
39
 
        chunk = ''.join(self.buf)
40
 
        chunk = re.sub(r'\s*\n\s*', '\n', chunk)
41
 
        chunk = re.sub(r'[ \t]+', ' ', chunk)
42
 
        self.bytes_saved += self.buflen - len(chunk)
43
 
        self.writefunc(chunk)
44
 
        self.buf = []
45
 
        self.buflen = 0
46
 
 
47
 
    def write(self, data):
48
 
        self.buf.append(data)
49
 
        self.buflen += len(data)
50
 
        self.bytes += len(data)
51
 
        if self.buflen > self.buf_limit:
52
 
            self.flush()
53
 
 
54
 
class TemplatedBranchView(object):
55
 
 
56
 
    template_path = None
57
 
 
58
 
    def __init__(self, branch, history):
59
 
        self._branch = branch
60
 
        self._history = history
61
 
        self.log = branch.log
62
 
 
63
 
    def __call__(self, environ, start_response):
64
 
        z = time.time()
65
 
        h = self._history
66
 
        kw = dict(parse_querystring(environ))
67
 
        util.set_context(kw)
68
 
        args = []
69
 
        while 1:
70
 
            arg = path_info_pop(environ)
71
 
            if arg is None:
72
 
                break
73
 
            args.append(arg)
74
 
 
75
 
        vals = {
76
 
            'branch': self._branch,
 
37
from loggerhead.branchview import BranchView
 
38
from loggerhead.history import History
 
39
 
 
40
log = logging.getLogger("loggerhead.controllers")
 
41
 
 
42
 
 
43
def cherrypy_friendly(s):
 
44
    """
 
45
    convert a config section name into a name that pleases cherrypy.
 
46
    """
 
47
    return re.sub(r'[^\w\d_]', '_', s)
 
48
 
 
49
 
 
50
class Group (object):
 
51
    def __init__(self, name, config):
 
52
        self.name = name
 
53
        self.friendly_name = config.get('name', name)
 
54
        self.description = config.get('description', '')
 
55
        
 
56
        self._views = []
 
57
        for view_name in config.sections:
 
58
            log.debug('Configuring (group %r) branch %r...', name, view_name)
 
59
            c_view_name = cherrypy_friendly(view_name)
 
60
            view = BranchView(name, c_view_name, config[view_name])
 
61
            self._views.append(view)
 
62
            setattr(self, c_view_name, view)
 
63
    
 
64
    views = property(lambda self: self._views)
 
65
 
 
66
 
 
67
class Root (controllers.RootController):
 
68
    def __init__(self):
 
69
        global my_config
 
70
        self._groups = []
 
71
        for group_name in my_config.sections:
 
72
            # FIXME: clean out any non-python chars
 
73
            c_group_name = cherrypy_friendly(group_name)
 
74
            group = Group(c_group_name, my_config[group_name])
 
75
            self._groups.append(group)
 
76
            setattr(self, c_group_name, group)
 
77
        
 
78
    @turbogears.expose(template='loggerhead.templates.browse')
 
79
    def index(self):
 
80
        return {
 
81
            'groups': self._groups,
77
82
            'util': util,
78
 
            'history': h,
79
 
            'url': self._branch.context_url,
 
83
            'title': my_config.get('title', ''),
80
84
        }
81
 
        vals.update(templatefunctions)
82
 
        headers = {}
83
 
        vals.update(self.get_values(h, args, kw, headers))
84
 
 
85
 
        self.log.info('Getting information for %s: %r secs' % (
86
 
            self.__class__.__name__, time.time() - z,))
87
 
        if 'Content-Type' not in headers:
88
 
            headers['Content-Type'] = 'text/html'
89
 
        writer = start_response("200 OK", headers.items())
90
 
        template = load_template(self.template_path)
91
 
        z = time.time()
92
 
        w = BufferingWriter(writer, 8192)
93
 
        template.expand_into(w, **vals)
94
 
        w.flush()
95
 
        self.log.info('Rendering %s: %r secs, %s bytes, %s (%2.1f%%) bytes saved' % (
96
 
            self.__class__.__name__, time.time() - z, w.bytes, w.bytes_saved, 100.0*w.bytes_saved/w.bytes))
97
 
        return []
 
85
 
 
86
    def _check_rebuild(self):
 
87
        for g in self._groups:
 
88
            for v in g.views:
 
89
                v.check_rebuild()
 
90
 
 
91
 
 
92
# singleton:
 
93
Root = Root()
 
94
 
 
95
# re-index every 6 hours
 
96
index_freq = 6 * 3600
 
97
 
 
98
turbogears.scheduler.add_interval_task(initialdelay=1, interval=index_freq, action=Root._check_rebuild)
 
99
 
 
100
# for use in profiling the very-slow get_change() method:
 
101
#h = util.get_history()
 
102
#w = list(h.get_revision_history())
 
103
#h._get_changes_profiled(w[:100])
 
104