Hey Floris, all, 

On Wed, Sep 29, 2010 at 00:12 +0100, Floris Bruynooghe wrote:
> As Holger pointed out the following test hangs py.test in my assertion
> clone, it triggers a bug in difflib:
> 
> def test_hang_in_diff():
>     x = "1\n" * 1000 + "abc" + "2\n" * 1000
>     y = "1\n" * 1000 + "def" + "2\n" * 1000
>     assert x == y
> 
> It seems difflib can not deal with the 1000 identical trailing items.
>
> It fails with a TypeError somewhere very deep in a recursion or, when
> consuming the generator inside a list comprehension, just completely
> hangs.  Also before failing it considers all the 2s as different too.
> Rather then debugging difflib (there are several possible bugs on
> bugs.python.org which might relate to this) I've come up with some
> code that does produce this instead:
> 
> ______________________________ test_hang_in_diff 
> _______________________________
> /tmp/sandbox/test_bugs.py:4: in test_hang_in_diff
> >       assert x == y
> E       assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == 
> '1\n1\n1\n1\n...n2\n2\n2\n2\n'
> E         Skipping 1990 identical leading characters in diff
> E         Skipping 1991 identical trailing characters in diff
> E           1
> E           1
> E           1
> E           1
> E           1
> E         - abc2
> E         + def2
> E           2
> E           2
> E           2
> E           2


looks good to me!


 
> Another solution is to use context_diff() which does not have this
> problem, but for some reason also considers all the trailing 2s to be
> different.  Additionally context diff also doesn't provide the nice
> markers for differences inside a line which might be problematic as
> there's no guarantee there will be nice line endings in the input.
> 
> In general I was already thinking of cutting off similar prefixes and
> suffixes before using ndiff, so this doesn't seem that bad to me.  Do
> others think this is acceptable?

I find it acceptable.  I guess we need to see how it works in RL projects.

Btw, I find it hard to guess how many people actually read this ML, despite
there being some >130 subscribers.  But we'll get issue reports when things go
bad i guess :) 

> This whole issue made me wonder if it should be possible to disable
> the pytest_assert_binrepr hook.  

We could do a general "--assertmode=(choice)" with e.g.:

    0: (no) don't do any assert reinterp (like --no-assert now)
    1: (basic) do basic reinterpreation
    2: (advanced) do basic reinterpretation + customizing hooks

and default to 2.  

> It is probably sufficient to add an
> option which can be checked right at the start of the builtin
> pytest_assert_binrepr hook which will just return None or [] right
> away.  But what is the best way to access the config setting from
> there?  Is it fine to use py.test.config or should the setting be
> piggy-backed on some global again (e.g. change the current
> py.builtin.builtins.AssertionError._pytesthook into a ._pytestconfig)?
>  Or maybe there's a more elegant solution for this that I'm unaware
> of?

I think there is an elegant solution.  Instead of using "hook" in py/code/ we
use a generic "customize" function that is to be called.  In 
pytest_assertion.py's pytest_configure we write that function 
such that it calls 

    pytest_assert_binrepr(config, ...) 

hope that makes sense. If in doubt leave it to me and just use py.test.config.
I also want to introduce an "ini" style file for py.test, btw. hopefully
real soon now.

best,
holger

_______________________________________________
py-dev mailing list
py-dev@codespeak.net
http://codespeak.net/mailman/listinfo/py-dev

Reply via email to