diff --git a/avocado/core/test.py b/avocado/core/test.py index fe802db984afe668018864a9891d2eb2ba86e01d..8d14261c8613f01424d971277432d3dd882a36c2 100644 --- a/avocado/core/test.py +++ b/avocado/core/test.py @@ -997,20 +997,20 @@ class Test(unittest.TestCase, TestData): except exceptions.TestBaseException as detail: self.__status = detail.status self.__fail_class = detail.__class__.__name__ - self.__fail_reason = str(detail) + self.__fail_reason = astring.to_text(detail) self.__traceback = stacktrace.prepare_exc_info(sys.exc_info()) except AssertionError as detail: self.__status = 'FAIL' self.__fail_class = detail.__class__.__name__ - self.__fail_reason = str(detail) + self.__fail_reason = astring.to_text(detail) self.__traceback = stacktrace.prepare_exc_info(sys.exc_info()) except Exception as detail: self.__status = 'ERROR' tb_info = stacktrace.tb_info(sys.exc_info()) self.__traceback = stacktrace.prepare_exc_info(sys.exc_info()) try: - self.__fail_class = str(detail.__class__.__name__) - self.__fail_reason = str(detail) + self.__fail_class = astring.to_text(detail.__class__.__name__) + self.__fail_reason = astring.to_text(detail) except TypeError: self.__fail_class = "Exception" self.__fail_reason = ("Unable to get exception, check the " diff --git a/avocado/plugins/jsonresult.py b/avocado/plugins/jsonresult.py index 5803097a404bf924d8136a24b947163771a7f8f9..16fb182fd7e446348f4b99b4fbfe4ad65b4532a8 100644 --- a/avocado/plugins/jsonresult.py +++ b/avocado/plugins/jsonresult.py @@ -23,6 +23,7 @@ import os from avocado.core.output import LOG_UI from avocado.core.parser import FileOrStdoutAction from avocado.core.plugin_interfaces import CLI, Result +from avocado.utils import astring UNKNOWN = '' @@ -44,7 +45,7 @@ class JSONResult(Result): 'whiteboard': test.get('whiteboard', UNKNOWN), 'logdir': test.get('logdir', UNKNOWN), 'logfile': test.get('logfile', UNKNOWN), - 'fail_reason': str(test.get('fail_reason', UNKNOWN))}) + 'fail_reason': astring.to_text(test.get('fail_reason', UNKNOWN))}) content = {'job_id': result.job_unique_id, 'debuglog': result.logfile, 'tests': tests, diff --git a/avocado/plugins/xunit.py b/avocado/plugins/xunit.py index 743d6a2def712e579aa3ff040bc89d7948159860..e1a583073f5aa627bd7304c886000e6fc325df4b 100644 --- a/avocado/plugins/xunit.py +++ b/avocado/plugins/xunit.py @@ -23,7 +23,7 @@ from xml.dom.minidom import Document from avocado.core.parser import FileOrStdoutAction from avocado.core.output import LOG_UI from avocado.core.plugin_interfaces import CLI, Result -from avocado.utils import data_structures +from avocado.utils import astring, data_structures class XUnitResult(Result): @@ -36,7 +36,7 @@ class XUnitResult(Result): def _escape_attr(self, attrib): attrib = ''.join(_ if _ in self.PRINTABLE else "\\x%02x" % ord(_) - for _ in str(attrib)) + for _ in astring.to_text(attrib, encoding='utf-8')) return attrib def _escape_cdata(self, cdata): diff --git a/avocado/utils/astring.py b/avocado/utils/astring.py index b06c41ecbaf57dd63a844b0c548317a58ede3e9f..52a8e38863de614283d48433ab7f459f8400f1b3 100644 --- a/avocado/utils/astring.py +++ b/avocado/utils/astring.py @@ -26,6 +26,7 @@ And not notice until their code starts failing. """ import itertools +import locale import re import sys import string @@ -35,6 +36,12 @@ from six.moves import zip from six.moves import xrange as range +#: On import evaluated value representing the system encoding +#: based on system locales using :func:`locale.getpreferredencoding`. +#: Use this value wisely as some files are dumped in different +#: encoding. +ENCODING = locale.getpreferredencoding() + #: String containing all fs-unfriendly chars (Windows-fat/Linux-ext3) FS_UNSAFE_CHARS = '<>:"/\\|?*;' @@ -313,21 +320,27 @@ def is_text(data): return isinstance(data, str) -def to_text(data, encoding=None): +def to_text(data, encoding=ENCODING): """ - Convert data to text + Convert anything to text decoded text - Action is only taken if data is "bytes", in which case it's - decoded into the given encoding and should produce a type that - passes the is_text() check. + When the data is bytes, it's decoded. When it's not of string types + it's re-formatted into text and returned. Otherwise (it's string) + it's returned unchanged. :param data: data to be transformed into text + :param encoding: encoding of the data (only used when decoding + is necessary) :type data: either bytes or other data that will be returned unchanged """ if is_bytes(data): if encoding is None: - return data.decode() + encoding = ENCODING + return data.decode(encoding) + elif not isinstance(data, string_types): + if sys.version_info[0] < 3: + return unicode(data) # pylint: disable=E0602 else: - return data.decode(encoding) + return str(data) return data diff --git a/avocado/utils/partition.py b/avocado/utils/partition.py index 2bc4cd90838d3f21becae31efad9e38db63c34b3..1286e6917b6cf2920ea126ea25e8c4359a49a1a1 100644 --- a/avocado/utils/partition.py +++ b/avocado/utils/partition.py @@ -109,9 +109,9 @@ class Partition(object): """ # list mounted file systems devices = [line.split()[0] - for line in process.system_output('mount').splitlines()] + for line in process.getoutput('mount').splitlines()] # list mounted swap devices - swaps = process.system_output('swapon -s').splitlines() + swaps = process.getoutput('swapon -s').splitlines() devices.extend([line.split()[0] for line in swaps if line.startswith('/')]) return devices @@ -122,7 +122,7 @@ class Partition(object): Lists the mount points. """ return [line.split()[2] - for line in process.system_output('mount').splitlines()] + for line in process.getoutput('mount').splitlines()] def get_mountpoint(self, filename=None): """ @@ -254,7 +254,7 @@ class Partition(object): # Try to kill all pids for pid in (line.split()[1] for line in out.splitlines()[1:]): try: - process.system("kill -9 %s" % pid, ignore_status=True, + process.system("kill -9 %d" % int(pid), ignore_status=True, sudo=True) except OSError: pass diff --git a/examples/tests/errortest_nasty.py b/examples/tests/errortest_nasty.py index 19878f4ccf54ad56c4ba586921a55162ab125792..6834d7c17ebe7a44c88df37a97ec92c4c4855ac3 100755 --- a/examples/tests/errortest_nasty.py +++ b/examples/tests/errortest_nasty.py @@ -27,7 +27,7 @@ class FailTest(Test): """ Avocado should report this as TestError. """ - raise NastyException("Nasty-string-like-exception") + raise NastyException(u"Nasty-string-like-exception\u017e") if __name__ == "__main__": diff --git a/examples/tests/errortest_nasty2.py b/examples/tests/errortest_nasty2.py index 2743a9c5bd7cc07b19674e4c858fe46fedb05171..970232a602a11def35cca7eb244c038e5c672742 100755 --- a/examples/tests/errortest_nasty2.py +++ b/examples/tests/errortest_nasty2.py @@ -14,6 +14,9 @@ class NastyException(Exception): def __str__(self): return self.msg + def __unicode__(self): + return self.msg + class FailTest(Test): diff --git a/optional_plugins/html/avocado_result_html/__init__.py b/optional_plugins/html/avocado_result_html/__init__.py index 2eca3eec8288aa5f80bce624771173e6f271fbfe..e80931151935671a8a4a7019229b4ff4937ab4e7 100644 --- a/optional_plugins/html/avocado_result_html/__init__.py +++ b/optional_plugins/html/avocado_result_html/__init__.py @@ -29,6 +29,7 @@ import pystache from avocado.core import exit_codes from avocado.core.output import LOG_UI from avocado.core.plugin_interfaces import CLI, Result +from avocado.utils import astring class ReportModel(object): @@ -156,7 +157,7 @@ class ReportModel(object): fail_reason = tst.get('fail_reason') if fail_reason is None: fail_reason = '' - fail_reason = str(fail_reason) + fail_reason = astring.to_text(fail_reason) if len(fail_reason) > exhibition_limit: fail_reason = ('