SubpageComments

Changeset

5:b60c5dcb85a3
2013-11-06 Paul Boddie raw files shortlog changelog graph Switched to MoinSupport search functionality from Include macro techniques.
README.txt (file) SubpageComments.py (file) actions/PostComment.py (file) macros/IncludeComments.py (file) setup.py (file)
     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 +    )