[Piglit] [PATCH 11/44] python: use six unicode/bytes/str handling

baker.dylan.c at gmail.com baker.dylan.c at gmail.com
Wed Jan 27 16:06:19 PST 2016


From: Dylan Baker <baker.dylan.c at gmail.com>

This is not feature complete for python 3.x in and of itself, but it
gets started by using six functions rather than str and unicode.

Signed-off-by: Dylan Baker <dylanx.c.baker at intel.com>
---
 framework/backends/compression.py |  8 +++++---
 framework/backends/junit.py       |  2 +-
 framework/exceptions.py           |  8 ++++++--
 framework/grouptools.py           |  5 +++--
 framework/profile.py              | 10 ++++++----
 framework/results.py              | 12 +++++++-----
 framework/status.py               | 31 +++++++++++++++++++------------
 framework/test/base.py            |  6 +++---
 templates/feature.mako            |  4 +++-
 templates/index.mako              |  5 ++++-
 unittests/deqp_tests.py           |  1 +
 unittests/utils.py                |  4 +++-
 12 files changed, 61 insertions(+), 35 deletions(-)

diff --git a/framework/backends/compression.py b/framework/backends/compression.py
index ab85a17..420c068 100644
--- a/framework/backends/compression.py
+++ b/framework/backends/compression.py
@@ -27,8 +27,8 @@ DECOMPRESSORS, which use compression modes ('bz2', 'gz', 'xz', 'none') to
 provide open-like functions with correct mode settings for writing or reading,
 respectively.
 
-They should always take unicode objects. It is up to the caller to ensure that
-they're passing unicode and not bytes.
+They should always take unicode (str in python 3.x) objects. It is up to the
+caller to ensure that they're passing unicode and not bytes.
 
 A helper, get_mode(), is provided to return the user selected mode (it will try
 the PIGLIT_COMPRESSION environment variable, then the piglit.conf
@@ -46,6 +46,7 @@ import os
 import subprocess
 import contextlib
 
+import six
 from six.moves import cStringIO as StringIO
 
 from framework import exceptions
@@ -59,13 +60,14 @@ __all__ = [
 ]
 
 
+ at six.python_2_unicode_compatible
 class UnsupportedCompressor(exceptions.PiglitInternalError):
     def __init__(self, method, *args, **kwargs):
         super(UnsupportedCompressor, self).__init__(*args, **kwargs)
         self.__method = method
 
     def __str__(self):
-        return 'unsupported compression method {}'.format(self.__method)
+        return u'unsupported compression method {}'.format(self.__method)
 
 
 # TODO: in python3 the bz2 module has an open function
diff --git a/framework/backends/junit.py b/framework/backends/junit.py
index e6c5d3a..cf48b40 100644
--- a/framework/backends/junit.py
+++ b/framework/backends/junit.py
@@ -104,7 +104,7 @@ class JUnitBackend(FileBackend):
                     continue
 
         # set the test count by counting the number of tests.
-        # This must be bytes or unicode
+        # This must be unicode (py3 str)
         piglit.attrib['tests'] = str(len(piglit))
 
         with open(os.path.join(self._dest, 'results.xml'), 'w') as f:
diff --git a/framework/exceptions.py b/framework/exceptions.py
index e0b04d6..566372f 100644
--- a/framework/exceptions.py
+++ b/framework/exceptions.py
@@ -24,6 +24,8 @@ from __future__ import print_function, absolute_import, division
 import sys
 import functools
 
+import six
+
 __all__ = [
     'PiglitInternalError',
     'PiglitFatalError',
@@ -52,6 +54,7 @@ def handler(func):
     return _inner
 
 
+ at six.python_2_unicode_compatible
 class PiglitException(Exception):
     """Class for non-error exceptions.
 
@@ -60,10 +63,11 @@ class PiglitException(Exception):
 
     """
     def __str__(self):
-        return ('An internal exception that should have been handled was not:'
+        return (u'An internal exception that should have been handled was not:'
                 '\n{}'.format(super(PiglitException, self).__str__()))
 
 
+ at six.python_2_unicode_compatible
 class PiglitInternalError(Exception):
     """Class for errors in piglit.
 
@@ -71,7 +75,7 @@ class PiglitInternalError(Exception):
 
     """
     def __str__(self):
-        return 'An internal error occured:\n{}'.format(
+        return u'An internal error occured:\n{}'.format(
             super(PiglitInternalError, self).__str__())
 
 
diff --git a/framework/grouptools.py b/framework/grouptools.py
index 406c608..9d16c2c 100644
--- a/framework/grouptools.py
+++ b/framework/grouptools.py
@@ -31,6 +31,7 @@ posix paths they may not start with a leading '/'.
 
 from __future__ import absolute_import, division, print_function
 
+import six
 from six.moves import zip
 
 __all__ = [
@@ -158,7 +159,7 @@ def from_path(path):
     This safely handles both Windows and Unix style paths.
 
     """
-    assert isinstance(path, (str, unicode)), 'Type must be string or unicode'
+    assert isinstance(path, six.string_types), 'Type must be string or unicode'
 
     if '\\' in path:
         path = path.replace('\\', SEPARATOR)
@@ -180,5 +181,5 @@ def format(name):
     want to see.
 
     """
-    assert isinstance(name, basestring)
+    assert isinstance(name, six.string_types)
     return name.replace(SEPARATOR, '/')
diff --git a/framework/profile.py b/framework/profile.py
index 94343db..b7204ed 100644
--- a/framework/profile.py
+++ b/framework/profile.py
@@ -34,6 +34,8 @@ import importlib
 import contextlib
 import itertools
 
+import six
+
 from framework import grouptools, exceptions, options
 from framework.dmesg import get_dmesg
 from framework.log import LogManager
@@ -73,7 +75,7 @@ class TestDict(dict):  # pylint: disable=too-few-public-methods
 
         """
         # keys should be strings
-        if not isinstance(key, basestring):
+        if not isinstance(key, six.string_types):
             raise exceptions.PiglitFatalError(
                 "TestDict keys must be strings, but was {}".format(type(key)))
 
@@ -348,7 +350,7 @@ class TestProfile(object):
         ...     g(['power', 'test'], 'powertest')
 
         """
-        assert isinstance(group, basestring), type(group)
+        assert isinstance(group, six.string_types), type(group)
 
         def adder(args, name=None, **kwargs):
             """Helper function that actually adds the tests.
@@ -374,10 +376,10 @@ class TestProfile(object):
                 if isinstance(args, list):
                     name = ' '.join(args)
                 else:
-                    assert isinstance(args, basestring)
+                    assert isinstance(args, six.string_types)
                     name = args
 
-            assert isinstance(name, basestring)
+            assert isinstance(name, six.string_types)
             lgroup = grouptools.join(group, name)
 
             self.test_list[lgroup] = test_class(
diff --git a/framework/results.py b/framework/results.py
index ffc5287..d8a9f16 100644
--- a/framework/results.py
+++ b/framework/results.py
@@ -27,6 +27,8 @@ import collections
 import copy
 import datetime
 
+import six
+
 from framework import status, exceptions, grouptools
 
 __all__ = [
@@ -83,8 +85,8 @@ class StringDescriptor(object):  # pylint: disable=too-few-public-methods
     returns a unicode object.
 
     """
-    def __init__(self, name, default=unicode()):
-        assert isinstance(default, unicode)
+    def __init__(self, name, default=six.text_type()):
+        assert isinstance(default, six.text_type)
         self.__name = name
         self.__default = default
 
@@ -92,12 +94,12 @@ class StringDescriptor(object):  # pylint: disable=too-few-public-methods
         return getattr(instance, self.__name, self.__default)
 
     def __set__(self, instance, value):
-        if isinstance(value, str):
+        if isinstance(value, six.binary_type):
             setattr(instance, self.__name, value.decode('utf-8', 'replace'))
-        elif isinstance(value, unicode):
+        elif isinstance(value, six.text_type):
             setattr(instance, self.__name, value)
         else:
-            raise TypeError('{} attribute must be a str or unicode instance, '
+            raise TypeError('{} attribute must be a unicode or bytes instance, '
                             'but was {}.'.format(self.__name, type(value)))
 
     def __delete__(self, instance):
diff --git a/framework/status.py b/framework/status.py
index d188f16..665c972 100644
--- a/framework/status.py
+++ b/framework/status.py
@@ -57,6 +57,9 @@ The formula for determining fixes is:
 """
 
 from __future__ import absolute_import, division, print_function
+
+import six
+
 from framework import exceptions
 
 __all__ = ['NOTRUN',
@@ -92,6 +95,7 @@ def status_lookup(status):
         raise StatusException(status)
 
 
+ at six.python_2_unicode_compatible
 class StatusException(exceptions.PiglitInternalError):
     """ Raise this exception when a string is passed to status_lookup that
     doesn't exists
@@ -107,9 +111,10 @@ class StatusException(exceptions.PiglitInternalError):
         super(StatusException, self).__init__(self)
 
     def __str__(self):
-        return 'Unknown status "{}"'.format(self.__status)
+        return u'Unknown status "{}"'.format(self.__status)
 
 
+ at six.python_2_unicode_compatible
 class Status(object):
     """ A simple class for representing the output values of tests.
 
@@ -138,7 +143,7 @@ class Status(object):
         assert isinstance(value, int), type(value)
         # The object is immutable, so calling self.foo = foo will raise a
         # TypeError. Using setattr from the parrent object works around this.
-        self.__name = name
+        self.__name = six.text_type(name)
         self.__value = value
         self.__fraction = fraction
 
@@ -160,11 +165,11 @@ class Status(object):
     def __repr__(self):
         return self.name
 
-    def __str__(self):
-        return str(self.name)
+    def __bytes__(self):
+        return six.binary_type(self.name)
 
-    def __unicode__(self):
-        return unicode(self.name)
+    def __str__(self):
+        return self.name
 
     def __lt__(self, other):
         return not self.__ge__(other)
@@ -177,8 +182,10 @@ class Status(object):
         # the __int__ magic method
         if isinstance(other, (int, Status)):
             return int(self) == int(other)
-        elif isinstance(other, (str, unicode)):
-            return unicode(self) == unicode(other)
+        elif isinstance(other, six.text_type):
+            return six.text_type(self) == other
+        elif isinstance(other, six.binary_type):
+            return six.binary_type(self) == other
         raise TypeError("Cannot compare type: {}".format(type(other)))
 
     def __ne__(self, other):
@@ -209,13 +216,13 @@ class NoChangeStatus(Status):
         super(NoChangeStatus, self).__init__(name, value, fraction)
 
     def __eq__(self, other):
-        if isinstance(other, (str, unicode, Status)):
-            return unicode(self) == unicode(other)
+        if isinstance(other, (str, six.text_type, Status)):
+            return six.text_type(self) == six.text_type(other)
         raise TypeError("Cannot compare type: {}".format(type(other)))
 
     def __ne__(self, other):
-        if isinstance(other, (str, unicode, Status)):
-            return unicode(self) != unicode(other)
+        if isinstance(other, (str, six.text_type, Status)):
+            return six.text_type(self) != six.text_type(other)
         raise TypeError("Cannot compare type: {}".format(type(other)))
 
 
diff --git a/framework/test/base.py b/framework/test/base.py
index 1272aff..af51386 100644
--- a/framework/test/base.py
+++ b/framework/test/base.py
@@ -216,15 +216,15 @@ class Test(object):
             self.is_skip()
         except TestIsSkip as e:
             self.result.result = 'skip'
-            self.result.out = unicode(e)
+            self.result.out = six.text_type(e)
             self.result.returncode = None
             return
 
         try:
             self._run_command()
         except TestRunError as e:
-            self.result.result = unicode(e.status)
-            self.result.out = unicode(e)
+            self.result.result = six.text_type(e.status)
+            self.result.out = six.text_type(e)
             self.result.returncode = None
             return
 
diff --git a/templates/feature.mako b/templates/feature.mako
index ac9bc86..9abd5bc 100644
--- a/templates/feature.mako
+++ b/templates/feature.mako
@@ -2,6 +2,8 @@
   import posixpath  # this must be posixpath, since we want /'s not \'s
   import re
 
+  from six.moves import range
+
 
   def feat_result(result):
       """Percentage result string"""
@@ -41,7 +43,7 @@
 
         ## Status columns
         ## Create an additional column for each summary
-        % for _ in xrange(len(results.results)):
+        % for _ in range(len(results.results)):
         <col />
         % endfor
       </colgroup>
diff --git a/templates/index.mako b/templates/index.mako
index d2b84b5..690206f 100644
--- a/templates/index.mako
+++ b/templates/index.mako
@@ -2,6 +2,9 @@
   import os
   import posixpath  # this must be posixpath, since we want /'s not \'s
   import re
+
+  from six.moves import range
+
   from framework import grouptools, status
 
   def group_changes(test, current):
@@ -86,7 +89,7 @@
 
         ## Status columns
         ## Create an additional column for each summary
-        % for _ in xrange(len(results.results)):
+        % for _ in range(len(results.results)):
         <col />
         % endfor
       </colgroup>
diff --git a/unittests/deqp_tests.py b/unittests/deqp_tests.py
index 0ae44f2..9b546b1 100644
--- a/unittests/deqp_tests.py
+++ b/unittests/deqp_tests.py
@@ -29,6 +29,7 @@ from __future__ import absolute_import, division, print_function
 
 import mock
 import nose.tools as nt
+import six
 
 from framework import profile, grouptools, exceptions
 from framework.test import deqp
diff --git a/unittests/utils.py b/unittests/utils.py
index ec2334e..8589953 100644
--- a/unittests/utils.py
+++ b/unittests/utils.py
@@ -42,6 +42,7 @@ try:
 except ImportError:
     import json
 from nose.plugins.skip import SkipTest
+import six
 from six.moves import getcwdb
 
 from framework import test, backends, core, results
@@ -87,6 +88,7 @@ JSON_DATA = {
 _SAVED_COMPRESSION = os.environ.get('PIGLIT_COMPRESSION')
 
 
+ at six.python_2_unicode_compatible
 class TestFailure(AssertionError):
     """An exception to be raised when a test fails.
 
@@ -105,7 +107,7 @@ class TestFailure(AssertionError):
 
     def __str__(self):
         if isinstance(self.__arg, Exception):
-            return 'exception type "{}" with message "{}" raised.'.format(
+            return u'exception type "{}" with message "{}" raised.'.format(
                 type(self.__arg), str(self.__arg))
         else:
             return self.__arg
-- 
2.7.0



More information about the Piglit mailing list