1.1 --- a/README.txt Sun Nov 03 23:26:52 2013 +0100
1.2 +++ b/README.txt Wed Nov 06 15:13:28 2013 +0100
1.3 @@ -16,17 +16,21 @@
1.4 follows with $SCDIR referring to the SubpageComments distribution directory
1.5 containing this README.txt file:
1.6
1.7 +python moinsetup.py -m install_extension_package $SCDIR
1.8 python moinsetup.py -m install_actions $SCDIR/actions
1.9 python moinsetup.py -m install_macros $SCDIR/macros
1.10 python moinsetup.py -m install_theme_resources $SCDIR
1.11 python moinsetup.py -m edit_theme_stylesheet screen.css includecomments.css
1.12 python moinsetup.py -m edit_theme_stylesheet print.css includecomments.css
1.13
1.14 -The first command installs the PostComment action.
1.15 +The first command runs the setup.py script and installs the library for the
1.16 +extension.
1.17
1.18 -The second command installs the IncludeComments macro.
1.19 +The second command installs the PostComment action.
1.20
1.21 -The third command installs the theme resources in the available theme
1.22 +The third command installs the IncludeComments macro.
1.23 +
1.24 +The fourth command installs the theme resources in the available theme
1.25 directories.
1.26
1.27 The remaining commands activate the styles provided by SubpageComments by
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/SubpageComments.py Wed Nov 06 15:13:28 2013 +0100
2.3 @@ -0,0 +1,28 @@
2.4 +# -*- coding: iso-8859-1 -*-
2.5 +"""
2.6 + MoinMoin - SubpageComments common functionality
2.7 +
2.8 + @copyright: 2013 by Paul Boddie <paul@boddie.org.uk>
2.9 + @license: GNU GPL (v2 or later), see COPYING.txt for details.
2.10 +"""
2.11 +
2.12 +from MoinSupport import getPagesForSearch
2.13 +
2.14 +def get_comment_numbers(pagename, request):
2.15 +
2.16 + """
2.17 + Return a list of comment numbers associated with the given 'pagename', using
2.18 + the 'request' provided.
2.19 + """
2.20 +
2.21 + pagenames = []
2.22 +
2.23 + for page in getPagesForSearch("title:regex:^%s/" % pagename, request):
2.24 + basename, number = page.page_name.rsplit("/", 1)
2.25 + if basename == pagename and number.isdigit():
2.26 + pagenames.append(int(number))
2.27 +
2.28 + pagenames.sort()
2.29 + return pagenames
2.30 +
2.31 +# vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/actions/PostComment.py Sun Nov 03 23:26:52 2013 +0100
3.2 +++ b/actions/PostComment.py Wed Nov 06 15:13:28 2013 +0100
3.3 @@ -10,7 +10,9 @@
3.4 from MoinMoin.PageEditor import PageEditor
3.5 from MoinMoin.security import Permissions
3.6 from MoinMoin.wikiutil import escape
3.7 -from MoinSupport import getPagesForSearch, getPagesFromResults, ActionSupport
3.8 +from MoinMoin.util import lock
3.9 +from MoinSupport import ActionSupport
3.10 +from SubpageComments import get_comment_numbers
3.11
3.12 __version__ = "0.1"
3.13
3.14 @@ -69,59 +71,53 @@
3.15 if not request.user.valid or not request.user.may.write(self.pagename):
3.16 return 0, _("You are not allowed to comment on this page.")
3.17
3.18 - # Determine the last comment.
3.19 -
3.20 - comments = get_comment_numbers(self.pagename, request)
3.21 - last_comment_pagename = comments and comments[-1] or -1
3.22 + # Obtain a lock to prevent contention over comment numbers.
3.23
3.24 - # Write the new page.
3.25 -
3.26 - comment_pagename = "%s/%04d" % (self.pagename, last_comment_pagename + 1)
3.27 - new_page = PageEditor(request, comment_pagename)
3.28 - username = request.user.name
3.29 + writelock = lock.WriteLock(self.page.getPagePath("comment-lock"))
3.30 + writelock.acquire()
3.31
3.32 try:
3.33 - # To add a page with an ACL, a special policy is required.
3.34 + # Determine the last comment.
3.35 +
3.36 + comments = get_comment_numbers(self.pagename, request)
3.37 + last_comment_pagename = comments and comments[-1] or -1
3.38
3.39 - may = request.user.may
3.40 - request.user.may = SpecialPermissions(request.user, comment_pagename)
3.41 + # Write the new page.
3.42
3.43 - # Save the page, labelling it with the actual username.
3.44 + comment_pagename = "%s/%04d" % (self.pagename, last_comment_pagename + 1)
3.45 + new_page = PageEditor(request, comment_pagename)
3.46 + username = request.user.name
3.47
3.48 try:
3.49 - new_page.saveText(comment_template % (username, username, comment), 0)
3.50 + # To add a page with an ACL, a special policy is required.
3.51 +
3.52 + may = request.user.may
3.53 + request.user.may = SpecialPermissions(request.user, comment_pagename)
3.54
3.55 - # Restore the superusers.
3.56 + # Save the page, labelling it with the actual username.
3.57 +
3.58 + try:
3.59 + new_page.saveText(comment_template % (username, username, comment), 0)
3.60 +
3.61 + # Restore the original policy.
3.62
3.63 - finally:
3.64 - request.user.may = may
3.65 + finally:
3.66 + request.user.may = may
3.67
3.68 - return 1, _("Comment added.")
3.69 - except new_page.SaveError, exc:
3.70 - return 0, unicode(exc)
3.71 + return 1, _("Comment added.")
3.72 + except new_page.SaveError, exc:
3.73 + return 0, unicode(exc)
3.74 +
3.75 + # Release the lock and let others post comments now.
3.76 +
3.77 + finally:
3.78 + writelock.release()
3.79
3.80 comment_template = """\
3.81 #acl %s:read,write,delete,revert All:read
3.82 #pragma comment-owner %s
3.83 %s"""
3.84
3.85 -def get_comment_numbers(pagename, request):
3.86 -
3.87 - """
3.88 - Return a list of comment numbers associated with the given 'pagename', using
3.89 - the 'request' provided.
3.90 - """
3.91 -
3.92 - pagenames = []
3.93 -
3.94 - for page in getPagesForSearch("title:regex:^%s/" % pagename, request):
3.95 - basename, number = page.page_name.rsplit("/", 1)
3.96 - if basename == pagename and number.isdigit():
3.97 - pagenames.append(int(number))
3.98 -
3.99 - pagenames.sort()
3.100 - return pagenames
3.101 -
3.102 # Action invocation function.
3.103
3.104 def execute(pagename, request):
4.1 --- a/macros/IncludeComments.py Sun Nov 03 23:26:52 2013 +0100
4.2 +++ b/macros/IncludeComments.py Wed Nov 06 15:13:28 2013 +0100
4.3 @@ -16,6 +16,7 @@
4.4 from MoinMoin.macro import Include
4.5 from MoinMoin.user import User
4.6 from MoinMoin.wikiutil import escape
4.7 +from SubpageComments import get_comment_numbers
4.8 import re
4.9 import codecs
4.10
4.11 @@ -68,18 +69,16 @@
4.12 </div>
4.13 """ % d)
4.14
4.15 + # Add included comments.
4.16 +
4.17 + pages = get_comment_numbers(pagename, request)
4.18 +
4.19 + ownerfn = re.compile("^#pragma comment-owner (.*?)$", re.MULTILINE | re.UNICODE).search
4.20 +
4.21 # NOTE: Much of the code below originates from the Include macro, but it
4.22 # NOTE: excludes various options of that macro and adds comment-related
4.23 # NOTE: output.
4.24
4.25 - # Add included comments.
4.26 -
4.27 - filterfn = re.compile(ur"^%s/" % re.escape(pagename), re.U).match
4.28 - pages = request.rootpage.getPageList(filter=filterfn)
4.29 - pages.sort()
4.30 -
4.31 - ownerfn = re.compile("^#pragma comment-owner (.*?)$", re.MULTILINE | re.UNICODE).search
4.32 -
4.33 # Track included pages.
4.34
4.35 if not hasattr(page, '_macroInclude_pagelist'):
4.36 @@ -88,6 +87,7 @@
4.37 # Visit each comment page.
4.38
4.39 for inc_name in pages:
4.40 + inc_name = "%s/%04d" % (pagename, inc_name)
4.41
4.42 # Skip unreadable or already included pages.
4.43
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/setup.py Wed Nov 06 15:13:28 2013 +0100
5.3 @@ -0,0 +1,13 @@
5.4 +#! /usr/bin/env python
5.5 +
5.6 +from distutils.core import setup
5.7 +
5.8 +setup(
5.9 + name = "SubpageComments",
5.10 + description = "Display and accept comments on MoinMoin wiki pages using subpages",
5.11 + author = "Paul Boddie",
5.12 + author_email = "paul@boddie.org.uk",
5.13 + url = "http://moinmo.in/ActionMarket/SubpageComments",
5.14 + version = "0.1",
5.15 + py_modules = ["SubpageComments"]
5.16 + )