summaryrefslogtreecommitdiff
path: root/nose/pyversion.py
diff options
context:
space:
mode:
Diffstat (limited to 'nose/pyversion.py')
-rw-r--r--nose/pyversion.py65
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)