Repository: HypothesisWorks/hypothesis
Pull request: Do not catch and record KeyboardInterrupt
When a KeyboardInterrupt occurs, `hypothesis` should not treat it as a normal exception raised by a test or by a strategy - in particular it should not retry running anything, it should exit more or less directly. Instead, #2186 shows that `hypothesis` retries the generation and finds it doesn't raise KeboardInterrupt the second time around, so `hypothesis` reports Flaky.

The goal of this PR is to reproduce this problem in the test suite and then to solve it.

There may be a related problem where `hypothesis` doesn't handle a test calling `sys.exit` (raising SystemExit) as well as it should.

Fixes #2186 

Problem statement:
hypothesis reports Flaky on KeyboardInterrupt
It should simply exit gracefully; especially in fuzzing modes it's often just worth running it until the user wants to do something else, so bizarre messages aren't a good response to KeyboardInterrupt. Ideally the traceback before the KeyboardInterrupt would let the user figure out whether something had gone into an infinite loop, but adding additional stuff afterward is definitely confusing. The below is a (partial, it overflowed my terminal's scrollbacl) traceback from when I hit control-C. It is... not very transparent, and the most apparent message is the "Flaky", which is untrue.

```python
...

    def __stoppable_test_function(self, data):
        """Run ``self._test_function``, but convert a ``StopTest`` exception
        into a normal return.
        """
        try:
>           self._test_function(data)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/engine.py:125: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <hypothesis.core.StateForActualGivenExecution object at 0x7f94142bcb38>
data = ConjectureData(VALID, 24 bytes, frozen)

    def evaluate_test_data(self, data):
        try:
>           result = self.execute(data)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/core.py:598: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <hypothesis.core.StateForActualGivenExecution object at 0x7f94142bcb38>
data = ConjectureData(VALID, 24 bytes, frozen), print_example = False, is_final = False, expected_failure = None

    def execute(self, data, print_example=False, is_final=False, expected_failure=None):
        text_repr = [None]
        if self.settings.deadline is None:
            test = self.test
        else:
    
            @proxies(self.test)
            def test(*args, **kwargs):
                self.__test_runtime = None
                initial_draws = len(data.draw_times)
                start = benchmark_time()
                result = self.test(*args, **kwargs)
                finish = benchmark_time()
                internal_draw_time = sum(data.draw_times[initial_draws:])
                runtime = datetime.timedelta(
                    seconds=finish - start - internal_draw_time
                )
                self.__test_runtime = runtime
                current_deadline = self.settings.deadline
                if not is_final:
                    current_deadline = (current_deadline // 4) * 5
                if runtime >= current_deadline:
                    raise DeadlineExceeded(runtime, self.settings.deadline)
                return result
    
        def run(data):
            if not hasattr(data, "can_reproduce_example_from_repr"):
                data.can_reproduce_example_from_repr = True
            with local_settings(self.settings):
                with deterministic_PRNG():
                    with BuildContext(data, is_final=is_final):
                        args, kwargs = data.draw(self.search_strategy)
                        if expected_failure is not None:
                            text_repr[0] = arg_string(test, args, kwargs)
    
                        if print_example:
                            example = "%s(%s)" % (
                                test.__name__,
                                arg_string(test, args, kwargs),
                            )
                            try:
                                ast.parse(example)
                            except SyntaxError:
                                data.can_reproduce_example_from_repr = False
                            report("Falsifying example: %s" % (example,))
                        elif current_verbosity() >= Verbosity.verbose:
                            report(
                                lambda: "Trying example: %s(%s)"
                                % (test.__name__, arg_string(test, args, kwargs))
                            )
                        return test(*args, **kwargs)
    
>       result = self.test_runner(data, run)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/core.py:563: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

data = ConjectureData(VALID, 24 bytes, frozen)
function = <function StateForActualGivenExecution.execute.<locals>.run at 0x7f94130127b8>

    def default_new_style_executor(data, function):
>       return function(data)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/executors.py:56: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

data = ConjectureData(VALID, 24 bytes, frozen)

    def run(data):
        if not hasattr(data, "can_reproduce_example_from_repr"):
            data.can_reproduce_example_from_repr = True
        with local_settings(self.settings):
            with deterministic_PRNG():
                with BuildContext(data, is_final=is_final):
>                   args, kwargs = data.draw(self.search_strategy)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/core.py:542: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = TupleStrategy((just(()), fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))}).map(lambda args: dict(args, **kwargs))))
label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = TupleStrategy((just(()), fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))}).map(lambda args: dict(args, **kwargs))))
label = 9447048757421901795

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
                return strategy.do_draw(self)
            else:
                try:
                    strategy.validate()
                    start_time = benchmark_time()
                    try:
>                       return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:851: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TupleStrategy((just(()), fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))}).map(lambda args: dict(args, **kwargs))))
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return tuple(data.draw(e) for e in self.element_strategies)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

.0 = <tuple_iterator object at 0x7f9413be9b70>

>   return tuple(data.draw(e) for e in self.element_strategies)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))}).map(lambda args: dict(args, **kwargs))
label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))}).map(lambda args: dict(args, **kwargs))
label = 10700208128082112041

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))}).map(lambda args: dict(args, **kwargs))
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
        # type: (ConjectureData) -> Ex
        for _ in range(3):
            i = data.index
            try:
                data.start_example(MAPPED_SEARCH_STRATEGY_DO_DRAW_LABEL)
>               result = self.pack(data.draw(self.mapped_strategy))

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/strategies.py:570: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))})
label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))})
label = 12000696373305623442

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = fixed_dictionaries({'delta': floats(min_value=-10000, max_value=10000),
 'jds': unreasonable_jd(),
 'scale': sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))})
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return data.draw(self.wrapped_strategy)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/lazy.py:156: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = FixedKeysDictStrategy(('delta', 'jds', 'scale'), TupleStrategy((floats(min_value=-10000, max_value=10000), unreasonable_jd(), sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc')))))
label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = FixedKeysDictStrategy(('delta', 'jds', 'scale'), TupleStrategy((floats(min_value=-10000, max_value=10000), unreasonable_jd(), sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc')))))
label = 12000696373305623442

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = FixedKeysDictStrategy(('delta', 'jds', 'scale'), TupleStrategy((floats(min_value=-10000, max_value=10000), unreasonable_jd(), sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc')))))
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
        # type: (ConjectureData) -> Ex
        for _ in range(3):
            i = data.index
            try:
                data.start_example(MAPPED_SEARCH_STRATEGY_DO_DRAW_LABEL)
>               result = self.pack(data.draw(self.mapped_strategy))

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/strategies.py:570: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = TupleStrategy((floats(min_value=-10000, max_value=10000), unreasonable_jd(), sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))))
label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = TupleStrategy((floats(min_value=-10000, max_value=10000), unreasonable_jd(), sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))))
label = 5375030803676309577

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TupleStrategy((floats(min_value=-10000, max_value=10000), unreasonable_jd(), sampled_from(('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc'))))
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return tuple(data.draw(e) for e in self.element_strategies)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

.0 = <tuple_iterator object at 0x7f9413be9cf8>

>   return tuple(data.draw(e) for e in self.element_strategies)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:60: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = unreasonable_jd(), label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = unreasonable_jd(), label = 9227067894999533075

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = unreasonable_jd(), data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return data.draw(self.wrapped_strategy)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/lazy.py:156: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = <hypothesis._strategies.CompositeStrategy object at 0x7f94142bc160>, label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = <hypothesis._strategies.CompositeStrategy object at 0x7f94142bc160>, label = 9227067894999533075

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <hypothesis._strategies.CompositeStrategy object at 0x7f94142bc160>
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return self.definition(data.draw, *self.args, **self.kwargs)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/_strategies.py:1911: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

draw = <bound method ConjectureData.draw of ConjectureData(VALID, 24 bytes, frozen)>

    @composite
    def unreasonable_jd(draw):
        return draw(one_of(reasonable_jd(),
                           ordered_jd(),
>                          unreasonable_ordinary_jd()))

astropy/time/tests/test_precision.py:131: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = one_of(reasonable_jd(), ordered_jd(), unreasonable_ordinary_jd()), label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = one_of(reasonable_jd(), ordered_jd(), unreasonable_ordinary_jd()), label = 11076910798766186203

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = one_of(reasonable_jd(), ordered_jd(), unreasonable_ordinary_jd())
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
        # type: (ConjectureData) -> Ex
        n = len(self.element_strategies)
        assert n > 0
        if n == 1:
            return data.draw(self.element_strategies[0])
    
        i = cu.integer_range(data, 0, n - 1)
    
>       return data.draw(self.element_strategies[i], label=self.branch_labels[i])

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/strategies.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = ordered_jd(), label = 13750153062621414729

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = ordered_jd(), label = 13750153062621414729

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ordered_jd(), data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return data.draw(self.wrapped_strategy)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/lazy.py:156: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = <hypothesis._strategies.CompositeStrategy object at 0x7f9413ec0780>, label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = <hypothesis._strategies.CompositeStrategy object at 0x7f9413ec0780>, label = 13118283642048003977

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <hypothesis._strategies.CompositeStrategy object at 0x7f9413ec0780>
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return self.definition(data.draw, *self.args, **self.kwargs)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/_strategies.py:1911: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

draw = <bound method ConjectureData.draw of ConjectureData(VALID, 24 bytes, frozen)>

    @composite
    def ordered_jd(draw):
        """JD pair that is ordered but not necessarily near now"""
>       return draw(floats(-1e7, 1e7)), draw(floats(-0.5, 0.5))

astropy/time/tests/test_precision.py:124: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = floats(min_value=-0.5, max_value=0.5), label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = floats(min_value=-0.5, max_value=0.5)
label = 6361134527623872643

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = floats(min_value=-0.5, max_value=0.5), data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return data.draw(self.wrapped_strategy)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/lazy.py:156: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = one_of(floats(min_value=0.0, max_value=0.5), floats(min_value=0.0, max_value=0.5).map(neg)), label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen)
strategy = one_of(floats(min_value=0.0, max_value=0.5), floats(min_value=0.0, max_value=0.5).map(neg))
label = 6361134527623872643

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = one_of(floats(min_value=0.0, max_value=0.5), floats(min_value=0.0, max_value=0.5).map(neg))
data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
        # type: (ConjectureData) -> Ex
        n = len(self.element_strategies)
        assert n > 0
        if n == 1:
            return data.draw(self.element_strategies[0])
    
        i = cu.integer_range(data, 0, n - 1)
    
>       return data.draw(self.element_strategies[i], label=self.branch_labels[i])

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/strategies.py:508: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = floats(min_value=0.0, max_value=0.5)
label = 17560280009627351640

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = floats(min_value=0.0, max_value=0.5)
label = 17560280009627351640

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = floats(min_value=0.0, max_value=0.5), data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
>       return data.draw(self.wrapped_strategy)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/lazy.py:156: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = FixedBoundedFloatStrategy(0.0, 0.5), label = None

    def draw(self, strategy, label=None):
        if self.is_find and not strategy.supports_find:
            raise InvalidArgument(
                (
                    "Cannot use strategy %r within a call to find (presumably "
                    "because it would be invalid after the call had ended)."
                )
                % (strategy,)
            )
    
        if strategy.is_empty:
            self.mark_invalid()
    
        if self.depth >= MAX_DEPTH:
            self.mark_invalid()
    
>       return self.__draw(strategy, label=label)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:836: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), strategy = FixedBoundedFloatStrategy(0.0, 0.5)
label = 7254141549895781909

    def __draw(self, strategy, label):
        at_top_level = self.depth == 0
        if label is None:
            label = strategy.label
        self.start_example(label=label)
        try:
            if not at_top_level:
>               return strategy.do_draw(self)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:845: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = FixedBoundedFloatStrategy(0.0, 0.5), data = ConjectureData(VALID, 24 bytes, frozen)

    def do_draw(self, data):
        f = self.lower_bound + (
            self.upper_bound - self.lower_bound
>       ) * d.fractional_float(data)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/searchstrategy/numbers.py:169: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

data = ConjectureData(VALID, 24 bytes, frozen)

    def fractional_float(data):
>       return (int_to_float(FLOAT_PREFIX | data.draw_bits(52)) - 1) / FULL_FLOAT

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/utils.py:162: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = ConjectureData(VALID, 24 bytes, frozen), n = 52, forced = None

    def draw_bits(self, n, forced=None):
        """Return an ``n``-bit integer from the underlying source of
        bytes. If ``forced`` is set to an integer will instead
        ignore the underlying source and simulate a draw as if it had
        returned that integer."""
        self.__assert_not_frozen("draw_bits")
        if n == 0:
            return 0
        assert n > 0
        n_bytes = bits_to_bytes(n)
        self.__check_capacity(n_bytes)
    
        if forced is not None:
            buf = bytearray(int_to_bytes(forced, n_bytes))
        else:
            buf = bytearray(self._draw_bytes(self, n_bytes))
        assert len(buf) == n_bytes
    
        # If we have a number of bits that is not a multiple of 8
        # we have to mask off the high bits.
        buf[0] &= BYTE_MASKS[n % 8]
        buf = hbytes(buf)
        result = int_from_bytes(buf)
    
>       self.observer.draw_bits(n, forced is not None, result)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:956: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <hypothesis.internal.conjecture.datatree.TreeRecordingObserver object at 0x7f9413db20f0>, n_bits = 52
forced = False, value = 1897835254600418

    def draw_bits(self, n_bits, forced, value):
        i = self.__index_in_current_node
        self.__index_in_current_node += 1
        node = self.__current_node
        assert len(node.bit_lengths) == len(node.values)
        if i < len(node.bit_lengths):
            if n_bits != node.bit_lengths[i]:
                inconsistent_generation()
            # Note that we don't check whether a previously
            # forced value is now free. That will be caught
            # if we ever split the node there, but otherwise
            # may pass silently. This is acceptable because it
            # means we skip a hash set lookup on every
            # draw and that's a pretty niche failure mode.
            if forced and i not in node.forced:
                inconsistent_generation()
            if value != node.values[i]:
>               node.split_at(i)

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/datatree.py:321: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TreeNode(bit_lengths=IntList([52, 3]), values=IntList([1102370613918253, 0]), _TreeNode__forced=None, transition=Conclusion(status=Status.VALID, interesting_origin=None), is_exhausted=False)
i = 0

    def split_at(self, i):
        """Splits the tree so that it can incorporate
        a decision at the ``draw_bits`` call corresponding
        to position ``i``, or raises ``Flaky`` if that was
        meant to be a forced node."""
    
>       if i in self.forced:

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/datatree.py:148: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TreeNode(bit_lengths=IntList([52, 3]), values=IntList([1102370613918253, 0]), _TreeNode__forced=None, transition=Conclusion(status=Status.VALID, interesting_origin=None), is_exhausted=False)

>   @property
    def forced(self):
E   KeyboardInterrupt

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/datatree.py:129: KeyboardInterrupt

During handling of the above exception, another exception occurred:

    @given(sampled_from(_scales), unreasonable_jd(), floats(-10000, 10000))
>   @example(scale='utc',
             jds=(0.0, 2.2204460492503136e-13),
             delta=6.661338147750941e-13)
    @example(scale='utc',
             jds=(2441682.5, 2.2204460492503136e-16),
             delta=7.327471962526035e-12)
    @example(scale='utc', jds=(0.0, 5.787592627370942e-13), delta=0.0)
    def test_jd_add_subtract_round_trip(scale, jds, delta):

astropy/time/tests/test_precision.py:428: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/optimiser.py:53: in run
    self.hill_climb()
../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/optimiser.py:109: in hill_climb
    self.do_hill_climbing(random_non_empty)
../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/optimiser.py:148: in do_hill_climbing
    parameter=parameter, example_index=select_example(self.current_data)
../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/optimiser.py:201: in attempt_to_improve
    return self.consider_new_buffer(prefix + replacement + data.buffer[ex.end :])
../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/optimiser.py:85: in consider_new_buffer
    return self.consider_new_test_data(self.engine.cached_test_function(buffer))
../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:930: in freeze
    self.observer.conclude_test(self.status, self.interesting_origin)
../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/datatree.py:361: in conclude_test
    inconsistent_generation()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    def inconsistent_generation():
        raise Flaky(
>           "Inconsistent data generation! Data generation behaved differently "
            "between different runs. Is your data generation depending on external "
            "state?"
        )
E       hypothesis.errors.Flaky: Inconsistent data generation! Data generation behaved differently between different runs. Is your data generation depending on external state?

../../../.virtualenvs/astropy/lib/python3.7/site-packages/hypothesis/internal/conjecture/datatree.py:40: Flaky
----------------------------------------------------- Hypothesis ------------------------------------------------------
You can add @seed(181308649047304964118112440164661885706) to this test or run pytest with --hypothesis-seed=181308649047304964118112440164661885706 to reproduce this failure.
================================================= 1 failed in 27.98s ==================================================
```

Hints from issue discussion:
There are [only a few places where we `except BaseException`](https://github.com/HypothesisWorks/hypothesis/search?q=%22except+BaseException%22&unscoped_q=%22except+BaseException%22), and we should probably only be catching `Exception` from those in `core.py` and `control.py`.

In particular the "Flaky" message is because Hypothesis tries to replay whatever example it was running when you ctrl-Cd, and it's unlikely to get another interrupt at just the right time... but it should be exiting instead.  Add the example to the database just in case, absolutely, but this isn't the time to replay it.
Indeed according to the 3.8 docs, the three BaseExceptions that are not Exceptions are KeyboardInterrupt, SystemExit, and GeneratorExit. 

KeyboardInterrupt is generated in the obvious circumstance. 

SystemExit is called if the code calls `sys.exit`, which probably should never happen in code under test by `hypothesis`; users should replace it with raising a normal exception whether or not that line is ever reached. I can imagine trapping this at the top level and telling them so.

GeneratorExit is raised when a generator or coroutine is shut down (rather than running off the end). I don't think it makes sense to ever trap that either? Apart from `finally`-like usage that immediately re-raises. 

So are any of the occurrences of `except BaseException` in `hypothesis` a good idea?

I guess "make the change, write some tests, and see if anything goes wrong" is an okay approach for something as well-tested as `hypothesis`. 
I think we should probably keep the ones that re-raise, because e.g. the `pytest.skip()` exception inherits directly from BaseException, but convert the others. 

And the experimental approach should indeed work - if it doesn't that highlights a weakness in our tests, 😁
There seem to be several `hypothesis` custom exception classes that inherit from `BaseException`. Why is that?
They're used for control flow in contexts where user code might be doing `except Exception:` and we want to bypass it; same as [pytest outcomes](https://github.com/pytest-dev/pytest/blob/85288b53218d4e0037dce9c34bd37f86fa9e212d/src/_pytest/outcomes.py#L15).
> They're used for control flow in contexts where user code might be doing `except Exception:` and we want to bypass it; same as [pytest outcomes](https://github.com/pytest-dev/pytest/blob/85288b53218d4e0037dce9c34bd37f86fa9e212d/src/_pytest/outcomes.py#L15).

Blerg. I may have to handle KeyboardException (and StopException?) specially to avoid doing troublesome things to these.
Fixed by #2189 
FYI writing `Fixes #2189` in the top-level PR description (but not comments) [will close this issue automatically on merge](https://help.github.com/en/github/managing-your-work-on-github/closing-issues-using-keywords) 😄 
Aha! I knew about the magical "Fixes" but not exactly where it works. I think it works in the git log too?
Yep, per the help link it also works in commit messages - I stopped using it in commits though as every rebase adds a new cross-reference to the issue log, and I tend to rebase a lot 😅

Commit message: Add and annotate no-branch pragma

Patch to review:
diff --git a/hypothesis-python/RELEASE.rst b/hypothesis-python/RELEASE.rst
new file mode 100644
index 0000000000..9c4c21103d
--- /dev/null
+++ b/hypothesis-python/RELEASE.rst
@@ -0,0 +1,6 @@
+RELEASE_TYPE: patch
+
+This patch ensures that a KeyboardInterrupt received during example generation
+is not treated as a mystery test failure but instead propagates to the top
+level, not recording the interrupted generation in the conjecture data tree.
+Thanks to Anne Archibald for identifying and fixing the problem.
diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/engine.py b/hypothesis-python/src/hypothesis/internal/conjecture/engine.py
index af1a8af63d..1f1416c9d2 100644
--- a/hypothesis-python/src/hypothesis/internal/conjecture/engine.py
+++ b/hypothesis-python/src/hypothesis/internal/conjecture/engine.py
@@ -138,14 +138,21 @@ def test_function(self, data):
         assert isinstance(data.observer, TreeRecordingObserver)
         self.call_count += 1
 
+        interrupted = False
         try:
             self.__stoppable_test_function(data)
+        except KeyboardInterrupt:
+            interrupted = True
+            raise
         except BaseException:
             self.save_buffer(data.buffer)
             raise
         finally:
-            data.freeze()
-            self.note_details(data)
+            # No branch, because if we're interrupted we always raise
+            # the KeyboardInterrupt, never continue to the code below.
+            if not interrupted:  # pragma: no branch
+                data.freeze()
+                self.note_details(data)
 
         self.debug_data(data)
 
diff --git a/hypothesis-python/tests/cover/test_baseexception.py b/hypothesis-python/tests/cover/test_baseexception.py
new file mode 100644
index 0000000000..82e11f7439
--- /dev/null
+++ b/hypothesis-python/tests/cover/test_baseexception.py
@@ -0,0 +1,77 @@
+# coding=utf-8
+#
+# This file is part of Hypothesis, which may be found at
+# https://github.com/HypothesisWorks/hypothesis/
+#
+# Most of this work is copyright (C) 2013-2019 David R. MacIver
+# (david@drmaciver.com), but it contains contributions by others. See
+# CONTRIBUTING.rst for a full list of people who may hold copyright, and
+# consult the git log if you need to determine who owns an individual
+# contribution.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public License,
+# v. 2.0. If a copy of the MPL was not distributed with this file, You can
+# obtain one at https://mozilla.org/MPL/2.0/.
+#
+# END HEADER
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+from hypothesis import given
+from hypothesis.strategies import composite, integers
+
+
+def test_keyboardinterrupt_no_rerun():
+    runs = [0]
+    interrupt = 3
+
+    @given(integers())
+    def test_raise_keyboardinterrupt(x):
+        runs[0] += 1
+        if runs[0] == interrupt:
+            raise KeyboardInterrupt
+
+    with pytest.raises(KeyboardInterrupt):
+        test_raise_keyboardinterrupt()
+
+    assert runs[0] == interrupt
+
+
+def test_keyboardinterrupt_in_strategy_no_rerun():
+    runs = [0]
+    interrupt = 3
+
+    @composite
+    def interrupt_eventually(draw):
+        runs[0] += 1
+        if runs[0] == interrupt:
+            # import pdb; pdb.set_trace()
+            raise KeyboardInterrupt
+        return draw(integers())
+
+    @given(interrupt_eventually())
+    def test_do_nothing(x):
+        pass
+
+    with pytest.raises(KeyboardInterrupt):
+        test_do_nothing()
+
+    assert runs[0] == interrupt
+
+
+def test_systemexit_no_rerun():
+    runs = [0]
+    interrupt = 3
+
+    @given(integers())
+    def test_raise_systemexit(x):
+        runs[0] += 1
+        if runs[0] == interrupt:
+            raise SystemExit
+
+    with pytest.raises(SystemExit):
+        test_raise_systemexit()
+
+    assert runs[0] == interrupt
diff --git a/hypothesis-python/tests/cover/test_conjecture_engine.py b/hypothesis-python/tests/cover/test_conjecture_engine.py
index a3da54604e..16b0380222 100644
--- a/hypothesis-python/tests/cover/test_conjecture_engine.py
+++ b/hypothesis-python/tests/cover/test_conjecture_engine.py
@@ -364,7 +364,7 @@ def x(data):
                 data.mark_interesting()
 
 
-def test_saves_on_interrupt():
+def test_does_not_save_on_interrupt():
     def interrupts(data):
         raise KeyboardInterrupt()
 
@@ -376,7 +376,7 @@ def interrupts(data):
 
     with pytest.raises(KeyboardInterrupt):
         runner.run()
-    assert db.data
+    assert not db.data
 
 
 def test_returns_written():


Code review comments:
diff_hunk: @@ -0,0 +1,77 @@
+# coding=utf-8
+#
+# This file is part of Hypothesis, which may be found at
+# https://github.com/HypothesisWorks/hypothesis/
+#
+# Most of this work is copyright (C) 2013-2019 David R. MacIver
+# (david@drmaciver.com), but it contains contributions by others. See
+# CONTRIBUTING.rst for a full list of people who may hold copyright, and
+# consult the git log if you need to determine who owns an individual
+# contribution.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public License,
+# v. 2.0. If a copy of the MPL was not distributed with this file, You can
+# obtain one at https://mozilla.org/MPL/2.0/.
+#
+# END HEADER
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+from hypothesis import given
+from hypothesis.strategies import composite, integers
+
+
+def test_keyboardinterrupt_no_rerun():
+    runs = [0]
+    interrupt = 3
+
+    @given(integers())
+    def test_raise_keyboardinterrupt(x):
+        runs[0] += 1
+        if runs[0] == interrupt:
+            raise KeyboardInterrupt
+
+    with pytest.raises(KeyboardInterrupt):
+        test_raise_keyboardinterrupt()
+
+    assert runs[0] == interrupt
+
+
+def test_keyboardinterrupt_in_strategy_no_rerun():
+    runs = [0]
+    interrupt = 3
+
+    @composite
+    def interrupt_eventually(draw):
+        runs[0] += 1
+        if runs[0] == interrupt:
+            # import pdb; pdb.set_trace()
+            raise KeyboardInterrupt
+        return draw(integers())
+
+    @given(interrupt_eventually())
+    def test_do_nothing(x):
+        pass
+
+    with pytest.raises(KeyboardInterrupt):
+        test_do_nothing()
+
+    assert runs[0] == interrupt
+
+
+def test_systemexit_no_rerun():
path: hypothesis-python/tests/cover/test_baseexception.py
text: @user1:
Would it make sense to merge this with `test_keyboardinterrupt_no_rerun` using `pytest.mark.parametrize`?

@user2:
Makes sense to me - we could also test raising `SystemExit` from a strategy.

@author:
I'm not totally sure what behaviour we want from SystemExit, it's a fairly weird exception to ever raise; this was more relevant when I was worrying about "all' BaseExceptions.

@author:
Actually while I'm clear what KeyboardInterrupt should do I don't really have any idea what SystemExit or anything else should do. Right now SystemExit raised in the system under test propagates out through the `given` decorator and is caught further up; you don't get a falsifying example or a Flaky if it arises part of the time (as you would with ValueError. If raised in a strategy, SystemExit behaves like ValueError. I'll check in a version that documents what's going on now; maybe don't merge it until it's clear we're doing the right thing.

diff_hunk: @@ -0,0 +1,77 @@
+# coding=utf-8
+#
+# This file is part of Hypothesis, which may be found at
+# https://github.com/HypothesisWorks/hypothesis/
+#
+# Most of this work is copyright (C) 2013-2019 David R. MacIver
+# (david@drmaciver.com), but it contains contributions by others. See
+# CONTRIBUTING.rst for a full list of people who may hold copyright, and
+# consult the git log if you need to determine who owns an individual
+# contribution.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public License,
+# v. 2.0. If a copy of the MPL was not distributed with this file, You can
+# obtain one at https://mozilla.org/MPL/2.0/.
+#
+# END HEADER
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+from hypothesis import given
+from hypothesis.strategies import composite, integers
+
+
+def test_keyboardinterrupt_no_rerun():
+    runs = [0]
+    interrupt = 3
+
+    @given(integers())
+    def test_raise_keyboardinterrupt(x):
+        runs[0] += 1
+        if runs[0] == interrupt:
+            raise KeyboardInterrupt
+
+    with pytest.raises(KeyboardInterrupt):
+        test_raise_keyboardinterrupt()
+
+    assert runs[0] == interrupt
+
+
+def test_keyboardinterrupt_in_strategy_no_rerun():
+    runs = [0]
+    interrupt = 3
+
+    @composite
+    def interrupt_eventually(draw):
+        runs[0] += 1
+        if runs[0] == interrupt:
+            # import pdb; pdb.set_trace()
path: hypothesis-python/tests/cover/test_baseexception.py
text: @user1:
Leftover debugging material?

@author:
oops, sorry