Martin v. Löwis wrote:
Johan Harjano ran into an interesting problem when trying to run the
Django test suite under Python 3.1.

Django has doctests of the form

>>> a6.headline
u'Default headline'

Even when converting the doctest with 2to3, the expected output is
unmodified. However, in 3.x, the expected output will change (i.e. not
produce an u"" prefix anymore).

Now, it might be possible to reformulate the test case (e.g. use print()
instead of relying on repr), however, this is undesirable as a) the test
should continue to test in 2.x that the result object is a unicode
string, and b) it makes the test less readable.

I would like to find a solution where this gets automatically corrected,
e.g. through 2to3, or through changes to doctest, or through changes of
str.__repr__.

Any proposal appreciated.

You can use a custom DocTestRunner that replaces sys.displayhook in
its run() method and records the changed output. Something like the
attached seems to do the trick.

Regards,
Ziga
import sys
import doctest
import linecache
import __builtin__


def greet():
    """
    The standard greeting, in unicode.

    >>> greet()
    u'Hello, world!'
    """
    return u'Hello, world!'


orig_displayhook = sys.displayhook

def py3_displayhook(value):
    if not isinstance(value, unicode):
        return orig_displayhook(value)
    __builtin__._ = value
    s = repr(value)
    if s.startswith(("u'", 'u"')):
        s = s[1:]
    print >> sys.stdout, s


class Runner(doctest.DocTestRunner):

    converted_files = {}

    def __init__(self, checker=None, verbose=None, optionflags=0):
        doctest.DocTestRunner.__init__(self, checker, False, optionflags)


    def run(self, test, compileflags=None, out=None, clear_globs=True):
        fn = test.filename
        if fn not in self.converted_files:
            self.converted_files[fn] = linecache.getlines(fn)
        sys.displayhook = py3_displayhook
        try:
            return doctest.DocTestRunner.run(self, test, compileflags,
                                              out, clear_globs)
        finally:
            sys.displayhook = orig_displayhook


    def report_failure(self, out, test, example, got):
        lines = [" " * example.indent + line for line in got.splitlines(True)]
        pos = test.lineno + example.lineno + 1
        self.converted_files[test.filename][pos:pos+len(lines)] = lines




def _test():
    import __main__
    finder = doctest.DocTestFinder()
    runner = Runner()
    for test in finder.find(__main__):
        runner.run(test)
    print "".join(runner.converted_files[__main__.__file__])


if __name__ == "__main__":
    _test()
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to