Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-u-msgpack-python for 
openSUSE:Factory checked in at 2022-10-12 18:22:29
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-u-msgpack-python (Old)
 and      /work/SRC/openSUSE:Factory/.python-u-msgpack-python.new.2275 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-u-msgpack-python"

Wed Oct 12 18:22:29 2022 rev:10 rq:1009898 version:2.7.1

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-u-msgpack-python/python-u-msgpack-python.changes
  2020-08-01 12:30:34.982423388 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-u-msgpack-python.new.2275/python-u-msgpack-python.changes
        2022-10-12 18:22:31.685340176 +0200
@@ -1,0 +2,7 @@
+Tue Oct 11 16:38:21 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com>
+
+- Update to Version 2.7.1 - 10/24/2020
+  * Add Ext type value validation to Ext class and ext_serializable() 
decorator.
+  * Change string formatting from % to .format() throughout codebase. 
+
+-------------------------------------------------------------------

Old:
----
  u-msgpack-python-2.6.0.tar.gz

New:
----
  u-msgpack-python-2.7.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-u-msgpack-python.spec ++++++
--- /var/tmp/diff_new_pack.zslnuI/_old  2022-10-12 18:22:32.553342345 +0200
+++ /var/tmp/diff_new_pack.zslnuI/_new  2022-10-12 18:22:32.557342355 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-u-msgpack-python
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-u-msgpack-python
-Version:        2.6.0
+Version:        2.7.1
 Release:        0
 Summary:        A MessagePack serializer and deserializer
 License:        MIT

++++++ u-msgpack-python-2.6.0.tar.gz -> u-msgpack-python-2.7.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/u-msgpack-python-2.6.0/PKG-INFO 
new/u-msgpack-python-2.7.1/PKG-INFO
--- old/u-msgpack-python-2.6.0/PKG-INFO 2020-04-25 10:39:46.034381400 +0200
+++ new/u-msgpack-python-2.7.1/PKG-INFO 2020-10-25 04:53:11.778906000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: u-msgpack-python
-Version: 2.6.0
+Version: 2.7.1
 Summary: A portable, lightweight MessagePack serializer and deserializer 
written in pure Python.
 Home-page: https://github.com/vsergeev/u-msgpack-python
 Author: vsergeev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/u-msgpack-python-2.6.0/README.md 
new/u-msgpack-python-2.7.1/README.md
--- old/u-msgpack-python-2.6.0/README.md        2020-04-25 10:31:46.000000000 
+0200
+++ new/u-msgpack-python-2.7.1/README.md        2020-10-25 04:08:04.000000000 
+0100
@@ -64,14 +64,14 @@
 
 Serializing and deserializing a raw Ext type:
 ``` python
->>> # Create an Ext object with type 0x05 and data b"\x01\x02\x03"
-... foo = umsgpack.Ext(0x05, b"\x01\x02\x03")
+>>> # Create an Ext object with type 5 and data b"\x01\x02\x03"
+... foo = umsgpack.Ext(5, b"\x01\x02\x03")
 >>> umsgpack.packb({u"stuff": foo, u"awesome": True})
 b'\x82\xa5stuff\xc7\x03\x05\x01\x02\x03\xa7awesome\xc3'
 >>> 
 >>> bar = umsgpack.unpackb(_)
 >>> print(bar['stuff'])
-Ext Object (Type: 0x05, Data: 0x01 0x02 0x03)
+Ext Object (Type: 5, Data: 0x01 0x02 0x03)
 >>> bar['stuff'].type
 5
 >>> bar['stuff'].data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/u-msgpack-python-2.6.0/setup.py 
new/u-msgpack-python-2.7.1/setup.py
--- old/u-msgpack-python-2.6.0/setup.py 2020-04-25 10:31:46.000000000 +0200
+++ new/u-msgpack-python-2.7.1/setup.py 2020-10-25 04:50:17.000000000 +0100
@@ -5,7 +5,7 @@
 
 setup(
     name='u-msgpack-python',
-    version='2.6.0',
+    version='2.7.1',
     description='A portable, lightweight MessagePack serializer and 
deserializer written in pure Python.',
     author='vsergeev',
     author_email='v...@sergeev.io',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/u-msgpack-python-2.6.0/test_umsgpack.py 
new/u-msgpack-python-2.7.1/test_umsgpack.py
--- old/u-msgpack-python-2.6.0/test_umsgpack.py 2020-04-25 10:21:55.000000000 
+0200
+++ new/u-msgpack-python-2.7.1/test_umsgpack.py 2020-10-25 04:50:17.000000000 
+0100
@@ -404,24 +404,24 @@
     def test_pack_single(self):
         for (name, obj, data) in single_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             self.assertEqual(umsgpack.packb(obj), data)
 
     def test_pack_composite(self):
         for (name, obj, data) in composite_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             self.assertEqual(umsgpack.packb(obj), data)
 
     def test_pack_exceptions(self):
         for (name, obj, exception) in pack_exception_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             with self.assertRaises(exception):
                 umsgpack.packb(obj)
@@ -429,8 +429,8 @@
     def test_unpack_single(self):
         for (name, obj, data) in single_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             unpacked = umsgpack.unpackb(data)
 
@@ -452,14 +452,14 @@
     def test_unpack_composite(self):
         for (name, obj, data) in composite_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             self.assertEqual(umsgpack.unpackb(data), obj)
 
     def test_unpack_exceptions(self):
         for (name, data, exception) in unpack_exception_test_vectors:
-            print("\tTesting %s" % name)
+            print("\tTesting {:s}".format(name))
 
             with self.assertRaises(exception):
                 umsgpack.unpackb(data)
@@ -469,8 +469,8 @@
 
         for (name, obj, data) in compatibility_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             self.assertEqual(umsgpack.packb(obj), data)
 
@@ -481,8 +481,8 @@
 
         for (name, obj, data) in compatibility_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             unpacked = umsgpack.unpackb(data)
 
@@ -539,17 +539,25 @@
         self.assertEqual(umsgpack.unpackb(data, use_tuple=True), obj_tuple)
 
     def test_ext_exceptions(self):
+        # Test invalid Ext type type
         with self.assertRaises(TypeError):
             _ = umsgpack.Ext(5.0, b"")
 
+        # Test invalid data type
         with self.assertRaises(TypeError):
             _ = umsgpack.Ext(0, u"unicode string")
 
+        # Test out of range Ext type value
+        with self.assertRaises(ValueError):
+            _ = umsgpack.Ext(-129, b"data")
+        with self.assertRaises(ValueError):
+            _ = umsgpack.Ext(128, b"data")
+
     def test_pack_ext_handler(self):
         for (name, obj, data) in ext_handlers_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             packed = umsgpack.packb(obj, ext_handlers=ext_handlers)
             self.assertEqual(packed, data)
@@ -557,8 +565,8 @@
     def test_unpack_ext_handler(self):
         for (name, obj, data) in ext_handlers_test_vectors:
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             unpacked = umsgpack.unpackb(data, ext_handlers=ext_handlers)
             self.assertEqual(unpacked, obj)
@@ -566,8 +574,8 @@
     def test_pack_force_float_precision(self):
         for ((name, obj, data), precision) in 
zip(float_precision_test_vectors, ["single", "double"]):
             obj_repr = repr(obj)
-            print("\tTesting %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             packed = umsgpack.packb(obj, force_float_precision=precision)
             self.assertEqual(packed, data)
@@ -575,8 +583,8 @@
     def test_pack_naive_timestamp(self):
         for (name, obj, data, _) in naive_timestamp_test_vectors:
             obj_repr = repr(obj)
-            print("\t Testing %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             packed = umsgpack.packb(obj)
             self.assertEqual(packed, data)
@@ -584,8 +592,8 @@
     def test_unpack_naive_timestamp(self):
         for (name, _, data, obj) in naive_timestamp_test_vectors:
             obj_repr = repr(obj)
-            print("\t Testing %s: object %s" %
-                  (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+            print("\tTesting {:s}: object {:s}".format(
+                  name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
             unpacked = umsgpack.unpackb(data)
             self.assertEqual(unpacked, obj)
@@ -594,8 +602,8 @@
         # Test overridden packing of datetime.datetime
         (name, obj, data) = override_ext_handlers_test_vectors[0]
         obj_repr = repr(obj)
-        print("\tTesting %s: object %s" %
-              (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+        print("\tTesting {:s}: object {:s}".format(
+              name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
         packed = umsgpack.packb(obj, ext_handlers=override_ext_handlers)
         self.assertEqual(packed, data)
@@ -604,12 +612,37 @@
         # Test overridden unpacking of Ext type -1
         (name, obj, data) = override_ext_handlers_test_vectors[1]
         obj_repr = repr(obj)
-        print("\tTesting %s: object %s" %
-              (name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
+        print("\tTesting {:s}: object {:s}".format(
+              name, obj_repr if len(obj_repr) < 24 else obj_repr[0:24] + 
"..."))
 
         unpacked = umsgpack.unpackb(data, ext_handlers=override_ext_handlers)
         self.assertEqual(unpacked, obj)
 
+    def test_ext_handlers_subclass(self):
+        class Rectangle:
+            def __init__(self, length, width):
+                self.length = length
+                self.width = width
+
+            def __eq__(self, other):
+                return self.length == other.length and self.width == 
other.width
+
+        class Square(Rectangle):
+            def __init__(self, width):
+                Rectangle.__init__(self, width, width)
+
+        # Test pack (packs base class)
+        packed = umsgpack.packb(Square(5), ext_handlers={
+            Rectangle: lambda obj: umsgpack.Ext(0x10, 
umsgpack.packb([obj.length, obj.width])),
+        })
+        self.assertEqual(packed, b"\xc7\x03\x10\x92\x05\x05")
+
+        # Test unpack (unpacks base class)
+        unpacked = umsgpack.unpackb(packed, ext_handlers={
+            0x10: lambda ext: Rectangle(*umsgpack.unpackb(ext.data)),
+        })
+        self.assertEqual(unpacked, Rectangle(5, 5))
+
     def test_ext_serializable(self):
         # Register test class
         @umsgpack.ext_serializable(0x20)
@@ -656,6 +689,16 @@
             class DummyClass:
                 pass
 
+        # Test out of range Ext type value
+        with self.assertRaises(ValueError):
+            @umsgpack.ext_serializable(-129)
+            class DummyClass2:
+                pass
+        with self.assertRaises(ValueError):
+            @umsgpack.ext_serializable(128)
+            class DummyClass3:
+                pass
+
         # Register class with missing packb() and unpackb()
         @umsgpack.ext_serializable(0x21)
         class IncompleteClass:
@@ -669,8 +712,44 @@
         with self.assertRaises(NotImplementedError):
             umsgpack.unpackb(b"\xd4\x21\x00")
 
-        # Unregister Ext serializable classes for future tests
-        umsgpack._ext_classes = {}
+        # Unregister Ext serializable classes to prevent interference with
+        # subsequent tests
+        umsgpack._ext_classes_to_code = {}
+        umsgpack._ext_code_to_classes = {}
+
+    def test_ext_serializable_subclass(self):
+        @umsgpack.ext_serializable(0x10)
+        class Rectangle:
+            def __init__(self, length, width):
+                self.length = length
+                self.width = width
+
+            def __eq__(self, other):
+                return self.length == other.length and self.width == 
other.width
+
+            def packb(self):
+                return umsgpack.packb([self.length, self.width])
+
+            @classmethod
+            def unpackb(cls, data):
+                return cls(*umsgpack.unpackb(data))
+
+        class Square(Rectangle):
+            def __init__(self, width):
+                Rectangle.__init__(self, width, width)
+
+        # Test pack (packs base class)
+        packed = umsgpack.packb(Square(5))
+        self.assertEqual(packed, b"\xc7\x03\x10\x92\x05\x05")
+
+        # Test unpack (unpacks base class)
+        unpacked = umsgpack.unpackb(packed)
+        self.assertEqual(unpacked, Rectangle(5, 5))
+
+        # Unregister Ext serializable classes to prevent interference with
+        # subsequent tests
+        umsgpack._ext_classes_to_code = {}
+        umsgpack._ext_code_to_classes = {}
 
     def test_streaming_writer(self):
         # Try first composite test vector
@@ -687,11 +766,10 @@
 
     def test_namespacing(self):
         # Get a list of global variables from umsgpack module
-        exported_vars = list(filter(lambda x: not x.startswith("_"),
-                                    dir(umsgpack)))
+        exported_vars = list([x for x in dir(umsgpack) if not 
x.startswith("_")])
         # Ignore imports
-        exported_vars = list(filter(lambda x: x != "struct" and x != 
"collections" and x != "datetime" and x !=
-                                    "sys" and x != "io" and x != "xrange" and 
x != "Hashable", exported_vars))
+        exported_vars = list([x for x in exported_vars if x != "struct" and x 
!= "collections" and x != "datetime" and x !=
+                                    "sys" and x != "io" and x != "xrange" and 
x != "Hashable"])
 
         self.assertTrue(len(exported_vars) == len(exported_vars_test_vector))
         for var in exported_vars_test_vector:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/u-msgpack-python-2.6.0/u_msgpack_python.egg-info/PKG-INFO 
new/u-msgpack-python-2.7.1/u_msgpack_python.egg-info/PKG-INFO
--- old/u-msgpack-python-2.6.0/u_msgpack_python.egg-info/PKG-INFO       
2020-04-25 10:39:45.000000000 +0200
+++ new/u-msgpack-python-2.7.1/u_msgpack_python.egg-info/PKG-INFO       
2020-10-25 04:53:11.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: u-msgpack-python
-Version: 2.6.0
+Version: 2.7.1
 Summary: A portable, lightweight MessagePack serializer and deserializer 
written in pure Python.
 Home-page: https://github.com/vsergeev/u-msgpack-python
 Author: vsergeev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/u-msgpack-python-2.6.0/umsgpack.py 
new/u-msgpack-python-2.7.1/umsgpack.py
--- old/u-msgpack-python-2.6.0/umsgpack.py      2020-04-25 10:31:46.000000000 
+0200
+++ new/u-msgpack-python-2.7.1/umsgpack.py      2020-10-25 04:50:17.000000000 
+0100
@@ -1,4 +1,4 @@
-# u-msgpack-python v2.6.0 - v at sergeev.io
+# u-msgpack-python v2.7.1 - v at sergeev.io
 # https://github.com/vsergeev/u-msgpack-python
 #
 # u-msgpack-python is a lightweight MessagePack serializer and deserializer
@@ -31,7 +31,7 @@
 # THE SOFTWARE.
 #
 """
-u-msgpack-python v2.6.0 - v at sergeev.io
+u-msgpack-python v2.7.1 - v at sergeev.io
 https://github.com/vsergeev/u-msgpack-python
 
 u-msgpack-python is a lightweight MessagePack serializer and deserializer
@@ -54,10 +54,10 @@
 else:
     from collections import Hashable
 
-__version__ = "2.6.0"
+__version__ = "2.7.1"
 "Module version string"
 
-version = (2, 6, 0)
+version = (2, 7, 1)
 "Module version tuple"
 
 
@@ -80,23 +80,33 @@
             type: application-defined type integer
             data: application-defined data byte array
 
+        TypeError:
+            Type is not an integer.
+        ValueError:
+            Type is out of range of -128 to 127.
+        TypeError::
+            Data is not type 'bytes' (Python 3) or not type 'str' (Python 2).
+
         Example:
-        >>> foo = umsgpack.Ext(0x05, b"\x01\x02\x03")
+        >>> foo = umsgpack.Ext(5, b"\x01\x02\x03")
         >>> umsgpack.packb({u"special stuff": foo, u"awesome": True})
         '\x82\xa7awesome\xc3\xadspecial stuff\xc7\x03\x05\x01\x02\x03'
         >>> bar = umsgpack.unpackb(_)
         >>> print(bar["special stuff"])
-        Ext Object (Type: 0x05, Data: 01 02 03)
+        Ext Object (Type: 5, Data: 01 02 03)
         >>>
         """
-        # Check type is type int
+        # Check type is type int and in range
         if not isinstance(type, int):
             raise TypeError("ext type is not type integer")
-        # Check data is type bytes
+        elif not (-2**7 <= type <= 2**7 - 1):
+            raise ValueError("ext type value {:d} is out of range (-128 to 
127)".format(type))
+        # Check data is type bytes or str
         elif sys.version_info[0] == 3 and not isinstance(data, bytes):
             raise TypeError("ext data is not type \'bytes\'")
         elif sys.version_info[0] == 2 and not isinstance(data, str):
             raise TypeError("ext data is not type \'str\'")
+
         self.type = type
         self.data = data
 
@@ -117,8 +127,8 @@
         """
         String representation of this Ext object.
         """
-        s = "Ext Object (Type: 0x%02x, Data: " % self.type
-        s += " ".join(["0x%02x" % ord(self.data[i:i + 1])
+        s = "Ext Object (Type: {:d}, Data: ".format(self.type)
+        s += " ".join(["0x{:02}".format(ord(self.data[i:i + 1]))
                        for i in xrange(min(len(self.data), 8))])
         if len(self.data) > 8:
             s += " ..."
@@ -140,7 +150,8 @@
 # Ext Serializable Decorator
 ##############################################################################
 
-_ext_classes = {}
+_ext_class_to_type = {}
+_ext_type_to_class = {}
 
 
 def ext_serializable(ext_type):
@@ -155,17 +166,25 @@
         ext_type: application-defined Ext type code
 
     Raises:
+        TypeError:
+            Ext type is not an integer.
+        ValueError:
+            Ext type is out of range of -128 to 127.
         ValueError:
             Ext type or class already registered.
     """
     def wrapper(cls):
-        if ext_type in _ext_classes:
-            raise ValueError("Ext type 0x{:02x} already registered with class 
{:s}".format(ext_type, repr(_ext_classes[ext_type])))
-        elif cls in _ext_classes:
-            raise ValueError("Class {:s} already registered with Ext type 
0x{:02x}".format(repr(cls), ext_type))
+        if not isinstance(ext_type, int):
+            raise TypeError("Ext type is not type integer")
+        elif not (-2**7 <= ext_type <= 2**7 - 1):
+            raise ValueError("Ext type value {:d} is out of range of -128 to 
127".format(ext_type))
+        elif ext_type in _ext_type_to_class:
+            raise ValueError("Ext type {:d} already registered with class 
{:s}".format(ext_type, repr(_ext_type_to_class[ext_type])))
+        elif cls in _ext_class_to_type:
+            raise ValueError("Class {:s} already registered with Ext type 
{:d}".format(repr(cls), ext_type))
 
-        _ext_classes[ext_type] = cls
-        _ext_classes[cls] = ext_type
+        _ext_type_to_class[ext_type] = cls
+        _ext_class_to_type[cls] = ext_type
 
         return cls
 
@@ -472,9 +491,9 @@
         _pack_nil(obj, fp, options)
     elif ext_handlers and obj.__class__ in ext_handlers:
         _pack_ext(ext_handlers[obj.__class__](obj), fp, options)
-    elif obj.__class__ in _ext_classes:
+    elif obj.__class__ in _ext_class_to_type:
         try:
-            _pack_ext(Ext(_ext_classes[obj.__class__], obj.packb()), fp, 
options)
+            _pack_ext(Ext(_ext_class_to_type[obj.__class__], obj.packb()), fp, 
options)
         except AttributeError:
             raise NotImplementedError("Ext serializable class {:s} is missing 
implementation of packb()".format(repr(obj.__class__)))
     elif isinstance(obj, bool):
@@ -506,9 +525,19 @@
             _pack_ext(ext_handlers[t](obj), fp, options)
         else:
             raise UnsupportedTypeException(
-                "unsupported type: %s" % str(type(obj)))
+                "unsupported type: {:s}".format(str(type(obj))))
+    elif _ext_class_to_type:
+        # Linear search for superclass
+        t = next((t for t in _ext_class_to_type if isinstance(obj, t)), None)
+        if t:
+            try:
+                _pack_ext(Ext(_ext_class_to_type[t], obj.packb()), fp, options)
+            except AttributeError:
+                raise NotImplementedError("Ext serializable class {:s} is 
missing implementation of packb()".format(repr(t)))
+        else:
+            raise UnsupportedTypeException("unsupported type: 
{:s}".format(str(type(obj))))
     else:
-        raise UnsupportedTypeException("unsupported type: %s" % str(type(obj)))
+        raise UnsupportedTypeException("unsupported type: 
{:s}".format(str(type(obj))))
 
 
 # Pack for Python 3, with unicode 'str' type, 'bytes' type, and no 'long' type
@@ -549,9 +578,9 @@
         _pack_nil(obj, fp, options)
     elif ext_handlers and obj.__class__ in ext_handlers:
         _pack_ext(ext_handlers[obj.__class__](obj), fp, options)
-    elif obj.__class__ in _ext_classes:
+    elif obj.__class__ in _ext_class_to_type:
         try:
-            _pack_ext(Ext(_ext_classes[obj.__class__], obj.packb()), fp, 
options)
+            _pack_ext(Ext(_ext_class_to_type[obj.__class__], obj.packb()), fp, 
options)
         except AttributeError:
             raise NotImplementedError("Ext serializable class {:s} is missing 
implementation of packb()".format(repr(obj.__class__)))
     elif isinstance(obj, bool):
@@ -583,10 +612,20 @@
             _pack_ext(ext_handlers[t](obj), fp, options)
         else:
             raise UnsupportedTypeException(
-                "unsupported type: %s" % str(type(obj)))
+                "unsupported type: {:s}".format(str(type(obj))))
+    elif _ext_class_to_type:
+        # Linear search for superclass
+        t = next((t for t in _ext_class_to_type if isinstance(obj, t)), None)
+        if t:
+            try:
+                _pack_ext(Ext(_ext_class_to_type[t], obj.packb()), fp, options)
+            except AttributeError:
+                raise NotImplementedError("Ext serializable class {:s} is 
missing implementation of packb()".format(repr(t)))
+        else:
+            raise UnsupportedTypeException("unsupported type: 
{:s}".format(str(type(obj))))
     else:
         raise UnsupportedTypeException(
-            "unsupported type: %s" % str(type(obj)))
+            "unsupported type: {:s}".format(str(type(obj))))
 
 
 def _packb2(obj, **options):
@@ -698,21 +737,21 @@
         return struct.unpack(">I", _read_except(fp, 4))[0]
     elif code == b'\xcf':
         return struct.unpack(">Q", _read_except(fp, 8))[0]
-    raise Exception("logic error, not int: 0x%02x" % ord(code))
+    raise Exception("logic error, not int: 0x{:02x}".format(ord(code)))
 
 
 def _unpack_reserved(code, fp, options):
     if code == b'\xc1':
         raise ReservedCodeException(
-            "encountered reserved code: 0x%02x" % ord(code))
+            "encountered reserved code: 0x{:02x}".format(ord(code)))
     raise Exception(
-        "logic error, not reserved code: 0x%02x" % ord(code))
+        "logic error, not reserved code: 0x{:02x}".format(ord(code)))
 
 
 def _unpack_nil(code, fp, options):
     if code == b'\xc0':
         return None
-    raise Exception("logic error, not nil: 0x%02x" % ord(code))
+    raise Exception("logic error, not nil: 0x{:02x}".format(ord(code)))
 
 
 def _unpack_boolean(code, fp, options):
@@ -720,7 +759,7 @@
         return False
     elif code == b'\xc3':
         return True
-    raise Exception("logic error, not boolean: 0x%02x" % ord(code))
+    raise Exception("logic error, not boolean: 0x{:02x}".format(ord(code)))
 
 
 def _unpack_float(code, fp, options):
@@ -728,7 +767,7 @@
         return struct.unpack(">f", _read_except(fp, 4))[0]
     elif code == b'\xcb':
         return struct.unpack(">d", _read_except(fp, 8))[0]
-    raise Exception("logic error, not float: 0x%02x" % ord(code))
+    raise Exception("logic error, not float: 0x{:02x}".format(ord(code)))
 
 
 def _unpack_string(code, fp, options):
@@ -741,7 +780,7 @@
     elif code == b'\xdb':
         length = struct.unpack(">I", _read_except(fp, 4))[0]
     else:
-        raise Exception("logic error, not string: 0x%02x" % ord(code))
+        raise Exception("logic error, not string: 0x{:02x}".format(ord(code)))
 
     # Always return raw bytes in compatibility mode
     global compatibility
@@ -765,7 +804,7 @@
     elif code == b'\xc6':
         length = struct.unpack(">I", _read_except(fp, 4))[0]
     else:
-        raise Exception("logic error, not binary: 0x%02x" % ord(code))
+        raise Exception("logic error, not binary: 0x{:02x}".format(ord(code)))
 
     return _read_except(fp, length)
 
@@ -788,7 +827,7 @@
     elif code == b'\xc9':
         length = struct.unpack(">I", _read_except(fp, 4))[0]
     else:
-        raise Exception("logic error, not ext: 0x%02x" % ord(code))
+        raise Exception("logic error, not ext: 0x{:02x}".format(ord(code)))
 
     ext_type = struct.unpack("b", _read_except(fp, 1))[0]
     ext_data = _read_except(fp, length)
@@ -799,11 +838,11 @@
         return ext_handlers[ext_type](Ext(ext_type, ext_data))
 
     # Unpack with ext classes, if type is registered
-    if ext_type in _ext_classes:
+    if ext_type in _ext_type_to_class:
         try:
-            return _ext_classes[ext_type].unpackb(ext_data)
+            return _ext_type_to_class[ext_type].unpackb(ext_data)
         except AttributeError:
-            raise NotImplementedError("Ext serializable class {:s} is missing 
implementation of unpackb()".format(repr(_ext_classes[ext_type])))
+            raise NotImplementedError("Ext serializable class {:s} is missing 
implementation of unpackb()".format(repr(_ext_type_to_class[ext_type])))
 
     # Timestamp extension
     if ext_type == -1:
@@ -829,7 +868,7 @@
         microseconds = struct.unpack(">I", ext_data[0:4])[0] // 1000
     else:
         raise UnsupportedTimestampException(
-            "unsupported timestamp with data length %d" % len(ext_data))
+            "unsupported timestamp with data length 
{:d}".format(len(ext_data)))
 
     return _epoch + datetime.timedelta(seconds=seconds,
                                        microseconds=microseconds)
@@ -843,7 +882,7 @@
     elif code == b'\xdd':
         length = struct.unpack(">I", _read_except(fp, 4))[0]
     else:
-        raise Exception("logic error, not array: 0x%02x" % ord(code))
+        raise Exception("logic error, not array: 0x{:02x}".format(ord(code)))
 
     if options.get('use_tuple'):
         return tuple((_unpack(fp, options) for i in xrange(length)))
@@ -865,7 +904,7 @@
     elif code == b'\xdf':
         length = struct.unpack(">I", _read_except(fp, 4))[0]
     else:
-        raise Exception("logic error, not map: 0x%02x" % ord(code))
+        raise Exception("logic error, not map: 0x{:02x}".format(ord(code)))
 
     d = {} if not options.get('use_ordered_dict') else 
collections.OrderedDict()
     for _ in xrange(length):
@@ -877,10 +916,10 @@
             k = _deep_list_to_tuple(k)
         elif not isinstance(k, Hashable):
             raise UnhashableKeyException(
-                "encountered unhashable key: %s, %s" % (str(k), str(type(k))))
+                "encountered unhashable key: \"{:s}\" ({:s})".format(str(k), 
str(type(k))))
         elif k in d:
             raise DuplicateKeyException(
-                "encountered duplicate key: %s, %s" % (str(k), str(type(k))))
+                "encountered duplicate key: \"{:s}\" ({:s})".format(str(k), 
str(type(k))))
 
         # Unpack value
         v = _unpack(fp, options)
@@ -889,7 +928,7 @@
             d[k] = v
         except TypeError:
             raise UnhashableKeyException(
-                "encountered unhashable key: %s" % str(k))
+                "encountered unhashable key: \"{:s}\"".format(str(k)))
     return d
 
 

Reply via email to