Skip to content

Commit 21502ba

Browse files
authored
Merge pull request #4148 from HypothesisWorks/DRMacIver/use-provided-pretty
Always use a repr_pretty if provided
2 parents b9d41db + 558db3c commit 21502ba

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

hypothesis-python/RELEASE.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
RELEASE_TYPE: patch
2+
3+
This patch changes the priority order of pretty printing logic so that a user
4+
provided pretty printing method will always be used in preference to e.g.
5+
printing it like a dataclass.

hypothesis-python/src/hypothesis/vendor/pretty.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,16 @@ def pretty(self, obj):
186186
pass
187187
else:
188188
return printer(obj, self, cycle)
189+
190+
# Look for the _repr_pretty_ method which allows users
191+
# to define custom pretty printing.
192+
# Some objects automatically create any requested
193+
# attribute. Try to ignore most of them by checking for
194+
# callability.
195+
pretty_method = _safe_getattr(obj, "_repr_pretty_", None)
196+
if callable(pretty_method):
197+
return pretty_method(self, cycle)
198+
189199
# Next walk the mro and check for either:
190200
# 1) a registered printer
191201
# 2) a _repr_pretty_ method
@@ -206,14 +216,6 @@ def pretty(self, obj):
206216
self.type_pprinters[cls] = printer
207217
return printer(obj, self, cycle)
208218
else:
209-
# Finally look for special method names.
210-
# Some objects automatically create any requested
211-
# attribute. Try to ignore most of them by checking for
212-
# callability.
213-
if "_repr_pretty_" in cls.__dict__:
214-
meth = cls._repr_pretty_
215-
if callable(meth):
216-
return meth(obj, self, cycle)
217219
if hasattr(cls, "__attrs_attrs__"):
218220
return pprint_fields(
219221
obj,

hypothesis-python/tests/cover/test_pretty.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4848
"""
4949

50+
import io
5051
import re
5152
import struct
5253
import sys
@@ -100,9 +101,12 @@ def _repr_pretty_(self, p, cycle):
100101
p.text("Dummy1(...)")
101102

102103

103-
class Dummy2(Dummy1):
104+
class Dummy2:
104105
_repr_pretty_ = None
105106

107+
def __repr__(self):
108+
return "Dummy2()"
109+
106110

107111
class NoModule:
108112
pass
@@ -207,7 +211,7 @@ def test_callability_checking():
207211
"""Test that the _repr_pretty_ method is tested for callability and skipped
208212
if not."""
209213
gotoutput = pretty.pretty(Dummy2())
210-
expectedoutput = "Dummy1(...)"
214+
expectedoutput = "Dummy2()"
211215

212216
assert gotoutput == expectedoutput
213217

@@ -901,3 +905,29 @@ class E(Enum):
901905
@pytest.mark.parametrize("obj", NAMESPACED_VALUES, ids=map(repr, NAMESPACED_VALUES))
902906
def test_includes_namespace_classes_in_pretty(obj):
903907
assert pretty.pretty(obj).startswith("Namespace.")
908+
909+
910+
class Banana:
911+
def _repr_pretty_(self, p, cycle):
912+
p.text("I am a banana")
913+
914+
915+
@dataclass
916+
class InheritsPretty(Banana):
917+
x: int
918+
y: int
919+
920+
921+
def test_uses_defined_pretty_printing_method():
922+
assert pretty.pretty(InheritsPretty(x=1, y=2)) == pretty.pretty(Banana())
923+
924+
925+
def test_prefers_singleton_printing_to_repr_pretty():
926+
out = io.StringIO()
927+
printer = pretty.RepresentationPrinter(out)
928+
banana = Banana()
929+
printer.singleton_pprinters[id(banana)] = lambda obj, p, cycle: p.text(
930+
"Actually a fish"
931+
)
932+
printer.pretty(banana)
933+
assert "Actually a fish" in out.getvalue()

0 commit comments

Comments
 (0)