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 2020/08/12 21:26:04 UTC

[qpid-proton] branch python-check-property-keys updated: PROTON-2237: Final tidy-up of logic and structure, added function doc to explain what is happening.

This is an automated email from the ASF dual-hosted git repository.

kpvdr pushed a commit to branch python-check-property-keys
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git


The following commit(s) were added to refs/heads/python-check-property-keys by this push:
     new e089561  PROTON-2237: Final tidy-up of logic and structure, added function doc to explain what is happening.
e089561 is described below

commit e089561d0b560a12198f29211aba95fa758fa81d
Author: Kim van der Riet <kp...@apache.org>
AuthorDate: Wed Aug 12 17:25:47 2020 -0400

    PROTON-2237: Final tidy-up of logic and structure, added function doc to explain what is happening.
---
 python/proton/_message.py            | 33 ++++++++++++++++++++++-----------
 python/tests/proton_tests/message.py |  5 +++++
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/python/proton/_message.py b/python/proton/_message.py
index 4780c14..4d022e0 100644
--- a/python/proton/_message.py
+++ b/python/proton/_message.py
@@ -38,6 +38,8 @@ from ._data import char, Data, decimal128, symbol, ulong, AnnotationDict
 from ._endpoints import Link
 from ._exceptions import EXCEPTIONS, MessageException
 
+from sys import version_info
+
 #
 # Hack to provide Python2 <---> Python3 compatibility
 try:
@@ -89,21 +91,30 @@ class Message(object):
             return err
 
     def _check_property_keys(self):
-        # In Py3, we cannot make changes to the dict while iterating, so we
+        '''
+        AMQP allows only string keys for properties. This function checks that this requirement is met
+        and raises a MessageException if not. However, in certain cases, conversions to string are
+        automatically performed:
+
+        1. When a key is a user-defined (non-AMQP) subclass of unicode/str (py2/py3).
+           AMQP types symbol and char, although derived from unicode/str, are not converted,
+           and result in an exception.
+
+        2. In Py2, when a key is binary. This is a convenience for Py2 users that encode
+           string literals without using the u'' prefix. In Py3, this is not the case, and
+           using a binary key will result in an error. AMQP type decimal128, which is derived
+           from binary, will not be converted, and will result in an exception.
+        '''
+        # We cannot make changes to the dict while iterating, so we
         # must save and make the changes afterwards
         changed_keys = []
         for k in self.properties.keys():
-            # Check for string types. (py2: unicode, py3: str via type hack above)
-            # or string subclasses. Exclude string subclasses symbol and char.
-            if isinstance(k, unicode) and not (type(k) is symbol or type(k) is char):
-                # Convert string subclasses to string
-                if not type(k) is unicode:
+            # If key is a subclass of unicode, convert to unicode. Exclude unicode subclasses symbol and char.
+            if isinstance(k, unicode)and not (type(k) is symbol or type(k) is char):
+                if type(k) is not unicode:
                     changed_keys.append((k, unicode(k)))
-                continue
-            # If key is binary then change to string. Exclude bytes subclass decimal128.
-            # Mostly for py2 users who encode strings without using the u'' prefix
-            # but py3 bytes() type will be converted also
-            elif isinstance(k, bytes) and not (type(k) is decimal128):
+            # Py2 only: If key is binary then convert to unicode. Exclude bytes subclass decimal128.
+            elif version_info[0] == 2 and isinstance(k, bytes) and not (type(k) is decimal128):
                 changed_keys.append((k, k.decode('utf-8')))
             else:
                 raise MessageException('Application property key is not string type: key=%s %s' % (str(k), type(k)))
diff --git a/python/tests/proton_tests/message.py b/python/tests/proton_tests/message.py
index e3afdd8..4fcaa1b 100644
--- a/python/tests/proton_tests/message.py
+++ b/python/tests/proton_tests/message.py
@@ -20,6 +20,8 @@
 from __future__ import absolute_import
 
 from uuid import uuid4
+from sys import version_info
+from unittest import skipIf
 
 from proton import *
 
@@ -143,6 +145,7 @@ class CodecTest(Test):
     for k in msg2.properties:
         assert type(k) is unicode, 'non-string key %s %s' % (k, type(k))
 
+  @skipIf(version_info[0] != 2, 'Property key binary to string conversion only supported for Py2')
   def testBinaryPropertyKey(self):
     self.msg.properties = {'abc': 123, b'def': 456}
     data = self.msg.encode()
@@ -180,6 +183,8 @@ class CodecTest(Test):
     self._testNonStringPropertyKey(decimal64(12))
     self._testNonStringPropertyKey(timestamp(1234567890))
     self._testNonStringPropertyKey(uuid4())
+    if version_info[0] == 3: # Py3 only
+        self._testNonStringPropertyKey(b'abc123')
 
   def testCharPropertyKey(self):
     self._testNonStringPropertyKey(char('A'))


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