Drop Python 3.6 support (#543)

The following steps have been taken:

1. Black was updated to latest version. The code has been formatted with
the new version.
2. The pyupgrade utility is installed. This helped to remove all the
code that was needed to support Python < 3.7.

Fix #541.

Co-authored-by: Inada Naoki <songofacandy@gmail.com>
This commit is contained in:
Evgeny Markov 2023-05-23 18:41:08 +02:00 committed by GitHub
parent feec06206c
commit c8d0751fe3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 60 additions and 119 deletions

View file

@ -1,10 +1,16 @@
PYTHON_SOURCES = msgpack test setup.py
.PHONY: all
all: cython
python setup.py build_ext -i -f
.PHONY: black
black:
black -S msgpack/ test/ setup.py
black $(PYTHON_SOURCES)
.PHONY: pyupgrade
pyupgrade:
@find $(PYTHON_SOURCES) -name '*.py' -type f -exec pyupgrade --py37-plus '{}' \;
.PHONY: cython
cython:

View file

@ -1,4 +1,3 @@
# coding: utf-8
from .exceptions import *
from .ext import ExtType, Timestamp

View file

@ -1,4 +1,3 @@
# coding: utf-8
from collections import namedtuple
import datetime
import sys
@ -15,10 +14,10 @@ class ExtType(namedtuple("ExtType", "code data")):
raise TypeError("data must be bytes")
if not 0 <= code <= 127:
raise ValueError("code must be 0~127")
return super(ExtType, cls).__new__(cls, code, data)
return super().__new__(cls, code, data)
class Timestamp(object):
class Timestamp:
"""Timestamp represents the Timestamp extension type in msgpack.
When built with Cython, msgpack uses C methods to pack and unpack `Timestamp`. When using pure-Python
@ -47,24 +46,18 @@ class Timestamp(object):
if not isinstance(nanoseconds, int):
raise TypeError("nanoseconds must be an integer")
if not (0 <= nanoseconds < 10**9):
raise ValueError(
"nanoseconds must be a non-negative integer less than 999999999."
)
raise ValueError("nanoseconds must be a non-negative integer less than 999999999.")
self.seconds = seconds
self.nanoseconds = nanoseconds
def __repr__(self):
"""String representation of Timestamp."""
return "Timestamp(seconds={0}, nanoseconds={1})".format(
self.seconds, self.nanoseconds
)
return f"Timestamp(seconds={self.seconds}, nanoseconds={self.nanoseconds})"
def __eq__(self, other):
"""Check for equality with another Timestamp object"""
if type(other) is self.__class__:
return (
self.seconds == other.seconds and self.nanoseconds == other.nanoseconds
)
return self.seconds == other.seconds and self.nanoseconds == other.nanoseconds
return False
def __ne__(self, other):
@ -164,9 +157,7 @@ class Timestamp(object):
:rtype: datetime.
"""
utc = datetime.timezone.utc
return datetime.datetime.fromtimestamp(0, utc) + datetime.timedelta(
seconds=self.to_unix()
)
return datetime.datetime.fromtimestamp(0, utc) + datetime.timedelta(seconds=self.to_unix())
@staticmethod
def from_datetime(dt):

View file

@ -4,23 +4,6 @@ import sys
import struct
if sys.version_info < (3, 5):
# Ugly hack...
RecursionError = RuntimeError
def _is_recursionerror(e):
return (
len(e.args) == 1
and isinstance(e.args[0], str)
and e.args[0].startswith("maximum recursion depth exceeded")
)
else:
def _is_recursionerror(e):
return True
if hasattr(sys, "pypy_version_info"):
# StringIO is slow on PyPy, StringIO is faster. However: PyPy's own
# StringBuilder is fastest.
@ -32,7 +15,7 @@ if hasattr(sys, "pypy_version_info"):
from __pypy__.builders import StringBuilder
USING_STRINGBUILDER = True
class StringIO(object):
class StringIO:
def __init__(self, s=b""):
if s:
self.builder = StringBuilder(len(s))
@ -109,10 +92,8 @@ def unpackb(packed, **kwargs):
ret = unpacker._unpack()
except OutOfData:
raise ValueError("Unpack failed: incomplete input")
except RecursionError as e:
if _is_recursionerror(e):
except RecursionError:
raise StackError
raise
if unpacker._got_extradata():
raise ExtraData(ret, unpacker._get_extradata())
return ret
@ -151,7 +132,7 @@ _MSGPACK_HEADERS = {
}
class Unpacker(object):
class Unpacker:
"""Streaming unpacker.
Arguments:
@ -334,9 +315,7 @@ class Unpacker(object):
if object_pairs_hook is not None and not callable(object_pairs_hook):
raise TypeError("`object_pairs_hook` is not callable")
if object_hook is not None and object_pairs_hook is not None:
raise TypeError(
"object_pairs_hook and object_hook are mutually " "exclusive"
)
raise TypeError("object_pairs_hook and object_hook are mutually exclusive")
if not callable(ext_hook):
raise TypeError("`ext_hook` is not callable")
@ -428,20 +407,18 @@ class Unpacker(object):
n = b & 0b00011111
typ = TYPE_RAW
if n > self._max_str_len:
raise ValueError("%s exceeds max_str_len(%s)" % (n, self._max_str_len))
raise ValueError(f"{n} exceeds max_str_len({self._max_str_len})")
obj = self._read(n)
elif b & 0b11110000 == 0b10010000:
n = b & 0b00001111
typ = TYPE_ARRAY
if n > self._max_array_len:
raise ValueError(
"%s exceeds max_array_len(%s)" % (n, self._max_array_len)
)
raise ValueError(f"{n} exceeds max_array_len({self._max_array_len})")
elif b & 0b11110000 == 0b10000000:
n = b & 0b00001111
typ = TYPE_MAP
if n > self._max_map_len:
raise ValueError("%s exceeds max_map_len(%s)" % (n, self._max_map_len))
raise ValueError(f"{n} exceeds max_map_len({self._max_map_len})")
elif b == 0xC0:
obj = None
elif b == 0xC2:
@ -457,7 +434,7 @@ class Unpacker(object):
n = self._buffer[self._buff_i]
self._buff_i += size
if n > self._max_bin_len:
raise ValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len))
raise ValueError(f"{n} exceeds max_bin_len({self._max_bin_len})")
obj = self._read(n)
elif 0xC7 <= b <= 0xC9:
size, fmt, typ = _MSGPACK_HEADERS[b]
@ -465,7 +442,7 @@ class Unpacker(object):
L, n = struct.unpack_from(fmt, self._buffer, self._buff_i)
self._buff_i += size
if L > self._max_ext_len:
raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len))
raise ValueError(f"{L} exceeds max_ext_len({self._max_ext_len})")
obj = self._read(L)
elif 0xCA <= b <= 0xD3:
size, fmt = _MSGPACK_HEADERS[b]
@ -478,9 +455,7 @@ class Unpacker(object):
elif 0xD4 <= b <= 0xD8:
size, fmt, typ = _MSGPACK_HEADERS[b]
if self._max_ext_len < size:
raise ValueError(
"%s exceeds max_ext_len(%s)" % (size, self._max_ext_len)
)
raise ValueError(f"{size} exceeds max_ext_len({self._max_ext_len})")
self._reserve(size + 1)
n, obj = struct.unpack_from(fmt, self._buffer, self._buff_i)
self._buff_i += size + 1
@ -493,7 +468,7 @@ class Unpacker(object):
n = self._buffer[self._buff_i]
self._buff_i += size
if n > self._max_str_len:
raise ValueError("%s exceeds max_str_len(%s)" % (n, self._max_str_len))
raise ValueError(f"{n} exceeds max_str_len({self._max_str_len})")
obj = self._read(n)
elif 0xDC <= b <= 0xDD:
size, fmt, typ = _MSGPACK_HEADERS[b]
@ -501,16 +476,14 @@ class Unpacker(object):
(n,) = struct.unpack_from(fmt, self._buffer, self._buff_i)
self._buff_i += size
if n > self._max_array_len:
raise ValueError(
"%s exceeds max_array_len(%s)" % (n, self._max_array_len)
)
raise ValueError(f"{n} exceeds max_array_len({self._max_array_len})")
elif 0xDE <= b <= 0xDF:
size, fmt, typ = _MSGPACK_HEADERS[b]
self._reserve(size)
(n,) = struct.unpack_from(fmt, self._buffer, self._buff_i)
self._buff_i += size
if n > self._max_map_len:
raise ValueError("%s exceeds max_map_len(%s)" % (n, self._max_map_len))
raise ValueError(f"{n} exceeds max_map_len({self._max_map_len})")
else:
raise FormatError("Unknown header: 0x%x" % b)
return typ, n, obj
@ -549,17 +522,14 @@ class Unpacker(object):
return
if self._object_pairs_hook is not None:
ret = self._object_pairs_hook(
(self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT))
for _ in range(n)
(self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT)) for _ in range(n)
)
else:
ret = {}
for _ in range(n):
key = self._unpack(EX_CONSTRUCT)
if self._strict_map_key and type(key) not in (str, bytes):
raise ValueError(
"%s is not allowed for map key" % str(type(key))
)
raise ValueError("%s is not allowed for map key" % str(type(key)))
if type(key) is str:
key = sys.intern(key)
ret[key] = self._unpack(EX_CONSTRUCT)
@ -634,7 +604,7 @@ class Unpacker(object):
return self._stream_offset
class Packer(object):
class Packer:
"""
MessagePack Packer
@ -844,9 +814,9 @@ class Packer(object):
continue
if self._datetime and check(obj, _DateTime):
raise ValueError("Cannot serialize %r where tzinfo=None" % (obj,))
raise ValueError(f"Cannot serialize {obj!r} where tzinfo=None")
raise TypeError("Cannot serialize %r" % (obj,))
raise TypeError(f"Cannot serialize {obj!r}")
def pack(self, obj):
try:
@ -933,7 +903,7 @@ class Packer(object):
def _pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT):
self._pack_map_header(n)
for (k, v) in pairs:
for k, v in pairs:
self._pack(k, nest_limit - 1)
self._pack(v, nest_limit - 1)

View file

@ -6,3 +6,8 @@ requires = [
"setuptools >= 35.0.2",
]
build-backend = "setuptools.build_meta"
[tool.black]
line-length = 100
target-version = ["py37"]
skip_string_normalization = true

View file

@ -1,5 +1,7 @@
# Also declared in pyproject.toml, if updating here please also update there
# Also declared in pyproject.toml, if updating here please also update there.
Cython~=0.29.30
# dev only tools. no need to add pyproject
black==22.3.0
# Tools required only for development. No need to add it to pyproject.toml file.
black==23.3.0
pytest==7.3.1
pyupgrade==3.3.2

View file

@ -17,7 +17,6 @@ project_urls =
classifiers =
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
import io
import os
import sys
@ -25,7 +24,7 @@ except ImportError:
def cythonize(src):
sys.stderr.write("cythonize: %r\n" % (src,))
sys.stderr.write(f"cythonize: {src!r}\n")
cython_compiler.compile([src], cplus=True)
@ -36,11 +35,7 @@ def ensure_source(src):
if not have_cython:
raise NoCython
cythonize(pyx)
elif (
os.path.exists(pyx)
and os.stat(src).st_mtime < os.stat(pyx).st_mtime
and have_cython
):
elif os.path.exists(pyx) and os.stat(src).st_mtime < os.stat(pyx).st_mtime and have_cython:
cythonize(pyx)
return src

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
import sys
import pytest

View file

@ -1,11 +1,10 @@
#!/usr/bin/env python
# coding: utf-8
from msgpack import packb, unpackb
def check(length, obj, use_bin_type=True):
v = packb(obj, use_bin_type=use_bin_type)
assert len(v) == length, "%r length should be %r but get %r" % (obj, length, len(v))
assert len(v) == length, f"{obj!r} length should be {length!r} but get {len(v)!r}"
assert unpackb(v, use_list=0, raw=not use_bin_type) == obj
@ -120,11 +119,11 @@ def test_match():
),
({}, b"\x80"),
(
dict([(x, x) for x in range(15)]),
{x: x for x in range(15)},
b"\x8f\x00\x00\x01\x01\x02\x02\x03\x03\x04\x04\x05\x05\x06\x06\x07\x07\x08\x08\t\t\n\n\x0b\x0b\x0c\x0c\r\r\x0e\x0e",
),
(
dict([(x, x) for x in range(16)]),
{x: x for x in range(16)},
b"\xde\x00\x10\x00\x00\x01\x01\x02\x02\x03\x03\x04\x04\x05\x05\x06\x06\x07\x07\x08\x08\t\t\n\n\x0b\x0b\x0c\x0c\r\r\x0e\x0e\x0f\x0f",
),
]

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
from pytest import raises
from msgpack import packb, unpackb, Unpacker, FormatError, StackError, OutOfData

View file

@ -1,4 +1,3 @@
from __future__ import print_function
import array
import msgpack
from msgpack import ExtType
@ -17,9 +16,7 @@ def test_pack_ext_type():
assert p(b"A" * 16) == b"\xd8\x42" + b"A" * 16 # fixext 16
assert p(b"ABC") == b"\xc7\x03\x42ABC" # ext 8
assert p(b"A" * 0x0123) == b"\xc8\x01\x23\x42" + b"A" * 0x0123 # ext 16
assert (
p(b"A" * 0x00012345) == b"\xc9\x00\x01\x23\x45\x42" + b"A" * 0x00012345
) # ext 32
assert p(b"A" * 0x00012345) == b"\xc9\x00\x01\x23\x45\x42" + b"A" * 0x00012345 # ext 32
def test_unpack_ext_type():
@ -49,7 +46,7 @@ def test_extension_type():
except AttributeError:
data = obj.tostring()
return ExtType(typecode, data)
raise TypeError("Unknown type object %r" % (obj,))
raise TypeError(f"Unknown type object {obj!r}")
def ext_hook(code, data):
print("ext_hook called", code, data)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
from msgpack import unpackb
@ -25,9 +24,7 @@ def testFixRaw():
def testFixMap():
check(
b"\x82\xc2\x81\xc0\xc0\xc3\x81\xc0\x80", {False: {None: None}, True: {None: {}}}
)
check(b"\x82\xc2\x81\xc0\xc0\xc3\x81\xc0\x80", {False: {None: None}, True: {None: {}}})
def testUnsignedInt():

View file

@ -1,6 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function, unicode_literals
import pytest
from msgpack import (

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
import pytest
from array import array

View file

@ -1,5 +1,3 @@
# coding: utf-8
from msgpack import packb, unpackb, ExtType

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
from pytest import raises
from msgpack import packb, unpackb

View file

@ -1,6 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function, unicode_literals
from collections import OrderedDict
from io import BytesIO
@ -81,9 +79,7 @@ def testPackByteArrays():
def testIgnoreUnicodeErrors():
re = unpackb(
packb(b"abc\xeddef", use_bin_type=False), raw=False, unicode_errors="ignore"
)
re = unpackb(packb(b"abc\xeddef", use_bin_type=False), raw=False, unicode_errors="ignore")
assert re == "abcdef"
@ -108,8 +104,8 @@ def testDecodeBinary():
def testPackFloat():
assert packb(1.0, use_single_float=True) == b"\xca" + struct.pack(str(">f"), 1.0)
assert packb(1.0, use_single_float=False) == b"\xcb" + struct.pack(str(">d"), 1.0)
assert packb(1.0, use_single_float=True) == b"\xca" + struct.pack(">f", 1.0)
assert packb(1.0, use_single_float=False) == b"\xcb" + struct.pack(">d", 1.0)
def testArraySize(sizes=[0, 5, 50, 1000]):
@ -154,7 +150,7 @@ def testMapSize(sizes=[0, 5, 50, 1000]):
bio.seek(0)
unpacker = Unpacker(bio, strict_map_key=False)
for size in sizes:
assert unpacker.unpack() == dict((i, i * 2) for i in range(size))
assert unpacker.unpack() == {i: i * 2 for i in range(size)}
def test_odict():

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
import io
import msgpack

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
import io
from msgpack import Unpacker, BufferFull
from msgpack import pack, packb

View file

@ -1,5 +1,3 @@
# coding: utf-8
from collections import namedtuple
from msgpack import packb, unpackb, ExtType
@ -10,7 +8,7 @@ def test_namedtuple():
def default(o):
if isinstance(o, T):
return dict(o._asdict())
raise TypeError("Unsupported type %s" % (type(o),))
raise TypeError(f"Unsupported type {type(o)}")
packed = packb(T(1, 42), strict_types=True, use_bin_type=True, default=default)
unpacked = unpackb(packed, raw=False)
@ -23,7 +21,7 @@ def test_tuple():
def default(o):
if isinstance(o, tuple):
return {"__type__": "tuple", "value": list(o)}
raise TypeError("Unsupported type %s" % (type(o),))
raise TypeError(f"Unsupported type {type(o)}")
def convert(o):
if o.get("__type__") == "tuple":
@ -44,9 +42,7 @@ def test_tuple_ext():
def default(o):
if isinstance(o, tuple):
# Convert to list and pack
payload = packb(
list(o), strict_types=True, use_bin_type=True, default=default
)
payload = packb(list(o), strict_types=True, use_bin_type=True, default=default)
return ExtType(MSGPACK_EXT_TYPE_TUPLE, payload)
raise TypeError(repr(o))
@ -54,7 +50,7 @@ def test_tuple_ext():
if code == MSGPACK_EXT_TYPE_TUPLE:
# Unpack and convert to tuple
return tuple(unpackb(payload, raw=False, ext_hook=convert))
raise ValueError("Unknown Ext code {}".format(code))
raise ValueError(f"Unknown Ext code {code}")
data = packb(t, strict_types=True, use_bin_type=True, default=default)
expected = unpackb(data, raw=False, ext_hook=convert)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
from msgpack import packb, unpackb
from collections import namedtuple

View file

@ -52,7 +52,7 @@ def test_unpacker_hook_refcnt():
def test_unpacker_ext_hook():
class MyUnpacker(Unpacker):
def __init__(self):
super(MyUnpacker, self).__init__(ext_hook=self._hook, raw=False)
super().__init__(ext_hook=self._hook, raw=False)
def _hook(self, code, data):
if code == 1: