Description

With Python 2.7.5 (and probably 2.7.4) /action/rss_rc.py causes a traceback:

 mod_wsgi (pid=26537): Exception occurred processing WSGI script '/home/rockart/webapps/web/drawiki/moin.wsgi'.
 Traceback (most recent call last):
   File "/home/rockart/webapps/web/drawiki/MoinMoin/support/werkzeug/wsgi.py", line 411, in __call__
     return self.app(environ, start_response)
   File "/home/rockart/webapps/web/drawiki/MoinMoin/wsgiapp.py", line 282, in __call__
     response = run(context)
   File "/home/rockart/webapps/web/drawiki/MoinMoin/wsgiapp.py", line 88, in run
     response = dispatch(request, context, action_name)
   File "/home/rockart/webapps/web/drawiki/MoinMoin/wsgiapp.py", line 136, in dispatch
     response = handle_action(context, pagename, action_name)
   File "/home/rockart/webapps/web/drawiki/MoinMoin/wsgiapp.py", line 195, in handle_action
     handler(context.page.page_name, context)
   File "/home/rockart/webapps/web/drawiki/MoinMoin/action/rss_rc.py", line 162, in execute
     handler._out.write(unicode(
 AttributeError: RssGenerator instance has no attribute '_out'

The problem may be that _out was removed from xml.sax.saxutils.XMLGenerator in Python 2.7.4. Line 162 of /action/rss_rc.py is:

        handler._out.write(unicode(
            '<!--\n'
            '    Add an "items=nnn" URL parameter to get more than the \n'
            '    default %(def_max_items)d items. You cannot get more than \n'
            '    %(items_limit)d items though.\n'
            '    \n'
            '    Add "unique=1" to get a list of changes where page names are unique,\n'
            '    i.e. where only the latest change of each page is reflected.\n'
            '    \n'
            '    Add "diffs=1" to add change diffs to the description of each items.\n'
            '    \n'
            '    Add "ddiffs=1" to link directly to the diff (good for FeedReader).\n'
            '    \n'
            '    Add "lines=nnn" to change maximum number of diff/body lines \n'
            '    to show. Cannot be more than %(lines_limit)d.\n'
            '    \n'
            '    Add "show_att=1" to show items related to attachments.\n'
            '    \n'
            '    Add "page=pattern" to show feed only for specific pages.\n'
            '    Pattern can be empty (it would match to all pages), \n'
            '    can start with circumflex (it would be interpreted as \n'
            '    regular expression in this case), end with slash (for \n'
            '    getting feed for page tree) or point to specific page (if \n'
            '    none of the above can be applied).\n'
            '    \n'
            '    Current settings: items=%(max_items)i, unique=%(unique)i, \n'
            '    diffs=%(diffs)i, ddiffs=%(ddiffs)i, lines=%(max_lines)i, \n'
            '    show_att=%(show_att)i\n'
            '-->\n' % locals()
            ).encode(config.charset))

Steps to reproduce

Using Python 2.7.4+ attempt to access something like:

http://www.mywiki/action/rss_rc/HelpContents?diffs=1&show_att=1&action=rss_rc&unique=0&page=HelpContents&ddiffs=1

Note: The only known use of the above link are 3+ bots that are attempting to follow the link below from the html header (started 2 days ago with repeated attempts every 5 minutes):

<link rel="alternate" title="DigitalRockArt Wiki: IntroductionToDigitalRockArt" href="/drawiki/IntroductionToDigitalRockArt?diffs=1&show_att=1&action=rss_rc&unique=0&page=IntroductionToDigitalRockArt&ddiffs=1" type="application/rss+xml">

Example

Component selection

Details

MoinMoin Version

1.9.6

OS and Version

Centos 5

Python Version

2.7.5

Server Setup

apache

Server Details

wsgi

Language you are using the wiki in (set in the browser/UserPreferences)

en

Workaround

Replace handler._out.write(unicode( with handler._write(unicode( and delete .encode(config.charset) -- creates ugly output but eliminates the 500 server errors.

Discussion

Plan

Note: The above fix is not correct. Instead of replacing handler._out.write(unicode( with handler._write(unicode( and deleting .encode(config.charset) as suggested in the workaround, it replaces handler._out.write(unicode( with handler._write( and deletes .encode(config.charset)). The unicode( and the final ) should remain. Without that, the _write() method is given a string rather than a unicode and throws a TypeError. -- MarkSapiro 2014-10-12 01:08:44

Well, I guess I tested the fix back then when I made it and it worked for me. But maybe instead of verbally describing changes you think are better, can you please just give a diff of what you propose? And also, if you get an exception with the current code, I'ld also like to see the full traceback. -- ThomasWaldmann 2014-10-13 16:24:38

To clarify about removal of unicode(x): such an operation is pointless except when x is str and pure ascii. If x is str and not pure ascii, all unicode(x) will give you is an UnicodeDecodeError as it'll try to decode the str using the default ascii decoder and that will crash for everything non-ascii. That's why after changeset 6de72050e1b9 (which you maybe have not seen as it was not linked to at first) it just uses a unicode literal format string. Arguments that replace placeholders in it are expected to be either str-pure-ascii or unicode. -- ThomasWaldmann 2014-10-13 16:47:57

What I proposed was instead of http://hg.moinmo.in/moin/1.9/rev/aee4ff651134, the following:

diff -r 4790615ddfb6 -r aee4ff651134 MoinMoin/action/rss_rc.py
--- a/MoinMoin/action/rss_rc.py Wed Jun 05 00:37:14 2013 +0200
+++ b/MoinMoin/action/rss_rc.py Sat Jun 08 02:25:24 2013 +0200
@@ -159,7 +159,7 @@
 
         # start SAX stream
         handler.startDocument()
-        handler._out.write(unicode(
+        handler._write(unicode(
             '<!--\n'
             '    Add an "items=nnn" URL parameter to get more than the \n'
             '    default %(def_max_items)d items. You cannot get more than \n'
@@ -188,7 +188,7 @@
             '    diffs=%(diffs)i, ddiffs=%(ddiffs)i, lines=%(max_lines)i, \n'
             '    show_att=%(show_att)i\n'
             '-->\n' % locals()
-            ).encode(config.charset))
+            ))
 
         # emit channel description
         handler.startNode('channel', {

With just http://hg.moinmo.in/moin/1.9/rev/aee4ff651134 installed, I got

2014-10-11 17:13:35,330 MoinMoin.wsgiapp ERROR An exception has occurred [http://munged.invalid/wiki/RecentChanges?action=rss_rc&unique=1&ddiffs=1].
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 282, in __call__
    response = run(context)
  File "/usr/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 88, in run
    response = dispatch(request, context, action_name)
  File "/usr/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 136, in dispatch
    response = handle_action(context, pagename, action_name)
  File "/usr/lib/python2.7/site-packages/MoinMoin/wsgiapp.py", line 195, in handle_action
    handler(context.page.page_name, context)
  File "/usr/lib/python2.7/site-packages/MoinMoin/action/rss_rc.py", line 190, in execute
    '-->\n' % locals()
  File "/usr/lib/python2.7/xml/sax/saxutils.py", line 103, in write
    super(UnbufferedTextIOWrapper, self).write(s)
TypeError: must be unicode, not str

I agree that changing the argument text to unicode rather than string as was done with http://hg.moinmo.in/moin/1.9/rev/6de72050e1b9 fixes the problem with http://hg.moinmo.in/moin/1.9/rev/6de72050e1b9 alone, but since the later patch wasn't referenced here before now, and I'm not that familiar with Mercurial, I wasn't aware of it. -- MarkSapiro 2014-10-13 19:02:09


CategoryMoinMoinBugFixed

MoinMoin: MoinMoinBugs/rss_rc_Python_2.7.5_compatibility (last edited 2014-10-13 19:02:10 by MarkSapiro)