CrossHair icon indicating copy to clipboard operation
CrossHair copied to clipboard

Support multiple contract syntaxes

Open dhouck opened this issue 5 years ago • 3 comments

Is your feature request related to a problem? Please describe. There are multiple runtime DBC packages for Python (e.g., PyContracts, dpcontracts, icontract, …). It would be nice to be able to use the same contracts for runtime checking with one of these tools, and compile-time checking with CrossHair.

Describe the solution you'd like Being able to tell when one of these packages is imported and reading their annotations would probably be simplest. I don’t know how decorated functions are currently handled, but it might also be simpler than trying to statically analyze the functions those decorators return.

Describe alternatives you've considered CrossHair could either support runtime checking on its own, or it could have a decorator that reads the docstring and applied the relevant decorators from one of these other systems. Both of these sound more complicated than my proposed solution, and they are less compatible with existing runtime-checked contracts.

dhouck avatar Feb 19 '20 00:02 dhouck

Love this idea.

And it might not be all that difficult to do; the stuff we'd need to change is relatively well encapsulated in get_fn_conditions and get_class_conditions in condition_parser.py. There are some details to consider, however, like whether it's ok for exceptions can be thrown and what kind of copy happens for previous/old value comparisons. I think class invariants also have some subtle behaviors that might vary between contract implementations.

If someone wanted to make this happen for their favorite syntax, I would be completely happy to shepherd it along.

Otherwise, internet, please post or thumbs-up your favorite tools: with enough votes, I could probably prioritize some of my own time to try and get an implementation out.

pschanely avatar Feb 19 '20 01:02 pschanely

You know what would be amazing? Symbolically executing tests written for Hypothesis! For example:

@given(st.integers(min_value=0))
def test(x):
    assert x ** 2 >= x

# could be equivalent to

def test(x: int):
    """pre: x >= 0"""
    assert x ** 2 >= x

this is particularly interesting to me because (a) I'm a core dev of Hypothesis 😜, (b) Hypothesis tests have to precisely describe the domain of valid inputs, and (c) they have a high density of assertions about error-prone behaviour!

I don't have time to write this myself (at least in the next few months), but would be delighted to help anyone who wants to have a go.

Zac-HD avatar Mar 11 '20 06:03 Zac-HD

An update: at present we support: PEP316, icontract, deal, an assert-based mode, and hypothesis. See these docs for details.

pschanely avatar Feb 24 '21 02:02 pschanely