Commits

Thomas Waldmann committed 8300781

make contenttype values pass the validator (add charset for text), fix namespace and name validators

mimetype string generation: remove blank after semicolon

Comments (0)

Files changed (12)

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)
 
 

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):

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

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'

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)

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')
 

MoinMoin/storage/middleware/_tests/test_indexing.py

         # 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'%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)
         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

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):

MoinMoin/storage/middleware/_tests/test_serialization.py

 
 
 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'}, ''),
 ]
 
 

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),

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

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 """