pprintpp-0.4.0/0000755000076600001200000000000013316030611014152 5ustar woleveradmin00000000000000pprintpp-0.4.0/.gitignore0000644000076600001200000000023212660246510016147 0ustar woleveradmin00000000000000*.class *.o *.pyc *.sqlite3 *.sw[op] *~ .DS_Store bin-debug/* bin-release/* bin/* tags *.beam *.dump env/ .env/ *egg-info* misc/ dist/ Icon? build/ .tox/ pprintpp-0.4.0/.travis.yml0000644000076600001200000000021613316030601016261 0ustar woleveradmin00000000000000language: python python: - 2.7 - 3.6 - 3.5 - 3.4 - pypy install: - pip install -r test-requires.txt script: - python test.py pprintpp-0.4.0/CHANGELOG.txt0000644000076600001200000000252013316030601016200 0ustar woleveradmin000000000000000.4.0 * Add IPython plugin (thanks @roee30; https://github.com/wolever/pprintpp/pull/20) 0.3.0 * Add support for subclasses of built-in collections and collections module (ex, if no __repr__ is defined, a subclass of dict will be repr'd ``MyDictSubclass({...})``). * Add support for ``collections.OrderedDict`` * Add ``quiet=True`` flag to monkeypatch * Fixed crash on non-hashable instancemethods (https://github.com/wolever/pprintpp/issues/18) 0.2.3 (2015-06-01) * Oops, fixed setup.py so the module is actually push'd to PyPI (thanks @OldhamMade). * pprintpp is now a package, not a single .py file. 0.2.2 (2015-05-14) * Add Python 2.6 compatibility (pprintpp will work without the `collections` module; thanks @ulope) * Fix set/frozenset bug on PyPy * Fix sorting of heterogeneous containers on Py3 0.2.1 (2014-04-22) * Some minor bugfixes 0.2.0 (2014-04-22) * Add Python 3 support 0.1.3 (2014-04-03) * Fix bug in printing Unicode strings when locale is imported * Improve Unicode printing so a wider range of Unicode characters will be printed directly. 0.1.2 (2014-03-30) * Add support for collections.Counter and collections.defaultdict 0.1.1 (2014-03-30) * Proper numpy support, fix sorting bug 0.1.0 (2014-03-30) * Initial release. pprintpp-0.4.0/LICENSE.txt0000644000076600001200000000316112316062416016005 0ustar woleveradmin00000000000000tl;dr: all code code is licensed under simplified BSD, unless stated otherwise. Unless stated otherwise in the source files, all code is copyright 2010 David Wolever . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of David Wolever. pprintpp-0.4.0/MANIFEST.in0000644000076600001200000000002312316062416015712 0ustar woleveradmin00000000000000include README.rst pprintpp-0.4.0/PKG-INFO0000644000076600001200000002316013316030611015251 0ustar woleveradmin00000000000000Metadata-Version: 1.1 Name: pprintpp Version: 0.4.0 Summary: A drop-in replacement for pprint that's actually pretty Home-page: https://github.com/wolever/pprintpp Author: David Wolever Author-email: david@wolever.net License: BSD Description: ``pprint++``: a drop-in replacement for ``pprint`` that's actually pretty ========================================================================= .. image:: https://travis-ci.org/wolever/pprintpp.svg?branch=master :target: https://travis-ci.org/wolever/pprintpp Now with Python 3 support! Installation ------------ ``pprint++`` can be installed with Python 2 or Python 3 using ``pip`` or ``easy_install``:: $ pip install pprintpp - OR - $ easy_install pprintpp Usage ----- ``pprint++`` can be used in three ways: 1. Through the separate ``pp`` package:: $ pip install pp-ez $ python ... >>> import pp >>> pp(["Hello", "world"]) ["Hello", "world"] For more, see https://pypi.python.org/pypi/pp-ez 2. As a command-line program, which will read Python literals from standard in and pretty-print them:: $ echo "{'hello': 'world'}" | pypprint {'hello': 'world'} 3. As an `ipython `_ extension:: In [1]: %load_ext pprintpp This will use pprintpp for ipython's output. To load this extension when ipython starts, put the previous line in your `startup file `_. You can change the indentation level like so:: In [2]: %config PPrintPP.indentation = 4 4. To monkeypatch ``pprint``:: >>> import pprintpp >>> pprintpp.monkeypatch() >>> import pprint >>> pprint.pprint(...) Note: the original ``pprint`` module will be available with ``import pprint_original``. Additionally, a warning will be issued if ``pprint`` has already been imported. This can be suppressed by passing ``quiet=True``. 5. And, if you *really* want, it can even be imported as a regular module: >>> import pprintpp >>> pprintpp.pprint(...) Usability Protips ----------------- ``pp`` ~~~~~~ For bonus code aesthetics, ``pprintpp.pprint`` can be imported as ``pp``: .. code:: pycon >>> from pprintpp import pprint as pp >>> pp(...) And if that is just too many letters, the ``pp-ez`` package can be installed from PyPI, ensuring that pretty-printing is never more than an ``import pp`` away:: $ pip install pp-ez $ python ... >>> import pp >>> pp(["Hello", "world"]) ["Hello", "world"] For more, see https://pypi.python.org/pypi/pp-ez Why is it prettier? ------------------- Unlike ``pprint``, ``pprint++`` strives to emit a readable, largely PEP8-compliant, representation of its input. It also has explicit support for: the ``collections`` module (``defaultdict`` and ``Counter``) and ``numpy`` arrays: .. code:: pycon >>> import numpy as np >>> from collections import defaultdict, Counter >>> pprint([np.array([[1,2],[3,4]]), defaultdict(int, {"foo": 1}), Counter("aaabbc")]) [ array([[1, 2], [3, 4]]), defaultdict(, {'foo': 1}), Counter({'a': 3, 'b': 2, 'c': 1}), ] Unicode characters, when possible, will be printed un-escaped. This is done by checking both the output stream's encoding (defaulting to ``utf-8``) and the character's Unicode category. An effort is made to print only characters which will be visually unambiguous: letters and numbers will be printed un-escaped, spaces, combining characters, and control characters will be escaped: .. code:: pycon >>> unistr = u"\xe9e\u0301" >>> print unistr éé >>> pprint(unistr) u'ée\u0301' The output stream's encoding will be considered too: .. code:: pycon >>> import io >>> stream = io.BytesIO() >>> stream.encoding = "ascii" >>> pprint(unistr, stream=stream) >>> print stream.getvalue() u'\xe9e\u0301' Subclassess of built-in collection types which don't define a new ``__repr__`` will have their class name explicitly added to their repr. For example: .. code:: pycon >>> class MyList(list): ... pass ... >>> pprint(MyList()) MyList() >>> pprint(MyList([1, 2, 3])) MyList([1, 2, 3]) Note that, as you might expect, custom ``__repr__`` methods will be respected: .. code:: pycon >>> class MyList(list): ... def __repr__(self): ... return "custom repr!" ... >>> pprint(MyList()) custom repr! **Note**: ``pprint++`` is still under development, so the format *will* change and improve over time. Example ~~~~~~~ With ``printpp``: .. code:: pycon >>> import pprintpp >>> pprintpp.pprint(["Hello", np.array([[1,2],[3,4]])]) [ 'Hello', array([[1, 2], [3, 4]]), ] >>> pprintpp.pprint(tweet) { 'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': { 'hashtags': [], 'urls': [ { 'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg', }, ], 'user_mentions': [], }, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': { 'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2', }, } Without ``printpp``:: >>> import pprint >>> import numpy as np >>> pprint.pprint(["Hello", np.array([[1,2],[3,4]])]) ['Hello', array([[1, 2], [3, 4]])] >>> tweet = {'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': {'hashtags': [], 'urls': [{'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg'}], 'user_mentions': []}, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': {'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2'}} >>> pprint.pprint(tweet) {'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': {'hashtags': [], 'urls': [{'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg'}], 'user_mentions': []}, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': {'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2'}} Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development Classifier: Topic :: Utilities pprintpp-0.4.0/pp/0000755000076600001200000000000013316030611014571 5ustar woleveradmin00000000000000pprintpp-0.4.0/pp/pp.py0000644000076600001200000000213012325757752015603 0ustar woleveradmin00000000000000import sys import types class pp_magic_module(types.ModuleType): original_module = sys.modules[__name__] __file__ = original_module.__file__ __package__ = original_module.__package__ def __init__(self): types.ModuleType.__init__(self, __name__) try: import pprintpp as pprint_mod except ImportError: import pprint as pprint_mod self._set_mod(pprint_mod) def _set_mod(self, mod): self.pprint_mod = mod type_dict = type(self).__dict__ for name in dir(mod): if name in type_dict or name.startswith("_"): continue setattr(self, name, getattr(mod, name)) self.__doc__ = mod.__doc__ def __call__(self, *args, **kwargs): return self.pprint(*args, **kwargs) def fmt(self, *args, **kwargs): return self.pformat(*args, **kwargs) def __repr__(self): return "" %( self.__name__, self.pprint_mod.__name__, ) sys.modules[__name__] = pp_magic_module() pprintpp-0.4.0/pp/README.rst0000644000076600001200000000173212660246510016273 0ustar woleveradmin00000000000000``pp``: an alias for pprint++ ============================= ``pp`` can be installed with Python 2 or Python 3 using ``pip`` or ``easy_install``:: $ pip install pprintpp pp-ez - OR - $ easy_install pprintpp pp-ez The ``pp`` package is just an alias for the ``pprintpp`` package (and falls back to the ``pprint`` package if ``pprintpp`` isn't available), plus a bit of magic so it can be called directly:: >>> import pp >>> pp(["Hello", "world"]) ["Hello", "world"] >>> pp.fmt([1, 2, 3]) '[1, 2, 3]' >>> pp.pprint([1, 2, 3]) [1, 2, 3] >>> pp.pformat([1, 2, 3]) '[1, 2, 3]' By default, ``pp`` tries to use the ``pprintpp`` package, but if that is not available it will fall back to using ``pprint``:: >>> import pp >>> pp >>> pp.pprint_mod See also: ``pprint++``: https://pypi.python.org/pypi/pprintpp pprintpp-0.4.0/pp/setup.cfg0000644000076600001200000000003412660246510016417 0ustar woleveradmin00000000000000[bdist_wheel] universal = 1 pprintpp-0.4.0/pp/setup.py0000644000076600001200000000211712660246510016314 0ustar woleveradmin00000000000000#!/usr/bin/env python import os import sys from setuptools import setup os.chdir(os.path.dirname(sys.argv[0]) or ".") try: long_description = open("README.rst", "U").read() except IOError: long_description = "See https://github.com/wolever/pprintpp" setup( name="pp-ez", version="0.2.0", url="https://github.com/wolever/pprintpp", author="David Wolever", author_email="david@wolever.net", description="A short alias for the pprintpp or pprint module", long_description=long_description, py_modules=["pp"], install_requires=[], license="BSD", classifiers=[ x.strip() for x in """ Development Status :: 3 - Alpha Environment :: Console Intended Audience :: Developers License :: OSI Approved :: BSD License Natural Language :: English Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 3 Topic :: Software Development Topic :: Utilities """.split("\n") if x.strip() ], ) pprintpp-0.4.0/pprintpp/0000755000076600001200000000000013316030611016026 5ustar woleveradmin00000000000000pprintpp-0.4.0/pprintpp/__init__.py0000644000076600001200000004625713316030601020154 0ustar woleveradmin00000000000000from __future__ import print_function import io import os import ast import sys import warnings import unicodedata __all__ = [ "pprint", "pformat", "isreadable", "isrecursive", "saferepr", "PrettyPrinter", ] # # Py2/Py3 compatibility stuff # try: from collections import OrderedDict, defaultdict, Counter _test_has_collections = True except ImportError: # Python 2.6 doesn't have collections class dummy_class(object): __repr__ = object() OrderedDict = defaultdict = Counter = dummy_class _test_has_collections = False PY3 = sys.version_info >= (3, 0, 0) BytesType = bytes TextType = str if PY3 else unicode u_prefix = '' if PY3 else 'u' if PY3: # Import builins explicitly to keep Py2 static analyzers happy import builtins chr_to_ascii = lambda x: builtins.ascii(x)[1:-1] unichr = chr from .safesort import safesort _iteritems = lambda x: x.items() else: chr_to_ascii = lambda x: repr(x)[2:-1] safesort = sorted _iteritems = lambda x: x.iteritems() def _sorted_py2(iterable): with warnings.catch_warnings(): if getattr(sys, "py3kwarning", False): warnings.filterwarnings("ignore", "comparing unequal types " "not supported", DeprecationWarning) return sorted(iterable) def _sorted_py3(iterable): try: return sorted(iterable) except TypeError: return safesort(iterable) _sorted = PY3 and _sorted_py3 or _sorted_py3 # # End compatibility stuff # class TextIO(io.TextIOWrapper): def __init__(self, encoding=None): io.TextIOWrapper.__init__(self, io.BytesIO(), encoding=encoding) def getvalue(self): self.flush() return self.buffer.getvalue().decode(self.encoding) # pprintpp will make an attempt to print as many Unicode characters as is # safely possible. It will use the character category along with this table to # determine whether or not it is safe to print a character. In this context, # "safety" is defined as "the character will appear visually distinct" - # combining characters, spaces, and other things which could be visually # ambiguous are repr'd, others will be printed. I made this table mostly by # hand, mostly guessing, so please file bugs. # Source: http://www.unicode.org/reports/tr44/#GC_Values_Table unicode_printable_categories = { "Lu": 1, # Uppercase_Letter an uppercase letter "Ll": 1, # Lowercase_Letter a lowercase letter "Lt": 1, # Titlecase_Letter a digraphic character, with first part uppercase "LC": 1, # Cased_Letter Lu | Ll | Lt "Lm": 0, # Modifier_Letter a modifier letter "Lo": 1, # Other_Letter other letters, including syllables and ideographs "L": 1, # Letter Lu | Ll | Lt | Lm | Lo "Mn": 0, # Nonspacing_Mark a nonspacing combining mark (zero advance width) "Mc": 0, # Spacing_Mark a spacing combining mark (positive advance width) "Me": 0, # Enclosing_Mark an enclosing combining mark "M": 1, # Mark Mn | Mc | Me "Nd": 1, # Decimal_Number a decimal digit "Nl": 1, # Letter_Number a letterlike numeric character "No": 1, # Other_Number a numeric character of other type "N": 1, # Number Nd | Nl | No "Pc": 1, # Connector_Punctuation a connecting punctuation mark, like a tie "Pd": 1, # Dash_Punctuation a dash or hyphen punctuation mark "Ps": 1, # Open_Punctuation an opening punctuation mark (of a pair) "Pe": 1, # Close_Punctuation a closing punctuation mark (of a pair) "Pi": 1, # Initial_Punctuation an initial quotation mark "Pf": 1, # Final_Punctuation a final quotation mark "Po": 1, # Other_Punctuation a punctuation mark of other type "P": 1, # Punctuation Pc | Pd | Ps | Pe | Pi | Pf | Po "Sm": 1, # Math_Symbol a symbol of mathematical use "Sc": 1, # Currency_Symbol a currency sign "Sk": 1, # Modifier_Symbol a non-letterlike modifier symbol "So": 1, # Other_Symbol a symbol of other type "S": 1, # Symbol Sm | Sc | Sk | So "Zs": 0, # Space_Separator a space character (of various non-zero widths) "Zl": 0, # Line_Separator U+2028 LINE SEPARATOR only "Zp": 0, # Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only "Z": 1, # Separator Zs | Zl | Zp "Cc": 0, # Control a C0 or C1 control code "Cf": 0, # Format a format control character "Cs": 0, # Surrogate a surrogate code point "Co": 0, # Private_Use a private-use character "Cn": 0, # Unassigned a reserved unassigned code point or a noncharacter "C": 0, # Other Cc | Cf | Cs | Co | Cn } ascii_table = dict( (unichr(i), chr_to_ascii(unichr(i))) for i in range(255) ) def pprint(object, stream=None, indent=4, width=80, depth=None): """Pretty-print a Python object to a stream [default is sys.stdout].""" printer = PrettyPrinter( stream=stream, indent=indent, width=width, depth=depth) printer.pprint(object) def pformat(object, indent=4, width=80, depth=None): """Format a Python object into a pretty-printed representation.""" return PrettyPrinter(indent=indent, width=width, depth=depth).pformat(object) def saferepr(object): """Version of repr() which can handle recursive data structures.""" return PrettyPrinter().pformat(object) def isreadable(object): """Determine if saferepr(object) is readable by eval().""" return PrettyPrinter().isreadable(object) def isrecursive(object): """Determine if object requires a recursive representation.""" return PrettyPrinter().isrecursive(object) def console(argv=None): if argv is None: argv = sys.argv if len(argv) != 1: name = argv[0] if name.startswith("/"): name = os.path.basename(name) print("Usage: %s" %(argv[0], )) print() print("Pipe Python literals into %s to pretty-print them" %(argv[0], )) return 1 obj = ast.literal_eval(sys.stdin.read().strip()) pprint(obj) return 0 def monkeypatch(mod=None, quiet=False): if "pprint" in sys.modules and not quiet: warnings.warn("'pprint' has already been imported; monkeypatching " "won't work everywhere.") import pprint sys.modules["pprint_original"] = pprint sys.modules["pprint"] = mod or sys.modules["pprintpp"] class PPrintSharedState(object): recursive = False readable = True cur_line_length = 0 def clone(self): new = type(self)() new.__dict__.update(self.__dict__) return new class PPrintState(object): indent = 4 level = 0 max_width = 80 max_depth = None stream = None context = None write_constrain = None class WriteConstrained(Exception): pass def __init__(self, **attrs): self.__dict__.update(attrs) self.s = PPrintSharedState() def assert_sanity(self): assert self.indent >= 0, "indent must be >= 0" assert self.max_depth is None or self.max_depth > 0, "depth must be > 0" assert self.max_width, "width must be != 0" def replace(self, **attrs): new_state = type(self)() new_state.__dict__.update(self.__dict__) new_state.__dict__.update(attrs) new_state.context = dict(new_state.context) new_state.s = self.s return new_state def clone(self, clone_shared=False): new = self.replace() if clone_shared: new.s = self.s.clone() return new def write(self, data): if self.write_constrain is not None: self.write_constrain -= len(data) if self.write_constrain < 0: raise self.WriteConstrained if isinstance(data, BytesType): data = data.decode("latin1") self.stream.write(data) nl_idx = data.rfind("\n") if nl_idx < 0: self.s.cur_line_length += len(data) else: self.s.cur_line_length = len(data) - (nl_idx + 1) def get_indent_string(self): return (self.level * self.indent) * " " def _mk_open_close_empty_dict(type_tuples): """ Generates a dictionary mapping either ``cls.__repr__`` xor ``cls`` to a tuple of ``(container_type, repr_open, repr_close, repr_empty)`` (see ``PrettyPrinter._open_close_empty`` for examples). Using either ``cls.__repr__`` xor ``cls`` is important because some types (specifically, ``set`` and ``frozenset`` on PyPy) share a ``__repr__``. When we are determining how to repr an object, the type is first checked, then if it's not found ``type.__repr__`` is checked. Note that ``__repr__`` is used so that trivial subclasses will behave sensibly. """ res = {} for (cls, open_close_empty) in type_tuples: if cls.__repr__ in res: res[cls] = (cls, ) + open_close_empty else: res[cls.__repr__] = (cls, ) + open_close_empty return res class PrettyPrinter(object): def __init__(self, indent=4, width=80, depth=None, stream=None): """Handle pretty printing operations onto a stream using a set of configured parameters. indent Number of spaces to indent for each level of nesting. width Attempted maximum number of columns in the output. depth The maximum depth to print out nested structures. stream The desired output stream. If omitted (or false), the standard output stream available at construction will be used. """ self.get_default_state = lambda: PPrintState( indent=int(indent), max_width=int(width), stream=stream or sys.stdout, context={}, ) self.get_default_state().assert_sanity() def pprint(self, object, state=None): state = state or self.get_default_state() self._format(object, state) state.write("\n") def pformat(self, object, state=None): sio = TextIO() state = state or self.get_default_state() state = state.replace(stream=sio) self._format(object, state) return sio.getvalue() def isrecursive(self, object): state = self.get_default_state() self._format(object, state) return state.s.recursive def isreadable(self, object): state = self.get_default_state() self._format(object, state) return state.s.readable and not state.s.recursive _open_close_empty = _mk_open_close_empty_dict([ (dict, ("dict", "{", "}", "{}")), (list, ("list", "[", "]", "[]")), (tuple, ("tuple", "(", ")", "()")), (set, ("set", "__PP_TYPE__([", "])", "__PP_TYPE__()")), (frozenset, ("set", "__PP_TYPE__([", "])", "__PP_TYPE__()")), (Counter, ("dict", "__PP_TYPE__({", "})", "__PP_TYPE__()")), (defaultdict, ("dict", None, "})", None)), (OrderedDict, ("odict", "__PP_TYPE__([", "])", "__PP_TYPE__()")), ]) def _format_nested_objects(self, object, state, typeish=None): objid = id(object) state.level += 1 state.context[objid] = 1 try: # First, try to fit everything on one line. For simplicity, assume # that it takes three characters to close the object (ex, `]),`) oneline_state = state.clone(clone_shared=True) oneline_state.stream = TextIO() oneline_state.write_constrain = ( state.max_width - state.s.cur_line_length - 3 ) try: self._write_nested_real(object, oneline_state, typeish, oneline=True) oneline_value = oneline_state.stream.getvalue() if "\n" in oneline_value: oneline_value = None except oneline_state.WriteConstrained: oneline_value = None if oneline_value is not None: state.write(oneline_value) return state.write("\n" + state.get_indent_string()) self._write_nested_real(object, state, typeish) finally: state.level -= 1 state.write(state.get_indent_string()) def _write_nested_real(self, object, state, typeish, oneline=False): indent_str = state.get_indent_string() first = True joiner = oneline and ", " or ",\n" + indent_str if typeish == "dict": for k, v in _sorted(object.items()): if first: first = False else: state.write(joiner) self._format(k, state) state.write(": ") self._format(v, state) elif typeish == "odict": for k, v in _iteritems(object): if first: first = False else: state.write(joiner) state.write("(") self._format(k, state) state.write(", ") self._format(v, state) state.write(")") else: if typeish == "set": object = _sorted(object) for o in object: if first: first = False else: state.write(joiner) self._format(o, state) if oneline and typeish == "tuple" and len(object) == 1: state.write(", ") elif not oneline: state.write(",\n") def _format(self, object, state): write = state.write if state.max_depth and state.level >= state.max_depth: write("...") return state = state.clone() objid = id(object) if objid in state.context: write(self._recursion(object, state)) return typ = type(object) r = typ.__repr__ # Note: see comments on _mk_open_close_empty_dict for the rational # behind looking up based first on type then on __repr__. try: opener_closer_empty = ( self._open_close_empty.get(typ) or self._open_close_empty.get(r) ) except TypeError: # This will happen if the type or the __repr__ is unhashable. # See: https://github.com/wolever/pprintpp/issues/18 opener_closer_empty = None if opener_closer_empty is not None: orig_type, typeish, opener, closer, empty = opener_closer_empty if typ != orig_type: if opener is not None and "__PP_TYPE__" not in opener: opener = "__PP_TYPE__(" + opener closer = closer + ")" if empty is not None and "__PP_TYPE__" not in empty: empty = "__PP_TYPE__(%s)" %(empty, ) if r == defaultdict.__repr__: factory_repr = object.default_factory opener = "__PP_TYPE__(%r, {" %(factory_repr, ) empty = opener + closer length = len(object) if length == 0: if "__PP_TYPE__" in empty: empty = empty.replace("__PP_TYPE__", typ.__name__) write(empty) return if "__PP_TYPE__" in opener: opener = opener.replace("__PP_TYPE__", typ.__name__) write(opener) self._format_nested_objects(object, state, typeish=typeish) write(closer) return if r == BytesType.__repr__: write(repr(object)) return if r == TextType.__repr__: if "'" in object and '"' not in object: quote = '"' quotes = {'"': '\\"'} else: quote = "'" quotes = {"'": "\\'"} qget = quotes.get ascii_table_get = ascii_table.get unicat_get = unicodedata.category write(u_prefix + quote) for char in object: if ord(char) > 0x7F: cat = unicat_get(char) if unicode_printable_categories.get(cat): try: write(char) continue except UnicodeEncodeError: pass write( qget(char) or ascii_table_get(char) or chr_to_ascii(char) ) write(quote) return orepr = repr(object) orepr = orepr.replace("\n", "\n" + state.get_indent_string()) state.s.readable = ( state.s.readable and not orepr.startswith("<") ) write(orepr) return def _repr(self, object, context, level): repr, readable, recursive = self.format(object, context.copy(), self._depth, level) if not readable: self._readable = False if recursive: self._recursive = True return repr def format(self, object, context, maxlevels, level): """Format object for a specific context, returning a string and flags indicating whether the representation is 'readable' and whether the object represents a recursive construct. """ state = self.get_default_state() result = self.pformat(object, state=state) return result, state.s.readable, state.s.recursive def _recursion(self, object, state): state.s.recursive = True return ("" % (type(object).__name__, id(object))) if __name__ == "__main__": try: import numpy as np except ImportError: class np(object): @staticmethod def array(o): return o somelist = [1,2,3] recursive = [] recursive.extend([recursive, recursive, recursive]) pprint({ "a": {"a": "b"}, "b": [somelist, somelist], "c": [ (1, ), (1,2,3), ], "ordereddict": OrderedDict([ (1, 1), (10, 10), (2, 2), (11, 11) ]), "counter": [ Counter(), Counter("asdfasdfasdf"), ], "dd": [ defaultdict(int, {}), defaultdict(int, {"foo": 42}), ], "frozenset": frozenset("abc"), "np": [ "hello", #np.array([[1,2],[3,4]]), "world", ], u"u": ["a", u"\u1234", "b"], "recursive": recursive, "z": { "very very very long key stuff 1234": { "much value": "very nest! " * 10, u"unicode": u"4U!'\"", }, "aldksfj alskfj askfjas fkjasdlkf jasdlkf ajslfjas": ["asdf"] * 10, }, }) pprint(u"\xe9e\u0301") uni_safe = u"\xe9 \u6f02 \u0e4f \u2661" uni_unsafe = u"\u200a \u0301 \n" unistr = uni_safe + " --- " + uni_unsafe sys.modules.pop("locale", None) pprint(unistr) stream = TextIO(encoding="ascii") pprint(unistr, stream=stream) print(stream.getvalue()) def load_ipython_extension(ipython): from .ipython import load_ipython_extension return load_ipython_extension(ipython) def unload_ipython_extension(ipython): from .ipython import unload_ipython_extension return unload_ipython_extension(ipython) pprintpp-0.4.0/pprintpp/ipython.py0000644000076600001200000000326113316030601020073 0ustar woleveradmin00000000000000""" An ipython extension that monkey-patches it to use pprintpp. This solution was adapted from an answer to this Stack Overflow question: https://stackoverflow.com/questions/35375099 asked by: https://stackoverflow.com/users/71522/david-wolever and answered by: https://stackoverflow.com/users/1530134/kupiakos """ import IPython from traitlets.config import Configurable from traitlets import Int from . import pformat original_representation = IPython.lib.pretty.RepresentationPrinter DEFAULT_INDENTATION = 2 def load_ipython_extension(ipython): ipython.config.PPrintPP.indentation = DEFAULT_INDENTATION IPython.lib.pretty.RepresentationPrinter = PPrintPPRepresentation pprintpp = PPrintPP(parent=ipython, config=ipython.config) ipython.configurables.append(pprintpp) def unload_ipython_extension(ipython): IPython.lib.pretty.RepresentationPrinter = original_representation try: pprintpp = [ configurable for configurable in ipython.configurables if isinstance(configurable, PPrintPP) ][0] except IndexError: print('Could not unload {}'.format(__name__)) else: ipython.configurables.remove(pprintpp) class PPrintPPRepresentation(object): """ A pretty printer that uses pprintpp """ def __init__(self, stream, *args, **kwargs): self.stream = stream self.config = IPython.get_ipython().config def pretty(self, obj): indentation = self.config.PPrintPP.indentation self.stream.write(pformat(obj, indent=indentation)) def flush(self): pass class PPrintPP(Configurable): """ PPrintPP configuration """ indentation = Int(config=True) pprintpp-0.4.0/pprintpp/safesort.py0000644000076600001200000000413112660246510020235 0ustar woleveradmin00000000000000import sys import textwrap import functools PY3 = (sys.version_info >= (3, 0, 0)) def memoized_property(f): @functools.wraps(f) def memoized_property_helper(self): val = f(self) self.__dict__[f.__name__] = val return val return property(memoized_property_helper) def _build_safe_cmp_func(name, cmp, prefix=""): code = textwrap.dedent("""\ def {name}(self, other): try: return {prefix}(self.obj {cmp} other.obj) except TypeError: pass try: return {prefix}(self.safeobj {cmp} other.safeobj) except TypeError: pass return {prefix}(self.verysafeobj {cmp} other.verysafeobj) """).format(name=name, cmp=cmp, prefix=prefix) gs = ls = {} exec(code, gs, ls) return gs[name] class SafelySortable(object): def __init__(self, obj, key=None): self.obj = ( obj if key is None else key(obj) ) @memoized_property def prefix(self): if PY3: return tuple(t.__name__ for t in type(self.obj).__mro__) return type(self.obj).__mro__ @memoized_property def safeobj(self): return (self.prefix, self.obj) @memoized_property def verysafeobj(self): return (self.prefix, id(self.obj)) def __hash__(self): # TODO: is this a good idea? Maybe this should not exist? try: return hash(self.obj) except TypeError: pass return 1 __lt__ = _build_safe_cmp_func("__lt__", "<") __gt__ = _build_safe_cmp_func("__gt__", ">") __le__ = _build_safe_cmp_func("__le__", "<=") __ge__ = _build_safe_cmp_func("__ge__", ">=") __eq__ = _build_safe_cmp_func("__eq__", "==") __ne__ = _build_safe_cmp_func("__ne__", "!=") __cmp__ = _build_safe_cmp_func("__cmp__", ",", "cmp") def safesort(input, key=None, reverse=False): """ Safely sort heterogeneous collections. """ # TODO: support cmp= on Py 2.x? return sorted(input, key=lambda o: SafelySortable(o, key=key), reverse=reverse) pprintpp-0.4.0/pprintpp.egg-info/0000755000076600001200000000000013316030611017520 5ustar woleveradmin00000000000000pprintpp-0.4.0/pprintpp.egg-info/dependency_links.txt0000644000076600001200000000000113316030610023565 0ustar woleveradmin00000000000000 pprintpp-0.4.0/pprintpp.egg-info/entry_points.txt0000644000076600001200000000005713316030610023017 0ustar woleveradmin00000000000000[console_scripts] pypprint = pprintpp:console pprintpp-0.4.0/pprintpp.egg-info/pbr.json0000644000076600001200000000005713316030610021177 0ustar woleveradmin00000000000000{"is_release": false, "git_version": "5464d2a"}pprintpp-0.4.0/pprintpp.egg-info/PKG-INFO0000644000076600001200000002316013316030610020616 0ustar woleveradmin00000000000000Metadata-Version: 1.1 Name: pprintpp Version: 0.4.0 Summary: A drop-in replacement for pprint that's actually pretty Home-page: https://github.com/wolever/pprintpp Author: David Wolever Author-email: david@wolever.net License: BSD Description: ``pprint++``: a drop-in replacement for ``pprint`` that's actually pretty ========================================================================= .. image:: https://travis-ci.org/wolever/pprintpp.svg?branch=master :target: https://travis-ci.org/wolever/pprintpp Now with Python 3 support! Installation ------------ ``pprint++`` can be installed with Python 2 or Python 3 using ``pip`` or ``easy_install``:: $ pip install pprintpp - OR - $ easy_install pprintpp Usage ----- ``pprint++`` can be used in three ways: 1. Through the separate ``pp`` package:: $ pip install pp-ez $ python ... >>> import pp >>> pp(["Hello", "world"]) ["Hello", "world"] For more, see https://pypi.python.org/pypi/pp-ez 2. As a command-line program, which will read Python literals from standard in and pretty-print them:: $ echo "{'hello': 'world'}" | pypprint {'hello': 'world'} 3. As an `ipython `_ extension:: In [1]: %load_ext pprintpp This will use pprintpp for ipython's output. To load this extension when ipython starts, put the previous line in your `startup file `_. You can change the indentation level like so:: In [2]: %config PPrintPP.indentation = 4 4. To monkeypatch ``pprint``:: >>> import pprintpp >>> pprintpp.monkeypatch() >>> import pprint >>> pprint.pprint(...) Note: the original ``pprint`` module will be available with ``import pprint_original``. Additionally, a warning will be issued if ``pprint`` has already been imported. This can be suppressed by passing ``quiet=True``. 5. And, if you *really* want, it can even be imported as a regular module: >>> import pprintpp >>> pprintpp.pprint(...) Usability Protips ----------------- ``pp`` ~~~~~~ For bonus code aesthetics, ``pprintpp.pprint`` can be imported as ``pp``: .. code:: pycon >>> from pprintpp import pprint as pp >>> pp(...) And if that is just too many letters, the ``pp-ez`` package can be installed from PyPI, ensuring that pretty-printing is never more than an ``import pp`` away:: $ pip install pp-ez $ python ... >>> import pp >>> pp(["Hello", "world"]) ["Hello", "world"] For more, see https://pypi.python.org/pypi/pp-ez Why is it prettier? ------------------- Unlike ``pprint``, ``pprint++`` strives to emit a readable, largely PEP8-compliant, representation of its input. It also has explicit support for: the ``collections`` module (``defaultdict`` and ``Counter``) and ``numpy`` arrays: .. code:: pycon >>> import numpy as np >>> from collections import defaultdict, Counter >>> pprint([np.array([[1,2],[3,4]]), defaultdict(int, {"foo": 1}), Counter("aaabbc")]) [ array([[1, 2], [3, 4]]), defaultdict(, {'foo': 1}), Counter({'a': 3, 'b': 2, 'c': 1}), ] Unicode characters, when possible, will be printed un-escaped. This is done by checking both the output stream's encoding (defaulting to ``utf-8``) and the character's Unicode category. An effort is made to print only characters which will be visually unambiguous: letters and numbers will be printed un-escaped, spaces, combining characters, and control characters will be escaped: .. code:: pycon >>> unistr = u"\xe9e\u0301" >>> print unistr éé >>> pprint(unistr) u'ée\u0301' The output stream's encoding will be considered too: .. code:: pycon >>> import io >>> stream = io.BytesIO() >>> stream.encoding = "ascii" >>> pprint(unistr, stream=stream) >>> print stream.getvalue() u'\xe9e\u0301' Subclassess of built-in collection types which don't define a new ``__repr__`` will have their class name explicitly added to their repr. For example: .. code:: pycon >>> class MyList(list): ... pass ... >>> pprint(MyList()) MyList() >>> pprint(MyList([1, 2, 3])) MyList([1, 2, 3]) Note that, as you might expect, custom ``__repr__`` methods will be respected: .. code:: pycon >>> class MyList(list): ... def __repr__(self): ... return "custom repr!" ... >>> pprint(MyList()) custom repr! **Note**: ``pprint++`` is still under development, so the format *will* change and improve over time. Example ~~~~~~~ With ``printpp``: .. code:: pycon >>> import pprintpp >>> pprintpp.pprint(["Hello", np.array([[1,2],[3,4]])]) [ 'Hello', array([[1, 2], [3, 4]]), ] >>> pprintpp.pprint(tweet) { 'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': { 'hashtags': [], 'urls': [ { 'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg', }, ], 'user_mentions': [], }, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': { 'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2', }, } Without ``printpp``:: >>> import pprint >>> import numpy as np >>> pprint.pprint(["Hello", np.array([[1,2],[3,4]])]) ['Hello', array([[1, 2], [3, 4]])] >>> tweet = {'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': {'hashtags': [], 'urls': [{'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg'}], 'user_mentions': []}, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': {'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2'}} >>> pprint.pprint(tweet) {'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': {'hashtags': [], 'urls': [{'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg'}], 'user_mentions': []}, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': {'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2'}} Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development Classifier: Topic :: Utilities pprintpp-0.4.0/pprintpp.egg-info/SOURCES.txt0000644000076600001200000000065013316030610021404 0ustar woleveradmin00000000000000.gitignore .travis.yml CHANGELOG.txt LICENSE.txt MANIFEST.in README.rst setup.cfg setup.py test-requires.txt test.py tox.ini pp/README.rst pp/pp.py pp/setup.cfg pp/setup.py pprintpp/__init__.py pprintpp/ipython.py pprintpp/safesort.py pprintpp.egg-info/PKG-INFO pprintpp.egg-info/SOURCES.txt pprintpp.egg-info/dependency_links.txt pprintpp.egg-info/entry_points.txt pprintpp.egg-info/pbr.json pprintpp.egg-info/top_level.txtpprintpp-0.4.0/pprintpp.egg-info/top_level.txt0000644000076600001200000000001113316030610022241 0ustar woleveradmin00000000000000pprintpp pprintpp-0.4.0/README.rst0000644000076600001200000001603013316030601015640 0ustar woleveradmin00000000000000``pprint++``: a drop-in replacement for ``pprint`` that's actually pretty ========================================================================= .. image:: https://travis-ci.org/wolever/pprintpp.svg?branch=master :target: https://travis-ci.org/wolever/pprintpp Now with Python 3 support! Installation ------------ ``pprint++`` can be installed with Python 2 or Python 3 using ``pip`` or ``easy_install``:: $ pip install pprintpp - OR - $ easy_install pprintpp Usage ----- ``pprint++`` can be used in three ways: 1. Through the separate ``pp`` package:: $ pip install pp-ez $ python ... >>> import pp >>> pp(["Hello", "world"]) ["Hello", "world"] For more, see https://pypi.python.org/pypi/pp-ez 2. As a command-line program, which will read Python literals from standard in and pretty-print them:: $ echo "{'hello': 'world'}" | pypprint {'hello': 'world'} 3. As an `ipython `_ extension:: In [1]: %load_ext pprintpp This will use pprintpp for ipython's output. To load this extension when ipython starts, put the previous line in your `startup file `_. You can change the indentation level like so:: In [2]: %config PPrintPP.indentation = 4 4. To monkeypatch ``pprint``:: >>> import pprintpp >>> pprintpp.monkeypatch() >>> import pprint >>> pprint.pprint(...) Note: the original ``pprint`` module will be available with ``import pprint_original``. Additionally, a warning will be issued if ``pprint`` has already been imported. This can be suppressed by passing ``quiet=True``. 5. And, if you *really* want, it can even be imported as a regular module: >>> import pprintpp >>> pprintpp.pprint(...) Usability Protips ----------------- ``pp`` ~~~~~~ For bonus code aesthetics, ``pprintpp.pprint`` can be imported as ``pp``: .. code:: pycon >>> from pprintpp import pprint as pp >>> pp(...) And if that is just too many letters, the ``pp-ez`` package can be installed from PyPI, ensuring that pretty-printing is never more than an ``import pp`` away:: $ pip install pp-ez $ python ... >>> import pp >>> pp(["Hello", "world"]) ["Hello", "world"] For more, see https://pypi.python.org/pypi/pp-ez Why is it prettier? ------------------- Unlike ``pprint``, ``pprint++`` strives to emit a readable, largely PEP8-compliant, representation of its input. It also has explicit support for: the ``collections`` module (``defaultdict`` and ``Counter``) and ``numpy`` arrays: .. code:: pycon >>> import numpy as np >>> from collections import defaultdict, Counter >>> pprint([np.array([[1,2],[3,4]]), defaultdict(int, {"foo": 1}), Counter("aaabbc")]) [ array([[1, 2], [3, 4]]), defaultdict(, {'foo': 1}), Counter({'a': 3, 'b': 2, 'c': 1}), ] Unicode characters, when possible, will be printed un-escaped. This is done by checking both the output stream's encoding (defaulting to ``utf-8``) and the character's Unicode category. An effort is made to print only characters which will be visually unambiguous: letters and numbers will be printed un-escaped, spaces, combining characters, and control characters will be escaped: .. code:: pycon >>> unistr = u"\xe9e\u0301" >>> print unistr éé >>> pprint(unistr) u'ée\u0301' The output stream's encoding will be considered too: .. code:: pycon >>> import io >>> stream = io.BytesIO() >>> stream.encoding = "ascii" >>> pprint(unistr, stream=stream) >>> print stream.getvalue() u'\xe9e\u0301' Subclassess of built-in collection types which don't define a new ``__repr__`` will have their class name explicitly added to their repr. For example: .. code:: pycon >>> class MyList(list): ... pass ... >>> pprint(MyList()) MyList() >>> pprint(MyList([1, 2, 3])) MyList([1, 2, 3]) Note that, as you might expect, custom ``__repr__`` methods will be respected: .. code:: pycon >>> class MyList(list): ... def __repr__(self): ... return "custom repr!" ... >>> pprint(MyList()) custom repr! **Note**: ``pprint++`` is still under development, so the format *will* change and improve over time. Example ~~~~~~~ With ``printpp``: .. code:: pycon >>> import pprintpp >>> pprintpp.pprint(["Hello", np.array([[1,2],[3,4]])]) [ 'Hello', array([[1, 2], [3, 4]]), ] >>> pprintpp.pprint(tweet) { 'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': { 'hashtags': [], 'urls': [ { 'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg', }, ], 'user_mentions': [], }, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': { 'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2', }, } Without ``printpp``:: >>> import pprint >>> import numpy as np >>> pprint.pprint(["Hello", np.array([[1,2],[3,4]])]) ['Hello', array([[1, 2], [3, 4]])] >>> tweet = {'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': {'hashtags': [], 'urls': [{'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg'}], 'user_mentions': []}, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': {'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2'}} >>> pprint.pprint(tweet) {'coordinates': None, 'created_at': 'Mon Jun 27 19:32:19 +0000 2011', 'entities': {'hashtags': [], 'urls': [{'display_url': 'tumblr.com/xnr37hf0yz', 'expanded_url': 'http://tumblr.com/xnr37hf0yz', 'indices': [107, 126], 'url': 'http://t.co/cCIWIwg'}], 'user_mentions': []}, 'place': None, 'source': 'Tumblr', 'truncated': False, 'user': {'contributors_enabled': True, 'default_profile': False, 'entities': {'hashtags': [], 'urls': [], 'user_mentions': []}, 'favourites_count': 20, 'id_str': '6253282', 'profile_link_color': '0094C2'}} pprintpp-0.4.0/setup.cfg0000644000076600001200000000010313316030611015765 0ustar woleveradmin00000000000000[bdist_wheel] universal = 1 [egg_info] tag_build = tag_date = 0 pprintpp-0.4.0/setup.py0000644000076600001200000000231313316030601015662 0ustar woleveradmin00000000000000#!/usr/bin/env python import os import sys from setuptools import setup os.chdir(os.path.dirname(sys.argv[0]) or ".") try: long_description = open("README.rst", "U").read() except IOError: long_description = "See https://github.com/wolever/pprintpp" setup( name="pprintpp", version="0.4.0", url="https://github.com/wolever/pprintpp", author="David Wolever", author_email="david@wolever.net", description="A drop-in replacement for pprint that's actually pretty", long_description=long_description, packages=["pprintpp"], entry_points={ 'console_scripts': [ 'pypprint = pprintpp:console', ], }, install_requires=[], license="BSD", classifiers=[ x.strip() for x in """ Development Status :: 3 - Alpha Environment :: Console Intended Audience :: Developers License :: OSI Approved :: BSD License Natural Language :: English Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 3 Topic :: Software Development Topic :: Utilities """.split("\n") if x.strip() ], ) pprintpp-0.4.0/test-requires.txt0000644000076600001200000000004612660246510017537 0ustar woleveradmin00000000000000nose==1.3.0 nose_parameterized==0.3.3 pprintpp-0.4.0/test.py0000644000076600001200000001153713017445724015527 0ustar woleveradmin00000000000000from __future__ import print_function import sys import ctypes import textwrap from nose.tools import assert_equal from nose_parameterized import parameterized, param sys.path.append("pp/") import pp import pprintpp as p from pprintpp import Counter, defaultdict, OrderedDict class PPrintppTestBase(object): def assertStdout(self, expected, trim=True): if trim: expected = textwrap.dedent(expected.rstrip().lstrip("\n")) # Assumes that nose's capture plugin is active assert_equal(sys.stdout.getvalue().rstrip(), expected) class TestPP(PPrintppTestBase): def test_pp(self): pp(["hello", "world"]) self.assertStdout("['hello', 'world']") def test_pp_pprint(self): pp.pprint("stuff") self.assertStdout("'stuff'") def test_fmt(self): print(pp.pformat("asdf")) print(pp.fmt("stuff")) self.assertStdout(""" 'asdf' 'stuff' """) def test_module_like(self): print(dir(pp)) print(repr(pp)) class MyDict(dict): pass class MyList(list): pass class MyTuple(tuple): pass class MySet(set): pass class MyFrozenSet(frozenset): pass class MyOrderedDict(p.OrderedDict): pass class MyDefaultDict(p.defaultdict): pass class MyCounter(p.Counter): pass class MyCounterWithRepr(p.Counter): def __repr__(self): return "MyCounterWithRepr('dummy')" class TestPPrint(PPrintppTestBase): uni_safe = u"\xe9 \u6f02 \u0e4f \u2661" uni_unsafe = u"\u200a \u0302 \n" slashed = lambda s: u"%s'%s'" %( p.u_prefix, s.encode("ascii", "backslashreplace").decode("ascii").replace("\n", "\\n") ) @parameterized([ param("safe", uni_safe, "%s'%s'" %(p.u_prefix, uni_safe)), param("unsafe", uni_unsafe, slashed(uni_unsafe)), param("encoding-aware", uni_safe, slashed(uni_safe), encoding="ascii"), param("high-end-chars", u"\U0002F9B2", slashed(u"\U0002F9B2"), encoding="ascii"), ]) def test_unicode(self, name, input, expected, encoding="utf-8"): stream = p.TextIO(encoding=encoding) p.pprint(input, stream=stream) assert_equal(stream.getvalue().rstrip("\n"), expected) @parameterized([ param(u"'\\'\"'"), param(u'"\'"'), param(u"'\"'"), param("frozenset(['a', 'b', 'c'])"), param("set([None, 1, 'a'])"), param("[]"), param("[1]"), param("{}"), param("{1: 1}"), param("set()"), param("set([1])"), param("frozenset()"), param("frozenset([1])"), param("()"), param("(1, )"), param("MyDict({})"), param("MyDict({1: 1})"), param("MyList([])"), param("MyList([1])"), param("MyTuple(())"), param("MyTuple((1, ))"), param("MySet()"), param("MySet([1])"), param("MyFrozenSet()"), param("MyFrozenSet([1])"), ] + ([] if not p._test_has_collections else [ param("Counter()"), param("Counter({1: 1})"), param("OrderedDict()"), param("OrderedDict([(1, 1), (5, 5), (2, 2)])"), param("MyOrderedDict()"), param("MyOrderedDict([(1, 1)])"), param("MyCounter()"), param("MyCounter({1: 1})"), param("MyCounterWithRepr('dummy')"), ])) def test_back_and_forth(self, expected): input = eval(expected) stream = p.TextIO() p.pprint(input, stream=stream) assert_equal(stream.getvalue().rstrip("\n"), expected) if p._test_has_collections: @parameterized([ param("defaultdict(%r, {})" %(int, ), defaultdict(int)), param("defaultdict(%r, {1: 1})" %(int, ), defaultdict(int, [(1, 1)])), param("MyDefaultDict(%r, {})" %(int, ), MyDefaultDict(int)), param("MyDefaultDict(%r, {1: 1})" %(int, ), MyDefaultDict(int, [(1, 1)])), ]) def test_expected_input(self, expected, input): stream = p.TextIO() p.pprint(input, stream=stream) assert_equal(stream.getvalue().rstrip("\n"), expected) def test_unhashable_repr(self): # In Python 3, C extensions can define a __repr__ method which is an # instance of `instancemethod`, which is unhashable. It turns out to be # spectacularly difficult to create an `instancemethod` and attach it to # a type without using C... so we'll simulate it using a more explicitly # unhashable type. # See also: http://stackoverflow.com/q/40876368/71522 class UnhashableCallable(object): __hash__ = None def __call__(self): return "some-repr" class MyCls(object): __repr__ = UnhashableCallable() obj = MyCls() assert_equal(p.pformat(obj), "some-repr") if __name__ == "__main__": import nose nose.main() pprintpp-0.4.0/tox.ini0000644000076600001200000000016113017443445015476 0ustar woleveradmin00000000000000[tox] envlist = py26,py27,py33,py35,pypy [testenv] deps = -rtest-requires.txt commands = python test.py