diff --git a/hypothesis-python/docs/changes.rst b/hypothesis-python/docs/changes.rst index 660090496c..2ba6a8f518 100644 --- a/hypothesis-python/docs/changes.rst +++ b/hypothesis-python/docs/changes.rst @@ -18,6 +18,37 @@ Hypothesis 6.x .. include:: ../RELEASE.rst +.. _v6.92.5: + +------------------- +6.92.5 - 2024-01-08 +------------------- + +This patch registers explicit strategies for a handful of builtin types, +motivated by improved introspection in PyPy 7.3.14 triggering existing +internal warnings. +Thanks to Carl Friedrich Bolz-Tereick for helping us work out what changed! + +.. _v6.92.4: + +------------------- +6.92.4 - 2024-01-08 +------------------- + +This patch fixes an error when writing :doc:`observability ` reports without a pre-existing ``.hypothesis`` directory. + +.. _v6.92.3: + +------------------- +6.92.3 - 2024-01-08 +------------------- + +This patch adds a new environment variable ``HYPOTHESIS_EXPERIMENTAL_OBSERVABILITY_NOCOVER``, +which turns on :doc:`observability ` data collection without collecting +code coverage data, which may be faster on Python 3.11 and earlier. + +Thanks to Harrison Goldstein for reporting and fixing :issue:`3821`. + .. _v6.92.2: ------------------- diff --git a/hypothesis-python/docs/observability.rst b/hypothesis-python/docs/observability.rst index 4d0493c20d..ea417f9680 100644 --- a/hypothesis-python/docs/observability.rst +++ b/hypothesis-python/docs/observability.rst @@ -44,6 +44,10 @@ or by using the :pypi:`sqlite-utils` and :pypi:`datasette` libraries:: sqlite-utils insert testcases.db testcases .hypothesis/observed/*_testcases.jsonl --nl --flatten datasette serve testcases.db +If you are experiencing a significant slow-down, you can try setting +``HYPOTHESIS_EXPERIMENTAL_OBSERVABILITY_NOCOVER`` instead; this will disable coverage information +collection. This should not be necessary on Python 3.12 or later. + Collecting more information --------------------------- diff --git a/hypothesis-python/setup.py b/hypothesis-python/setup.py index d4054fd5af..a668b76531 100644 --- a/hypothesis-python/setup.py +++ b/hypothesis-python/setup.py @@ -63,7 +63,7 @@ def local_file(name): # zoneinfo is an odd one: every dependency is conditional, because they're # only necessary on old versions of Python or Windows systems. "zoneinfo": [ - "tzdata>=2023.3 ; sys_platform == 'win32'", + "tzdata>=2023.4 ; sys_platform == 'win32'", "backports.zoneinfo>=0.2.1 ; python_version<'3.9'", ], # We only support Django versions with upstream support - see diff --git a/hypothesis-python/src/hypothesis/core.py b/hypothesis-python/src/hypothesis/core.py index 82e359fc2f..ee9762525d 100644 --- a/hypothesis-python/src/hypothesis/core.py +++ b/hypothesis-python/src/hypothesis/core.py @@ -88,6 +88,7 @@ ) from hypothesis.internal.healthcheck import fail_health_check from hypothesis.internal.observability import ( + OBSERVABILITY_COLLECT_COVERAGE, TESTCASE_CALLBACKS, deliver_json_blob, make_testcase, @@ -968,7 +969,7 @@ def _execute_once_for_engine(self, data: ConjectureData) -> None: _can_trace = ( sys.gettrace() is None or sys.version_info[:2] >= (3, 12) ) and not PYPY - _trace_obs = TESTCASE_CALLBACKS + _trace_obs = TESTCASE_CALLBACKS and OBSERVABILITY_COLLECT_COVERAGE _trace_failure = ( self.failed_normally and not self.failed_due_to_deadline diff --git a/hypothesis-python/src/hypothesis/internal/observability.py b/hypothesis-python/src/hypothesis/internal/observability.py index 6752868737..0da4aca764 100644 --- a/hypothesis-python/src/hypothesis/internal/observability.py +++ b/hypothesis-python/src/hypothesis/internal/observability.py @@ -12,10 +12,13 @@ import json import os +import sys +import warnings from datetime import date, timedelta from typing import Callable, Dict, List, Optional from hypothesis.configuration import storage_directory +from hypothesis.errors import HypothesisWarning from hypothesis.internal.conjecture.data import ConjectureData, Status TESTCASE_CALLBACKS: List[Callable[[dict], None]] = [] @@ -76,13 +79,29 @@ def make_testcase( def _deliver_to_file(value): # pragma: no cover kind = "testcases" if value["type"] == "test_case" else "info" fname = storage_directory("observed", f"{date.today().isoformat()}_{kind}.jsonl") - fname.parent.mkdir(exist_ok=True) + fname.parent.mkdir(exist_ok=True, parents=True) _WROTE_TO.add(fname) with fname.open(mode="a") as f: f.write(json.dumps(value) + "\n") -if "HYPOTHESIS_EXPERIMENTAL_OBSERVABILITY" in os.environ: # pragma: no cover +OBSERVABILITY_COLLECT_COVERAGE = ( + "HYPOTHESIS_EXPERIMENTAL_OBSERVABILITY_NOCOVER" not in os.environ +) +if OBSERVABILITY_COLLECT_COVERAGE is False and sys.version_info[:2] >= ( + 3, + 12, +): # pragma: no cover + warnings.warn( + "Coverage data collection should be quite fast in Python 3.12 or later " + "so there should be no need to turn coverage reporting off.", + HypothesisWarning, + stacklevel=2, + ) +if ( + "HYPOTHESIS_EXPERIMENTAL_OBSERVABILITY" in os.environ + or OBSERVABILITY_COLLECT_COVERAGE is False +): # pragma: no cover TESTCASE_CALLBACKS.append(_deliver_to_file) # Remove files more than a week old, to cap the size on disk diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/core.py b/hypothesis-python/src/hypothesis/strategies/_internal/core.py index 03653c61e1..b3a558c306 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/core.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/core.py @@ -1438,7 +1438,7 @@ def from_type_guarded(thing): kwargs[k] = from_type_guarded(hints[k]) if p.default is not Parameter.empty and kwargs[k] is not ...: kwargs[k] = just(p.default) | kwargs[k] - if params and not kwargs: + if params and not kwargs and not issubclass(thing, BaseException): from_type_repr = repr_call(from_type, (thing,), {}) builds_repr = repr_call(builds, (thing,), {}) warnings.warn( diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/types.py b/hypothesis-python/src/hypothesis/strategies/_internal/types.py index aba2e457a0..d91102cb50 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/types.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/types.py @@ -625,17 +625,18 @@ def _networks(bits): BaseExceptionGroup: st.builds( BaseExceptionGroup, st.text(), - st.lists(st.from_type(BaseException), min_size=1), + st.lists(st.from_type(BaseException), min_size=1, max_size=5), ), ExceptionGroup: st.builds( ExceptionGroup, st.text(), - st.lists(st.from_type(Exception), min_size=1), + st.lists(st.from_type(Exception), min_size=1, max_size=5), ), enumerate: st.builds(enumerate, st.just(())), filter: st.builds(filter, st.just(lambda _: None), st.just(())), map: st.builds(map, st.just(lambda _: None), st.just(())), reversed: st.builds(reversed, st.just(())), + zip: st.builds(zip), # avoids warnings on PyPy 7.3.14+ property: st.builds(property, st.just(lambda _: None)), classmethod: st.builds(classmethod, st.just(lambda self: self)), staticmethod: st.builds(staticmethod, st.just(lambda self: self)), diff --git a/hypothesis-python/src/hypothesis/version.py b/hypothesis-python/src/hypothesis/version.py index 968da9a95e..15d22bf279 100644 --- a/hypothesis-python/src/hypothesis/version.py +++ b/hypothesis-python/src/hypothesis/version.py @@ -8,5 +8,5 @@ # 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/. -__version_info__ = (6, 92, 2) +__version_info__ = (6, 92, 5) __version__ = ".".join(map(str, __version_info__)) diff --git a/requirements/coverage.txt b/requirements/coverage.txt index 9ac3ca1c6e..d3f46edce6 100644 --- a/requirements/coverage.txt +++ b/requirements/coverage.txt @@ -8,7 +8,7 @@ annotated-types==0.6.0 # via -r requirements/coverage.in async-timeout==4.0.3 # via redis -attrs==23.1.0 +attrs==23.2.0 # via hypothesis (hypothesis-python/setup.py) black==23.12.1 # via -r requirements/coverage.in @@ -16,7 +16,7 @@ click==8.1.7 # via # -r requirements/coverage.in # black -coverage==7.3.4 +coverage==7.4.0 # via -r requirements/coverage.in dpcontracts==0.6.0 # via -r requirements/coverage.in @@ -38,7 +38,7 @@ mypy-extensions==1.0.0 # via # black # typing-inspect -numpy==1.26.2 +numpy==1.26.3 # via # -r requirements/coverage.in # pandas @@ -58,7 +58,7 @@ pluggy==1.3.0 # via pytest ptyprocess==0.7.0 # via pexpect -pytest==7.4.3 +pytest==7.4.4 # via # -r requirements/test.in # pytest-xdist @@ -94,5 +94,5 @@ typing-extensions==4.9.0 # typing-inspect typing-inspect==0.9.0 # via libcst -tzdata==2023.3 +tzdata==2023.4 # via pandas diff --git a/requirements/fuzzing.txt b/requirements/fuzzing.txt index a91c7abdca..6f484e3cdc 100644 --- a/requirements/fuzzing.txt +++ b/requirements/fuzzing.txt @@ -10,7 +10,7 @@ ansi2html==1.9.1 # via dash async-timeout==4.0.3 # via redis -attrs==23.1.0 +attrs==23.2.0 # via # hypothesis # hypothesis (hypothesis-python/setup.py) @@ -31,7 +31,7 @@ click==8.1.7 # black # flask # hypothesis -coverage==7.3.4 +coverage==7.4.0 # via # -r requirements/coverage.in # hypofuzz @@ -58,7 +58,7 @@ flask==3.0.0 # via dash hypofuzz==23.12.1 # via -r requirements/fuzzing.in -hypothesis[cli]==6.92.1 +hypothesis[cli]==6.92.2 # via # hypofuzz # hypothesis @@ -92,7 +92,7 @@ mypy-extensions==1.0.0 # typing-inspect nest-asyncio==1.5.8 # via dash -numpy==1.26.2 +numpy==1.26.3 # via # -r requirements/coverage.in # pandas @@ -121,7 +121,7 @@ ptyprocess==0.7.0 # via pexpect pygments==2.17.2 # via rich -pytest==7.4.3 +pytest==7.4.4 # via # -r requirements/test.in # hypofuzz @@ -172,7 +172,7 @@ typing-extensions==4.9.0 # typing-inspect typing-inspect==0.9.0 # via libcst -tzdata==2023.3 +tzdata==2023.4 # via pandas urllib3==2.1.0 # via requests diff --git a/requirements/test.txt b/requirements/test.txt index efea209a06..01d7e5d116 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -4,7 +4,7 @@ # # ./build.sh upgrade-requirements # -attrs==23.1.0 +attrs==23.2.0 # via hypothesis (hypothesis-python/setup.py) exceptiongroup==1.2.0 ; python_version < "3.11" # via @@ -22,7 +22,7 @@ pluggy==1.3.0 # via pytest ptyprocess==0.7.0 # via pexpect -pytest==7.4.3 +pytest==7.4.4 # via # -r requirements/test.in # pytest-xdist diff --git a/requirements/tools.txt b/requirements/tools.txt index 5f1643b847..c230369164 100644 --- a/requirements/tools.txt +++ b/requirements/tools.txt @@ -10,7 +10,7 @@ asgiref==3.7.2 # via django asttokens==2.4.1 # via stack-data -attrs==23.1.0 +attrs==23.2.0 # via hypothesis (hypothesis-python/setup.py) autoflake==2.2.1 # via shed @@ -42,7 +42,7 @@ colorama==0.4.6 # via tox com2ann==0.3.0 # via shed -coverage==7.3.4 +coverage==7.4.0 # via -r requirements/tools.in cryptography==41.0.7 # via @@ -53,7 +53,7 @@ decorator==5.1.1 # via ipython distlib==0.3.8 # via virtualenv -django==5.0 +django==5.0.1 # via -r requirements/tools.in docutils==0.20.1 # via @@ -165,7 +165,7 @@ pure-eval==0.2.2 # via stack-data pycparser==2.21 # via cffi -pyflakes==3.1.0 +pyflakes==3.2.0 # via autoflake pygments==2.17.2 # via @@ -177,9 +177,9 @@ pyproject-api==1.6.1 # via tox pyproject-hooks==1.0.0 # via build -pyright==1.1.342 +pyright==1.1.344 # via -r requirements/tools.in -pytest==7.4.3 +pytest==7.4.4 # via -r requirements/tools.in python-dateutil==2.8.2 # via -r requirements/tools.in @@ -206,7 +206,7 @@ rfc3986==2.0.0 # via twine rich==13.7.0 # via twine -ruff==0.1.9 +ruff==0.1.11 # via -r requirements/tools.in secretstorage==3.3.3 # via keyring @@ -279,7 +279,7 @@ tomli==2.0.1 # tox tox==4.11.4 # via -r requirements/tools.in -traitlets==5.14.0 +traitlets==5.14.1 # via # ipython # matplotlib-inline @@ -289,11 +289,11 @@ types-click==7.1.8 # via -r requirements/tools.in types-pkg-resources==0.1.3 # via -r requirements/tools.in -types-pyopenssl==23.3.0.0 +types-pyopenssl==23.3.0.20240106 # via types-redis types-pytz==2023.3.1.1 # via -r requirements/tools.in -types-redis==4.6.0.11 +types-redis==4.6.0.20240106 # via -r requirements/tools.in typing-extensions==4.9.0 # via @@ -311,7 +311,7 @@ urllib3==2.1.0 # twine virtualenv==20.25.0 # via tox -wcwidth==0.2.12 +wcwidth==0.2.13 # via prompt-toolkit wheel==0.42.0 # via pip-tools diff --git a/tooling/src/hypothesistooling/__main__.py b/tooling/src/hypothesistooling/__main__.py index fe1babe51d..9f66e4be06 100644 --- a/tooling/src/hypothesistooling/__main__.py +++ b/tooling/src/hypothesistooling/__main__.py @@ -396,8 +396,8 @@ def run_tox(task, version, *args): "3.12": "3.12.1", "3.13": "3.13.0a2", "pypy3.8": "pypy3.8-7.3.11", - "pypy3.9": "pypy3.9-7.3.13", - "pypy3.10": "pypy3.10-7.3.13", + "pypy3.9": "pypy3.9-7.3.14", + "pypy3.10": "pypy3.10-7.3.14", } ci_version = "3.10" # Keep this in sync with GH Actions main.yml and .readthedocs.yml