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 py-dev@codespeak.net http://codespeak.net/mailman/listinfo/py-dev