Open PiotrZakrzewski opened 2 years ago
What a neat idea!
I'm also musing about a hybrid approach: if a good repr exists, it's nice to have something that's trivially copy+pasteable into an repl / debugger / unit test. Issue #48 is also a counterexample repr problem that might be influenced by our choices.
I will need to perform some experiments; depending on how rich.inspect
is implemented, some of the CrossHair smoke and mirrors for symbolic values might leak through. (either way, it's a good test) I'll have time in the next week to dig in.
Some exploration (and interesting CrossHair fixes related to rich
's dynamic imports) has happened. But there's a bit of an onion to unravel here: I'd like to make a few improvements along the way, so it'll take a while. More updates in a few weeks!
So this took me a few months to get to ... instead of a few weeks. But better late than never. As of 98ec6da735af699e6a729e2572baf56ac101473d, I've got something working: we output an eval()-able string that approximates the way we constructed the instance within CrossHair. This should remove the counterexample dependency on repr() for custom class instances.
This is an ~aggressively breaking change, and I'll want to poke at a few things before I cut a release ... but will update this issue again when that happens.
I just want to mention that I came across this "issue" when started playing with CrossHair 0.0.31, classes annotated with @dataclasses.dataclass are represented nicely when I output pytest tests, but once I get to custom classes I get something like mentioned here - object reference.
def test_myfunction():
assert myfunction(<concolic.intro.Counter object at 0x0000021928B99DD8>) == False
Oh, great - glad that multiple people are interested in this. Would y'all give 0.0.32 a try? It contains my changes to make this issue better.
Here is a trivial example that reports the counterexample even though the class doesn't define repr: https://crosshair-web.org/?crosshair=0.1&python=3.8&gist=ea119ca6c87f9d92a6d75f58fad24898
The one thing I can say about provided counterexample is that object attribute values are not mentioned by their names, but generally good direction.
/tmp/main.py:12: error: false when calling process(Foo(0, 0)) (which returns (0, 0))
The one thing I can say about provided counterexample is that object attribute values are not mentioned by their names, but generally good direction.
/tmp/main.py:12: error: false when calling process(Foo(0, 0)) (which returns (0, 0))
Ah, indeed. I'd point out that keyword-only arguments (those after the optional *,
marker) will be reported with a keyword. (like the "z" parameter in this example)
But the current behavior suppresses keywords when it can. This is something a matter of taste; I've made a poll in #180 - please vote!
Is your feature request related to a problem? Please describe. When working with class instances as function parameters counter examples provided on stdout of crosshair show str(object) which does not contain info about the value of fields of this counter example. It looks like this:
Describe the solution you'd like Using rich.inspect could allow for pretty printing objects even without custom
__repr__
see https://rich.readthedocs.io/en/stable/introduction.html Describe alternatives you've considered Add msg / or at least docs to inform user that implementing
__repr__
will improve their user experience?