Python 3 support

* Implicit relative import 'import version' to import htmloutput.version.
  Use explicit relative import instead 'from . import version'.
  Somehow 'from htmloutput import version' does not work for python2
  when I tested this with horizon nosetest.
* Python3 dict does not has_key(). Use 'not in' instead.
* Open a file for writing with 'wb' (binary mode).
  In Python 3, encode() converts unicode including regular string into
  bytes. In Python 2, encode() converts unicode string into string and
  string and bytes are handled equivalently. Thus, opening a file with
  binary mode works both for python2 and python3.
* Decoding from string to unicode is only needed for Python 2,
  so six.PY2 check is added to isinstance(x, str) if-clause.

Change-Id: Ied161e133ced1d672aba9d1a44b52034dfb676da
This commit is contained in:
Akihiro Motoki 2017-06-22 19:18:31 +09:00
parent 102b6d32c1
commit 71d12999b0
2 changed files with 12 additions and 6 deletions

View File

@ -44,7 +44,9 @@ from nose.plugins import Plugin
import nose.plugins.skip import nose.plugins.skip
from xml.sax import saxutils from xml.sax import saxutils
import version import six
from . import version
__version__ = version.__version__ __version__ = version.__version__
class TemplateData(object): class TemplateData(object):
@ -513,7 +515,7 @@ class HtmlOutput(Plugin):
ending = ending, ending = ending,
) )
if self.html_file: if self.html_file:
html_file = open(self.html_file, 'w') html_file = open(self.html_file, 'wb')
html_file.write(output.encode('utf8')) html_file.write(output.encode('utf8'))
else: else:
stream.write(output.encode('utf8')) stream.write(output.encode('utf8'))
@ -621,7 +623,7 @@ class HtmlOutput(Plugin):
cls = test.test.__class__ cls = test.test.__class__
else: else:
cls = test.__class__ cls = test.__class__
if not rmap.has_key(cls): if cls not in rmap:
rmap[cls] = [] rmap[cls] = []
classes.append(cls) classes.append(cls)
rmap[cls].append(data_tuple) rmap[cls].append(data_tuple)
@ -639,13 +641,17 @@ class HtmlOutput(Plugin):
# Comments below from the original source project. # Comments below from the original source project.
# TODO: clean this up within the context of a nose plugin. # TODO: clean this up within the context of a nose plugin.
# o and e should be byte string because they are collected from stdout and stderr? # o and e should be byte string because they are collected from stdout and stderr?
if isinstance(o,str): # NOTE: In Python3 unicode is natively supported as string,
# so there is no need to decode() here.
if six.PY2 and isinstance(o, str):
# TODO: some problem with 'string_escape': it escape \n and mess up formating # TODO: some problem with 'string_escape': it escape \n and mess up formating
# uo = unicode(o.encode('string_escape')) # uo = unicode(o.encode('string_escape'))
uo = o.decode('latin-1') uo = o.decode('latin-1')
else: else:
uo = o uo = o
if isinstance(e,str): # NOTE: In Python3 unicode is natively supported as string,
# so there is no need to decode() here.
if six.PY2 and isinstance(e, str):
# TODO: some problem with 'string_escape': it escape \n and mess up formating # TODO: some problem with 'string_escape': it escape \n and mess up formating
# ue = unicode(e.encode('string_escape')) # ue = unicode(e.encode('string_escape'))
ue = e.decode('latin-1') ue = e.decode('latin-1')

View File

@ -9,7 +9,7 @@ setuptools.setup(
license="Apache License, Version 2.0", license="Apache License, Version 2.0",
url="https://git.openstack.org/cgit/openstack-infra/nose-html-output", url="https://git.openstack.org/cgit/openstack-infra/nose-html-output",
packages=["htmloutput"], packages=["htmloutput"],
install_requires=['nose'], install_requires=['nose', 'six'],
classifiers=[ classifiers=[
"Environment :: Console", "Environment :: Console",
"Topic :: Software Development :: Testing", "Topic :: Software Development :: Testing",