D2750: thirdparty: start vendoring cbor python library

pulkit (Pulkit Goyal) phabricator at mercurial-scm.org
Fri Mar 9 10:54:32 UTC 2018


pulkit created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  CBOR stands for Concise Binary Object Representation, which is a data format
  which is very compact and extensible.
  
  This patch moves the python library which can serilaize and deserialize python
  objects to/from cbor formats. The library is taken from
  https://github.com/agronholm/cbor2/ from changeset
  6dad14d08b841dbbacefa08f4b3505d68072b753.
  
  There is another python library for cbor at
  https://github.com/brianolson/cbor_py/ which is used in evolve extension and was
  imported in initial version of this series. That library though contains C code
  and is bit faster, but has known bugs around serializing nested structures, is
  unmaintained, raises an Exception object instead of a more dedicated Error type.
  
  So, it's better to use a bug free and actively maintained library.
  
  This library is not yet used and will be used in later commits.
  
  1. no-check-commit because we are importing a third library module

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D2750

AFFECTED FILES
  mercurial/thirdparty/cbor/.travis.yml
  mercurial/thirdparty/cbor/LICENSE.txt
  mercurial/thirdparty/cbor/README.rst
  mercurial/thirdparty/cbor/cbor2/__init__.py
  mercurial/thirdparty/cbor/cbor2/compat.py
  mercurial/thirdparty/cbor/cbor2/decoder.py
  mercurial/thirdparty/cbor/cbor2/encoder.py
  mercurial/thirdparty/cbor/cbor2/types.py
  mercurial/thirdparty/cbor/docs/conf.py
  mercurial/thirdparty/cbor/docs/customizing.rst
  mercurial/thirdparty/cbor/docs/index.rst
  mercurial/thirdparty/cbor/docs/modules/decoder.rst
  mercurial/thirdparty/cbor/docs/modules/encoder.rst
  mercurial/thirdparty/cbor/docs/modules/types.rst
  mercurial/thirdparty/cbor/docs/usage.rst
  mercurial/thirdparty/cbor/docs/versionhistory.rst
  mercurial/thirdparty/cbor/setup.cfg
  mercurial/thirdparty/cbor/setup.py
  mercurial/thirdparty/cbor/tests/test_decoder.py
  mercurial/thirdparty/cbor/tests/test_encoder.py
  mercurial/thirdparty/cbor/tests/test_types.py
  mercurial/thirdparty/cbor/tox.ini

CHANGE DETAILS

diff --git a/mercurial/thirdparty/cbor/tox.ini b/mercurial/thirdparty/cbor/tox.ini
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/tox.ini
@@ -0,0 +1,12 @@
+[tox]
+envlist = py27, py33, py34, py35, py36, pypy, pypy3, flake8
+skip_missing_interpreters = true
+
+[testenv]
+commands = python -m pytest {posargs}
+extras = test
+
+[testenv:flake8]
+deps = flake8
+commands = flake8 cbor2 tests
+skip_install = true
diff --git a/mercurial/thirdparty/cbor/tests/test_types.py b/mercurial/thirdparty/cbor/tests/test_types.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/tests/test_types.py
@@ -0,0 +1,36 @@
+import pytest
+
+from cbor2.types import CBORTag, CBORSimpleValue
+
+
+def test_tag_repr():
+    assert repr(CBORTag(600, 'blah')) == "CBORTag(600, 'blah')"
+
+
+def test_tag_equals():
+    tag1 = CBORTag(500, ['foo'])
+    tag2 = CBORTag(500, ['foo'])
+    tag3 = CBORTag(500, ['bar'])
+    assert tag1 == tag2
+    assert not tag1 == tag3
+    assert not tag1 == 500
+
+
+def test_simple_value_repr():
+    assert repr(CBORSimpleValue(1)) == "CBORSimpleValue(1)"
+
+
+def test_simple_value_equals():
+    tag1 = CBORSimpleValue(1)
+    tag2 = CBORSimpleValue(1)
+    tag3 = CBORSimpleValue(21)
+    assert tag1 == tag2
+    assert tag1 == 1
+    assert not tag1 == tag3
+    assert not tag1 == 21
+    assert not tag2 == "21"
+
+
+def test_simple_value_too_big():
+    exc = pytest.raises(TypeError, CBORSimpleValue, 256)
+    assert str(exc.value) == 'simple value too big'
diff --git a/mercurial/thirdparty/cbor/tests/test_encoder.py b/mercurial/thirdparty/cbor/tests/test_encoder.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/tests/test_encoder.py
@@ -0,0 +1,318 @@
+import re
+from binascii import unhexlify
+from collections import OrderedDict
+from datetime import datetime, timedelta, date
+from decimal import Decimal
+from email.mime.text import MIMEText
+from fractions import Fraction
+from uuid import UUID
+
+import pytest
+
+from cbor2.compat import timezone
+from cbor2.encoder import dumps, CBOREncodeError, dump, shareable_encoder
+from cbor2.types import CBORTag, undefined, CBORSimpleValue
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (0, '00'),
+    (1, '01'),
+    (10, '0a'),
+    (23, '17'),
+    (24, '1818'),
+    (100, '1864'),
+    (1000, '1903e8'),
+    (1000000, '1a000f4240'),
+    (1000000000000, '1b000000e8d4a51000'),
+    (18446744073709551615, '1bffffffffffffffff'),
+    (18446744073709551616, 'c249010000000000000000'),
+    (-18446744073709551616, '3bffffffffffffffff'),
+    (-18446744073709551617, 'c349010000000000000000'),
+    (-1, '20'),
+    (-10, '29'),
+    (-100, '3863'),
+    (-1000, '3903e7')
+])
+def test_integer(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value) == expected
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (1.1, 'fb3ff199999999999a'),
+    (1.0e+300, 'fb7e37e43c8800759c'),
+    (-4.1, 'fbc010666666666666'),
+    (float('inf'), 'f97c00'),
+    (float('nan'), 'f97e00'),
+    (float('-inf'), 'f9fc00')
+])
+def test_float(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value) == expected
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (b'', '40'),
+    (b'\x01\x02\x03\x04', '4401020304'),
+])
+def test_bytestring(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value) == expected
+
+
+def test_bytearray():
+    expected = unhexlify('4401020304')
+    assert dumps(bytearray(b'\x01\x02\x03\x04')) == expected
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (u'', '60'),
+    (u'a', '6161'),
+    (u'IETF', '6449455446'),
+    (u'"\\', '62225c'),
+    (u'\u00fc', '62c3bc'),
+    (u'\u6c34', '63e6b0b4')
+])
+def test_string(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value) == expected
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (False, 'f4'),
+    (True, 'f5'),
+    (None, 'f6'),
+    (undefined, 'f7')
+], ids=['false', 'true', 'null', 'undefined'])
+def test_special(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value) == expected
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (CBORSimpleValue(0), 'e0'),
+    (CBORSimpleValue(2), 'e2'),
+    (CBORSimpleValue(19), 'f3'),
+    (CBORSimpleValue(32), 'f820')
+])
+def test_simple_value(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value) == expected
+
+
+#
+# Tests for extension tags
+#
+
+ at pytest.mark.parametrize('value, as_timestamp, expected', [
+    (datetime(2013, 3, 21, 20, 4, 0, tzinfo=timezone.utc), False,
+     'c074323031332d30332d32315432303a30343a30305a'),
+    (datetime(2013, 3, 21, 20, 4, 0, 380841, tzinfo=timezone.utc), False,
+     'c0781b323031332d30332d32315432303a30343a30302e3338303834315a'),
+    (datetime(2013, 3, 21, 22, 4, 0, tzinfo=timezone(timedelta(hours=2))), False,
+     'c07819323031332d30332d32315432323a30343a30302b30323a3030'),
+    (datetime(2013, 3, 21, 20, 4, 0), False, 'c074323031332d30332d32315432303a30343a30305a'),
+    (datetime(2013, 3, 21, 20, 4, 0, tzinfo=timezone.utc), True, 'c11a514b67b0'),
+    (datetime(2013, 3, 21, 22, 4, 0, tzinfo=timezone(timedelta(hours=2))), True, 'c11a514b67b0')
+], ids=['datetime/utc', 'datetime+micro/utc', 'datetime/eet', 'naive', 'timestamp/utc',
+        'timestamp/eet'])
+def test_datetime(value, as_timestamp, expected):
+    expected = unhexlify(expected)
+    assert dumps(value, datetime_as_timestamp=as_timestamp, timezone=timezone.utc) == expected
+
+
+def test_date():
+    expected = unhexlify('c074323031332d30332d32315430303a30303a30305a')
+    assert dumps(date(2013, 3, 21), timezone=timezone.utc) == expected
+
+
+def test_naive_datetime():
+    """Test that naive datetimes are gracefully rejected when no timezone has been set."""
+    exc = pytest.raises(CBOREncodeError, dumps, datetime(2013, 3, 21))
+    exc.match('naive datetime encountered and no default timezone has been set')
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (Decimal('14.123'), 'c4822219372b'),
+    (Decimal('NaN'), 'f97e00'),
+    (Decimal('Infinity'), 'f97c00'),
+    (Decimal('-Infinity'), 'f9fc00')
+], ids=['normal', 'nan', 'inf', 'neginf'])
+def test_decimal(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value) == expected
+
+
+def test_rational():
+    expected = unhexlify('d81e820205')
+    assert dumps(Fraction(2, 5)) == expected
+
+
+def test_regex():
+    expected = unhexlify('d8236d68656c6c6f2028776f726c6429')
+    assert dumps(re.compile(u'hello (world)')) == expected
+
+
+def test_mime():
+    expected = unhexlify(
+        'd824787b436f6e74656e742d547970653a20746578742f706c61696e3b20636861727365743d2269736f2d38'
+        '3835392d3135220a4d494d452d56657273696f6e3a20312e300a436f6e74656e742d5472616e736665722d456'
+        'e636f64696e673a2071756f7465642d7072696e7461626c650a0a48656c6c6f203d413475726f')
+    message = MIMEText(u'Hello \u20acuro', 'plain', 'iso-8859-15')
+    assert dumps(message) == expected
+
+
+def test_uuid():
+    expected = unhexlify('d825505eaffac8b51e480581277fdcc7842faf')
+    assert dumps(UUID(hex='5eaffac8b51e480581277fdcc7842faf')) == expected
+
+
+def test_custom_tag():
+    expected = unhexlify('d917706548656c6c6f')
+    assert dumps(CBORTag(6000, u'Hello')) == expected
+
+
+def test_cyclic_array():
+    """Test that an array that contains itself can be serialized with value sharing enabled."""
+    expected = unhexlify('d81c81d81c81d81d00')
+    a = [[]]
+    a[0].append(a)
+    assert dumps(a, value_sharing=True) == expected
+
+
+def test_cyclic_array_nosharing():
+    """Test that serializing a cyclic structure w/o value sharing will blow up gracefully."""
+    a = []
+    a.append(a)
+    exc = pytest.raises(CBOREncodeError, dumps, a)
+    exc.match('cyclic data structure detected but value sharing is disabled')
+
+
+def test_cyclic_map():
+    """Test that a dict that contains itself can be serialized with value sharing enabled."""
+    expected = unhexlify('d81ca100d81d00')
+    a = {}
+    a[0] = a
+    assert dumps(a, value_sharing=True) == expected
+
+
+def test_cyclic_map_nosharing():
+    """Test that serializing a cyclic structure w/o value sharing will fail gracefully."""
+    a = {}
+    a[0] = a
+    exc = pytest.raises(CBOREncodeError, dumps, a)
+    exc.match('cyclic data structure detected but value sharing is disabled')
+
+
+ at pytest.mark.parametrize('value_sharing, expected', [
+    (False, '828080'),
+    (True, 'd81c82d81c80d81d01')
+], ids=['nosharing', 'sharing'])
+def test_not_cyclic_same_object(value_sharing, expected):
+    """Test that the same shareable object can be included twice if not in a cyclic structure."""
+    expected = unhexlify(expected)
+    a = []
+    b = [a, a]
+    assert dumps(b, value_sharing=value_sharing) == expected
+
+
+def test_unsupported_type():
+    exc = pytest.raises(CBOREncodeError, dumps, lambda: None)
+    exc.match('cannot serialize type function')
+
+
+def test_default():
+    class DummyType(object):
+        def __init__(self, state):
+            self.state = state
+
+    def default_encoder(encoder, value):
+        encoder.encode(value.state)
+
+    expected = unhexlify('820305')
+    obj = DummyType([3, 5])
+    serialized = dumps(obj, default=default_encoder)
+    assert serialized == expected
+
+
+def test_default_cyclic():
+    class DummyType(object):
+        def __init__(self, value=None):
+            self.value = value
+
+    @shareable_encoder
+    def default_encoder(encoder, value):
+        state = encoder.encode_to_bytes(value.value)
+        encoder.encode(CBORTag(3000, state))
+
+    expected = unhexlify('D81CD90BB849D81CD90BB843D81D00')
+    obj = DummyType()
+    obj2 = DummyType(obj)
+    obj.value = obj2
+    serialized = dumps(obj, value_sharing=True, default=default_encoder)
+    assert serialized == expected
+
+
+def test_dump_to_file(tmpdir):
+    path = tmpdir.join('testdata.cbor')
+    with path.open('wb') as fp:
+        dump([1, 10], fp)
+
+    assert path.read_binary() == b'\x82\x01\x0a'
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (OrderedDict([(b'a', b''), (b'b', b'')]), 'A2416140416240'),
+    (OrderedDict([(b'b', b''), (b'a', b'')]), 'A2416140416240'),
+    (OrderedDict([(u'a', u''), (u'b', u'')]), 'a2616160616260'),
+    (OrderedDict([(u'b', u''), (u'a', u'')]), 'a2616160616260'),
+    (OrderedDict([(b'00001', u''), (b'002', u'')]), 'A2433030326045303030303160'),
+    (OrderedDict([(255, 0), (2, 0)]), 'a2020018ff00')
+], ids=['bytes in order', 'bytes out of order', 'text in order',
+        'text out of order', 'byte length', 'integer keys'])
+def test_ordered_map(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value, canonical=True) == expected
+
+
+ at pytest.mark.parametrize('value, expected', [
+    (3.5, 'F94300'),
+    (100000.0, 'FA47C35000'),
+    (3.8, 'FB400E666666666666'),
+    (float('inf'), 'f97c00'),
+    (float('nan'), 'f97e00'),
+    (float('-inf'), 'f9fc00'),
+    (float.fromhex('0x1.0p-24'), 'f90001'),
+    (float.fromhex('0x1.4p-24'), 'fa33a00000'),
+    (float.fromhex('0x1.ff8p-63'), 'fa207fc000')
+], ids=['float 16', 'float 32', 'float 64', 'inf', 'nan', '-inf',
+        'float 16 minimum positive subnormal', 'mantissa o/f to 32',
+        'exponent o/f to 32'])
+def test_minimal_floats(value, expected):
+    expected = unhexlify(expected)
+    assert dumps(value, canonical=True) == expected
+
+
+def test_tuple_key():
+    assert dumps({(2, 1): u''}) == unhexlify('a182020160')
+
+
+ at pytest.mark.parametrize('frozen', [False, True], ids=['set', 'frozenset'])
+def test_set(frozen):
+    value = {u'a', u'b', u'c'}
+    if frozen:
+        value = frozenset(value)
+
+    serialized = dumps(value)
+    assert len(serialized) == 10
+    assert serialized.startswith(unhexlify('d9010283'))
+
+
+ at pytest.mark.parametrize('frozen', [False, True], ids=['set', 'frozenset'])
+def test_canonical_set(frozen):
+    value = {u'y', u'x', u'aa', u'a'}
+    if frozen:
+        value = frozenset(value)
+
+    serialized = dumps(value, canonical=True)
+    assert serialized == unhexlify('d9010284616161786179626161')
diff --git a/mercurial/thirdparty/cbor/tests/test_decoder.py b/mercurial/thirdparty/cbor/tests/test_decoder.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/tests/test_decoder.py
@@ -0,0 +1,342 @@
+from __future__ import division
+
+import math
+import re
+import sys
+from binascii import unhexlify
+from datetime import datetime, timedelta
+from decimal import Decimal
+from email.message import Message
+from fractions import Fraction
+from io import BytesIO
+from uuid import UUID
+
+import pytest
+
+from cbor2.compat import timezone
+from cbor2.decoder import loads, CBORDecodeError, load, CBORDecoder
+from cbor2.types import CBORTag, undefined, CBORSimpleValue
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('00', 0),
+    ('01', 1),
+    ('0a', 10),
+    ('17', 23),
+    ('1818', 24),
+    ('1819', 25),
+    ('1864', 100),
+    ('1903e8', 1000),
+    ('1a000f4240', 1000000),
+    ('1b000000e8d4a51000', 1000000000000),
+    ('1bffffffffffffffff', 18446744073709551615),
+    ('c249010000000000000000', 18446744073709551616),
+    ('3bffffffffffffffff', -18446744073709551616),
+    ('c349010000000000000000', -18446744073709551617),
+    ('20', -1),
+    ('29', -10),
+    ('3863', -100),
+    ('3903e7', -1000)
+])
+def test_integer(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+def test_invalid_integer_subtype():
+    exc = pytest.raises(CBORDecodeError, loads, b'\x1c')
+    assert str(exc.value).endswith('unknown unsigned integer subtype 0x1c')
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('f90000', 0.0),
+    ('f98000', -0.0),
+    ('f93c00', 1.0),
+    ('fb3ff199999999999a', 1.1),
+    ('f93e00', 1.5),
+    ('f97bff', 65504.0),
+    ('fa47c35000', 100000.0),
+    ('fa7f7fffff', 3.4028234663852886e+38),
+    ('fb7e37e43c8800759c', 1.0e+300),
+    ('f90001', 5.960464477539063e-8),
+    ('f90400', 0.00006103515625),
+    ('f9c400', -4.0),
+    ('fbc010666666666666', -4.1),
+    ('f97c00', float('inf')),
+    ('f9fc00', float('-inf')),
+    ('fa7f800000', float('inf')),
+    ('faff800000', float('-inf')),
+    ('fb7ff0000000000000', float('inf')),
+    ('fbfff0000000000000', float('-inf'))
+])
+def test_float(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+ at pytest.mark.parametrize('payload', ['f97e00', 'fa7fc00000', 'fb7ff8000000000000'])
+def test_float_nan(payload):
+    decoded = loads(unhexlify(payload))
+    assert math.isnan(decoded)
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('f4', False),
+    ('f5', True),
+    ('f6', None),
+    ('f7', undefined)
+])
+def test_special(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded is expected
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('40', b''),
+    ('4401020304', b'\x01\x02\x03\x04'),
+])
+def test_binary(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('60', u''),
+    ('6161', u'a'),
+    ('6449455446', u'IETF'),
+    ('62225c', u'\"\\'),
+    ('62c3bc', u'\u00fc'),
+    ('63e6b0b4', u'\u6c34')
+])
+def test_string(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('80', []),
+    ('83010203', [1, 2, 3]),
+    ('8301820203820405', [1, [2, 3], [4, 5]]),
+    ('98190102030405060708090a0b0c0d0e0f101112131415161718181819', list(range(1, 26)))
+])
+def test_array(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('a0', {}),
+    ('a201020304', {1: 2, 3: 4})
+])
+def test_map(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('a26161016162820203', {'a': 1, 'b': [2, 3]}),
+    ('826161a161626163', ['a', {'b': 'c'}]),
+    ('a56161614161626142616361436164614461656145',
+     {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D', 'e': 'E'})
+])
+def test_mixed_array_map(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('5f42010243030405ff', b'\x01\x02\x03\x04\x05'),
+    ('7f657374726561646d696e67ff', 'streaming'),
+    ('9fff', []),
+    ('9f018202039f0405ffff', [1, [2, 3], [4, 5]]),
+    ('9f01820203820405ff', [1, [2, 3], [4, 5]]),
+    ('83018202039f0405ff', [1, [2, 3], [4, 5]]),
+    ('83019f0203ff820405', [1, [2, 3], [4, 5]]),
+    ('9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff', list(range(1, 26))),
+    ('bf61610161629f0203ffff', {'a': 1, 'b': [2, 3]}),
+    ('826161bf61626163ff', ['a', {'b': 'c'}]),
+    ('bf6346756ef563416d7421ff', {'Fun': True, 'Amt': -2}),
+])
+def test_streaming(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('e0', 0),
+    ('e2', 2),
+    ('f3', 19),
+    ('f820', 32),
+    ('e0', CBORSimpleValue(0)),
+    ('e2', CBORSimpleValue(2)),
+    ('f3', CBORSimpleValue(19)),
+    ('f820', CBORSimpleValue(32))
+])
+def test_simple_value(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+#
+# Tests for extension tags
+#
+
+
+ at pytest.mark.parametrize('payload, expected', [
+    ('c074323031332d30332d32315432303a30343a30305a',
+     datetime(2013, 3, 21, 20, 4, 0, tzinfo=timezone.utc)),
+    ('c0781b323031332d30332d32315432303a30343a30302e3338303834315a',
+     datetime(2013, 3, 21, 20, 4, 0, 380841, tzinfo=timezone.utc)),
+    ('c07819323031332d30332d32315432323a30343a30302b30323a3030',
+     datetime(2013, 3, 21, 22, 4, 0, tzinfo=timezone(timedelta(hours=2)))),
+    ('c11a514b67b0', datetime(2013, 3, 21, 20, 4, 0, tzinfo=timezone.utc)),
+    ('c11a514b67b0', datetime(2013, 3, 21, 22, 4, 0, tzinfo=timezone(timedelta(hours=2))))
+], ids=['datetime/utc', 'datetime+micro/utc', 'datetime/eet', 'timestamp/utc', 'timestamp/eet'])
+def test_datetime(payload, expected):
+    decoded = loads(unhexlify(payload))
+    assert decoded == expected
+
+
+def test_bad_datetime():
+    exc = pytest.raises(CBORDecodeError, loads, unhexlify('c06b303030302d3132332d3031'))
+    assert str(exc.value).endswith('invalid datetime string: 0000-123-01')
+
+
+def test_fraction():
+    decoded = loads(unhexlify('c48221196ab3'))
+    assert decoded == Decimal('273.15')
+
+
+def test_bigfloat():
+    decoded = loads(unhexlify('c5822003'))
+    assert decoded == Decimal('1.5')
+
+
+def test_rational():
+    decoded = loads(unhexlify('d81e820205'))
+    assert decoded == Fraction(2, 5)
+
+
+def test_regex():
+    decoded = loads(unhexlify('d8236d68656c6c6f2028776f726c6429'))
+    expr = re.compile(u'hello (world)')
+    assert decoded == expr
+
+
+def test_mime():
+    decoded = loads(unhexlify(
+        'd824787b436f6e74656e742d547970653a20746578742f706c61696e3b20636861727365743d2269736f2d38'
+        '3835392d3135220a4d494d452d56657273696f6e3a20312e300a436f6e74656e742d5472616e736665722d45'
+        '6e636f64696e673a2071756f7465642d7072696e7461626c650a0a48656c6c6f203d413475726f'))
+    assert isinstance(decoded, Message)
+    assert decoded.get_payload() == 'Hello =A4uro'
+
+
+def test_uuid():
+    decoded = loads(unhexlify('d825505eaffac8b51e480581277fdcc7842faf'))
+    assert decoded == UUID(hex='5eaffac8b51e480581277fdcc7842faf')
+
+
+def test_bad_shared_reference():
+    exc = pytest.raises(CBORDecodeError, loads, unhexlify('d81d05'))
+    assert str(exc.value).endswith('shared reference 5 not found')
+
+
+def test_uninitialized_shared_reference():
+    fp = BytesIO(unhexlify('d81d00'))
+    decoder = CBORDecoder(fp)
+    decoder._shareables.append(None)
+    exc = pytest.raises(CBORDecodeError, decoder.decode)
+    assert str(exc.value).endswith('shared value 0 has not been initialized')
+
+
+def test_cyclic_array():
+    decoded = loads(unhexlify('d81c81d81d00'))
+    assert decoded == [decoded]
+
+
+def test_cyclic_map():
+    decoded = loads(unhexlify('d81ca100d81d00'))
+    assert decoded == {0: decoded}
+
+
+def test_unhandled_tag():
+    """
+    Test that a tag is simply ignored and its associated value returned if there is no special
+    handling available for it.
+
+    """
+    decoded = loads(unhexlify('d917706548656c6c6f'))
+    assert decoded == CBORTag(6000, u'Hello')
+
+
+def test_premature_end_of_stream():
+    """
+    Test that the decoder detects a situation where read() returned fewer than expected bytes.
+
+    """
+    exc = pytest.raises(CBORDecodeError, loads, unhexlify('437879'))
+    exc.match('premature end of stream \(expected to read 3 bytes, got 2 instead\)')
+
+
+def test_tag_hook():
+    def reverse(decoder, tag, fp, shareable_index=None):
+        return tag.value[::-1]
+
+    decoded = loads(unhexlify('d917706548656c6c6f'), tag_hook=reverse)
+    assert decoded == u'olleH'
+
+
+def test_tag_hook_cyclic():
+    class DummyType(object):
+        def __init__(self, value):
+            self.value = value
+
+    def unmarshal_dummy(decoder, tag, shareable_index=None):
+        instance = DummyType.__new__(DummyType)
+        decoder.set_shareable(shareable_index, instance)
+        instance.value = decoder.decode_from_bytes(tag.value)
+        return instance
+
+    decoded = loads(unhexlify('D81CD90BB849D81CD90BB843D81D00'), tag_hook=unmarshal_dummy)
+    assert isinstance(decoded, DummyType)
+    assert decoded.value.value is decoded
+
+
+def test_object_hook():
+    class DummyType(object):
+        def __init__(self, state):
+            self.state = state
+
+    payload = unhexlify('A2616103616205')
+    decoded = loads(payload, object_hook=lambda decoder, value: DummyType(value))
+    assert isinstance(decoded, DummyType)
+    assert decoded.state == {'a': 3, 'b': 5}
+
+
+def test_error_major_type():
+    exc = pytest.raises(CBORDecodeError, loads, b'')
+    assert str(exc.value).startswith('error reading major type at index 0: ')
+
+
+def test_load_from_file(tmpdir):
+    path = tmpdir.join('testdata.cbor')
+    path.write_binary(b'\x82\x01\x0a')
+    with path.open('rb') as fp:
+        obj = load(fp)
+
+    assert obj == [1, 10]
+
+
+ at pytest.mark.skipif(sys.version_info < (3, 0), reason="No exception with python 2.7")
+def test_nested_exception():
+    exc = pytest.raises((CBORDecodeError, TypeError), loads, unhexlify('A1D9177082010201'))
+    exc.match(r"error decoding value at index 8: "
+              r"(unhashable type: 'CBORTag'|'CBORTag' objects are unhashable)")
+
+
+def test_set():
+    payload = unhexlify('d9010283616361626161')
+    value = loads(payload)
+    assert type(value) is set
+    assert value == set([u'a', u'b', u'c'])
diff --git a/mercurial/thirdparty/cbor/setup.py b/mercurial/thirdparty/cbor/setup.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/setup.py
@@ -0,0 +1,12 @@
+from setuptools import setup
+
+setup(
+    use_scm_version={
+        'version_scheme': 'post-release',
+        'local_scheme': 'dirty-tag'
+    },
+    setup_requires=[
+        'setuptools >= 36.2.7',
+        'setuptools_scm >= 1.7.0'
+    ]
+)
diff --git a/mercurial/thirdparty/cbor/setup.cfg b/mercurial/thirdparty/cbor/setup.cfg
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/setup.cfg
@@ -0,0 +1,46 @@
+[metadata]
+name = cbor2
+description = Pure Python CBOR (de)serializer with extensive tag support
+long_description = file: README.rst
+author = Alex Grönholm
+author_email = alex.gronholm at nextday.fi
+url = https://github.com/agronholm/cbor2
+license = MIT
+license_file = LICENSE.txt
+keywords = serialization cbor
+classifiers =
+    Development Status :: 5 - Production/Stable
+    Intended Audience :: Developers
+    License :: OSI Approved :: MIT License
+    Programming Language :: Python
+    Programming Language :: Python :: 2.7
+    Programming Language :: Python :: 3
+    Programming Language :: Python :: 3.3
+    Programming Language :: Python :: 3.4
+    Programming Language :: Python :: 3.5
+    Programming Language :: Python :: 3.6
+
+[options]
+packages = find:
+
+[options.extras_require]
+test =
+    pytest
+    pytest-cov
+
+[tool:pytest]
+addopts = -rsx --cov --tb=short
+testpaths = tests
+
+[coverage:run]
+source = cbor2
+
+[coverage:report]
+show_missing = true
+
+[flake8]
+max-line-length = 99
+exclude = .tox,build,docs
+
+[bdist_wheel]
+universal = 1
diff --git a/mercurial/thirdparty/cbor/docs/versionhistory.rst b/mercurial/thirdparty/cbor/docs/versionhistory.rst
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/docs/versionhistory.rst
@@ -0,0 +1,78 @@
+Version history
+===============
+
+This library adheres to `Semantic Versioning <http://semver.org/>`_.
+
+**UNRELEASED**
+
+- Added canonical encoding (via ``canonical=True``) (PR by Sekenre)
+- Added support for encoding/decoding sets (semantic tag 258) (PR by Sekenre)
+
+**4.0.1** (2017-08-21)
+
+- Fixed silent truncation of decoded data if there are not enough bytes in the stream for an exact
+  read (``CBORDecodeError`` is now raised instead)
+
+**4.0.0** (2017-04-24)
+
+- **BACKWARD INCOMPATIBLE** Value sharing has been disabled by default, for better compatibility
+  with other implementations and better performance (since it is rarely needed)
+- **BACKWARD INCOMPATIBLE** Replaced the ``semantic_decoders`` decoder option with the ``tag_hook``
+  option
+- **BACKWARD INCOMPATIBLE** Replaced the ``encoders`` encoder option with the ``default`` option
+- **BACKWARD INCOMPATIBLE** Factored out the file object argument (``fp``) from all callbacks
+- **BACKWARD INCOMPATIBLE** The encoder no longer supports every imaginable type implementing the
+  ``Sequence`` or ``Map`` interface, as they turned out to be too broad
+- Added the ``object_hook`` option for decoding dicts into complex objects
+  (intended for situations where JSON compatibility is required and semantic tags cannot be used)
+- Added encoding and decoding of simple values (``CBORSimpleValue``)
+  (contributed by Jerry Lundström)
+- Replaced the decoder for bignums with a simpler and faster version (contributed by orent)
+- Made all relevant classes and functions available directly in the ``cbor2`` namespace
+- Added proper documentation
+
+**3.0.4** (2016-09-24)
+
+- Fixed TypeError when trying to encode extension types (regression introduced in 3.0.3)
+
+**3.0.3** (2016-09-23)
+
+- No changes, just re-releasing due to git tagging screw-up
+
+**3.0.2** (2016-09-23)
+
+- Fixed decoding failure for datetimes with microseconds (tag 0)
+
+**3.0.1** (2016-08-08)
+
+- Fixed error in the cyclic structure detection code that could mistake one container for
+  another, sometimes causing a bogus error about cyclic data structures where there was none
+
+**3.0.0** (2016-07-03)
+
+- **BACKWARD INCOMPATIBLE** Encoder callbacks now receive three arguments: the encoder instance,
+  the value to encode and a file-like object. The callback must must now either write directly to
+  the file-like object or call another encoder callback instead of returning an iterable.
+- **BACKWARD INCOMPATIBLE** Semantic decoder callbacks now receive four arguments: the decoder
+  instance, the primitive value, a file-like object and the shareable index for the decoded value.
+  Decoders that support value sharing must now set the raw value at the given index in
+  ``decoder.shareables``.
+- **BACKWARD INCOMPATIBLE** Removed support for iterative encoding (``CBOREncoder.encode()`` is no
+  longer a generator function and always returns ``None``)
+- Significantly improved performance (encoder ~30 % faster, decoder ~60 % faster)
+- Fixed serialization round-trip for ``undefined`` (simple type #23)
+- Added proper support for value sharing in callbacks
+
+**2.0.0** (2016-06-11)
+
+- **BACKWARD INCOMPATIBLE** Deserialize unknown tags as ``CBORTag`` objects so as not to lose
+  information
+- Fixed error messages coming from nested structures
+
+**1.1.0** (2016-06-10)
+
+- Fixed deserialization of cyclic structures
+
+**1.0.0** (2016-06-08)
+
+- Initial release
diff --git a/mercurial/thirdparty/cbor/docs/usage.rst b/mercurial/thirdparty/cbor/docs/usage.rst
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/docs/usage.rst
@@ -0,0 +1,81 @@
+Basic usage
+===========
+
+Serializing and deserializing with cbor2 is pretty straightforward::
+
+    from cbor2 import dumps, loads
+
+    # Serialize an object as a bytestring
+    data = dumps(['hello', 'world'])
+
+    # Deserialize a bytestring
+    obj = loads(data)
+
+    # Efficiently deserialize from a file
+    with open('input.cbor', 'rb') as fp:
+        obj = load(fp)
+
+    # Efficiently serialize an object to a file
+    with open('output.cbor', 'wb') as fp:
+        dump(obj, fp)
+
+Some data types, however, require extra considerations, as detailed below.
+
+String/bytes handling on Python 2
+---------------------------------
+
+The ``str`` type is encoded as binary on Python 2. If you want to encode strings as text on
+Python 2, use unicode strings instead.
+
+Date/time handling
+------------------
+
+The CBOR specification does not support naïve datetimes (that is, datetimes where ``tzinfo`` is
+missing). When the encoder encounters such a datetime, it needs to know which timezone it belongs
+to. To this end, you can specify a default timezone by passing a :class:`~datetime.tzinfo` instance
+to :func:`~cbor2.encoder.dump`/:func:`~cbor2.encoder.dumps` call as the ``timezone`` argument.
+Decoded datetimes are always timezone aware.
+
+By default, datetimes are serialized in a manner that retains their timezone offsets. You can
+optimize the data stream size by passing ``datetime_as_timestamp=False`` to
+:func:`~cbor2.encoder.dump`/:func:`~cbor2.encoder.dumps`, but this causes the timezone offset
+information to be lost.
+
+Cyclic (recursive) data structures
+----------------------------------
+
+If the encoder encounters a shareable object (ie. list or dict) that it has been before, it will
+by default raise :exc:`~cbor2.encoder.CBOREncodeError` indicating that a cyclic reference has been
+detected and value sharing was not enabled. CBOR has, however, an extension specification that
+allows the encoder to reference a previously encoded value without processing it again. This makes
+it possible to serialize such cyclic references, but value sharing has to be enabled by passing
+``value_sharing=True`` to :func:`~cbor2.encoder.dump`/:func:`~cbor2.encoder.dumps`.
+
+.. warning:: Support for value sharing is rare in other CBOR implementations, so think carefully
+    whether you want to enable it. It also causes some line overhead, as all potentially shareable
+    values must be tagged as such.
+
+Tag support
+-----------
+
+In addition to all standard CBOR tags, this library supports many extended tags:
+
+=== ======================================== ====================================================
+Tag Semantics                                Python type(s)
+=== ======================================== ====================================================
+0   Standard date/time string                datetime.date / datetime.datetime
+1   Epoch-based date/time                    datetime.date / datetime.datetime
+2   Positive bignum                          int / long
+3   Negative bignum                          int / long
+4   Decimal fraction                         decimal.Decimal
+5   Bigfloat                                 decimal.Decimal
+28  Mark shared value                        N/A
+29  Reference shared value                   N/A
+30  Rational number                          fractions.Fraction
+35  Regular expression                       ``_sre.SRE_Pattern`` (result of ``re.compile(...)``)
+36  MIME message                             email.message.Message
+37  Binary UUID                              uuid.UUID
+258 Set of unique items                      set
+=== ======================================== ====================================================
+
+Arbitary tags can be represented with the :class:`~cbor2.types.CBORTag` class.
diff --git a/mercurial/thirdparty/cbor/docs/modules/types.rst b/mercurial/thirdparty/cbor/docs/modules/types.rst
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/docs/modules/types.rst
@@ -0,0 +1,5 @@
+:mod:`cbor2.types`
+==================
+
+.. automodule:: cbor2.types
+    :members:
diff --git a/mercurial/thirdparty/cbor/docs/modules/encoder.rst b/mercurial/thirdparty/cbor/docs/modules/encoder.rst
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/docs/modules/encoder.rst
@@ -0,0 +1,5 @@
+:mod:`cbor2.encoder`
+====================
+
+.. automodule:: cbor2.encoder
+    :members:
diff --git a/mercurial/thirdparty/cbor/docs/modules/decoder.rst b/mercurial/thirdparty/cbor/docs/modules/decoder.rst
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/docs/modules/decoder.rst
@@ -0,0 +1,5 @@
+:mod:`cbor2.decoder`
+====================
+
+.. automodule:: cbor2.decoder
+    :members:
diff --git a/mercurial/thirdparty/cbor/docs/index.rst b/mercurial/thirdparty/cbor/docs/index.rst
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/docs/index.rst
@@ -0,0 +1,15 @@
+.. include:: ../README.rst
+   :start-line: 7
+   :end-before: Project links
+
+Table of contents
+-----------------
+
+.. toctree::
+   :maxdepth: 2
+
+   usage
+   customizing
+   versionhistory
+
+* :ref:`API reference <modindex>`
diff --git a/mercurial/thirdparty/cbor/docs/customizing.rst b/mercurial/thirdparty/cbor/docs/customizing.rst
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/docs/customizing.rst
@@ -0,0 +1,132 @@
+Customizing encoding and decoding
+=================================
+
+Both the encoder and decoder can be customized to support a wider range of types.
+
+On the encoder side, this is accomplished by passing a callback as the ``default`` constructor
+argument. This callback will receive an object that the encoder could not serialize on its own.
+The callback should then return a value that the encoder can serialize on its own, although the
+return value is allowed to contain objects that also require the encoder to use the callback, as
+long as it won't result in an infinite loop.
+
+On the decoder side, you have two options: ``tag_hook`` and ``object_hook``. The former is called
+by the decoder to process any semantic tags that have no predefined decoders. The latter is called
+for any newly decoded ``dict`` objects, and is mostly useful for implementing a JSON compatible
+custom type serialization scheme. Unless your requirements restrict you to JSON compatible types
+only, it is recommended to use ``tag_hook`` for this purpose.
+
+JSON compatibility
+------------------
+
+In certain applications, it may be desirable to limit the supported types to the same ones
+serializable as JSON: (unicode) string, integer, float, boolean, null, array and object (dict).
+This can be done by passing the ``json_compatible`` option to the encoder. When incompatible types
+are encountered, a :class:`~cbor2.encoder.CBOREncodeError` is then raised.
+
+For the decoder, there is no support for detecting incoming incompatible types yet.
+
+Using the CBOR tags for custom types
+------------------------------------
+
+The most common way to use ``default`` is to call :meth:`~cbor2.encoder.CBOREncoder.encode`
+to add a custom tag in the data stream, with the payload as the value::
+
+    class Point(object):
+        def __init__(self, x, y):
+            self.x = x
+            self.y = y
+
+    def default_encoder(encoder, value):
+        # Tag number 4000 was chosen arbitrarily
+        encoder.encode(CBORTag(4000, [value.x, value.y]))
+
+The corresponding ``tag_hook`` would be::
+
+    def tag_hook(decoder, tag, shareable_index=None):
+        if tag.tag != 4000:
+            return tag
+
+        # tag.value is now the [x, y] list we serialized before
+        return Point(*tag.value)
+
+Using dicts to carry custom types
+---------------------------------
+
+The same could be done with ``object_hook``, except less efficiently::
+
+    def default_encoder(encoder, value):
+        encoder.encode(dict(typename='Point', x=value.x, y=value.y))
+
+    def object_hook(decoder, value):
+        if value.get('typename') != 'Point':
+            return value
+
+        return Point(value['x'], value['y'])
+
+You should make sure that whatever way you decide to use for telling apart your "specially marked"
+dicts from arbitrary data dicts won't mistake on for the other.
+
+Value sharing with custom types
+-------------------------------
+
+In order to properly encode and decode cyclic references with custom types, some special care has
+to be taken. Suppose you have a custom type as below, where every child object contains a reference
+to its parent and the parent contains a list of children::
+
+    from cbor2 import dumps, loads, shareable_encoder, CBORTag
+
+
+    class MyType(object):
+        def __init__(self, parent=None):
+            self.parent = parent
+            self.children = []
+            if parent:
+                self.parent.children.append(self)
+
+This would not normally be serializable, as it would lead to an endless loop (in the worst case)
+and raise some exception (in the best case). Now, enter CBOR's extension tags 28 and 29. These tags
+make it possible to add special markers into the data stream which can be later referenced and
+substituted with the object marked earlier.
+
+To do this, in ``default`` hooks used with the encoder you will need to use the
+:meth:`~cbor2.encoder.shareable_encoder` decorator on your ``default`` hook function. It will
+automatically automatically add the object to the shared values registry on the encoder and prevent
+it from being serialized twice (instead writing a reference to the data stream)::
+
+    @shareable_encoder
+    def default_encoder(encoder, value):
+        # The state has to be serialized separately so that the decoder would have a chance to
+        # create an empty instance before the shared value references are decoded
+        serialized_state = encoder.encode_to_bytes(value.__dict__)
+        encoder.encode(CBORTag(3000, serialized_state))
+
+On the decoder side, you will need to initialize an empty instance for shared value lookup before
+the object's state (which may contain references to it) is decoded.
+This is done with the :meth:`~cbor2.encoder.CBORDecoder.set_shareable` method::
+
+    def tag_hook(decoder, tag, shareable_index=None):
+        # Return all other tags as-is
+        if tag.tag != 3000:
+            return tag
+
+        # Create a raw instance before initializing its state to make it possible for cyclic
+        # references to work
+        instance = MyType.__new__(MyType)
+        decoder.set_shareable(shareable_index, instance)
+
+        # Separately decode the state of the new object and then apply it
+        state = decoder.decode_from_bytes(tag.value)
+        instance.__dict__.update(state)
+        return instance
+
+You could then verify that the cyclic references have been restored after deserialization::
+
+    parent = MyType()
+    child1 = MyType(parent)
+    child2 = MyType(parent)
+    serialized = dumps(parent, default=default_encoder, value_sharing=True)
+
+    new_parent = loads(serialized, tag_hook=tag_hook)
+    assert new_parent.children[0].parent is new_parent
+    assert new_parent.children[1].parent is new_parent
+
diff --git a/mercurial/thirdparty/cbor/docs/conf.py b/mercurial/thirdparty/cbor/docs/conf.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/docs/conf.py
@@ -0,0 +1,33 @@
+# coding: utf-8
+#!/usr/bin/env python
+import pkg_resources
+
+
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.intersphinx'
+]
+
+templates_path = ['_templates']
+source_suffix = '.rst'
+master_doc = 'index'
+project = 'cbor2'
+author = u'Alex Grönholm'
+copyright = u'2016, ' + author
+
+v = pkg_resources.get_distribution(project).parsed_version
+version = v.base_version
+release = v.public
+
+language = None
+
+exclude_patterns = ['_build']
+pygments_style = 'sphinx'
+highlight_language = 'python'
+todo_include_todos = False
+
+html_theme = 'sphinx_rtd_theme'
+html_static_path = ['_static']
+htmlhelp_basename = project.replace('-', '') + 'doc'
+
+intersphinx_mapping = {'python': ('http://docs.python.org/', None)}
diff --git a/mercurial/thirdparty/cbor/cbor2/types.py b/mercurial/thirdparty/cbor/cbor2/types.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/cbor2/types.py
@@ -0,0 +1,55 @@
+class CBORTag(object):
+    """
+    Represents a CBOR semantic tag.
+
+    :param int tag: tag number
+    :param value: encapsulated value (any object)
+    """
+
+    __slots__ = 'tag', 'value'
+
+    def __init__(self, tag, value):
+        self.tag = tag
+        self.value = value
+
+    def __eq__(self, other):
+        if isinstance(other, CBORTag):
+            return self.tag == other.tag and self.value == other.value
+        return NotImplemented
+
+    def __repr__(self):
+        return 'CBORTag({self.tag}, {self.value!r})'.format(self=self)
+
+
+class CBORSimpleValue(object):
+    """
+    Represents a CBOR "simple value".
+
+    :param int value: the value (0-255)
+    """
+
+    __slots__ = 'value'
+
+    def __init__(self, value):
+        if value < 0 or value > 255:
+            raise TypeError('simple value too big')
+        self.value = value
+
+    def __eq__(self, other):
+        if isinstance(other, CBORSimpleValue):
+            return self.value == other.value
+        elif isinstance(other, int):
+            return self.value == other
+        return NotImplemented
+
+    def __repr__(self):
+        return 'CBORSimpleValue({self.value})'.format(self=self)
+
+
+class UndefinedType(object):
+    __slots__ = ()
+
+
+#: Represents the "undefined" value.
+undefined = UndefinedType()
+break_marker = object()
diff --git a/mercurial/thirdparty/cbor/cbor2/encoder.py b/mercurial/thirdparty/cbor/cbor2/encoder.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/cbor2/encoder.py
@@ -0,0 +1,425 @@
+import re
+import struct
+from collections import OrderedDict, defaultdict
+from contextlib import contextmanager
+from functools import wraps
+from datetime import datetime, date, time
+from io import BytesIO
+
+from cbor2.compat import iteritems, timezone, long, unicode, as_unicode, bytes_from_list
+from cbor2.compat import pack_float16, unpack_float16
+from cbor2.types import CBORTag, undefined, CBORSimpleValue
+
+
+class CBOREncodeError(Exception):
+    """Raised when an error occurs while serializing an object into a CBOR datastream."""
+
+
+def shareable_encoder(func):
+    """
+    Wrap the given encoder function to gracefully handle cyclic data structures.
+
+    If value sharing is enabled, this marks the given value shared in the datastream on the
+    first call. If the value has already been passed to this method, a reference marker is
+    instead written to the data stream and the wrapped function is not called.
+
+    If value sharing is disabled, only infinite recursion protection is done.
+
+    """
+    @wraps(func)
+    def wrapper(encoder, value, *args, **kwargs):
+        value_id = id(value)
+        container, container_index = encoder._shared_containers.get(value_id, (None, None))
+        if encoder.value_sharing:
+            if container is value:
+                # Generate a reference to the previous index instead of encoding this again
+                encoder.write(encode_length(0xd8, 0x1d))
+                encode_int(encoder, container_index)
+            else:
+                # Mark the container as shareable
+                encoder._shared_containers[value_id] = (value, len(encoder._shared_containers))
+                encoder.write(encode_length(0xd8, 0x1c))
+                func(encoder, value, *args, **kwargs)
+        else:
+            if container is value:
+                raise CBOREncodeError('cyclic data structure detected but value sharing is '
+                                      'disabled')
+            else:
+                encoder._shared_containers[value_id] = (value, None)
+                func(encoder, value, *args, **kwargs)
+                del encoder._shared_containers[value_id]
+
+    return wrapper
+
+
+def encode_length(major_tag, length):
+    if length < 24:
+        return struct.pack('>B', major_tag | length)
+    elif length < 256:
+        return struct.pack('>BB', major_tag | 24, length)
+    elif length < 65536:
+        return struct.pack('>BH', major_tag | 25, length)
+    elif length < 4294967296:
+        return struct.pack('>BL', major_tag | 26, length)
+    else:
+        return struct.pack('>BQ', major_tag | 27, length)
+
+
+def encode_int(encoder, value):
+    # Big integers (2 ** 64 and over)
+    if value >= 18446744073709551616 or value < -18446744073709551616:
+        if value >= 0:
+            major_type = 0x02
+        else:
+            major_type = 0x03
+            value = -value - 1
+
+        values = []
+        while value > 0:
+            value, remainder = divmod(value, 256)
+            values.insert(0, remainder)
+
+        payload = bytes_from_list(values)
+        encode_semantic(encoder, CBORTag(major_type, payload))
+    elif value >= 0:
+        encoder.write(encode_length(0, value))
+    else:
+        encoder.write(encode_length(0x20, abs(value) - 1))
+
+
+def encode_bytestring(encoder, value):
+    encoder.write(encode_length(0x40, len(value)) + value)
+
+
+def encode_bytearray(encoder, value):
+    encode_bytestring(encoder, bytes(value))
+
+
+def encode_string(encoder, value):
+    encoded = value.encode('utf-8')
+    encoder.write(encode_length(0x60, len(encoded)) + encoded)
+
+
+ at shareable_encoder
+def encode_array(encoder, value):
+    encoder.write(encode_length(0x80, len(value)))
+    for item in value:
+        encoder.encode(item)
+
+
+ at shareable_encoder
+def encode_map(encoder, value):
+    encoder.write(encode_length(0xa0, len(value)))
+    for key, val in iteritems(value):
+        encoder.encode(key)
+        encoder.encode(val)
+
+
+def encode_sortable_key(encoder, value):
+    """Takes a key and calculates the length of its optimal byte representation"""
+    encoded = encoder.encode_to_bytes(value)
+    return len(encoded), encoded
+
+
+ at shareable_encoder
+def encode_canonical_map(encoder, value):
+    """Reorder keys according to Canonical CBOR specification"""
+    keyed_keys = ((encode_sortable_key(encoder, key), key) for key in value.keys())
+    encoder.write(encode_length(0xa0, len(value)))
+    for sortkey, realkey in sorted(keyed_keys):
+        encoder.write(sortkey[1])
+        encoder.encode(value[realkey])
+
+
+def encode_semantic(encoder, value):
+    encoder.write(encode_length(0xc0, value.tag))
+    encoder.encode(value.value)
+
+
+#
+# Semantic decoders (major tag 6)
+#
+
+def encode_datetime(encoder, value):
+    # Semantic tag 0
+    if not value.tzinfo:
+        if encoder.timezone:
+            value = value.replace(tzinfo=encoder.timezone)
+        else:
+            raise CBOREncodeError(
+                'naive datetime encountered and no default timezone has been set')
+
+    if encoder.datetime_as_timestamp:
+        from calendar import timegm
+        timestamp = timegm(value.utctimetuple()) + value.microsecond // 1000000
+        encode_semantic(encoder, CBORTag(1, timestamp))
+    else:
+        datestring = as_unicode(value.isoformat().replace('+00:00', 'Z'))
+        encode_semantic(encoder, CBORTag(0, datestring))
+
+
+def encode_date(encoder, value):
+    value = datetime.combine(value, time()).replace(tzinfo=timezone.utc)
+    encode_datetime(encoder, value)
+
+
+def encode_decimal(encoder, value):
+    # Semantic tag 4
+    if value.is_nan():
+        encoder.write(b'\xf9\x7e\x00')
+    elif value.is_infinite():
+        encoder.write(b'\xf9\x7c\x00' if value > 0 else b'\xf9\xfc\x00')
+    else:
+        dt = value.as_tuple()
+        mantissa = sum(d * 10 ** i for i, d in enumerate(reversed(dt.digits)))
+        with encoder.disable_value_sharing():
+            encode_semantic(encoder, CBORTag(4, [dt.exponent, mantissa]))
+
+
+def encode_rational(encoder, value):
+    # Semantic tag 30
+    with encoder.disable_value_sharing():
+        encode_semantic(encoder, CBORTag(30, [value.numerator, value.denominator]))
+
+
+def encode_regexp(encoder, value):
+    # Semantic tag 35
+    encode_semantic(encoder, CBORTag(35, as_unicode(value.pattern)))
+
+
+def encode_mime(encoder, value):
+    # Semantic tag 36
+    encode_semantic(encoder, CBORTag(36, as_unicode(value.as_string())))
+
+
+def encode_uuid(encoder, value):
+    # Semantic tag 37
+    encode_semantic(encoder, CBORTag(37, value.bytes))
+
+
+def encode_set(encoder, value):
+    # Semantic tag 258
+    encode_semantic(encoder, CBORTag(258, tuple(value)))
+
+
+def encode_canonical_set(encoder, value):
+    # Semantic tag 258
+    values = sorted([(encode_sortable_key(encoder, key), key) for key in value])
+    encode_semantic(encoder, CBORTag(258, [key[1] for key in values]))
+
+
+#
+# Special encoders (major tag 7)
+#
+
+def encode_simple_value(encoder, value):
+    if value.value < 20:
+        encoder.write(struct.pack('>B', 0xe0 | value.value))
+    else:
+        encoder.write(struct.pack('>BB', 0xf8, value.value))
+
+
+def encode_float(encoder, value):
+    # Handle special values efficiently
+    import math
+    if math.isnan(value):
+        encoder.write(b'\xf9\x7e\x00')
+    elif math.isinf(value):
+        encoder.write(b'\xf9\x7c\x00' if value > 0 else b'\xf9\xfc\x00')
+    else:
+        encoder.write(struct.pack('>Bd', 0xfb, value))
+
+
+def encode_minimal_float(encoder, value):
+    # Handle special values efficiently
+    import math
+    if math.isnan(value):
+        encoder.write(b'\xf9\x7e\x00')
+    elif math.isinf(value):
+        encoder.write(b'\xf9\x7c\x00' if value > 0 else b'\xf9\xfc\x00')
+    else:
+        encoded = struct.pack('>Bf', 0xfa, value)
+        if struct.unpack('>Bf', encoded)[1] != value:
+            encoded = struct.pack('>Bd', 0xfb, value)
+            encoder.write(encoded)
+        else:
+            f16 = pack_float16(value)
+            if f16 and unpack_float16(f16[1:]) == value:
+                encoder.write(f16)
+            else:
+                encoder.write(encoded)
+
+
+def encode_boolean(encoder, value):
+    encoder.write(b'\xf5' if value else b'\xf4')
+
+
+def encode_none(encoder, value):
+    encoder.write(b'\xf6')
+
+
+def encode_undefined(encoder, value):
+    encoder.write(b'\xf7')
+
+
+default_encoders = OrderedDict([
+    (bytes, encode_bytestring),
+    (bytearray, encode_bytearray),
+    (unicode, encode_string),
+    (int, encode_int),
+    (long, encode_int),
+    (float, encode_float),
+    (('decimal', 'Decimal'), encode_decimal),
+    (bool, encode_boolean),
+    (type(None), encode_none),
+    (tuple, encode_array),
+    (list, encode_array),
+    (dict, encode_map),
+    (defaultdict, encode_map),
+    (OrderedDict, encode_map),
+    (type(undefined), encode_undefined),
+    (datetime, encode_datetime),
+    (date, encode_date),
+    (type(re.compile('')), encode_regexp),
+    (('fractions', 'Fraction'), encode_rational),
+    (('email.message', 'Message'), encode_mime),
+    (('uuid', 'UUID'), encode_uuid),
+    (CBORSimpleValue, encode_simple_value),
+    (CBORTag, encode_semantic),
+    (set, encode_set),
+    (frozenset, encode_set)
+])
+
+canonical_encoders = OrderedDict([
+    (float, encode_minimal_float),
+    (dict, encode_canonical_map),
+    (defaultdict, encode_canonical_map),
+    (OrderedDict, encode_canonical_map),
+    (set, encode_canonical_set),
+    (frozenset, encode_canonical_set)
+])
+
+
+class CBOREncoder(object):
+    """
+    Serializes objects to a byte stream using Concise Binary Object Representation.
+
+    :param datetime_as_timestamp: set to ``True`` to serialize datetimes as UNIX timestamps
+        (this makes datetimes more concise on the wire but loses the time zone information)
+    :param datetime.tzinfo timezone: the default timezone to use for serializing naive datetimes
+    :param value_sharing: if ``True``, allows more efficient serializing of repeated values and,
+        more importantly, cyclic data structures, at the cost of extra line overhead
+    :param default: a callable that is called by the encoder with three arguments
+        (encoder, value, file object) when no suitable encoder has been found, and should use the
+        methods on the encoder to encode any objects it wants to add to the data stream
+    :param canonical: Forces mapping types to be output in a stable order to guarantee that the
+        output will always produce the same hash given the same input.
+    """
+
+    __slots__ = ('fp', 'datetime_as_timestamp', 'timezone', 'default', 'value_sharing',
+                 'json_compatible', '_shared_containers', '_encoders')
+
+    def __init__(self, fp, datetime_as_timestamp=False, timezone=None, value_sharing=False,
+                 default=None, canonical=False):
+        self.fp = fp
+        self.datetime_as_timestamp = datetime_as_timestamp
+        self.timezone = timezone
+        self.value_sharing = value_sharing
+        self.default = default
+        self._shared_containers = {}  # indexes used for value sharing
+        self._encoders = default_encoders.copy()
+        if canonical:
+            self._encoders.update(canonical_encoders)
+
+    def _find_encoder(self, obj_type):
+        from sys import modules
+
+        for type_, enc in list(iteritems(self._encoders)):
+            if type(type_) is tuple:
+                modname, typename = type_
+                imported_type = getattr(modules.get(modname), typename, None)
+                if imported_type is not None:
+                    del self._encoders[type_]
+                    self._encoders[imported_type] = enc
+                    type_ = imported_type
+                else:  # pragma: nocover
+                    continue
+
+            if issubclass(obj_type, type_):
+                self._encoders[obj_type] = enc
+                return enc
+
+        return None
+
+    @contextmanager
+    def disable_value_sharing(self):
+        """Disable value sharing in the encoder for the duration of the context block."""
+        old_value_sharing = self.value_sharing
+        self.value_sharing = False
+        yield
+        self.value_sharing = old_value_sharing
+
+    def write(self, data):
+        """
+        Write bytes to the data stream.
+
+        :param data: the bytes to write
+
+        """
+        self.fp.write(data)
+
+    def encode(self, obj):
+        """
+        Encode the given object using CBOR.
+
+        :param obj: the object to encode
+
+        """
+        obj_type = obj.__class__
+        encoder = self._encoders.get(obj_type) or self._find_encoder(obj_type) or self.default
+        if not encoder:
+            raise CBOREncodeError('cannot serialize type %s' % obj_type.__name__)
+
+        encoder(self, obj)
+
+    def encode_to_bytes(self, obj):
+        """
+        Encode the given object to a byte buffer and return its value as bytes.
+
+        This method was intended to be used from the ``default`` hook when an object needs to be
+        encoded separately from the rest but while still taking advantage of the shared value
+        registry.
+
+        """
+        old_fp = self.fp
+        self.fp = fp = BytesIO()
+        self.encode(obj)
+        self.fp = old_fp
+        return fp.getvalue()
+
+
+def dumps(obj, **kwargs):
+    """
+    Serialize an object to a bytestring.
+
+    :param obj: the object to serialize
+    :param kwargs: keyword arguments passed to :class:`~.CBOREncoder`
+    :return: the serialized output
+    :rtype: bytes
+
+    """
+    fp = BytesIO()
+    dump(obj, fp, **kwargs)
+    return fp.getvalue()
+
+
+def dump(obj, fp, **kwargs):
+    """
+    Serialize an object to a file.
+
+    :param obj: the object to serialize
+    :param fp: a file-like object
+    :param kwargs: keyword arguments passed to :class:`~.CBOREncoder`
+
+    """
+    CBOREncoder(fp, **kwargs).encode(obj)
diff --git a/mercurial/thirdparty/cbor/cbor2/decoder.py b/mercurial/thirdparty/cbor/cbor2/decoder.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/cbor2/decoder.py
@@ -0,0 +1,407 @@
+import re
+import struct
+from datetime import datetime, timedelta
+from io import BytesIO
+
+from cbor2.compat import timezone, xrange, byte_as_integer, unpack_float16
+from cbor2.types import CBORTag, undefined, break_marker, CBORSimpleValue
+
+timestamp_re = re.compile(r'^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)'
+                          r'(?:\.(\d+))?(?:Z|([+-]\d\d):(\d\d))$')
+
+
+class CBORDecodeError(Exception):
+    """Raised when an error occurs deserializing a CBOR datastream."""
+
+
+def decode_uint(decoder, subtype, shareable_index=None, allow_indefinite=False):
+    # Major tag 0
+    if subtype < 24:
+        return subtype
+    elif subtype == 24:
+        return struct.unpack('>B', decoder.read(1))[0]
+    elif subtype == 25:
+        return struct.unpack('>H', decoder.read(2))[0]
+    elif subtype == 26:
+        return struct.unpack('>L', decoder.read(4))[0]
+    elif subtype == 27:
+        return struct.unpack('>Q', decoder.read(8))[0]
+    elif subtype == 31 and allow_indefinite:
+        return None
+    else:
+        raise CBORDecodeError('unknown unsigned integer subtype 0x%x' % subtype)
+
+
+def decode_negint(decoder, subtype, shareable_index=None):
+    # Major tag 1
+    uint = decode_uint(decoder, subtype)
+    return -uint - 1
+
+
+def decode_bytestring(decoder, subtype, shareable_index=None):
+    # Major tag 2
+    length = decode_uint(decoder, subtype, allow_indefinite=True)
+    if length is None:
+        # Indefinite length
+        buf = bytearray()
+        while True:
+            initial_byte = byte_as_integer(decoder.read(1))
+            if initial_byte == 255:
+                return buf
+            else:
+                length = decode_uint(decoder, initial_byte & 31)
+                value = decoder.read(length)
+                buf.extend(value)
+    else:
+        return decoder.read(length)
+
+
+def decode_string(decoder, subtype, shareable_index=None):
+    # Major tag 3
+    return decode_bytestring(decoder, subtype).decode('utf-8')
+
+
+def decode_array(decoder, subtype, shareable_index=None):
+    # Major tag 4
+    items = []
+    decoder.set_shareable(shareable_index, items)
+    length = decode_uint(decoder, subtype, allow_indefinite=True)
+    if length is None:
+        # Indefinite length
+        while True:
+            value = decoder.decode()
+            if value is break_marker:
+                break
+            else:
+                items.append(value)
+    else:
+        for _ in xrange(length):
+            item = decoder.decode()
+            items.append(item)
+
+    return items
+
+
+def decode_map(decoder, subtype, shareable_index=None):
+    # Major tag 5
+    dictionary = {}
+    decoder.set_shareable(shareable_index, dictionary)
+    length = decode_uint(decoder, subtype, allow_indefinite=True)
+    if length is None:
+        # Indefinite length
+        while True:
+            key = decoder.decode()
+            if key is break_marker:
+                break
+            else:
+                value = decoder.decode()
+                dictionary[key] = value
+    else:
+        for _ in xrange(length):
+            key = decoder.decode()
+            value = decoder.decode()
+            dictionary[key] = value
+
+    if decoder.object_hook:
+        return decoder.object_hook(decoder, dictionary)
+    else:
+        return dictionary
+
+
+def decode_semantic(decoder, subtype, shareable_index=None):
+    # Major tag 6
+    tagnum = decode_uint(decoder, subtype)
+
+    # Special handling for the "shareable" tag
+    if tagnum == 28:
+        shareable_index = decoder._allocate_shareable()
+        return decoder.decode(shareable_index)
+
+    value = decoder.decode()
+    semantic_decoder = semantic_decoders.get(tagnum)
+    if semantic_decoder:
+        return semantic_decoder(decoder, value, shareable_index)
+
+    tag = CBORTag(tagnum, value)
+    if decoder.tag_hook:
+        return decoder.tag_hook(decoder, tag, shareable_index)
+    else:
+        return tag
+
+
+def decode_special(decoder, subtype, shareable_index=None):
+    # Simple value
+    if subtype < 20:
+        return CBORSimpleValue(subtype)
+
+    # Major tag 7
+    return special_decoders[subtype](decoder)
+
+
+#
+# Semantic decoders (major tag 6)
+#
+
+def decode_datetime_string(decoder, value, shareable_index=None):
+    # Semantic tag 0
+    match = timestamp_re.match(value)
+    if match:
+        year, month, day, hour, minute, second, micro, offset_h, offset_m = match.groups()
+        if offset_h:
+            tz = timezone(timedelta(hours=int(offset_h), minutes=int(offset_m)))
+        else:
+            tz = timezone.utc
+
+        return datetime(int(year), int(month), int(day), int(hour), int(minute), int(second),
+                        int(micro or 0), tz)
+    else:
+        raise CBORDecodeError('invalid datetime string: {}'.format(value))
+
+
+def decode_epoch_datetime(decoder, value, shareable_index=None):
+    # Semantic tag 1
+    return datetime.fromtimestamp(value, timezone.utc)
+
+
+def decode_positive_bignum(decoder, value, shareable_index=None):
+    # Semantic tag 2
+    from binascii import hexlify
+    return int(hexlify(value), 16)
+
+
+def decode_negative_bignum(decoder, value, shareable_index=None):
+    # Semantic tag 3
+    return -decode_positive_bignum(decoder, value) - 1
+
+
+def decode_fraction(decoder, value, shareable_index=None):
+    # Semantic tag 4
+    from decimal import Decimal
+    exp = Decimal(value[0])
+    mantissa = Decimal(value[1])
+    return mantissa * (10 ** exp)
+
+
+def decode_bigfloat(decoder, value, shareable_index=None):
+    # Semantic tag 5
+    from decimal import Decimal
+    exp = Decimal(value[0])
+    mantissa = Decimal(value[1])
+    return mantissa * (2 ** exp)
+
+
+def decode_sharedref(decoder, value, shareable_index=None):
+    # Semantic tag 29
+    try:
+        shared = decoder._shareables[value]
+    except IndexError:
+        raise CBORDecodeError('shared reference %d not found' % value)
+
+    if shared is None:
+        raise CBORDecodeError('shared value %d has not been initialized' % value)
+    else:
+        return shared
+
+
+def decode_rational(decoder, value, shareable_index=None):
+    # Semantic tag 30
+    from fractions import Fraction
+    return Fraction(*value)
+
+
+def decode_regexp(decoder, value, shareable_index=None):
+    # Semantic tag 35
+    return re.compile(value)
+
+
+def decode_mime(decoder, value, shareable_index=None):
+    # Semantic tag 36
+    from email.parser import Parser
+    return Parser().parsestr(value)
+
+
+def decode_uuid(decoder, value, shareable_index=None):
+    # Semantic tag 37
+    from uuid import UUID
+    return UUID(bytes=value)
+
+
+def decode_set(decoder, value, shareable_index=None):
+    # Semantic tag 258
+    return set(value)
+
+
+#
+# Special decoders (major tag 7)
+#
+
+def decode_simple_value(decoder, shareable_index=None):
+    return CBORSimpleValue(struct.unpack('>B', decoder.read(1))[0])
+
+
+def decode_float16(decoder, shareable_index=None):
+    payload = decoder.read(2)
+    return unpack_float16(payload)
+
+
+def decode_float32(decoder, shareable_index=None):
+    return struct.unpack('>f', decoder.read(4))[0]
+
+
+def decode_float64(decoder, shareable_index=None):
+    return struct.unpack('>d', decoder.read(8))[0]
+
+
+major_decoders = {
+    0: decode_uint,
+    1: decode_negint,
+    2: decode_bytestring,
+    3: decode_string,
+    4: decode_array,
+    5: decode_map,
+    6: decode_semantic,
+    7: decode_special
+}
+
+special_decoders = {
+    20: lambda self: False,
+    21: lambda self: True,
+    22: lambda self: None,
+    23: lambda self: undefined,
+    24: decode_simple_value,
+    25: decode_float16,
+    26: decode_float32,
+    27: decode_float64,
+    31: lambda self: break_marker
+}
+
+semantic_decoders = {
+    0: decode_datetime_string,
+    1: decode_epoch_datetime,
+    2: decode_positive_bignum,
+    3: decode_negative_bignum,
+    4: decode_fraction,
+    5: decode_bigfloat,
+    29: decode_sharedref,
+    30: decode_rational,
+    35: decode_regexp,
+    36: decode_mime,
+    37: decode_uuid,
+    258: decode_set
+}
+
+
+class CBORDecoder(object):
+    """
+    Deserializes a CBOR encoded byte stream.
+
+    :param tag_hook: Callable that takes 3 arguments: the decoder instance, the
+        :class:`~cbor2.types.CBORTag` and the shareable index for the resulting object, if any.
+        This callback is called for any tags for which there is no built-in decoder.
+        The return value is substituted for the CBORTag object in the deserialized output.
+    :param object_hook: Callable that takes 2 arguments: the decoder instance and the dictionary.
+        This callback is called for each deserialized :class:`dict` object.
+        The return value is substituted for the dict in the deserialized output.
+    """
+
+    __slots__ = ('fp', 'tag_hook', 'object_hook', '_shareables')
+
+    def __init__(self, fp, tag_hook=None, object_hook=None):
+        self.fp = fp
+        self.tag_hook = tag_hook
+        self.object_hook = object_hook
+        self._shareables = []
+
+    def _allocate_shareable(self):
+        self._shareables.append(None)
+        return len(self._shareables) - 1
+
+    def set_shareable(self, index, value):
+        """
+        Set the shareable value for the last encountered shared value marker, if any.
+
+        If the given index is ``None``, nothing is done.
+
+        :param index: the value of the ``shared_index`` argument to the decoder
+        :param value: the shared value
+
+        """
+        if index is not None:
+            self._shareables[index] = value
+
+    def read(self, amount):
+        """
+        Read bytes from the data stream.
+
+        :param int amount: the number of bytes to read
+
+        """
+        data = self.fp.read(amount)
+        if len(data) < amount:
+            raise CBORDecodeError('premature end of stream (expected to read {} bytes, got {} '
+                                  'instead)'.format(amount, len(data)))
+
+        return data
+
+    def decode(self, shareable_index=None):
+        """
+        Decode the next value from the stream.
+
+        :raises CBORDecodeError: if there is any problem decoding the stream
+
+        """
+        try:
+            initial_byte = byte_as_integer(self.fp.read(1))
+            major_type = initial_byte >> 5
+            subtype = initial_byte & 31
+        except Exception as e:
+            raise CBORDecodeError('error reading major type at index {}: {}'
+                                  .format(self.fp.tell(), e))
+
+        decoder = major_decoders[major_type]
+        try:
+            return decoder(self, subtype, shareable_index)
+        except CBORDecodeError:
+            raise
+        except Exception as e:
+            raise CBORDecodeError('error decoding value at index {}: {}'.format(self.fp.tell(), e))
+
+    def decode_from_bytes(self, buf):
+        """
+        Wrap the given bytestring as a file and call :meth:`decode` with it as the argument.
+
+        This method was intended to be used from the ``tag_hook`` hook when an object needs to be
+        decoded separately from the rest but while still taking advantage of the shared value
+        registry.
+
+        """
+        old_fp = self.fp
+        self.fp = BytesIO(buf)
+        retval = self.decode()
+        self.fp = old_fp
+        return retval
+
+
+def loads(payload, **kwargs):
+    """
+    Deserialize an object from a bytestring.
+
+    :param bytes payload: the bytestring to serialize
+    :param kwargs: keyword arguments passed to :class:`~.CBORDecoder`
+    :return: the deserialized object
+
+    """
+    fp = BytesIO(payload)
+    return CBORDecoder(fp, **kwargs).decode()
+
+
+def load(fp, **kwargs):
+    """
+    Deserialize an object from an open file.
+
+    :param fp: the input file (any file-like object)
+    :param kwargs: keyword arguments passed to :class:`~.CBORDecoder`
+    :return: the deserialized object
+
+    """
+    return CBORDecoder(fp, **kwargs).decode()
diff --git a/mercurial/thirdparty/cbor/cbor2/compat.py b/mercurial/thirdparty/cbor/cbor2/compat.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/cbor2/compat.py
@@ -0,0 +1,101 @@
+from math import ldexp
+import struct
+import sys
+
+
+if sys.version_info.major < 3:
+    from datetime import tzinfo, timedelta
+
+    class timezone(tzinfo):
+        def __init__(self, offset):
+            self.offset = offset
+
+        def utcoffset(self, dt):
+            return self.offset
+
+        def dst(self, dt):
+            return timedelta(0)
+
+        def tzname(self, dt):
+            return 'UTC+00:00'
+
+    def as_unicode(string):
+        return string.decode('utf-8')
+
+    def iteritems(self):
+        return self.iteritems()
+
+    def bytes_from_list(values):
+        return bytes(bytearray(values))
+
+    byte_as_integer = ord
+    timezone.utc = timezone(timedelta(0))
+    xrange = xrange  # noqa: F821
+    long = long  # noqa: F821
+    unicode = unicode  # noqa: F821
+else:
+    from datetime import timezone
+
+    def byte_as_integer(bytestr):
+        return bytestr[0]
+
+    def as_unicode(string):
+        return string
+
+    def iteritems(self):
+        return self.items()
+
+    xrange = range
+    long = int
+    unicode = str
+    bytes_from_list = bytes
+
+
+if sys.version_info.major >= 3 and sys.version_info.minor >= 6:
+    # Python 3.6 added 16 bit floating point to struct
+
+    def pack_float16(value):
+        try:
+            return struct.pack('>Be', 0xf9, value)
+        except OverflowError:
+            return False
+
+    def unpack_float16(payload):
+        return struct.unpack('>e', payload)[0]
+else:
+    def pack_float16(value):
+        # Based on node-cbor by hildjj
+        # which was based in turn on Carsten Borman's cn-cbor
+        u32 = struct.pack('>f', value)
+        u = struct.unpack('>I', u32)[0]
+
+        if u & 0x1FFF != 0:
+            return False
+
+        s16 = (u >> 16) & 0x8000
+        exponent = (u >> 23) & 0xff
+        mantissa = u & 0x7fffff
+
+        if 113 <= exponent <= 142:
+            s16 += ((exponent - 112) << 10) + (mantissa >> 13)
+        elif 103 <= exponent < 113:
+            if mantissa & ((1 << (126 - exponent)) - 1):
+                return False
+
+            s16 += ((mantissa + 0x800000) >> (126 - exponent))
+        else:
+            return False
+
+        return struct.pack('>BH', 0xf9, s16)
+
+    def unpack_float16(payload):
+        # Code adapted from RFC 7049, appendix D
+        def decode_single(single):
+            return struct.unpack("!f", struct.pack("!I", single))[0]
+
+        payload = struct.unpack('>H', payload)[0]
+        value = (payload & 0x7fff) << 13 | (payload & 0x8000) << 16
+        if payload & 0x7c00 != 0x7c00:
+            return ldexp(decode_single(value), 112)
+
+        return decode_single(value | 0x7f800000)
diff --git a/mercurial/thirdparty/cbor/cbor2/__init__.py b/mercurial/thirdparty/cbor/cbor2/__init__.py
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/cbor2/__init__.py
@@ -0,0 +1,3 @@
+from cbor2.decoder import load, loads, CBORDecoder, CBORDecodeError  # noqa
+from cbor2.encoder import dump, dumps, CBOREncoder, CBOREncodeError, shareable_encoder  # noqa
+from cbor2.types import CBORTag, CBORSimpleValue, undefined  # noqa
diff --git a/mercurial/thirdparty/cbor/README.rst b/mercurial/thirdparty/cbor/README.rst
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/README.rst
@@ -0,0 +1,24 @@
+.. image:: https://travis-ci.org/agronholm/cbor2.svg?branch=master
+  :target: https://travis-ci.org/agronholm/cbor2
+  :alt: Build Status
+.. image:: https://coveralls.io/repos/github/agronholm/cbor2/badge.svg?branch=master
+  :target: https://coveralls.io/github/agronholm/cbor2?branch=master
+  :alt: Code Coverage
+
+This library provides encoding and decoding for the Concise Binary Object Representation (CBOR)
+(`RFC 7049`_) serialization format.
+
+There exists another Python CBOR implementation (cbor) which is faster on CPython due to its C
+extensions. On PyPy, cbor2 and cbor are almost identical in performance. The other implementation
+also lacks documentation and a comprehensive test suite, does not support most standard extension
+tags and is known to crash (segfault) when passed a cyclic structure (say, a list containing
+itself).
+
+.. _RFC 7049: https://tools.ietf.org/html/rfc7049
+
+Project links
+-------------
+
+* `Documentation <http://cbor2.readthedocs.org/>`_
+* `Source code <https://github.com/agronholm/cbor2>`_
+* `Issue tracker <https://github.com/agronholm/cbor2/issues>`_
diff --git a/mercurial/thirdparty/cbor/LICENSE.txt b/mercurial/thirdparty/cbor/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/LICENSE.txt
@@ -0,0 +1,19 @@
+This is the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+Copyright (c) Alex Grönholm
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/mercurial/thirdparty/cbor/.travis.yml b/mercurial/thirdparty/cbor/.travis.yml
new file mode 100644
--- /dev/null
+++ b/mercurial/thirdparty/cbor/.travis.yml
@@ -0,0 +1,58 @@
+language: python
+sudo: false
+
+stages:
+  - name: test
+  - name: deploy to pypi
+    if: type = push AND tag =~ ^\d+\.\d+\.\d+
+
+jobs:
+  fast_finish: true
+  include:
+    - env: TOXENV=flake8
+
+    - env: TOXENV=pypy
+      python: pypy3
+
+    - env: TOXENV=pypy3
+      python: pypy3
+
+    - env: TOXENV=py27
+      python: "2.7"
+      after_success: &after_success
+        - pip install coveralls
+        - coveralls
+
+    - env: TOXENV=py33
+      python: "3.3"
+      after_success: *after_success
+
+    - env: TOXENV=py34
+      python: "3.4"
+      after_success: *after_success
+
+    - env: TOXENV=py35
+      python: "3.5"
+      after_success: *after_success
+
+    - env: TOXENV=py36
+      python: "3.6"
+      after_success: *after_success
+
+    - stage: deploy to pypi
+      install: pip install "setuptools >= 36.2.7"
+      script: skip
+      deploy:
+        provider: pypi
+        user: agronholm
+        password:
+          secure: QZ5qoxsrzns/b27adWNzh/OAJp86yRuxTyAFhvas/pbkiALdlT/+PGyhJBnpe+7WBTWnkIXl+YU//voJ0btf6DJcWwgRavMsy22LJJPkvvK+2DHiZ//DbpLbqKWc74y4moce29BCajFTm9JkVwcL2dgN9WuZt+Tay0efcP4sESLxo5lIGdlaQbu+9zVs61Z4Ov+yyEMO/j3LeKshNmUq+84CveQWMiXndXBfJX5TWwjahmUNDp5fMctJxr4fqgL4HCTVQhU79dPc00yDEGS45QkpP8JDrF1DQvU5Ht4COz/Lvzt11pwsAvws2ddclqBUCQsGaWvEWH5rxZTYx/MaMVdTctaUVNoT0wnFUsXXZkomQV0x8vb5RtRLDrKwXosXlSEqnRyiKhdgHGoswHvB7XF5BtQ5RmydRX77pwEGmFd3lqRif2bos0MEeOJA8Xds0TGOKO4PyokBnj/a0tjT2LEVxObmTT6grz5QPXi386AWgxbNl0Lp7cnkSpCqC1hEHVqrDlbtu7uvfGwwe/sYlEcQ07PNCvFoR2GXJawbeHmJRfz+KXjffrt2yCzc671FL1goUysHKdBCppvUInI8FCMQpVWEh5MmQJKB4IpDrhqfo0VS+NNZgZ8lFStq27Pmwqf1HUTGlaDi9VQ0Vo7tW5j4JbD/JvOQSb3j9DjUFps=
+        distributions: sdist bdist_wheel
+        on:
+          tags: true
+
+install:
+  - pip install "setuptools >= 36.2.7"
+  - pip install tox
+
+script: tox



To: pulkit, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list