Hello community,

here is the log from the commit of package python-u-msgpack-python for 
openSUSE:Factory checked in at 2018-04-05 15:29:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-u-msgpack-python (Old)
 and      /work/SRC/openSUSE:Factory/.python-u-msgpack-python.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-u-msgpack-python"

Thu Apr  5 15:29:19 2018 rev:4 rq:593368 version:2.5.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-u-msgpack-python/python-u-msgpack-python.changes
  2018-03-24 16:05:37.784586699 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-u-msgpack-python.new/python-u-msgpack-python.changes
     2018-04-05 15:29:23.705026176 +0200
@@ -1,0 +2,14 @@
+Tue Apr  3 23:19:39 UTC 2018 - jeng...@inai.de
+
+- Ensure neutrality and time-agnosticness of description.
+
+-------------------------------------------------------------------
+Sun Apr  1 22:14:43 UTC 2018 - a...@gmx.de
+
+- remove u-msgpack-bigendian_broken.patch
+
+- update to version 2.5.0:
+  * Add support for the timestamp extension type.
+  * Fix tests on big endian platforms
+
+-------------------------------------------------------------------

Old:
----
  u-msgpack-bigendian_broken.patch
  u-msgpack-python-2.4.1.tar.gz

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

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

Other differences:
------------------
++++++ python-u-msgpack-python.spec ++++++
--- /var/tmp/diff_new_pack.GXPBKJ/_old  2018-04-05 15:29:24.361002466 +0200
+++ /var/tmp/diff_new_pack.GXPBKJ/_new  2018-04-05 15:29:24.361002466 +0200
@@ -18,38 +18,30 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-u-msgpack-python
-Version:        2.4.1
+Version:        2.5.0
 Release:        0
-Summary:        A portable, lightweight MessagePack serializer and deserializer
+Summary:        A MessagePack serializer and deserializer
 License:        MIT
 Group:          Development/Languages/Python
-Url:            https://github.com/vsergeev/u-msgpack-python
+URL:            https://github.com/vsergeev/u-msgpack-python
 Source:         
https://pypi.io/packages/source/u/u-msgpack-python/u-msgpack-python-%{version}.tar.gz
-Patch0:         u-msgpack-bigendian_broken.patch
 BuildRequires:  %{python_module devel}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildArch:      noarch
 %python_subpackages
 
 %description
-u-msgpack-python is a lightweight MessagePack serializer and
-deserializer module written in pure Python, compatible with both
-Python 2 and Python 3, as well as CPython and PyPy implementations of
-Python. u-msgpack-python is fully compliant with the latest
-MessagePack specification. In particular, it supports the new binary,
-UTF-8 string, and application-defined ext types.
+u-msgpack-python is a MessagePack serializer and
+deserializer module written in pure Python, compatible with
+Python 2, Python 3, in both the CPython and PyPy implementations of
+Python. u-msgpack-python is fully compliant with the MessagePack
+2017-09-17 specification. In particular, it supports the binary,
+UTF-8 string, and application-defined extended types.
 
 %prep
 %setup -q -n u-msgpack-python-%{version}
-# we are noarch, so ifarch does not work here
-case "$(uname -m)" in
-    ppc|ppc64|s390|s390x)
-%patch0 -p1
-       ;;
-esac
 
 %build
 %python_build
@@ -64,7 +56,7 @@
 
 %files %{python_files}
 %defattr(-,root,root,-)
-%doc LICENSE
+%license LICENSE
 %pycache_only %{python_sitelib}/__pycache__
 %{python_sitelib}/umsgpack.py*
 %{python_sitelib}/u_msgpack_python-%{version}-py%{python_version}.egg-info

++++++ u-msgpack-python-2.4.1.tar.gz -> u-msgpack-python-2.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/u-msgpack-python-2.4.1/PKG-INFO 
new/u-msgpack-python-2.5.0/PKG-INFO
--- old/u-msgpack-python-2.4.1/PKG-INFO 2017-04-25 15:45:00.000000000 +0200
+++ new/u-msgpack-python-2.5.0/PKG-INFO 2018-04-02 01:15:22.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: u-msgpack-python
-Version: 2.4.1
+Version: 2.5.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.4.1/README.md 
new/u-msgpack-python-2.5.0/README.md
--- old/u-msgpack-python-2.4.1/README.md        1970-01-01 01:00:00.000000000 
+0100
+++ new/u-msgpack-python-2.5.0/README.md        2018-04-01 02:54:55.000000000 
+0200
@@ -0,0 +1,425 @@
+# u-msgpack-python [![Build 
Status](https://travis-ci.org/vsergeev/u-msgpack-python.svg?branch=master)](https://travis-ci.org/vsergeev/u-msgpack-python)
 [![GitHub 
release](https://img.shields.io/github/release/vsergeev/u-msgpack-python.svg?maxAge=7200)](https://github.com/vsergeev/u-msgpack-python)
 
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/vsergeev/u-msgpack-python/blob/master/LICENSE)
+
+u-msgpack-python is a lightweight [MessagePack](http://msgpack.org/) 
serializer and deserializer module written in pure Python, compatible with both 
Python 2 and 3, as well CPython and PyPy implementations of Python. 
u-msgpack-python is fully compliant with the latest [MessagePack 
specification](https://github.com/msgpack/msgpack/blob/master/spec.md). In 
particular, it supports the new binary, UTF-8 string, application-defined ext, 
and timestamp types.
+
+u-msgpack-python is currently distributed on 
[PyPI](https://pypi.python.org/pypi/u-msgpack-python) and as a single file: 
[umsgpack.py](https://raw.github.com/vsergeev/u-msgpack-python/master/umsgpack.py).
+
+## Installation
+
+With pip:
+``` text
+$ pip install u-msgpack-python
+```
+
+With easy_install:
+``` text
+$ easy_install u-msgpack-python
+```
+
+or simply drop 
[umsgpack.py](https://raw.github.com/vsergeev/u-msgpack-python/master/umsgpack.py)
 into your project!
+``` text
+$ wget https://raw.github.com/vsergeev/u-msgpack-python/master/umsgpack.py
+```
+
+## Examples
+
+Basic Example:
+``` python
+>>> import umsgpack
+>>> umsgpack.packb({u"compact": True, u"schema": 0})
+b'\x82\xa7compact\xc3\xa6schema\x00'
+>>> umsgpack.unpackb(_)
+{u'compact': True, u'schema': 0}
+>>> 
+```
+
+A more complicated example:
+``` python
+>>> umsgpack.packb([1, True, False, 0xffffffff, {u"foo": b"\x80\x01\x02", \
+...                 u"bar": [1,2,3, {u"a": [1,2,3,{}]}]}, -1, 2.12345])
+b'\x97\x01\xc3\xc2\xce\xff\xff\xff\xff\x82\xa3foo\xc4\x03\x80\x01\
+\x02\xa3bar\x94\x01\x02\x03\x81\xa1a\x94\x01\x02\x03\x80\xff\xcb\
+@\x00\xfc\xd3Z\x85\x87\x94'
+>>> umsgpack.unpackb(_)
+[1, True, False, 4294967295, {u'foo': b'\x80\x01\x02', \
+ u'bar': [1, 2, 3, {u'a': [1, 2, 3, {}]}]}, -1, 2.12345]
+>>> 
+```
+
+Streaming serialization with file-like objects:
+``` python
+>>> f = open('test.bin', 'wb')
+>>> umsgpack.pack({u"compact": True, u"schema": 0}, f)
+>>> umsgpack.pack([1,2,3], f)
+>>> f.close()
+>>> 
+>>> f = open('test.bin', 'rb')
+>>> umsgpack.unpack(f)
+{u'compact': True, u'schema': 0}
+>>> umsgpack.unpack(f)
+[1, 2, 3]
+>>> f.close()
+>>> 
+```
+
+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")
+>>> 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)
+>>> bar['stuff'].type
+5
+>>> bar['stuff'].data
+b'\x01\x02\x03'
+>>> 
+```
+
+Serializing and deserializing application-defined types with Ext handlers:
+``` python
+>>> umsgpack.packb([complex(1,2), decimal.Decimal("0.31")],
+...  ext_handlers = {
+...   complex: lambda obj: umsgpack.Ext(0x30, struct.pack("ff", obj.real, 
obj.imag)),
+...   decimal.Decimal: lambda obj: umsgpack.Ext(0x40, str(obj).encode()),
+... })
+b'\x92\xd70\x00\x00\x80?\x00\x00\x00@\xd6@0.31'
+>>> umsgpack.unpackb(_,
+...  ext_handlers = {
+...   0x30: lambda ext: complex(*struct.unpack("ff", ext.data)),
+...   0x40: lambda ext: decimal.Decimal(ext.data.decode()),
+... })
+[(1+2j), Decimal('0.31')]
+>>> 
+```
+
+Python standard library style names `dump`, `dumps`, `load`, `loads` are also 
available:
+``` python
+>>> umsgpack.dumps({u"compact": True, u"schema": 0})
+b'\x82\xa7compact\xc3\xa6schema\x00'
+>>> umsgpack.loads(_)
+{u'compact': True, u'schema': 0}
+>>> 
+>>> f = open('test.bin', 'wb')
+>>> umsgpack.dump({u"compact": True, u"schema": 0}, f)
+>>> f.close()
+>>> 
+>>> f = open('test.bin', 'rb')
+>>> umsgpack.load(f)
+{u'compact': True, u'schema': 0}
+>>> 
+```
+
+## Ext Handlers
+
+The packing functions accept an optional `ext_handlers` dictionary that maps
+custom types to callables that pack the type into an Ext object. The callable
+should accept the custom type object as an argument and return a packed
+`umsgpack.Ext` object.
+
+Example for packing `set`, `complex`, and `decimal.Decimal` types into Ext
+objects with type codes 0x20, 0x30, and 0x40, respectively:
+
+``` python
+>>> umsgpack.packb([1, True, {"foo", 2}, complex(3, 4), 
decimal.Decimal("0.31")],
+...  ext_handlers = {
+...   set: lambda obj: umsgpack.Ext(0x20, umsgpack.packb(list(obj))),
+...   complex: lambda obj: umsgpack.Ext(0x30, struct.pack("ff", obj.real, 
obj.imag)),
+...   decimal.Decimal: lambda obj: umsgpack.Ext(0x40, str(obj).encode()),
+... })
+b'\x95\x01\xc3\xc7\x06 \x92\xa3foo\x02\xd70\x00\x00@@\x00\x00\x80@\xd6@0.31'
+>>> 
+```
+Similarly, the unpacking functions accept an optional `ext_handlers` dictionary
+that maps Ext type codes to callables that unpack the Ext into a custom object.
+The callable should accept a `umsgpack.Ext` object as an argument and return an
+unpacked custom type object.
+
+Example for unpacking Ext objects with type codes 0x20, 0x30, and 0x40, into
+`set`, `complex`, and `decimal.Decimal` typed objects, respectively:
+
+``` python
+>>> umsgpack.unpackb(b'\x95\x01\xc3\xc7\x06 
\x92\xa3foo\x02\xd70\x00\x00@@\x00\x00\x80@\xd6@0.31',
+...  ext_handlers = {
+...   0x20: lambda ext: set(umsgpack.unpackb(ext.data)),
+...   0x30: lambda ext: complex(*struct.unpack("ff", ext.data)),
+...   0x40: lambda ext: decimal.Decimal(ext.data.decode()),
+... })
+[1, True, {'foo', 2}, (3+4j), Decimal('0.31')]
+>>> 
+```
+
+Example for packing and unpacking a custom class:
+
+``` python
+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 pack(self):
+        return struct.pack(">iii", self.x, self.y, self.z)
+
+    @staticmethod
+    def unpack(data):
+        return Point(*struct.unpack(">iii", data))
+
+# Pack
+obj = Point(1,2,3)
+data = umsgpack.packb(obj, ext_handlers = {Point: lambda obj: 
umsgpack.Ext(0x10, obj.pack())})
+
+# Unpack
+obj = umsgpack.unpackb(data, ext_handlers = {0x10: lambda ext: 
Point.unpack(ext.data)})
+print(obj) # -> Point(1, 2, 3)
+```
+
+## Streaming Serialization and Deserialization
+
+The streaming `pack()`/`dump()` and `unpack()`/`load()` functions allow 
packing and unpacking objects directly to and from a stream, respectively. 
Streaming may be necessary when unpacking serialized bytes whose size is 
unknown in advance, or it may be more convenient and efficient when working 
directly with stream objects (e.g. files or stream sockets).
+
+`pack(obj, fp)` / `dump(obj, fp)` serialize Python object `obj` to a 
`.write()` supporting file-like object `fp`.
+
+``` python
+>>> class Foo:
+...     def write(self, data):
+...         # write 'data' bytes
+...         pass
+... 
+>>> f = Foo()
+>>> umsgpack.pack({u"compact": True, u"schema": 0}, f)
+>>> 
+```
+
+`unpack(fp)` / `load(fp)` deserialize a Python object from a `.read()` 
supporting file-like object `fp`.
+
+``` python
+>>> class Bar:
+...     def read(self, n):
+...         # read and return 'n' number of bytes
+...         return b"\x01"*n
+... 
+>>> f = Bar()
+>>> umsgpack.unpack(f)
+1
+>>> 
+```
+
+## Options
+
+### Ordered Dictionaries
+
+The unpacking functions provide a `use_ordered_dict` option to unpack 
MessagePack maps into the `collections.OrderedDict` type, rather than the 
unordered `dict` type, to preserve the order of deserialized MessagePack maps.
+
+``` python
+>>> umsgpack.unpackb(b'\x82\xa7compact\xc3\xa6schema\x00')
+{'compact': True, 'schema': 0}
+>>> umsgpack.unpackb(b'\x82\xa7compact\xc3\xa6schema\x00', 
use_ordered_dict=True)
+OrderedDict([('compact', True), ('schema', 0)])
+>>> 
+```
+
+### 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.
+
+``` python
+>>> # Attempt to unpack invalid UTF-8 string
+... umsgpack.unpackb(b'\xa4\x80\x01\x02\x03')
+...
+umsgpack.InvalidStringException: unpacked string is invalid utf-8
+>>> umsgpack.unpackb(b'\xa4\x80\x01\x02\x03', allow_invalid_utf8=True)
+b'\x80\x01\x02\x03'
+>>> 
+```
+
+### Float Precision
+
+The packing functions provide a `force_float_precision` option to force 
packing of floats into the specified precision: `"single"` for IEEE-754 
single-precision floats, or `"double"` for IEEE-754 double-precision floats.
+
+``` python
+>>> # Force float packing to single-precision floats
+... umsgpack.packb(2.5, force_float_precision="single")
+b'\xca@ \x00\x00'
+>>> # Force float packing to double-precision floats
+... umsgpack.packb(2.5, force_float_precision="double")
+b'\xcb@\x04\x00\x00\x00\x00\x00\x00'
+>>> 
+```
+
+### Old Specification Compatibility Mode
+
+The compatibility mode supports the "raw" bytes MessagePack type from the [old 
specification](https://github.com/msgpack/msgpack/blob/master/spec-old.md). 
When the module-wide `compatibility` option is enabled, both unicode strings 
and bytes will be serialized into the "raw" MessagePack type, and the "raw" 
MessagePack type will be deserialized into bytes.
+
+``` python
+>>> umsgpack.compatibility = True
+>>>
+>>> umsgpack.packb([u"some string", b"some bytes"])
+b'\x92\xabsome string\xaasome bytes'
+>>> umsgpack.unpackb(_)
+[b'some string', b'some bytes']
+>>> 
+```
+
+## Exceptions
+
+### Packing Exceptions
+
+If an error occurs during packing, umsgpack will raise an exception derived 
from `umsgpack.PackException`. All possible packing exceptions are described 
below.
+
+* `UnsupportedTypeException`: Object type not supported for packing.
+
+    ``` python
+    >>> # Attempt to pack set type
+    ... umsgpack.packb(set([1,2,3]))
+    ...
+    umsgpack.UnsupportedTypeException: unsupported type: <type 'set'>
+    >>> 
+
+    >>> # Attempt to pack > 64-bit unsigned int
+    ... umsgpack.packb(2**64)
+    ...
+    umsgpack.UnsupportedTypeException: huge unsigned int
+    >>> 
+    ```
+
+### 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.
+
+* `TypeError`: Packed data is not type `str` (Python 2), or not type `bytes` 
(Python 3).
+
+    ``` python
+    # Attempt to unpack non-str type data in Python 2
+    >>> umsgpack.unpackb(u"no good")
+    ...
+    TypeError: expected packed data as type 'str'
+    >>> 
+
+    # Attempt to unpack non-bytes type data in Python 3
+    >>> umsgpack.unpackb("no good")
+    ...
+    TypeError: expected packed data as type 'bytes'
+    >>> 
+    ```
+
+* `InsufficientDataException`: Insufficient data to unpack the serialized 
object.
+
+    ``` python
+    # Attempt to unpack a cut-off serialized 32-bit unsigned int
+    >>> umsgpack.unpackb(b"\xce\xff\xff\xff")
+    ...
+    umsgpack.InsufficientDataException
+    >>> 
+
+    # Attempt to unpack an array of length 2 missing the second item
+    >>> umsgpack.unpackb(b"\x92\xc2")
+    ...
+    umsgpack.InsufficientDataException
+    >>> 
+
+    ```
+* `InvalidStringException`: Invalid UTF-8 string encountered during unpacking.
+
+       String bytes are strictly decoded with UTF-8. This exception is thrown 
if
+       UTF-8 decoding of string bytes fails. Use the `allow_invalid_utf8` 
option
+       to unpack invalid MessagePack strings into byte strings.
+
+    ``` python
+    # Attempt to unpack invalid UTF-8 string
+    >>> umsgpack.unpackb(b"\xa2\x80\x81")
+    ...
+    umsgpack.InvalidStringException: unpacked string is invalid utf-8
+    >>> 
+    ```
+
+* `UnsupportedTimestampException`: Unsupported timestamp encountered during 
unpacking.
+
+    The official timestamp extension type supports 32-bit, 64-bit and 96-bit
+    formats. This exception is thrown if a timestamp extension type with an
+    unsupported format is encountered.
+
+    ``` python
+    # Attempt to unpack invalid timestamp
+    >>> umsgpack.unpackb(b"\xd5\xff\x01\x02")
+    ...
+    umsgpack.UnsupportedTimestampException: unsupported timestamp with data 
length 2
+    >>> 
+    ```
+
+* `ReservedCodeException`: Reserved code encountered during unpacking.
+
+    ``` python
+    # Attempt to unpack reserved code 0xc1
+    >>> umsgpack.unpackb(b"\xc1")
+    ...
+    umsgpack.ReservedCodeException: reserved code encountered: 0xc1
+    >>> 
+    ```
+
+* `UnhashableKeyException`: Unhashable key encountered during map unpacking. 
The packed map cannot be unpacked into a Python dictionary.
+
+    Python dictionaries only support keys that are instances of 
`collections.Hashable`, so while the map `{ { u'abc': True } : 5 }` has a 
MessagePack serialization, it cannot be unpacked into a valid Python dictionary.
+
+    ``` python
+    # Attempt to unpack { {} : False }
+    >>> umsgpack.unpackb(b"\x82\x80\xc2")
+    ...
+    umsgpack.UnhashableKeyException: encountered unhashable key type: {}, 
<type 'dict'>
+    >>> 
+    ```
+
+* `DuplicateKeyException`: Duplicate key encountered during map unpacking.
+
+    Python dictionaries do not support duplicate keys, but MessagePack maps 
may be serialized with duplicate keys.
+
+    ``` python
+    # Attempt to unpack { 1: True, 1: False }
+    >>> umsgpack.unpackb(b"\x82\x01\xc3\x01\xc2")
+    ...
+    umsgpack.DuplicateKeyException: encountered duplicate key: 1, <type 'int'>
+    >>> 
+    ```
+
+## Behavior Notes
+
+* Python 2
+  * `unicode` type objects are packed into, and unpacked from, the msgpack 
`string` format
+  * `str` type objects are packed into, and unpacked from, the msgpack 
`binary` format
+* Python 3
+  * `str` type objects are packed into, and unpacked from, the msgpack 
`string` format
+  * `bytes` type objects are packed into, and unpacked from, the msgpack 
`binary` format
+* The msgpack string format is strictly decoded with UTF-8 — an exception is 
thrown if the string bytes cannot be decoded into a valid UTF-8 string, unless 
the `allow_invalid_utf8` option is enabled
+* The msgpack array format is unpacked into a Python list, unless it is the 
key of a map, in which case it is unpacked into a Python tuple
+* Python tuples and lists are both packed into the msgpack array format
+* Python float types are packed into the msgpack float32 or float64 format 
depending on the system's `sys.float_info`
+* 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.
+
+## Testing
+
+The included unit tests may be run with `test_umsgpack.py`, under your 
favorite interpreter.
+
+``` text
+$ python2 test_umsgpack.py
+$ python3 test_umsgpack.py
+$ pypy test_umsgpack.py
+$ pypy3 test_umsgpack.py
+```
+
+Alternatively, you can use `tox` or `detox` to test multiple Python versions 
at once.
+
+``` text
+$ pip install tox
+$ tox
+```
+
+## License
+
+u-msgpack-python is MIT licensed. See the included `LICENSE` file for more 
details.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/u-msgpack-python-2.4.1/setup.py 
new/u-msgpack-python-2.5.0/setup.py
--- old/u-msgpack-python-2.4.1/setup.py 2017-04-25 15:43:31.000000000 +0200
+++ new/u-msgpack-python-2.5.0/setup.py 2018-04-01 02:54:55.000000000 +0200
@@ -5,7 +5,7 @@
 
 setup(
     name='u-msgpack-python',
-    version='2.4.1',
+    version='2.5.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.4.1/test_umsgpack.py 
new/u-msgpack-python-2.5.0/test_umsgpack.py
--- old/u-msgpack-python-2.4.1/test_umsgpack.py 2017-04-25 15:43:28.000000000 
+0200
+++ new/u-msgpack-python-2.5.0/test_umsgpack.py 2018-04-01 02:54:55.000000000 
+0200
@@ -11,6 +11,7 @@
 import sys
 import struct
 import unittest
+import datetime
 import io
 from collections import OrderedDict, namedtuple
 
@@ -116,6 +117,27 @@
     ["empty array", [], b"\x90"],
     # Empty Map
     ["empty map", {}, b"\x80"],
+    # 32-bit Timestamp
+    ["32-bit timestamp", datetime.datetime(1970, 1, 1, 0, 0, 0, 0, 
umsgpack._utc_tzinfo),
+        b"\xd6\xff\x00\x00\x00\x00"],
+    ["32-bit timestamp", datetime.datetime(2000, 1, 1, 10, 5, 2, 0, 
umsgpack._utc_tzinfo),
+        b"\xd6\xff\x38\x6d\xd1\x4e"],
+    # 64-bit Timestamp
+    ["64-bit timestamp", datetime.datetime(2000, 1, 1, 10, 5, 2, 1234, 
umsgpack._utc_tzinfo),
+        b"\xd7\xff\x00\x4b\x51\x40\x38\x6d\xd1\x4e"],
+    ["64-bit timestamp", datetime.datetime(2200, 1, 1, 10, 5, 2, 0, 
umsgpack._utc_tzinfo),
+        b"\xd7\xff\x00\x00\x00\x01\xb0\x9e\xa6\xce"],
+    ["64-bit timestamp", datetime.datetime(2200, 1, 1, 10, 5, 2, 1234, 
umsgpack._utc_tzinfo),
+        b"\xd7\xff\x00\x4b\x51\x41\xb0\x9e\xa6\xce"],
+    # 96-bit Timestamp
+    ["96-bit timestamp", datetime.datetime(1900, 1, 1, 10, 5, 2, 0, 
umsgpack._utc_tzinfo),
+        b"\xc7\x0c\xff\x00\x00\x00\x00\xff\xff\xff\xff\x7c\x56\x0f\x4e"],
+    ["96-bit timestamp", datetime.datetime(1900, 1, 1, 10, 5, 2, 1234, 
umsgpack._utc_tzinfo),
+        b"\xc7\x0c\xff\x00\x12\xd4\x50\xff\xff\xff\xff\x7c\x56\x0f\x4e"],
+    ["96-bit timestamp", datetime.datetime(3000, 1, 1, 10, 5, 2, 0, 
umsgpack._utc_tzinfo),
+        b"\xc7\x0c\xff\x00\x00\x00\x00\x00\x00\x00\x07\x91\x5f\x59\xce"],
+    ["96-bit timestamp", datetime.datetime(3000, 1, 1, 10, 5, 2, 1234, 
umsgpack._utc_tzinfo),
+        b"\xc7\x0c\xff\x00\x12\xd4\x50\x00\x00\x00\x07\x91\x5f\x59\xce"],
 ]
 
 composite_test_vectors = [
@@ -262,6 +284,9 @@
     # Reserved code (0xc1)
     ["reserved code", b"\xc1",
         umsgpack.ReservedCodeException],
+    # Unsupported timestamp (unsupported data length)
+    ["unsupported timestamp", b"\xc7\x02\xff\xaa\xbb",
+        umsgpack.UnsupportedTimestampException],
     # Invalid string (non utf-8)
     ["invalid string", b"\xa1\x80",
         umsgpack.InvalidStringException],
@@ -297,9 +322,9 @@
 CustomType = namedtuple('CustomType', ['x', 'y', 'z'])
 
 ext_handlers = {
-    complex: lambda obj: umsgpack.Ext(0x20, struct.pack("ff", obj.real, 
obj.imag)),
+    complex: lambda obj: umsgpack.Ext(0x20, struct.pack("<ff", obj.real, 
obj.imag)),
     CustomType: lambda obj: umsgpack.Ext(0x30, umsgpack.packb(list(obj))),
-    0x20: lambda ext: complex(*struct.unpack("ff", ext.data)),
+    0x20: lambda ext: complex(*struct.unpack("<ff", ext.data)),
     0x30: lambda ext: CustomType(*umsgpack.unpackb(ext.data)),
 }
 
@@ -309,6 +334,22 @@
      b"\xd7\x30\x93\xc4\x03\x61\x62\x63\x7b\xc3"],
 ]
 
+override_ext_handlers = {
+    datetime.datetime:
+        lambda obj: umsgpack.Ext(0x40, 
obj.strftime("%Y%m%dT%H:%M:%S.%f").encode()),
+    -0x01:
+        lambda ext: ext,
+}
+
+override_ext_handlers_test_vectors = [
+    ["pack override",
+        datetime.datetime(2000, 1, 1, 10, 5, 2, 0, umsgpack._utc_tzinfo),
+        b'\xc7\x18@20000101T10:05:02.000000'],
+    ["unpack override",
+        umsgpack.Ext(-0x01, 
b"\x00\xbb\xcc\xdd\x01\x02\x03\x04\x05\x06\x07\x08"),
+        b'\xc7\x0c\xff\x00\xbb\xcc\xdd\x01\x02\x03\x04\x05\x06\x07\x08'],
+]
+
 # These are the only global variables that should be exported by umsgpack
 exported_vars_test_vector = [
     "Ext",
@@ -318,6 +359,7 @@
     "UnsupportedTypeException",
     "InsufficientDataException",
     "InvalidStringException",
+    "UnsupportedTimestampException",
     "ReservedCodeException",
     "UnhashableKeyException",
     "DuplicateKeyException",
@@ -466,10 +508,7 @@
 
     def test_ext_exceptions(self):
         with self.assertRaises(TypeError):
-            _ = umsgpack.Ext(-1, b"")
-
-        with self.assertRaises(TypeError):
-            _ = umsgpack.Ext(128, b"")
+            _ = umsgpack.Ext(5.0, b"")
 
         with self.assertRaises(TypeError):
             _ = umsgpack.Ext(0, u"unicode string")
@@ -501,6 +540,26 @@
             packed = umsgpack.packb(obj, force_float_precision=precision)
             self.assertEqual(packed, data)
 
+    def test_pack_ext_override(self):
+        # 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] + 
"..."))
+
+        packed = umsgpack.packb(obj, ext_handlers=override_ext_handlers)
+        self.assertEqual(packed, data)
+
+    def test_unpack_ext_override(self):
+        # 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] + 
"..."))
+
+        unpacked = umsgpack.unpackb(data, ext_handlers=override_ext_handlers)
+        self.assertEqual(unpacked, obj)
+
     def test_streaming_writer(self):
         # Try first composite test vector
         (_, obj, data) = composite_test_vectors[0]
@@ -519,7 +578,7 @@
         exported_vars = list(filter(lambda x: not x.startswith("_"),
                                     dir(umsgpack)))
         # Ignore imports
-        exported_vars = list(filter(lambda x: x != "struct" and x != 
"collections" and x !=
+        exported_vars = list(filter(lambda x: x != "struct" and x != 
"collections" and x != "datetime" and x !=
                                     "sys" and x != "io" and x != "xrange", 
exported_vars))
 
         self.assertTrue(len(exported_vars) == len(exported_vars_test_vector))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/u-msgpack-python-2.4.1/u_msgpack_python.egg-info/PKG-INFO 
new/u-msgpack-python-2.5.0/u_msgpack_python.egg-info/PKG-INFO
--- old/u-msgpack-python-2.4.1/u_msgpack_python.egg-info/PKG-INFO       
2017-04-25 15:45:00.000000000 +0200
+++ new/u-msgpack-python-2.5.0/u_msgpack_python.egg-info/PKG-INFO       
2018-04-02 01:15:22.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: u-msgpack-python
-Version: 2.4.1
+Version: 2.5.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.4.1/u_msgpack_python.egg-info/SOURCES.txt 
new/u-msgpack-python-2.5.0/u_msgpack_python.egg-info/SOURCES.txt
--- old/u-msgpack-python-2.4.1/u_msgpack_python.egg-info/SOURCES.txt    
2017-04-25 15:45:00.000000000 +0200
+++ new/u-msgpack-python-2.5.0/u_msgpack_python.egg-info/SOURCES.txt    
2018-04-02 01:15:22.000000000 +0200
@@ -1,5 +1,6 @@
 LICENSE
 MANIFEST.in
+README.md
 setup.cfg
 setup.py
 test_umsgpack.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/u-msgpack-python-2.4.1/umsgpack.py 
new/u-msgpack-python-2.5.0/umsgpack.py
--- old/u-msgpack-python-2.4.1/umsgpack.py      2017-04-25 15:43:31.000000000 
+0200
+++ new/u-msgpack-python-2.5.0/umsgpack.py      2018-04-01 02:54:55.000000000 
+0200
@@ -1,4 +1,4 @@
-# u-msgpack-python v2.4.1 - v at sergeev.io
+# u-msgpack-python v2.5.0 - 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.4.1 - v at sergeev.io
+u-msgpack-python v2.5.0 - v at sergeev.io
 https://github.com/vsergeev/u-msgpack-python
 
 u-msgpack-python is a lightweight MessagePack serializer and deserializer
@@ -45,13 +45,14 @@
 """
 import struct
 import collections
+import datetime
 import sys
 import io
 
-__version__ = "2.4.1"
+__version__ = "2.5.0"
 "Module version string"
 
-version = (2, 4, 1)
+version = (2, 5, 0)
 "Module version tuple"
 
 
@@ -71,13 +72,9 @@
         Construct a new Ext object.
 
         Args:
-            type: application-defined type integer from 0 to 127
+            type: application-defined type integer
             data: application-defined data byte array
 
-        Raises:
-            TypeError:
-                Specified ext type is outside of 0 to 127 range.
-
         Example:
         >>> foo = umsgpack.Ext(0x05, b"\x01\x02\x03")
         >>> umsgpack.packb({u"special stuff": foo, u"awesome": True})
@@ -87,9 +84,9 @@
         Ext Object (Type: 0x05, Data: 01 02 03)
         >>>
         """
-        # Application ext type should be 0 <= type <= 127
-        if not isinstance(type, int) or not (type >= 0 and type <= 127):
-            raise TypeError("ext type out of range")
+        # Check type is type int
+        if not isinstance(type, int):
+            raise TypeError("ext type is not type integer")
         # Check data is type bytes
         elif sys.version_info[0] == 3 and not isinstance(data, bytes):
             raise TypeError("ext data is not type \'bytes\'")
@@ -168,6 +165,11 @@
     pass
 
 
+class UnsupportedTimestampException(UnpackException):
+    "Unsupported timestamp format encountered during unpacking."
+    pass
+
+
 class ReservedCodeException(UnpackException):
     "Reserved code encountered during unpacking."
     pass
@@ -341,6 +343,29 @@
         raise UnsupportedTypeException("huge ext data")
 
 
+def _pack_ext_timestamp(obj, fp, options):
+    delta = obj - _epoch
+    seconds = delta.seconds + delta.days * 86400
+    microseconds = delta.microseconds
+
+    if microseconds == 0 and 0 <= seconds <= 2**32 - 1:
+        # 32-bit timestamp
+        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))
+    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))
+    else:
+        raise UnsupportedTypeException("huge timestamp")
+
+
 def _pack_array(obj, fp, options):
     if len(obj) <= 15:
         fp.write(struct.pack("B", 0x90 | len(obj)))
@@ -428,6 +453,8 @@
         _pack_array(obj, fp, options)
     elif isinstance(obj, dict):
         _pack_map(obj, fp, options)
+    elif isinstance(obj, datetime.datetime):
+        _pack_ext_timestamp(obj, fp, options)
     elif isinstance(obj, Ext):
         _pack_ext(obj, fp, options)
     elif ext_handlers:
@@ -498,6 +525,8 @@
         _pack_array(obj, fp, options)
     elif isinstance(obj, dict):
         _pack_map(obj, fp, options)
+    elif isinstance(obj, datetime.datetime):
+        _pack_ext_timestamp(obj, fp, options)
     elif isinstance(obj, Ext):
         _pack_ext(obj, fp, options)
     elif ext_handlers:
@@ -703,16 +732,46 @@
     else:
         raise Exception("logic error, not ext: 0x%02x" % ord(code))
 
-    ext = Ext(ord(_read_except(fp, 1)), _read_except(fp, length))
+    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:
-        ext = ext_handlers[ext.type](ext)
+        return ext_handlers[ext.type](ext)
+
+    # Timestamp extension
+    if ext.type == -1:
+        return _unpack_ext_timestamp(ext, options)
 
     return ext
 
 
+def _unpack_ext_timestamp(ext, options):
+    if len(ext.data) == 4:
+        # 32-bit timestamp
+        seconds = struct.unpack(">I", ext.data)[0]
+        microseconds = 0
+    elif len(ext.data) == 8:
+        # 64-bit timestamp
+        value = struct.unpack(">Q", ext.data)[0]
+        seconds = value & 0x3ffffffff
+        microseconds = (value >> 34) // 1000
+    elif len(ext.data) == 12:
+        # 96-bit timestamp
+        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))
+
+    return _epoch + datetime.timedelta(seconds=seconds,
+                                       microseconds=microseconds)
+
+
 def _unpack_array(code, fp, options):
     if (ord(code) & 0xf0) == 0x90:
         length = (ord(code) & ~0xf0)
@@ -801,6 +860,8 @@
             Insufficient data to unpack the serialized object.
         InvalidStringException(UnpackException):
             Invalid UTF-8 string encountered during unpacking.
+        UnsupportedTimestampException(UnpackException):
+            Unsupported timestamp format encountered during unpacking.
         ReservedCodeException(UnpackException):
             Reserved code encountered during unpacking.
         UnhashableKeyException(UnpackException):
@@ -843,6 +904,8 @@
             Insufficient data to unpack the serialized object.
         InvalidStringException(UnpackException):
             Invalid UTF-8 string encountered during unpacking.
+        UnsupportedTimestampException(UnpackException):
+            Unsupported timestamp format encountered during unpacking.
         ReservedCodeException(UnpackException):
             Reserved code encountered during unpacking.
         UnhashableKeyException(UnpackException):
@@ -888,6 +951,8 @@
             Insufficient data to unpack the serialized object.
         InvalidStringException(UnpackException):
             Invalid UTF-8 string encountered during unpacking.
+        UnsupportedTimestampException(UnpackException):
+            Unsupported timestamp format encountered during unpacking.
         ReservedCodeException(UnpackException):
             Reserved code encountered during unpacking.
         UnhashableKeyException(UnpackException):
@@ -934,6 +999,8 @@
             Insufficient data to unpack the serialized object.
         InvalidStringException(UnpackException):
             Invalid UTF-8 string encountered during unpacking.
+        UnsupportedTimestampException(UnpackException):
+            Unsupported timestamp format encountered during unpacking.
         ReservedCodeException(UnpackException):
             Reserved code encountered during unpacking.
         UnhashableKeyException(UnpackException):
@@ -966,6 +1033,8 @@
     global load
     global loads
     global compatibility
+    global _epoch
+    global _utc_tzinfo
     global _float_precision
     global _unpack_dispatch_table
     global xrange
@@ -973,6 +1042,14 @@
     # Compatibility mode for handling strings/bytes with the old specification
     compatibility = False
 
+    if sys.version_info[0] == 3:
+        _utc_tzinfo = datetime.timezone.utc
+    else:
+        _utc_tzinfo = None
+
+    # Calculate epoch datetime
+    _epoch = datetime.datetime(1970, 1, 1, tzinfo=_utc_tzinfo)
+
     # Auto-detect system float precision
     if sys.float_info.mant_dig == 53:
         _float_precision = "double"


Reply via email to