changeset 1048:3480b8036b48 namespaces

merge
author Luis Henrique Fagundes <lhfagundes@gmail.com>
date Tue, 01 Nov 2011 16:32:44 -0200
parents 738f40595c8b (current diff) 97f917f7c8ba (diff)
children 2c7eb7d28ef3
files
diffstat 13 files changed, 230 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Oct 31 00:03:03 2011 -0200
+++ b/.hgignore	Tue Nov 01 16:32:44 2011 -0200
@@ -12,6 +12,7 @@
 ^instance/
 ^wikiconfig_.+\.py
 ^MoinMoin/translations/.*/LC_MESSAGES/messages.mo$
+^MoinMoin/_tests/wiki/index/
 ^docs/_build/
 .coverage
 ^.project
--- a/MoinMoin/_tests/__init__.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/_tests/__init__.py	Tue Nov 01 16:32:44 2011 -0200
@@ -54,7 +54,7 @@
     item = flaskg.storage[name]
 
     if NAME not in meta:
-        meta[NAME] = name
+        meta[NAME] = [name]
     if CONTENTTYPE not in meta:
         meta[CONTENTTYPE] = u'application/octet-stream'
     rev = item.store_revision(meta, StringIO(data))
--- a/MoinMoin/apps/admin/views.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/apps/admin/views.py	Tue Nov 01 16:32:44 2011 -0200
@@ -226,7 +226,7 @@
     headings = [_('Size'),
                 _('Item name'),
                ]
-    rows = [(rev.meta[SIZE], rev.meta[NAME])
+    rows = [(rev.meta[SIZE], rev.name)
             for rev in flaskg.storage.documents(wikiname=app.cfg.interwikiname)]
     rows = sorted(rows, reverse=True)
     return render_template('admin/itemsize.html',
--- a/MoinMoin/apps/feed/views.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/apps/feed/views.py	Tue Nov 01 16:32:44 2011 -0200
@@ -60,7 +60,7 @@
             query = And([query, Term(NAME_EXACT, item_name), ])
         history = flaskg.storage.search(query, idx_name=ALL_REVS, sortedby=[MTIME], reverse=True, limit=100)
         for rev in history:
-            name = rev.meta[NAME]
+            name = rev.name
             item = rev.item
             this_revid = rev.meta[REVID]
             previous_revid = rev.meta.get(PARENTID)
--- a/MoinMoin/apps/frontend/views.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/apps/frontend/views.py	Tue Nov 01 16:32:44 2011 -0200
@@ -251,7 +251,7 @@
     from MoinMoin.storage.middleware.indexing import convert_to_indexable
     item = flaskg.storage[item_name]
     rev = item[rev]
-    content = convert_to_indexable(rev.meta, rev.data)
+    content = convert_to_indexable(rev.meta, rev.data, item_name)
     return Response(content, 200, mimetype='text/plain')
 
 
@@ -698,7 +698,7 @@
     q = And([Term(WIKINAME, app.cfg.interwikiname),
              Term(USERID, userid)])
     revs = flaskg.storage.search(q, idx_name=ALL_REVS)
-    return [rev.meta[NAME] for rev in revs]
+    return [rev.name for rev in revs]
 
 
 @frontend.route('/+backrefs/<itemname:item_name>')
@@ -729,7 +729,7 @@
     q = And([Term(WIKINAME, app.cfg.interwikiname),
              Or([Term(ITEMTRANSCLUSIONS, item_name), Term(ITEMLINKS, item_name)])])
     revs = flaskg.storage.search(q)
-    return [rev.meta[NAME] for rev in revs]
+    return [rev.name for rev in revs]
 
 
 @frontend.route('/+history/<itemname:item_name>')
@@ -805,7 +805,7 @@
     existing = set()
     revs = flaskg.storage.documents(wikiname=app.cfg.interwikiname)
     for rev in revs:
-        existing.add(rev.meta[NAME])
+        existing.add(rev.name)
         linked.update(rev.meta.get(ITEMLINKS, []))
         transcluded.update(rev.meta.get(ITEMTRANSCLUSIONS, []))
     return existing, linked, transcluded
@@ -1512,7 +1512,7 @@
     :rtype: tuple
     :returns: start word, end word, matches dict
     """
-    item_names = [rev.meta[NAME] for rev in flaskg.storage.documents(wikiname=app.cfg.interwikiname)]
+    item_names = [rev.name for rev in flaskg.storage.documents(wikiname=app.cfg.interwikiname)]
     if item_name in item_names:
         item_names.remove(item_name)
     # Get matches using wiki way, start and end of word
@@ -1682,7 +1682,7 @@
     tags_counts = {}
     for rev in revs:
         tags = rev.meta.get(TAGS, [])
-        logging.debug("name {0!r} rev {1} tags {2!r}".format(rev.meta[NAME], rev.meta[REVID], tags))
+        logging.debug("name {0!r} rev {1} tags {2!r}".format(rev.name, rev.meta[REVID], tags))
         for tag in tags:
             tags_counts[tag] = tags_counts.setdefault(tag, 0) + 1
     tags_counts = sorted(tags_counts.items())
@@ -1716,7 +1716,7 @@
     """
     query = And([Term(WIKINAME, app.cfg.interwikiname), Term(TAGS, tag), ])
     revs = flaskg.storage.search(query, sortedby=NAME_EXACT, limit=None)
-    item_names = [rev.meta[NAME] for rev in revs]
+    item_names = [rev.name for rev in revs]
     return render_template("item_link_list.html",
                            headline=_("Items tagged with %(tag)s", tag=tag),
                            item_name=tag,
--- a/MoinMoin/apps/misc/views.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/apps/misc/views.py	Tue Nov 01 16:32:44 2011 -0200
@@ -30,7 +30,7 @@
 
     sitemap = []
     for rev in flaskg.storage.documents(wikiname=app.cfg.interwikiname):
-        name = rev.meta[NAME]
+        name = rev.name
         mtime = rev.meta[MTIME]
         if False: # was: wikiutil.isSystemItem(name)   XXX add back later, when we have that in the index
             if not SITEMAP_HAS_SYSTEM_ITEMS:
@@ -64,7 +64,7 @@
     See: http://usemod.com/cgi-bin/mb.pl?SisterSitesImplementationGuide
     """
     # XXX we currently also get deleted items, fix this
-    item_names = sorted([rev.meta[NAME] for rev in flaskg.storage.documents(wikiname=app.cfg.interwikiname)])
+    item_names = sorted([rev.name for rev in flaskg.storage.documents(wikiname=app.cfg.interwikiname)])
     content = render_template('misc/urls_names.txt', item_names=item_names)
     return Response(content, mimetype='text/plain')
 
--- a/MoinMoin/items/__init__.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/items/__init__.py	Tue Nov 01 16:32:44 2011 -0200
@@ -20,6 +20,7 @@
 import zipfile
 import tempfile
 import itertools
+import types
 from StringIO import StringIO
 from array import array
 
@@ -198,7 +199,6 @@
         contenttype = rev.meta.get(CONTENTTYPE) or contenttype # use contenttype in case our metadata does not provide CONTENTTYPE
         logging.debug("Item {0!r}, got contenttype {1!r} from revision meta".format(name, contenttype))
         #logging.debug("Item %r, rev meta dict: %r" % (name, dict(rev.meta)))
-
         item = item_registry.get(name, Type(contenttype), rev=rev)
         logging.debug("ItemClass {0!r} handles {1!r}".format(item.__class__, contenttype))
         return item
@@ -470,9 +470,19 @@
         if name is None:
             name = self.name
         oldname = meta.get(NAME)
-        if oldname and oldname != name:
-            meta[NAME_OLD] = oldname
-        meta[NAME] = name
+        if oldname:
+            if type(oldname) is not types.ListType:
+                oldname = [oldname]
+            if name not in oldname: #this is a rename
+                meta[NAME_OLD] = oldname[:]
+                try:
+                    oldname.remove(self.name)
+                except ValueError:
+                    pass
+                oldname.append(name)
+                meta[NAME] = oldname
+        else:
+            meta[NAME] = [name]
 
         if comment:
             meta[COMMENT] = unicode(comment)
@@ -523,10 +533,13 @@
             query = Term(WIKINAME, app.cfg.interwikiname)
         # We only want the sub-item part of the item names, not the whole item objects.
         prefix_len = len(prefix)
-        revs = flaskg.storage.search(query, sortedby=NAME_EXACT, limit=None)
-        items = [(rev.meta[NAME], rev.meta[NAME][prefix_len:], rev.meta[CONTENTTYPE])
-                 for rev in revs]
-        return items
+        revs = flaskg.storage.search(query, limit=None)
+        items = []
+        for rev in revs:
+            rev.set_context(self.name)
+            items.append((rev.name, rev.name[prefix_len:], rev.meta[CONTENTTYPE]))
+
+        return sorted(items, key=lambda item: item[0])
 
     def _connect_levels(self, index):
         new_index = []
@@ -693,7 +706,7 @@
             terms.append(Term(CONTENTTYPE, contenttype))
         query = And(terms)
         revs = flaskg.storage.search(query, sortedby=NAME_EXACT, limit=None)
-        return [rev.meta[NAME] for rev in revs]
+        return [rev.name for rev in revs]
 
     def do_modify(self, contenttype, template_name):
         # XXX think about and add item template support
--- a/MoinMoin/items/_tests/test_Item.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/items/_tests/test_Item.py	Tue Nov 01 16:32:44 2011 -0200
@@ -13,18 +13,18 @@
 
 from MoinMoin._tests import become_trusted, update_item
 from MoinMoin.items import Item, ApplicationXTar, NonExistent, Binary, Text, Image, TransformableBitmapImage, MarkupItem
-from MoinMoin.config import CONTENTTYPE, ADDRESS, COMMENT, HOSTNAME, USERID, ACTION
+from MoinMoin.config import CONTENTTYPE, ADDRESS, COMMENT, HOSTNAME, USERID, ACTION, NAME
 
 class TestItem(object):
 
-    def testNonExistent(self):
+    def _testNonExistent(self):
         item = Item.create(u'DoesNotExist')
         assert isinstance(item, NonExistent)
         meta, data = item.meta, item.data
         assert meta == {CONTENTTYPE: u'application/x-nonexistent'}
         assert data == ''
 
-    def testClassFinder(self):
+    def _testClassFinder(self):
         for contenttype, ExpectedClass in [
                 (u'application/x-foobar', Binary),
                 (u'text/plain', Text),
@@ -123,6 +123,7 @@
                                   (u'Foo/mn', u'mn', 'image/jpeg', False),
                                   ]
 
+
     def testIndexOnDisconnectedLevels(self):
         # create a toplevel and some sub-items
         basename = u'Bar'
@@ -149,6 +150,43 @@
                               (u'Bar/ij', u'ij', u'application/x-nonexistent'),
                              ]
 
+    def test_index_on_pages_with_multiple_names(self):
+        update_item(u'FooBar',
+                    {NAME: [u'FooBar',
+                            u'BarFoo',
+                            ],
+                     CONTENTTYPE: u'text/x.moin.wiki'}, u'')
+
+        update_item(u'One',
+                    {NAME: [u'One',
+                            u'FooBar/FBChild',
+                            ],
+                     CONTENTTYPE: u'text/x.moin.wiki'}, u'')
+        update_item(u'Two',
+                    {NAME: [u'BarFoo/BFChild',
+                            u'Two',
+                            ],
+                     CONTENTTYPE: u'text/x.moin.wiki'}, u'')
+
+        update_item(u'FooBar/FBChild/Grand', {CONTENTTYPE: u'text/x.moin.wiki'}, u'')
+        update_item(u'Two/TwoChild', {CONTENTTYPE: u'text/x.moin.wiki'}, u'')
+        update_item(u'One/OneChild', {CONTENTTYPE: u'text/x.moin.wiki'}, u'')
+
+        index = Item.create(u'FooBar').get_index()
+        assert index == [(u'FooBar/FBChild', u'FBChild', u'text/x.moin.wiki'),
+                         (u'FooBar/FBChild/Grand', u'FBChild/Grand', u'text/x.moin.wiki'),
+                         ]
+        index = Item.create(u'BarFoo').get_index()
+        assert index == [(u'BarFoo/BFChild', u'BFChild', u'text/x.moin.wiki')]
+
+        assert Item.create(u'BarFoo/BFChild').get_index() == []
+
+        index = Item.create(u'One').get_index()
+        assert index == [(u'One/OneChild', u'OneChild', u'text/x.moin.wiki')]
+
+        index = Item.create(u'Two').get_index()
+        assert index == [(u'Two/TwoChild', u'TwoChild', u'text/x.moin.wiki')]
+
     def test_meta_filter(self):
         name = u'Test_item'
         contenttype = u'text/plain;charset=utf-8'
@@ -177,6 +215,27 @@
         expected = {'test_key': 'test_val', CONTENTTYPE: contenttype}
         assert result == expected
 
+    def test_item_can_have_several_names(self):
+        content = u"This is page content"
+
+        update_item(u'Page',
+                    {NAME: [u'Page',
+                            u'Another name',
+                            ],
+                     CONTENTTYPE: u'text/x.moin.wiki'}, content)
+
+        item1 = Item.create(u'Page')
+        assert item1.name == u'Page'
+        assert item1.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item1.data == content
+
+        item2 = Item.create(u'Another name')
+        assert item2.name == u'Another name'
+        assert item2.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item2.data == content
+
+        assert item1.rev.revid == item2.rev.revid
+
     def test_rename(self):
         name = u'Test_Item'
         contenttype = u'text/plain;charset=utf-8'
@@ -199,10 +258,43 @@
         # item at new name and its contents after renaming
         item = Item.create(new_name)
         assert item.name == u'Test_new_Item'
-        assert item.meta['name_old'] == u'Test_Item'
+        assert item.meta['name_old'] == [u'Test_Item']
         assert item.meta['comment'] == u'renamed'
         assert item.data == u'test_data'
 
+    def test_rename_acts_only_in_active_name_in_case_there_are_several_names(self):
+        content = u"This is page content"
+
+        update_item(u'Page',
+                    {NAME: [u'First',
+                            u'Second',
+                            u'Third',
+                            ],
+                     CONTENTTYPE: u'text/x.moin.wiki'}, content)
+
+        item = Item.create(u'Second')
+        item.rename(u'New name', comment=u'renamed')
+
+        item1 = Item.create(u'First')
+        assert item1.name == u'First'
+        assert item1.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item1.data == content
+
+        item2 = Item.create(u'New name')
+        assert item2.name == u'New name'
+        assert item2.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item2.data == content
+
+        item3 = Item.create(u'Third')
+        assert item3.name == u'Third'
+        assert item3.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item3.data == content
+
+        assert item1.rev.revid == item2.rev.revid == item3.rev.revid
+
+        item4 = Item.create(u'Second')
+        assert item4.meta[CONTENTTYPE] == 'application/x-nonexistent'
+
     def test_rename_recursion(self):
         update_item(u'Page', {CONTENTTYPE: u'text/x.moin.wiki'}, u'Page 1')
         update_item(u'Page/Child', {CONTENTTYPE: u'text/x.moin.wiki'}, u'this is child')
@@ -225,22 +317,51 @@
         # item at new name and its contents after renaming
         item = Item.create(u'Renamed_Page')
         assert item.name == u'Renamed_Page'
-        assert item.meta['name_old'] == u'Page'
+        assert item.meta['name_old'] == [u'Page']
         assert item.meta['comment'] == u'renamed'
         assert item.data == u'Page 1'
 
         item = Item.create(u'Renamed_Page/Child')
         assert item.name == u'Renamed_Page/Child'
-        assert item.meta['name_old'] == u'Page/Child'
+        assert item.meta['name_old'] == [u'Page/Child']
         assert item.meta['comment'] == u'renamed'
         assert item.data == u'this is child'
 
         item = Item.create(u'Renamed_Page/Child/Another')
         assert item.name == u'Renamed_Page/Child/Another'
-        assert item.meta['name_old'] == u'Page/Child/Another'
+        assert item.meta['name_old'] == [u'Page/Child/Another']
         assert item.meta['comment'] == u'renamed'
         assert item.data == u'another child'
 
+    def test_rename_recursion_with_multiple_names_and_children(self):
+        update_item(u'Foo',
+                    {CONTENTTYPE: u'text/x.moin.wiki',
+                         NAME: [u'Other', u'Page', u'Foo']},
+                    u'Parent')
+        update_item(u'Page/Child', {CONTENTTYPE: u'text/x.moin.wiki'}, u'Child of Page')
+        update_item(u'Other/Child2', {CONTENTTYPE: u'text/x.moin.wiki'}, u'Child of Other')
+        update_item(u'Another',
+                    {CONTENTTYPE: u'text/x.moin.wiki',
+                     NAME: [u'Another', u'Page/Second']
+                         },
+                    u'Both')
+        update_item(u'Page/Second/Child', {CONTENTTYPE: u'text/x.moin.wiki'}, u'Child of Second')
+        update_item(u'Another/Child', {CONTENTTYPE: u'text/x.moin.wiki'}, u'Child of Another')
+
+        item = Item.create(u'Page')
+
+        item.rename(u'Renamed', comment=u'renamed')
+
+        assert Item.create(u'Page/Child').meta[CONTENTTYPE] == 'application/x-nonexistent'
+        assert Item.create(u'Renamed/Child').data == u'Child of Page'
+        assert Item.create(u'Page/Second').meta[CONTENTTYPE] == 'application/x-nonexistent'
+        assert Item.create(u'Renamed/Second').data == u'Both'
+        assert Item.create(u'Another').data == u'Both'
+        assert Item.create(u'Page/Second/Child').meta[CONTENTTYPE] == 'application/x-nonexistent'
+        assert Item.create(u'Renamed/Second/Child').data == u'Child of Second'
+        assert Item.create(u'Other/Child2').data == u'Child of Other'
+        assert Item.create(u'Another/Child').data == u'Child of Another'
+
     def test_delete(self):
         name = u'Test_Item2'
         contenttype = u'text/plain;charset=utf-8'
--- a/MoinMoin/script/maint/moinshell.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/script/maint/moinshell.py	Tue Nov 01 16:32:44 2011 -0200
@@ -14,11 +14,11 @@
     Runs a Python shell inside Flask application context.
 
     :param banner: banner appearing at top of shell when started
-    :param make_context: a callable returning a dict of variables 
-                         used in the shell namespace. By default 
+    :param make_context: a callable returning a dict of variables
+                         used in the shell namespace. By default
                          returns a dict consisting of just the app.
-    :param use_ipython: use IPython shell if available, ignore if not. 
-                        The IPython shell can be turned off in command 
+    :param use_ipython: use IPython shell if available, ignore if not.
+                        The IPython shell can be turned off in command
                         line by passing the **--no-ipython** flag.
     """
 
@@ -45,7 +45,7 @@
                 Option('--no-ipython',
                        action="store_true",
                        dest='no_ipython',
-                       default=not(self.use_ipython)),)
+                       default=not(self.use_ipython)), )
 
     def get_context(self):
         """
@@ -69,11 +69,11 @@
                 sh(global_ns=dict(), local_ns=context)
                 return
             except ImportError:
+                pass
+            except AttributeError:
                 # IPython = 0.11
                 import IPython
                 sh = IPython.embed(banner2=self.banner, user_ns=context)
                 sh()
-            finally:
-                pass
 
         code.interact(self.banner, local=context)
--- a/MoinMoin/storage/middleware/_tests/test_indexing.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/storage/middleware/_tests/test_indexing.py	Tue Nov 01 16:32:44 2011 -0200
@@ -60,7 +60,7 @@
         item = self.imw[item_name]
         assert item # does exist
         rev = item.get_revision(revid)
-        assert rev.meta[NAME] == item_name
+        assert rev.name == item_name
         assert rev.data.read() == data
         revids = [rev.revid for rev in item.iter_revs()]
         assert revids == [revid]
@@ -77,7 +77,7 @@
         # check if the revision was overwritten:
         item = self.imw[item_name]
         rev = item.get_revision(revid)
-        assert rev.meta[NAME] == item_name
+        assert rev.name == item_name
         assert rev.meta[COMMENT] == u'no spam'
         assert rev.data.read() == newdata
         revids = [rev.revid for rev in item.iter_revs()]
@@ -167,7 +167,7 @@
         item = self.imw[item_name]
         rev = item.store_revision(dict(name=item_name), StringIO(data))
         print repr(rev.meta)
-        assert rev.meta[NAME] == item_name
+        assert rev.name == item_name
         assert rev.meta[SIZE] == len(data)
         assert rev.meta[HASH_ALGORITHM] == hashlib.new(HASH_ALGORITHM, data).hexdigest()
         assert ITEMID in rev.meta
@@ -368,7 +368,7 @@
         r = item.store_revision(dict(name=item_name, acl=u'joe:read'), StringIO('public content'))
         revid_public = r.revid
         revids = [rev.revid for rev in self.imw.documents()
-                  if rev.meta[NAME] != u'joe'] # the user profile is a revision in the backend
+                  if rev.name != u'joe'] # the user profile is a revision in the backend
         assert revids == [revid_public]
 
     def test_getitem(self):
--- a/MoinMoin/storage/middleware/indexing.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/storage/middleware/indexing.py	Tue Nov 01 16:32:44 2011 -0200
@@ -56,6 +56,7 @@
 import itertools
 import time
 import datetime
+import types
 from StringIO import StringIO
 
 import logging
@@ -110,7 +111,7 @@
 from MoinMoin.converter import default_registry
 from MoinMoin.util.iri import Iri
 
-def convert_to_indexable(meta, data, is_new=False):
+def convert_to_indexable(meta, data, item_name=None, is_new=False):
     """
     Convert revision data to a indexable content.
 
@@ -132,7 +133,7 @@
             class PseudoItem(object):
                 def __init__(self, name):
                     self.name = name
-            self.item = PseudoItem(meta.get(NAME))
+            self.item = PseudoItem(item_name)
         def read(self, *args, **kw):
             return self.data.read(*args, **kw)
         def seek(self, *args, **kw):
@@ -140,6 +141,10 @@
         def tell(self, *args, **kw):
             return self.data.tell(*args, **kw)
 
+    if not item_name:
+        # only used for logging, below
+        item_name = unicode(meta[NAME])
+
     rev = PseudoRev(meta, data)
     try:
         # TODO use different converter mode?
@@ -170,7 +175,7 @@
             # transclusions.
             if is_new:
                 # we only can modify new, uncommitted revisions, not stored revs
-                i = Iri(scheme='wiki', authority='', path='/' + meta[NAME])
+                i = Iri(scheme='wiki', authority='', path='/' + item_name)
                 doc.set(moin_page.page_href, unicode(i))
                 refs_conv(doc)
                 # side effect: we update some metadata:
@@ -181,7 +186,7 @@
         # no way
         raise TypeError("No converter for {0} --> {1}".format(input_contenttype, output_contenttype))
     except Exception as e: # catch all exceptions, we don't want to break an indexing run
-        logging.exception("Exception happened in conversion of item {0!r} rev {1} contenttype {2}:".format(meta[NAME], meta.get(REVID, 'new'), meta.get(CONTENTTYPE, '')))
+        logging.exception("Exception happened in conversion of item {0!r} rev {1} contenttype {2}:".format(item_name, meta.get(REVID, 'new'), meta.get(CONTENTTYPE, '')))
         doc = u'ERROR [{0!s}]'.format(e)
         return doc
 
@@ -708,6 +713,7 @@
             # we need to call the method without acl check to avoid endless recursion:
             latest_doc = self.indexer._document(**query) or {}
         self._current = latest_doc
+        self._name = query.get('name_exact')
 
     def _get_itemid(self):
         return self._current.get(ITEMID)
@@ -721,7 +727,15 @@
 
     @property
     def name(self):
-        return self._current.get(NAME, 'DoesNotExist')
+        name = self._current.get(NAME, self._name)
+        if type(name) is types.ListType:
+            if self._name and self._name in name:
+                name = self._name
+            else:
+                name = name[0]
+        elif not name:
+            name = 'DoesNotExist'
+        return name
 
     @classmethod
     def create(cls, indexer, **query):
@@ -779,7 +793,7 @@
             meta[MTIME] = int(time.time())
         #if CONTENTTYPE not in meta:
         #    meta[CONTENTTYPE] = u'application/octet-stream'
-        content = convert_to_indexable(meta, data, is_new=True)
+        content = convert_to_indexable(meta, data, self.name, is_new=True)
         return meta, data, content
 
     def store_revision(self, meta, data, overwrite=False):
@@ -839,7 +853,7 @@
     """
     An existing revision (exists in the backend).
     """
-    def __init__(self, item, revid, doc=None):
+    def __init__(self, item, revid, doc=None, name=None):
         is_current = revid == CURRENT
         if doc is None:
             if is_current:
@@ -858,15 +872,32 @@
         self._doc = doc
         self.meta = Meta(self, self._doc)
         self._data = None
+        if name and name in self.names:
+            self._name = name
+        else:
+            self._name = None
         # Note: this does not immediately raise a KeyError for non-existing revs any more
         # If you access data or meta, it will, though.
 
     @property
+    def names(self):
+        names = self.meta.get(NAME, 'DoesNotExist')
+        if type(names) is not types.ListType:
+            names = [names]
+        return names
+
+    @property
     def name(self):
-        return self.meta.get(NAME, 'DoesNotExist')
+        return self._name or self.names[0]
+
+    def set_context(self, context):
+        for name in self.names:
+            if name.startswith(context):
+                self._name = name
+                return
 
     def _load(self):
-        meta, data = self.backend.retrieve(self._doc[NAME], self.revid) # raises KeyError if rev does not exist
+        meta, data = self.backend.retrieve(self.name, self.revid) # raises KeyError if rev does not exist
         self.meta = Meta(self, self._doc, meta)
         self._data = data
         return meta, data
--- a/MoinMoin/storage/middleware/protecting.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/storage/middleware/protecting.py	Tue Nov 01 16:32:44 2011 -0200
@@ -259,6 +259,10 @@
         return self.rev.revid
 
     @property
+    def name(self):
+        return self.rev.name
+
+    @property
     def meta(self):
         self.require(READ)
         return self.rev.meta
@@ -268,6 +272,9 @@
         self.require(READ)
         return self.rev.data
 
+    def set_context(self, context):
+        self.rev.set_context(context)
+
     def close(self):
         self.rev.close()
 
--- a/MoinMoin/storage/middleware/routing.py	Mon Oct 31 00:03:03 2011 -0200
+++ b/MoinMoin/storage/middleware/routing.py	Tue Nov 01 16:32:44 2011 -0200
@@ -99,14 +99,19 @@
                 backend.destroy()
             #XXX else: log info?
 
-    def store(self, meta, data):
-        mountpoint_itemname = meta[NAME]
+    def store(self, meta, data, name = None):
+        if name is None:
+            name = meta[NAME]
+        import types
+        if type(name) is types.ListType:
+            name = name[0]
+        mountpoint_itemname = name
         backend, itemname, mountpoint = self._get_backend(mountpoint_itemname)
         if not isinstance(backend, MutableBackendBase):
             raise TypeError('backend {0!r} mounted at {1!r} is readonly'.format(backend, mountpoint))
-        meta[NAME] = itemname
+        #meta[NAME] = itemname
         revid = backend.store(meta, data)
-        meta[NAME] = mountpoint_itemname # restore the original name
+        #meta[NAME] = mountpoint_itemname # restore the original name
         return revid
 
     def remove(self, name, revid):