Commits

Roger Haase  committed 54174e4 Merge

merge

  • Participants
  • Parent commits 606a6b2, e2a2352

Comments (0)

Files changed (20)

File MoinMoin/_tests/test_test_environ.py

         itemname = u"this item shouldn't exist yet"
         assert not storage.has_item(itemname)
         item = storage[itemname]
-        new_rev = item.store_revision({NAME: [itemname, ], CONTENTTYPE: u'text/plain'}, StringIO(''))
+        new_rev = item.store_revision({NAME: [itemname, ], CONTENTTYPE: u'text/plain;charset=utf-8'}, StringIO(''))
         assert storage.has_item(itemname)
 
 

File MoinMoin/apps/admin/templates/admin/userbrowser.html

             {% endif %}
         </td>
         <td>
-            <form action="{{ url_for('admin.userprofile', user_name=u.name) }}" method="GET">
+            <form action="{{ url_for('admin.userprofile', user_name=u.name[0]) }}" method="POST">
                 <input type="hidden" name="key" value="disabled" />
                 <input type="hidden" name="val" value="{{ u.disabled and "0" or "1" }}" />
                 <input type="submit" name="userprofile" value="{{ u.disabled and _("Enable user") or _("Disable user") }}" />

File MoinMoin/apps/admin/views.py

 from MoinMoin.themes import render_template
 from MoinMoin.apps.admin import admin
 from MoinMoin import user
-from MoinMoin.constants.keys import NAME, ITEMID, SIZE, EMAIL
+from MoinMoin.constants.keys import NAME, ITEMID, SIZE, EMAIL, DISABLED
 from MoinMoin.constants.rights import SUPERUSER
 from MoinMoin.security import require_permission
 
     user_accounts = [dict(uid=rev.meta[ITEMID],
                           name=rev.meta[NAME],
                           email=rev.meta[EMAIL],
-                          disabled=False,  # TODO: add to index
+                          disabled=rev.meta[DISABLED],
                           groups=[groupname for groupname in groups if rev.meta[NAME] in groups[groupname]],
                      ) for rev in revs]
     return render_template('admin/userbrowser.html', user_accounts=user_accounts, title_name=_(u"Users"))
         ok = False
         if hasattr(u, key):
             ok = True
-            oldval = getattr(u, key)
+            oldval = u.profile[key]
             if isinstance(oldval, bool):
-                val = bool(val)
+                val = bool(int(val))
             elif isinstance(oldval, int):
                 val = int(val)
             elif isinstance(oldval, unicode):
             else:
                 ok = False
         if ok:
-            setattr(u, key, val)
+            u.profile[key] = val
             u.save()
             flash(u'{0}.{1}: {2} -> {3}'.format(user_name, key, unicode(oldval), unicode(val), ), "info")
         else:

File MoinMoin/apps/frontend/_tests/test_frontend.py

 
     def test_jfu_server(self):
         self._test_view_post('frontend.jfu_server', status='200 OK', data=['{', '}'], form=dict(
-            data_file=FileStorage(StringIO("Hello, world"), filename='C:\\fakepath\\DoesntExist.txt', content_type='text/plain'),
+            data_file=FileStorage(StringIO("Hello, world"), filename='C:\\fakepath\\DoesntExist.txt', content_type='text/plain; charset=utf-8'),
         ), viewopts=dict(item_name='WillBeCreated'), content_types=['application/json', ])
 
     def test_show_item(self):

File MoinMoin/constants/namespaces.py

+# Copyright: 2013 MoinMoin:CheerXiao
+# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
+
+"""
+MoinMoin - namespaces related constants
+"""
+
+NAMESPACE_DEFAULT = u''
+NAMESPACE_USERPROFILES = u'userprofiles'

File MoinMoin/converter/_tests/test_include.py

 
     def test_IncludeHandlesCircularRecursion(self):
         # detect circular recursion and create error message
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'{{page2}}')
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u'{{page3}}')
-        update_item(u'page3', {CONTENTTYPE: u'text/x.moin.wiki'}, u'{{page4}}')
-        update_item(u'page4', {CONTENTTYPE: u'text/x.moin.wiki'}, u'{{page2}}')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'{{page2}}')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'{{page3}}')
+        update_item(u'page3', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'{{page4}}')
+        update_item(u'page4', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'{{page2}}')
         page1 = Item.create(u'page1')
         rendered = page1.content._render_data()
         # an error message will follow strong tag
 
     def test_ExternalInclude(self):
         # external include
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'{{http://moinmo.in}}')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'{{http://moinmo.in}}')
         rendered = Item.create(u'page1').content._render_data()
         assert '<object class="moin-http moin-transclusion" data="http://moinmo.in" data-href="http://moinmo.in">http://moinmo.in</object>' in rendered
         # external include embedded within text (object is an inline tag)
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'before {{http://moinmo.in}} after')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'before {{http://moinmo.in}} after')
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>before <object class="moin-http moin-transclusion" data="http://moinmo.in" data-href="http://moinmo.in">http://moinmo.in</object> after</p>' in rendered
         # external include embedded within text italic and bold markup (object is an inline tag)
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"before ''italic '''bold {{http://moinmo.in}} bold''' italic'' normal")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"before ''italic '''bold {{http://moinmo.in}} bold''' italic'' normal")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>before <em>italic <strong>bold <object class="moin-http moin-transclusion" data="http://moinmo.in" data-href="http://moinmo.in">http://moinmo.in</object> bold</strong> italic</em> normal</p>' in rendered
 
     def test_InlineInclude(self):
 
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'before {{page2}} after')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'before {{page2}} after')
         # transclude single paragraph as inline
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u'Single line')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'Single line')
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>before <span class="moin-transclusion" data-href="/page2">Single line</span> after</p>' in rendered
         # transclude multiple paragraphs as block
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u'Two\n\nParagraphs')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'Two\n\nParagraphs')
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>before </p><div class="moin-transclusion" data-href="/page2"><p>Two</p><p>Paragraphs</p></div><p> after</p></div>' in rendered
         # transclude single paragraph with internal markup as inline
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"this text contains ''italic'' string")
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"this text contains ''italic'' string")
         rendered = Item.create(u'page1').content._render_data()
         assert 'before <span class="moin-transclusion" data-href="/page2">this text contains <em>italic</em>' in rendered
         # transclude single paragraph as only content within a paragraph
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'Content of page2 is\n\n{{page2}}')
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Single Line")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'Content of page2 is\n\n{{page2}}')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Single Line")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>Content of page2 is</p><p><span class="moin-transclusion" data-href="/page2">Single Line</span></p>' in rendered
         # transclude single row table within a paragraph, block element forces paragraph to be split into 2 parts
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'before {{page2}} after')
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"|| table || cell ||")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'before {{page2}} after')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"|| table || cell ||")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>before </p><div class="moin-transclusion" data-href="/page2"><table' in rendered
         assert '</table></div><p> after</p>' in rendered
         assert rendered.count('<table>') == 1
         # transclude two row table within a paragraph, block element forces paragraph to be split into 2 parts
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'before {{page2}} after')
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"|| this || has ||\n|| two || rows ||")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'before {{page2}} after')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"|| this || has ||\n|| two || rows ||")
         rendered = Item.create(u'page1').content._render_data()
         # inclusion of block item within a paragraph results in a before and after p
         assert '<p>before </p><div class="moin-transclusion" data-href="/page2"><table' in rendered
         assert '</table></div><p> after</p>' in rendered
         assert rendered.count('<table>') == 1
         # transclude nonexistent item
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'before {{nonexistent}} after')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'before {{nonexistent}} after')
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>before <span class="moin-transclusion" data-href="/nonexistent"><a href="/+modify/nonexistent">' in rendered
         assert '</a></span> after</p>' in rendered
         # transclude empty item
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'text {{page2}} text')
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'text {{page2}} text')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <span class="moin-transclusion" data-href="/page2"></span> text</p>' in rendered
 
 
     def test_InlineIncludeWithinMarkup(self):
         # transclude single line item within italic and bold markup
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Normal ''italic '''bold {{page2}} bold''' italic'' normal")
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Single Line")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Normal ''italic '''bold {{page2}} bold''' italic'' normal")
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Single Line")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>Normal <em>italic <strong>bold <span class="moin-transclusion" data-href="/page2">Single Line</span> bold</strong> italic</em> normal</p>' in rendered
         # transclude double line item within italic and bold markup
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Normal ''italic '''bold {{page2}} bold''' italic'' normal")
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Double\n\nLine")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Normal ''italic '''bold {{page2}} bold''' italic'' normal")
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Double\n\nLine")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>Normal <em>italic <strong>bold </strong></em></p><div class="moin-transclusion" data-href="/page2"><p>Double</p><p>Line</p></div><p><em><strong> bold</strong> italic</em> normal</p>' in rendered
         # transclude single line item within comment
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"comment /* before {{page2}} after */")
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Single Line")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"comment /* before {{page2}} after */")
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Single Line")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>comment <span class="comment">before <span class="moin-transclusion" data-href="/page2">Single Line</span> after</span></p>' in rendered
         # transclude double line item within comment
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"comment /* before {{page2}} after */")
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Double\n\nLine")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"comment /* before {{page2}} after */")
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Double\n\nLine")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>comment <span class="comment">before </span></p><div class="comment moin-transclusion" data-href="/page2"><p>Double</p><p>Line</p></div><p><span class="comment"> after</span></p>' in rendered
 
         # the 3rd parameter, u'',  should be a binary string defining a png image, but it is not needed for this simple test
         update_item(u'logo.png', {CONTENTTYPE: u'image/png'}, u'')
         # simple transclusion
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'{{logo.png}}')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'{{logo.png}}')
         rendered = Item.create(u'page1').content._render_data()
         assert '<p><span class="moin-transclusion" data-href="/logo.png"><img alt="logo.png" src=' in rendered
         assert '/logo.png" /></span></p>' in rendered
         # within paragraph
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'text {{logo.png}} text')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'text {{logo.png}} text')
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <span class="moin-transclusion" data-href="/logo.png"><img alt="logo.png" src=' in rendered
         assert '/logo.png" /></span> text</p>' in rendered
         # within markup
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Normal ''italic '''bold {{logo.png}} bold''' italic'' normal")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Normal ''italic '''bold {{logo.png}} bold''' italic'' normal")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>Normal <em>italic <strong>bold <span class="moin-transclusion" data-href="/logo.png"><img alt="logo.png" src=' in rendered
         assert '/logo.png" /></span> bold</strong> italic</em> normal</p>' in rendered
         # multiple transclusions
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'{{logo.png}}{{logo.png}}')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'{{logo.png}}{{logo.png}}')
         rendered = Item.create(u'page1').content._render_data()
         assert '<p><span class="moin-transclusion" data-href="/logo.png"><img alt="logo.png" src=' in rendered
         assert '/logo.png" /></span><span class="moin-transclusion" data-href="/logo.png"><img alt="logo.png" src=' in rendered
 
     def test_IncludeAsLinkAlternate(self):
         # image as link alternate
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"text [[page2|{{logo.png}}]] text")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"text [[page2|{{logo.png}}]] text")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <a href="/page2"><span class="moin-transclusion" data-href="/logo.png"><img alt="logo.png" src="' in rendered
         assert '/logo.png" /></span></a> text</p>' in rendered
         # link alternate with image embedded in markup
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"text [[page2|plain '''bold {{logo.png}} bold''' plain]] text")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"text [[page2|plain '''bold {{logo.png}} bold''' plain]] text")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <a href="/page2">plain <strong>bold <span class="moin-transclusion" data-href="/logo.png"><img alt="logo.png" src="' in rendered
         assert '/logo.png" /></span> bold</strong> plain</a> text</p>' in rendered
         # nonexistent image used in link alternate
         # XXX html validation errora: A inside A - the image alternate turns into an A-tag to create the non-existant image.  Error is easily seen.
         # IE9, Firefox, Chrome, Safari, and Opera display this OK;  the only usable hyperlink is to create the missing image.
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"text [[page2|{{logoxxx.png}}]] text")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"text [[page2|{{logoxxx.png}}]] text")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <a href="/page2"><span class="moin-transclusion" data-href="/logoxxx.png"><a href="/+modify/logoxxx.png">' in rendered
         assert '</a></span></a> text</p>' in rendered
         # image used as alternate to nonexistent page
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u"text [[page2xxx|{{logo.png}}]] text")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"text [[page2xxx|{{logo.png}}]] text")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <a class="moin-nonexistent" href="/page2xxx"><span class="moin-transclusion" data-href="/logo.png"><img alt="logo.png" src="' in rendered
         assert '/logo.png" /></span></a> text</p>' in rendered
         # transclude block elem as link alternate to nonexistent page
         # XXX html validation errors, block element inside A.
         # IE9, Firefox, Chrome, Safari, and Opera display this OK;  the hyperlink is the entire div enclosing the block elem
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'text [[MyPage|{{page2}}]] text')
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"Double\n\nLine")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'text [[MyPage|{{page2}}]] text')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"Double\n\nLine")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <a class="moin-nonexistent" href="/MyPage"><div class="moin-transclusion" data-href="/page2"><p>Double</p><p>Line</p></div></a> text</p>' in rendered
         # transclude empty item as link alternate to nonexistent page
         # hyperlink will be empty span and invisible
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'text [[MyPage|{{page2}}]] text')
-        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki'}, u"")
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'text [[MyPage|{{page2}}]] text')
+        update_item(u'page2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u"")
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <a class="moin-nonexistent" href="/MyPage"><span class="moin-transclusion" data-href="/page2"></span></a> text</p>' in rendered
         # transclude external page as link alternate to nonexistent page
-        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki'}, u'text [[MyPage|{{http://moinmo.in}}]] text')
+        update_item(u'page1', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'text [[MyPage|{{http://moinmo.in}}]] text')
         rendered = Item.create(u'page1').content._render_data()
         assert '<p>text <a class="moin-nonexistent" href="/MyPage"><object class="moin-http moin-transclusion" data="http://moinmo.in" data-href="http://moinmo.in">http://moinmo.in</object></a> text</p>' in rendered

File MoinMoin/items/_tests/test_Blog.py

     NO_ENTRIES_MSG = u"There are no entries"
 
     name = u'NewBlogItem'
-    contenttype = u'text/x.moin.wiki'
+    contenttype = u'text/x.moin.wiki;charset=utf-8'
     data = u"This is the header item of this blog"
     meta = {CONTENTTYPE: contenttype, ITEMTYPE: ITEMTYPE_BLOG}
     comment = u'saved it'
 
 class TestBlogEntry(TestView):
     blog_name = u'NewBlogItem'
-    contenttype = u'text/x.moin.wiki'
+    contenttype = u'text/x.moin.wiki;charset=utf-8'
     blog_data = u"This is the header item of this blog"
     blog_meta = {CONTENTTYPE: contenttype, ITEMTYPE: ITEMTYPE_BLOG}
     comment = u'saved it'

File MoinMoin/items/_tests/test_Content.py

     def test_get_templates(self):
         item_name1 = u'Template_Item1'
         item1 = Item.create(item_name1)
-        contenttype1 = u'text/plain'
+        contenttype1 = u'text/plain;charset=utf-8'
         meta = {CONTENTTYPE: contenttype1, TAGS: ['template']}
         item1._save(meta)
         item1 = Item.create(item_name1)
 
         item_name2 = u'Template_Item2'
         item2 = Item.create(item_name2)
-        contenttype1 = u'text/plain'
+        contenttype1 = u'text/plain;charset=utf-8'
         meta = {CONTENTTYPE: contenttype1, TAGS: ['template']}
         item2._save(meta)
         item2 = Item.create(item_name2)
 
     def test_data_conversion(self):
         item_name = u'Text_Item'
-        item = Item.create(item_name, ITEMTYPE_DEFAULT, u'text/plain')
+        item = Item.create(item_name, ITEMTYPE_DEFAULT, u'text/plain;charset=utf-8')
         test_text = u'This \n is \n a \n Test'
         # test for data_internal_to_form
         result = Text.data_internal_to_form(item.content, test_text)
     def test__render_data_diff_text(self):
         item_name = u'Text_Item'
         item = Item.create(item_name)
-        contenttype = u'text/plain'
+        contenttype = u'text/plain;charset=utf-8'
         meta = {CONTENTTYPE: contenttype}
         item._save(meta)
         item1 = Item.create(item_name)
     def test__render_data_highlight(self):
         item_name = u'Text_Item'
         item = Item.create(item_name)
-        contenttype = u'text/plain'
+        contenttype = u'text/plain;charset=utf-8'
         meta = {CONTENTTYPE: contenttype}
         item._save(meta)
         item1 = Item.create(item_name)

File MoinMoin/items/_tests/test_Item.py

                     {NAME: [u'Page',
                             u'Another name',
                             ],
-                     CONTENTTYPE: u'text/x.moin.wiki'}, content)
+                     CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, content)
 
         item1 = Item.create(u'Page')
         assert item1.name == u'Page'
-        assert item1.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item1.meta[CONTENTTYPE] == 'text/x.moin.wiki;charset=utf-8'
         assert item1.content.data == content
 
         item2 = Item.create(u'Another name')
         assert item2.name == u'Another name'
-        assert item2.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item2.meta[CONTENTTYPE] == 'text/x.moin.wiki;charset=utf-8'
         assert item2.content.data == content
 
         assert item1.rev.revid == item2.rev.revid
                             u'Second',
                             u'Third',
                             ],
-                     CONTENTTYPE: u'text/x.moin.wiki'}, content)
+                     CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, 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.meta[CONTENTTYPE] == 'text/x.moin.wiki;charset=utf-8'
         assert item1.content.data == content
 
         item2 = Item.create(u'New name')
         assert item2.name == u'New name'
-        assert item2.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item2.meta[CONTENTTYPE] == 'text/x.moin.wiki;charset=utf-8'
         assert item2.content.data == content
 
         item3 = Item.create(u'Third')
         assert item3.name == u'Third'
-        assert item3.meta[CONTENTTYPE] == 'text/x.moin.wiki'
+        assert item3.meta[CONTENTTYPE] == 'text/x.moin.wiki;charset=utf-8'
         assert item3.content.data == content
 
         assert item1.rev.revid == item2.rev.revid == item3.rev.revid
         assert item4.meta[CONTENTTYPE] == CONTENTTYPE_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')
-        update_item(u'Page/Child/Another', {CONTENTTYPE: u'text/x.moin.wiki'}, u'another child')
+        update_item(u'Page', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'Page 1')
+        update_item(u'Page/Child', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'this is child')
+        update_item(u'Page/Child/Another', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'another child')
 
         item = Item.create(u'Page')
         item.rename(u'Renamed_Page', comment=u'renamed')
 
     def test_rename_recursion_with_multiple_names_and_children(self):
         update_item(u'Foo', {
-            CONTENTTYPE: u'text/x.moin.wiki',
+            CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8',
             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'Page/Child', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'Child of Page')
+        update_item(u'Other/Child2', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'Child of Other')
         update_item(u'Another', {
-            CONTENTTYPE: u'text/x.moin.wiki',
+            CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8',
             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')
+        update_item(u'Page/Second/Child', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'Child of Second')
+        update_item(u'Another/Child', {CONTENTTYPE: u'text/x.moin.wiki;charset=utf-8'}, u'Child of Another')
 
         item = Item.create(u'Page')
 

File MoinMoin/log.py

 # See http://docs.python.org/library/logging.html#configuring-logging
 # We just use stderr output by default, if you want anything else,
 # you will have to configure logging.
-logging_defaults = {
-    'loglevel': 'INFO',
-}
 logging_config = """\
+[DEFAULT]
+# Default loglevel, to adjust verbosity: DEBUG, INFO, WARNING, ERROR, CRITICAL
+loglevel=INFO
+
 [loggers]
 keys=root
 
     if conf_fname:
         try:
             conf_fname = os.path.abspath(conf_fname)
-            logging.config.fileConfig(conf_fname)
+            # we open the conf file here to be able to give a reasonable
+            # error message in case of failure (if we give the filename to
+            # fileConfig(), it silently ignores unreadable files and gives
+            # unhelpful error msgs like "No section: 'formatters'"):
+            f = open(conf_fname)
+            try:
+                logging.config.fileConfig(f)
+            finally:
+                f.close()
             configured = True
             l = getLogger(__name__)
             l.info('using logging configuration read from "{0}"'.format(conf_fname))
     if not configured:
         # load builtin fallback logging config
         from StringIO import StringIO
-        config_file = StringIO(logging_config)
-        logging.config.fileConfig(config_file, logging_defaults)
+        f = StringIO(logging_config)
+        try:
+            logging.config.fileConfig(f)
+        finally:
+            f.close()
         configured = True
         l = getLogger(__name__)
         if err_msg:
             l.warning('load_config for "{0}" failed with "{1}".'.format(conf_fname, err_msg))
-        l.warning('using logging configuration read from built-in fallback in MoinMoin.log module!')
+        l.info('using logging configuration read from built-in fallback in MoinMoin.log module!')
         warnings.showwarning = _log_warning
 
+    import MoinMoin
+    code_path = os.path.dirname(MoinMoin.__file__)
+    l.info('Running %s %s code from %s' % (MoinMoin.project, MoinMoin.version, code_path))
+
 
 def getLogger(name):
     """ wrapper around logging.getLogger, so we can do some more stuff:

File MoinMoin/storage/__init__.py

 """
 
 
-CONTENT, USERPROFILES = u'content', u'userprofiles'
+BACKENDS_PACKAGE = 'MoinMoin.storage.backends'
 
-BACKENDS_PACKAGE = 'MoinMoin.storage.backends'
+from MoinMoin.constants.namespaces import NAMESPACE_DEFAULT, NAMESPACE_USERPROFILES
+
+BACKEND_DEFAULT, BACKEND_USERPROFILES = u'default', u'userprofiles'
 
 
 def backend_from_uri(uri):
     if not user_profile_acl:
         user_profile_acl = dict(before=u'All:', default=u'', after=u'', hierarchic=False)
     namespaces = {
-        u'': CONTENT,
-        u'userprofiles:': USERPROFILES,
+        NAMESPACE_DEFAULT: BACKEND_DEFAULT,
+        NAMESPACE_USERPROFILES + ':': BACKEND_USERPROFILES,
     }
     backends = {
-        CONTENT: None,
-        USERPROFILES: None,
+        BACKEND_DEFAULT: None,
+        BACKEND_USERPROFILES: None,
     }
     acls = {
-        'userprofiles:': user_profile_acl,
-        '': content_acl,
+        NAMESPACE_USERPROFILES + ':': user_profile_acl,
+        NAMESPACE_DEFAULT: content_acl,
     }
     return create_mapping(uri, namespaces, backends, acls)

File MoinMoin/storage/middleware/_tests/test_indexing.py

 
 from MoinMoin.constants.keys import (NAME, SIZE, ITEMID, REVID, DATAID, HASH_ALGORITHM, CONTENT, COMMENT,
                                      LATEST_REVS, ALL_REVS, NAMESPACE)
+from MoinMoin.constants.namespaces import NAMESPACE_USERPROFILES
 
 from MoinMoin.auth import GivenAuth
 from MoinMoin._tests import wikiconfig
         # TODO: this is a very simple check that assumes that data is put 1:1
         # into index' CONTENT field.
         item_name = u'foo'
-        meta = dict(name=[item_name, ], contenttype=u'text/plain')
+        meta = dict(name=[item_name, ], contenttype=u'text/plain;charset=utf-8')
         data = 'some test content\n'
         item = self.imw[item_name]
         data_file = StringIO(data)
     def test_namespaces(self):
         item_name_n = u'normal'
         item = self.imw[item_name_n]
-        rev_n = item.store_revision(dict(name=[item_name_n, ], contenttype=u'text/plain'),
+        rev_n = item.store_revision(dict(name=[item_name_n, ], contenttype=u'text/plain;charset=utf-8'),
                                     StringIO(str(item_name_n)), return_rev=True)
-        item_name_u = u'userprofiles:userprofile'
+        item_name_u = u'%s:userprofile' % NAMESPACE_USERPROFILES
         item = self.imw[item_name_u]
-        rev_u = item.store_revision(dict(name=[item_name_u, ], contenttype=u'text/plain'),
+        rev_u = item.store_revision(dict(name=[item_name_u, ], contenttype=u'text/plain;charset=utf-8'),
                                     StringIO(str(item_name_u)), return_rev=True)
         item = self.imw[item_name_n]
         rev_n = item.get_revision(rev_n.revid)
         assert rev_n.meta[NAME] == [item_name_n, ]
         item = self.imw[item_name_u]
         rev_u = item.get_revision(rev_u.revid)
-        assert rev_u.meta[NAMESPACE] == u'userprofiles'
+        assert rev_u.meta[NAMESPACE] == NAMESPACE_USERPROFILES
         assert rev_u.meta[NAME] == [item_name_u.split(':')[1]]
 
     def test_parentnames(self):
         item_name = u'child'
         item = self.imw[item_name]
         item.store_revision(dict(name=[u'child', u'p1/a', u'p2/b', u'p2/c', u'p3/p4/d', ],
-                                 contenttype=u'text/plain'),
+                                 contenttype=u'text/plain;charset=utf-8'),
                             StringIO(''))
         item = self.imw[item_name]
         assert item.parentnames == [u'p1', u'p2', u'p3/p4', ]  # one p2 duplicate removed

File MoinMoin/storage/middleware/_tests/test_protecting.py

         revids = []
         for item_name, acl, content in items:
             item = self.imw[item_name]
-            r = item.store_revision(dict(name=[item_name, ], acl=acl, contenttype=u'text/plain'),
+            r = item.store_revision(dict(name=[item_name, ], acl=acl, contenttype=u'text/plain;charset=utf-8'),
                                     StringIO(content), return_rev=True)
             revids.append(r.revid)
         return revids
         revid_unprotected, revid_protected = self.make_items(u'joe:write', u'boss:write')
         # now testing:
         item = self.imw[UNPROTECTED]
-        item.store_revision(dict(name=[UNPROTECTED, ], acl=u'joe:write', contenttype=u'text/plain'), StringIO(UNPROTECTED_CONTENT))
+        item.store_revision(dict(name=[UNPROTECTED, ], acl=u'joe:write', contenttype=u'text/plain;charset=utf-8'), StringIO(UNPROTECTED_CONTENT))
         item = self.imw[PROTECTED]
         with pytest.raises(AccessDenied):
-            item.store_revision(dict(name=[PROTECTED, ], acl=u'boss:write', contenttype=u'text/plain'), StringIO(UNPROTECTED_CONTENT))
+            item.store_revision(dict(name=[PROTECTED, ], acl=u'boss:write', contenttype=u'text/plain;charset=utf-8'), StringIO(UNPROTECTED_CONTENT))
 
     def test_write_create(self):
         # now testing:
         item_name = u'newitem'
         item = self.imw[item_name]
-        item.store_revision(dict(name=[item_name, ], contenttype=u'text/plain'), StringIO('new content'))
+        item.store_revision(dict(name=[item_name, ], contenttype=u'text/plain;charset=utf-8'), StringIO('new content'))
 
     def test_overwrite_revision(self):
         revid_unprotected, revid_protected = self.make_items(u'joe:write,destroy', u'boss:write,destroy')
         # now testing:
         item = self.imw[UNPROTECTED]
-        item.store_revision(dict(name=[UNPROTECTED, ], acl=u'joe:write,destroy', contenttype=u'text/plain', revid=revid_unprotected),
+        item.store_revision(dict(name=[UNPROTECTED, ], acl=u'joe:write,destroy', contenttype=u'text/plain;charset=utf-8', revid=revid_unprotected),
                             StringIO(UNPROTECTED_CONTENT), overwrite=True)
         item = self.imw[PROTECTED]
         with pytest.raises(AccessDenied):
-            item.store_revision(dict(name=[PROTECTED, ], acl=u'boss:write,destroy', contenttype=u'text/plain', revid=revid_protected),
+            item.store_revision(dict(name=[PROTECTED, ], acl=u'boss:write,destroy', contenttype=u'text/plain;charset=utf-8', revid=revid_protected),
                                 StringIO(UNPROTECTED_CONTENT), overwrite=True)
 
     def test_destroy_revision(self):

File MoinMoin/storage/middleware/_tests/test_serialization.py

 from ..serialization import serialize, deserialize
 
 from MoinMoin.constants.keys import NAME, CONTENTTYPE
+from MoinMoin.constants.namespaces import NAMESPACE_DEFAULT
 
 from MoinMoin.storage.backends.stores import MutableBackend
 from MoinMoin.storage.stores.memory import BytesStore, FileStore
 
 
 contents = [
-    (u'Foo', {NAME: [u'Foo', ], CONTENTTYPE: u'text/plain'}, ''),
-    (u'Foo', {NAME: [u'Foo', ], CONTENTTYPE: u'text/plain'}, '2nd'),
-    (u'Subdir', {NAME: [u'Subdir', ], CONTENTTYPE: u'text/plain'}, ''),
-    (u'Subdir/Foo', {NAME: [u'Subdir/Foo', ], CONTENTTYPE: u'text/plain'}, ''),
-    (u'Subdir/Bar', {NAME: [u'Subdir/Bar', ], CONTENTTYPE: u'text/plain'}, ''),
+    (u'Foo', {NAME: [u'Foo', ], CONTENTTYPE: u'text/plain;charset=utf-8'}, ''),
+    (u'Foo', {NAME: [u'Foo', ], CONTENTTYPE: u'text/plain;charset=utf-8'}, '2nd'),
+    (u'Subdir', {NAME: [u'Subdir', ], CONTENTTYPE: u'text/plain;charset=utf-8'}, ''),
+    (u'Subdir/Foo', {NAME: [u'Subdir/Foo', ], CONTENTTYPE: u'text/plain;charset=utf-8'}, ''),
+    (u'Subdir/Bar', {NAME: [u'Subdir/Bar', ], CONTENTTYPE: u'text/plain;charset=utf-8'}, ''),
 ]
 
 
     meta_store = BytesStore()
     data_store = FileStore()
     _backend = MutableBackend(meta_store, data_store)
-    namespaces = [('', u'backend')]
+    namespaces = [(NAMESPACE_DEFAULT, u'backend')]
     backends = {u'backend': _backend}
     backend = RoutingBackend(namespaces, backends)
     backend.create()

File MoinMoin/storage/middleware/indexing.py

 
 from MoinMoin.constants.keys import (WIKINAME, NAMESPACE, NAME, NAME_EXACT, MTIME, CONTENTTYPE, TAGS, LANGUAGE,
                                      USERID, ADDRESS, HOSTNAME, SIZE, ACTION, COMMENT, SUMMARY, CONTENT,
-                                     EXTERNALLINKS, ITEMLINKS, ITEMTRANSCLUSIONS, ACL, EMAIL, OPENID,
+                                     EXTERNALLINKS, ITEMLINKS, ITEMTRANSCLUSIONS, ACL, DISABLED, EMAIL, OPENID,
                                      ITEMID, REVID, CURRENT, PARENTID, PTIME, LATEST_REVS, ALL_REVS, BACKENDNAME)
 from MoinMoin.constants.contenttypes import CONTENTTYPE_USER
+from MoinMoin.constants.namespaces import NAMESPACE_DEFAULT
 from MoinMoin.constants import keys
 from MoinMoin.constants.keys import ITEMTYPE
 
 WHOOSH_FILESTORAGE = 'FileStorage'
 INDEXES = [LATEST_REVS, ALL_REVS, ]
 
+VALIDATION_HANDLING_STRICT = 'strict'
+VALIDATION_HANDLING_WARN = 'warn'
+VALIDATION_HANDLING = VALIDATION_HANDLING_WARN
+
 
 def get_names(meta):
     """
         common_fields = {
             # wikiname so we can have a shared index in a wiki farm, always check this!
             WIKINAME: ID(stored=True),
+            # namespace, so we can have different namespaces within a wiki, always check this!
+            NAMESPACE: ID(stored=True),
             # tokenized NAME from metadata - use this for manual searching from UI
             NAME: TEXT(stored=True, multitoken_query="and", analyzer=item_name_analyzer(), field_boost=2.0),
             # unmodified NAME from metadata - use this for precise lookup by the code.
             # killing other users from index when update_document() is called!
             EMAIL: ID(stored=True),
             OPENID: ID(stored=True),
+            DISABLED: BOOLEAN(stored=True),
         }
         latest_revs_fields.update(**userprofile_fields)
 
             Schema = ContentMetaSchema
         m = Schema(meta)
         valid = m.validate(state)
-        # TODO: currently we just log validation results. in the end we should
-        # reject invalid stuff in some comfortable way.
         if not valid:
             logging.warning("metadata validation failed, see below")
             for e in m.children:
                 logging.warning("{0}, {1}".format(e.valid, e))
+            if VALIDATION_HANDLING == VALIDATION_HANDLING_STRICT:
+                raise ValueError('metadata validation failed and strict handling requested, see the log for details')
 
         # we do not have anything in m that is not defined in the schema,
         # e.g. userdefined meta keys or stuff we do not validate. thus, we

File MoinMoin/storage/middleware/routing.py

         """
         self.namespaces = namespaces
         self.backends = backends
+        for namespace, backend_name in namespaces:
+            assert isinstance(namespace, unicode)
+            assert backend_name in backends
 
     def open(self):
         for backend in self.backends.values():

File MoinMoin/storage/middleware/validation.py

     """
     if element.raw is Unset:
         element.set(state[keys.NAMESPACE])
+    v = element.value
+    if v is None:
+        return True  # the routing middleware can extract namespace from the name
     return name_validator(element, state)
 
 
     String.named(keys.PARENTID).validated_by(uuid_validator).using(optional=True),
     String.named(keys.WIKINAME).using(strip=False).validated_by(wikiname_validator),
     String.named(keys.NAMESPACE).using(strip=False).validated_by(namespace_validator),
-    List.named(keys.NAME).of(String.using(strip=False).validated_by(name_validator)),
+    List.named(keys.NAME).of(String.using(strip=False).validated_by(name_validator)).using(optional=True),
     List.named(keys.NAME_OLD).of(String.using(strip=False).validated_by(name_validator)).using(optional=True),
     Integer.named(keys.MTIME).validated_by(mtime_validator),
     String.named(keys.ACTION).validated_by(action_validator),

File MoinMoin/user.py

 
 from MoinMoin import wikiutil
 from MoinMoin.constants.contenttypes import CONTENTTYPE_USER
+from MoinMoin.constants.namespaces import NAMESPACE_USERPROFILES
 from MoinMoin.constants.keys import *
 from MoinMoin.constants.misc import ANON
 from MoinMoin.i18n import _, L_, N_
 
 def update_user_query(**q):
     USER_QUERY_STDARGS = {
+        NAMESPACE: NAMESPACE_USERPROFILES,
         CONTENTTYPE: CONTENTTYPE_USER,
         WIKINAME: app.cfg.interwikiname,  # XXX for now, search only users of THIS wiki
                                           # maybe add option to not index wiki users
               force=True because these changes are not detected!
         """
         if self._changed or force:
+            self[NAMESPACE] = NAMESPACE_USERPROFILES
             self[CONTENTTYPE] = CONTENTTYPE_USER
             q = {ITEMID: self[ITEMID]}
             q = update_user_query(**q)

File MoinMoin/util/_tests/test_mimetype.py

 
         # major == 'text'
         result2 = MimeType_obj.content_type(major='text', minor='plain', charset="utf-16", params=None)
-        expected = 'text/plain; charset="utf-16"'
+        expected = 'text/plain;charset="utf-16"'
         assert result2 == expected
 
         # when all the parameters passed are None

File MoinMoin/util/mimetype.py

         mimestr = "{0}/{1}".format(major, minor)
         params = ['{0}="{1}"'.format(key.lower(), value) for key, value in params.items()]
         params.insert(0, mimestr)
-        return "; ".join(params)
+        return ";".join(params)
 
     def mime_type(self):
         """ return a string major/minor only, no params """