Skip to content

Commit

Permalink
Use provider-driven context manager
Browse files Browse the repository at this point in the history
  • Loading branch information
pschanely committed Mar 6, 2024
1 parent c782228 commit b303a81
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 49 deletions.
13 changes: 0 additions & 13 deletions hypothesis_crosshair_provider/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,6 @@ def _hypothesis_setup_hook(*a, **kw):
f"This version of hypothesis doesn't support the CrossHair backend"
)
return
if not hasattr(
hypothesis.core, "hacky_patchable_run_context_yielding_per_test_case_context"
):
warnings.warn(
f"This version of hypothesis doesn't support the CrossHair backend"
)
return
AVAILABLE_PROVIDERS[
"crosshair"
] = "hypothesis_crosshair_provider.crosshair_provider.CrossHairPrimitiveProvider"
from hypothesis_crosshair_provider.crosshair_provider import \
hacky_patchable_run_context_yielding_per_test_case_context

hypothesis.core.hacky_patchable_run_context_yielding_per_test_case_context = (
hacky_patchable_run_context_yielding_per_test_case_context
)
57 changes: 24 additions & 33 deletions hypothesis_crosshair_provider/crosshair_provider.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import math
import os
import sys
from contextlib import ExitStack, contextmanager
from time import monotonic
Expand All @@ -21,28 +22,25 @@
_PREVIOUS_REALIZED_DRAWS = None


@contextmanager
def hacky_patchable_run_context_yielding_per_test_case_context():

# TODO: detect whether this specific test is supposed to use the
# crosshair backend and return nullcontext if it isn't.
# Checking settings.default.backend doesn't appear to reflect decorated settings:
# if hypothesis.settings.default.backend != "crosshair":
# yield nullcontext
# return
class CrossHairPrimitiveProvider(PrimitiveProvider):
"""An implementation of PrimitiveProvider based on CrossHair."""

if "-v" in sys.argv or "-vv" in sys.argv:
set_debug(True)
search_root = RootNode()
def __init__(self, *_a, **_kw) -> None:
self.name_id = 0
self.current_exit_stack: Optional[ExitStack] = None
self.search_root = RootNode()
if len(os.environ.get("DEBUG_CROSSHAIR", "")) > 1:
set_debug(os.environ["DEBUG_CROSSHAIR"].lower() not in ("0", "false"))
elif "-vv" in sys.argv:
set_debug(True)

@contextmanager
def single_execution_context() -> Any:
nonlocal search_root
if search_root.child.is_exhausted():
def per_test_case_context_manager(self):
if self.search_root.child.is_exhausted():
debug("Resetting search root")
# might be nice to signal that we're done somehow.
# But for now, just start over!
search_root = RootNode()
self.search_root = RootNode()
global _PREVIOUS_REALIZED_DRAWS
_PREVIOUS_REALIZED_DRAWS = None
iter_start = monotonic()
Expand All @@ -51,7 +49,7 @@ def single_execution_context() -> Any:
space = StateSpace(
execution_deadline=iter_start + per_path_timeout,
model_check_timeout=per_path_timeout / 2,
search_root=search_root,
search_root=self.search_root,
)
space._hypothesis_draws = [] # keep a log of drawn values
try:
Expand Down Expand Up @@ -82,14 +80,18 @@ def single_execution_context() -> Any:
except Exception as exc:
try:
exc.args = deep_realize(exc.args)
debug(
f"end iter (exception: {type(exc).__name__}: {exc})",
test_stack(exc.__traceback__),
)
except Exception:
exc.args = ()
debug(
f"end iter ({type(exc)} exception)",
test_stack(exc.__traceback__),
)
debug(
f"end iter ({type(exc)} exception)",
test_stack(exc.__traceback__),
)
raise exc
except (IgnoreAttempt, UnexploredPath):
except (IgnoreAttempt, UnexploredPath) as e:
pass
finally:
if any_choices_made:
Expand All @@ -99,17 +101,6 @@ def single_execution_context() -> Any:
)
else:
debug("no decisions made; ignoring this iteration")

yield single_execution_context


class CrossHairPrimitiveProvider(PrimitiveProvider):
"""An implementation of PrimitiveProvider based on CrossHair."""

def __init__(self, conjecturedata: object, /) -> None:
self.name_id = 0
self.current_exit_stack: Optional[ExitStack] = None

def _next_name(self, prefix: str) -> str:
self.name_id += 1
return f"{prefix}_{self.name_id:02d}"
Expand Down
6 changes: 3 additions & 3 deletions hypothesis_crosshair_provider/crosshair_provider_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from hypothesis_crosshair_provider.crosshair_provider import (
CrossHairPrimitiveProvider,
hacky_patchable_run_context_yielding_per_test_case_context)
)


def _example_user_code(s_bool, s_int, s_float, s_str, s_bytes):
Expand All @@ -17,10 +17,10 @@ def _example_user_code(s_bool, s_int, s_float, s_str, s_bytes):


def test_end_to_end():
with hacky_patchable_run_context_yielding_per_test_case_context() as per_run_mgr:
provider = CrossHairPrimitiveProvider()
with provider.per_test_case_context_manager() as per_run_mgr:
found_ct = 0
for _ in range(30):
provider = CrossHairPrimitiveProvider(None)
try:
with per_run_mgr():
s_bool = provider.draw_boolean()
Expand Down

0 comments on commit b303a81

Please sign in to comment.