Hello community, here is the log from the commit of package python-u-msgpack-python for openSUSE:Factory checked in at 2020-08-01 12:30:26 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-u-msgpack-python (Old) and /work/SRC/openSUSE:Factory/.python-u-msgpack-python.new.3592 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-u-msgpack-python" Sat Aug 1 12:30:26 2020 rev:9 rq:822417 version:2.6.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-u-msgpack-python/python-u-msgpack-python.changes 2019-11-04 17:11:50.480609506 +0100 +++ /work/SRC/openSUSE:Factory/.python-u-msgpack-python.new.3592/python-u-msgpack-python.changes 2020-08-01 12:30:34.982423388 +0200 @@ -1,0 +2,7 @@ +Thu Jul 23 12:18:09 UTC 2020 - Marketa Calabkova <mcalabkova@suse.com> + +- update to 2.6.0 + * Add `use_tuple` option to unpacking functions for unpacking MessagePack arrays into tuples. + * Add `ext_serializable()` decorator for registration of application classes with Ext types for automatic packing and unpacking. + +------------------------------------------------------------------- Old: ---- u-msgpack-python-2.5.2.tar.gz New: ---- u-msgpack-python-2.6.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-u-msgpack-python.spec ++++++ --- /var/tmp/diff_new_pack.eMkvUu/_old 2020-08-01 12:30:36.882425168 +0200 +++ /var/tmp/diff_new_pack.eMkvUu/_new 2020-08-01 12:30:36.886425171 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-u-msgpack-python # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 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.5.2 +Version: 2.6.0 Release: 0 Summary: A MessagePack serializer and deserializer License: MIT ++++++ u-msgpack-python-2.5.2.tar.gz -> u-msgpack-python-2.6.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/u-msgpack-python-2.5.2/LICENSE new/u-msgpack-python-2.6.0/LICENSE --- old/u-msgpack-python-2.5.2/LICENSE 2017-08-05 03:25:46.000000000 +0200 +++ new/u-msgpack-python-2.6.0/LICENSE 2020-04-25 10:31:46.000000000 +0200 @@ -1,4 +1,4 @@ - Copyright (c) 2013-2016 vsergeev / Ivan (Vanya) A. Sergeev + Copyright (c) 2013-2020 vsergeev / Ivan (Vanya) A. Sergeev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/u-msgpack-python-2.5.2/PKG-INFO new/u-msgpack-python-2.6.0/PKG-INFO --- old/u-msgpack-python-2.5.2/PKG-INFO 2019-08-15 09:21:16.000000000 +0200 +++ new/u-msgpack-python-2.6.0/PKG-INFO 2020-04-25 10:39:46.034381400 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: u-msgpack-python -Version: 2.5.2 +Version: 2.6.0 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.5.2/README.md new/u-msgpack-python-2.6.0/README.md --- old/u-msgpack-python-2.5.2/README.md 2019-03-04 03:10:56.000000000 +0100 +++ new/u-msgpack-python-2.6.0/README.md 2020-04-25 10:31:46.000000000 +0200 @@ -79,6 +79,23 @@
+Serializing and deserializing application-defined types with `ext_serializable()`:
+``` python
+>>> @umsgpack.ext_serializable(0x50)
+... class Point(collections.namedtuple('Point', ['x', 'y'])):
+... def packb(self):
+... return struct.pack(">ii", self.x, self.y)
+... @staticmethod
+... def unpackb(data):
+... return Point(*struct.unpack(">ii", data))
+...
+>>> umsgpack.packb(Point(1, 2))
+b'\xd7P\x00\x00\x00\x01\x00\x00\x00\x02'
+>>> umsgpack.unpackb(_)
+Point(x=1, y=2)
+>>>
+```
+
Serializing and deserializing application-defined types with Ext handlers:
``` python
>>> umsgpack.packb([complex(1,2), decimal.Decimal("0.31")],
@@ -113,6 +130,45 @@
>>>
+## Ext Serializable + +The `ext_serializable()` decorator registers application classes for automatic +packing and unpacking with the specified Ext type. The decorator accepts the +Ext type code as an argument. The application class should implement a +`packb()` method that returns serialized bytes, and an `unpackb()` class method +or static method that accepts serialized bytes and returns an instance of the +application class. + +Example for registering, packing, and unpacking a custom class with Ext type +code 0x10: + +``` python +@umsgpack.ext_serializable(0x10) +class Point(object): + def __init__(self, x, y, z): + self.x = x + self.y = y + self.z = z + + def __str__(self): + return "Point({}, {}, {})".format(self.x, self.y, self.z) + + def packb(self): + return struct.pack(">iii", self.x, self.y, self.z) + + @staticmethod + def unpackb(data): + return Point(*struct.unpack(">iii", data)) + +# Pack +obj = Point(1,2,3) +data = umsgpack.packb(obj) + +# Unpack +obj = umsgpack.unpackb(data) +print(obj) # -> Point(1, 2, 3) +``` + ## Ext Handlers The packing functions accept an optional `ext_handlers` dictionary that maps @@ -225,6 +281,18 @@
+## Tuples
+
+The unpacking functions provide a `use_tuple` option to unpack MessagePack arrays into tuples, rather than lists.
+
+``` python
+>>> umsgpack.unpackb(b'\x93\xa1a\xc3\x92\x01\x92\x02\x03')
+['a', True, [1, [2, 3]]]
+>>> umsgpack.unpackb(b'\x93\xa1a\xc3\x92\x01\x92\x02\x03', use_tuple=True)
+('a', True, (1, (2, 3)))
+>>>
+```
+
### Invalid UTF-8 Strings
The unpacking functions provide an `allow_invalid_utf8` option to unpack MessagePack strings with invalid UTF-8 into the `umsgpack.InvalidString` type, instead of throwing an exception. The `umsgpack.InvalidString` type is a subclass of `bytes`, and can be used like any other `bytes` object.
@@ -289,6 +357,19 @@
>>>
```
+* `NotImplementedError`: Ext serializable class is missing implementation of `packb()`.
+
+ ``` python
+ >>> @umsgpack.ext_serializable(0x50)
+ ... class Point(collections.namedtuple('Point', ['x', 'y'])):
+ ... pass
+ ...
+ >>> umsgpack.packb(Point(1, 2))
+ ...
+ NotImplementedError: Ext serializable class <class '__main__.Point'> is missing implementation of packb()
+ >>>
+ ```
+
### Unpacking Exceptions
If a non-byte-string argument is passed to `umsgpack.unpackb()`, it will raise a `TypeError` exception. If an error occurs during unpacking, umsgpack will raise an exception derived from `umsgpack.UnpackException`. All possible unpacking exceptions are described below.
@@ -387,6 +468,19 @@
>>>
```
+* `NotImplementedError`: Ext serializable class is missing implementation of `unpackb()`.
+
+ ``` python
+ >>> @umsgpack.ext_serializable(0x50)
+ ... class Point(collections.namedtuple('Point', ['x', 'y'])):
+ ... pass
+ ...
+ >>> umsgpack.unpackb(b'\xd7\x50\x00\x00\x00\x01\x00\x00\x00\x02')
+ ...
+ NotImplementedError: Ext serializable class <class '__main__.Point'> is missing implementation of unpackb()
+ >>>
+ ```
+
## Behavior Notes
* Python 2
@@ -402,6 +496,7 @@
* The Python `datetime.datetime` type is packed into, and unpacked from, the msgpack `timestamp` format
* Note that this Python type only supports microsecond resolution, while the msgpack `timestamp` format supports nanosecond resolution. Timestamps with finer than microsecond resolution will lose precision during unpacking. Users may override the packing and unpacking of the msgpack `timestamp` format with a custom type for alternate behavior.
* Both naive and aware timestamp are supported. Naive timestamps are packed as if they are in the UTC timezone. Timestamps are always unpacked as aware `datetime.datetime` objects in the UTC timezone.
+* Ext type handlers specified in the optional `ext_handlers` dictionary will override `ext_serializable()` classes during packing and unpacking
## Testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/u-msgpack-python-2.5.2/setup.py new/u-msgpack-python-2.6.0/setup.py
--- old/u-msgpack-python-2.5.2/setup.py 2019-08-15 09:18:51.000000000 +0200
+++ new/u-msgpack-python-2.6.0/setup.py 2020-04-25 10:31:46.000000000 +0200
@@ -5,7 +5,7 @@
setup(
name='u-msgpack-python',
- version='2.5.2',
+ version='2.6.0',
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.5.2/test_umsgpack.py new/u-msgpack-python-2.6.0/test_umsgpack.py
--- old/u-msgpack-python-2.5.2/test_umsgpack.py 2019-08-15 09:18:40.000000000 +0200
+++ new/u-msgpack-python-2.6.0/test_umsgpack.py 2020-04-25 10:21:55.000000000 +0200
@@ -319,6 +319,12 @@
["float precision double", 2.5, b"\xcb\x40\x04\x00\x00\x00\x00\x00\x00"],
]
+tuple_test_vectors = [
+ ["nested array", [0x01, [b"\x80", [[u"a", u"b", u"c"], True]]],
+ b"\x92\x01\x92\xc4\x01\x80\x92\x93\xa1a\xa1b\xa1c\xc3",
+ (0x01, (b"\x80", ((u"a", u"b", u"c"), True)))],
+]
+
naive_timestamp_test_vectors = [
["32-bit timestamp (naive)", datetime.datetime(2000, 1, 1, 10, 5, 2, 0, umsgpack._utc_tzinfo),
b"\xd6\xff\x38\x6d\xd1\x4e",
@@ -377,6 +383,7 @@
"DuplicateKeyException",
"KeyNotPrimitiveException",
"KeyDuplicateException",
+ "ext_serializable",
"pack",
"packb",
"unpack",
@@ -518,6 +525,19 @@
self.assertTrue(isinstance(unpacked, OrderedDict))
self.assertEqual(unpacked, obj)
+ def test_unpack_tuple(self):
+ # Use tuple test vector
+ (_, obj, data, obj_tuple) = tuple_test_vectors[0]
+
+ # Unpack with default options (list)
+ self.assertEqual(umsgpack.unpackb(data), obj)
+
+ # Unpack with use_tuple=False (list)
+ self.assertEqual(umsgpack.unpackb(data, use_tuple=False), obj)
+
+ # Unpack with use_tuple=True (tuple)
+ self.assertEqual(umsgpack.unpackb(data, use_tuple=True), obj_tuple)
+
def test_ext_exceptions(self):
with self.assertRaises(TypeError):
_ = umsgpack.Ext(5.0, b"")
@@ -590,6 +610,68 @@
unpacked = umsgpack.unpackb(data, ext_handlers=override_ext_handlers)
self.assertEqual(unpacked, obj)
+ def test_ext_serializable(self):
+ # Register test class
+ @umsgpack.ext_serializable(0x20)
+ class CustomComplex:
+ def __init__(self, real, imag):
+ self.real = real
+ self.imag = imag
+
+ def __eq__(self, other):
+ return self.real == other.real and self.imag == other.imag
+
+ def packb(self):
+ return struct.pack("<II", self.real, self.imag)
+
+ @classmethod
+ def unpackb(cls, data):
+ return cls(*struct.unpack("<II", data))
+
+ obj, data = CustomComplex(123, 456), b"\xd7\x20\x7b\x00\x00\x00\xc8\x01\x00\x00"
+
+ # Test pack
+ packed = umsgpack.packb(obj)
+ self.assertEqual(packed, data)
+
+ # Test unpack
+ unpacked = umsgpack.unpackb(packed)
+ self.assertTrue(isinstance(unpacked, CustomComplex))
+ self.assertEqual(unpacked, obj)
+
+ _, obj, data = ext_handlers_test_vectors[0]
+
+ # Test pack priority of ext_handlers over ext_serializable()
+ packed = umsgpack.packb(obj, ext_handlers=ext_handlers)
+ self.assertEqual(packed, data)
+
+ # Test unpack priority of ext_handlers over ext_serializable()
+ unpacked = umsgpack.unpackb(data, ext_handlers=ext_handlers)
+ self.assertTrue(isinstance(unpacked, complex))
+ self.assertEqual(unpacked, obj)
+
+ # Test registration collision
+ with self.assertRaises(ValueError):
+ @umsgpack.ext_serializable(0x20)
+ class DummyClass:
+ pass
+
+ # Register class with missing packb() and unpackb()
+ @umsgpack.ext_serializable(0x21)
+ class IncompleteClass:
+ pass
+
+ # Test unimplemented packb()
+ with self.assertRaises(NotImplementedError):
+ umsgpack.packb(IncompleteClass())
+
+ # Test unimplemented unpackb()
+ with self.assertRaises(NotImplementedError):
+ umsgpack.unpackb(b"\xd4\x21\x00")
+
+ # Unregister Ext serializable classes for future tests
+ umsgpack._ext_classes = {}
+
def test_streaming_writer(self):
# Try first composite test vector
(_, obj, data) = composite_test_vectors[0]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/u-msgpack-python-2.5.2/u_msgpack_python.egg-info/PKG-INFO new/u-msgpack-python-2.6.0/u_msgpack_python.egg-info/PKG-INFO
--- old/u-msgpack-python-2.5.2/u_msgpack_python.egg-info/PKG-INFO 2019-08-15 09:21:15.000000000 +0200
+++ new/u-msgpack-python-2.6.0/u_msgpack_python.egg-info/PKG-INFO 2020-04-25 10:39:45.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: u-msgpack-python
-Version: 2.5.2
+Version: 2.6.0
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.5.2/umsgpack.py new/u-msgpack-python-2.6.0/umsgpack.py
--- old/u-msgpack-python-2.5.2/umsgpack.py 2019-08-15 09:18:51.000000000 +0200
+++ new/u-msgpack-python-2.6.0/umsgpack.py 2020-04-25 10:31:46.000000000 +0200
@@ -1,4 +1,4 @@
-# u-msgpack-python v2.5.2 - v at sergeev.io
+# u-msgpack-python v2.6.0 - v at sergeev.io
# https://github.com/vsergeev/u-msgpack-python
#
# u-msgpack-python is a lightweight MessagePack serializer and deserializer
@@ -10,7 +10,7 @@
#
# MIT License
#
-# Copyright (c) 2013-2016 vsergeev / Ivan (Vanya) A. Sergeev
+# Copyright (c) 2013-2020 vsergeev / Ivan (Vanya) A. Sergeev
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -31,7 +31,7 @@
# THE SOFTWARE.
#
"""
-u-msgpack-python v2.5.2 - v at sergeev.io
+u-msgpack-python v2.6.0 - 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.5.2"
+__version__ = "2.6.0"
"Module version string"
-version = (2, 5, 2)
+version = (2, 6, 0)
"Module version tuple"
@@ -104,9 +104,8 @@
"""
Compare this Ext object with another for equality.
"""
- return (isinstance(other, self.__class__) and
- self.type == other.type and
- self.data == other.data)
+ return isinstance(other, self.__class__) \
+ and self.type == other.type and self.data == other.data
def __ne__(self, other):
"""
@@ -135,7 +134,43 @@
class InvalidString(bytes):
"""Subclass of bytes to hold invalid UTF-8 strings."""
- pass
+
+
+##############################################################################
+# Ext Serializable Decorator
+##############################################################################
+
+_ext_classes = {}
+
+
+def ext_serializable(ext_type):
+ """
+ Return a decorator to register a class for automatic packing and unpacking
+ with the specified Ext type code. The application class should implement a
+ `packb()` method that returns serialized bytes, and an `unpackb()` class
+ method or static method that accepts serialized bytes and returns an
+ instance of the application class.
+
+ Args:
+ ext_type: application-defined Ext type code
+
+ Raises:
+ 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))
+
+ _ext_classes[ext_type] = cls
+ _ext_classes[cls] = ext_type
+
+ return cls
+
+ return wrapper
+
##############################################################################
# Exceptions
@@ -145,39 +180,32 @@
# Base Exception classes
class PackException(Exception):
"Base class for exceptions encountered during packing."
- pass
class UnpackException(Exception):
"Base class for exceptions encountered during unpacking."
- pass
# Packing error
class UnsupportedTypeException(PackException):
"Object type not supported for packing."
- pass
# Unpacking error
class InsufficientDataException(UnpackException):
"Insufficient data to unpack the serialized object."
- pass
class InvalidStringException(UnpackException):
"Invalid UTF-8 string encountered during unpacking."
- pass
class UnsupportedTimestampException(UnpackException):
"Unsupported timestamp format encountered during unpacking."
- pass
class ReservedCodeException(UnpackException):
"Reserved code encountered during unpacking."
- pass
class UnhashableKeyException(UnpackException):
@@ -185,12 +213,10 @@
Unhashable key encountered during map unpacking.
The serialized map cannot be deserialized into a Python dictionary.
"""
- pass
class DuplicateKeyException(UnpackException):
"Duplicate key encountered during map unpacking."
- pass
# Backwards compatibility
@@ -340,14 +366,11 @@
elif obj_len == 16:
fp.write(b"\xd8" + struct.pack("B", obj.type & 0xff) + obj.data)
elif obj_len < 2**8:
- fp.write(b"\xc7" +
- struct.pack("BB", obj_len, obj.type & 0xff) + obj.data)
+ fp.write(b"\xc7" + struct.pack("BB", obj_len, obj.type & 0xff) + obj.data)
elif obj_len < 2**16:
- fp.write(b"\xc8" +
- struct.pack(">HB", obj_len, obj.type & 0xff) + obj.data)
+ fp.write(b"\xc8" + struct.pack(">HB", obj_len, obj.type & 0xff) + obj.data)
elif obj_len < 2**32:
- fp.write(b"\xc9" +
- struct.pack(">IB", obj_len, obj.type & 0xff) + obj.data)
+ fp.write(b"\xc9" + struct.pack(">IB", obj_len, obj.type & 0xff) + obj.data)
else:
raise UnsupportedTypeException("huge ext data")
@@ -366,18 +389,14 @@
if microseconds == 0 and 0 <= seconds <= 2**32 - 1:
# 32-bit timestamp
- fp.write(b"\xd6\xff" +
- struct.pack(">I", seconds))
+ fp.write(b"\xd6\xff" + struct.pack(">I", seconds))
elif 0 <= seconds <= 2**34 - 1:
# 64-bit timestamp
value = ((microseconds * 1000) << 34) | seconds
- fp.write(b"\xd7\xff" +
- struct.pack(">Q", value))
+ fp.write(b"\xd7\xff" + struct.pack(">Q", value))
elif -2**63 <= abs(seconds) <= 2**63 - 1:
# 96-bit timestamp
- fp.write(b"\xc7\x0c\xff" +
- struct.pack(">I", microseconds * 1000) +
- struct.pack(">q", seconds))
+ fp.write(b"\xc7\x0c\xff" + struct.pack(">Iq", microseconds * 1000, seconds))
else:
raise UnsupportedTypeException("huge timestamp")
@@ -453,6 +472,11 @@
_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:
+ try:
+ _pack_ext(Ext(_ext_classes[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):
_pack_boolean(obj, fp, options)
elif isinstance(obj, (int, long)):
@@ -525,6 +549,11 @@
_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:
+ try:
+ _pack_ext(Ext(_ext_classes[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):
_pack_boolean(obj, fp, options)
elif isinstance(obj, int):
@@ -764,39 +793,43 @@
ext_type = struct.unpack("b", _read_except(fp, 1))[0]
ext_data = _read_except(fp, length)
- # Create extension object
- ext = Ext(ext_type, ext_data)
-
# Unpack with ext handler, if we have one
ext_handlers = options.get("ext_handlers")
- if ext_handlers and ext.type in ext_handlers:
- return ext_handlers[ext.type](ext)
+ if ext_handlers and ext_type in ext_handlers:
+ return ext_handlers[ext_type](Ext(ext_type, ext_data))
+
+ # Unpack with ext classes, if type is registered
+ if ext_type in _ext_classes:
+ try:
+ return _ext_classes[ext_type].unpackb(ext_data)
+ except AttributeError:
+ raise NotImplementedError("Ext serializable class {:s} is missing implementation of unpackb()".format(repr(_ext_classes[ext_type])))
# Timestamp extension
- if ext.type == -1:
- return _unpack_ext_timestamp(ext, options)
+ if ext_type == -1:
+ return _unpack_ext_timestamp(ext_data, options)
- return ext
+ return Ext(ext_type, ext_data)
-def _unpack_ext_timestamp(ext, options):
- obj_len = len(ext.data)
+def _unpack_ext_timestamp(ext_data, options):
+ obj_len = len(ext_data)
if obj_len == 4:
# 32-bit timestamp
- seconds = struct.unpack(">I", ext.data)[0]
+ seconds = struct.unpack(">I", ext_data)[0]
microseconds = 0
elif obj_len == 8:
# 64-bit timestamp
- value = struct.unpack(">Q", ext.data)[0]
+ value = struct.unpack(">Q", ext_data)[0]
seconds = value & 0x3ffffffff
microseconds = (value >> 34) // 1000
elif obj_len == 12:
# 96-bit timestamp
- seconds = struct.unpack(">q", ext.data[4:12])[0]
- microseconds = struct.unpack(">I", ext.data[0:4])[0] // 1000
+ seconds = struct.unpack(">q", ext_data[4:12])[0]
+ 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" % len(ext_data))
return _epoch + datetime.timedelta(seconds=seconds,
microseconds=microseconds)
@@ -812,6 +845,9 @@
else:
raise Exception("logic error, not array: 0x%02x" % ord(code))
+ if options.get('use_tuple'):
+ return tuple((_unpack(fp, options) for i in xrange(length)))
+
return [_unpack(fp, options) for i in xrange(length)]
@@ -831,8 +867,7 @@
else:
raise Exception("logic error, not map: 0x%02x" % ord(code))
- d = {} if not options.get('use_ordered_dict') \
- else collections.OrderedDict()
+ d = {} if not options.get('use_ordered_dict') else collections.OrderedDict()
for _ in xrange(length):
# Unpack key
k = _unpack(fp, options)
@@ -878,6 +913,8 @@
Ext into an object
use_ordered_dict (bool): unpack maps into OrderedDict, instead of
unordered dict (default False)
+ use_tuple (bool): unpacks arrays into tuples, instead of lists (default
+ False)
allow_invalid_utf8 (bool): unpack invalid strings into instances of
InvalidString, for access to the bytes
(default False)
@@ -922,6 +959,8 @@
Ext into an object
use_ordered_dict (bool): unpack maps into OrderedDict, instead of
unordered dict (default False)
+ use_tuple (bool): unpacks arrays into tuples, instead of lists (default
+ False)
allow_invalid_utf8 (bool): unpack invalid strings into instances of
InvalidString, for access to the bytes
(default False)
@@ -967,6 +1006,8 @@
Ext into an object
use_ordered_dict (bool): unpack maps into OrderedDict, instead of
unordered dict (default False)
+ use_tuple (bool): unpacks arrays into tuples, instead of lists (default
+ False)
allow_invalid_utf8 (bool): unpack invalid strings into instances of
InvalidString, for access to the bytes
(default False)
@@ -1015,6 +1056,8 @@
Ext into an object
use_ordered_dict (bool): unpack maps into OrderedDict, instead of
unordered dict (default False)
+ use_tuple (bool): unpacks arrays into tuples, instead of lists (default
+ False)
allow_invalid_utf8 (bool): unpack invalid strings into instances of
InvalidString, for access to the bytes
(default False)