Skip to content

Commit 0bb47e9

Browse files
authored
Merge pull request #4799 from zhangli091011/fix/issue-4402-symbolic-data-repr
Show data(...) for symbolic data arguments
2 parents 49f5e1e + ed70dff commit 0bb47e9

6 files changed

Lines changed: 25 additions & 17 deletions

File tree

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,4 @@ their individual contributions.
206206
* `Yiyang Zhan <https://www.github.com/zhanpon>`_
207207
* `Zac Hatfield-Dodds <https://www.github.com/Zac-HD>`_ (zac.hatfield.dodds@gmail.com)
208208
* `Zebulun Arendsee <https://www.github.com/arendsee>`_ (zbwrnz@gmail.com)
209+
* `zhangli091011 <https://github.com/zhangli091011>`_

hypothesis/RELEASE.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
RELEASE_TYPE: patch
2+
3+
This release improves observability output under symbolic backends by displaying
4+
arguments generated by :func:`~hypothesis.strategies.data` as ``data(...)``.
5+
6+
Thanks to zhangli091011 for this fix!

hypothesis/src/hypothesis/core.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,11 @@ def __init__(
936936
self.print_given_args = getattr(
937937
wrapped_test, "_hypothesis_internal_print_given_args", True
938938
)
939+
self.known_safe_to_repr = {
940+
name
941+
for name, strategy in stuff.given_kwargs.items()
942+
if strategy == st.data()
943+
}
939944

940945
self.last_exception = None
941946
self.falsifying_examples = ()
@@ -1083,6 +1088,7 @@ def run(data: ConjectureData) -> None:
10831088
else None
10841089
),
10851090
avoid_realization=data.provider.avoid_realization,
1091+
known_safe_to_repr=self.known_safe_to_repr,
10861092
)
10871093
report(printer.getvalue())
10881094

@@ -1100,6 +1106,7 @@ def run(data: ConjectureData) -> None:
11001106
else None
11011107
),
11021108
avoid_realization=data.provider.avoid_realization,
1109+
known_safe_to_repr=self.known_safe_to_repr,
11031110
)
11041111
self._string_repr = printer.getvalue()
11051112

hypothesis/src/hypothesis/vendor/pretty.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def _repr_pretty_(self, p, cycle):
7070
import types
7171
import warnings
7272
from collections import Counter, OrderedDict, defaultdict, deque
73-
from collections.abc import Callable, Generator, Iterable, Sequence
73+
from collections.abc import Callable, Collection, Generator, Iterable, Sequence
7474
from contextlib import contextmanager, suppress
7575
from enum import Enum, Flag
7676
from functools import partial
@@ -554,6 +554,7 @@ def repr_call(
554554
arg_slices: ArgLabelsT | None = None,
555555
leading_comment: str | None = None,
556556
avoid_realization: bool = False,
557+
known_safe_to_repr: Collection[str] = (),
557558
) -> None:
558559
"""Helper function to represent a function call.
559560
@@ -619,7 +620,7 @@ def repr_call(
619620
entry = comments.get(label)
620621
if entry:
621622
self._commented_slices.add(entry[1])
622-
if avoid_realization:
623+
if avoid_realization and label not in known_safe_to_repr:
623624
self.text("<symbolic>")
624625
else:
625626
self.pretty(v)

hypothesis/tests/conjecture/test_provider.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,9 @@ def test_function(data):
478478

479479
with capture_out() as out:
480480
test_function()
481+
assert (
482+
"Trying example: test_function(\n data=data(...),\n)" in out.getvalue()
483+
)
481484
assert "Draw 1: <symbolic>" in out.getvalue()
482485

483486

@@ -496,9 +499,8 @@ def test_function(data):
496499
assert {tc.representation for tc in test_cases} == {
497500
# from the first ChoiceTemplate(type="simplest") example
498501
"test_function(\n data=data(...),\n)\nDraw 1: 0",
499-
# from all other examples. data=<symbolic> isn't ideal; we should special
500-
# case this as data=data(...).
501-
f"test_function(\n data=<symbolic>,\n)\nDraw 1: {RealizeProvider.REALIZED}",
502+
# from all other examples
503+
f"test_function(\n data=data(...),\n)\nDraw 1: {RealizeProvider.REALIZED}",
502504
}
503505

504506

hypothesis/tests/cover/test_observability.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,9 @@ def f(data):
186186
with capture_observations() as observations:
187187
f()
188188

189-
crosshair = settings.get_current_profile_name() == "crosshair"
190-
expected = textwrap.dedent(f"""
189+
expected = textwrap.dedent("""
191190
f(
192-
data={'<symbolic>' if crosshair else 'data(...)'},
191+
data=data(...),
193192
)
194193
Draw 1: True
195194
Draw 2 (second): True
@@ -198,15 +197,7 @@ def f(data):
198197
tc for tc in observations if tc.type == "test_case" and tc.status == "passed"
199198
]
200199
assert test_cases
201-
representations = {tc.representation for tc in test_cases}
202-
if crosshair:
203-
# Under the crosshair backend Hypothesis observes the same example under
204-
# both the crosshair provider (data=<symbolic>) and its own concrete
205-
# replay (data=data(...)), so there is more than one representation;
206-
# just require the symbolic one to be present.
207-
assert expected in representations
208-
else:
209-
assert {tc.representation for tc in test_cases} == {expected}
200+
assert {tc.representation for tc in test_cases} == {expected}
210201

211202

212203
def test_capture_named_arguments():

0 commit comments

Comments
 (0)