Use doctest with bytes, str & unicode on Python 2.x and 3.x
Project description
pretext
=======
.. image:: https://travis-ci.org/moreati/b-prefix-all-the-doctests.svg
:target: https://travis-ci.org/moreati/b-prefix-all-the-doctests
This package makes it easy to write doctests that involve strings, and
still have those doctests work with Python 2.6, 2.7, and 3.3+.
Just `import pretext` and call `pretext.activate()`. By default Python 3.x
`repr()` behaviour is used
.. code:: python
>>> import pretext; pretext.activate()
>>> b'Now strings have a consistant repr on Python 2.x & 3.x'
b'Now strings have a consistant repr on all Python versions'
>>> u'Unicode strings & nested strings work too'.split()
['Unicode', 'strings', '&', 'nested', 'strings', 'work', 'too']
The problem
-----------
Suppose you have the following doctest, and you aren't using pretext
.. code:: python
>>> textfunc()
u'I return a textual (unicode) string'
>>> bytesfunc()
b'I return a byte (binary) string'
On Python 2.x ``textfunc()`` will pass. On Python 3.x it will fail.
This is because doctest compares the expected value with ``repr(textfunc())``,
and on Python 3.x the `repr()` will not include a ``u''`` prefix.
On Python 2.x ``bytesfunc()`` will fail. On Python 3.x it will pass.
This is because on Python 2.x ``repr(bytesfunc())`` won't include the ``b''``
prefix.
If the tests cases are editted to remove the prefixes, i.e.
.. code:: python
>>> textfunc()
'I return a textual (unicode) string'
>>> bytesfunc()
'I return a byte (binary) string'
then the failures will be reversed. ``textfunc()`` will now fail on Python 2.x,
``bytesfunc()`` will fail on Python 3.x.
The hack
--------
Replace ``repr()`` and ``sys.displayhook`` with versions that always prefix
string literals, regardless of the Python version. Now the doctests can
- directly show the string values returned by functions/methods,
without resorting to ``print()``, or ``.encode()`` etc
- successfully test the examples on all Python versions
Proof of concept:
.. code:: python
r"""
>>> import sys
>>> import pretext
>>> myrepr = bar.PrefixRepr()
>>> repr = myrepr.repr
>>> def _displayhook(value):
... if value is not None:
... sys.stdout.write(myrepr.repr(value))
>>> sys.displayhook = _displayhook
>>> u''
u''
>>> b''
b''
>>> bytes()
b''
>>> b'\0'
b'\x00'
>>> b"'"
b"'"
"""
Alternatives
------------
If you're ready to run screaming at the above, there are alternatives e.g.
- Wrap byte-string returns in ``bytearray()``.
``repr(bytearray(b'abc')) == "bytearray(b'abc'))"`` on all versions of
python that have ``bytearray()`` (2.6 onward) e.g.
.. code:: python
>>> bytearray(bytesfunc())
bytearray(b'I return a byte (binary) string')
- Support Python 3.x exclusively
- Use ``print(bytesfunc().decode('ascii'))`` and choose your input values carefully
- Use ``#doctest: +SKIP``
- Use ``#doctest: +ELLIPSIS``
For HTML or XML in a doctest `lxml`_ includes the modules
`lxml.html.usedoctest`_ and `lxml.usedoctext`_.
.. _lxml: https://pypi.python.org/pypi/lxml
.. _lxml.html.usedoctest: http://lxml.de/api/lxml.html.usedoctest-module.html
.. _lxml.usedoctest: http://lxml.de/api/lxml.usedoctest-module.html
=======
.. image:: https://travis-ci.org/moreati/b-prefix-all-the-doctests.svg
:target: https://travis-ci.org/moreati/b-prefix-all-the-doctests
This package makes it easy to write doctests that involve strings, and
still have those doctests work with Python 2.6, 2.7, and 3.3+.
Just `import pretext` and call `pretext.activate()`. By default Python 3.x
`repr()` behaviour is used
.. code:: python
>>> import pretext; pretext.activate()
>>> b'Now strings have a consistant repr on Python 2.x & 3.x'
b'Now strings have a consistant repr on all Python versions'
>>> u'Unicode strings & nested strings work too'.split()
['Unicode', 'strings', '&', 'nested', 'strings', 'work', 'too']
The problem
-----------
Suppose you have the following doctest, and you aren't using pretext
.. code:: python
>>> textfunc()
u'I return a textual (unicode) string'
>>> bytesfunc()
b'I return a byte (binary) string'
On Python 2.x ``textfunc()`` will pass. On Python 3.x it will fail.
This is because doctest compares the expected value with ``repr(textfunc())``,
and on Python 3.x the `repr()` will not include a ``u''`` prefix.
On Python 2.x ``bytesfunc()`` will fail. On Python 3.x it will pass.
This is because on Python 2.x ``repr(bytesfunc())`` won't include the ``b''``
prefix.
If the tests cases are editted to remove the prefixes, i.e.
.. code:: python
>>> textfunc()
'I return a textual (unicode) string'
>>> bytesfunc()
'I return a byte (binary) string'
then the failures will be reversed. ``textfunc()`` will now fail on Python 2.x,
``bytesfunc()`` will fail on Python 3.x.
The hack
--------
Replace ``repr()`` and ``sys.displayhook`` with versions that always prefix
string literals, regardless of the Python version. Now the doctests can
- directly show the string values returned by functions/methods,
without resorting to ``print()``, or ``.encode()`` etc
- successfully test the examples on all Python versions
Proof of concept:
.. code:: python
r"""
>>> import sys
>>> import pretext
>>> myrepr = bar.PrefixRepr()
>>> repr = myrepr.repr
>>> def _displayhook(value):
... if value is not None:
... sys.stdout.write(myrepr.repr(value))
>>> sys.displayhook = _displayhook
>>> u''
u''
>>> b''
b''
>>> bytes()
b''
>>> b'\0'
b'\x00'
>>> b"'"
b"'"
"""
Alternatives
------------
If you're ready to run screaming at the above, there are alternatives e.g.
- Wrap byte-string returns in ``bytearray()``.
``repr(bytearray(b'abc')) == "bytearray(b'abc'))"`` on all versions of
python that have ``bytearray()`` (2.6 onward) e.g.
.. code:: python
>>> bytearray(bytesfunc())
bytearray(b'I return a byte (binary) string')
- Support Python 3.x exclusively
- Use ``print(bytesfunc().decode('ascii'))`` and choose your input values carefully
- Use ``#doctest: +SKIP``
- Use ``#doctest: +ELLIPSIS``
For HTML or XML in a doctest `lxml`_ includes the modules
`lxml.html.usedoctest`_ and `lxml.usedoctext`_.
.. _lxml: https://pypi.python.org/pypi/lxml
.. _lxml.html.usedoctest: http://lxml.de/api/lxml.html.usedoctest-module.html
.. _lxml.usedoctest: http://lxml.de/api/lxml.usedoctest-module.html
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
pretext-0.0.4.tar.gz
(11.2 kB
view hashes)
Built Distribution
Close
Hashes for pretext-0.0.4-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 21461c993359aa9946715ecbd8f7a0785e13e1cbe2142d2f5d1ae033f91d6264 |
|
MD5 | 5f7ff813abdf605bb4fd15135b3ce861 |
|
BLAKE2b-256 | f86581fb591f4e4560cc65eb8c62255440d4830994eb32a6f57829b58292ed8f |