gminick / sphinx-gsoc2009

fork of sphinx

A support for per-paragraph comments and user/developer interface for submitting/committing fixes.

commit 1619: d16335626c05
parent 1618: f9d4256eb2e0
branch: default
Basic commit possible now
Wojtek Walczak / gminick
7 months ago

Changed (Δ2.1 KB):

raw changeset »

sphinx/builders/webapp/templates/webapp.conf (2 lines added, 0 lines removed)

sphinx/builders/webapp/webapp.py (12 lines added, 11 lines removed)

sphinx/config.py (2 lines added, 1 lines removed)

sphinx/quickstart.py (2 lines added, 1 lines removed)

sphinx/themes/basic/static/comments.js (9 lines added, 8 lines removed)

sphinx/web/middleware/appserver.py (45 lines added, 7 lines removed)

sphinx/web/singlebuilder.py (3 lines added, 3 lines removed)

sphinx/web/webconfig.py (2 lines added, 0 lines removed)

Up to file-list sphinx/builders/webapp/templates/webapp.conf:

@@ -3,5 +3,7 @@ licence={{ licence }}
3
3
4
4
[Repository]
5
5
repodir={{ repodir }}
6
reporoot={{ reporoot }}
7
repopath={{ reporoot }}/{{ repodir }}
6
8
reposums={{ reposums }}
7
9
piddbfile={{ piddbfile }}

Up to file-list sphinx/builders/webapp/webapp.py:

@@ -50,7 +50,7 @@ class WebAppBuilder(StandaloneHTMLBuilde
50
50
        self.public_dir = path.join(self.outdir, 'public')
51
51
        
52
52
        # _build/webapp/repo - reST source files as a repository
53
        self.repodir = path.join(self.outdir, 'repo')
53
        self.reporoot = path.join(self.outdir, 'repo')
54
54
        
55
55
        # _build/webapp/html - HTML templates for webapp/middleware
56
56
        self.html_dir = path.join(self.outdir, 'html')
@@ -111,7 +111,7 @@ class WebAppBuilder(StandaloneHTMLBuilde
111
111
            repo = self.detect_repo()
112
112
            if repo:
113
113
                # currently - only mercurial
114
                commands.clone(self.ui, repo.base_path, self.repodir)
114
                commands.clone(self.ui, repo.base_path, self.reporoot)
115
115
            else:
116
116
                self.new_repo()
117
117
        except Exception, err:
@@ -121,8 +121,8 @@ class WebAppBuilder(StandaloneHTMLBuilde
121
121
        return get_workdir_manager_for_path(self.srcdir)
122
122
123
123
    def new_repo(self):
124
        commands.init(self.ui, self.repodir)
125
        repo = repository(self.ui, self.repodir)
124
        commands.init(self.ui, self.reporoot)
125
        repo = repository(self.ui, self.reporoot)
126
126
        builddir = path.join(self.srcdir, '_build')
127
127
        def callback(arg, directory, files):
128
128
            srclen = len(self.srcdir)
@@ -131,7 +131,7 @@ class WebAppBuilder(StandaloneHTMLBuilde
131
131
            for elem in files:
132
132
                srcfile = path.join(directory, elem)
133
133
                subdir = directory[srclen+1:]
134
                dstfile = path.join(path.join(self.repodir, subdir), elem)
134
                dstfile = path.join(path.join(self.reporoot, subdir), elem)
135
135
                if path.isdir(srcfile):
136
136
                    os.mkdir(dstfile)
137
137
                elif not path.exists(dstfile):
@@ -141,7 +141,7 @@ class WebAppBuilder(StandaloneHTMLBuilde
141
141
142
142
    def add_pids_to_paragraphs(self):
143
143
        def add_pids_to_lines(filename):
144
            dirbase = path.join(self.orig_outdir, self.webconfig.repodir)
144
            dirbase = path.join(self.orig_outdir, self.webconfig.repopath)
145
145
            fullpath = path.join(dirbase, filename)
146
146
            try:
147
147
                w = codecs.open(fullpath, 'r', self.encoding)
@@ -213,6 +213,7 @@ class WebAppBuilder(StandaloneHTMLBuilde
213
213
                                { 'licence': self.config.licence,
214
214
                                  'piddbfile': self.config.piddbfile,
215
215
                                  'repodir': self.config.repodir,
216
                                  'reporoot': self.config.reporoot,
216
217
                                  'reposums': self.config.reposums })
217
218
            conf_dst = path.join(self.outdir, 'webapp.conf')
218
219
            w = codecs.open(conf_dst, 'w', self.encoding)
@@ -285,7 +286,7 @@ def cutcwd(fpath):
285
286
286
287
class WebappHTMLTranslator(HTMLTranslator):
287
288
    licence = None
288
    repodir = None
289
    repopath = None
289
290
    piddbfile = None
290
291
    def __init__(self, *args, **kwds):
291
292
        self.templ_env = None # templates environment
@@ -294,8 +295,8 @@ class WebappHTMLTranslator(HTMLTranslato
294
295
        self.piddb = PidDb(self.piddbfile)
295
296
        HTMLTranslator.__init__(self, *args, **kwds)
296
297
297
    def init_attributes(self, repodir, piddbfile, licence):
298
        self.repodir = repodir
298
    def init_attributes(self, repopath, piddbfile, licence):
299
        self.repopath = repopath
299
300
        self.piddbfile = piddbfile
300
301
        self.licence = licence
301
302
@@ -323,8 +324,8 @@ class WebappHTMLTranslator(HTMLTranslato
323
324
        HTMLTranslator.depart_paragraph(self, node)
324
325
        if not self.should_be_compact_paragraph(node) and node.source:
325
326
           nodename = cutcwd(node.source)
326
           if self.repodir:
327
               nodename = nodename[len(self.repodir)+1:]
327
           if self.repopath:
328
               nodename = nodename[len(self.repopath)+1:]
328
329
           self.body.append(comm_template.render({ 'licence': self.licence,
329
330
                                                   'node': nodename,
330
331
                                                   'paragraph_id': self.pid,

Up to file-list sphinx/config.py:

@@ -120,7 +120,8 @@ class Config(object):
120
120
121
121
        # Web application options
122
122
        xapian_db = ('xapian_db', 'webapp'),
123
        repodir = ('repo/doc', 'webapp'),
123
        repodir = ('doc', 'webapp'),
124
        reporoot = ('repo', 'webapp'),
124
125
        reposums = ('reposums.pkl', None),
125
126
        piddbfile = ('piddb.pkl', None),
126
127
        licence = ('BSD', 'webapp'),

Up to file-list sphinx/quickstart.py:

@@ -227,7 +227,8 @@ latex_documents = [
227
227
# -- Options for WebApp --------------------------------------------------------
228
228
# configuration options for Xapian:
229
229
xapian_db = 'xapian_db'
230
repodir = 'repo/doc'
230
reporoot = 'repo'
231
repodir = 'doc'
231
232
reposums = 'reposums.pkl'
232
233
piddbfile = 'piddb.pkl'
233
234
licence = 'BSD'

Up to file-list sphinx/themes/basic/static/comments.js:

106
106
 *                                       located in 'id' file under
107
107
 *                                       'comment_no' index
108
108
 *
109
 * commit_fix(id, fix_no) -> commit a fix located in 'id' file under
110
 *                           'fix_no' index to the repository
109
 * commit_fix(node, id, fix_no) -> commit a fix located in 'id' file under
110
 *                                 'fix_no' index to the repository
111
111
 *
112
112
 **
113
113
 *** general-use functions ************************************************
@@ -205,6 +205,7 @@ function print_generic(what, id, data) {
205
205
   var c_flag = (what == 'comments') ? true : false;
206
206
   var singular = (what == 'comments') ? 'comment' : 'fix';
207
207
   var isdev = is_developer();
208
   var node = $('div[class=submitFixFields_' + id + ']').attr('value');
208
209
   
209
210
   if(what == 'comments') {
210
211
      empty_comments(id);
@@ -247,8 +248,8 @@ function print_generic(what, id, data) {
247
248
      return '<a href="#" onclick="delete_comment(\'' + db + '\', \'' + id +  '\', \'' + comment_no + '\')">delete</a>' 
248
249
   } 
249
250
250
   function commit_button(id, fix_no) {
251
      return '<a href="#" onclick="commit_fix(\'' + id + '\', \''
251
   function commit_button(node, id, fix_no) {
252
      return '<a href="#" onclick="commit_fix(\'' + node + '\', \'' +  id + '\', \''
252
253
                  + fix_no + '\')">commit</a>'
253
254
   }
254
255
@@ -258,7 +259,7 @@ function print_generic(what, id, data) {
258
259
             +    'Admin actions: '
259
260
             +    delete_comment_button(what, id, data[i].comment_no)
260
261
             +    ', '
261
             +    commit_button(id, data[i].comment_no)
262
             +    commit_button(node, id, data[i].comment_no)
262
263
             +    '.'
263
264
             +  '</td>'
264
265
             + '</tr>' 
@@ -290,7 +291,7 @@ function print_generic(what, id, data) {
290
291
         +  '</tr>'
291
292
         +  (isdev ? developers_actions(what, id, data, i) : '')
292
293
         +  '<tr><td> </td></tr>'
293
         +  proposed_fix(c_flag, data[i].paragraph)
294
         +  proposed_fix(c_flag, data[i].paragraph_diff)
294
295
         +  "<tr>"
295
296
         +    "<td>"
296
297
         +      'Comment: ' + data[i].comment
@@ -507,11 +508,11 @@ function delete_comment(db, id, comment_
507
508
         });
508
509
}
509
510
510
function commit_fix(id, fix_no) {
511
function commit_fix(node, id, fix_no) {
511
512
   var c_path = location.protocol + "//" + location.host + "/commit_fix";
512
513
   $.ajax({ url: c_path,
513
514
            type: 'GET',
514
            data: "id=" + id + "&fix_no=" + fix_no,
515
            data: "node=" + node + "&id=" + id + "&fix_no=" + fix_no,
515
516
            success: function() { load_func(id)}
516
517
         });
517
518
}

Up to file-list sphinx/web/middleware/appserver.py:

@@ -26,6 +26,7 @@ from os import path
26
26
from difflib import Differ
27
27
from hashlib import md5
28
28
29
from anyvc import workdir
29
30
from jinja2 import Environment, FileSystemLoader, Template
30
31
from webob import Request, Response
31
32
@@ -173,9 +174,10 @@ class AppServer(object):
173
174
        self.piddb = PidDb(self.webconfig.piddbfile)
174
175
        self.webauth = WebAuth()
175
176
        self.webauth.developers_load('developers.txt')
177
        self.repo = workdir.get_workdir_manager_for_path(self.webconfig.repopath)
176
178
        self.reposums = RepoSums(self.webconfig.reposums)
177
179
        self.htmlbuilder = SinglefileHTMLBuilder(self.www_dir,
178
                                                 self.webconfig.repodir,
180
                                                 self.webconfig.repopath,
179
181
                                                 self.webconfig.piddbfile,
180
182
                                                 self.webconfig.licence)
181
183
        self.init_templates()
@@ -344,11 +346,46 @@ class AppServer(object):
344
346
345
347
    def doCommitFix(self, req, resp):
346
348
        """Commit fix"""
347
        p_id, fix_no = req.GET['id'], req.GET['fix_no']
349
        def new_file_to_commit(file_path, record):
350
            """Open a file 'file_path' and in its content change a paragraph
351
            'paragraph_orig' with 'paragraph_submitted' from the 'record'
352
            dict. Then overwrite the 'file_path' file with a new version
353
            of a file and commit it to the repository."""
354
            try:
355
                w = open(file_path)
356
                file_contents = w.read()
357
                w.close()
358
            except Exception, err:
359
                raise SphinxError(err)
360
361
            filesub = re.sub(re.escape(record['paragraph_orig']),
362
                             record['paragraph_submitted'],
363
                             file_contents)
364
365
            try:
366
                w = open(file_path, 'w')
367
                w.write(filesub)
368
                w.close()
369
            except Exception, err:
370
                raise SphinxError(err)
371
372
            olddir = os.getcwd()
373
            os.chdir(path.join(olddir, self.webconfig.reporoot))
374
            self.repo.commit(message='need to add textarea for '\
375
                                     'message in the post form',
376
                             paths=(path.join('doc', path.basename(file_path)),))
377
            os.chdir(olddir)
378
379
        node, p_id, fix_no = req.GET['node'], req.GET['id'], int(req.GET['fix_no'])
348
380
        fixes_db_path = get_fixes_db_path(p_id)
349
381
        data = load_comments(fixes_db_path)
350
        fix_index = index_by_key_val(data, 'comment_no', int(fix_no))
351
        print '>>>', p_id, fix_no, data[fix_index]['paragraph_orig']
382
        fix_index = index_by_key_val(data, 'comment_no', fix_no)
383
        file_path = path.join(self.webconfig.repopath, node)
384
        new_file_to_commit(file_path, data[fix_index])
385
        delete_comment(fixes_db_path, p_id, fix_no)
386
        self.piddb.add_record(node, p_id, data[fix_index]['paragraph_submitted'],
387
                              save=True)
388
        # need to reload the page to see the changes
352
389
        return resp
353
390
354
391
    def doAddComment(self, req, resp):
@@ -392,8 +429,9 @@ class AppServer(object):
392
429
393
430
            d = Differ()
394
431
            pdiff = list(d.compare(p2, p1))
395
            db_rec['paragraph'] = modify_diff(pdiff)
396
            db_rec['paragraph_orig'] = pdiff
432
            db_rec['paragraph_submitted'] = req.POST.get(p_str)
433
            db_rec['paragraph_diff'] = modify_diff(pdiff)
434
            db_rec['paragraph_orig'] = req.POST.get(p_orig_str)
397
435
            db_path = get_fixes_db_path(p_id)
398
436
        else:
399
437
            db_path = get_comments_db_path(p_id)
@@ -465,7 +503,7 @@ class AppServer(object):
465
503
        resp.charset = 'utf8' 
466
504
        file_path = self.constructPath(req)
467
505
468
        repo_file = path.join(self.webconfig.repodir,file_path[:-5] + '.rst')
506
        repo_file = path.join(self.webconfig.repopath,file_path[:-5] + '.rst')
469
507
        if check_rst_sum(repo_file):
470
508
            self.htmlbuilder.render_page(file_path[:-5])
471
509

Up to file-list sphinx/web/singlebuilder.py:

@@ -23,9 +23,9 @@ from sphinx.errors import SphinxError
23
23
class SinglefileHTMLBuilder(StandaloneHTMLBuilder, Sphinx):
24
24
    """Render a file when requested using data from a pickled archive.
25
25
    Handle theming."""
26
    def __init__(self, www_dir, repodir, piddbfile, licence):
26
    def __init__(self, www_dir, repopath, piddbfile, licence):
27
27
        self.outdir = www_dir
28
        self.srcdir = repodir
28
        self.srcdir = repopath
29
29
        self.piddbfile = piddbfile
30
30
        self.licence = licence
31
31
        self.cwd = os.getcwd()
@@ -67,7 +67,7 @@ class SinglefileHTMLBuilder(StandaloneHT
67
67
    def init_translator_class(self):
68
68
        WebappHTMLTranslator.licence = self.licence
69
69
        WebappHTMLTranslator.piddbfile = self.piddbfile
70
        WebappHTMLTranslator.repodir = self.srcdir
70
        WebappHTMLTranslator.repopath = self.srcdir
71
71
        self.translator_class = WebappHTMLTranslator
72
72
73
73
    def render_page(self, docname):

Up to file-list sphinx/web/webconfig.py:

@@ -23,5 +23,7 @@ class WebConfig(object):
23
23
24
24
        self.piddbfile = self.conf.get('Repository', 'piddbfile')
25
25
        self.repodir = self.conf.get('Repository', 'repodir')
26
        self.reporoot = self.conf.get('Repository', 'reporoot')
27
        self.repopath = self.conf.get('Repository', 'repopath')
26
28
        self.reposums = self.conf.get('Repository', 'reposums')
27
29