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.You are not allowed to attach a file to this page.