-
-
Notifications
You must be signed in to change notification settings - Fork 32.7k
Closed as not planned
Closed as not planned
Copy link
Labels
topic-free-threadingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Bug report
Bug description:
I bisected and this is a regression that was introduced by 7ccacb2.
Steps to reproduce:
- Clone numpy and cython repositories
- Build python
main
branch with--disable-gil
- Install numpy dependencies, build numpy, and run the full numpy test suite:
cd /path/to/numpy
python -m pip install setuptools ninja meson-python pytest hypothesis spin /path/to/cython
spin build --clean
spin test -- -x
On my machine, this very quickly exits with the following test failure:
_______________________________________________________________________________ TestArray2String.test_any_text _______________________________________________________________________________
self = <hypothesis.core.StateForActualGivenExecution object at 0x4ecdebabd10>, data = ConjectureData(OVERRUN, 0 bytes, frozen)
with local_settings(self.settings):
with deterministic_PRNG():
with BuildContext(data, is_final=is_final) as context:
# providers may throw in per_case_context_fn, and we'd like
# `result` to still be set in these cases.
result = None
with data.provider.per_test_case_context_manager():
# Run the test function once, via the executor hook.
# In most cases this will delegate straight to `run(data)`.
> result = self.test_runner(data, run)
context = <hypothesis.control.BuildContext object at 0x4ecdeba9910>
data = ConjectureData(OVERRUN, 0 bytes, frozen)
example_kwargs = None
expected_failure = (HypothesisWarning('It looks like `register_random` was passed an object that could be garbage collected immediately a...a62810>\n\n../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/entropy.py:132: HypothesisWarning\n')
is_final = True
print_example = True
result = None
run = <function StateForActualGivenExecution.execute_once.<locals>.run at 0x4ecdf7042e0>
self = <hypothesis.core.StateForActualGivenExecution object at 0x4ecdebabd10>
test = <function TestArray2String.test_any_text at 0x4ecd055f640>
text_repr = None
../../../../../../hypothesis/hypothesis-python/src/hypothesis/core.py:951:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../../../../hypothesis/hypothesis-python/src/hypothesis/core.py:739: in default_executor
return function(data)
data = ConjectureData(OVERRUN, 0 bytes, frozen)
function = <function StateForActualGivenExecution.execute_once.<locals>.run at 0x4ecdf7042e0>
../../../../../../hypothesis/hypothesis-python/src/hypothesis/core.py:862: in run
kw, argslices = context.prep_args_kwargs_from_strategies(
args = ()
context = <hypothesis.control.BuildContext object at 0x4ecdeba9910>
data = ConjectureData(OVERRUN, 0 bytes, frozen)
example_kwargs = None
expected_failure = (HypothesisWarning('It looks like `register_random` was passed an object that could be garbage collected immediately a...a62810>\n\n../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/entropy.py:132: HypothesisWarning\n')
kwargs = {'self': <numpy._core.tests.test_arrayprint.TestArray2String object at 0x4ecd0cf0610>}
print_example = True
self = <hypothesis.core.StateForActualGivenExecution object at 0x4ecdebabd10>
test = <function TestArray2String.test_any_text at 0x4ecd055f640>
text_repr = None
../../../../../../hypothesis/hypothesis-python/src/hypothesis/control.py:157: in prep_args_kwargs_from_strategies
obj = check(self.data.draw(s, observe_as=f"generate:{k}"))
arg_labels = {}
check = <hypothesis.control._Checker object at 0x4ecdebacc10>
k = 'text'
kwarg_strategies = {'text': from_dtype(dtype('<U'))}
kwargs = {}
s = from_dtype(dtype('<U'))
self = <hypothesis.control.BuildContext object at 0x4ecdeba9910>
start_idx = 0
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2387: in draw
return strategy.do_draw(self)
at_top_level = True
key = 'generate:text'
label = 7273923036097914769
observe_as = 'generate:text'
self = ConjectureData(OVERRUN, 0 bytes, frozen)
start_time = 6066655.102763833
strategy = from_dtype(dtype('<U'))
../../../../../../hypothesis/hypothesis-python/src/hypothesis/strategies/_internal/lazy.py:167: in do_draw
return data.draw(self.wrapped_strategy)
data = ConjectureData(OVERRUN, 0 bytes, frozen)
self = from_dtype(dtype('<U'))
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2381: in draw
return strategy.do_draw(self)
at_top_level = False
label = 7273923036097914769
observe_as = None
self = ConjectureData(OVERRUN, 0 bytes, frozen)
start_time = None
strategy = text(alphabet=characters()).filter(lambda b: b[-1:] != "\0").map(str_)
../../../../../../hypothesis/hypothesis-python/src/hypothesis/strategies/_internal/lazy.py:167: in do_draw
return data.draw(self.wrapped_strategy)
data = ConjectureData(OVERRUN, 0 bytes, frozen)
self = text(alphabet=characters()).filter(lambda b: b[-1:] != "\0").map(str_)
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2381: in draw
return strategy.do_draw(self)
at_top_level = False
label = 7273923036097914769
observe_as = None
self = ConjectureData(OVERRUN, 0 bytes, frozen)
start_time = None
strategy = text().filter(lambda b: b[-1:] != "\0").map(str_)
../../../../../../hypothesis/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py:843: in do_draw
x = data.draw(self.mapped_strategy)
_ = 0
data = ConjectureData(OVERRUN, 0 bytes, frozen)
self = text().filter(lambda b: b[-1:] != "\0").map(str_)
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2381: in draw
return strategy.do_draw(self)
at_top_level = False
label = 10358930435738099914
observe_as = None
self = ConjectureData(OVERRUN, 0 bytes, frozen)
start_time = None
strategy = text().filter(lambda b: b[-1:] != "\0")
../../../../../../hypothesis/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py:1006: in do_draw
result = self.do_filtered_draw(data)
data = ConjectureData(OVERRUN, 0 bytes, frozen)
self = text().filter(lambda b: b[-1:] != "\0")
../../../../../../hypothesis/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py:1016: in do_filtered_draw
value = data.draw(self.filtered_strategy)
data = ConjectureData(OVERRUN, 0 bytes, frozen)
i = 0
self = text().filter(lambda b: b[-1:] != "\0")
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2381: in draw
return strategy.do_draw(self)
at_top_level = False
label = 13472932985108582247
observe_as = None
self = ConjectureData(OVERRUN, 0 bytes, frozen)
start_time = None
strategy = text()
../../../../../../hypothesis/hypothesis-python/src/hypothesis/strategies/_internal/strings.py:117: in do_draw
return data.draw_string(
__class__ = <class 'hypothesis.strategies._internal.strings.TextStrategy'>
data = ConjectureData(OVERRUN, 0 bytes, frozen)
elems = characters()
self = text()
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2162: in draw_string
value = self.provider.draw_string(
fake_forced = False
forced = None
intervals = IntervalSet(((0, 1114111),))
kwargs = {'intervals': IntervalSet(((0, 1114111),)), 'max_size': inf, 'min_size': 0}
max_size = inf
min_size = 0
observe = True
self = ConjectureData(OVERRUN, 0 bytes, frozen)
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:1562: in draw_string
while elements.more():
average_size = 5
chars = []
elements = <hypothesis.internal.conjecture.utils.many object at 0x4ecdebacd90>
fake_forced = False
forced = None
intervals = IntervalSet(((0, 1114111),))
max_size = inf
min_size = 0
self = <hypothesis.internal.conjecture.data.HypothesisProvider object at 0x4ecdf608210>
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/utils.py:283: in more
should_continue = self.data.draw_boolean(
forced_result = None
self = <hypothesis.internal.conjecture.utils.many object at 0x4ecdebacd90>
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2240: in draw_boolean
value = self.provider.draw_boolean(
fake_forced = False
forced = None
kwargs = {'p': 0.8333333333333334}
observe = False
p = 0.8333333333333334
self = ConjectureData(OVERRUN, 0 bytes, frozen)
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:1326: in draw_boolean
i = self._cd.draw_bits(
bits = 3
fake_forced = False
falsey = 1
forced = None
p = 0.8333333333333334
partial = True
remainder = 0.666666666666667
self = <hypothesis.internal.conjecture.data.HypothesisProvider object at 0x4ecdf608210>
size = 8
truthy = 6
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2510: in draw_bits
self.__check_capacity(n_bytes)
fake_forced = False
forced = None
n = 3
n_bytes = 1
self = ConjectureData(OVERRUN, 0 bytes, frozen)
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2552: in __check_capacity
self.mark_overrun()
n = 1
self = ConjectureData(OVERRUN, 0 bytes, frozen)
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2577: in mark_overrun
self.conclude_test(Status.OVERRUN)
self = ConjectureData(OVERRUN, 0 bytes, frozen)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = ConjectureData(OVERRUN, 0 bytes, frozen), status = Status.OVERRUN, interesting_origin = None
def conclude_test(
self,
status: Status,
interesting_origin: Optional[InterestingOrigin] = None,
) -> NoReturn:
assert (interesting_origin is None) or (status == Status.INTERESTING)
self.__assert_not_frozen("conclude_test")
self.interesting_origin = interesting_origin
self.status = status
self.freeze()
> raise StopTest(self.testcounter)
E hypothesis.errors.StopTest: 2
interesting_origin = None
self = ConjectureData(OVERRUN, 0 bytes, frozen)
status = Status.OVERRUN
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/conjecture/data.py:2564: StopTest
The above exception was the direct cause of the following exception:
self = <numpy._core.tests.test_arrayprint.TestArray2String object at 0x4ecd0cf0610>
@given(hynp.from_dtype(np.dtype("U")))
> def test_any_text(self, text):
f = <function given.<locals>.run_test_as_given.<locals>.wrapped_test at 0x4ecd3035aa0>
self = <numpy._core.tests.test_arrayprint.TestArray2String object at 0x4ecd0cf0610>
numpy/_core/tests/test_arrayprint.py:504:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
errors_to_report = [(["\nYou can reproduce this example by temporarily adding @reproduce_failure('6.100.2', b'AA==') as a decorator on your test case"], Flaky('Unreliable assumption: An example which satisfied assumptions on the first run now fails it.'))]
settings = settings(database=None, deadline=None, derandomize=True, max_examples=100, phases=(Phase.explicit, Phase.reuse, Phase.....large_base_example, HealthCheck.function_scoped_fixture, HealthCheck.differing_executors], verbosity=Verbosity.normal)
target_lines = [], trailer = ''
def _raise_to_user(errors_to_report, settings, target_lines, trailer=""):
"""Helper function for attaching notes and grouping multiple errors."""
failing_prefix = "Falsifying example: "
ls = []
for fragments, err in errors_to_report:
for note in fragments:
add_note(err, note)
if note.startswith(failing_prefix):
ls.append(note[len(failing_prefix) :])
if current_pytest_item.value:
current_pytest_item.value._hypothesis_failing_examples = ls
if len(errors_to_report) == 1:
_, the_error_hypothesis_found = errors_to_report[0]
else:
assert errors_to_report
the_error_hypothesis_found = BaseExceptionGroup(
f"Hypothesis found {len(errors_to_report)} distinct failures{trailer}.",
[e for _, e in errors_to_report],
)
if settings.verbosity >= Verbosity.normal:
for line in target_lines:
add_note(the_error_hypothesis_found, line)
> raise the_error_hypothesis_found
E hypothesis.errors.Flaky: Unreliable assumption: An example which satisfied assumptions on the first run now fails it.
E
E You can reproduce this example by temporarily adding @reproduce_failure('6.100.2', b'AA==') as a decorator on your test case
_ = ["\nYou can reproduce this example by temporarily adding @reproduce_failure('6.100.2', b'AA==') as a decorator on your test case"]
err = Flaky('Unreliable assumption: An example which satisfied assumptions on the first run now fails it.')
errors_to_report = [(["\nYou can reproduce this example by temporarily adding @reproduce_failure('6.100.2', b'AA==') as a decorator on your test case"], Flaky('Unreliable assumption: An example which satisfied assumptions on the first run now fails it.'))]
failing_prefix = 'Falsifying example: '
fragments = ["\nYou can reproduce this example by temporarily adding @reproduce_failure('6.100.2', b'AA==') as a decorator on your test case"]
ls = []
note = "\nYou can reproduce this example by temporarily adding @reproduce_failure('6.100.2', b'AA==') as a decorator on your test case"
settings = settings(database=None, deadline=None, derandomize=True, max_examples=100, phases=(Phase.explicit, Phase.reuse, Phase.....large_base_example, HealthCheck.function_scoped_fixture, HealthCheck.differing_executors], verbosity=Verbosity.normal)
target_lines = []
the_error_hypothesis_found = Flaky('Unreliable assumption: An example which satisfied assumptions on the first run now fails it.')
trailer = ''
../../../../../../hypothesis/hypothesis-python/src/hypothesis/core.py:1286: Flaky
If I add the reproduce_failure
decorator suggested by hypothesis, I get:
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/entropy.py:195: in deterministic_PRNG
register_random(hypothesis.core._hypothesis_global_random)
seed = 0
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
r = <random.Random object at 0x2a09af82810>
if not (PYPY or GRAALPY): # pragma: no branch
# PYPY and GRAALPY do not have `sys.getrefcount`
gc.collect()
if not gc.get_referrers(r):
breakpoint()
if sys.getrefcount(r) <= _PLATFORM_REF_COUNT:
raise ReferenceError(
f"`register_random` was passed `r={r}` which will be "
"garbage collected immediately after `register_random` creates a "
"weakref to it. This will prevent Hypothesis from managing this "
"PRNG. See the docs for `register_random` for more "
"details."
)
else:
> warnings.warn(
"It looks like `register_random` was passed an object that could "
"be garbage collected immediately after `register_random` creates "
"a weakref to it. This will prevent Hypothesis from managing this "
"PRNG. See the docs for `register_random` for more details.",
HypothesisWarning,
stacklevel=2,
)
E hypothesis.errors.HypothesisWarning: It looks like `register_random` was passed an object that could be garbage collected immediately after `register_random` creates a weakref to it. This will prevent Hypothesis from managing this PRNG. See the docs for `register_random` for more details.
r = <random.Random object at 0x2a09af82810>
../../../../../../hypothesis/hypothesis-python/src/hypothesis/internal/entropy.py:132: HypothesisWarning
This check in hypothesis uses gc.get_referrers()
to avoid adding objects that would be immediately GC'd to a weak value dict.
If I insert a breakpoint right after the gc.get_referrers()
call in hypothesis and check sys.getrefcount(r)
, I get:
(Pdb) sys.getrefcount(r)
4
(Pdb) gc.get_referrers(r)
[{'r': <random.Random object at 0x4487ef82810>}]
And r
is a valid random.Random
object:
(Pdb) p r
<random.Random object at 0x45c54f82810>
(Pdb) r.randbytes(10)
b'7K\xb3\xb4\xd9\x8d\x10\xb9i\xfa'
Also worth noting: It only happens if I run the full numpy test suite. If I run just this one test or all the tests in test_array_print
, it passes.
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Metadata
Metadata
Assignees
Labels
topic-free-threadingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error