Skip to content

Commit

Permalink
Add output checker with support to remove u/b for string literals in …
Browse files Browse the repository at this point in the history
…doctests.
  • Loading branch information
sallner committed May 18, 2018
1 parent 7212349 commit b636e98
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 8 deletions.
8 changes: 6 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
Changes
=======

4.6.3 (unreleased)
4.7.0 (unreleased)
------------------

- Nothing changed yet.
New Features:

- Add doctest output output checker ``LiteralsOutputChecker`` which allows to
remove unicode and bytes prefixes from string literals in doctests. Inspired
by pytest.


4.6.2 (2017-06-12)
Expand Down
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ setupstack
A simple framework for automating doctest set-up and tear-down.
See setupstack.txt.

stringliterals
Bytes / unicode normalizing output checker.
Useful for doctests under python 2 and 3.

wait
A small utility for dealing with timing non-determinism
See wait.txt.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def read(*rnames):

setup(
name='zope.testing',
version='4.6.3.dev0',
version='4.7.0.dev0',
url='https://github.com/zopefoundation/zope.testing',
license='ZPL 2.1',
description='Zope testing helpers',
Expand Down
50 changes: 50 additions & 0 deletions src/zope/testing/stringliterals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import doctest
import re

ALLOW_UNICODE = doctest.register_optionflag('ALLOW_UNICODE')
ALLOW_BYTES = doctest.register_optionflag('ALLOW_BYTES')


class LiteralsOutputChecker(doctest.OutputChecker):
"""A checker with support for u/b literals.
Use the option flags from this module to get the desired effects:
ALLOW_UNICODE removes u/U prefixes
ALLOW_BYTES removes b/B prefixes
This version was copied from pytest
https://github.com/pytest-dev/pytest/blob/master/_pytest/doctest.py
which commented:
Copied from doctest_nose_plugin.py from the nltk project:
https://github.com/nltk/nltk
Further extended to also support byte literals.
"""

_unicode_literal_re = re.compile(r"(\W|^)[uU]([rR]?[\'\"])", re.UNICODE)
_bytes_literal_re = re.compile(r"(\W|^)[bB]([rR]?[\'\"])", re.UNICODE)

def check_output(self, want, got, optionflags):
res = doctest.OutputChecker.check_output(self, want, got,
optionflags)
if res:
return True

allow_unicode = optionflags & ALLOW_UNICODE
allow_bytes = optionflags & ALLOW_BYTES
if not allow_unicode and not allow_bytes:
return False

else:
def remove_prefixes(regex, txt):
return re.sub(regex, r'\1\2', txt)

if allow_unicode:
want = remove_prefixes(self._unicode_literal_re, want)
got = remove_prefixes(self._unicode_literal_re, got)
if allow_bytes:
want = remove_prefixes(self._bytes_literal_re, want)
got = remove_prefixes(self._bytes_literal_re, got)
res = doctest.OutputChecker.check_output(self, want, got,
optionflags)
return res
101 changes: 101 additions & 0 deletions src/zope/testing/test_stringliterals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from zope.testing.stringliterals import ALLOW_BYTES
from zope.testing.stringliterals import ALLOW_UNICODE
from zope.testing.stringliterals import LiteralsOutputChecker
import textwrap
import unittest


class TestLiteralsOutputChecker(unittest.TestCase):
"""Testing .renormalizing.LiteralsOutputChecker."""

def setUp(self):
super(TestLiteralsOutputChecker, self).setUp()
self.checker = LiteralsOutputChecker()

def test__LiteralsOutputChecker__check_output__1(self):
"""It works with simple strings."""
want = textwrap.dedent("""\
'Test string'
""")
got = textwrap.dedent("""\
'Test string'
""")
self.assertTrue(self.checker.check_output(want, got, 0))

def test__LiteralsOutputChecker__check_output__2(self):
"""It fails with simple strings."""
want = textwrap.dedent("""\
'Test string'
""")
got = textwrap.dedent("""\
'False test string'
""")
self.assertFalse(self.checker.check_output(want, got, 0))

def test__LiteralsOutputChecker__check_output__3(self):
"""It allows byte literals with option flag."""
want = textwrap.dedent("""\
'Test string'
b'Test bytes'
""")
got = textwrap.dedent("""\
b'Test string'
'Test bytes'
""")
self.assertFalse(self.checker.check_output(want, got, 0))
self.assertTrue(self.checker.check_output(want, got, ALLOW_BYTES))

def test__LiteralsOutputChecker__check_output__4(self):
"""It fails on byte literals with the ALLOW_UNICODE option flag."""
want = textwrap.dedent("""\
'Test string'
b'Test bytes'
""")
got = textwrap.dedent("""\
b'Test string'
'Test bytes'
""")
self.assertFalse(self.checker.check_output(want, got, 0))
self.assertFalse(self.checker.check_output(want, got, ALLOW_UNICODE))

def test__LiteralsOutputChecker__check_output__5(self):
"""It works allows unicode literals with option flag."""
want = textwrap.dedent("""\
'Test string'
u'Test unicode'
""")
got = textwrap.dedent("""\
u'Test string'
'Test unicode'
""")
self.assertFalse(self.checker.check_output(want, got, 0))
self.assertTrue(self.checker.check_output(want, got, ALLOW_UNICODE))

def test__LiteralsOutputChecker__check_output__6(self):
"""It fails on unicode literals with the ALLOW_BYTES option flag."""
want = textwrap.dedent("""\
'Test string'
u'Test unicode'
""")
got = textwrap.dedent("""\
u'Test string'
'Test unicode'
""")
self.assertFalse(self.checker.check_output(want, got, 0))
self.assertFalse(self.checker.check_output(want, got, ALLOW_BYTES))

def test__LiteralsOutputChecker__check_output__7(self):
"""It accepts both flags at the same time."""
want = textwrap.dedent("""\
'Test string'
'Test unicode'
'Test bytes'
""")
got = textwrap.dedent("""\
'Test string'
u'Test unicode'
b'Test bytes'
""")
self.assertFalse(self.checker.check_output(want, got, 0))
self.assertTrue(self.checker.check_output(
want, got, ALLOW_UNICODE | ALLOW_BYTES))
13 changes: 8 additions & 5 deletions src/zope/testing/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
##############################################################################
"""Tests for the testing framework.
"""
from zope.testing import renormalizing
from zope.testing.test_renormalizing import Exception2To3
from zope.testing.test_stringliterals import TestLiteralsOutputChecker
import doctest
import sys
import re
import sys
import unittest
from zope.testing import renormalizing
from zope.testing.test_renormalizing import Exception2To3

def print_(*args):
sys.stdout.write(' '.join(map(str, args))+'\n')
Expand Down Expand Up @@ -60,6 +61,8 @@ def test_suite():
if sys.version_info[0] < 3:
suite.addTests(doctest.DocTestSuite('zope.testing.server'))
suite.addTests(doctest.DocFileSuite('formparser.txt'))
suite.addTest(
unittest.makeSuite(Exception2To3))
suite.addTests([
unittest.makeSuite(Exception2To3),
unittest.makeSuite(TestLiteralsOutputChecker),
])
return suite

0 comments on commit b636e98

Please sign in to comment.