diff options
Diffstat (limited to 'nose/pyversion.py')
-rw-r--r-- | nose/pyversion.py | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/nose/pyversion.py b/nose/pyversion.py index a6ec3f7..07c105f 100644 --- a/nose/pyversion.py +++ b/nose/pyversion.py @@ -3,19 +3,33 @@ This module contains fixups for using nose under different versions of Python. """ import sys import os +import traceback import types import inspect import nose.util __all__ = ['make_instancemethod', 'cmp_to_key', 'sort_list', 'ClassType', 'TypeType', 'UNICODE_STRINGS', 'unbound_method', 'ismethod', - 'bytes_'] + 'bytes_', 'is_base_exception', 'force_unicode', 'exc_to_unicode', + 'format_exception'] # In Python 3.x, all strings are unicode (the call to 'unicode()' in the 2.x # source will be replaced with 'str()' when running 2to3, so this test will # then become true) UNICODE_STRINGS = (type(unicode()) == type(str())) +if sys.version_info[:2] < (3, 0): + def force_unicode(s, encoding='UTF-8'): + try: + s = unicode(s) + except UnicodeDecodeError: + s = str(s).decode(encoding, 'replace') + + return s +else: + def force_unicode(s, encoding='UTF-8'): + return str(s) + # new.instancemethod() is obsolete for new-style classes (Python 3.x) # We need to use descriptor methods instead. try: @@ -147,3 +161,52 @@ else: return func.func_code.co_flags & CO_GENERATOR != 0 except AttributeError: return False + +# Make a function to help check if an exception is derived from BaseException. +# In Python 2.4, we just use Exception instead. +if sys.version_info[:2] < (2, 5): + def is_base_exception(exc): + return isinstance(exc, Exception) +else: + def is_base_exception(exc): + return isinstance(exc, BaseException) + +if sys.version_info[:2] < (3, 0): + def exc_to_unicode(ev, encoding='utf-8'): + if is_base_exception(ev): + if not hasattr(ev, '__unicode__'): + # 2.5- + if not hasattr(ev, 'message'): + # 2.4 + msg = len(ev.args) and ev.args[0] or '' + else: + msg = ev.message + msg = force_unicode(msg, encoding=encoding) + clsname = force_unicode(ev.__class__.__name__, + encoding=encoding) + ev = u'%s: %s' % (clsname, msg) + elif not isinstance(ev, unicode): + ev = repr(ev) + + return force_unicode(ev, encoding=encoding) +else: + def exc_to_unicode(ev, encoding='utf-8'): + return str(ev) + +def format_exception(exc_info, encoding='UTF-8'): + ec, ev, tb = exc_info + + # Our exception object may have been turned into a string, and Python 3's + # traceback.format_exception() doesn't take kindly to that (it expects an + # actual exception object). So we work around it, by doing the work + # ourselves if ev is not an exception object. + if not is_base_exception(ev): + tb_data = force_unicode( + ''.join(traceback.format_tb(tb)), + encoding) + ev = exc_to_unicode(ev) + return tb_data + ev + else: + return force_unicode( + ''.join(traceback.format_exception(*exc_info)), + encoding) |