Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion test-requires.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
nose==1.3.0
pytest
parameterized==0.6.1
254 changes: 125 additions & 129 deletions test.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,100 @@
from __future__ import print_function

import sys
import ctypes
import textwrap

from nose.tools import assert_equal
from parameterized import parameterized, param
from contextlib import redirect_stdout
import io
import pytest

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):
def test_pp():
expected = "['hello', 'world']"
f = io.StringIO()
with redirect_stdout(f):
pp(["hello", "world"])
self.assertStdout("['hello', 'world']")
actual = f.getvalue().rstrip("\n")
assert actual == expected

def test_pp_pprint(self):
def test_pp_print():
expected = "'stuff'"
f = io.StringIO()
with redirect_stdout(f):
pp.pprint("stuff")
self.assertStdout("'stuff'")
actual = f.getvalue().rstrip("\n")
assert actual == expected

def test_fmt(self):
def test_fmt():
expected = "'asdf'\n'stuff'"
f = io.StringIO()
with redirect_stdout(f):
print(pp.pformat("asdf"))
print(pp.fmt("stuff"))
self.assertStdout("""
'asdf'
'stuff'
""")

def test_module_like(self):
print(dir(pp))
print(repr(pp))

actual = f.getvalue().rstrip("\n")
assert actual == expected

def test_module_like():
print(dir(pp))
print(repr(pp))

uni_safe = "\xe9 \u6f02 \u0e4f \u2661"
uni_unsafe = "\u200a \u0302 \n"
slashed = lambda s: u"%s'%s'" %(
p.u_prefix,
s.encode("ascii", "backslashreplace").decode("ascii").replace("\n", "\\n")
)

test_unicode_data = [
(uni_safe, "%s'%s'" %(p.u_prefix, uni_safe), "utf-8"),
(uni_unsafe, slashed(uni_unsafe), "utf-8"),
(uni_unsafe, slashed(uni_unsafe), "ascii"),
("\U0002F9B2", slashed("\U0002F9B2"), "ascii")
]

@pytest.mark.parametrize("input,expected,encoding", test_unicode_data)
def test_unicode(input, expected, encoding):
stream = p.TextIO(encoding=encoding)
p.pprint(input, stream=stream)
assert stream.getvalue().rstrip("\n") == expected

test_back_and_forth_data = [
"'\\'\"'",
'"\'"',
"'\"'",
"frozenset(['a', 'b', 'c'])",
"set([None, 1, 'a'])",
"[]",
"[1]",
"{}",
"{1: 1}",
"set()",
"set([1])",
"frozenset()",
"frozenset([1])",
"()",
"(1, )",
"MyDict({})",
"MyDict({1: 1})",
"MyList([])",
"MyList([1])",
"MyTuple(())",
"MyTuple((1, ))",
"MySet()",
"MySet([1])",
"MyFrozenSet()",
"MyFrozenSet([1])",
"Counter()",
"Counter({1: 1})",
"OrderedDict()",
"OrderedDict([(1, 1), (5, 5), (2, 2)])",
"MyOrderedDict()",
"MyOrderedDict([(1, 1)])",
"MyCounter()",
"MyCounter({1: 1})",
"MyCounterWithRepr('dummy')",
]

class MyDict(dict):
pass
Expand Down Expand Up @@ -70,104 +124,46 @@ 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()
@pytest.mark.parametrize("expected", test_back_and_forth_data)
def test_back_and_forth(expected):
input = eval(expected)
stream = p.TextIO()
p.pprint(input, stream=stream)
assert stream.getvalue().rstrip("\n") == expected

test_expected_input_data = [
("defaultdict(%r, {})" %(int, ), defaultdict(int)),
("defaultdict(%r, {1: 1})" %(int, ), defaultdict(int, [(1, 1)])),
("MyDefaultDict(%r, {})" %(int, ), MyDefaultDict(int)),
("MyDefaultDict(%r, {1: 1})" %(int, ), MyDefaultDict(int, [(1, 1)])),
]

@pytest.mark.parametrize("expected,input", test_expected_input_data)
def test_expected_input(expected, input):
stream = p.TextIO()
p.pprint(input, stream=stream)
assert stream.getvalue().rstrip("\n") == expected


def test_unhashable_repr():
# 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 p.pformat(obj) == "some-repr"