Skip to content

Commit b821528

Browse files
committed
Improve ghostwritten locations
1 parent 198badc commit b821528

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

hypothesis-python/RELEASE.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
RELEASE_TYPE: patch
2+
3+
This patch teaches the Ghostwriter an additional check for function
4+
and class locations that should make it use public APIs more often.

hypothesis-python/src/hypothesis/extra/ghostwriter.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -673,11 +673,25 @@ def _valid_syntax_repr(strategy):
673673
KNOWN_FUNCTION_LOCATIONS: Dict[object, str] = {}
674674

675675

676+
def _get_module_helper(obj):
677+
# Get the __module__ attribute of the object, and return the first ancestor module
678+
# which contains the object; falling back to the literal __module__ if none do.
679+
# The goal is to show location from which obj should usually be accessed, rather
680+
# than what we assume is an internal submodule which defined it.
681+
module_name = obj.__module__
682+
dots = [i for i, c in enumerate(module_name) if c == "."] + [None]
683+
for idx in dots:
684+
if getattr(sys.modules.get(module_name[:idx]), obj.__name__, None) is obj:
685+
KNOWN_FUNCTION_LOCATIONS[obj] = module_name[:idx]
686+
return module_name[:idx]
687+
return module_name
688+
689+
676690
def _get_module(obj):
677691
if obj in KNOWN_FUNCTION_LOCATIONS:
678692
return KNOWN_FUNCTION_LOCATIONS[obj]
679693
try:
680-
return obj.__module__
694+
return _get_module_helper(obj)
681695
except AttributeError:
682696
if not _is_probably_ufunc(obj):
683697
raise
@@ -936,7 +950,7 @@ def magic(
936950
functions.add(f)
937951
if getattr(thing, "__name__", None):
938952
if inspect.isclass(thing):
939-
KNOWN_FUNCTION_LOCATIONS[f] = thing.__module__
953+
KNOWN_FUNCTION_LOCATIONS[f] = _get_module_helper(thing)
940954
else:
941955
KNOWN_FUNCTION_LOCATIONS[f] = thing.__name__
942956
except (TypeError, ValueError):

hypothesis-python/tests/ghostwriter/test_ghostwriter.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import click
3838
import pytest
3939

40+
from hypothesis import assume
4041
from hypothesis.errors import InvalidArgument, Unsatisfiable
4142
from hypothesis.extra import cli, ghostwriter
4243
from hypothesis.internal.compat import BaseExceptionGroup
@@ -501,3 +502,7 @@ def test_obj_name(temp_script_file, temp_script_file_with_py_function):
501502
assert isinstance(
502503
cli.obj_name(str(temp_script_file_with_py_function)), FunctionType
503504
)
505+
506+
507+
def test_gets_public_location_not_impl_location():
508+
assert ghostwriter._get_module(assume) == "hypothesis" # not "hypothesis.control"

0 commit comments

Comments
 (0)