~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/controllers/__init__.py

  • Committer: Robey Pointer
  • Date: 2007-03-26 06:09:27 UTC
  • Revision ID: robey@lag.net-20070326060927-1o991yjbbxkqpf3d
fix some lame setup.py errors

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
 
21
import os
19
22
import re
 
23
import sys
20
24
import time
21
25
 
22
 
from paste.request import path_info_pop, parse_querystring
 
26
import turbogears
 
27
from turbogears import controllers
 
28
from cherrypy import HTTPRedirect, NotFound
 
29
from configobj import ConfigObj
23
30
 
24
31
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
 
 
69
 
        args = []
70
 
        while 1:
71
 
            arg = path_info_pop(environ)
72
 
            if arg is None:
73
 
                break
74
 
            args.append(arg)
75
 
 
76
 
        vals = {
77
 
            'branch': self._branch,
 
32
from loggerhead.branchview import BranchView
 
33
from loggerhead.history import History, is_branch
 
34
 
 
35
log = logging.getLogger("loggerhead.controllers")
 
36
 
 
37
 
 
38
def cherrypy_friendly(s):
 
39
    """
 
40
    convert a config section name into a name that pleases cherrypy.
 
41
    """
 
42
    return re.sub(r'[^\w\d_]', '_', s)
 
43
 
 
44
 
 
45
class Project (object):
 
46
    def __init__(self, name, config):
 
47
        self.name = name
 
48
        self.friendly_name = config.get('name', name)
 
49
        self.description = config.get('description', '')
 
50
        self.long_description = config.get('long_description', '')
 
51
        self._config = config
 
52
        
 
53
        self._views = []
 
54
        for view_name in config.sections:
 
55
            log.debug('Configuring (project %r) branch %r...', name, view_name)
 
56
            self._add_view(view_name, config[view_name], config[view_name].get('folder'))
 
57
        
 
58
        auto_folder = config.get('auto_publish_folder', None)
 
59
        if auto_folder is not None:
 
60
            auto_list = []
 
61
            # scan a folder for bazaar branches, and add them automatically
 
62
            for path, folders, filenames in os.walk(auto_folder):
 
63
                for folder in folders:
 
64
                    folder = os.path.join(path, folder)
 
65
                    if is_branch(folder):
 
66
                        auto_list.append(folder)
 
67
            auto_list.sort()
 
68
            for folder in auto_list:
 
69
                view_name = os.path.basename(folder)
 
70
                log.debug('Auto-configuring (project %r) branch %r...', name, view_name)
 
71
                self._add_view(view_name, ConfigObj(), folder)
 
72
    
 
73
    def _add_view(self, view_name, view_config, folder):
 
74
        c_view_name = cherrypy_friendly(view_name)
 
75
        view = BranchView(self.name, c_view_name, view_name, folder, view_config, self._config)
 
76
        self._views.append(view)
 
77
        setattr(self, c_view_name, view)
 
78
        
 
79
    views = property(lambda self: self._views)
 
80
 
 
81
 
 
82
class Root (controllers.RootController):
 
83
    def __init__(self):
 
84
        self._projects = []
 
85
        for project_name in sys._loggerhead_config.sections:
 
86
            c_project_name = cherrypy_friendly(project_name)
 
87
            project = Project(c_project_name, sys._loggerhead_config[project_name])
 
88
            self._projects.append(project)
 
89
            setattr(self, c_project_name, project)
 
90
        
 
91
    @turbogears.expose(template='loggerhead.templates.browse')
 
92
    def index(self):
 
93
        return {
 
94
            'projects': self._projects,
78
95
            'util': util,
79
 
            'history': h,
80
 
            'url': self._branch.context_url,
 
96
            'title': sys._loggerhead_config.get('title', ''),
81
97
        }
82
 
        vals.update(templatefunctions)
83
 
        headers = {}
84
 
        vals.update(self.get_values(h, args, kw, headers))
85
 
 
86
 
        self.log.info('Getting information for %s: %r secs' % (
87
 
            self.__class__.__name__, time.time() - z,))
88
 
        if 'Content-Type' not in headers:
89
 
            headers['Content-Type'] = 'text/html'
90
 
        writer = start_response("200 OK", headers.items())
91
 
        template = load_template(self.template_path)
92
 
        z = time.time()
93
 
        w = BufferingWriter(writer, 8192)
94
 
        template.expand_into(w, **vals)
95
 
        w.flush()
96
 
        self.log.info('Rendering %s: %r secs, %s bytes, %s (%2.1f%%) bytes saved' % (
97
 
            self.__class__.__name__, time.time() - z, w.bytes, w.bytes_saved, 100.0*w.bytes_saved/w.bytes))
98
 
        return []
 
98
 
 
99
    def _check_rebuild(self):
 
100
        for p in self._projects:
 
101
            for v in p.views:
 
102
                v.check_rebuild()
 
103
 
 
104
 
 
105
# singleton:
 
106
Root = Root()
 
107
 
 
108
 
 
109
# for use in profiling the very-slow get_change() method:
 
110
#h = Root.bazaar.bzr_dev.get_history()
 
111
#w = list(h.get_revision_history())
 
112
#h._get_changes_profiled(w[:100])
99
113