u-msgpack-python 2.8.0__tar.gz → 2.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/LICENSE +1 -1
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/PKG-INFO +14 -3
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/README.md +2 -7
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/setup.cfg +0 -3
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/setup.py +3 -2
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/test_umsgpack.py +29 -16
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/u_msgpack_python.egg-info/PKG-INFO +14 -3
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/u_msgpack_python.egg-info/SOURCES.txt +2 -1
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/umsgpack/__init__.py +132 -33
- u_msgpack_python-2.9.0/umsgpack/__init__.pyi +126 -0
- u_msgpack_python-2.9.0/umsgpack/py.typed +0 -0
- u-msgpack-python-2.8.0/umsgpack/__init__.pyi +0 -41
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/MANIFEST.in +0 -0
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/u_msgpack_python.egg-info/dependency_links.txt +0 -0
- {u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/u_msgpack_python.egg-info/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2013-
|
|
1
|
+
Copyright (c) 2013-2026 vsergeev / Ivan (Vanya) A. Sergeev
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: u-msgpack-python
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
4
4
|
Summary: A portable, lightweight MessagePack serializer and deserializer written in pure Python.
|
|
5
5
|
Home-page: https://github.com/vsergeev/u-msgpack-python
|
|
6
6
|
Author: vsergeev
|
|
@@ -15,6 +15,17 @@ Classifier: Programming Language :: Python :: 2
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
16
16
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
17
17
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
18
|
+
Description-Content-Type: text/x-rst
|
|
18
19
|
License-File: LICENSE
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: description-content-type
|
|
25
|
+
Dynamic: home-page
|
|
26
|
+
Dynamic: keywords
|
|
27
|
+
Dynamic: license
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
Dynamic: summary
|
|
19
30
|
|
|
20
|
-
u-msgpack-python is a lightweight `MessagePack <http://msgpack.org/>`_ 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 <https://github.com/msgpack/msgpack/blob/master/spec.md>`_. In particular, it supports the new binary, UTF-8 string,
|
|
31
|
+
u-msgpack-python is a lightweight `MessagePack <http://msgpack.org/>`_ 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 <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. See https://github.com/vsergeev/u-msgpack-python for more information.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# u-msgpack-python [](https://github.com/vsergeev/u-msgpack-python/actions/workflows/tests.yml) [](https://u-msgpack-python.readthedocs.io/en/latest/) [](https://github.com/vsergeev/u-msgpack-python) [](https://github.com/vsergeev/u-msgpack-python/blob/master/LICENSE)
|
|
1
|
+
# u-msgpack-python [](https://github.com/vsergeev/u-msgpack-python/actions/workflows/tests.yml) [](https://u-msgpack-python.readthedocs.io/en/latest/) [](https://github.com/vsergeev/u-msgpack-python) [](https://github.com/vsergeev/u-msgpack-python/blob/master/LICENSE)
|
|
2
2
|
|
|
3
|
-
u-msgpack-python is a lightweight [MessagePack](http://msgpack.org/) serializer and deserializer module written in pure Python, compatible with 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.
|
|
3
|
+
u-msgpack-python is a lightweight [MessagePack](http://msgpack.org/) serializer and deserializer module written in pure Python, compatible with Python 2 and 3, as well as 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.
|
|
4
4
|
|
|
5
5
|
u-msgpack-python is currently distributed as a package on [PyPI](https://pypi.python.org/pypi/u-msgpack-python) and as a single file module.
|
|
6
6
|
|
|
@@ -11,11 +11,6 @@ With pip:
|
|
|
11
11
|
$ pip install u-msgpack-python
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
With easy_install:
|
|
15
|
-
``` text
|
|
16
|
-
$ easy_install u-msgpack-python
|
|
17
|
-
```
|
|
18
|
-
|
|
19
14
|
or simply drop `umsgpack.py` into your project!
|
|
20
15
|
``` text
|
|
21
16
|
$ wget https://raw.github.com/vsergeev/u-msgpack-python/master/umsgpack/__init__.py -O umsgpack.py
|
|
@@ -5,14 +5,15 @@ except ImportError:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name='u-msgpack-python',
|
|
8
|
-
version='2.
|
|
8
|
+
version='2.9.0',
|
|
9
9
|
description='A portable, lightweight MessagePack serializer and deserializer written in pure Python.',
|
|
10
10
|
author='vsergeev',
|
|
11
11
|
author_email='v@sergeev.io',
|
|
12
12
|
url='https://github.com/vsergeev/u-msgpack-python',
|
|
13
13
|
packages=['umsgpack'],
|
|
14
14
|
package_data={'umsgpack': ['*.pyi', 'py.typed']},
|
|
15
|
-
long_description="""u-msgpack-python is a lightweight `MessagePack <http://msgpack.org/>`_ 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 <https://github.com/msgpack/msgpack/blob/master/spec.md>`_. In particular, it supports the new binary, UTF-8 string,
|
|
15
|
+
long_description="""u-msgpack-python is a lightweight `MessagePack <http://msgpack.org/>`_ 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 <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. See https://github.com/vsergeev/u-msgpack-python for more information.""",
|
|
16
|
+
long_description_content_type='text/x-rst',
|
|
16
17
|
classifiers=[
|
|
17
18
|
"Development Status :: 5 - Production/Stable",
|
|
18
19
|
"License :: OSI Approved :: MIT License",
|
|
@@ -381,6 +381,7 @@ exported_vars_test_vector = [
|
|
|
381
381
|
"ReservedCodeException",
|
|
382
382
|
"UnhashableKeyException",
|
|
383
383
|
"DuplicateKeyException",
|
|
384
|
+
"MaximumDepthException",
|
|
384
385
|
"KeyNotPrimitiveException",
|
|
385
386
|
"KeyDuplicateException",
|
|
386
387
|
"ext_serializable",
|
|
@@ -438,9 +439,9 @@ class TestUmsgpack(unittest.TestCase):
|
|
|
438
439
|
# one we end up with depends on the architecture (32-bit/64-bit)
|
|
439
440
|
if sys.version_info[0] == 2:
|
|
440
441
|
# Allow both {int,long} -> unpackb -> {int,long}
|
|
441
|
-
if isinstance(obj, int) or isinstance(obj, long):
|
|
442
|
+
if isinstance(obj, int) or isinstance(obj, long): # noqa: F821
|
|
442
443
|
self.assertTrue(isinstance(unpacked, int) or
|
|
443
|
-
isinstance(unpacked, long))
|
|
444
|
+
isinstance(unpacked, long)) # noqa: F821
|
|
444
445
|
else:
|
|
445
446
|
self.assertTrue(isinstance(unpacked, type(obj)))
|
|
446
447
|
# In Python3, we only have the int integer type
|
|
@@ -490,7 +491,7 @@ class TestUmsgpack(unittest.TestCase):
|
|
|
490
491
|
# so convert any string obj to bytes before comparison
|
|
491
492
|
if sys.version_info[0] == 3 and isinstance(obj, str):
|
|
492
493
|
_obj = obj.encode('utf-8')
|
|
493
|
-
elif sys.version_info[0] == 2 and isinstance(obj, unicode):
|
|
494
|
+
elif sys.version_info[0] == 2 and isinstance(obj, unicode): # noqa: F821
|
|
494
495
|
_obj = bytes(obj)
|
|
495
496
|
else:
|
|
496
497
|
_obj = obj
|
|
@@ -712,11 +713,6 @@ class TestUmsgpack(unittest.TestCase):
|
|
|
712
713
|
with self.assertRaises(NotImplementedError):
|
|
713
714
|
umsgpack.unpackb(b"\xd4\x21\x00")
|
|
714
715
|
|
|
715
|
-
# Unregister Ext serializable classes to prevent interference with
|
|
716
|
-
# subsequent tests
|
|
717
|
-
umsgpack._ext_classes_to_code = {}
|
|
718
|
-
umsgpack._ext_code_to_classes = {}
|
|
719
|
-
|
|
720
716
|
def test_ext_serializable_subclass(self):
|
|
721
717
|
@umsgpack.ext_serializable(0x10)
|
|
722
718
|
class Rectangle:
|
|
@@ -746,17 +742,12 @@ class TestUmsgpack(unittest.TestCase):
|
|
|
746
742
|
unpacked = umsgpack.unpackb(packed)
|
|
747
743
|
self.assertEqual(unpacked, Rectangle(5, 5))
|
|
748
744
|
|
|
749
|
-
# Unregister Ext serializable classes to prevent interference with
|
|
750
|
-
# subsequent tests
|
|
751
|
-
umsgpack._ext_classes_to_code = {}
|
|
752
|
-
umsgpack._ext_code_to_classes = {}
|
|
753
|
-
|
|
754
745
|
def test_streaming_writer(self):
|
|
755
746
|
# Try first composite test vector
|
|
756
747
|
(_, obj, data) = composite_test_vectors[0]
|
|
757
748
|
writer = io.BytesIO()
|
|
758
749
|
umsgpack.pack(obj, writer)
|
|
759
|
-
self.
|
|
750
|
+
self.assertEqual(writer.getvalue(), data)
|
|
760
751
|
|
|
761
752
|
def test_streaming_reader(self):
|
|
762
753
|
# Try first composite test vector
|
|
@@ -764,12 +755,34 @@ class TestUmsgpack(unittest.TestCase):
|
|
|
764
755
|
reader = io.BytesIO(data)
|
|
765
756
|
self.assertEqual(umsgpack.unpack(reader), obj)
|
|
766
757
|
|
|
758
|
+
def test_max_depth_default_wraps_recursion(self):
|
|
759
|
+
# Default (no max_depth): deeply nested input must raise a
|
|
760
|
+
# MaximumDepthException (an UnpackException), not a bare RecursionError.
|
|
761
|
+
payload = b"\x91" * 5000 + b"\xc0"
|
|
762
|
+
self.assertRaises(umsgpack.MaximumDepthException, umsgpack.unpackb, payload)
|
|
763
|
+
self.assertRaises(umsgpack.UnpackException, umsgpack.unpackb, payload)
|
|
764
|
+
# Moderate nesting still works.
|
|
765
|
+
self.assertEqual(umsgpack.unpackb(b"\x91" * 100 + b"\xc0"),
|
|
766
|
+
umsgpack.unpackb(b"\x91" * 100 + b"\xc0"))
|
|
767
|
+
|
|
768
|
+
def test_max_depth_cap_arrays_and_maps(self):
|
|
769
|
+
self.assertTrue(
|
|
770
|
+
umsgpack.unpackb(b"\x91" * 32 + b"\xc0", max_depth=32) is not None)
|
|
771
|
+
self.assertRaises(umsgpack.MaximumDepthException,
|
|
772
|
+
umsgpack.unpackb, b"\x91" * 33 + b"\xc0", max_depth=32)
|
|
773
|
+
self.assertRaises(umsgpack.MaximumDepthException,
|
|
774
|
+
umsgpack.unpackb, b"\x81\xa1k" * 17 + b"\xc0", max_depth=16)
|
|
775
|
+
# Siblings are not counted, only nesting depth.
|
|
776
|
+
self.assertEqual(
|
|
777
|
+
len(umsgpack.unpackb(b"\xdc\x00\xc8" + b"\xc0" * 200, max_depth=1)), 200)
|
|
778
|
+
|
|
767
779
|
def test_namespacing(self):
|
|
768
780
|
# Get a list of global variables from umsgpack module
|
|
769
781
|
exported_vars = list([x for x in dir(umsgpack) if not x.startswith("_")])
|
|
770
782
|
# Ignore imports
|
|
771
|
-
|
|
772
|
-
|
|
783
|
+
ignore_vars = ["struct", "collections", "datetime", "sys", "io",
|
|
784
|
+
"xrange", "Hashable", "functools"]
|
|
785
|
+
exported_vars = [x for x in exported_vars if x not in ignore_vars]
|
|
773
786
|
|
|
774
787
|
self.assertTrue(len(exported_vars) == len(exported_vars_test_vector))
|
|
775
788
|
for var in exported_vars_test_vector:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: u-msgpack-python
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
4
4
|
Summary: A portable, lightweight MessagePack serializer and deserializer written in pure Python.
|
|
5
5
|
Home-page: https://github.com/vsergeev/u-msgpack-python
|
|
6
6
|
Author: vsergeev
|
|
@@ -15,6 +15,17 @@ Classifier: Programming Language :: Python :: 2
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
16
16
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
17
17
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
18
|
+
Description-Content-Type: text/x-rst
|
|
18
19
|
License-File: LICENSE
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: description-content-type
|
|
25
|
+
Dynamic: home-page
|
|
26
|
+
Dynamic: keywords
|
|
27
|
+
Dynamic: license
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
Dynamic: summary
|
|
19
30
|
|
|
20
|
-
u-msgpack-python is a lightweight `MessagePack <http://msgpack.org/>`_ 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 <https://github.com/msgpack/msgpack/blob/master/spec.md>`_. In particular, it supports the new binary, UTF-8 string,
|
|
31
|
+
u-msgpack-python is a lightweight `MessagePack <http://msgpack.org/>`_ 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 <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. See https://github.com/vsergeev/u-msgpack-python for more information.
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
# u-msgpack-python v2.
|
|
1
|
+
# u-msgpack-python v2.9.0 - v at sergeev.io
|
|
2
2
|
# https://github.com/vsergeev/u-msgpack-python
|
|
3
3
|
#
|
|
4
4
|
# u-msgpack-python is a lightweight MessagePack serializer and deserializer
|
|
5
|
-
# module, compatible with both Python 2 and 3, as well CPython and PyPy
|
|
5
|
+
# module, compatible with both Python 2 and 3, as well as CPython and PyPy
|
|
6
6
|
# implementations of Python. u-msgpack-python is fully compliant with the
|
|
7
|
-
# latest MessagePack specification
|
|
8
|
-
# particular, it
|
|
9
|
-
#
|
|
7
|
+
# latest MessagePack specification
|
|
8
|
+
# (https://github.com/msgpack/msgpack/blob/master/spec.md). In particular, it
|
|
9
|
+
# supports the new binary, UTF-8 string, application-defined ext, and
|
|
10
|
+
# timestamp types.
|
|
10
11
|
#
|
|
11
12
|
# MIT License
|
|
12
13
|
#
|
|
13
|
-
# Copyright (c) 2013-
|
|
14
|
+
# Copyright (c) 2013-2026 vsergeev / Ivan (Vanya) A. Sergeev
|
|
14
15
|
#
|
|
15
16
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
16
17
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -31,20 +32,22 @@
|
|
|
31
32
|
# THE SOFTWARE.
|
|
32
33
|
#
|
|
33
34
|
"""
|
|
34
|
-
u-msgpack-python v2.
|
|
35
|
+
u-msgpack-python v2.9.0 - v at sergeev.io
|
|
35
36
|
https://github.com/vsergeev/u-msgpack-python
|
|
36
37
|
|
|
37
38
|
u-msgpack-python is a lightweight MessagePack serializer and deserializer
|
|
38
|
-
module, compatible with both Python 2 and 3, as well CPython and PyPy
|
|
39
|
+
module, compatible with both Python 2 and 3, as well as CPython and PyPy
|
|
39
40
|
implementations of Python. u-msgpack-python is fully compliant with the
|
|
40
|
-
latest MessagePack specification
|
|
41
|
-
particular, it
|
|
41
|
+
latest MessagePack specification
|
|
42
|
+
(https://github.com/msgpack/msgpack/blob/master/spec.md). In particular, it
|
|
43
|
+
supports the new binary, UTF-8 string, application-defined ext, and timestamp
|
|
42
44
|
types.
|
|
43
45
|
|
|
44
46
|
License: MIT
|
|
45
47
|
"""
|
|
46
48
|
import struct
|
|
47
49
|
import collections
|
|
50
|
+
import functools
|
|
48
51
|
import datetime
|
|
49
52
|
import sys
|
|
50
53
|
import io
|
|
@@ -54,10 +57,11 @@ if sys.version_info[0:2] >= (3, 3):
|
|
|
54
57
|
else:
|
|
55
58
|
from collections import Hashable
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
|
|
61
|
+
__version__ = "2.9.0"
|
|
58
62
|
"Module version string"
|
|
59
63
|
|
|
60
|
-
version = (2,
|
|
64
|
+
version = (2, 9, 0)
|
|
61
65
|
"Module version tuple"
|
|
62
66
|
|
|
63
67
|
|
|
@@ -91,10 +95,10 @@ class Ext(object):
|
|
|
91
95
|
Example:
|
|
92
96
|
>>> foo = umsgpack.Ext(5, b"\\x01\\x02\\x03")
|
|
93
97
|
>>> umsgpack.packb({u"special stuff": foo, u"awesome": True})
|
|
94
|
-
'\\x82\\
|
|
98
|
+
b'\\x82\\xadspecial stuff\\xc7\\x03\\x05\\x01\\x02\\x03\\xa7awesome\\xc3'
|
|
95
99
|
>>> bar = umsgpack.unpackb(_)
|
|
96
100
|
>>> print(bar["special stuff"])
|
|
97
|
-
Ext Object (Type: 5, Data:
|
|
101
|
+
Ext Object (Type: 5, Data: 0x01 0x02 0x03)
|
|
98
102
|
"""
|
|
99
103
|
# Check type is type int and in range
|
|
100
104
|
if not isinstance(type, int):
|
|
@@ -238,6 +242,10 @@ class DuplicateKeyException(UnpackException):
|
|
|
238
242
|
"Duplicate key encountered during map unpacking."
|
|
239
243
|
|
|
240
244
|
|
|
245
|
+
class MaximumDepthException(UnpackException):
|
|
246
|
+
"Maximum nesting depth exceeded during unpacking."
|
|
247
|
+
|
|
248
|
+
|
|
241
249
|
# Backwards compatibility
|
|
242
250
|
KeyNotPrimitiveException = UnhashableKeyException
|
|
243
251
|
KeyDuplicateException = DuplicateKeyException
|
|
@@ -442,7 +450,7 @@ def _pack_map(obj, fp, options):
|
|
|
442
450
|
elif obj_len < 2**32:
|
|
443
451
|
fp.write(b"\xdf" + struct.pack(">I", obj_len))
|
|
444
452
|
else:
|
|
445
|
-
raise UnsupportedTypeException("huge
|
|
453
|
+
raise UnsupportedTypeException("huge map")
|
|
446
454
|
|
|
447
455
|
for k, v in obj.items():
|
|
448
456
|
pack(k, fp, **options)
|
|
@@ -480,8 +488,6 @@ def _pack2(obj, fp, **options):
|
|
|
480
488
|
>>> f = open('test.bin', 'wb')
|
|
481
489
|
>>> umsgpack.pack({u"compact": True, u"schema": 0}, f)
|
|
482
490
|
"""
|
|
483
|
-
global compatibility
|
|
484
|
-
|
|
485
491
|
ext_handlers = options.get("ext_handlers")
|
|
486
492
|
|
|
487
493
|
if obj is None:
|
|
@@ -566,8 +572,6 @@ def _pack3(obj, fp, **options):
|
|
|
566
572
|
>>> f = open('test.bin', 'wb')
|
|
567
573
|
>>> umsgpack.pack({u"compact": True, u"schema": 0}, f)
|
|
568
574
|
"""
|
|
569
|
-
global compatibility
|
|
570
|
-
|
|
571
575
|
ext_handlers = options.get("ext_handlers")
|
|
572
576
|
|
|
573
577
|
if obj is None:
|
|
@@ -777,7 +781,6 @@ def _unpack_string(code, fp, options):
|
|
|
777
781
|
raise Exception("logic error, not string: 0x{:02x}".format(ord(code)))
|
|
778
782
|
|
|
779
783
|
# Always return raw bytes in compatibility mode
|
|
780
|
-
global compatibility
|
|
781
784
|
if compatibility:
|
|
782
785
|
return _read_except(fp, length)
|
|
783
786
|
|
|
@@ -868,7 +871,7 @@ def _unpack_ext_timestamp(ext_data, options):
|
|
|
868
871
|
microseconds=microseconds)
|
|
869
872
|
|
|
870
873
|
|
|
871
|
-
def _unpack_array(code, fp, options):
|
|
874
|
+
def _unpack_array(code, fp, options, depth=None):
|
|
872
875
|
if (ord(code) & 0xf0) == 0x90:
|
|
873
876
|
length = (ord(code) & ~0xf0)
|
|
874
877
|
elif code == b'\xdc':
|
|
@@ -879,9 +882,12 @@ def _unpack_array(code, fp, options):
|
|
|
879
882
|
raise Exception("logic error, not array: 0x{:02x}".format(ord(code)))
|
|
880
883
|
|
|
881
884
|
if options.get('use_tuple'):
|
|
882
|
-
return tuple((_unpack(fp, options)
|
|
885
|
+
return tuple((_unpack(fp, options) if depth is None
|
|
886
|
+
else _unpack_depth(fp, options, depth)
|
|
887
|
+
for i in xrange(length)))
|
|
883
888
|
|
|
884
|
-
return [_unpack(fp, options)
|
|
889
|
+
return [_unpack(fp, options) if depth is None
|
|
890
|
+
else _unpack_depth(fp, options, depth) for i in xrange(length)]
|
|
885
891
|
|
|
886
892
|
|
|
887
893
|
def _deep_list_to_tuple(obj):
|
|
@@ -890,7 +896,7 @@ def _deep_list_to_tuple(obj):
|
|
|
890
896
|
return obj
|
|
891
897
|
|
|
892
898
|
|
|
893
|
-
def _unpack_map(code, fp, options):
|
|
899
|
+
def _unpack_map(code, fp, options, depth=None):
|
|
894
900
|
if (ord(code) & 0xf0) == 0x80:
|
|
895
901
|
length = (ord(code) & ~0xf0)
|
|
896
902
|
elif code == b'\xde':
|
|
@@ -903,7 +909,8 @@ def _unpack_map(code, fp, options):
|
|
|
903
909
|
d = {} if not options.get('use_ordered_dict') else collections.OrderedDict()
|
|
904
910
|
for _ in xrange(length):
|
|
905
911
|
# Unpack key
|
|
906
|
-
k = _unpack(fp, options)
|
|
912
|
+
k = _unpack(fp, options) if depth is None \
|
|
913
|
+
else _unpack_depth(fp, options, depth)
|
|
907
914
|
|
|
908
915
|
if isinstance(k, list):
|
|
909
916
|
# Attempt to convert list into a hashable tuple
|
|
@@ -916,7 +923,8 @@ def _unpack_map(code, fp, options):
|
|
|
916
923
|
"encountered duplicate key: \"{:s}\" ({:s})".format(str(k), str(type(k))))
|
|
917
924
|
|
|
918
925
|
# Unpack value
|
|
919
|
-
v = _unpack(fp, options)
|
|
926
|
+
v = _unpack(fp, options) if depth is None \
|
|
927
|
+
else _unpack_depth(fp, options, depth)
|
|
920
928
|
|
|
921
929
|
try:
|
|
922
930
|
d[k] = v
|
|
@@ -930,6 +938,33 @@ def _unpack(fp, options):
|
|
|
930
938
|
code = _read_except(fp, 1)
|
|
931
939
|
return _unpack_dispatch_table[code](code, fp, options)
|
|
932
940
|
|
|
941
|
+
|
|
942
|
+
def _unpack_depth(fp, options, depth):
|
|
943
|
+
code = _read_except(fp, 1)
|
|
944
|
+
return _unpack_depth_dispatch_table[code](code, fp, options, depth)
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
def _limit_depth(unpack_container):
|
|
948
|
+
"""Wrap a depth-aware container unpacker to enforce options['max_depth'].
|
|
949
|
+
|
|
950
|
+
depth is passed as a local argument and incremented on entry.
|
|
951
|
+
"""
|
|
952
|
+
@functools.wraps(unpack_container)
|
|
953
|
+
def wrapper(code, fp, options, depth):
|
|
954
|
+
depth += 1
|
|
955
|
+
if depth > options['max_depth']:
|
|
956
|
+
raise MaximumDepthException("maximum nesting depth exceeded")
|
|
957
|
+
return unpack_container(code, fp, options, depth)
|
|
958
|
+
return wrapper
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
def _ignore_depth(unpacker):
|
|
962
|
+
"""Adapt a scalar (non-container) unpacker to the depth dispatch signature."""
|
|
963
|
+
@functools.wraps(unpacker)
|
|
964
|
+
def wrapper(code, fp, options, depth):
|
|
965
|
+
return unpacker(code, fp, options)
|
|
966
|
+
return wrapper
|
|
967
|
+
|
|
933
968
|
########################################
|
|
934
969
|
|
|
935
970
|
|
|
@@ -951,6 +986,10 @@ def _unpack2(fp, **options):
|
|
|
951
986
|
allow_invalid_utf8 (bool): unpack invalid strings into instances of
|
|
952
987
|
:class:`InvalidString`, for access to the
|
|
953
988
|
bytes (default False)
|
|
989
|
+
max_depth (int): maximum nesting depth of arrays/maps to unpack; when
|
|
990
|
+
exceeded, :class:`MaximumDepthException` is raised. If
|
|
991
|
+
None (default), depth is bounded only by the
|
|
992
|
+
interpreter's recursion limit.
|
|
954
993
|
|
|
955
994
|
Returns:
|
|
956
995
|
Python object
|
|
@@ -969,13 +1008,23 @@ def _unpack2(fp, **options):
|
|
|
969
1008
|
The serialized map cannot be deserialized into a Python dictionary.
|
|
970
1009
|
DuplicateKeyException(UnpackException):
|
|
971
1010
|
Duplicate key encountered during map unpacking.
|
|
1011
|
+
MaximumDepthException(UnpackException):
|
|
1012
|
+
Maximum nesting depth exceeded while unpacking a deeply-nested
|
|
1013
|
+
object, or the configured limit was exceeded (when ``max_depth`` is
|
|
1014
|
+
set).
|
|
972
1015
|
|
|
973
1016
|
Example:
|
|
974
1017
|
>>> f = open('test.bin', 'rb')
|
|
975
|
-
>>> umsgpack.
|
|
1018
|
+
>>> umsgpack.unpack(f)
|
|
976
1019
|
{u'compact': True, u'schema': 0}
|
|
977
1020
|
"""
|
|
978
|
-
|
|
1021
|
+
try:
|
|
1022
|
+
return _unpack(fp, options) if options.get('max_depth') is None \
|
|
1023
|
+
else _unpack_depth(fp, options, 0)
|
|
1024
|
+
except RuntimeError as e:
|
|
1025
|
+
if "maximum recursion depth" in str(e):
|
|
1026
|
+
raise MaximumDepthException("maximum nesting depth exceeded")
|
|
1027
|
+
raise
|
|
979
1028
|
|
|
980
1029
|
|
|
981
1030
|
def _unpack3(fp, **options):
|
|
@@ -996,6 +1045,10 @@ def _unpack3(fp, **options):
|
|
|
996
1045
|
allow_invalid_utf8 (bool): unpack invalid strings into instances of
|
|
997
1046
|
:class:`InvalidString`, for access to the
|
|
998
1047
|
bytes (default False)
|
|
1048
|
+
max_depth (int): maximum nesting depth of arrays/maps to unpack; when
|
|
1049
|
+
exceeded, :class:`MaximumDepthException` is raised. If
|
|
1050
|
+
None (default), depth is bounded only by the
|
|
1051
|
+
interpreter's recursion limit.
|
|
999
1052
|
|
|
1000
1053
|
Returns:
|
|
1001
1054
|
Python object
|
|
@@ -1014,13 +1067,21 @@ def _unpack3(fp, **options):
|
|
|
1014
1067
|
The serialized map cannot be deserialized into a Python dictionary.
|
|
1015
1068
|
DuplicateKeyException(UnpackException):
|
|
1016
1069
|
Duplicate key encountered during map unpacking.
|
|
1070
|
+
MaximumDepthException(UnpackException):
|
|
1071
|
+
Maximum nesting depth exceeded while unpacking a deeply-nested
|
|
1072
|
+
object, or the configured limit was exceeded (when ``max_depth`` is
|
|
1073
|
+
set).
|
|
1017
1074
|
|
|
1018
1075
|
Example:
|
|
1019
1076
|
>>> f = open('test.bin', 'rb')
|
|
1020
|
-
>>> umsgpack.
|
|
1077
|
+
>>> umsgpack.unpack(f)
|
|
1021
1078
|
{'compact': True, 'schema': 0}
|
|
1022
1079
|
"""
|
|
1023
|
-
|
|
1080
|
+
try:
|
|
1081
|
+
return _unpack(fp, options) if options.get('max_depth') is None \
|
|
1082
|
+
else _unpack_depth(fp, options, 0)
|
|
1083
|
+
except RecursionError:
|
|
1084
|
+
raise MaximumDepthException("maximum nesting depth exceeded")
|
|
1024
1085
|
|
|
1025
1086
|
|
|
1026
1087
|
# For Python 2, expects a str object
|
|
@@ -1042,6 +1103,10 @@ def _unpackb2(s, **options):
|
|
|
1042
1103
|
allow_invalid_utf8 (bool): unpack invalid strings into instances of
|
|
1043
1104
|
:class:`InvalidString`, for access to the
|
|
1044
1105
|
bytes (default False)
|
|
1106
|
+
max_depth (int): maximum nesting depth of arrays/maps to unpack; when
|
|
1107
|
+
exceeded, :class:`MaximumDepthException` is raised. If
|
|
1108
|
+
None (default), depth is bounded only by the
|
|
1109
|
+
interpreter's recursion limit.
|
|
1045
1110
|
|
|
1046
1111
|
Returns:
|
|
1047
1112
|
Python object
|
|
@@ -1062,6 +1127,10 @@ def _unpackb2(s, **options):
|
|
|
1062
1127
|
The serialized map cannot be deserialized into a Python dictionary.
|
|
1063
1128
|
DuplicateKeyException(UnpackException):
|
|
1064
1129
|
Duplicate key encountered during map unpacking.
|
|
1130
|
+
MaximumDepthException(UnpackException):
|
|
1131
|
+
Maximum nesting depth exceeded while unpacking a deeply-nested
|
|
1132
|
+
object, or the configured limit was exceeded (when ``max_depth`` is
|
|
1133
|
+
set).
|
|
1065
1134
|
|
|
1066
1135
|
Example:
|
|
1067
1136
|
>>> umsgpack.unpackb(b'\\x82\\xa7compact\\xc3\\xa6schema\\x00')
|
|
@@ -1069,7 +1138,13 @@ def _unpackb2(s, **options):
|
|
|
1069
1138
|
"""
|
|
1070
1139
|
if not isinstance(s, (str, bytearray)):
|
|
1071
1140
|
raise TypeError("packed data must be type 'str' or 'bytearray'")
|
|
1072
|
-
|
|
1141
|
+
try:
|
|
1142
|
+
return _unpack(io.BytesIO(s), options) if options.get('max_depth') is None \
|
|
1143
|
+
else _unpack_depth(io.BytesIO(s), options, 0)
|
|
1144
|
+
except RuntimeError as e:
|
|
1145
|
+
if "maximum recursion depth" in str(e):
|
|
1146
|
+
raise MaximumDepthException("maximum nesting depth exceeded")
|
|
1147
|
+
raise
|
|
1073
1148
|
|
|
1074
1149
|
|
|
1075
1150
|
# For Python 3, expects a bytes object
|
|
@@ -1091,6 +1166,10 @@ def _unpackb3(s, **options):
|
|
|
1091
1166
|
allow_invalid_utf8 (bool): unpack invalid strings into instances of
|
|
1092
1167
|
:class:`InvalidString`, for access to the
|
|
1093
1168
|
bytes (default False)
|
|
1169
|
+
max_depth (int): maximum nesting depth of arrays/maps to unpack; when
|
|
1170
|
+
exceeded, :class:`MaximumDepthException` is raised. If
|
|
1171
|
+
None (default), depth is bounded only by the
|
|
1172
|
+
interpreter's recursion limit.
|
|
1094
1173
|
|
|
1095
1174
|
Returns:
|
|
1096
1175
|
Python object
|
|
@@ -1111,6 +1190,10 @@ def _unpackb3(s, **options):
|
|
|
1111
1190
|
The serialized map cannot be deserialized into a Python dictionary.
|
|
1112
1191
|
DuplicateKeyException(UnpackException):
|
|
1113
1192
|
Duplicate key encountered during map unpacking.
|
|
1193
|
+
MaximumDepthException(UnpackException):
|
|
1194
|
+
Maximum nesting depth exceeded while unpacking a deeply-nested
|
|
1195
|
+
object, or the configured limit was exceeded (when ``max_depth`` is
|
|
1196
|
+
set).
|
|
1114
1197
|
|
|
1115
1198
|
Example:
|
|
1116
1199
|
>>> umsgpack.unpackb(b'\\x82\\xa7compact\\xc3\\xa6schema\\x00')
|
|
@@ -1118,7 +1201,11 @@ def _unpackb3(s, **options):
|
|
|
1118
1201
|
"""
|
|
1119
1202
|
if not isinstance(s, (bytes, bytearray)):
|
|
1120
1203
|
raise TypeError("packed data must be type 'bytes' or 'bytearray'")
|
|
1121
|
-
|
|
1204
|
+
try:
|
|
1205
|
+
return _unpack(io.BytesIO(s), options) if options.get('max_depth') is None \
|
|
1206
|
+
else _unpack_depth(io.BytesIO(s), options, 0)
|
|
1207
|
+
except RecursionError:
|
|
1208
|
+
raise MaximumDepthException("maximum nesting depth exceeded")
|
|
1122
1209
|
|
|
1123
1210
|
#############################################################################
|
|
1124
1211
|
# Module Initialization
|
|
@@ -1194,7 +1281,7 @@ def __init():
|
|
|
1194
1281
|
# Build a dispatch table for fast lookup of unpacking function
|
|
1195
1282
|
|
|
1196
1283
|
_unpack_dispatch_table = {}
|
|
1197
|
-
#
|
|
1284
|
+
# Positive fixint
|
|
1198
1285
|
for code in range(0, 0x7f + 1):
|
|
1199
1286
|
_unpack_dispatch_table[struct.pack("B", code)] = _unpack_integer
|
|
1200
1287
|
# Fix map
|
|
@@ -1244,5 +1331,17 @@ def __init():
|
|
|
1244
1331
|
for code in range(0xe0, 0xff + 1):
|
|
1245
1332
|
_unpack_dispatch_table[struct.pack("B", code)] = _unpack_integer
|
|
1246
1333
|
|
|
1334
|
+
# Parallel dispatch table for the optional max_depth path. The array/map
|
|
1335
|
+
# entries are the same container functions as the default table, wrapped by
|
|
1336
|
+
# _limit_depth; scalar unpackers are adapted to accept (and ignore) the
|
|
1337
|
+
# depth argument so _unpack() can dispatch uniformly with no per-code switch.
|
|
1338
|
+
global _unpack_depth_dispatch_table
|
|
1339
|
+
_unpack_depth_dispatch_table = {}
|
|
1340
|
+
for code_bytes, unpacker in _unpack_dispatch_table.items():
|
|
1341
|
+
if unpacker is _unpack_array or unpacker is _unpack_map:
|
|
1342
|
+
_unpack_depth_dispatch_table[code_bytes] = _limit_depth(unpacker)
|
|
1343
|
+
else:
|
|
1344
|
+
_unpack_depth_dispatch_table[code_bytes] = _ignore_depth(unpacker)
|
|
1345
|
+
|
|
1247
1346
|
|
|
1248
1347
|
__init()
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from typing import Any, Callable, Protocol, TypeVar
|
|
2
|
+
|
|
3
|
+
_T = TypeVar("_T")
|
|
4
|
+
|
|
5
|
+
__version__: str
|
|
6
|
+
|
|
7
|
+
version: tuple[int, int, int]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def pack(
|
|
11
|
+
obj: Any,
|
|
12
|
+
fp: _SupportsWrite,
|
|
13
|
+
*,
|
|
14
|
+
ext_handlers: dict[type[Any], Callable[[Any], Ext]] | None = None,
|
|
15
|
+
force_float_precision: str = ...,
|
|
16
|
+
) -> None: ...
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def packb(
|
|
20
|
+
obj: Any,
|
|
21
|
+
*,
|
|
22
|
+
ext_handlers: dict[type[Any], Callable[[Any], Ext]] | None = None,
|
|
23
|
+
force_float_precision: str = ...,
|
|
24
|
+
) -> bytes: ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def dump(
|
|
28
|
+
obj: Any,
|
|
29
|
+
fp: _SupportsWrite,
|
|
30
|
+
*,
|
|
31
|
+
ext_handlers: dict[type[Any], Callable[[Any], Ext]] | None = None,
|
|
32
|
+
force_float_precision: str = ...,
|
|
33
|
+
) -> None: ...
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def dumps(
|
|
37
|
+
obj: Any,
|
|
38
|
+
*,
|
|
39
|
+
ext_handlers: dict[type[Any], Callable[[Any], Ext]] | None = None,
|
|
40
|
+
force_float_precision: str = ...,
|
|
41
|
+
) -> bytes: ...
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def unpackb(
|
|
45
|
+
s: bytes | bytearray | memoryview,
|
|
46
|
+
*,
|
|
47
|
+
ext_handlers: dict[int, Callable[[Ext], Any]] | None = None,
|
|
48
|
+
use_ordered_dict: bool = False,
|
|
49
|
+
use_tuple: bool = False,
|
|
50
|
+
allow_invalid_utf8: bool = False,
|
|
51
|
+
max_depth: int | None = None,
|
|
52
|
+
) -> Any: ...
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def unpack(
|
|
56
|
+
fp: _SupportsRead,
|
|
57
|
+
*,
|
|
58
|
+
ext_handlers: dict[int, Callable[[Ext], Any]] | None = None,
|
|
59
|
+
use_ordered_dict: bool = False,
|
|
60
|
+
use_tuple: bool = False,
|
|
61
|
+
allow_invalid_utf8: bool = False,
|
|
62
|
+
max_depth: int | None = None,
|
|
63
|
+
) -> Any: ...
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def loads(
|
|
67
|
+
s: bytes | bytearray | memoryview,
|
|
68
|
+
*,
|
|
69
|
+
ext_handlers: dict[int, Callable[[Ext], Any]] | None = None,
|
|
70
|
+
use_ordered_dict: bool = False,
|
|
71
|
+
use_tuple: bool = False,
|
|
72
|
+
allow_invalid_utf8: bool = False,
|
|
73
|
+
max_depth: int | None = None,
|
|
74
|
+
) -> Any: ...
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def load(
|
|
78
|
+
fp: _SupportsRead,
|
|
79
|
+
*,
|
|
80
|
+
ext_handlers: dict[int, Callable[[Ext], Any]] | None = None,
|
|
81
|
+
use_ordered_dict: bool = False,
|
|
82
|
+
use_tuple: bool = False,
|
|
83
|
+
allow_invalid_utf8: bool = False,
|
|
84
|
+
max_depth: int | None = None,
|
|
85
|
+
) -> Any: ...
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class _SupportsRead(Protocol):
|
|
89
|
+
def read(self, __size: int) -> bytes: ...
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class _SupportsWrite(Protocol):
|
|
93
|
+
def write(self, __data: bytes) -> Any: ...
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class Ext:
|
|
97
|
+
type: int
|
|
98
|
+
data: bytes
|
|
99
|
+
def __init__(self, type: int, data: bytes) -> None: ...
|
|
100
|
+
def __eq__(self, other: object) -> bool: ...
|
|
101
|
+
def __ne__(self, other: object) -> bool: ...
|
|
102
|
+
def __hash__(self) -> int: ...
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class InvalidString(bytes): ...
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def ext_serializable(ext_type: int) -> Callable[[type[_T]], type[_T]]: ...
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class PackException(Exception): ...
|
|
112
|
+
class UnpackException(Exception): ...
|
|
113
|
+
class UnsupportedTypeException(PackException): ...
|
|
114
|
+
class InsufficientDataException(UnpackException): ...
|
|
115
|
+
class InvalidStringException(UnpackException): ...
|
|
116
|
+
class UnsupportedTimestampException(UnpackException): ...
|
|
117
|
+
class ReservedCodeException(UnpackException): ...
|
|
118
|
+
class UnhashableKeyException(UnpackException): ...
|
|
119
|
+
class DuplicateKeyException(UnpackException): ...
|
|
120
|
+
class MaximumDepthException(UnpackException): ...
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
KeyNotPrimitiveException = UnhashableKeyException
|
|
124
|
+
KeyDuplicateException = DuplicateKeyException
|
|
125
|
+
|
|
126
|
+
compatibility: bool
|
|
File without changes
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
from typing import Any
|
|
2
|
-
|
|
3
|
-
__version__: str
|
|
4
|
-
|
|
5
|
-
version: tuple[int, int, int]
|
|
6
|
-
|
|
7
|
-
def pack(obj, fp, **options) -> None: ...
|
|
8
|
-
def packb(obj, **options) -> bytes: ...
|
|
9
|
-
def dump(obj, fp, **options) -> None: ...
|
|
10
|
-
def dumps(obj, **options) -> bytes: ...
|
|
11
|
-
|
|
12
|
-
def unpackb(s: bytes | bytearray, **options) -> Any: ...
|
|
13
|
-
def unpack(fp, **options) -> Any: ...
|
|
14
|
-
def loads(s: bytes | bytearray, **options) -> Any: ...
|
|
15
|
-
def load(fp, **options) -> Any: ...
|
|
16
|
-
|
|
17
|
-
class Ext:
|
|
18
|
-
type: int
|
|
19
|
-
data: bytes
|
|
20
|
-
def __init__(self, type: int, data: bytes) -> None: ...
|
|
21
|
-
def __eq__(self, other) -> bool: ...
|
|
22
|
-
def __ne__(self, other) -> bool: ...
|
|
23
|
-
def __hash__(self) -> int: ...
|
|
24
|
-
|
|
25
|
-
class InvalidString(bytes): ...
|
|
26
|
-
|
|
27
|
-
def ext_serializable(ext_type: int): ...
|
|
28
|
-
|
|
29
|
-
class PackException(Exception): ...
|
|
30
|
-
class UnpackException(Exception): ...
|
|
31
|
-
class UnsupportedTypeException(PackException): ...
|
|
32
|
-
class InsufficientDataException(UnpackException): ...
|
|
33
|
-
class InvalidStringException(UnpackException): ...
|
|
34
|
-
class UnsupportedTimestampException(UnpackException): ...
|
|
35
|
-
class ReservedCodeException(UnpackException): ...
|
|
36
|
-
class UnhashableKeyException(UnpackException): ...
|
|
37
|
-
class DuplicateKeyException(UnpackException): ...
|
|
38
|
-
KeyNotPrimitiveException = UnhashableKeyException
|
|
39
|
-
KeyDuplicateException = DuplicateKeyException
|
|
40
|
-
|
|
41
|
-
compatibility: bool
|
|
File without changes
|
{u-msgpack-python-2.8.0 → u_msgpack_python-2.9.0}/u_msgpack_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|