changeset 386:44a5abc782ee

Fixed line endings in rst parser and removed the copy import. imported from: moin--main--1.5--patch-390
author Alexander Schremmer <alex@alexanderweb.de.tla>
date Wed, 18 Jan 2006 13:03:07 +0000
parents 795eef4b227d
children 82e784448a27
files ChangeLog MoinMoin/parser/rst.py
diffstat 2 files changed, 569 insertions(+), 560 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jan 18 08:48:13 2006 +0000
+++ b/ChangeLog	Wed Jan 18 13:03:07 2006 +0000
@@ -2,6 +2,18 @@
 # arch-tag: automatic-ChangeLog--arch@arch.thinkmo.de--2003-archives/moin--main--1.5
 #
 
+2006-01-18 14:03:07 GMT	Alexander Schremmer <alex@alexanderweb.de.tla>	patch-390
+
+    Summary:
+      Fixed line endings in rst parser and removed the copy import.
+    Revision:
+      moin--main--1.5--patch-390
+
+
+    modified files:
+     ChangeLog MoinMoin/parser/rst.py
+
+
 2006-01-18 09:48:13 GMT	Thomas Waldmann <tw@waldmann-edv.de>	patch-389
 
     Summary:
--- a/MoinMoin/parser/rst.py	Wed Jan 18 08:48:13 2006 +0000
+++ b/MoinMoin/parser/rst.py	Wed Jan 18 13:03:07 2006 +0000
@@ -1,560 +1,557 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - ReStructured Text Parser
-
-    @copyright: 2004 by Matthew Gilbert <gilbert AT voxmea DOT net>
-        and by Alexander Schremmer <alex AT alexanderweb DOT de>
-    @license: GNU GPL, see COPYING for details.
-
-    REQUIRES docutils 0.3.10 or later (must be later than December 30th, 2005)
-"""
-
-import re
-import new
-import StringIO
-import __builtin__
-import sys
-
-#import copy #broken, see comments at top of this file:
-from MoinMoin.support import copy
-
-import types
-import os
-
-# docutils imports are below
-import MoinMoin.parser.wiki
-from MoinMoin.Page import Page
-from MoinMoin.action import AttachFile
-from MoinMoin import wikiutil
-
-Dependencies = [] # this parser just depends on the raw text
-
-# --- make docutils safe by overriding all module-scoped names related to IO ---
-
-# TODO: Add an error message to dummyOpen so that the user knows what they did
-# requested an unsupported feature of docutils in MoinMoin.
-def dummyOpen(x, y=None, z=None): return
-
-class dummyIO(StringIO.StringIO):
-    def __init__(self, destination=None, destination_path=None,
-                 encoding=None, error_handler='', autoclose=1,
-                 handle_io_errors=1, source_path=None):
-        StringIO.StringIO.__init__(self)
-
-class dummyUrllib2:
-    def urlopen(a):
-        return StringIO.StringIO()
-    urlopen = staticmethod(urlopen)
-
-# # # All docutils imports must be contained below here
-try:
-    import docutils
-    from docutils.core import publish_parts
-    from docutils.writers import html4css1
-    from docutils.nodes import reference
-    from docutils.parsers import rst
-    from docutils.parsers.rst import directives, roles
-# # # All docutils imports must be contained above here
-
-    ErrorParser = None # used in the case of missing docutils
-    docutils.io.FileOutput = docutils.io.FileInput = dummyIO
-except ImportError:
-    # we need to workaround this totally broken plugin interface that does
-    # not allow us to raise exceptions
-    class ErrorParser:
-        caching = 0
-        Dependencies = Dependencies # copy dependencies from module-scope
-
-        def __init__(self, raw, request, **kw):
-            self.raw = raw
-            self.request = request
-    
-        def format(self, formatter):
-            _ = self.request.getText
-            from MoinMoin.parser import plain
-            self.request.write(formatter.sysmsg(1) +
-                               formatter.rawHTML(_('Rendering of reStructured text is not possible, ''please'' install docutils.')) +
-                               formatter.sysmsg(0))
-            plain.Parser(self.raw, self.request).format(formatter)
-    
-    # Create a pseudo docutils environment
-    docutils = html4css1 = dummyUrllib2()
-    html4css1.HTMLTranslator = html4css1.Writer = object
-
-def safe_import(name, globals = None, locals = None, fromlist = None):
-    mod = __builtin__.__import__(name, globals, locals, fromlist)
-    if mod:
-        mod.open = dummyOpen
-        mod.urllib2 = dummyUrllib2
-    return mod
-
-# Go through and change all docutils modules to use a dummyOpen and dummyUrllib2
-# module. Also make sure that any docutils imported modules also get the dummy
-# implementations.
-for i in sys.modules.keys():
-    if i.startswith('docutils') and sys.modules[i]:
-        sys.modules[i].open = dummyOpen
-        sys.modules[i].urllib2 = dummyUrllib2
-        sys.modules[i].__import__ = safe_import
-        
-# --- End of dummy-code --------------------------------------------------------
-
-def html_escape_unicode(node):
-    # Find Python function that does this for me. string.encode('ascii',
-    # 'xmlcharrefreplace') only 2.3 and above.
-    for i in node:
-        if ord(i) > 127:
-            node = node.replace(i, '&#%d;' % (ord(i)))
-    return node
-
-class MoinWriter(html4css1.Writer):
-
-    config_section = 'MoinMoin writer'
-    config_section_dependencies = ('writers',)
-
-    #"""Final translated form of `document`."""
-    output = None
-
-    def wiki_resolver(self, node):
-        """
-            Normally an unknown reference would be an error in an reST document.
-            However, this is how new documents are created in the wiki. This
-            passes on unknown references to eventually be handled by
-            MoinMoin.
-        """
-        if hasattr(node, 'indirect_reference_name'):
-            node['refuri'] = node.indirect_reference_name
-        elif (len(node['ids']) != 0):
-            # If the node has an id then it's probably an internal link. Let
-            # docutils generate an error.
-            return False
-        elif node.hasattr('name'):
-            node['refuri'] = node['name']
-        else:
-            node['refuri'] = node['refname']
-        del node['refname']
-        node.resolved = 1
-        self.nodes.append(node)
-        return True
-
-    wiki_resolver.priority = 001
-
-    def __init__(self, formatter, request):
-        html4css1.Writer.__init__(self)
-        self.formatter = formatter
-        self.request = request
-        # Add our wiki unknown_reference_resolver to our list of functions to
-        # run when a target isn't found
-        self.unknown_reference_resolvers = [self.wiki_resolver]
-        # We create a new parser to process MoinMoin wiki style links in the
-        # reST.
-        self.wikiparser = MoinMoin.parser.wiki.Parser('', self.request)
-        self.wikiparser.formatter = self.formatter
-        self.wikiparser.hilite_re = None
-        self.nodes = []
-        # Make sure it's a supported docutils version.
-        required_version = (0, 3, 10)
-        current_version = tuple([int(i) for i in (docutils.__version__.split('.')+['0','0'])[:3]])
-        if current_version < required_version:
-            err = 'ERROR: The installed docutils version is %s;' % ('.'.join([str(i) for i in current_version]))
-            err += ' version %s or later is required.' % ('.'.join([str(i) for i in required_version]))
-            raise RuntimeError, err
-
-    def translate(self):
-        visitor = MoinTranslator(self.document,
-                                 self.formatter,
-                                 self.request,
-                                 self.wikiparser,
-                                 self)
-        self.document.walkabout(visitor)
-        self.visitor = visitor
-        self.output = html_escape_unicode(visitor.astext())
-
-class Parser:
-    caching = 1
-    Dependencies = Dependencies # copy dependencies from module-scope
-
-    def __init__(self, raw, request, **kw):
-        self.raw = raw
-        self.request = request
-        self.form = request.form
-
-    def format(self, formatter):
-        # Create our simple parser
-        parser = MoinDirectives(self.request)
-
-        parts = publish_parts(
-            source = self.raw,
-            writer = MoinWriter(formatter, self.request),
-            settings_overrides = {
-                'halt_level': 5,
-                'traceback': True,
-                'file_insertion_enabled': 0,
-                'raw_enabled': 0,
-                'stylesheet_path': '',
-            }
-        )
-
-        html = []
-        if parts['title']:
-            html.append(formatter.rawHTML('<h2>' + parts['title'] + '</h2>'))
-        # If there is only one subtitle then it is held in parts['subtitle'].
-        # However, if there is more than one subtitle then this is empty and
-        # fragment contains all of the subtitles.
-        if parts['subtitle']:
-            html.append(formatter.rawHTML('<h3>' + parts['subtitle'] + '</h3>'))
-        if parts['docinfo']:
-            html.append(parts['docinfo'])
-        html.append(parts['fragment'])
-        self.request.write(html_escape_unicode('\n'.join(html)))
-
-class RawHTMLList(list):
-    """
-        RawHTMLList catches all html appended to internal HTMLTranslator lists.
-        It passes the HTML through the MoinMoin rawHTML formatter to strip 
-        markup when necessary. This is to support other formatting outputs
-        (such as ?action=format&mimetype=text/plain).
-    """
-    
-    def __init__(self, formatter):
-        self.formatter = formatter
-        
-    def append(self, text):
-        f = sys._getframe()
-        if f.f_back.f_code.co_filename.endswith('html4css1.py'):
-            if isinstance(text, types.StringType) or isinstance(text, types.UnicodeType):
-                text = self.formatter.rawHTML(text)
-        list.append(self, text)
-
-class MoinTranslator(html4css1.HTMLTranslator):
-
-    def __init__(self, document, formatter, request, parser, writer):
-        html4css1.HTMLTranslator.__init__(self, document)
-        self.formatter = formatter
-        self.request = request
-        # Using our own writer when needed. Save the old one to restore
-        # after the page has been processed by the html4css1 parser.
-        self.original_write, self.request.write = self.request.write, self.capture_wiki_formatting
-        self.wikiparser = parser
-        self.wikiparser.request = request
-        # MoinMoin likes to start the initial headers at level 3 and the title
-        # gets level 2, so to comply with their styles, we do here also.
-        # TODO: Could this be fixed by passing this value in settings_overrides?
-        self.initial_header_level = 3
-        # Temporary place for wiki returned markup. This will be filled when
-        # replacing the default writer with the capture_wiki_formatting
-        # function (see visit_image for an example).
-        self.wiki_text = ''
-        self.setup_wiki_handlers()
-        
-        # Make all internal lists RawHTMLLists, see RawHTMLList class
-        # comment for more information.
-        for i in self.__dict__:
-            if isinstance(getattr(self, i), types.ListType):
-                setattr(self, i, RawHTMLList(formatter))
-
-    def depart_docinfo(self, node):
-        """
-            depart_docinfo assigns a new list to self.body, we need to re-make that
-            into a RawHTMLList.
-        """
-        html4css1.HTMLTranslator.depart_docinfo(self, node)
-        self.body = RawHTMLList(self.formatter)
-
-    def capture_wiki_formatting(self, text):
-        """
-            Captures MoinMoin generated markup to the instance variable
-            wiki_text.
-        """
-        # For some reason getting empty strings here which of course overwrites
-        # what we really want (this is called multiple times per MoinMoin
-        # format call, which I don't understand).
-        self.wiki_text += text
-
-    def process_wiki_text(self, text):
-        """
-            This sequence is repeated numerous times, so its captured as a
-            single call here. Its important that wiki_text is blanked before we
-            make the format call. format will call request.write which we've
-            hooked to capture_wiki_formatting. If wiki_text is not blanked
-            before a call to request.write we will get the old markup as well as
-            the newly generated markup.
-
-            TODO: Could implement this as a list so that it acts as a stack. I
-            don't like having to remember to blank wiki_text.
-        """
-        self.wiki_text = ''
-        self.wikiparser.raw = text
-        self.wikiparser.format(self.formatter)
-
-    def add_wiki_markup(self):
-        """
-            Place holder in case this becomes more elaborate someday. For now it
-            only appends the MoinMoin generated markup to the html body and
-            raises SkipNode.
-        """
-        self.body.append(self.wiki_text)
-        self.wiki_text = ''
-        raise docutils.nodes.SkipNode
-
-    def astext(self):
-        self.request.write = self.original_write
-        return html4css1.HTMLTranslator.astext(self)
-
-    def fixup_wiki_formatting(self, text):
-        replacement = {'<p>': '', '</p>': '', '\n': '', '> ': '>'}
-        for src, dst in replacement.items():
-            text = text.replace(src, dst)
-        # Everything seems to have a space ending the text block. We want to
-        # get rid of this
-        if text and text[-1] == ' ':
-            text = text[:-1]
-        return text
-
-    def visit_reference(self, node):
-        """
-            Pass links to MoinMoin to get the correct wiki space url. Extract
-            the url and pass it on to the html4css1 writer to handle. Inline
-            images are also handled by visit_image. Not sure what the "drawing:"
-            link scheme is used for, so for now it is handled here.
-
-            Also included here is a hack to allow MoinMoin macros. This routine
-            checks for a link which starts with "[[". This link is passed to the
-            MoinMoin formatter and the resulting markup is inserted into the
-            document in the place of the original link reference.
-        """
-        if 'refuri' in node.attributes:
-            refuri = node['refuri']
-            prefix = ''
-            link = refuri
-            if ':' in refuri:
-                prefix, link = refuri.lstrip().split(':', 1)
-            
-            # First see if MoinMoin should handle completely. Exits through add_wiki_markup.
-            if ((refuri.startswith('[[') and refuri.endswith(']]')) or 
-                    (prefix == 'drawing') or
-                    (prefix == 'inline')):
-                self.process_wiki_text(refuri)
-                # Don't call fixup_wiki_formatting because who knows what
-                # MoinMoin is inserting. (exits through add_wiki_markup)
-                self.add_wiki_markup()
-
-            # From here down, all links are handled by docutils (except 
-            # missing attachments), just fixup node['refuri'].
-            if prefix == 'attachment':
-                attach_file = AttachFile.getFilename(self.request, 
-                        self.request.page.page_name, link)
-                if not os.path.exists(attach_file):
-                    # Attachment doesn't exist, give to MoinMoin to insert
-                    # upload text.
-                    self.process_wiki_text(refuri)
-                    self.add_wiki_markup()
-                # Attachment exists, just get a link to it.
-                node['refuri'] = AttachFile.getAttachUrl(self.request.page.page_name, 
-                        link, self.request)
-                if not [i for i in node.children if i.__class__ == docutils.nodes.image]:
-                    node['classes'].append(prefix)                
-            elif prefix == 'wiki':
-                wikitag, wikiurl, wikitail, err = wikiutil.resolve_wiki(self.request, link)
-                wikiurl = wikiutil.mapURL(self.request, wikiurl)
-                node['refuri'] = wikiutil.join_wiki(wikiurl, wikitail)
-                # Only add additional class information if the reference does
-                # not have a child image (don't want to add additional markup
-                # for images with targets).
-                if not [i for i in node.children if i.__class__ == docutils.nodes.image]:
-                    node['classes'].append('interwiki')
-            elif prefix != '':
-                # Some link scheme (http, file, https, mailto, etc.), add class
-                # information if the reference doesn't have a child image (don't 
-                # want additional markup for images with targets). 
-                # Don't touch the refuri.
-                if not [i for i in node.children if i.__class__ == docutils.nodes.image]:
-                    node['classes'].append(prefix)
-            else:
-                # Default case - make a link to a wiki page.
-                page = MoinMoin.Page.Page(self.request, refuri)
-                node['refuri'] = page.url(self.request)
-                if not page.exists():
-                    node['classes'].append('nonexistent')
-        html4css1.HTMLTranslator.visit_reference(self, node)
-
-    def visit_image(self, node):
-        """
-            Need to intervene in the case of inline images. We need MoinMoin to
-            give us the actual src line to the image and then we can feed this
-            to the default html4css1 writer. NOTE: Since the writer can't "open"
-            this image the scale attribute doesn't work without directly
-            specifying the height or width (or both).
-
-            TODO: Need to handle figures similarly.
-        """
-        uri = node['uri'].lstrip()
-        prefix = ''          # assume no prefix
-        attach_name = uri
-        if ':' in uri:
-            prefix = uri.split(':', 1)[0]
-            attach_name = uri.split(':', 1)[1]
-        # if prefix isn't URL, try to display in page
-        if not prefix.lower() in ('file', 'http', 'https', 'ftp'):
-            attach_file = AttachFile.getFilename(self.request, 
-                    self.request.page.page_name, attach_name)
-            if not os.path.exists(attach_file):
-                # Attachment doesn't exist, MoinMoin should process it
-                if prefix == '':
-                    prefix = 'inline:'
-                self.process_wiki_text(prefix + attach_name)
-                self.wiki_text = self.fixup_wiki_formatting(self.wiki_text)
-                self.add_wiki_markup()
-            # Attachment exists, get a link to it.
-            # create the url
-            node['uri'] = AttachFile.getAttachUrl(self.request.page.page_name, 
-                    attach_name, self.request, addts = 1)
-            if not node.hasattr('alt'):
-                node['alt'] = node.get('name', uri)
-        html4css1.HTMLTranslator.visit_image(self, node)
-
-    def create_wiki_functor(self, moin_func):
-        moin_callable = getattr(self.formatter, moin_func)
-        def visit_func(self, node):
-            self.wiki_text = ''
-            self.request.write(moin_callable(1))
-            self.body.append(self.wiki_text)
-        def depart_func(self, node):
-            self.wiki_text = ''
-            self.request.write(moin_callable(0))
-            self.body.append(self.wiki_text)
-        return visit_func, depart_func
-
-    def setup_wiki_handlers(self):
-        """
-            Have the MoinMoin formatter handle markup when it makes sense. These
-            are portions of the document that do not contain reST specific
-            markup. This allows these portions of the document to look
-            consistent with other wiki pages.
-
-            Setup dispatch routines to handle basic document markup. The
-            hanlders dict is the html4css1 handler name followed by the wiki
-            handler name.
-        """
-        handlers = {
-            # Text Markup
-            'emphasis': 'emphasis',
-            'strong': 'strong',
-            'literal': 'code',
-            # Blocks
-            'literal_block': 'preformatted',
-            # Simple Lists
-            # bullet-lists are handled completely by docutils because it uses
-            # the node context to decide when to make a compact list 
-            # (no <p> tags).
-            'list_item': 'listitem',
-            # Definition List
-            'definition_list': 'definition_list',
-            # Admonitions
-            'warning': 'highlight'
-        }
-        for rest_func, moin_func in handlers.items():
-            visit_func, depart_func = self.create_wiki_functor(moin_func)
-            visit_func = new.instancemethod(visit_func, self, MoinTranslator)
-            depart_func = new.instancemethod(depart_func, self, MoinTranslator)
-            setattr(self, 'visit_%s' % (rest_func), visit_func)
-            setattr(self, 'depart_%s' % (rest_func), depart_func)
-
-    # Enumerated list takes an extra paramter so we handle this differently
-    def visit_enumerated_list(self, node):
-        self.wiki_text = ''
-        self.request.write(self.formatter.number_list(1, start=node.get('start', None)))
-        self.body.append(self.wiki_text)
-
-    def depart_enumerated_list(self, node):
-        self.wiki_text = ''
-        self.request.write(self.formatter.number_list(0))
-        self.body.append(self.wiki_text)
-
-
-class MoinDirectives:
-    """
-        Class to handle all custom directive handling. This code is called as
-        part of the parsing stage.
-    """
-
-    def __init__(self, request):
-        self.request = request
-
-        # include MoinMoin pages
-        directives.register_directive('include', self.include)
-
-        # used for MoinMoin macros
-        directives.register_directive('macro', self.macro)
-
-        # disallow a few directives in order to prevent XSS
-        # for directive in ('meta', 'include', 'raw'):
-        for directive in ('meta', 'raw'):
-            directives.register_directive(directive, None)
-
-        # disable the raw role
-        roles._roles['raw'] = None
-
-        # As a quick fix for infinite includes we only allow a fixed number of
-        # includes per page
-        self.num_includes = 0
-        self.max_includes = 10
-
-    # Handle the include directive rather than letting the default docutils
-    # parser handle it. This allows the inclusion of MoinMoin pages instead of
-    # something from the filesystem.
-    def include(self, name, arguments, options, content, lineno,
-                content_offset, block_text, state, state_machine):
-        # content contains the included file name
-
-        _ = self.request.getText
-
-        # Limit the number of documents that can be included
-        if self.num_includes < self.max_includes:
-            self.num_includes += 1
-        else:
-            lines = [_("**Maximum number of allowed includes exceeded**")]
-            state_machine.insert_input(lines, 'MoinDirectives')
-            return
-
-        if len(content):
-            page = Page(page_name = content[0], request = self.request)
-            if page.exists():
-                text = page.get_raw_body()
-                lines = text.split('\n')
-                # Remove the "#format rst" line
-                if lines[0].startswith("#format"):
-                    del lines[0]
-            else:
-                lines = [_("**Could not find the referenced page: %s**") % (content[0],)]
-            # Insert the text from the included document and then continue
-            # parsing
-            state_machine.insert_input(lines, 'MoinDirectives')
-        return
-
-    include.content = True
-
-    # Add additional macro directive.
-    # This allows MoinMoin macros to be used either by using the directive
-    # directly or by using the substitution syntax. Much cleaner than using the
-    # reference hack (`[[SomeMacro]]`_). This however simply adds a node to the
-    # document tree which is a reference, but through a much better user
-    # interface.
-    def macro(self, name, arguments, options, content, lineno,
-                content_offset, block_text, state, state_machine):
-        # content contains macro to be called
-        if len(content):
-            # Allow either with or without brackets
-            if content[0].startswith('[['):
-                macro = content[0]
-            else:
-                macro = '[[%s]]' % content[0]
-            ref = reference(macro, refuri = macro)
-            ref['name'] = macro
-            return [ref]
-        return
-
-    macro.content = True
-
-if ErrorParser: # fixup in case of missing docutils
-    Parser = ErrorParser
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - ReStructured Text Parser
+
+    @copyright: 2004 by Matthew Gilbert <gilbert AT voxmea DOT net>
+        and by Alexander Schremmer <alex AT alexanderweb DOT de>
+    @license: GNU GPL, see COPYING for details.
+
+    REQUIRES docutils 0.3.10 or later (must be later than December 30th, 2005)
+"""
+
+import re
+import new
+import StringIO
+import __builtin__
+import sys
+
+import types
+import os
+
+# docutils imports are below
+import MoinMoin.parser.wiki
+from MoinMoin.Page import Page
+from MoinMoin.action import AttachFile
+from MoinMoin import wikiutil
+
+Dependencies = [] # this parser just depends on the raw text
+
+# --- make docutils safe by overriding all module-scoped names related to IO ---
+
+# TODO: Add an error message to dummyOpen so that the user knows what they did
+# requested an unsupported feature of docutils in MoinMoin.
+def dummyOpen(x, y=None, z=None): return
+
+class dummyIO(StringIO.StringIO):
+    def __init__(self, destination=None, destination_path=None,
+                 encoding=None, error_handler='', autoclose=1,
+                 handle_io_errors=1, source_path=None):
+        StringIO.StringIO.__init__(self)
+
+class dummyUrllib2:
+    def urlopen(a):
+        return StringIO.StringIO()
+    urlopen = staticmethod(urlopen)
+
+# # # All docutils imports must be contained below here
+try:
+    import docutils
+    from docutils.core import publish_parts
+    from docutils.writers import html4css1
+    from docutils.nodes import reference
+    from docutils.parsers import rst
+    from docutils.parsers.rst import directives, roles
+# # # All docutils imports must be contained above here
+
+    ErrorParser = None # used in the case of missing docutils
+    docutils.io.FileOutput = docutils.io.FileInput = dummyIO
+except ImportError:
+    # we need to workaround this totally broken plugin interface that does
+    # not allow us to raise exceptions
+    class ErrorParser:
+        caching = 0
+        Dependencies = Dependencies # copy dependencies from module-scope
+
+        def __init__(self, raw, request, **kw):
+            self.raw = raw
+            self.request = request
+    
+        def format(self, formatter):
+            _ = self.request.getText
+            from MoinMoin.parser import plain
+            self.request.write(formatter.sysmsg(1) +
+                               formatter.rawHTML(_('Rendering of reStructured text is not possible, ''please'' install docutils.')) +
+                               formatter.sysmsg(0))
+            plain.Parser(self.raw, self.request).format(formatter)
+    
+    # Create a pseudo docutils environment
+    docutils = html4css1 = dummyUrllib2()
+    html4css1.HTMLTranslator = html4css1.Writer = object
+
+def safe_import(name, globals = None, locals = None, fromlist = None):
+    mod = __builtin__.__import__(name, globals, locals, fromlist)
+    if mod:
+        mod.open = dummyOpen
+        mod.urllib2 = dummyUrllib2
+    return mod
+
+# Go through and change all docutils modules to use a dummyOpen and dummyUrllib2
+# module. Also make sure that any docutils imported modules also get the dummy
+# implementations.
+for i in sys.modules.keys():
+    if i.startswith('docutils') and sys.modules[i]:
+        sys.modules[i].open = dummyOpen
+        sys.modules[i].urllib2 = dummyUrllib2
+        sys.modules[i].__import__ = safe_import
+        
+# --- End of dummy-code --------------------------------------------------------
+
+def html_escape_unicode(node):
+    # Find Python function that does this for me. string.encode('ascii',
+    # 'xmlcharrefreplace') only 2.3 and above.
+    for i in node:
+        if ord(i) > 127:
+            node = node.replace(i, '&#%d;' % (ord(i)))
+    return node
+
+class MoinWriter(html4css1.Writer):
+
+    config_section = 'MoinMoin writer'
+    config_section_dependencies = ('writers',)
+
+    #"""Final translated form of `document`."""
+    output = None
+
+    def wiki_resolver(self, node):
+        """
+            Normally an unknown reference would be an error in an reST document.
+            However, this is how new documents are created in the wiki. This
+            passes on unknown references to eventually be handled by
+            MoinMoin.
+        """
+        if hasattr(node, 'indirect_reference_name'):
+            node['refuri'] = node.indirect_reference_name
+        elif (len(node['ids']) != 0):
+            # If the node has an id then it's probably an internal link. Let
+            # docutils generate an error.
+            return False
+        elif node.hasattr('name'):
+            node['refuri'] = node['name']
+        else:
+            node['refuri'] = node['refname']
+        del node['refname']
+        node.resolved = 1
+        self.nodes.append(node)
+        return True
+
+    wiki_resolver.priority = 001
+
+    def __init__(self, formatter, request):
+        html4css1.Writer.__init__(self)
+        self.formatter = formatter
+        self.request = request
+        # Add our wiki unknown_reference_resolver to our list of functions to
+        # run when a target isn't found
+        self.unknown_reference_resolvers = [self.wiki_resolver]
+        # We create a new parser to process MoinMoin wiki style links in the
+        # reST.
+        self.wikiparser = MoinMoin.parser.wiki.Parser('', self.request)
+        self.wikiparser.formatter = self.formatter
+        self.wikiparser.hilite_re = None
+        self.nodes = []
+        # Make sure it's a supported docutils version.
+        required_version = (0, 3, 10)
+        current_version = tuple([int(i) for i in (docutils.__version__.split('.')+['0','0'])[:3]])
+        if current_version < required_version:
+            err = 'ERROR: The installed docutils version is %s;' % ('.'.join([str(i) for i in current_version]))
+            err += ' version %s or later is required.' % ('.'.join([str(i) for i in required_version]))
+            raise RuntimeError, err
+
+    def translate(self):
+        visitor = MoinTranslator(self.document,
+                                 self.formatter,
+                                 self.request,
+                                 self.wikiparser,
+                                 self)
+        self.document.walkabout(visitor)
+        self.visitor = visitor
+        self.output = html_escape_unicode(visitor.astext())
+
+class Parser:
+    caching = 1
+    Dependencies = Dependencies # copy dependencies from module-scope
+
+    def __init__(self, raw, request, **kw):
+        self.raw = raw
+        self.request = request
+        self.form = request.form
+
+    def format(self, formatter):
+        # Create our simple parser
+        parser = MoinDirectives(self.request)
+
+        parts = publish_parts(
+            source = self.raw,
+            writer = MoinWriter(formatter, self.request),
+            settings_overrides = {
+                'halt_level': 5,
+                'traceback': True,
+                'file_insertion_enabled': 0,
+                'raw_enabled': 0,
+                'stylesheet_path': '',
+            }
+        )
+
+        html = []
+        if parts['title']:
+            html.append(formatter.rawHTML('<h2>' + parts['title'] + '</h2>'))
+        # If there is only one subtitle then it is held in parts['subtitle'].
+        # However, if there is more than one subtitle then this is empty and
+        # fragment contains all of the subtitles.
+        if parts['subtitle']:
+            html.append(formatter.rawHTML('<h3>' + parts['subtitle'] + '</h3>'))
+        if parts['docinfo']:
+            html.append(parts['docinfo'])
+        html.append(parts['fragment'])
+        self.request.write(html_escape_unicode('\n'.join(html)))
+
+class RawHTMLList(list):
+    """
+        RawHTMLList catches all html appended to internal HTMLTranslator lists.
+        It passes the HTML through the MoinMoin rawHTML formatter to strip 
+        markup when necessary. This is to support other formatting outputs
+        (such as ?action=format&mimetype=text/plain).
+    """
+    
+    def __init__(self, formatter):
+        self.formatter = formatter
+        
+    def append(self, text):
+        f = sys._getframe()
+        if f.f_back.f_code.co_filename.endswith('html4css1.py'):
+            if isinstance(text, types.StringType) or isinstance(text, types.UnicodeType):
+                text = self.formatter.rawHTML(text)
+        list.append(self, text)
+
+class MoinTranslator(html4css1.HTMLTranslator):
+
+    def __init__(self, document, formatter, request, parser, writer):
+        html4css1.HTMLTranslator.__init__(self, document)
+        self.formatter = formatter
+        self.request = request
+        # Using our own writer when needed. Save the old one to restore
+        # after the page has been processed by the html4css1 parser.
+        self.original_write, self.request.write = self.request.write, self.capture_wiki_formatting
+        self.wikiparser = parser
+        self.wikiparser.request = request
+        # MoinMoin likes to start the initial headers at level 3 and the title
+        # gets level 2, so to comply with their styles, we do here also.
+        # TODO: Could this be fixed by passing this value in settings_overrides?
+        self.initial_header_level = 3
+        # Temporary place for wiki returned markup. This will be filled when
+        # replacing the default writer with the capture_wiki_formatting
+        # function (see visit_image for an example).
+        self.wiki_text = ''
+        self.setup_wiki_handlers()
+        
+        # Make all internal lists RawHTMLLists, see RawHTMLList class
+        # comment for more information.
+        for i in self.__dict__:
+            if isinstance(getattr(self, i), types.ListType):
+                setattr(self, i, RawHTMLList(formatter))
+
+    def depart_docinfo(self, node):
+        """
+            depart_docinfo assigns a new list to self.body, we need to re-make that
+            into a RawHTMLList.
+        """
+        html4css1.HTMLTranslator.depart_docinfo(self, node)
+        self.body = RawHTMLList(self.formatter)
+
+    def capture_wiki_formatting(self, text):
+        """
+            Captures MoinMoin generated markup to the instance variable
+            wiki_text.
+        """
+        # For some reason getting empty strings here which of course overwrites
+        # what we really want (this is called multiple times per MoinMoin
+        # format call, which I don't understand).
+        self.wiki_text += text
+
+    def process_wiki_text(self, text):
+        """
+            This sequence is repeated numerous times, so its captured as a
+            single call here. Its important that wiki_text is blanked before we
+            make the format call. format will call request.write which we've
+            hooked to capture_wiki_formatting. If wiki_text is not blanked
+            before a call to request.write we will get the old markup as well as
+            the newly generated markup.
+
+            TODO: Could implement this as a list so that it acts as a stack. I
+            don't like having to remember to blank wiki_text.
+        """
+        self.wiki_text = ''
+        self.wikiparser.raw = text
+        self.wikiparser.format(self.formatter)
+
+    def add_wiki_markup(self):
+        """
+            Place holder in case this becomes more elaborate someday. For now it
+            only appends the MoinMoin generated markup to the html body and
+            raises SkipNode.
+        """
+        self.body.append(self.wiki_text)
+        self.wiki_text = ''
+        raise docutils.nodes.SkipNode
+
+    def astext(self):
+        self.request.write = self.original_write
+        return html4css1.HTMLTranslator.astext(self)
+
+    def fixup_wiki_formatting(self, text):
+        replacement = {'<p>': '', '</p>': '', '\n': '', '> ': '>'}
+        for src, dst in replacement.items():
+            text = text.replace(src, dst)
+        # Everything seems to have a space ending the text block. We want to
+        # get rid of this
+        if text and text[-1] == ' ':
+            text = text[:-1]
+        return text
+
+    def visit_reference(self, node):
+        """
+            Pass links to MoinMoin to get the correct wiki space url. Extract
+            the url and pass it on to the html4css1 writer to handle. Inline
+            images are also handled by visit_image. Not sure what the "drawing:"
+            link scheme is used for, so for now it is handled here.
+
+            Also included here is a hack to allow MoinMoin macros. This routine
+            checks for a link which starts with "[[". This link is passed to the
+            MoinMoin formatter and the resulting markup is inserted into the
+            document in the place of the original link reference.
+        """
+        if 'refuri' in node.attributes:
+            refuri = node['refuri']
+            prefix = ''
+            link = refuri
+            if ':' in refuri:
+                prefix, link = refuri.lstrip().split(':', 1)
+            
+            # First see if MoinMoin should handle completely. Exits through add_wiki_markup.
+            if ((refuri.startswith('[[') and refuri.endswith(']]')) or 
+                    (prefix == 'drawing') or
+                    (prefix == 'inline')):
+                self.process_wiki_text(refuri)
+                # Don't call fixup_wiki_formatting because who knows what
+                # MoinMoin is inserting. (exits through add_wiki_markup)
+                self.add_wiki_markup()
+
+            # From here down, all links are handled by docutils (except 
+            # missing attachments), just fixup node['refuri'].
+            if prefix == 'attachment':
+                attach_file = AttachFile.getFilename(self.request, 
+                        self.request.page.page_name, link)
+                if not os.path.exists(attach_file):
+                    # Attachment doesn't exist, give to MoinMoin to insert
+                    # upload text.
+                    self.process_wiki_text(refuri)
+                    self.add_wiki_markup()
+                # Attachment exists, just get a link to it.
+                node['refuri'] = AttachFile.getAttachUrl(self.request.page.page_name, 
+                        link, self.request)
+                if not [i for i in node.children if i.__class__ == docutils.nodes.image]:
+                    node['classes'].append(prefix)                
+            elif prefix == 'wiki':
+                wikitag, wikiurl, wikitail, err = wikiutil.resolve_wiki(self.request, link)
+                wikiurl = wikiutil.mapURL(self.request, wikiurl)
+                node['refuri'] = wikiutil.join_wiki(wikiurl, wikitail)
+                # Only add additional class information if the reference does
+                # not have a child image (don't want to add additional markup
+                # for images with targets).
+                if not [i for i in node.children if i.__class__ == docutils.nodes.image]:
+                    node['classes'].append('interwiki')
+            elif prefix != '':
+                # Some link scheme (http, file, https, mailto, etc.), add class
+                # information if the reference doesn't have a child image (don't 
+                # want additional markup for images with targets). 
+                # Don't touch the refuri.
+                if not [i for i in node.children if i.__class__ == docutils.nodes.image]:
+                    node['classes'].append(prefix)
+            else:
+                # Default case - make a link to a wiki page.
+                page = MoinMoin.Page.Page(self.request, refuri)
+                node['refuri'] = page.url(self.request)
+                if not page.exists():
+                    node['classes'].append('nonexistent')
+        html4css1.HTMLTranslator.visit_reference(self, node)
+
+    def visit_image(self, node):
+        """
+            Need to intervene in the case of inline images. We need MoinMoin to
+            give us the actual src line to the image and then we can feed this
+            to the default html4css1 writer. NOTE: Since the writer can't "open"
+            this image the scale attribute doesn't work without directly
+            specifying the height or width (or both).
+
+            TODO: Need to handle figures similarly.
+        """
+        uri = node['uri'].lstrip()
+        prefix = ''          # assume no prefix
+        attach_name = uri
+        if ':' in uri:
+            prefix = uri.split(':', 1)[0]
+            attach_name = uri.split(':', 1)[1]
+        # if prefix isn't URL, try to display in page
+        if not prefix.lower() in ('file', 'http', 'https', 'ftp'):
+            attach_file = AttachFile.getFilename(self.request, 
+                    self.request.page.page_name, attach_name)
+            if not os.path.exists(attach_file):
+                # Attachment doesn't exist, MoinMoin should process it
+                if prefix == '':
+                    prefix = 'inline:'
+                self.process_wiki_text(prefix + attach_name)
+                self.wiki_text = self.fixup_wiki_formatting(self.wiki_text)
+                self.add_wiki_markup()
+            # Attachment exists, get a link to it.
+            # create the url
+            node['uri'] = AttachFile.getAttachUrl(self.request.page.page_name, 
+                    attach_name, self.request, addts = 1)
+            if not node.hasattr('alt'):
+                node['alt'] = node.get('name', uri)
+        html4css1.HTMLTranslator.visit_image(self, node)
+
+    def create_wiki_functor(self, moin_func):
+        moin_callable = getattr(self.formatter, moin_func)
+        def visit_func(self, node):
+            self.wiki_text = ''
+            self.request.write(moin_callable(1))
+            self.body.append(self.wiki_text)
+        def depart_func(self, node):
+            self.wiki_text = ''
+            self.request.write(moin_callable(0))
+            self.body.append(self.wiki_text)
+        return visit_func, depart_func
+
+    def setup_wiki_handlers(self):
+        """
+            Have the MoinMoin formatter handle markup when it makes sense. These
+            are portions of the document that do not contain reST specific
+            markup. This allows these portions of the document to look
+            consistent with other wiki pages.
+
+            Setup dispatch routines to handle basic document markup. The
+            hanlders dict is the html4css1 handler name followed by the wiki
+            handler name.
+        """
+        handlers = {
+            # Text Markup
+            'emphasis': 'emphasis',
+            'strong': 'strong',
+            'literal': 'code',
+            # Blocks
+            'literal_block': 'preformatted',
+            # Simple Lists
+            # bullet-lists are handled completely by docutils because it uses
+            # the node context to decide when to make a compact list 
+            # (no <p> tags).
+            'list_item': 'listitem',
+            # Definition List
+            'definition_list': 'definition_list',
+            # Admonitions
+            'warning': 'highlight'
+        }
+        for rest_func, moin_func in handlers.items():
+            visit_func, depart_func = self.create_wiki_functor(moin_func)
+            visit_func = new.instancemethod(visit_func, self, MoinTranslator)
+            depart_func = new.instancemethod(depart_func, self, MoinTranslator)
+            setattr(self, 'visit_%s' % (rest_func), visit_func)
+            setattr(self, 'depart_%s' % (rest_func), depart_func)
+
+    # Enumerated list takes an extra paramter so we handle this differently
+    def visit_enumerated_list(self, node):
+        self.wiki_text = ''
+        self.request.write(self.formatter.number_list(1, start=node.get('start', None)))
+        self.body.append(self.wiki_text)
+
+    def depart_enumerated_list(self, node):
+        self.wiki_text = ''
+        self.request.write(self.formatter.number_list(0))
+        self.body.append(self.wiki_text)
+
+
+class MoinDirectives:
+    """
+        Class to handle all custom directive handling. This code is called as
+        part of the parsing stage.
+    """
+
+    def __init__(self, request):
+        self.request = request
+
+        # include MoinMoin pages
+        directives.register_directive('include', self.include)
+
+        # used for MoinMoin macros
+        directives.register_directive('macro', self.macro)
+
+        # disallow a few directives in order to prevent XSS
+        # for directive in ('meta', 'include', 'raw'):
+        for directive in ('meta', 'raw'):
+            directives.register_directive(directive, None)
+
+        # disable the raw role
+        roles._roles['raw'] = None
+
+        # As a quick fix for infinite includes we only allow a fixed number of
+        # includes per page
+        self.num_includes = 0
+        self.max_includes = 10
+
+    # Handle the include directive rather than letting the default docutils
+    # parser handle it. This allows the inclusion of MoinMoin pages instead of
+    # something from the filesystem.
+    def include(self, name, arguments, options, content, lineno,
+                content_offset, block_text, state, state_machine):
+        # content contains the included file name
+
+        _ = self.request.getText
+
+        # Limit the number of documents that can be included
+        if self.num_includes < self.max_includes:
+            self.num_includes += 1
+        else:
+            lines = [_("**Maximum number of allowed includes exceeded**")]
+            state_machine.insert_input(lines, 'MoinDirectives')
+            return
+
+        if len(content):
+            page = Page(page_name = content[0], request = self.request)
+            if page.exists():
+                text = page.get_raw_body()
+                lines = text.split('\n')
+                # Remove the "#format rst" line
+                if lines[0].startswith("#format"):
+                    del lines[0]
+            else:
+                lines = [_("**Could not find the referenced page: %s**") % (content[0],)]
+            # Insert the text from the included document and then continue
+            # parsing
+            state_machine.insert_input(lines, 'MoinDirectives')
+        return
+
+    include.content = True
+
+    # Add additional macro directive.
+    # This allows MoinMoin macros to be used either by using the directive
+    # directly or by using the substitution syntax. Much cleaner than using the
+    # reference hack (`[[SomeMacro]]`_). This however simply adds a node to the
+    # document tree which is a reference, but through a much better user
+    # interface.
+    def macro(self, name, arguments, options, content, lineno,
+                content_offset, block_text, state, state_machine):
+        # content contains macro to be called
+        if len(content):
+            # Allow either with or without brackets
+            if content[0].startswith('[['):
+                macro = content[0]
+            else:
+                macro = '[[%s]]' % content[0]
+            ref = reference(macro, refuri = macro)
+            ref['name'] = macro
+            return [ref]
+        return
+
+    macro.content = True
+
+if ErrorParser: # fixup in case of missing docutils
+    Parser = ErrorParser