Skip to content

Commit

Permalink
Merge pull request #3107 from Zac-HD/systemexit-handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Zac-HD committed Sep 26, 2021
2 parents dbcf72d + 4f3c34a commit 70e3c72
Show file tree
Hide file tree
Showing 18 changed files with 76 additions and 39 deletions.
9 changes: 9 additions & 0 deletions hypothesis-python/RELEASE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
RELEASE_TYPE: minor

This release follows :pypi:`pytest` in considering :class:`SystemExit` and
:class:`GeneratorExit` exceptions to be test failures, meaning that we will
shink to minimal examples and check for flakiness even though they subclass
:class:`BaseException` directly (:issue:`2223`).

:class:`KeyboardInterrupt` continues to interrupt everything, and will be
re-raised immediately.
2 changes: 1 addition & 1 deletion hypothesis-python/src/hypothesis/_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def __setattr__(cls, name, value):
"settings with settings.load_profile, or use @settings(...) "
"to decorate your test instead."
)
return type.__setattr__(cls, name, value)
return super().__setattr__(name, value)


class settings(metaclass=settingsMeta):
Expand Down
8 changes: 6 additions & 2 deletions hypothesis-python/src/hypothesis/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def decode_failure(blob):
class WithRunner(MappedSearchStrategy):
def __init__(self, base, runner):
assert runner is not None
MappedSearchStrategy.__init__(self, base)
super().__init__(base)
self.runner = runner

def do_draw(self, data):
Expand Down Expand Up @@ -493,7 +493,11 @@ def failure_exceptions_to_catch():
This is intended to cover most common test runners; if you would
like another to be added please open an issue or pull request.
"""
exceptions = [Exception]
# While SystemExit and GeneratorExit are instances of BaseException, we also
# expect them to be deterministic - unlike KeyboardInterrupt - and so we treat
# them as standard exceptions, check for flakiness, etc.
# See https://github.com/HypothesisWorks/hypothesis/issues/2223 for details.
exceptions = [Exception, SystemExit, GeneratorExit]
if "_pytest" in sys.modules: # pragma: no branch
exceptions.append(sys.modules["_pytest"].outcomes.Failed)
return tuple(exceptions)
Expand Down
2 changes: 1 addition & 1 deletion hypothesis-python/src/hypothesis/extra/_array_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ def __init__(
min_side=1,
max_side=None,
):
st.SearchStrategy.__init__(self)
super().__init__()
self.base_shape = base_shape
self.side_strat = st.integers(min_side, max_side)
self.num_shapes = num_shapes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ class LearnedDFA(DFA):
distinguished by a membership test and a set of experiments."""

def __init__(self, lstar):
DFA.__init__(self)
super().__init__()
self.__lstar = lstar
self.__generation = lstar.generation

Expand Down
4 changes: 2 additions & 2 deletions hypothesis-python/src/hypothesis/stateful.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def __setattr__(cls, name, value):
"on the {cls} class."
).format(cls=cls.__name__, value=value)
)
return type.__setattr__(cls, name, value)
return super().__setattr__(name, value)


class RuleBasedStateMachine(metaclass=StateMachineMeta):
Expand Down Expand Up @@ -883,7 +883,7 @@ def invariant_wrapper(*args, **kwargs):

class RuleStrategy(SearchStrategy):
def __init__(self, machine):
SearchStrategy.__init__(self)
super().__init__()
self.machine = machine
self.rules = list(machine.rules())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class TupleStrategy(SearchStrategy):
strategies for each of their elements."""

def __init__(self, strategies):
SearchStrategy.__init__(self)
super().__init__()
self.element_strategies = tuple(strategies)

def do_validate(self):
Expand Down Expand Up @@ -136,7 +136,7 @@ class ListStrategy(SearchStrategy):
allowed lengths, and generates lists with the correct size and contents."""

def __init__(self, elements, min_size=0, max_size=float("inf")):
SearchStrategy.__init__(self)
super().__init__()
self.min_size = min_size or 0
self.max_size = max_size if max_size is not None else float("inf")
assert 0 <= self.min_size <= self.max_size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class DeferredStrategy(SearchStrategy):
"""A strategy which may be used before it is fully defined."""

def __init__(self, definition):
SearchStrategy.__init__(self)
super().__init__()
self.__wrapped_strategy = None
self.__in_repr = False
self.__definition = definition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class LazyStrategy(SearchStrategy):
"""

def __init__(self, function, args, kwargs, filters=(), *, force_repr=None):
SearchStrategy.__init__(self)
super().__init__()
self.__wrapped_strategy = None
self.__representation = force_repr
self.function = function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class FloatStrategy(SearchStrategy):
"""Generic superclass for strategies which produce floats."""

def __init__(self, allow_infinity, allow_nan, width):
SearchStrategy.__init__(self)
super().__init__()
assert isinstance(allow_infinity, bool)
assert isinstance(allow_nan, bool)
assert width in (16, 32, 64)
Expand Down Expand Up @@ -239,7 +239,7 @@ class FixedBoundedFloatStrategy(SearchStrategy):
"""

def __init__(self, lower_bound, upper_bound, width):
SearchStrategy.__init__(self)
super().__init__()
assert isinstance(lower_bound, float)
assert isinstance(upper_bound, float)
assert 0 <= lower_bound < upper_bound
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ class ArtificialRandom(HypothesisRandom):
VERSION = 10 ** 6

def __init__(self, note_method_calls, data):
HypothesisRandom.__init__(self, note_method_calls=note_method_calls)
super().__init__(note_method_calls=note_method_calls)
self.__data = data
self.__state = RandomState()

Expand Down Expand Up @@ -397,7 +397,7 @@ def convert_kwargs(name, kwargs):

class TrueRandom(HypothesisRandom):
def __init__(self, seed, note_method_calls):
HypothesisRandom.__init__(self, note_method_calls)
super().__init__(note_method_calls)
self.__seed = seed
self.__random = Random(seed)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ class SampledFromStrategy(SearchStrategy):
"""

def __init__(self, elements, repr_=None, transformations=()):
SearchStrategy.__init__(self)
super().__init__()
self.elements = cu.check_sample(elements, "sampled_from")
assert self.elements
self.repr_ = repr_
Expand Down Expand Up @@ -592,7 +592,7 @@ class OneOfStrategy(SearchStrategy):
"""

def __init__(self, strategies):
SearchStrategy.__init__(self)
super().__init__()
strategies = tuple(strategies)
self.original_strategies = list(strategies)
self.__element_strategies = None
Expand Down Expand Up @@ -778,7 +778,7 @@ class MappedSearchStrategy(SearchStrategy):
"""

def __init__(self, strategy, pack=None):
SearchStrategy.__init__(self)
super().__init__()
self.mapped_strategy = strategy
if pack is not None:
self.pack = pack
Expand Down
4 changes: 1 addition & 3 deletions hypothesis-python/src/hypothesis/vendor/pretty.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,7 @@ def __init__(
max_seq_length=MAX_SEQ_LENGTH,
):

PrettyPrinter.__init__(
self, output, max_width, newline, max_seq_length=max_seq_length
)
super().__init__(output, max_width, newline, max_seq_length=max_seq_length)
self.verbose = verbose
self.stack = []
if singleton_pprinters is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ def test_do_nothing(x):
test_do_nothing()


@pytest.mark.parametrize(
"e", [KeyboardInterrupt, SystemExit, GeneratorExit, ValueError]
)
@pytest.mark.parametrize("e", [KeyboardInterrupt, ValueError])
def test_baseexception_no_rerun_no_flaky(e):
runs = [0]
interrupt = 3
Expand Down Expand Up @@ -100,3 +98,31 @@ def test_do_nothing(x):
# Now SystemExit and GeneratorExit are caught like other exceptions
with pytest.raises(Flaky):
test_do_nothing()


TEMPLATE = """
from hypothesis import given, note, strategies as st
@st.composite
def things(draw):
raise {exception}
@given(st.data(), st.integers())
def test(data, x):
if x > 100:
data.draw({strategy})
raise {exception}
"""


@pytest.mark.parametrize("exc_name", ["SystemExit", "GeneratorExit"])
@pytest.mark.parametrize("use_composite", [True, False])
def test_explanations(testdir, exc_name, use_composite):
code = TEMPLATE.format(
exception=exc_name, strategy="things()" if use_composite else "st.none()"
)
test_file = str(testdir.makepyfile(code))
pytest_stdout = str(testdir.runpytest_inprocess(test_file, "--tb=native").stdout)
assert "x=101" in pytest_stdout
assert exc_name in pytest_stdout
6 changes: 3 additions & 3 deletions hypothesis-python/tests/quality/test_poisoned_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

class Poisoned(SearchStrategy):
def __init__(self, poison_chance):
SearchStrategy.__init__(self)
super().__init__()
self.__poison_chance = poison_chance
self.__ints = st.integers(0, 10)

Expand All @@ -41,7 +41,7 @@ def do_draw(self, data):

class LinearLists(SearchStrategy):
def __init__(self, elements, size):
SearchStrategy.__init__(self)
super().__init__()
self.__length = st.integers(0, size)
self.__elements = elements

Expand All @@ -51,7 +51,7 @@ def do_draw(self, data):

class Matrices(SearchStrategy):
def __init__(self, elements, size):
SearchStrategy.__init__(self)
super().__init__()
self.__length = st.integers(0, ceil(size ** 0.5))
self.__elements = elements

Expand Down
2 changes: 1 addition & 1 deletion hypothesis-python/tests/quality/test_poisoned_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class PoisonedTree(SearchStrategy):
"""

def __init__(self, p):
SearchStrategy.__init__(self)
super().__init__()
self.__p = p

def do_draw(self, data):
Expand Down
2 changes: 1 addition & 1 deletion requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pytest==6.2.5
# pytest-xdist
pytest-forked==1.3.0
# via pytest-xdist
pytest-xdist==2.3.0
pytest-xdist==2.4.0
# via -r requirements/test.in
sortedcontainers==2.4.0
# via hypothesis (hypothesis-python/setup.py)
Expand Down
20 changes: 10 additions & 10 deletions requirements/tools.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ cryptography==3.4.8
# via secretstorage
decorator==5.1.0
# via ipython
distlib==0.3.2
distlib==0.3.3
# via virtualenv
django==3.2.7
# via -r requirements/tools.in
Expand Down Expand Up @@ -109,7 +109,7 @@ importlib-metadata==4.8.1
# twine
iniconfig==1.1.1
# via pytest
ipython==7.27.0
ipython==7.28.0
# via -r requirements/tools.in
isort==5.9.3
# via shed
Expand All @@ -125,7 +125,7 @@ keyring==23.2.1
# via twine
lark-parser==0.12.0
# via -r requirements/tools.in
libcst==0.3.20
libcst==0.3.21
# via
# -r requirements/tools.in
# pybetter
Expand Down Expand Up @@ -161,11 +161,11 @@ pexpect==4.8.0
# via ipython
pickleshare==0.7.5
# via ipython
pip-tools==6.2.0
pip-tools==6.3.0
# via -r requirements/tools.in
pkginfo==1.7.1
# via twine
platformdirs==2.3.0
platformdirs==2.4.0
# via
# black
# virtualenv
Expand Down Expand Up @@ -213,15 +213,15 @@ pytz==2021.1
# via
# babel
# django
pyupgrade==2.26.0.post1
pyupgrade==2.28.0
# via shed
pyyaml==5.4.1
# via
# bandit
# libcst
readme-renderer==29.0
# via twine
regex==2021.8.28
regex==2021.9.24
# via black
requests==2.26.0
# via
Expand Down Expand Up @@ -295,7 +295,7 @@ tomli==1.2.1
# pep517
tox==3.24.4
# via -r requirements/tools.in
tqdm==4.62.2
tqdm==4.62.3
# via twine
traitlets==5.1.0
# via
Expand All @@ -320,9 +320,9 @@ typing-extensions==3.10.0.2
# typing-inspect
typing-inspect==0.7.1
# via libcst
urllib3==1.26.6
urllib3==1.26.7
# via requests
virtualenv==20.8.0
virtualenv==20.8.1
# via tox
wcwidth==0.2.5
# via prompt-toolkit
Expand Down

0 comments on commit 70e3c72

Please sign in to comment.