Attachment 'Annotate-1.9-3.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     MoinMoin - show annotations of a page revision
   4 
   5     @copyright: 2010-2014 Henryk Gerlach <hgerlach@gmx.de>
   6     @license: GNU GPL, see COPYING for details.
   7 """
   8 
   9 
  10 import difflib
  11 from MoinMoin import log
  12 logging = log.getLogger(__name__)
  13 
  14 from MoinMoin import wikiutil
  15 from MoinMoin.logfile import editlog
  16 from MoinMoin.Page import Page
  17 from MoinMoin.widget import html
  18 
  19 def execute(pagename, request):
  20     """ 
  21     Handle "action=annotate". Send page with annotations.
  22 
  23     @param pagename: compute annotations for this page
  24     @param request: request object, following keywords are taken from request.values
  25     @keyword rev: compute annotations for this revision
  26     @keyword ignorews: if 1: ignore whitespace
  27     """
  28     if not request.user.may.read(pagename):
  29         Page(request, pagename).send_page()
  30         return
  31 
  32     try:
  33         rev = int(request.values.get('rev', None))
  34     except StandardError:
  35         rev = None
  36 
  37     page = Page(request, pagename)
  38     currentrev = page.current_rev()
  39     if rev == None or rev > currentrev:
  40         rev = currentrev
  41 
  42     # spacing flag?
  43     ignorews = int(request.values.get('ignorews', 0))
  44 
  45     _ = request.getText
  46 
  47 
  48     def merge_annotation(oldlines, newlines, **kw):
  49         """
  50         Find changes between oldlines and newlines.
  51     
  52         @param oldlines: list of old decoration and text lines (decoration, line)
  53         @param newlines: list of new decoration and text lines (decoration, line)
  54         @keyword ignorews: if 1: ignore whitespace
  55         @rtype: list
  56         @return: changed old lines get replaced by new lines with new decoration
  57         """
  58 
  59 
  60         false = lambda s: None
  61         if kw.get('ignorews', 0):
  62             d = difflib.Differ(false)
  63         else:
  64             d = difflib.Differ(false, false)
  65     
  66         lines = list(d.compare( map(lambda s: s[1], oldlines), map(lambda s: s[1], newlines)))
  67     
  68         result = []
  69         iold = inew = 0
  70         for l in lines:
  71             if l[0] == " ":
  72                 result.append( oldlines[iold] )
  73                 iold += 1
  74                 inew += 1
  75             if l[0] == "-": 
  76                 iold+=1
  77             if l[0] == "+":
  78                 result.append( newlines[inew] )
  79                 inew += 1
  80         return result
  81 
  82     def decorate_lines(rev):
  83         """
  84         Compute list of (decoration, lines) corresponding to revision.
  85         
  86         @param rev: the revision to decorate
  87         """
  88         page   = Page(request, pagename, rev=rev)
  89         log    = page.editlog_entry()
  90         editor = log.getEditor(request) or _('N/A'),
  91         date   = request.user.getFormattedDateTime(wikiutil.version2timestamp(log.ed_time_usecs)) or _('N/A')
  92         return map(lambda l: [(rev, editor, date), l], page.get_raw_body().split("\n"))
  93     
  94     #compute all revisions that are relevant for the annotation of the requested rev
  95     allrevs = []
  96 
  97     logs = list(editlog.EditLog(request, rootpagename=pagename))
  98 
  99     while logs: #fast forward to requested rev
 100        if int(rev) == int(logs[-1].rev): break
 101        logs.pop()
 102 
 103     while logs:
 104        l = logs.pop()
 105        allrevs.append(int(l.rev))
 106        if l.action in ['ATTNEW','ATTDEL']:
 107           allrevs.pop() #these actions are not relevant for the text 
 108        elif l.action in ['SAVE/REVERT']:
 109           #remove reverted editions
 110           while l.extra != logs[-1].rev:
 111              logs.pop()
 112     allrevs.reverse()
 113 
 114     #compute annotations
 115     if not allrevs:
 116        #The page has no revisions. Maybe a default page.
 117        currtext = []
 118     else:
 119        rev_iter = allrevs.pop(0)
 120        currtext = decorate_lines(rev_iter)
 121     for rev_iter in allrevs:
 122         oldtext = currtext
 123         currtext = decorate_lines(rev_iter)
 124         currtext = merge_annotation(oldtext, currtext, ignorews=ignorews)
 125 
 126     # build and send the page
 127     def render_action(text, query, **kw):
 128         kw.update(dict(rel='nofollow'))
 129         return page.link_to(request, text, querystr=query, **kw)
 130 
 131     f = request.formatter
 132     if rev == currentrev:
 133         request.theme.send_title(_('Annotate for "%s"') % (pagename, ), pagename=pagename)
 134     else:
 135         request.theme.send_title(_('Annotate for "%s" revison %d') % (pagename, rev ), pagename=pagename)
 136 
 137     # Start content (important for RTL support)
 138     request.write(request.formatter.startContent("content"))
 139 
 140     request.write("<table><tr><th>"+_("Line")+"</th><th>"+_("Editor")+"</th><th>"+_("Date")+"</th><th>"+_("Rev")+"</th></tr>")
 141     for annotation, l in currtext:
 142         rev, editor, date = annotation
 143         request.write("<tr><td>") 
 144         request.write(f.text(l))
 145         request.write("</td><td>"+ editor[0] + "</td><td>"+date+"</td>")
 146         request.write("<td>"+render_action(_(str(rev)), {'action': 'recall', 'rev': '%d' % rev})+"</td></tr>")
 147 
 148     request.write("</table>")
 149     request.write(request.formatter.endContent())
 150     request.theme.send_footer(pagename)
 151     request.theme.send_closing_html()

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2010-10-21 16:57:27, 3.7 KB) [[attachment:Annotate-1.9-1.py]]
  • [get | view] (2012-04-13 16:55:31, 4.0 KB) [[attachment:Annotate-1.9-2.py]]
  • [get | view] (2014-10-17 08:52:22, 4.9 KB) [[attachment:Annotate-1.9-3.py]]
  • [get | view] (2010-10-20 19:43:00, 69.0 KB) [[attachment:annotate_example.png]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.