changeset 4169:1d5995a6a0e2

Moved unique-id-generation from request into own object
author Florian Krupicka <florian.krupicka@googlemail.com>
date Mon, 16 Jun 2008 17:21:25 +0200
parents 2edbd96f3179
children 02fcab41459f
files MoinMoin/formatter/__init__.py MoinMoin/formatter/text_html.py MoinMoin/macro/TableOfContents.py MoinMoin/web/contexts.py MoinMoin/web/utils.py
diffstat 5 files changed, 98 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/formatter/__init__.py	Mon Jun 16 12:11:24 2008 +0200
+++ b/MoinMoin/formatter/__init__.py	Mon Jun 16 17:21:25 2008 +0200
@@ -75,12 +75,12 @@
 
     def startContent(self, content_id="content", **kw):
         if self.page:
-            self.request.begin_include(self.page.page_name)
+            self.request.uid_generator.begin(self.page.page_name)
         return ""
 
     def endContent(self):
         if self.page:
-            self.request.end_include()
+            self.request.uid_generator.end()
         return ""
 
     # Links ##############################################################
@@ -415,7 +415,7 @@
         if not ns is None:
             ns = self.sanitize_to_id(ns)
         id = self.sanitize_to_id(id)
-        id = self.request.make_unique_id(id, ns)
+        id = self.request.uid_generator(id, ns)
         return id
 
     def qualify_id(self, id):
--- a/MoinMoin/formatter/text_html.py	Mon Jun 16 12:11:24 2008 +0200
+++ b/MoinMoin/formatter/text_html.py	Mon Jun 16 17:21:25 2008 +0200
@@ -410,7 +410,7 @@
         """
 
         if hasattr(self, 'page'):
-            self.request.begin_include(self.page.page_name)
+            self.request.uid_generator.begin(self.page.page_name)
 
         result = []
         # Use the content language
@@ -434,7 +434,7 @@
         result.append(self.anchordef('bottom'))
         result.append(self._close('div', newline=newline))
         if hasattr(self, 'page'):
-            self.request.end_include()
+            self.request.uid_generator.end()
         return ''.join(result)
 
     def lang(self, on, lang_name):
--- a/MoinMoin/macro/TableOfContents.py	Mon Jun 16 12:11:24 2008 +0200
+++ b/MoinMoin/macro/TableOfContents.py	Mon Jun 16 17:21:25 2008 +0200
@@ -142,7 +142,7 @@
 
     pname = macro.formatter.page.page_name
 
-    macro.request.push_unique_ids()
+    macro.request.uid_generator.push()
 
     macro.request._tocfm_collected_headings = []
     macro.request._tocfm_orig_formatter = macro.formatter
@@ -205,7 +205,7 @@
         result.append(macro.formatter.number_list(0))
         lastlvl -= 1
 
-    macro.request.pop_unique_ids()
+    macro.request.uid_generator.pop()
 
     result.append(macro.formatter.div(0))
     return ''.join(result)
--- a/MoinMoin/web/contexts.py	Mon Jun 16 12:11:24 2008 +0200
+++ b/MoinMoin/web/contexts.py	Mon Jun 16 17:21:25 2008 +0200
@@ -18,7 +18,7 @@
 from MoinMoin.formatter import text_html
 from MoinMoin.request import RequestBase
 from MoinMoin.web.request import Request, Response
-from MoinMoin.web.utils import check_spider
+from MoinMoin.web.utils import check_spider, UniqueIDGenerator
 from MoinMoin.web.exceptions import Forbidden, SurgeProtection
 
 from MoinMoin import log
@@ -267,3 +267,16 @@
         return dicts
     dicts = cached_property(dicts)
 
+    def uid_generator(self):
+        pagename = None
+        if hasattr(self, 'page') and self.page.pagename:
+            pagename = self.page.pagename
+        return UniqueIDGenerator(pagename=pagename)
+    uid_generator = cached_property(uid_generator)
+
+    def reset(self):
+        self.current_lang = self.cfg.language_default
+        if hasattr(self, '_fmt_hd_counters'):
+            del self._fmt_hd_counters
+        if hasattr(self, 'uid_generator'):
+            del self.uid_generator
--- a/MoinMoin/web/utils.py	Mon Jun 16 12:11:24 2008 +0200
+++ b/MoinMoin/web/utils.py	Mon Jun 16 17:21:25 2008 +0200
@@ -234,3 +234,80 @@
         url = wikiutil.getFrontPage(request).url(request)
     url = request.getQualifiedURL(url)
     return abort(redirect(url))
+
+class UniqueIDGenerator(object):
+    def __init__(self, pagename=None):
+        self.unique_stack = []
+        self.include_stack = []
+        self.include_id = None
+        self.page_ids = {None: {}}
+        self.pagename = pagename
+
+    def push(self):
+        """
+        Used by the TOC macro, this ensures that the ID namespaces
+        are reset to the status when the current include started.
+        This guarantees that doing the ID enumeration twice results
+        in the same results, on any level.
+        """
+        self.unique_stack.append((self.page_ids, self.include_id))
+        self.include_id, pids = self.include_stack[-1]
+        self.page_ids = {}
+        for namespace in pids:
+            self.page_ids[namespace] = pids[namespace].copy()
+
+    def pop(self):
+        """
+        Used by the TOC macro to reset the ID namespaces after
+        having parsed the page for TOC generation and after
+        printing the TOC.
+        """
+        self.page_ids, self.include_id = self.unique_stack.pop()
+        return self.page_ids, self.include_id
+
+    def begin(self):
+        """
+        Called by the formatter when a document begins, which means
+        that include causing nested documents gives us an include
+        stack in self.include_id_stack.
+        """
+        pids = {}
+        for namespace in self.page_ids:
+            pids[namespace] = self.page_ids[namespace].copy()
+        self.include_stack.append((self.include_id, pids))
+        self.include_id = self(base)
+        # if it's the page name then set it to None so we don't
+        # prepend anything to IDs, but otherwise keep it.
+        if self.pagename and self.pagename == self.include_id:
+            self.include_id = None
+
+    def end(self):
+        """
+        Called by the formatter when a document ends, restores
+        the current include ID to the previous one and discards
+        the page IDs state we kept around for push().
+        """
+        self.include_id, pids = self.include_stack.pop()
+
+    def __call__(self, base, namespace=None):
+        """
+        Generates a unique ID using a given base name. Appends a running count to the base.
+
+        Needs to stay deterministic!
+
+        @param base: the base of the id
+        @type base: unicode
+        @param namespace: the namespace for the ID, used when including pages
+
+        @returns: a unique (relatively to the namespace) ID
+        @rtype: unicode
+        """
+        if not isinstance(base, unicode):
+            base = unicode(str(base), 'ascii', 'ignore')
+        if not namespace in self.page_ids:
+            self.page_ids[namespace] = {}
+        count = self.page_ids[namespace].get(base, -1) + 1
+        self.page_ids[namespace][base] = count
+        if not count:
+            return base
+        return u'%s-%d' % (base, count)