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-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org