changeset 1961:4e528d291fc0

Page*.py: improve docstrings
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sat, 07 Apr 2007 19:25:07 +0200
parents 1687a0130ebe
children 40821d91633d
files MoinMoin/Page.py MoinMoin/PageEditor.py MoinMoin/PageGraphicalEditor.py
diffstat 3 files changed, 96 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/Page.py	Sat Apr 07 16:31:57 2007 +0200
+++ b/MoinMoin/Page.py	Sat Apr 07 19:25:07 2007 +0200
@@ -9,9 +9,27 @@
     The RootPage is some virtual page located at / and is mainly used to do namespace
     operations like getting the page list. 
 
+    Currently, this is all a big mixture between high-level page code, intermediate 
+    data/underlay layering code, caching code and low-level filesystem storage code.
+    To see the filesystem storage layout we use, best is to look into data/pages/
+    (underlay dir uses the same format).
+
+    TODO:
+    * Cleanly separate the code into packages for:
+      * Page (or rather: Item)
+      * Layering
+      * Cache
+      * Storage
+    * ACLs should be handled on a low layer, raising an Exception when access
+      is denied, so we won't have security issues just because someone forgot to check
+      user.may.read(secretpage).
+    * The distinction between a item and a item revision should be clearer.
+    * Items can be anything, not just wiki pages, but also files of any mimetype.
+      The mimetype hierarchy should be modelled by a MimeTypeItem class hierarchy.
+
     @copyright: 2000-2004 by Juergen Hermann <jh@web.de>,
                 2005-2007 by MoinMoin:ThomasWaldmann,
-                2006 by MoinMoin:FlorianFesti.
+                2006 by MoinMoin:FlorianFesti,
                 2007 by ReimarBauer
     @license: GNU GPL, see COPYING for details.
 """
@@ -107,13 +125,11 @@
 
 
 class Page(object):
-    """Page - Manage an (immutable) page associated with a WikiName.
-       To change a page's content, use the PageEditor class.
+    """ Page - Manage an (immutable) page associated with a WikiName.
+        To change a page's content, use the PageEditor class.
     """
-
     def __init__(self, request, page_name, **kw):
-        """
-        Create page object.
+        """ Create page object.
 
         Note that this is a 'lean' operation, since the text for the page
         is loaded on demand. Thus, things like `Page(name).link_to()` are
@@ -184,6 +200,8 @@
         # path to normal / underlay page dir
         self._pagepath = [normalpath, underlaypath]
 
+    # now we define some properties to lazy load some attributes on first access:
+    
     def get_body(self):
         if self.__body is None:
             # try to open file
@@ -211,25 +229,25 @@
         self.__body = newbody
         self.__meta = None
         self.__data = None
-    body = property(fget=get_body, fset=set_body)
+    body = property(fget=get_body, fset=set_body) # complete page text
 
     def get_meta(self):
         if self.__meta is None:
             self.__meta, self.__data = wikiutil.get_processing_instructions(self.body)
         return self.__meta
-    meta = property(fget=get_meta)
+    meta = property(fget=get_meta) # processing instructions, ACLs (upper part of page text)
 
     def get_data(self):
         if self.__data is None:
             self.__meta, self.__data = wikiutil.get_processing_instructions(self.body)
         return self.__data
-    data = property(fget=get_data)
+    data = property(fget=get_data) # content (lower part of page text)
 
     def get_pi(self):
         if self.__pi is None:
             self.__pi = self.parse_processing_instructions()
         return self.__pi
-    pi = property(fget=get_pi)
+    pi = property(fget=get_pi) # processed meta stuff
     
     def getlines(self):
         """ Return a list of all lines in body.
@@ -243,7 +261,7 @@
         """ Load the raw markup from the page file.
 
         @rtype: unicode
-        @return: raw page contents of this page
+        @return: raw page contents of this page, unicode
         """
         return self.body
 
@@ -251,7 +269,7 @@
         """ Returns the raw markup from the page file, as a string.
 
         @rtype: str
-        @return: raw page contents of this page
+        @return: raw page contents of this page, utf-8-encoded
         """
         return self.body.encode("utf-8")
 
@@ -269,8 +287,8 @@
         self.__body_modified = modified
 
     def get_current_from_pagedir(self, pagedir):
-        """ get the current revision number from an arbitrary pagedir.
-            does not modify page object's state, uncached, direct disk access.
+        """ Get the current revision number from an arbitrary pagedir.
+            Does not modify page object's state, uncached, direct disk access.
             @param pagedir: the pagedir with the 'current' file to read
             @return: int currentrev
         """
@@ -285,10 +303,9 @@
         return rev
 
     def get_rev_dir(self, pagedir, rev=0):
-        """Get a revision of a page from an arbitrary pagedir.
+        """ Get a revision of a page from an arbitrary pagedir.
         
-        Does not modify page object's state, uncached, direct disk
-        access.
+        Does not modify page object's state, uncached, direct disk access.
 
         @param pagedir: the path to the page storage area
         @param rev: int revision to get (default is 0 and means the current
@@ -335,7 +352,7 @@
             self.page_name = realPath[-len(self.page_name):]
 
     def get_rev(self, use_underlay=-1, rev=0):
-        """Get information about a revision.
+        """ Get information about a revision.
 
         filename, number, and (existance test) of this page and revision.
 
@@ -384,7 +401,7 @@
         return data
 
     def current_rev(self):
-        """Return number of current revision.
+        """ Return number of current revision.
         
         This is the same as get_rev()[1].
         
@@ -394,8 +411,8 @@
         return rev
 
     def get_real_rev(self):
-        """Returns the real revision number of this page. A rev=0 is
-        translated to the current revision.
+        """ Returns the real revision number of this page.
+            A rev==0 is translated to the current revision.
 
         @returns: revision number > 0
         @rtype: int
@@ -405,9 +422,8 @@
         return self.rev
 
     def getPageBasePath(self, use_underlay=-1):
-        """
-        Get full path to a page-specific storage area. `args` can
-        contain additional path components that are added to the base path.
+        """ Get full path to a page-specific storage area. `args` can
+            contain additional path components that are added to the base path.
 
         @param use_underlay: force using a specific pagedir, default -1
                                 -1 = automatically choose page dir
@@ -439,9 +455,8 @@
         return underlay, path
 
     def getPageStatus(self, *args, **kw):
-        """
-        Get full path to a page-specific storage area. `args` can
-        contain additional path components that are added to the base path.
+        """ Get full path to a page-specific storage area. `args` can
+            contain additional path components that are added to the base path.
 
         @param args: additional path components
         @keyword use_underlay: force using a specific pagedir, default '-1'
@@ -471,13 +486,11 @@
         return underlay, fullpath
 
     def getPagePath(self, *args, **kw):
-        """Return path to the page storage area."""
-
+        """ Return path to the page storage area. """
         return self.getPageStatus(*args, **kw)[1]
 
     def _text_filename(self, **kw):
-        """
-        The name of the page file, possibly of an older page.
+        """ The name of the page file, possibly of an older page.
 
         @keyword rev: page revision, overriding self.rev
         @rtype: string
@@ -512,8 +525,7 @@
         return log
 
     def last_edit(self, request):
-        """
-        Return the last edit.
+        """ Return the last edit.
         This is used by MoinMoin/xmlrpc/__init__.py.
 
         @param request: the request object
@@ -614,9 +626,9 @@
         the higher level methods isUnderlayPage and isStandardPage for
         cleaner code.
 
-        @param rev: revision to look for. Default check current
-        @param domain: where to look for the page. Default look in all,
-            available values: 'underlay', 'standard'
+        @param rev: revision to look for. Default: check current
+        @param domain: where to look for the page. Default: look in all,
+                       available values: 'underlay', 'standard'
         @param includeDeleted: ignore page state, just check its pagedir
         @rtype: bool
         @return: true, if page exists
@@ -667,8 +679,7 @@
             raise
 
     def mtime_usecs(self):
-        """
-        Get modification timestamp of this page.
+        """ Get modification timestamp of this page.
 
         @rtype: long
         @return: mtime of page (or 0 if page does not exist)
@@ -696,9 +707,7 @@
         return mtime
 
     def mtime_printable(self, request):
-        """
-        Get printable (as per user's preferences) modification
-        timestamp of this page.
+        """ Get printable (as per user's preferences) modification timestamp of this page.
 
         @rtype: string
         @return: formatted string with mtime of page
@@ -712,8 +721,7 @@
         return result
 
     def split_title(self, force=0):
-        """
-        Return a string with the page name split by spaces, if the user wants that.
+        """ Return a string with the page name split by spaces, if the user wants that.
 
         @param force: if != 0, then force splitting the page_name
         @rtype: unicode
@@ -806,8 +814,7 @@
         return link
 
     def getSubscribers(self, request, **kw):
-        """
-        Get all subscribers of this page.
+        """ Get all subscribers of this page.
 
         @param request: the request object
         @keyword include_self: if 1, include current user (default: 0)
@@ -866,8 +873,8 @@
         return subscriber_list
 
     def parse_processing_instructions(self):
-        """ parse page text and extract processing instructions
-            return a dict of PIs and the non-PI rest of the body
+        """ Parse page text and extract processing instructions,
+            return a dict of PIs and the non-PI rest of the body.
         """
         from MoinMoin import i18n
         from MoinMoin import security
@@ -972,6 +979,8 @@
     def send_page(self, msg=None, **keywords):
         """ Output the formatted page.
 
+        TODO: "kill send_page(), quick" (since 2002 :)
+
         @param msg: if given, display message in header area
         @keyword content_only: if 1, omit http headers, page header and footer
         @keyword content_id: set the id of the enclosing div
@@ -1255,7 +1264,6 @@
             import MoinMoin
             if hasattr(MoinMoin, '__loader__'):
                 __file__ = os.path.join(MoinMoin.__loader__.archive, 'dummy')
-
             try:
                 exec code
             except "CacheNeedsUpdate": # convert the exception
@@ -1304,8 +1312,7 @@
         return code
 
     def _emptyPageText(self, request):
-        """
-        Output the default page content for new pages.
+        """ Output the default page content for new pages.
 
         @param request: the request object
         """
@@ -1320,8 +1327,7 @@
 
 
     def getRevList(self):
-        """
-        Get a page revision list of this page, including the current version,
+        """ Get a page revision list of this page, including the current version,
         sorted by revision number in descending order (current page first).
 
         @rtype: list of ints
@@ -1342,8 +1348,7 @@
         return revisions
 
     def olderrevision(self, rev=0):
-        """
-        Get revision of the next older page revision than rev.
+        """ Get revision of the next older page revision than rev.
         rev == 0 means this page objects revision (that may be an old
         revision already!)
         """
@@ -1590,9 +1595,8 @@
         Page.__init__(self, request, page_name)
 
     def getPageBasePath(self, use_underlay=0):
-        """
-        Get full path to a page-specific storage area. `args` can
-        contain additional path components that are added to the base path.
+        """ Get full path to a page-specific storage area. `args` can
+            contain additional path components that are added to the base path.
 
         @param use_underlay: force using a specific pagedir, default 0:
                                 1 = use underlay page dir
@@ -1796,5 +1800,3 @@
         self.request.clock.stop('getPageCount')
 
         return count
-
-
--- a/MoinMoin/PageEditor.py	Sat Apr 07 16:31:57 2007 +0200
+++ b/MoinMoin/PageEditor.py	Sat Apr 07 19:25:07 2007 +0200
@@ -4,6 +4,12 @@
     
     PageEditor is used for r/w access to a wiki page (edit, rename, delete operations).
 
+    TODO:
+    * See comments in Page.py, most apply here, too.
+    * The editor code should be modularized so we will be able to use it for any
+      text/* mimetype data with some special features enabled depending on the
+      mimetype (e.g. enable wiki markup help when editing wiki mimetype).
+  
     @copyright: 2000-2004 by Juergen Hermann <jh@web.de>,
                 2005-2007 by MoinMoin:ThomasWaldmann,
                 2007 by ReimarBauer
@@ -48,10 +54,9 @@
 ### PageEditor - Edit pages
 #############################################################################
 class PageEditor(Page):
-    """Editor for a wiki page."""
+    """ Editor for a wiki page. """
 
     # exceptions for .saveText()
-
     class SaveError(error.Error):
         pass
     class AccessDenied(SaveError):
@@ -70,8 +75,7 @@
         pass
 
     def __init__(self, request, page_name, **keywords):
-        """
-        Create page editor object.
+        """ Create page editor object.
         
         @param page_name: name of the page
         @param request: the request object
@@ -118,7 +122,7 @@
         return False
 
     def sendconfirmleaving(self):
-        """ to prevent moving away from the page without saving it """
+        """ Prevents moving away from the page without saving it. """
         _ = self._
         self.request.write(u'''\
 <script type="text/javascript">
@@ -131,8 +135,7 @@
 ''' % _("Your changes are not saved!"))
 
     def sendEditor(self, **kw):
-        """
-        Send the editor form page.
+        """ Send the editor form page.
 
         @keyword preview: if given, show this text in preview mode
         @keyword staytop: don't go to #preview
@@ -471,9 +474,8 @@
         request.theme.send_closing_html()
 
     def sendCancel(self, newtext, rev):
-        """
-        User clicked on Cancel button. If edit locking is active,
-        delete the current lock file.
+        """ User clicked on Cancel button.
+            If edit locking is active, delete the current lock file.
 
         @param newtext: the edited text (which has been cancelled)
         @param rev: not used!?
@@ -488,8 +490,7 @@
         page.send_page(msg=_('Edit was cancelled.'))
 
     def copyPage(self, newpagename, comment=None):
-        """
-        Copy the current version of the page (keeping the backups, logs and attachments).
+        """ Copy the current version of the page (keeping the backups, logs and attachments).
 
         @param comment: Comment given by user
         @rtype: unicode
@@ -554,9 +555,8 @@
                 return False, _('Could not copy page because of file system error: %s.') % unicode(err)
 
     def renamePage(self, newpagename, comment=None):
-        """
-        Rename the current version of the page (making a backup before deletion
-        and keeping the backups, logs and attachments).
+        """ Rename the current version of the page (making a backup before deletion
+            and keeping the backups, logs and attachments).
 
         @param comment: Comment given by user
         @rtype: unicode
@@ -632,9 +632,8 @@
                 return False, _('Could not rename page because of file system error: %s.') % unicode(err)
 
     def deletePage(self, comment=None):
-        """
-        Delete the current version of the page (making a backup before deletion
-        and keeping the backups, logs and attachments).
+        """ Delete the current version of the page (making a backup before deletion
+            and keeping the backups, logs and attachments).
 
         @param comment: Comment given by user
         @rtype: unicode
@@ -675,8 +674,8 @@
         return success, msg
 
     def _sendNotification(self, comment, emails, email_lang, revisions, trivial):
-        """
-        Send notification email for a single language.
+        """ Send notification email for a single language.
+
         @param comment: editor's comment given when saving the page
         @param emails: list of email addresses
         @param email_lang: language of emails
@@ -733,8 +732,7 @@
 
 
     def _notifySubscribers(self, comment, trivial):
-        """
-        Send email to all subscribers of this page.
+        """ Send email to all subscribers of this page.
 
         @param comment: editor's comment given when saving the page
         @param trivial: editor's suggestion that the change is trivial (Subscribers may ignore this)
@@ -765,8 +763,7 @@
         return ''
 
     def _get_local_timestamp(self):
-        """
-        Returns the string that can be used by the TIME substitution.
+        """ Returns the string that can be used by the TIME substitution.
 
         @return: str with a timestamp in it
         """
@@ -793,8 +790,7 @@
         return time.strftime("%Y-%m-%dT%H:%M:%S", timefuncs.tmtuple(now)) + zone
 
     def _expand_variables(self, text):
-        """
-        Expand @VARIABLE@ in `text`and return the expanded text.
+        """ Expand @VARIABLE@ in `text`and return the expanded text.
         
         @param text: current text of wikipage
         @rtype: string
@@ -911,9 +907,7 @@
 
     def copy_underlay_page(self):
         # renamed from copypage to avoid conflicts with copyPage
-        """
-        Copy a page from underlay directory to page directory
-        """
+        """ Copy a page from underlay directory to page directory """
         src = self.getPagePath(use_underlay=1, check_create=0)
         dst = self.getPagePath(use_underlay=0, check_create=0)
         if src and dst and src != dst and os.path.exists(src):
@@ -1161,9 +1155,7 @@
 
 
 class PageLock:
-    """
-    PageLock - Lock pages
-    """
+    """ PageLock - Lock pages """
     # TODO: race conditions throughout, need to lock file during queries & update
     def __init__(self, pageobj):
         """
@@ -1195,8 +1187,7 @@
 
 
     def acquire(self):
-        """
-        Begin an edit lock depending on the mode chosen in the config.
+        """ Begin an edit lock depending on the mode chosen in the config.
 
         @rtype: tuple
         @return: tuple is returned containing 2 values:
@@ -1262,8 +1253,7 @@
 
 
     def release(self, force=0):
-        """ 
-        Release lock, if we own it.
+        """ Release lock, if we own it.
 
         @param force: if 1, unconditionally release the lock.
         """
@@ -1276,12 +1266,12 @@
 
 
     def _filename(self):
-        """get path and filename for edit-lock file"""
+        """ Get path and filename for edit-lock file. """
         return self.pageobj.getPagePath('edit-lock', isfile=1)
 
 
     def _readLockFile(self):
-        """Load lock info if not yet loaded."""
+        """ Load lock info if not yet loaded. """
         _ = self._
         self.owner = None
         self.owner_html = wikiutil.escape(_("<unknown>"))
@@ -1300,7 +1290,7 @@
 
 
     def _writeLockFile(self):
-        """Write new lock file."""
+        """ Write new lock file. """
         self._deleteLockFile()
         try:
             editlog.EditLog(self.request, filename=self._filename()).add(
@@ -1309,7 +1299,7 @@
             pass
 
     def _deleteLockFile(self):
-        """Delete the lock file unconditionally."""
+        """ Delete the lock file unconditionally. """
         try:
             os.remove(self._filename())
         except OSError:
--- a/MoinMoin/PageGraphicalEditor.py	Sat Apr 07 16:31:57 2007 +0200
+++ b/MoinMoin/PageGraphicalEditor.py	Sat Apr 07 19:25:07 2007 +0200
@@ -4,6 +4,9 @@
 
     Same as PageEditor, but we use the HTML based GUI editor here.
 
+    TODO:
+    * see PageEditor.py
+
     @copyright: 2006 Bastian Blank, Florian Festi,
                 2006-2007 MoinMoin:ThomasWaldmann
     @license: GNU GPL, see COPYING for details.
@@ -28,15 +31,14 @@
 
 
 class PageGraphicalEditor(PageEditor.PageEditor):
-
+    """ Same as PageEditor, but use the GUI editor (FCKeditor) """
     def word_rule(self):
         regex = re.compile(r"\(\?<![^)]*?\)")
         word_rule = regex.sub("", WikiParser.word_rule)
         return repr(word_rule)[1:]
 
     def sendEditor(self, **kw):
-        """
-        Send the editor form page.
+        """ Send the editor form page.
 
         @keyword preview: if given, show this text in preview mode
         @keyword staytop: don't go to #preview