Skip to content

Commit 3154fb3

Browse files
authored
Merge pull request #4353 from tybug/refactor
Improve ast performance and refactor some code
2 parents decd12a + e9a3f90 commit 3154fb3

File tree

9 files changed

+59
-57
lines changed

9 files changed

+59
-57
lines changed

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ jobs:
252252
pyodide xbuildenv install $PYODIDE_VERSION
253253
- name: Set up Pyodide venv and install dependencies
254254
run: |
255-
pip install --upgrade setuptools pip wheel==0.45.1 build
255+
pip install --upgrade setuptools pip wheel build
256256
python -m build --wheel hypothesis-python --outdir dist/
257257
pip download --dest=dist/ hypothesis-python/ pytest tzdata # fetch all the wheels
258258

hypothesis-python/RELEASE.rst

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
RELEASE_TYPE: patch
2+
3+
Refactor some internals.

hypothesis-python/src/hypothesis/control.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,11 @@ def __init__(
132132
data: ConjectureData,
133133
*,
134134
is_final: bool = False,
135-
close_on_capture: bool = True,
136135
) -> None:
137136
self.data = data
138137
self.tasks: list[Callable[[], Any]] = []
139138
self.is_final = is_final
140-
self.close_on_capture = close_on_capture
141-
self.close_on_del = False
139+
142140
# Use defaultdict(list) here to handle the possibility of having multiple
143141
# functions registered for the same object (due to caching, small ints, etc).
144142
# The printer will discard duplicates which return different representations.

hypothesis-python/src/hypothesis/core.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -1010,16 +1010,18 @@ def run(data):
10101010

10111011
# self.test_runner can include the execute_example method, or setup/teardown
10121012
# _example, so it's important to get the PRNG and build context in place first.
1013-
with local_settings(self.settings):
1014-
with deterministic_PRNG():
1015-
with BuildContext(data, is_final=is_final) as context:
1016-
# providers may throw in per_case_context_fn, and we'd like
1017-
# `result` to still be set in these cases.
1018-
result = None
1019-
with data.provider.per_test_case_context_manager():
1020-
# Run the test function once, via the executor hook.
1021-
# In most cases this will delegate straight to `run(data)`.
1022-
result = self.test_runner(data, run)
1013+
with (
1014+
local_settings(self.settings),
1015+
deterministic_PRNG(),
1016+
BuildContext(data, is_final=is_final) as context,
1017+
):
1018+
# providers may throw in per_case_context_fn, and we'd like
1019+
# `result` to still be set in these cases.
1020+
result = None
1021+
with data.provider.per_test_case_context_manager():
1022+
# Run the test function once, via the executor hook.
1023+
# In most cases this will delegate straight to `run(data)`.
1024+
result = self.test_runner(data, run)
10231025

10241026
# If a failure was expected, it should have been raised already, so
10251027
# instead raise an appropriate diagnostic error.

hypothesis-python/src/hypothesis/internal/conjecture/choice.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,11 @@ def choice_permitted(choice: ChoiceT, constraints: ChoiceConstraintsT) -> bool:
540540
constraints = cast(FloatConstraints, constraints)
541541
if math.isnan(choice):
542542
return constraints["allow_nan"]
543-
return (
544-
sign_aware_lte(constraints["min_value"], choice)
545-
and sign_aware_lte(choice, constraints["max_value"])
546-
) and not (0 < abs(choice) < constraints["smallest_nonzero_magnitude"])
543+
if 0 < abs(choice) < constraints["smallest_nonzero_magnitude"]:
544+
return False
545+
return sign_aware_lte(constraints["min_value"], choice) and sign_aware_lte(
546+
choice, constraints["max_value"]
547+
)
547548
elif isinstance(choice, str):
548549
constraints = cast(StringConstraints, constraints)
549550
if len(choice) < constraints["min_size"]:

hypothesis-python/src/hypothesis/internal/constants_ast.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
if TYPE_CHECKING:
2424
from typing import TypeAlias
2525

26-
ConstantT: "TypeAlias" = Union[int, float, bool, bytes, str]
26+
ConstantT: "TypeAlias" = Union[int, float, bytes, str]
2727

2828

2929
class ConstantVisitor(NodeVisitor):
@@ -103,12 +103,20 @@ def _module_ast(module: ModuleType) -> Optional[AST]:
103103
def local_modules() -> tuple[ModuleType, ...]:
104104
modules = []
105105
for module in sys.modules.values():
106-
if not hasattr(module, "__file__"):
107-
continue
108-
if module.__file__ is None: # pragma: no cover
109-
continue
110-
111-
if ModuleLocation.from_path(module.__file__) is not ModuleLocation.LOCAL:
106+
if (
107+
not hasattr(module, "__file__")
108+
or module.__file__ is None
109+
# Skip expensive path lookup for stdlib modules.
110+
# This will cause false negatives if a user names their module the
111+
# same as a stdlib module.
112+
#
113+
# sys.stdlib_module_names is new in 3.10
114+
or (
115+
sys.version_info >= (3, 10)
116+
and module.__name__ in sys.stdlib_module_names
117+
)
118+
or ModuleLocation.from_path(module.__file__) is not ModuleLocation.LOCAL
119+
):
112120
continue
113121

114122
modules.append(module)

hypothesis-python/src/hypothesis/internal/floats.py

+10-21
Original file line numberDiff line numberDiff line change
@@ -139,41 +139,30 @@ def next_up_normal(value: float, width: int, *, allow_subnormal: bool) -> float:
139139
mantissa_mask = (1 << 52) - 1
140140

141141

142-
def float_permitted(
143-
f: float,
144-
*,
145-
min_value: float,
146-
max_value: float,
147-
allow_nan: bool,
148-
smallest_nonzero_magnitude: float,
149-
) -> bool:
150-
if math.isnan(f):
151-
return allow_nan
152-
if 0 < abs(f) < smallest_nonzero_magnitude:
153-
return False
154-
return sign_aware_lte(min_value, f) and sign_aware_lte(f, max_value)
155-
156-
157142
def make_float_clamper(
158143
min_value: float,
159144
max_value: float,
160145
*,
161-
smallest_nonzero_magnitude: float,
162146
allow_nan: bool,
147+
smallest_nonzero_magnitude: float,
163148
) -> Callable[[float], float]:
164149
"""
165150
Return a function that clamps positive floats into the given bounds.
166151
"""
152+
from hypothesis.internal.conjecture.choice import choice_permitted
153+
167154
assert sign_aware_lte(min_value, max_value)
168155
range_size = min(max_value - min_value, float_info.max)
169156

170157
def float_clamper(f: float) -> float:
171-
if float_permitted(
158+
if choice_permitted(
172159
f,
173-
min_value=min_value,
174-
max_value=max_value,
175-
allow_nan=allow_nan,
176-
smallest_nonzero_magnitude=smallest_nonzero_magnitude,
160+
{
161+
"min_value": min_value,
162+
"max_value": max_value,
163+
"allow_nan": allow_nan,
164+
"smallest_nonzero_magnitude": smallest_nonzero_magnitude,
165+
},
177166
):
178167
return f
179168
# Outside bounds; pick a new value, sampled from the allowed range,

hypothesis-python/src/hypothesis/internal/scrutineer.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,14 @@ def get_explaining_locations(traces):
217217

218218
# see e.g. https://docs.python.org/3/library/sysconfig.html#posix-user
219219
# for examples of these path schemes
220-
STDLIB_DIRS = [
220+
STDLIB_DIRS = {
221221
Path(sysconfig.get_path("platstdlib")).resolve(),
222222
Path(sysconfig.get_path("stdlib")).resolve(),
223-
]
224-
SITE_PACKAGES_DIRS = [
223+
}
224+
SITE_PACKAGES_DIRS = {
225225
Path(sysconfig.get_path("purelib")).resolve(),
226226
Path(sysconfig.get_path("platlib")).resolve(),
227-
]
227+
}
228228

229229
EXPLANATION_STUB = (
230230
"Explanation:",

hypothesis-python/tests/cover/test_float_utils.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
import pytest
1515

1616
from hypothesis import example, given, strategies as st
17-
from hypothesis.internal.conjecture.choice import choice_equal
17+
from hypothesis.internal.conjecture.choice import choice_equal, choice_permitted
1818
from hypothesis.internal.floats import (
1919
count_between_floats,
20-
float_permitted,
2120
make_float_clamper,
2221
next_down,
2322
next_up,
@@ -96,11 +95,13 @@ def test_float_clamper(constraints, input_value):
9695

9796
# if input_value was permitted in the first place, then the clamped value should
9897
# be the same as the input value.
99-
if float_permitted(
98+
if choice_permitted(
10099
input_value,
101-
min_value=min_value,
102-
max_value=max_value,
103-
allow_nan=allow_nan,
104-
smallest_nonzero_magnitude=smallest_nonzero_magnitude,
100+
{
101+
"min_value": min_value,
102+
"max_value": max_value,
103+
"allow_nan": allow_nan,
104+
"smallest_nonzero_magnitude": smallest_nonzero_magnitude,
105+
},
105106
):
106107
assert choice_equal(input_value, clamped)

0 commit comments

Comments
 (0)