changeset 3382:d0cc11c9c821

merged main
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Fri, 21 Mar 2008 00:23:47 +0100
parents c8296a0c9799 (current diff) dd7df6fe929a (diff)
children 339628170ebf
files
diffstat 14 files changed, 215 insertions(+), 113 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/PageEditor.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/PageEditor.py	Fri Mar 21 00:23:47 2008 +0100
@@ -658,7 +658,7 @@
                 return False, _('Could not rename page because of file system error: %s.') % unicode(err)
 
 
-    def revertPage(self, revision):
+    def revertPage(self, revision, comment=u''):
         """ Reverts page to the given revision
 
         @param revision: revision to revert to
@@ -668,15 +668,16 @@
         _ = self.request.getText
 
         if not self.request.user.may.revert(self.page_name):
-            raise self.RevertError(_('You are not allowed to revert this page!'))
+            # no real message necessary, cannot happen if
+            # user doesn't try to exploit us
+            raise self.RevertError('not allowed')
         elif revision is None:
-            raise self.RevertError(_('You were viewing the current revision of this page when you called the revert action. '
-                    'If you want to revert to an older revision, first view that older revision and '
-                    'then call revert to this (older) revision again.'))
+            # see above
+            raise self.RevertError('cannot revert to current rev')
         else:
             revstr = '%08d' % revision
             pg = Page(self.request, self.page_name, rev=revision)
-            msg = self.saveText(pg.get_raw_body(), 0, extra=revstr, action="SAVE/REVERT", notify=False)
+            msg = self.saveText(pg.get_raw_body(), 0, extra=revstr, action="SAVE/REVERT", notify=False, comment=comment)
 
             # Remove cache entry (if exists)
             pg = Page(self.request, self.page_name)
--- a/MoinMoin/_tests/test_wikiutil.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/_tests/test_wikiutil.py	Fri Mar 21 00:23:47 2008 +0100
@@ -540,6 +540,9 @@
         assert a == 7
         assert choice == u'a'
 
+    def _test_invoke_choice_required(self, i=wikiutil.required_arg((u'b', u'a'))):
+        assert i == u'a'
+
     def _test_trailing(self, a, _trailing_args=[]):
         assert _trailing_args == [u'a']
 
@@ -616,6 +619,10 @@
         ief(self.request, self._test_invoke_float_required, u'1.4')
         ief(self.request, self._test_invoke_float_required, u'i=1.4')
         py.test.raises(ValueError, ief, self.request,
+                       self._test_invoke_choice_required, u'')
+        ief(self.request, self._test_invoke_choice_required, u'a')
+        ief(self.request, self._test_invoke_choice_required, u'i=a')
+        py.test.raises(ValueError, ief, self.request,
                        self._test_invoke_float_required, u',')
 
     def testConstructors(self):
--- a/MoinMoin/action/__init__.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/action/__init__.py	Fri Mar 21 00:23:47 2008 +0100
@@ -55,7 +55,7 @@
         self.form_trigger_label = _("Do it.") # label for the trigger button
         self.page = Page(request, pagename)
         self.error = ''
-        self.method = 'GET'
+        self.method = 'POST'
         self.enctype = 'multipart/form-data'
 
     # CHECKS -----------------------------------------------------------------
@@ -64,7 +64,11 @@
         return self.actionname in self.cfg.actions_excluded
 
     def is_allowed(self):
-        """ Return True if action is allowed (by ACL) """
+        """
+        Return True if action is allowed (by ACL), or
+        return a tuple (allowed, message) to show a
+        message other than the default.
+        """
         return True
 
     def check_condition(self):
@@ -155,16 +159,16 @@
     def render_msg(self, msg, msgtype):
         """ Called to display some message (can also be the action form) """
         self.request.theme.add_msg(msg, msgtype)
-        self.page.send_page()
+        do_show(self.pagename, self.request)
 
     def render_success(self, msg, msgtype):
         """ Called to display some message when the action succeeded """
         self.request.theme.add_msg(msg, msgtype)
-        self.page.send_page()
+        do_show(self.pagename, self.request)
 
     def render_cancel(self):
         """ Called when user has hit the cancel button """
-        self.page.send_page() # we don't tell user he has hit cancel :)
+        do_show(self.pagename, self.request)
 
     def render(self):
         """ Render action - this is the main function called by action's
@@ -183,8 +187,14 @@
         error = None
         if self.is_excluded():
             error = _('Action %(actionname)s is excluded in this wiki!') % {'actionname': self.actionname }
-        elif not self.is_allowed():
-            error = _('You are not allowed to use action %(actionname)s on this page!') % {'actionname': self.actionname }
+        else:
+            allowed = self.is_allowed()
+            if isinstance(allowed, tuple):
+                allowed, msg = allowed
+            else:
+                msg = _('You are not allowed to use action %(actionname)s on this page!') % {'actionname': self.actionname }
+            if not allowed:
+                error = msg
         if error is None:
             error = self.check_condition()
         if error:
--- a/MoinMoin/action/diff.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/action/diff.py	Fri Mar 21 00:23:47 2008 +0100
@@ -110,7 +110,7 @@
     revlist = currentpage.getRevList()
 
     # Revision list starts from 2...
-    if oldrev == min(revlist) + 1:
+    if oldrev == min(revlist):
         disable_prev = u' disabled="true"'
     else:
         disable_prev = u''
@@ -123,6 +123,7 @@
     page_url = wikiutil.escape(currentpage.url(request), True)
 
     navigation_html = """
+<span class="diff-header">%s</span>
 <table class="diff">
 <tr>
  <td style="border:0">
@@ -136,7 +137,13 @@
   </span>
  </td>
  <td style="border:0">
-  <span class="diff-header">%s</span>
+  <span style="text-align:center">
+   <form action="%s" method="get">
+    <input name="action" value="revert" type="hidden">
+    <input name="rev" value="%d" type="hidden">
+    <input value="%s" type="submit"%s>
+   </form>
+  </span>
  </td>
  <td style="border:0">
   <span style="text-align:right">
@@ -150,8 +157,9 @@
  </td>
 </tr>
 </table>
-""" % (page_url, oldrev - 1, oldrev, _("Previous change"), disable_prev,
-       title,
+""" % (title,
+       page_url, oldrev - 1, oldrev, _("Previous change"), disable_prev,
+       page_url, rev2, _("Revert to this revision"), u'',
        page_url, newrev, newrev + 1, _("Next change"), disable_next, )
 
     request.write(f.rawHTML(navigation_html))
--- a/MoinMoin/action/info.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/action/info.py	Fri Mar 21 00:23:47 2008 +0100
@@ -146,7 +146,8 @@
                         actions.append(render_action(_('edit'), {'action': 'AttachFile', 'drawing': '%s' % filename.replace(".draw", "")}))
 
                     actions.append(render_action(_('get'), {'action': 'AttachFile', 'do': 'get', 'target': '%s' % filename}))
-                    actions.append(render_action(_('del'), {'action': 'AttachFile', 'do': 'del', 'target': '%s' % filename}))
+                    if request.user.may.delete(pagename):
+                        actions.append(render_action(_('del'), {'action': 'AttachFile', 'do': 'del', 'target': '%s' % filename}))
 
             history.addRow((
                 rev,
--- a/MoinMoin/action/revert.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/action/revert.py	Fri Mar 21 00:23:47 2008 +0100
@@ -3,25 +3,107 @@
     MoinMoin - revert a page to a previous revision
 
     @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
-                2006 MoinMoin:ThomasWaldmann
+                2006 MoinMoin:ThomasWaldmann,
+                2007 MoinMoin:ReimarBauer,
+                2008 MoinMoin:JohannesBerg
     @license: GNU GPL, see COPYING for details.
 """
+from MoinMoin import wikiutil
+from MoinMoin.PageEditor import PageEditor
+from MoinMoin.action import ActionBase
+
+class revert(ActionBase):
+    """ revert page action
+
+    Note: the action name is the class name
+    """
+    def __init__(self, pagename, request):
+        ActionBase.__init__(self, pagename, request)
+        self.use_ticket = True
+        _ = self._
+        self.form_trigger = 'revert'
+        self.form_trigger_label = _('Revert')
+        self.method = 'POST'
+
+    def is_allowed(self):
+        # this is not strictly necessary because the underlying storage code checks
+        # as well
+        _ = self._
+        may = self.request.user.may
+        allowed = may.write(self.pagename) and may.delete(self.pagename)
+        return allowed, _('You are not allowed to revert this page!')
+
+    def check_condition(self):
+        """ checks valid page and rev """
+        _ = self._
+        if not self.request.rev:
+            # same string as in PageEditor...
+            note = _('You were viewing the current revision of this page when you called the revert action. '
+                     'If you want to revert to an older revision, first view that older revision and '
+                     'then call revert to this (older) revision again.')
+            return note
+
+        if not self.page.exists():
+            return _('This page is already deleted or was never created!')
+        else:
+            return None
+
+    def do_action(self):
+        """ revert pagename """
+        form = self.form
+        comment = form.get('comment', [u''])[0]
+        comment = wikiutil.clean_input(comment)
+
+        if self.request.request_method != 'POST':
+            return False, u''
+
+        rev = self.request.rev
+        pg = PageEditor(self.request, self.pagename)
+
+        try:
+            msg = pg.revertPage(rev, comment)
+            # make it show the current version...
+            self.request.rev = None
+        except PageEditor.RevertError, error:
+            msg = unicode(error)
+        except PageEditor.Unchanged, error:
+            msg = unicode(error)
+
+        return True, msg
+
+    def get_form_html(self, buttons_html):
+        """ creates the form """
+        _ = self._
+
+        d = {
+            'pagename': self.pagename,
+            'comment_label': _("Optional reason for reverting this page"),
+            'buttons_html': buttons_html,
+            'querytext': _('Really revert this page?'),
+            'rev': self.request.rev
+            }
+
+        return '''
+<strong>%(querytext)s</strong>
+<table>
+    <tr>
+        <td class="label"><label>%(comment_label)s</label></td>
+        <td class="content">
+            <input type="text" name="comment" size="80" maxlength="200">
+            <input type="hidden" name="rev" value="%(rev)d">
+        </td>
+    </tr>
+    <tr>
+        <td></td>
+        <td class="buttons">
+            %(buttons_html)s
+        </td>
+    </tr>
+</table>
+''' % d
+
+
 
 def execute(pagename, request):
-    """ restore another revision of a page as a new current revision """
-    from MoinMoin.PageEditor import PageEditor
-
-    if request.request_method != 'POST':
-        return
-
-    rev = request.rev
-    pg = PageEditor(request, pagename)
-
-    try:
-        msg = pg.revertPage(rev)
-    except PageEditor.RevertError, error:
-        msg = unicode(error)
-
-    request.reset()
-    request.theme.add_msg(msg, "dialog")
-    pg.send_page()
+    """ Glue code for actions """
+    revert(pagename, request).render()
--- a/MoinMoin/macro/EmbedObject.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/macro/EmbedObject.py	Fri Mar 21 00:23:47 2008 +0100
@@ -46,7 +46,7 @@
     else:
         return ""
 
-def macro_EmbedObject(macro, target=None, pagename=None,
+def macro_EmbedObject(macro, target=wikiutil.required_arg(unicode), pagename=None,
                       width=wikiutil.UnitArgument(None, float, ['px', 'em', 'mm', '%']),
                       height=wikiutil.UnitArgument(None, float, ['px', 'em', 'mm', '%']),
                       alt=u'',
@@ -75,13 +75,6 @@
     if not pagename:
         pagename = fmt.page.page_name
 
-    if not target:
-        return fmt.text(_('%(extension_name)s %(extension_type)s: Required argument %(argument_name)s missing.') % {
-            "extension_name": extension_name,
-            "extension_type": extension_type,
-            "argument_name": "target",
-        })
-
     if not wikiutil.is_URL(target):
         pagename, fname = AttachFile.absoluteName(target, pagename)
 
--- a/MoinMoin/macro/Navigation.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/macro/Navigation.py	Fri Mar 21 00:23:47 2008 +0100
@@ -8,6 +8,7 @@
 
 import re
 from MoinMoin.Page import Page
+from MoinMoin import wikiutil
 
 Dependencies = ["namespace"]
 
@@ -65,11 +66,12 @@
     # querystring for slideshow links
     PROJECTION = {'action': 'print', 'media': 'projection', }
 
-    def __init__(self, macro, args):
+    def __init__(self, macro, scheme, depth):
         """ Prepare common values used during processing.
         """
         self.macro = macro
-        self.args = args.split(',')
+        self.scheme = scheme
+        self.depth = depth
         self._ = self.macro.request.getText
 
         self.pagename = self.macro.formatter.page.page_name
@@ -85,19 +87,17 @@
         if self.print_mode and self.media != 'projection':
             return None
 
-        scheme = self.args[0] or '<default>'
-        return getattr(self, 'do_'+scheme, self.badscheme)()
+        return getattr(self, 'do_%s' % self.scheme, self.badscheme)()
 
 
     def badscheme(self):
         """ Bad scheme argument.
         """
         _ = self._
-        scheme = self.args[0]
         return (self.macro.formatter.sysmsg(1) +
                 self.macro.formatter.text(
             _("Unsupported navigation scheme '%(scheme)s'!") %
-            {'scheme': scheme}) +
+            {'scheme': self.scheme}) +
                 self.macro.formatter.sysmsg(0))
 
 
@@ -120,11 +120,6 @@
                     self.macro.formatter.text(_('No parent page found!'))+
                     self.macro.formatter.sysmsg(0))
 
-        try:
-            depth = int(self.args[1])
-        except (IndexError, TypeError, ValueError):
-            depth = 0
-
         # iterate over children, adding links to all of them
         result = []
         children = _getPages(request, '^%s/' % re.escape(parent))
@@ -134,7 +129,7 @@
             shortname = child[len(parent):]
 
             # possibly limit depth
-            if depth and shortname.count('/') > depth:
+            if self.depth and shortname.count('/') > self.depth:
                 continue
 
             if child == self.pagename:
@@ -221,14 +216,17 @@
         return self.do_slideshow(focus=self.pagename) + ''.join(result)
 
 
-def execute(macro, args):
+def macro_Navigation(macro,
+                    scheme=wikiutil.required_arg((u'children', u'siblings',
+                                                  u'slideshow', u'slides')),
+                    depth=0):
     # get HTML code with the links
-    navi = Navigation(macro, args or '').dispatch()
+    navi = Navigation(macro, scheme, depth).dispatch()
 
     if navi:
         # return links packed into a table
-        return '<table class="navigation"><tr><td>%s</td></tr></table>' % navi
+        return u'<table class="navigation"><tr><td>%s</td></tr></table>' % navi
 
     # navigation disabled in plain print mode
-    return ''
+    return u''
 
--- a/MoinMoin/macro/NewPage.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/macro/NewPage.py	Fri Mar 21 00:23:47 2008 +0100
@@ -40,26 +40,26 @@
             and create the page as a subpage of MoinMoinBugs.
     """
 
-    arguments = ['template', 'buttonLabel', 'parentPage', 'nameTemplate']
-
-    def __init__(self, macro, args):
+    def __init__(self, macro, template=u'', button_label=u'',
+                 parent_page=u'', name_template=u'%s'):
         self.macro = macro
         self.request = macro.request
         self.formatter = macro.formatter
-        self.args = self.getArgs(args)
-
-    def getArgs(self, argstr):
-        """ Temporary function until Oliver Graf args parser is finished
-
-        @param argstr: string from the wiki markup <<NewPage(string)>>
-        @rtype: dict
-        @return: dictionary with macro options
-        """
-        if not argstr:
-            return {}
-        args = [s.strip() for s in argstr.split(',')]
-        args = dict(zip(self.arguments, args))
-        return args
+        self.template = template
+        _ = self.request.getText
+        if button_label:
+            # Try to get a translation, this will probably not work in
+            # most cases, but better than nothing.
+            self.label = self.request.getText(button_label)
+        else:
+            self.label = _("Create New Page")
+        if parent_page == '@ME' and self.request.user.valid:
+            self.parent = self.request.user.name
+        elif parent_page == '@SELF':
+            self.parent = self.formatter.page.page_name
+        else:
+            self.parent = parent_page
+        self.nametemplate = name_template
 
     def renderInPage(self):
         """ Render macro in page context
@@ -70,32 +70,16 @@
         f = self.formatter
         _ = self.request.getText
 
-        parent = self.args.get('parentPage') or ''
-        template = self.args.get('template') or ''
-        label = self.args.get('buttonLabel')
-        nametemplate = self.args.get('nameTemplate') or u'%s'
+        requires_input = '%s' in self.nametemplate
 
-        if parent == '@ME' and self.request.user.valid:
-            parent = self.request.user.name
-        if parent == '@SELF':
-            parent = f.page.page_name
-
-        requires_input = '%s' in nametemplate
-
-        if label:
-            # Try to get a translation, this will probably not work in
-            # most cases, but better than nothing.
-            label = self.request.getText(label)
-        else:
-            label = _("Create New Page")
 
         # TODO: better abstract this using the formatter
         html = [
             u'<form class="macro" method="get" action="%s/%s"><div>' % (self.request.getScriptname(), wikiutil.quoteWikinameURL(self.formatter.page.page_name)),
             u'<input type="hidden" name="action" value="newpage">',
-            u'<input type="hidden" name="parent" value="%s">' % wikiutil.escape(parent, 1),
-            u'<input type="hidden" name="template" value="%s">' % wikiutil.escape(template, 1),
-            u'<input type="hidden" name="nametemplate" value="%s">' % wikiutil.escape(nametemplate, 1),
+            u'<input type="hidden" name="parent" value="%s">' % wikiutil.escape(self.parent, 1),
+            u'<input type="hidden" name="template" value="%s">' % wikiutil.escape(self.template, 1),
+            u'<input type="hidden" name="nametemplate" value="%s">' % wikiutil.escape(self.nametemplate, 1),
         ]
 
         if requires_input:
@@ -103,12 +87,13 @@
                 u'<input type="text" name="pagename" size="30">',
             ]
         html += [
-            u'<input type="submit" value="%s">' % wikiutil.escape(label, 1),
+            u'<input type="submit" value="%s">' % wikiutil.escape(self.label, 1),
             u'</div></form>',
             ]
         return self.formatter.rawHTML('\n'.join(html))
 
-def execute(macro, args):
+def macro_NewPage(macro, template=u'', button_label=u'',
+                  parent_page=u'', name_template=u'%s'):
     """ Temporary glue code to use with moin current macro system """
-    return NewPage(macro, args).renderInPage()
+    return NewPage(macro, template, button_label, parent_page, name_template).renderInPage()
 
--- a/MoinMoin/macro/RecentChanges.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/macro/RecentChanges.py	Fri Mar 21 00:23:47 2008 +0100
@@ -39,12 +39,11 @@
         elif action == 'ATTDRW':
             comment = _("Drawing '%(filename)s' saved.") % {
                 'filename': filename}
-    elif not comment:
-        if '/REVERT' in action:
-            rev = int(line.extra)
-            comment = _("Revert to revision %(rev)d.") % {'rev': rev}
-        elif '/RENAME' in action:
-            comment = _("Renamed from '%(oldpagename)s'.") % {'oldpagename': line.extra}
+    elif '/REVERT' in action:
+        rev = int(line.extra)
+        comment = (_("Revert to revision %(rev)d.") % {'rev': rev}) + " " + comment
+    elif '/RENAME' in action:
+        comment = (_("Renamed from '%(oldpagename)s'.") % {'oldpagename': line.extra}) + " " + comment
 
     return wikiutil.make_breakable(comment, _MAX_COMMENT_LENGTH)
 
--- a/MoinMoin/request/request_wsgi.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/request/request_wsgi.py	Fri Mar 21 00:23:47 2008 +0100
@@ -37,7 +37,20 @@
 
     def read(self, n=None):
         if n is None:
-            return self.stdin.read()
+            # We can't do that, because wsgi 1.0 requires n:
+            #return self.stdin.read()
+            # Thus, if we have no n, we have to simulate the usual behaviour (or
+            # it won't work e.g. with mod_wsgi 1.3 and maybe other wsgi 1.0 servers).
+            # Note: just requesting a extremely large amount (expecting it to never
+            # be reached, but still all data returned) also does not work (mod_wsgi
+            # 1.3 gives a MemoryError when doing that):
+            data = []
+            while True:
+                read_data = self.stdin.read(4000)
+                if not read_data:
+                    break
+                data.append(read_data)
+            return ''.join(data)
         else:
             return self.stdin.read(n)
 
--- a/MoinMoin/theme/__init__.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/theme/__init__.py	Fri Mar 21 00:23:47 2008 +0100
@@ -1008,10 +1008,9 @@
             'do_button': _("Do"),
             'baseurl': self.request.getScriptname(),
             'pagename_quoted': wikiutil.quoteWikinameURL(self.request.page.page_name),
-            'pageurl': self.request.page.url(self.request),
             }
         html = '''
-<form class="actionsmenu" method="POST" action="%(pageurl)s">
+<form class="actionsmenu" method="GET" action="">
 <div>
     <label>%(label)s</label>
     <select name="action"
--- a/MoinMoin/wikiutil.py	Fri Mar 21 00:18:04 2008 +0100
+++ b/MoinMoin/wikiutil.py	Fri Mar 21 00:23:47 2008 +0100
@@ -1646,7 +1646,7 @@
         @param argtype: the type the argument should have
         """
         if not (argtype in (bool, int, long, float, complex, unicode) or
-                isinstance(argtype, IEFArgument)):
+                isinstance(argtype, (IEFArgument, tuple, list))):
             raise TypeError("argtype must be a valid type")
         self.argtype = argtype
 
@@ -1705,7 +1705,13 @@
                 return None
             return default.parse_argument(value)
         elif isinstance(default, required_arg):
-            return _convert_arg(request, value, default.argtype, name)
+            if isinstance(default.argtype, (tuple, list)):
+                # treat choice specially and return None if no choice
+                # is given in the value
+                choices = [None] + list(default.argtype)
+                return get_choice(request, value, name, choices)
+            else:
+                return _convert_arg(request, value, default.argtype, name)
         return value
 
     assert isinstance(fixed_args, (list, tuple))
--- a/docs/CHANGES	Fri Mar 21 00:18:04 2008 +0100
+++ b/docs/CHANGES	Fri Mar 21 00:23:47 2008 +0100
@@ -1677,7 +1677,7 @@
 
   International support:    
     * mail_from can be now a unicode name-address 
-      e.g u'Jürgen wiki <noreply@jhwiki.org>'
+      e.g u'Jürgen wiki <noreply@jhwiki.org>'
 
   Theme changes:
     * logo_string is now should be really only the logo (img).
@@ -3543,7 +3543,7 @@
       there before a new version is written to disk
     * Removed the "Reset" button from EditPage
     * Added "Reduce editor size" link
-    * Added Latin-1 WikiNames (JürgenHermann ;)
+    * Added Latin-1 WikiNames (JürgenHermann ;)
     * Speeded up RecentChanges by looking up hostnames ONCE while saving
     * Show at most 14 (distinct) days in RecentChanges
     * Added icons for common functions, at the top of the page