You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kp...@apache.org on 2018/01/20 22:04:20 UTC

qpid-interop-test git commit: QPIDIT-109: Made all Python shims run under either Python 2 or Python 3. Added separate shims for Python 2 and Python 3 so that both these can run against the other shims. Modified config.sh to add a PYTHON3PATH to the envir

Repository: qpid-interop-test
Updated Branches:
  refs/heads/master 703daa719 -> ee57f686f


QPIDIT-109: Made all Python shims run under either Python 2 or Python 3. Added separate shims for Python 2 and Python 3 so that both these can run against the other shims. Modified config.sh to add a PYTHON3PATH to the environment which is used when the Python 3 shims are in use, and presuppose that the Proton Python3 artifacts are installed into /lib64/proton/bindings/python3. At present, this must be done by hand.


Project: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/commit/ee57f686
Tree: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/tree/ee57f686
Diff: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/diff/ee57f686

Branch: refs/heads/master
Commit: ee57f686f510e31295bbe8086f492e6d21419210
Parents: 703daa7
Author: Kim van der Riet <kv...@localhost.localdomain>
Authored: Sat Jan 20 17:03:55 2018 -0500
Committer: Kim van der Riet <kv...@localhost.localdomain>
Committed: Sat Jan 20 17:03:55 2018 -0500

----------------------------------------------------------------------
 config.sh.in                                    |  4 +-
 shims/qpid-proton-python/src/_compat.py         |  4 ++
 .../src/amqp_large_content_test/Receiver.py     |  8 ++--
 .../src/amqp_large_content_test/Sender.py       |  6 +--
 .../src/amqp_types_test/Receiver.py             |  5 ++-
 .../src/amqp_types_test/Sender.py               |  8 ++--
 .../src/jms_hdrs_props_test/Receiver.py         | 21 +++++++----
 .../src/jms_hdrs_props_test/Sender.py           | 24 ++++++------
 .../src/jms_messages_test/Receiver.py           | 39 ++++++++++++--------
 .../src/jms_messages_test/Sender.py             | 22 +++++------
 src/python/qpid_interop_test/__init__.py        |  5 ---
 .../amqp_large_content_test.py                  |  5 +--
 src/python/qpid_interop_test/amqp_types_test.py |  5 +--
 .../qpid_interop_test/interop_test_errors.py    |  2 +-
 .../qpid_interop_test/jms_hdrs_props_test.py    | 13 +++----
 .../qpid_interop_test/jms_messages_test.py      | 13 +++----
 src/python/qpid_interop_test/shims.py           | 26 +++++++++----
 src/python/qpid_interop_test/test_type_map.py   |  4 +-
 18 files changed, 119 insertions(+), 95 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/config.sh.in
----------------------------------------------------------------------
diff --git a/config.sh.in b/config.sh.in
index a58e3de..a76a7d0 100644
--- a/config.sh.in
+++ b/config.sh.in
@@ -18,6 +18,8 @@
 
 export QPID_INTEROP_TEST_HOME=@CMAKE_SOURCE_DIR@
 export QIT_INSTALL_PREFIX=@CMAKE_INSTALL_PREFIX@
-export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/lib64/proton/bindings/python:@CMAKE_INSTALL_PREFIX@/lib/@PYTHON_DIR_NAME@/site-packages:@CMAKE_INSTALL_PREFIX@/libexec/qpid_interop_test/shims/qpid-proton-python:$PYTHONPATH
+CURRENT_PYTHONPATH=$PYTHONPATH
+export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/lib64/proton/bindings/python:@CMAKE_INSTALL_PREFIX@/lib/@PYTHON_DIR_NAME@/site-packages:@CMAKE_INSTALL_PREFIX@/libexec/qpid_interop_test/shims/qpid-proton-python:$CURRENT_PYTHONPATH
+export PYTHON3PATH=@CMAKE_INSTALL_PREFIX@/lib64/proton/bindings/python3:@CMAKE_INSTALL_PREFIX@/lib/@PYTHON_DIR_NAME@/site-packages:@CMAKE_INSTALL_PREFIX@/libexec/qpid_interop_test/shims/qpid-proton-python:$CURRENT_PYTHONPATH
 export LD_LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib64:$LD_LIBRARY_PATH
 export PATH=@CMAKE_INSTALL_PREFIX@/lib/@PYTHON_DIR_NAME@/site-packages/qpid_interop_test:$PATH

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/_compat.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/_compat.py b/shims/qpid-proton-python/src/_compat.py
index bafedc7..133ba2a 100644
--- a/shims/qpid-proton-python/src/_compat.py
+++ b/shims/qpid-proton-python/src/_compat.py
@@ -29,6 +29,8 @@ import types
 IS_PY3 = sys.version_info[0] == 3
 
 if IS_PY3:
+    def _decode_hex(s):
+        return bytes.fromhex(s)
     def _letters():
         return string.ascii_letters
     def _long(i, r):
@@ -39,6 +41,8 @@ if IS_PY3:
         return str(i)
 
 else:
+    def _decode_hex(s):
+        return s.decode('hex')
     def _letters():
         return string.letters
     def _long(i, r):

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/amqp_large_content_test/Receiver.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_large_content_test/Receiver.py b/shims/qpid-proton-python/src/amqp_large_content_test/Receiver.py
index d958fad..3870e5d 100755
--- a/shims/qpid-proton-python/src/amqp_large_content_test/Receiver.py
+++ b/shims/qpid-proton-python/src/amqp_large_content_test/Receiver.py
@@ -87,8 +87,8 @@ class AmqpLargeContentTestReceiver(MessagingHandler):
     def get_str_message_size(message):
         """Find the size of a bytes, unicode or symbol message in MB"""
         if _compat.IS_PY3:
-            if isinstance(message, (bytes, string, symbol)):
-                return len(str(message)) / 1024 / 1024 # in MB
+            if isinstance(message, (bytes, str, symbol)):
+                return int(len(message) / 1024 / 1024) # in MB
         else:
             if isinstance(message, (bytes, unicode, symbol)):
                 return len(str(message)) / 1024 / 1024 # in MB
@@ -113,10 +113,10 @@ class AmqpLargeContentTestReceiver(MessagingHandler):
         (tot_size, num_elts) where tot_size = num_elts * elt_size. Note that key size is excluded from size.
         """
         if isinstance(message, dict):
-            keys = message.keys()
+            keys = list(message.keys())
             num_elts = len(keys)
             elt_size = len(message[keys[0]])
-            return (elt_size * num_elts / 1024 / 1024, num_elts)
+            return (int(elt_size * num_elts / 1024 / 1024), num_elts)
         return None
 
 # --- main ---

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/amqp_large_content_test/Sender.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_large_content_test/Sender.py b/shims/qpid-proton-python/src/amqp_large_content_test/Sender.py
index 955c46e..2a9375b 100755
--- a/shims/qpid-proton-python/src/amqp_large_content_test/Sender.py
+++ b/shims/qpid-proton-python/src/amqp_large_content_test/Sender.py
@@ -79,7 +79,7 @@ class AmqpLargeContentTestSender(MessagingHandler):
         AMQP value.
         """
         if self.amqp_type == 'binary':
-            return Message(body=bytes(AmqpLargeContentTestSender.create_test_string(tot_size_bytes)))
+            return Message(body=AmqpLargeContentTestSender.create_test_string(tot_size_bytes).encode('utf-8'))
         if self.amqp_type == 'string':
             return Message(body=_compat._unicode(AmqpLargeContentTestSender.create_test_string(tot_size_bytes)))
         if self.amqp_type == 'symbol':
@@ -101,7 +101,7 @@ class AmqpLargeContentTestSender(MessagingHandler):
     @staticmethod
     def create_test_list(tot_size_bytes, num_elts):
         """Create a list containing num_elts with a sum of all elements being tot_size_bytes"""
-        size_per_elt_bytes = tot_size_bytes / num_elts
+        size_per_elt_bytes = int(tot_size_bytes / num_elts)
         test_list = []
         for _ in range(num_elts):
             test_list.append(_compat._unicode(AmqpLargeContentTestSender.create_test_string(size_per_elt_bytes)))
@@ -110,7 +110,7 @@ class AmqpLargeContentTestSender(MessagingHandler):
     @staticmethod
     def create_test_map(tot_size_bytes, num_elts):
         """Create a map containing num_elts with a sum of all elements being tot_size_bytes (excluding keys)"""
-        size_per_elt_bytes = tot_size_bytes / num_elts
+        size_per_elt_bytes = int(tot_size_bytes / num_elts)
         test_map = {}
         for elt_no in range(num_elts):
             test_map[_compat._unicode('elt_%06d' % elt_no)] = \

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_types_test/Receiver.py b/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
index 9d3dc19..289fb06 100755
--- a/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
+++ b/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
@@ -103,8 +103,9 @@ class AmqpTypesTestReceiver(MessagingHandler):
                     self.received_value_list.append(event.message.body)
                 else:
                     self.received_value_list.append(hex(ord(event.message.body)))
-            elif self.amqp_type == 'binary' or \
-                 self.amqp_type == 'string' or \
+            elif self.amqp_type == 'binary':
+                self.received_value_list.append(event.message.body.decode('utf-8'))
+            elif self.amqp_type == 'string' or \
                  self.amqp_type == 'symbol':
                 self.received_value_list.append(event.message.body)
             elif self.amqp_type == 'list' or \

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/amqp_types_test/Sender.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_types_test/Sender.py b/shims/qpid-proton-python/src/amqp_types_test/Sender.py
index df47c15..3fc96a1 100755
--- a/shims/qpid-proton-python/src/amqp_types_test/Sender.py
+++ b/shims/qpid-proton-python/src/amqp_types_test/Sender.py
@@ -100,16 +100,16 @@ class AmqpTypesTestSender(MessagingHandler):
         if self.amqp_type == 'long':
             return Message(id=(self.sent+1), body=_compat._long(test_value, 16))
         if self.amqp_type == 'float':
-            return Message(id=(self.sent+1), body=float32(unpack('!f', test_value[2:].decode('hex'))[0]))
+            return Message(id=(self.sent+1), body=float32(unpack('!f', _compat._decode_hex(test_value[2:]))[0]))
         if self.amqp_type == 'double':
-            return Message(id=(self.sent+1), body=unpack('!d', test_value[2:].decode('hex'))[0])
+            return Message(id=(self.sent+1), body=unpack('!d', _compat._decode_hex(test_value[2:]))[0])
         if self.amqp_type == 'decimal32':
             return Message(id=(self.sent+1), body=decimal32(int(test_value[2:], 16)))
         if self.amqp_type == 'decimal64':
             l64 = _compat._long(test_value[2:], 16)
             return Message(id=(self.sent+1), body=decimal64(l64))
         if self.amqp_type == 'decimal128':
-            return Message(id=(self.sent+1), body=decimal128(test_value[2:].decode('hex')))
+            return Message(id=(self.sent+1), body=decimal128(_compat._decode_hex(test_value[2:])))
         if self.amqp_type == 'char':
             if len(test_value) == 1: # Format 'a'
                 return Message(id=(self.sent+1), body=char(test_value))
@@ -120,7 +120,7 @@ class AmqpTypesTestSender(MessagingHandler):
         if self.amqp_type == 'uuid':
             return Message(id=(self.sent+1), body=UUID(test_value))
         if self.amqp_type == 'binary':
-            return Message(id=(self.sent+1), body=bytes(test_value))
+            return Message(id=(self.sent+1), body=test_value.encode('utf-8'))
         if self.amqp_type == 'string':
             return Message(id=(self.sent+1), body=_compat._unicode(test_value))
         if self.amqp_type == 'symbol':

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py b/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py
index cf9813a..00d8ffb 100755
--- a/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py
+++ b/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py
@@ -35,6 +35,7 @@ from proton.handlers import MessagingHandler
 from proton.reactor import Container
 from qpid_interop_test.jms_types import QPID_JMS_TYPE_ANNOTATION_NAME
 from qpid_interop_test.interop_test_errors import InteropTestError
+import _compat
 
 
 class JmsHdrsPropsTestReceiver(MessagingHandler):
@@ -79,11 +80,14 @@ class JmsHdrsPropsTestReceiver(MessagingHandler):
 
     def on_message(self, event):
         """Event callback when a message is received by the client"""
-        if event.message.id and event.message.id < self.received:
+        if event.message.id and isinstance(event.message.id, int) and event.message.id < self.received:
             return # ignore duplicate message
         if self.received < self.expected:
             if self.current_subtype is None:
-                self.current_subtype = self.subtype_itr.next()
+                if _compat.IS_PY3:
+                    self.current_subtype = next(self.subtype_itr)
+                else:
+                    self.current_subtype = self.subtype_itr.next()
                 self.current_subtype_msg_list = []
             self.current_subtype_msg_list.append(self._handle_message(event.message))
             self._process_jms_headers(event.message)
@@ -153,10 +157,13 @@ class JmsHdrsPropsTestReceiver(MessagingHandler):
         if self.current_subtype == 'byte':
             return hex(unpack('b', message.body)[0])
         if self.current_subtype == 'bytes':
-            return str(message.body)
+            return message.body.decode('utf-8')
         if self.current_subtype == 'char':
             if len(message.body) == 2: # format 'a' or '\xNN'
-                return str(message.body[1]) # strip leading '\x00' char
+                if _compat.IS_PY3:
+                    return chr(message.body[1]) # strip leading '\x00' char
+                else:
+                    return str(message.body[1]) # strip leading '\x00' char
             raise InteropTestError('Unexpected strring length for type char: %d' % len(message.body))
         if self.current_subtype == 'double':
             return '0x%016x' % unpack('!Q', message.body)[0]
@@ -194,7 +201,7 @@ class JmsHdrsPropsTestReceiver(MessagingHandler):
         if self.current_subtype == 'byte':
             return hex(value)
         if self.current_subtype == 'bytes':
-            return str(value)
+            return value.decode('utf-8')
         if self.current_subtype == 'char':
             return str(value)
         if self.current_subtype == 'double':
@@ -257,7 +264,7 @@ class JmsHdrsPropsTestReceiver(MessagingHandler):
         if self.current_subtype == 'byte':
             return hex(value)
         if self.current_subtype == 'bytes':
-            return str(value)
+            return value.decode('utf-8')
         if self.current_subtype == 'char':
             return str(value)
         if self.current_subtype == 'double':
@@ -293,7 +300,7 @@ class JmsHdrsPropsTestReceiver(MessagingHandler):
         correlation_id = message.correlation_id
         if correlation_id is not None:
             if 'JMS_CORRELATIONID_AS_BYTES' in self.flag_map and self.flag_map['JMS_CORRELATIONID_AS_BYTES']:
-                self.jms_header_map['JMS_CORRELATIONID_HEADER'] = {'bytes': correlation_id}
+                self.jms_header_map['JMS_CORRELATIONID_HEADER'] = {'bytes': correlation_id.decode('utf-8')}
             else:
                 self.jms_header_map['JMS_CORRELATIONID_HEADER'] = {'string': correlation_id}
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py b/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
index d70974e..8e889d0 100755
--- a/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
+++ b/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
@@ -165,10 +165,10 @@ class JmsHdrsPropsTestSender(MessagingHandler):
         elif test_value_type == 'byte':
             body_bytes = pack('b', int(test_value, 16))
         elif test_value_type == 'bytes':
-            body_bytes = str(test_value) # remove unicode
+            body_bytes = test_value.encode('utf-8')
         elif test_value_type == 'char':
             # JMS expects two-byte chars, ASCII chars can be prefixed with '\x00'
-            body_bytes = '\x00' + str(test_value) # remove unicode
+            body_bytes = b'\x00' + test_value.encode('utf-8')
         elif test_value_type == 'double' or test_value_type == 'float':
             body_bytes = test_value[2:].decode('hex')
         elif test_value_type == 'int':
@@ -199,7 +199,7 @@ class JmsHdrsPropsTestSender(MessagingHandler):
         elif test_value_type == 'byte':
             value = byte(int(test_value, 16))
         elif test_value_type == 'bytes':
-            value = str(test_value) # remove unicode
+            value = test_value.encode('utf-8')
         elif test_value_type == 'char':
             value = char(test_value)
         elif test_value_type == 'double':
@@ -256,7 +256,7 @@ class JmsHdrsPropsTestSender(MessagingHandler):
         elif test_value_type == 'byte':
             body_list = [byte(int(test_value, 16))]
         elif test_value_type == 'bytes':
-            body_list = [str(test_value)]
+            body_list = [test_value.encode('utf-8')]
         elif test_value_type == 'char':
             body_list = [char(test_value)]
         elif test_value_type == 'double':
@@ -292,9 +292,9 @@ class JmsHdrsPropsTestSender(MessagingHandler):
     def _get_jms_message_header_kwargs(self):
         hdr_kwargs = {}
         hdr_annotations = {}
-        for jms_header in self.test_headers_map.iterkeys():
+        for jms_header in list(self.test_headers_map.keys()):
             value_map = self.test_headers_map[jms_header]
-            value_type = value_map.keys()[0] # There is only ever one value in map
+            value_type = list(value_map.keys())[0] # There is only ever one value in map
             value = value_map[value_type]
             if jms_header == 'JMS_TYPE_HEADER':
                 if value_type == 'string':
@@ -307,7 +307,7 @@ class JmsHdrsPropsTestSender(MessagingHandler):
                 if value_type == 'string':
                     hdr_kwargs['correlation_id'] = value
                 elif value_type == 'bytes':
-                    hdr_kwargs['correlation_id'] = str(value)
+                    hdr_kwargs['correlation_id'] = value.encode('utf-8')
                 else:
                     raise InteropTestError('JmsSenderShim._get_jms_message_header_kwargs(): ' +
                                            'JMS_CORRELATIONID_HEADER requires value type "string" or "bytes", ' +
@@ -334,9 +334,9 @@ class JmsHdrsPropsTestSender(MessagingHandler):
 
     def _add_jms_message_properties(self, message):
         """Adds message properties to the supplied message from self.test_properties_map"""
-        for property_name in self.test_properties_map.iterkeys():
+        for property_name in list(self.test_properties_map.keys()):
             value_map = self.test_properties_map[property_name]
-            value_type = value_map.keys()[0] # There is only ever one value in map
+            value_type = list(value_map.keys())[0] # There is only ever one value in map
             value = value_map[value_type]
             if message.properties is None:
                 message.properties = {}
@@ -345,11 +345,11 @@ class JmsHdrsPropsTestSender(MessagingHandler):
             elif value_type == 'byte':
                 message.properties[property_name] = byte(int(value, 16))
             elif value_type == 'double':
-                message.properties[property_name] = unpack('!d', value[2:].decode('hex'))[0]
+                message.properties[property_name] = unpack('!d', _compat._decode_hex(value[2:]))[0]
             elif value_type == 'float':
-                message.properties[property_name] = float32(unpack('!f', value[2:].decode('hex'))[0])
+                message.properties[property_name] = float32(unpack('!f', _compat._decode_hex(value[2:]))[0])
             elif value_type == 'int':
-                message.properties[property_name] = int(value, 16)
+                message.properties[property_name] = int32(int(value, 16))
             elif value_type == 'long':
                 message.properties[property_name] = _compat._long(value, 16)
             elif value_type == 'short':

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/jms_messages_test/Receiver.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/jms_messages_test/Receiver.py b/shims/qpid-proton-python/src/jms_messages_test/Receiver.py
index e7d1172..494906f 100755
--- a/shims/qpid-proton-python/src/jms_messages_test/Receiver.py
+++ b/shims/qpid-proton-python/src/jms_messages_test/Receiver.py
@@ -34,6 +34,7 @@ from proton.handlers import MessagingHandler
 from proton.reactor import Container
 from qpid_interop_test.interop_test_errors import InteropTestError
 from qpid_interop_test.jms_types import QPID_JMS_TYPE_ANNOTATION_NAME
+import _compat
 
 class JmsMessagesTestReceiver(MessagingHandler):
     """
@@ -56,7 +57,7 @@ class JmsMessagesTestReceiver(MessagingHandler):
         self.current_subtype_msg_list = None
 
     def get_received_value_map(self):
-        """"Return the collected message values received"""
+        """Return the collected message values received"""
         return self.received_value_map
 
     def on_start(self, event):
@@ -66,11 +67,14 @@ class JmsMessagesTestReceiver(MessagingHandler):
 
     def on_message(self, event):
         """Event callback when a message is received by the client"""
-        if event.message.id and event.message.id < self.received:
+        if event.message.id and isinstance(event.message.id, int) and event.message.id < self.received:
             return # ignore duplicate message
         if self.received < self.expected:
             if self.current_subtype is None:
-                self.current_subtype = self.subtype_itr.next()
+                if _compat.IS_PY3:
+                    self.current_subtype = next(self.subtype_itr)
+                else:
+                    self.current_subtype = self.subtype_itr.next()
                 self.current_subtype_msg_list = []
             self.current_subtype_msg_list.append(self._handle_message(event.message))
             if len(self.current_subtype_msg_list) >= self.expteced_msg_map[self.current_subtype]:
@@ -109,14 +113,14 @@ class JmsMessagesTestReceiver(MessagingHandler):
         return None
 
     def _get_tot_num_messages(self):
-        """"Counts up the total number of messages which should be received from the expected message map"""
+        """Counts up the total number of messages which should be received from the expected message map"""
         total = 0
         for key in self.expteced_msg_map:
             total += int(self.expteced_msg_map[key])
         return total
 
     def _receive_jms_message(self, message):
-        """"Receives a JMS message (without a body)"""
+        """Receives a JMS message (without a body)"""
         assert self.jms_msg_type == 'JMS_MESSAGE_TYPE'
         assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(0)
         if message.body is not None:
@@ -125,7 +129,7 @@ class JmsMessagesTestReceiver(MessagingHandler):
         return None
 
     def _receive_jms_bytesmessage(self, message):
-        """"Receives a JMS bytes message"""
+        """Receives a JMS bytes message"""
         assert self.jms_msg_type == 'JMS_BYTESMESSAGE_TYPE'
         assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(3)
         if self.current_subtype == 'boolean':
@@ -138,11 +142,14 @@ class JmsMessagesTestReceiver(MessagingHandler):
         if self.current_subtype == 'byte':
             return hex(unpack('b', message.body)[0])
         if self.current_subtype == 'bytes':
-            return str(message.body)
+            return message.body.decode('utf-8')
         if self.current_subtype == 'char':
             if len(message.body) == 2: # format 'a' or '\xNN'
-                return str(message.body[1]) # strip leading '\x00' char
-            raise InteropTestError('Unexpected strring length for type char: %d' % len(message.body))
+                if _compat.IS_PY3:
+                    return chr(message.body[1]) # strip leading '\x00' char
+                else:
+                    return str(message.body[1]) # strip leading '\x00' char
+            raise InteropTestError('Unexpected string length for type char: %d' % len(message.body))
         if self.current_subtype == 'double':
             return '0x%016x' % unpack('!Q', message.body)[0]
         if self.current_subtype == 'float':
@@ -157,7 +164,7 @@ class JmsMessagesTestReceiver(MessagingHandler):
             # NOTE: first 2 bytes are string length, must be present
             if len(message.body) >= 2:
                 str_len = unpack('!H', message.body[:2])[0]
-                str_body = str(message.body[2:])
+                str_body = message.body[2:].decode('utf-8')
                 if len(str_body) != str_len:
                     raise InteropTestError('String length mismatch: size=%d, but len(\'%s\')=%d' %
                                            (str_len, str_body, len(str_body)))
@@ -169,17 +176,17 @@ class JmsMessagesTestReceiver(MessagingHandler):
                                (self.jms_msg_type, self.current_subtype))
 
     def _recieve_jms_mapmessage(self, message):
-        """"Receives a JMS map message"""
+        """Receives a JMS map message"""
         assert self.jms_msg_type == 'JMS_MAPMESSAGE_TYPE'
         assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(2)
-        key, value = message.body.items()[0]
+        key, value = list(message.body.items())[0]
         assert key[:-3] == self.current_subtype
         if self.current_subtype == 'boolean':
             return str(value)
         if self.current_subtype == 'byte':
             return hex(value)
         if self.current_subtype == 'bytes':
-            return str(value)
+            return value.decode('utf-8')
         if self.current_subtype == 'char':
             return str(value)
         if self.current_subtype == 'double':
@@ -198,7 +205,7 @@ class JmsMessagesTestReceiver(MessagingHandler):
                                (self.jms_msg_type, self.current_subtype))
 
     def _recieve_jms_objectmessage(self, message):
-        """"Receives a JMS Object message"""
+        """Receives a JMS Object message"""
         assert self.jms_msg_type == 'JMS_OBJECTMESSAGE_TYPE'
         assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(1)
         return self._get_java_obj(message.body)
@@ -242,7 +249,7 @@ class JmsMessagesTestReceiver(MessagingHandler):
         if self.current_subtype == 'byte':
             return hex(value)
         if self.current_subtype == 'bytes':
-            return str(value)
+            return value.decode('utf-8')
         if self.current_subtype == 'char':
             return str(value)
         if self.current_subtype == 'double':
@@ -262,7 +269,7 @@ class JmsMessagesTestReceiver(MessagingHandler):
                                (self.jms_msg_type, self.current_subtype))
 
     def _receive_jms_textmessage(self, message):
-        """"Receives a JMS text message"""
+        """Receives a JMS text message"""
         assert self.jms_msg_type == 'JMS_TEXTMESSAGE_TYPE'
         assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(5)
         return message.body

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/shims/qpid-proton-python/src/jms_messages_test/Sender.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/jms_messages_test/Sender.py b/shims/qpid-proton-python/src/jms_messages_test/Sender.py
index 472b014..6815dc5 100755
--- a/shims/qpid-proton-python/src/jms_messages_test/Sender.py
+++ b/shims/qpid-proton-python/src/jms_messages_test/Sender.py
@@ -153,12 +153,12 @@ class JmsMessagesTestSender(MessagingHandler):
         elif test_value_type == 'byte':
             body_bytes = pack('b', int(test_value, 16))
         elif test_value_type == 'bytes':
-            body_bytes = str(test_value) # remove unicode
+            body_bytes = test_value.encode('utf-8')
         elif test_value_type == 'char':
             # JMS expects two-byte chars, ASCII chars can be prefixed with '\x00'
-            body_bytes = '\x00' + str(test_value) # remove unicode
+            body_bytes = b'\x00' + test_value.encode('utf-8')
         elif test_value_type == 'double' or test_value_type == 'float':
-            body_bytes = test_value[2:].decode('hex')
+            body_bytes = _compat._decode_hex(test_value[2:])
         elif test_value_type == 'int':
             body_bytes = pack('!i', int(test_value, 16))
         elif test_value_type == 'long':
@@ -168,7 +168,7 @@ class JmsMessagesTestSender(MessagingHandler):
         elif test_value_type == 'string':
             # NOTE: First two bytes must be string length
             test_value_str = str(test_value) # remove unicode
-            body_bytes = pack('!H', len(test_value_str)) + test_value_str
+            body_bytes = pack('!H', len(test_value_str)) + test_value_str.encode('utf-8')
         else:
             raise InteropTestError('JmsMessagesTestSender._create_jms_bytesmessage: Unknown or unsupported subtype "%s"' %
                                    test_value_type)
@@ -185,13 +185,13 @@ class JmsMessagesTestSender(MessagingHandler):
         elif test_value_type == 'byte':
             value = byte(int(test_value, 16))
         elif test_value_type == 'bytes':
-            value = str(test_value) # remove unicode
+            value = test_value.encode('utf-8')
         elif test_value_type == 'char':
             value = char(test_value)
         elif test_value_type == 'double':
-            value = unpack('!d', test_value[2:].decode('hex'))[0]
+            value = unpack('!d', _compat._decode_hex(test_value[2:]))[0]
         elif test_value_type == 'float':
-            value = float32(unpack('!f', test_value[2:].decode('hex'))[0])
+            value = float32(unpack('!f', _compat._decode_hex(test_value[2:]))[0])
         elif test_value_type == 'int':
             value = int32(int(test_value, 16))
         elif test_value_type == 'long':
@@ -229,7 +229,7 @@ class JmsMessagesTestSender(MessagingHandler):
         if out_str_list[0] != java_class_str:
             raise InteropTestError('JmsMessagesTestSender._s_get_java_obj_binary(): Call to JavaObjToBytes failed\n%s' %
                                    out_str)
-        return out_str_list[1].decode('hex')
+        return _compat._decode_hex(out_str_list[1])
 
     def _create_jms_streammessage(self, test_value_type, test_value):
         """Create a JMS stream message"""
@@ -238,13 +238,13 @@ class JmsMessagesTestSender(MessagingHandler):
         elif test_value_type == 'byte':
             body_list = [byte(int(test_value, 16))]
         elif test_value_type == 'bytes':
-            body_list = [str(test_value)]
+            body_list = [test_value.encode('utf-8')]
         elif test_value_type == 'char':
             body_list = [char(test_value)]
         elif test_value_type == 'double':
-            body_list = [unpack('!d', test_value[2:].decode('hex'))[0]]
+            body_list = [unpack('!d', _compat._decode_hex(test_value[2:]))[0]]
         elif test_value_type == 'float':
-            body_list = [float32(unpack('!f', test_value[2:].decode('hex'))[0])]
+            body_list = [float32(unpack('!f', _compat._decode_hex(test_value[2:]))[0])]
         elif test_value_type == 'int':
             body_list = [int32(int(test_value, 16))]
         elif test_value_type == 'long':

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/src/python/qpid_interop_test/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/__init__.py b/src/python/qpid_interop_test/__init__.py
index 70204e4..31d5a2e 100644
--- a/src/python/qpid_interop_test/__init__.py
+++ b/src/python/qpid_interop_test/__init__.py
@@ -16,8 +16,3 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-
-import broker_properties
-import interop_test_errors
-import shims
-import test_type_map

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/src/python/qpid_interop_test/amqp_large_content_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_large_content_test.py b/src/python/qpid_interop_test/amqp_large_content_test.py
index 1d215c4..0b95b86 100755
--- a/src/python/qpid_interop_test/amqp_large_content_test.py
+++ b/src/python/qpid_interop_test/amqp_large_content_test.py
@@ -236,9 +236,8 @@ if __name__ == '__main__':
                     qpid_interop_test.shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
                 qpid_interop_test.shims.ProtonPython2Shim.NAME: \
                     qpid_interop_test.shims.ProtonPython2Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
-                # TODO: Enable the Python3 shim when Proton can build both Python2 and Python3 bindings
-                #qpid_interop_test.shims.ProtonPython3Shim.NAME: \
-                #    qpid_interop_test.shims.ProtonPython3Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
+                qpid_interop_test.shims.ProtonPython3Shim.NAME: \
+                    qpid_interop_test.shims.ProtonPython3Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
                }
     # Add shims that need detection during installation only if the necessary bits are present
     # AMQP DotNetLite client

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/src/python/qpid_interop_test/amqp_types_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_types_test.py b/src/python/qpid_interop_test/amqp_types_test.py
index ed027ca..17f3f1e 100755
--- a/src/python/qpid_interop_test/amqp_types_test.py
+++ b/src/python/qpid_interop_test/amqp_types_test.py
@@ -462,9 +462,8 @@ if __name__ == '__main__':
                     qpid_interop_test.shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
                 qpid_interop_test.shims.ProtonPython2Shim.NAME: \
                     qpid_interop_test.shims.ProtonPython2Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
-                # TODO: Enable the Python3 shim when Proton can build both Python2 and Python3 bindings
-                #qpid_interop_test.shims.ProtonPython3Shim.NAME: \
-                #    qpid_interop_test.shims.ProtonPython3Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
+                qpid_interop_test.shims.ProtonPython3Shim.NAME: \
+                    qpid_interop_test.shims.ProtonPython3Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
                }
     # Add shims that need detection during installation only if the necessary bits are present
     # Rhea Javascript client

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/src/python/qpid_interop_test/interop_test_errors.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/interop_test_errors.py b/src/python/qpid_interop_test/interop_test_errors.py
index 6be8959..f300057 100644
--- a/src/python/qpid_interop_test/interop_test_errors.py
+++ b/src/python/qpid_interop_test/interop_test_errors.py
@@ -21,7 +21,7 @@ Module containing Error classes for interop testing
 # under the License.
 #
 
-class InteropTestError(StandardError):
+class InteropTestError(Exception):
     """
     Generic simple error class for use in interop tests
     """

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/src/python/qpid_interop_test/jms_hdrs_props_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/jms_hdrs_props_test.py b/src/python/qpid_interop_test/jms_hdrs_props_test.py
index baf0f64..acefabf 100755
--- a/src/python/qpid_interop_test/jms_hdrs_props_test.py
+++ b/src/python/qpid_interop_test/jms_hdrs_props_test.py
@@ -121,10 +121,10 @@ class JmsMessageTypes(TestTypeMap):
                   b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
                   b'The quick brown fox jumped over the lazy dog 0123456789.' #* 100],
                  ],
-        'char': ['a',
-                 'Z',
-                 '\x01',
-                 '\x7f'],
+        'char': [b'a',
+                 b'Z',
+                 b'\x01',
+                 b'\x7f'],
         }
 
     # The TYPE_SUBMAP defines test values for JMS message types that allow typed message content. Note that the
@@ -703,9 +703,8 @@ if __name__ == '__main__':
                     qpid_interop_test.shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
                 qpid_interop_test.shims.ProtonPython2Shim.NAME: \
                     qpid_interop_test.shims.ProtonPython2Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
-                # TODO: Enable the Python3 shim when Proton can build both Python2 and Python3 bindings
-                #qpid_interop_test.shims.ProtonPython3Shim.NAME: \
-                #    qpid_interop_test.shims.ProtonPython3Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
+                qpid_interop_test.shims.ProtonPython3Shim.NAME: \
+                    qpid_interop_test.shims.ProtonPython3Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
                 qpid_interop_test.shims.QpidJmsShim.NAME: \
                     qpid_interop_test.shims.QpidJmsShim(QIT_JMS_CLASSPATH, QPID_JMS_SENDER_SHIM, QPID_JMS_RECEIVER_SHIM),
                }

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/src/python/qpid_interop_test/jms_messages_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/jms_messages_test.py b/src/python/qpid_interop_test/jms_messages_test.py
index 29ab3ff..4798cf0 100755
--- a/src/python/qpid_interop_test/jms_messages_test.py
+++ b/src/python/qpid_interop_test/jms_messages_test.py
@@ -122,10 +122,10 @@ class JmsMessageTypes(TestTypeMap):
                   b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
                   b'The quick brown fox jumped over the lazy dog 0123456789.' #* 100],
                  ],
-        'char': ['a',
-                 'Z',
-                 '\x01',
-                 '\x7f'],
+        'char': [b'a',
+                 b'Z',
+                 b'\x01',
+                 b'\x7f'],
         }
 
     # The TYPE_SUBMAP defines test values for JMS message types that allow typed message content. Note that the
@@ -356,9 +356,8 @@ if __name__ == '__main__':
                     qpid_interop_test.shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
                 qpid_interop_test.shims.ProtonPython2Shim.NAME: \
                     qpid_interop_test.shims.ProtonPython2Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
-                # TODO: Enable the Python3 shim when Proton can build both Python2 and Python3 bindings
-                #qpid_interop_test.shims.ProtonPython3Shim.NAME: \
-                #    qpid_interop_test.shims.ProtonPython3Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
+                qpid_interop_test.shims.ProtonPython3Shim.NAME: \
+                    qpid_interop_test.shims.ProtonPython3Shim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
                 qpid_interop_test.shims.QpidJmsShim.NAME: \
                     qpid_interop_test.shims.QpidJmsShim(QIT_JMS_CLASSPATH, QPID_JMS_SENDER_SHIM, QPID_JMS_RECEIVER_SHIM),
                }

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/src/python/qpid_interop_test/shims.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/shims.py b/src/python/qpid_interop_test/shims.py
index ecc4610..6ba5da6 100644
--- a/src/python/qpid_interop_test/shims.py
+++ b/src/python/qpid_interop_test/shims.py
@@ -20,8 +20,9 @@ Module containing worker thread classes and shims
 # under the License.
 #
 
+from copy import deepcopy
 from json import loads
-from os import getenv, getpgid, killpg, path, setsid
+from os import environ, getenv, getpgid, killpg, path, setsid
 from signal import SIGKILL, SIGTERM
 from subprocess import Popen, PIPE, CalledProcessError
 from sys import stdout
@@ -50,6 +51,9 @@ class ShimWorkerThread(Thread):
         killed
         """
         self.join(timeout)
+        self.kill()
+
+    def kill(self, num_attempts=2, wait_time=2):
         if self.is_alive():
             if self.proc is not None:
                 if self._terminate_pg_loop():
@@ -89,19 +93,22 @@ class ShimWorkerThread(Thread):
 
 class Sender(ShimWorkerThread):
     """Sender class for multi-threaded send"""
-    def __init__(self, use_shell_flag, send_shim_args, broker_addr, queue_name, test_key, json_test_str):
+    def __init__(self, use_shell_flag, send_shim_args, broker_addr, queue_name, test_key, json_test_str, python3_flag):
         super(Sender, self).__init__('sender_thread_%s' % queue_name)
         if send_shim_args is None:
             print 'ERROR: Sender: send_shim_args == None'
         self.use_shell_flag = use_shell_flag
         self.arg_list.extend(send_shim_args)
         self.arg_list.extend([broker_addr, queue_name, test_key, json_test_str])
+        self.env = deepcopy(environ)
+        if python3_flag:
+            self.env['PYTHONPATH']=self.env['PYTHON3PATH']
 
     def run(self):
         """Thread starts here"""
         try:
             #print str('\n>>SNDR>>' + str(self.arg_list)) # DEBUG - useful to see command-line sent to shim
-            self.proc = Popen(self.arg_list, stdout=PIPE, stderr=PIPE, shell=self.use_shell_flag, preexec_fn=setsid)
+            self.proc = Popen(self.arg_list, stdout=PIPE, stderr=PIPE, shell=self.use_shell_flag, preexec_fn=setsid, env=self.env)
             (stdoutdata, stderrdata) = self.proc.communicate()
             if len(stderrdata) > 0:
                 #print '<<SNDR ERROR<<', stderrdata # DEBUG - useful to see shim's failure message
@@ -124,18 +131,21 @@ class Sender(ShimWorkerThread):
 
 class Receiver(ShimWorkerThread):
     """Receiver class for multi-threaded receive"""
-    def __init__(self, receive_shim_args, broker_addr, queue_name, test_key, json_test_str):
+    def __init__(self, receive_shim_args, broker_addr, queue_name, test_key, json_test_str, python3_flag):
         super(Receiver, self).__init__('receiver_thread_%s' % queue_name)
         if receive_shim_args is None:
             print 'ERROR: Receiver: receive_shim_args == None'
         self.arg_list.extend(receive_shim_args)
         self.arg_list.extend([broker_addr, queue_name, test_key, json_test_str])
+        self.env = deepcopy(environ)
+        if python3_flag:
+            self.env['PYTHONPATH']=self.env['PYTHON3PATH']
 
     def run(self):
         """Thread starts here"""
         try:
             #print str('\n>>RCVR>>' + str(self.arg_list)) # DEBUG - useful to see command-line sent to shim
-            self.proc = Popen(self.arg_list, stdout=PIPE, stderr=PIPE, preexec_fn=setsid)
+            self.proc = Popen(self.arg_list, stdout=PIPE, stderr=PIPE, preexec_fn=setsid, env=self.env)
             (stdoutdata, stderrdata) = self.proc.communicate()
             if len(stderrdata) > 0:
                 #print '<<RCVR ERROR<<', stderrdata # DEBUG - useful to see shim's failure message
@@ -168,13 +178,15 @@ class Shim(object):
 
     def create_sender(self, broker_addr, queue_name, test_key, json_test_str):
         """Create a new sender instance"""
-        sender = Sender(self.use_shell_flag, self.send_params, broker_addr, queue_name, test_key, json_test_str)
+        sender = Sender(self.use_shell_flag, self.send_params, broker_addr, queue_name, test_key, json_test_str,
+                        'Python3' in self.NAME)
         sender.daemon = True
         return sender
 
     def create_receiver(self, broker_addr, queue_name, test_key, json_test_str):
         """Create a new receiver instance"""
-        receiver = Receiver(self.receive_params, broker_addr, queue_name, test_key, json_test_str)
+        receiver = Receiver(self.receive_params, broker_addr, queue_name, test_key, json_test_str,
+                            'Python3' in self.NAME)
         receiver.daemon = True
         return receiver
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/ee57f686/src/python/qpid_interop_test/test_type_map.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/test_type_map.py b/src/python/qpid_interop_test/test_type_map.py
index 378f0e2..59e5686 100644
--- a/src/python/qpid_interop_test/test_type_map.py
+++ b/src/python/qpid_interop_test/test_type_map.py
@@ -86,7 +86,7 @@ class TestTypeMap(object):
                 try:
                     new_type_map[type] = self.TYPE_MAP[type]
                 except KeyError:
-                    print 'No such type: "%s". Use --help for valid types' % type
+                    print('No such type: "%s". Use --help for valid types' % type)
                     sys.exit(1) # Errors or failures present
             self.TYPE_MAP = new_type_map
         if "exclude_type" in args and args.exclude_type is not None:
@@ -94,7 +94,7 @@ class TestTypeMap(object):
                 try:
                     self.TYPE_MAP.pop(type)
                 except KeyError:
-                    print 'No such type: "%s". Use --help for valid types' % type
+                    print('No such type: "%s". Use --help for valid types' % type)
                     sys.exit(1) # Errors or failures present
         return self
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org