Disclaimer: I'm the author of the package.
For a comparison with other formatters, see Other Formatters.
Formatting
Unlike pprint.pprint, prettyformatter spreads vertically more and attempts to align items more.
Unlike json.dumps, prettyformatter is usually more compact and attempts to align dictionary values wherever reasonable.
from prettyformatter import pprint
batters = [
{"id": "1001", "type": "Regular"},
{"id": "1002", "type": "Chocolate"},
{"id": "1003", "type": "Blueberry"},
{"id": "1004", "type": "Devil's Food"},
]
toppings = [
{"id": "5001", "type": None},
{"id": "5002", "type": "Glazed"},
{"id": "5005", "type": "Sugar"},
{"id": "5007", "type": "Powdered Sugar"},
{"id": "5006", "type": "Chocolate with Sprinkles"},
{"id": "5003", "type": "Chocolate"},
{"id": "5004", "type": "Maple"},
]
data = {"id": "0001", "type": "donut", "name": "Cake", "ppu": 0.55, "batters": batters, "topping": toppings}
pprint(data)
Output:
{
"id" : "0001",
"type" : "donut",
"name" : "Cake",
"ppu" : 0.55,
"batters":
[
{"id": "1001", "type": "Regular"},
{"id": "1002", "type": "Chocolate"},
{"id": "1003", "type": "Blueberry"},
{"id": "1004", "type": "Devil's Food"},
],
"topping":
[
{"id": "5001", "type": None},
{"id": "5002", "type": "Glazed"},
{"id": "5005", "type": "Sugar"},
{"id": "5007", "type": "Powdered Sugar"},
{"id": "5006", "type": "Chocolate with Sprinkles"},
{"id": "5003", "type": "Chocolate"},
{"id": "5004", "type": "Maple"},
],
}
Features
See here for the full documentation.
JSON
Unlike pprint.pprint, prettyformatter supports JSON conversion via the json=True argument. This includes changing None to null, True to true, False to false, and correct use of quotes.
Unlike json.dumps, prettyformatter supports JSON coercion with more data types. This includes changing any dataclass or mapping into a dict and any iterable into a list.
from dataclasses import dataclass
from prettyformatter import PrettyDataclass, pprint
@dataclass(unsafe_hash=True)
class Point(PrettyDataclass):
x: int
y: int
pprint((Point(1, 2), Point(3, 4)), json=True)
Output:
[{"x": 1, "y": 2}, {"x": 3, "y": 4}]
Customization
Unlike pprint.pprint or json.dumps, prettyformatter supports easy customization with additional types.
Implementing the __pargs__ and/or __pkwargs__ methods for a prettyformatter.PrettyClass subclass allows one to easily customize classes in the form of "cls_name(*args, **kwargs)".
from prettyformatter import PrettyClass
class Dog(PrettyClass):
def __init__(self, name, **kwargs):
self.name = name
def __pkwargs__(self):
return {"name": self.name}
print(Dog("Fido"))
"""
Dog(name="Fido")
"""
print(Dog("Fido"), json=True)
"""
{"name": "Fido"}
"""
Implementing the __pformat__ method allows even more specific implementations of the pformat function.
Implementing the @prettyformatter.register function also allows customizing classes that already exist in the same way implementing __pformat__ would.
import numpy as np
from prettyformatter import pprint, register
@register(np.ndarray)
def pformat_ndarray(obj, specifier, depth, indent, shorten, json):
if json:
return pformat(obj.tolist(), specifier, depth, indent, shorten, json)
with np.printoptions(formatter=dict(all=lambda x: format(x, specifier))):
return repr(obj).replace("\n", "\n" + " " * depth)
pprint(dict.fromkeys("ABC", np.arange(9).reshape(3, 3)))
Output:
{
"A":
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]]),
"B":
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]]),
"C":
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]]),
}