Yelp / Testify

A more pythonic testing framework.
Other
306 stars 67 forks source link

Testify with a new version of IPython will crash with encoding error. #231

Closed pharaun closed 8 years ago

pharaun commented 10 years ago

Versions:

Symptoms:

  1. Traceback emits an unicode character (filepath, exception itself, etc)
  2. IPython is used to pretty-print the traceback and colorize it, will then choke and crash.
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 88: ordinal not in range(128)

Reason:

  1. Its because the traceback extracted is returned in Bytestring form (str) which contains a encoded unicode character.
  2. IPython will implicitly convert it to Unicode string via ascii decoding and boom.

Patch:

diff --git a/testify/test_result.py b/testify/test_result.py
index e5aab91..8eac2ec 100644
--- a/testify/test_result.py
+++ b/testify/test_result.py
@@ -36,6 +36,11 @@ try:
     list_tb = ListTB(color_scheme='Linux')
     def fancy_tb_formatter(etype, value, tb, length=None):
         tb = traceback.extract_tb(tb, limit=length)
+
+        # Since IPython ~ 1.10 will crash with a unicode error, decode
+        # the bytestring returned from traceback into an unicode string
+        tb = [(t[0], t[1], t[2], t[3].decode('utf-8')) for t in tb]
+
         return list_tb.text(etype, value, tb, context=0)
 except ImportError:
     fancy_tb_formatter = None

Testing:

I have not had time to write a proper test but to test this, just pass in a "string/traceback" with encoded unicode character and watch it crash on IPython 1.1.0

pharaun commented 10 years ago

This is technically not the correct place for a fix, the fix should go into IPython itself.

Specifically: https://github.com/ipython/ipython/blob/master/IPython/core/ultratb.py#L533-L538

Will attempt to patch but not sure how to fix it for now.

mittonk commented 10 years ago

Here's some smallish repro steps:

# -*- coding: utf-8 -*-                                                                                                                    
import testify

class UnicodeFailTestCase(testify.TestCase):
    def test_unicode(self):
        testify.assert_equal(u'é', u'ü')

Using:

Python 2.6.7
testify==0.5.3
ipdb==0.8
ipython==1.1.0
pharaun commented 10 years ago

https://pythonhosted.org/kitchen/unicode-frustrations.html#frustration-5-exceptions <- outlines the issue mittonk reproduced.

asottile commented 8 years ago

Confirmed with latest testify and latest ipython in python2

It passes however in python3