On Mon, Aug 16, 2010 at 01:29:13PM +0200, Ronny Pfannschmidt wrote:
> On Mon, 2010-08-16 at 01:25 +0100, Floris Bruynooghe wrote:
> > The attached patch makes compare equal a special case and checks if
> > the two arguments to it are both a list, text or dict and tries to
> > generate a nicer explanation text for them. The patch is more like a
> > proof of concept then a final implementation, I may have done some
> > very strange or silly things as I'm not familiar with the code. It
> > would be great to get feedback, both on the general concept and the
> > actual implementation (particularly note the way I had to hack
> > _format_explanation() in assertion.py).
>
> I think it will be helpful to have some kind of hook to add more
> explain-functions
Adding hooks should be possible, looking at all the .visit_*()
functions it would seem only one hook is required, unless separate
hooks for each rich compare operator are deemed useful.
The trickiest bit I think is how to produce multiline explanations.
_format_explanation() concatenates all newlines. Having only special
cases for \n{ and \n} which is used by .visit_Call() to force nested
and indented newlines. In the patch I added \n== for this but a more
general one is probably required, something like \n> or \n~ could work
I guess. This could be completely hidden from the hook however, by
returning a list for each line to be printed, the caller of the hook
would then join these up correctly so that _format_explanation() will
add newlines and indentation correctly. A possible api for the hook
could be:
def pytest_assert_compare(op, left, right, left_repr, right_repr):
"""Customise compare
Return None for no custom compare, otherwise return a list of
strings. The strings will be joined by newlines but any newlines
*in* a string will be escaped.
"""
pass
I guess the reprs are not really necessary if there's an easy way to
make them. It's just that I used them in my original patch.
Another option is to encapsulate the arguments into an object that
also knows how the builtin types and operators are compared, something
like:
class CompareItem(object):
def __init__(self, op, left, right, ...):
self.op = op
self.left = left
self.right = right
...
def default(self):
if type(self.left) != type(self.right):
return None
if self.op == '==':
if isinstance(self.left, (list, tuple)):
return self.sequence_equal()
elif isinstance(self.left, basestring):
return self.string_equal()
...
elif self.op == '!=':
...
def sequence_equal(self):
pass
def string_equal(self):
pass
...
This would allow pytest_assert_compare() to use those methods as part
of the implementation.
There's also the question of who should truncate large amounts of data
(e.g. screenfulls of diffs): the hook itself, the caller of the hook
or _format_explanation()? Probably one of the first two to get rid of
the memory usage as soon as possible.
> In particular, cause there are many more build-in types to manage,
> and i have at least 2 projects where custom compare-explain is helpfull
>
> another wishlist item i see is the rest of rich compare
> i.e. <, >, <=, >=, !=
Sure, all builtin types and operators should ideally be supported by
default as best as possible. I just started with some I wanted most.
Regards
Floris
--
Debian GNU/Linux -- The Power of Freedom
www.debian.org | www.gnu.org | www.kernel.org
_______________________________________________
py-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/py-dev