changeset 1034:06a2fd20eab7

Merge with upstream.
author Alexander Schremmer <alex AT alexanderweb DOT de>
date Fri, 21 Jul 2006 02:36:01 +0200
parents e1239c38785c (diff) c51d2f5b04db (current diff)
children 742545e99167 b339cd4e61c9
files docs/CHANGES.aschremmer
diffstat 5 files changed, 109 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/Page.py	Thu Jul 20 17:24:28 2006 +0200
+++ b/MoinMoin/Page.py	Fri Jul 21 02:36:01 2006 +0200
@@ -1177,7 +1177,7 @@
                     # XXX The following code is commented because it is incorrect for dynamic pages:
                     #lastmod = os.path.getmtime(self._text_filename())
                     #request.http_headers(["Last-Modified: %s" % timefuncs.formathttpdate(lastmod)])
-                    pass
+                    request.http_headers()
             else:
                 request.http_headers(['Status: 404 NOTFOUND'])
                 request.setResponseCode(404)
--- a/MoinMoin/action/SyncPages.py	Thu Jul 20 17:24:28 2006 +0200
+++ b/MoinMoin/action/SyncPages.py	Fri Jul 21 02:36:01 2006 +0200
@@ -9,26 +9,39 @@
 """
 
 import os
+import re
 import zipfile
 import xmlrpclib
 from datetime import datetime
 
 from MoinMoin import wikiutil, config, user
+from MoinMoin.packages import unpackLine
 from MoinMoin.PageEditor import PageEditor
 from MoinMoin.Page import Page
 from MoinMoin.wikidicts import Dict
 
 class ActionStatus(Exception): pass
 
+class RemotePage(object):
+    """ This class represents a page in (another) wiki. """
+    def __init__(self, name, revno):
+        self.name = name
+        self.revno = revno
+
 class RemoteWiki(object):
     """ This class should be the base for all implementations of remote wiki
         classes. """
+
+    def __repr__(self):
+        """ Returns a representation of the instance for debugging purposes. """
+        return NotImplemented
+
     def getInterwikiName(self):
         """ Returns the interwiki name of the other wiki. """
         return NotImplemented
-    
-    def __repr__(self):
-        """ Returns a representation of the instance for debugging purposes. """
+
+    def getRemotePages(self):
+        """ Returns a list of RemotePage instances. """
         return NotImplemented
 
 class MoinWiki(RemoteWiki):
@@ -38,6 +51,7 @@
         self.valid = not wikitag_bad
         self.xmlrpc_url = self.wiki_url + "?action=xmlrpc2"
         self.connection = self.createConnection()
+        # XXX add version and interwiki name checking!
 
     def createConnection(self):
         return xmlrpclib.ServerProxy(self.xmlrpc_url, allow_none=True)
@@ -46,6 +60,10 @@
     def getInterwikiName(self):
         return self.connection.interwikiName()
 
+    def getRemotePages(self):
+        pages = self.connection.getAllPagesEx({"include_revno": True})
+        return [RemotePage(unicode(name), revno) for name, revno in pages]
+
     def __repr__(self):
         return "<RemoteWiki wiki_url=%r valid=%r>" % (self.valid, self.wiki_url)
 
@@ -55,44 +73,74 @@
         self.pagename = pagename
         self.page = Page(request, pagename)
 
-    def parsePage(self):
-        defaults = {
+    def parse_page(self):
+        options = {
             "remotePrefix": "",
             "localPrefix": "",
-            "remoteWiki": ""
+            "remoteWiki": "",
+            "localMatch": None,
+            "remoteMatch": None,
+            "pageList": None,
+            "groupList": None,
         }
+
+        options.update(Dict(self.request, self.pagename).get_dict())
+
+        # Convert page and group list strings to lists
+        if options["pageList"] is not None:
+            options["pageList"] = unpackLine(options["pageList"], ",")
+        if options["groupList"] is not None:
+            options["groupList"] = unpackLine(options["groupList"], ",")
+
+        return options
+
+    def fix_params(self, params):
+        """ Does some fixup on the parameters. """
+
+        # merge the pageList case into the remoteMatch case
+        if params["pageList"] is not None:
+            params["remoteMatch"] = u'|'.join([r'^%s$' % re.escape(name) for name in params["pageList"]])
+
+        if params["localMatch"] is not None:
+            params["localMatch"] = re.compile(params["localMatch"], re.U)
         
-        defaults.update(Dict(self.request, self.pagename).get_dict())
-        return defaults
-        
+        if params["remoteMatch"] is not None:
+            params["remoteMatch"] = re.compile(params["remoteMatch"], re.U)
+
+        return params
+
     def render(self):
         """ Render action
 
-        This action returns a wiki page with optional message, or
-        redirects to new page.
+        This action returns a status message.
         """
         _ = self.request.getText
-        
-        params = self.parsePage()
-        
+
+        params = self.fix_params(self.parse_page())
+
+
         try:
             if not self.request.cfg.interwikiname:
                 raise ActionStatus(_("Please set an interwikiname in your wikiconfig (see HelpOnConfiguration) to be able to use this action."))
 
             if not params["remoteWiki"]:
                 raise ActionStatus(_("Incorrect parameters. Please supply at least the ''remoteWiki'' parameter."))
-            
+
             remote = MoinWiki(params["remoteWiki"])
-            
+
             if not remote.valid:
                 raise ActionStatus(_("The ''remoteWiki'' is unknown."))
-            
-            # ...
-            self.sync(params)
+
+            self.sync(params, remote)
         except ActionStatus, e:
             return self.page.send_page(self.request, msg=u'<p class="error">%s</p>\n' % (e.args[0], ))
 
         return self.page.send_page(self.request, msg=_("Syncronisation finished."))
     
+    def sync(self, params, remote):
+        """ This method does the syncronisation work. """
+        
+        r_pages = remote.getRemotePages()
+
 def execute(pagename, request):
     ActionClass(pagename, request).render()
--- a/MoinMoin/mail/sendmail.py	Thu Jul 20 17:24:28 2006 +0200
+++ b/MoinMoin/mail/sendmail.py	Fri Jul 21 02:36:01 2006 +0200
@@ -74,7 +74,13 @@
     charset.header_encoding = QP
     charset.body_encoding = QP
     msg.set_charset(charset)
-    msg.set_payload(charset.body_encode(text))
+
+    # work around a bug in python 2.4.3 and above:
+    msg.set_payload('=')
+    if msg.as_string().endswith('='):
+        text = charset.body_encode(text)
+
+    msg.set_payload(text)
 
     # Create message headers
     # Don't expose emails addreses of the other subscribers, instead we
--- a/MoinMoin/xmlrpc/__init__.py	Thu Jul 20 17:24:28 2006 +0200
+++ b/MoinMoin/xmlrpc/__init__.py	Fri Jul 21 02:36:01 2006 +0200
@@ -219,10 +219,37 @@
         """ Get all pages readable by current user
 
         @rtype: list
-        @return: a list of all pages. The result is a list of utf-8 strings.
+        @return: a list of all pages.
         """
-        pagelist = self.request.rootpage.getPageList()
-        return map(self._outstr, pagelist)
+
+        return [self._outstr(x) for x in self.request.rootpage.getPageList()]
+
+
+    def xmlrpc_getAllPagesEx(self, opts=None):
+        """ Get all pages readable by current user. Not an WikiRPC method.
+
+        @param opts: dictionary that can contain the following arguments:
+                include_system:: set it to false if you do not want to see system pages
+                include_revno:: set it to True if you want to have lists with [pagename, revno]
+                include_deleted:: set it to True if you want to include deleted pages
+        @rtype: list
+        @return: a list of all pages.
+        """
+        options = {"include_system": True, "include_revno": False, "include_deleted": False}
+        if opts is not None:
+            options.update(opts)
+
+        if options["include_system"]:
+            filter = lambda name: not wikiutil.isSystemPage(self.request, name)
+        else:
+            filter = lambda name: True
+
+        pagelist = self.request.rootpage.getPageList(filter=filter, exists=not options["include_deleted"])
+        
+        if options['include_revno']:
+            return [[self._outstr(x), Page(self.request, x).get_real_rev()] for x in pagelist]
+        else:
+            return [self._outstr(x) for x in pagelist]
 
     def xmlrpc_getRecentChanges(self, date):
         """ Get RecentChanges since date
--- a/docs/CHANGES.aschremmer	Thu Jul 20 17:24:28 2006 +0200
+++ b/docs/CHANGES.aschremmer	Fri Jul 21 02:36:01 2006 +0200
@@ -11,7 +11,7 @@
     * Implement a cross-site authentication system, i.e. mainly an
       identity storage.
     * Clean up trailing whitespace.
-    * Add page locking.
+    * Add page locking, i.e. use the one in the new storage layer.
     * How about using unique IDs that just derive from the interwikiname?
 
   New Features:
@@ -24,6 +24,8 @@
     * XMLRPC method to merge remote changes locally
     * XMLRPC method to get the interwiki name
     * TagStore/PickleTagStore class
+    * XMLRPC method to get the pagelist in a special way (revnos,
+      no system pages etc.)
 
   Bugfixes (only stuff that is buggy in moin/1.6 main branch):
     * Conflict resolution fixes.
@@ -62,7 +64,7 @@
          added interwikiName XMLRPC method, added mergeChanges XMLRPC method. Started analysis of the moinupdate
          script written by Stefan Merten.
 Week 29: Finished first version of the mergeChanges method. Added Tag and TagStore classes which are currently
-         using pickle-based storage.
+         using pickle-based storage. Added getAllPagesEx XMLRPC method.
 
 2006-07-18: the requested daily entry is missing here, see http://moinmoin.wikiwikiweb.de/GoogleSoc2006/BetterProgress
 2006-07-19: the requested daily entry is missing here, see http://moinmoin.wikiwikiweb.de/GoogleSoc2006/BetterProgress