hypothesis icon indicating copy to clipboard operation
hypothesis copied to clipboard

Teach `ghostwriter.equivalent` to handle positional-only params by position, not name

Open Zac-HD opened this issue 4 years ago • 0 comments

Consider the following example:

import math
from hypothesis.extra.ghostwriter import equivalent

def gcd(a: int, b: int) -> int:
    return math.gcd(a, b)

print(equivalent(gcd, math.gcd))
@given(a=st.integers(), b=st.integers(), x=st.nothing(), y=st.nothing())
def test_equivalent_gcd_gcd(a, b, x, y):
    result_0_gcd = test_expected_output.gcd(a=a, b=b)
    result_1_gcd = math.gcd(x, y)
    assert result_0_gcd == result_1_gcd, (result_0_gcd, result_1_gcd)

This is kinda silly: the Ghostwriter treats math.gcd(x, y, /) as if the argument names are meaningful! We wanted:

@given(a=st.integers(), b=st.integers())
def test_equivalent_gcd_gcd(a, b):
    result_0_gcd = test_expected_output.gcd(a=a, b=b)
    result_1_gcd = math.gcd(a, b)
    assert result_0_gcd == result_1_gcd, (result_0_gcd, result_1_gcd)

The solution is going to involve expanding _make_equiv_body. Rough notes: get given_args in _make_equiv_body; use write_call with passed variable names for posonly arguments; prefer pos-or-kw names then kwonly names then pos-only names as successive fallbacks. very rough start: https://github.com/HypothesisWorks/hypothesis/compare/master...Zac-HD:hypothesis:posonly-eqiv-ghostwriter

Other ideas: sort equivalent funcs by qualname, for stable output under shouldn't-matter changes of ordering; use module name instead of index to distinguish function results; add a did-you-mean if one func is actually a module (or look up matching functions on it? also works for two modules...).

Zac-HD avatar Feb 08 '21 13:02 Zac-HD