PKu‹8GfÄnüü pretext.pyfrom __future__ import print_function try: import builtins except ImportError: import __builtin__ as builtins try: import reprlib except ImportError: import repr as reprlib import sys __all__ = [ 'Repr', 'PrefixRepr', 'BytesRepr', 'UnicodeRepr', ] class Repr(reprlib.Repr): """A Repr that doesn't truncate it's output >>> myrepr = Repr().repr >>> myrepr('0123456789') "'0123456789'" >>> len(myrepr('0123456789')) 12 >>> len(myrepr('0123456789'*1000)) 10002 """ def __init__(self): self.maxlevel = sys.maxsize self.maxdict = sys.maxsize self.maxlist = sys.maxsize self.maxset = sys.maxsize self.maxfrozenset = sys.maxsize self.maxdeque = sys.maxsize self.maxarray = sys.maxsize self.maxlong = sys.maxsize self.maxstring = sys.maxsize self.maxlong = sys.maxsize self.maxother = sys.maxsize class PrefixRepr(Repr): """A Repr that always prefixes any string, and doesn't truncate For byte strings this mirrors the behaviour of repr() in Python 3.x. For textual strings this mirrors the behaviour of repr() in Python 2.x. >>> prefix_repr = PrefixRepr().repr >>> prefix_repr(b'0123456789') "b'0123456789'" >>> prefix_repr(u'0123456789') "u'0123456789'" """ def __init__(self): Repr.__init__(self) self._old_repr = repr def repr_str(self, obj, level): """Return the repr of a string, prefixed with b or u """ if str is bytes: # Python 2.x return b'b%s' % (self._old_repr(obj),) else: # Python 3.x return u'u%s' % (self._old_repr(obj),) class BytesRepr(PrefixRepr): """A Repr that prefixes byte strings, and doesn't truncate This mirrors the behaviour of repr() in Python 3.x. >>> py3_repr = BytesRepr().repr >>> py3_repr(b'0123456789') "b'0123456789'" >>> py3_repr(u'0123456789') "'0123456789'" """ def repr_str(self, obj, level): if str is bytes: # Python 2.x return b'b%s' % (self._old_repr(obj),) else: # Python 3.x return self._old_repr(obj) def repr_unicode(self, obj, level): # Only Python 2.x has a builtin type called unicode r = self._old_repr(obj) assert r[0] == 'u' return r[1:] class UnicodeRepr(PrefixRepr): """A Repr that prefixes textual (unicode) strings & doesn't truncate This mirrors the behaviour of repr() in Python 2.x. >>> py2_repr = UnicodeRepr().repr >>> py2_repr(b'0123456789') "'0123456789'" >>> py2_repr(u'0123456789') "u'0123456789'" """ def repr_str(self, obj, level): if str is bytes: return self._old_repr(obj) else: return u'u%s' % (self._old_repr(obj),) def repr_bytes(self, obj, level): r = self._old_repr(obj) assert r[0] == 'b' return r[1:] prepr = PrefixRepr().repr brepr = BytesRepr().repr urepr = UnicodeRepr().repr def _displayhook(value, repr_fn): if value is None: return # Set '_' to None to avoid recursion builtins._ = None text = repr_fn(value) try: sys.stdout.write(text) except UnicodeEncodeError: bytes = text.encode(sys.stdout.encoding, 'backslashreplace') if hasattr(sys.stdout, 'buffer'): sys.stdout.buffer.write(bytes) else: text = bytes.decode(sys.stdout.encoding, 'strict') sys.stdout.write(text) sys.stdout.write("\n") builtins._ = value def pdisplayhook(value): _displayhook(value, prepr) def bdisplayhook(value): _displayhook(value, brepr) def udisplayhook(value): _displayhook(value, urepr) PK¨š8GÑçâe e 'pretext-0.0.2.dist-info/DESCRIPTION.rstpretext ======= .. 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 is an experiment in writing doctests that involve strings, and that are cross-compatible with Python 2.6, 2.7, and 3.3+. The problem ----------- Suppose you have the following doctest .. code:: python >>> textfunc() u'I return a textual (unicode) string' >>> bytesfunc() b'I return a byte (binary) string' On Python 3.x the first test case will fail, because doctest will compare ``repr(textfunc())`` which will not include a ``u''`` prefix. On Python 2.x the second test will fail, because ``repr(bytesfunc())`` will not 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`` PK¨š8G*D¦ÿÿ%pretext-0.0.2.dist-info/metadata.json{"classifiers": ["Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Documentation", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing"], "extensions": {"python.details": {"contacts": [{"email": "alex@moreati.org.uk", "name": "Alex Willmer", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/moreati/b-prefix-all-the-doctests"}}}, "generator": "bdist_wheel (0.24.0)", "keywords": ["doctest", "bytes", "unicode", "bytestring", "prefix", "literal", "string", "str"], "license": "Apache Software License 2.0", "metadata_version": "2.0", "name": "pretext", "summary": "Use doctest with bytes, str & unicode on Python 2.x and 3.x", "version": "0.0.2"}PK¨š8G§ÓãË// pretext-0.0.2.dist-info/pbr.json{"is_release": false, "git_version": "884d436"}PK¨š8G(>> textfunc() u'I return a textual (unicode) string' >>> bytesfunc() b'I return a byte (binary) string' On Python 3.x the first test case will fail, because doctest will compare ``repr(textfunc())`` which will not include a ``u''`` prefix. On Python 2.x the second test will fail, because ``repr(bytesfunc())`` will not 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`` PK¨š8GùzúÈŠŠpretext-0.0.2.dist-info/RECORDpretext.py,sha256=YFN_xc5MuJDOiksdAYem16nLf3Ofj2SH_K9ePMx8RSA,3836 pretext-0.0.2.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 pretext-0.0.2.dist-info/RECORD,, pretext-0.0.2.dist-info/METADATA,sha256=b72FsV7QclcRmPDjH9_Rs8XN6RUMrOITSw9jyFPb_ao,3597 pretext-0.0.2.dist-info/top_level.txt,sha256=AdEydxGeSzbdOGBTpuaF1mBJhaZAUr1Cq-dMZGW9p80,8 pretext-0.0.2.dist-info/DESCRIPTION.rst,sha256=3kzow7vSqRd0GMeuhypTLWsyzpq4aBuHnMavA5oQzts,2405 pretext-0.0.2.dist-info/metadata.json,sha256=m_-V6ITQEzKvtxCzePofR-bgwNBN6WCA4gdF60bccho,1279 pretext-0.0.2.dist-info/pbr.json,sha256=0h4gR6Hpqcqe--WNXJfcrwnnThMXH3oesL99uWXymTk,47 PKu‹8GfÄnüü pretext.pyPK¨š8GÑçâe e '$pretext-0.0.2.dist-info/DESCRIPTION.rstPK¨š8G*D¦ÿÿ%Îpretext-0.0.2.dist-info/metadata.jsonPK¨š8G§ÓãË// pretext-0.0.2.dist-info/pbr.jsonPK¨š8G(