From 0516c2c2a97ef48a2becf30bc8b2365ca16199f1 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 9 Mar 2023 01:22:38 +0900 Subject: [PATCH 01/14] Action: Update test workflow --- .github/workflows/test.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5e41167f..88781025 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,7 @@ jobs: test: strategy: matrix: - os: [ubuntu-22.04, windows-2022, macos-10.15] + os: ["ubuntu-latest", "windows-latest", "macos-latest"] py: ["3.11", "3.10", "3.9", "3.8", "3.7"] runs-on: ${{ matrix.os }} @@ -41,9 +41,3 @@ jobs: shell: bash run: | MSGPACK_PUREPYTHON=1 pytest -v test - - - name: Publish Wheels to TestPyPI - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: ${{ secrets.PYPI_API_TOKEN }} From 802cbc9495ed059b62b46f057cf3d71f756e2480 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Sat, 1 Apr 2023 00:02:25 +0900 Subject: [PATCH 02/14] Add security policy --- SECURITY.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..75f0c541 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +## Security contact information + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. \ No newline at end of file From 45f848695c855966d8a46656d8de1a2734d934ae Mon Sep 17 00:00:00 2001 From: Laerte Pereira <5853172+Laerte@users.noreply.github.com> Date: Sat, 8 Apr 2023 02:18:25 -0300 Subject: [PATCH 03/14] fix: build status badge (#538) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb816485..7f7c4234 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MessagePack for Python -[![Build Status](https://travis-ci.org/msgpack/msgpack-python.svg?branch=master)](https://travis-ci.org/msgpack/msgpack-python) +[![Build Status](https://github.com/msgpack/msgpack-python/actions/workflows/wheel.yml/badge.svg)](https://github.com/msgpack/msgpack-python/actions/workflows/wheel.yml) [![Documentation Status](https://readthedocs.org/projects/msgpack-python/badge/?version=latest)](https://msgpack-python.readthedocs.io/en/latest/?badge=latest) ## What's this From feec06206c7f8dd8efeac6177badbf5b256b36e4 Mon Sep 17 00:00:00 2001 From: sblondon Date: Sun, 21 May 2023 09:26:39 +0200 Subject: [PATCH 04/14] Drop python2 support (#519) The PR removes python2 references and cases. Close #518 Co-authored-by: Inada Naoki --- README.md | 4 +-- docs/conf.py | 20 ++++++------ msgpack/__init__.py | 2 +- msgpack/_packer.pyx | 1 - msgpack/_unpacker.pyx | 2 +- msgpack/ext.py | 24 +++----------- msgpack/fallback.py | 70 ++++++++++++----------------------------- setup.py | 3 +- test/test_buffer.py | 1 - test/test_case.py | 2 +- test/test_except.py | 2 +- test/test_extension.py | 15 ++------- test/test_memoryview.py | 5 --- test/test_pack.py | 6 ---- test/test_timestamp.py | 27 +++++++--------- test/test_unpack.py | 4 +-- tox.ini | 13 -------- 17 files changed, 58 insertions(+), 143 deletions(-) diff --git a/README.md b/README.md index 7f7c4234..61f99e1f 100644 --- a/README.md +++ b/README.md @@ -220,9 +220,9 @@ and `raw=True` options. ```pycon >>> import msgpack ->>> msgpack.unpackb(msgpack.packb([b'spam', u'eggs'], use_bin_type=False), raw=True) +>>> msgpack.unpackb(msgpack.packb([b'spam', 'eggs'], use_bin_type=False), raw=True) [b'spam', b'eggs'] ->>> msgpack.unpackb(msgpack.packb([b'spam', u'eggs'], use_bin_type=True), raw=False) +>>> msgpack.unpackb(msgpack.packb([b'spam', 'eggs'], use_bin_type=True), raw=False) [b'spam', 'eggs'] ``` diff --git a/docs/conf.py b/docs/conf.py index 6b432be0..91ce77f0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -40,8 +40,8 @@ master_doc = "index" # General information about the project. -project = u"msgpack" -copyright = u"Inada Naoki" +project = "msgpack" +copyright = "Inada Naoki" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -181,7 +181,7 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ("index", "msgpack.tex", u"msgpack Documentation", u"Author", "manual"), + ("index", "msgpack.tex", "msgpack Documentation", "Author", "manual"), ] # The name of an image file (relative to this directory) to place at the top of @@ -209,7 +209,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [("index", "msgpack", u"msgpack Documentation", [u"Author"], 1)] +man_pages = [("index", "msgpack", "msgpack Documentation", ["Author"], 1)] # If true, show URL addresses after external links. # man_show_urls = False @@ -224,8 +224,8 @@ ( "index", "msgpack", - u"msgpack Documentation", - u"Author", + "msgpack Documentation", + "Author", "msgpack", "One line description of project.", "Miscellaneous", @@ -245,10 +245,10 @@ # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. -epub_title = u"msgpack" -epub_author = u"Author" -epub_publisher = u"Author" -epub_copyright = u"2013, Author" +epub_title = "msgpack" +epub_author = "Author" +epub_publisher = "Author" +epub_copyright = "2013, Author" # The language of the text. It defaults to the language option # or en if the language is not set. diff --git a/msgpack/__init__.py b/msgpack/__init__.py index 1300b866..6c10dc23 100644 --- a/msgpack/__init__.py +++ b/msgpack/__init__.py @@ -10,7 +10,7 @@ __version__ = "1.0.5" -if os.environ.get("MSGPACK_PUREPYTHON") or sys.version_info[0] == 2: +if os.environ.get("MSGPACK_PUREPYTHON"): from .fallback import Packer, unpackb, Unpacker else: try: diff --git a/msgpack/_packer.pyx b/msgpack/_packer.pyx index 396da0c2..074b39fc 100644 --- a/msgpack/_packer.pyx +++ b/msgpack/_packer.pyx @@ -98,7 +98,6 @@ cdef class Packer(object): If set to true, datetime with tzinfo is packed into Timestamp type. Note that the tzinfo is stripped in the timestamp. You can get UTC datetime with `timestamp=3` option of the Unpacker. - (Python 2 is not supported). :param str unicode_errors: The error handler for encoding unicode. (default: 'strict') diff --git a/msgpack/_unpacker.pyx b/msgpack/_unpacker.pyx index 8b06661e..d5dc5ea5 100644 --- a/msgpack/_unpacker.pyx +++ b/msgpack/_unpacker.pyx @@ -236,7 +236,7 @@ cdef class Unpacker(object): 0 - Timestamp 1 - float (Seconds from the EPOCH) 2 - int (Nanoseconds from the EPOCH) - 3 - datetime.datetime (UTC). Python 2 is not supported. + 3 - datetime.datetime (UTC). :param bool strict_map_key: If true (default), only str or bytes are accepted for map (dict) keys. diff --git a/msgpack/ext.py b/msgpack/ext.py index 23e0d6b4..07f96a58 100644 --- a/msgpack/ext.py +++ b/msgpack/ext.py @@ -5,19 +5,6 @@ import struct -PY2 = sys.version_info[0] == 2 - -if PY2: - int_types = (int, long) - _utc = None -else: - int_types = int - try: - _utc = datetime.timezone.utc - except AttributeError: - _utc = datetime.timezone(datetime.timedelta(0)) - - class ExtType(namedtuple("ExtType", "code data")): """ExtType represents ext type in msgpack.""" @@ -55,9 +42,9 @@ def __init__(self, seconds, nanoseconds=0): Note: Negative times (before the UNIX epoch) are represented as negative seconds + positive ns. """ - if not isinstance(seconds, int_types): + if not isinstance(seconds, int): raise TypeError("seconds must be an integer") - if not isinstance(nanoseconds, int_types): + if not isinstance(nanoseconds, int): raise TypeError("nanoseconds must be an integer") if not (0 <= nanoseconds < 10**9): raise ValueError( @@ -174,11 +161,10 @@ def to_unix_nano(self): def to_datetime(self): """Get the timestamp as a UTC datetime. - Python 2 is not supported. - :rtype: datetime. """ - return datetime.datetime.fromtimestamp(0, _utc) + datetime.timedelta( + utc = datetime.timezone.utc + return datetime.datetime.fromtimestamp(0, utc) + datetime.timedelta( seconds=self.to_unix() ) @@ -186,8 +172,6 @@ def to_datetime(self): def from_datetime(dt): """Create a Timestamp from datetime with tzinfo. - Python 2 is not supported. - :rtype: Timestamp """ return Timestamp.from_unix(dt.timestamp()) diff --git a/msgpack/fallback.py b/msgpack/fallback.py index e8cebc1b..618c3622 100644 --- a/msgpack/fallback.py +++ b/msgpack/fallback.py @@ -4,22 +4,6 @@ import struct -PY2 = sys.version_info[0] == 2 -if PY2: - int_types = (int, long) - - def dict_iteritems(d): - return d.iteritems() - -else: - int_types = int - unicode = str - xrange = range - - def dict_iteritems(d): - return d.items() - - if sys.version_info < (3, 5): # Ugly hack... RecursionError = RuntimeError @@ -134,15 +118,6 @@ def unpackb(packed, **kwargs): return ret -if sys.version_info < (2, 7, 6): - - def _unpack_from(f, b, o=0): - """Explicit type cast for legacy struct.unpack_from""" - return struct.unpack_from(f, bytes(b), o) - -else: - _unpack_from = struct.unpack_from - _NO_FORMAT_USED = "" _MSGPACK_HEADERS = { 0xC4: (1, _NO_FORMAT_USED, TYPE_BIN), @@ -202,7 +177,7 @@ class Unpacker(object): 0 - Timestamp 1 - float (Seconds from the EPOCH) 2 - int (Nanoseconds from the EPOCH) - 3 - datetime.datetime (UTC). Python 2 is not supported. + 3 - datetime.datetime (UTC). :param bool strict_map_key: If true (default), only str or bytes are accepted for map (dict) keys. @@ -477,7 +452,7 @@ def _read_header(self): size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) if len(fmt) > 0: - n = _unpack_from(fmt, self._buffer, self._buff_i)[0] + n = struct.unpack_from(fmt, self._buffer, self._buff_i)[0] else: n = self._buffer[self._buff_i] self._buff_i += size @@ -487,7 +462,7 @@ def _read_header(self): elif 0xC7 <= b <= 0xC9: size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) - L, n = _unpack_from(fmt, self._buffer, self._buff_i) + 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)) @@ -496,7 +471,7 @@ def _read_header(self): size, fmt = _MSGPACK_HEADERS[b] self._reserve(size) if len(fmt) > 0: - obj = _unpack_from(fmt, self._buffer, self._buff_i)[0] + obj = struct.unpack_from(fmt, self._buffer, self._buff_i)[0] else: obj = self._buffer[self._buff_i] self._buff_i += size @@ -507,13 +482,13 @@ def _read_header(self): "%s exceeds max_ext_len(%s)" % (size, self._max_ext_len) ) self._reserve(size + 1) - n, obj = _unpack_from(fmt, self._buffer, self._buff_i) + n, obj = struct.unpack_from(fmt, self._buffer, self._buff_i) self._buff_i += size + 1 elif 0xD9 <= b <= 0xDB: size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) if len(fmt) > 0: - (n,) = _unpack_from(fmt, self._buffer, self._buff_i) + (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i) else: n = self._buffer[self._buff_i] self._buff_i += size @@ -523,7 +498,7 @@ def _read_header(self): elif 0xDC <= b <= 0xDD: size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) - (n,) = _unpack_from(fmt, self._buffer, self._buff_i) + (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i) self._buff_i += size if n > self._max_array_len: raise ValueError( @@ -532,7 +507,7 @@ def _read_header(self): elif 0xDE <= b <= 0xDF: size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) - (n,) = _unpack_from(fmt, self._buffer, self._buff_i) + (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)) @@ -554,12 +529,12 @@ def _unpack(self, execute=EX_CONSTRUCT): # TODO should we eliminate the recursion? if typ == TYPE_ARRAY: if execute == EX_SKIP: - for i in xrange(n): + for i in range(n): # TODO check whether we need to call `list_hook` self._unpack(EX_SKIP) return ret = newlist_hint(n) - for i in xrange(n): + for i in range(n): ret.append(self._unpack(EX_CONSTRUCT)) if self._list_hook is not None: ret = self._list_hook(ret) @@ -567,7 +542,7 @@ def _unpack(self, execute=EX_CONSTRUCT): return ret if self._use_list else tuple(ret) if typ == TYPE_MAP: if execute == EX_SKIP: - for i in xrange(n): + for i in range(n): # TODO check whether we need to call hooks self._unpack(EX_SKIP) self._unpack(EX_SKIP) @@ -575,17 +550,17 @@ def _unpack(self, execute=EX_CONSTRUCT): if self._object_pairs_hook is not None: ret = self._object_pairs_hook( (self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT)) - for _ in xrange(n) + for _ in range(n) ) else: ret = {} - for _ in xrange(n): + for _ in range(n): key = self._unpack(EX_CONSTRUCT) - if self._strict_map_key and type(key) not in (unicode, bytes): + if self._strict_map_key and type(key) not in (str, bytes): raise ValueError( "%s is not allowed for map key" % str(type(key)) ) - if not PY2 and type(key) is str: + if type(key) is str: key = sys.intern(key) ret[key] = self._unpack(EX_CONSTRUCT) if self._object_hook is not None: @@ -698,7 +673,6 @@ class Packer(object): If set to true, datetime with tzinfo is packed into Timestamp type. Note that the tzinfo is stripped in the timestamp. You can get UTC datetime with `timestamp=3` option of the Unpacker. - (Python 2 is not supported). :param str unicode_errors: The error handler for encoding unicode. (default: 'strict') @@ -743,8 +717,6 @@ def __init__( self._autoreset = autoreset self._use_bin_type = use_bin_type self._buffer = StringIO() - if PY2 and datetime: - raise ValueError("datetime is not supported in Python 2") self._datetime = bool(datetime) self._unicode_errors = unicode_errors or "strict" if default is not None: @@ -774,7 +746,7 @@ def _pack( if obj: return self._buffer.write(b"\xc3") return self._buffer.write(b"\xc2") - if check(obj, int_types): + if check(obj, int): if 0 <= obj < 0x80: return self._buffer.write(struct.pack("B", obj)) if -0x20 <= obj < 0: @@ -806,7 +778,7 @@ def _pack( raise ValueError("%s is too large" % type(obj).__name__) self._pack_bin_header(n) return self._buffer.write(obj) - if check(obj, unicode): + if check(obj, str): obj = obj.encode("utf-8", self._unicode_errors) n = len(obj) if n >= 2**32: @@ -855,13 +827,11 @@ def _pack( if check(obj, list_types): n = len(obj) self._pack_array_header(n) - for i in xrange(n): + for i in range(n): self._pack(obj[i], nest_limit - 1) return if check(obj, dict): - return self._pack_map_pairs( - len(obj), dict_iteritems(obj), nest_limit - 1 - ) + return self._pack_map_pairs(len(obj), obj.items(), nest_limit - 1) if self._datetime and check(obj, _DateTime) and obj.tzinfo is not None: obj = Timestamp.from_datetime(obj) @@ -1004,7 +974,7 @@ def reset(self): def getbuffer(self): """Return view of internal buffer.""" - if USING_STRINGBUILDER or PY2: + if USING_STRINGBUILDER: return memoryview(self.bytes()) else: return self._buffer.getbuffer() diff --git a/setup.py b/setup.py index 9630cda0..15ba7741 100755 --- a/setup.py +++ b/setup.py @@ -10,7 +10,6 @@ PYPY = hasattr(sys, "pypy_version_info") -PY2 = sys.version_info[0] == 2 class NoCython(Exception): @@ -79,7 +78,7 @@ def __init__(self, *args, **kwargs): macros = [("__LITTLE_ENDIAN__", "1")] ext_modules = [] -if not PYPY and not PY2 and not os.environ.get("MSGPACK_PUREPYTHON"): +if not PYPY and not os.environ.get("MSGPACK_PUREPYTHON"): ext_modules.append( Extension( "msgpack._cmsgpack", diff --git a/test/test_buffer.py b/test/test_buffer.py index 62507cf4..04470584 100644 --- a/test/test_buffer.py +++ b/test/test_buffer.py @@ -6,7 +6,6 @@ from msgpack import packb, unpackb -@pytest.mark.skipif(sys.version_info[0] == 2, reason="Python 2 is not supported") def test_unpack_buffer(): from array import array diff --git a/test/test_case.py b/test/test_case.py index a0a3c5ad..1c4e3229 100644 --- a/test/test_case.py +++ b/test/test_case.py @@ -134,4 +134,4 @@ def test_match(): def test_unicode(): - assert unpackb(packb(u"foobar"), use_list=1) == u"foobar" + assert unpackb(packb("foobar"), use_list=1) == "foobar" diff --git a/test/test_except.py b/test/test_except.py index 5544f2bc..745ebecb 100644 --- a/test/test_except.py +++ b/test/test_except.py @@ -53,7 +53,7 @@ def test_invalidvalue(): def test_strict_map_key(): - valid = {u"unicode": 1, b"bytes": 2} + valid = {"unicode": 1, b"bytes": 2} packed = packb(valid, use_bin_type=True) assert valid == unpackb(packed, raw=False, strict_map_key=True) diff --git a/test/test_extension.py b/test/test_extension.py index 6b365751..dfbe4350 100644 --- a/test/test_extension.py +++ b/test/test_extension.py @@ -55,10 +55,7 @@ def ext_hook(code, data): print("ext_hook called", code, data) assert code == 123 obj = array.array("d") - try: - obj.frombytes(data) - except AttributeError: # PY2 - obj.fromstring(data) + obj.frombytes(data) return obj obj = [42, b"hello", array.array("d", [1.1, 2.2, 3.3])] @@ -67,20 +64,14 @@ def ext_hook(code, data): assert obj == obj2 -import sys - -if sys.version > "3": - long = int - - def test_overriding_hooks(): def default(obj): - if isinstance(obj, long): + if isinstance(obj, int): return {"__type__": "long", "__data__": str(obj)} else: return obj - obj = {"testval": long(1823746192837461928374619)} + obj = {"testval": 1823746192837461928374619} refobj = {"testval": default(obj["testval"])} refout = msgpack.packb(refobj) assert isinstance(refout, (str, bytes)) diff --git a/test/test_memoryview.py b/test/test_memoryview.py index a0939a69..63beab10 100644 --- a/test/test_memoryview.py +++ b/test/test_memoryview.py @@ -7,11 +7,6 @@ import sys -pytestmark = pytest.mark.skipif( - sys.version_info[0] < 3, reason="Only Python 3 supports buffer protocol" -) - - def make_array(f, data): a = array(f) a.frombytes(data) diff --git a/test/test_pack.py b/test/test_pack.py index a51d84c9..65c9cb17 100644 --- a/test/test_pack.py +++ b/test/test_pack.py @@ -80,9 +80,6 @@ def testPackByteArrays(): check(td) -@pytest.mark.skipif( - sys.version_info < (3, 0), reason="Python 2 passes invalid surrogates" -) def testIgnoreUnicodeErrors(): re = unpackb( packb(b"abc\xeddef", use_bin_type=False), raw=False, unicode_errors="ignore" @@ -96,9 +93,6 @@ def testStrictUnicodeUnpack(): unpackb(packed, raw=False, use_list=1) -@pytest.mark.skipif( - sys.version_info < (3, 0), reason="Python 2 passes invalid surrogates" -) def testIgnoreErrorsPack(): re = unpackb( packb("abc\uDC80\uDCFFdef", use_bin_type=True, unicode_errors="ignore"), diff --git a/test/test_timestamp.py b/test/test_timestamp.py index 253228e7..af84a2ff 100644 --- a/test/test_timestamp.py +++ b/test/test_timestamp.py @@ -4,9 +4,6 @@ import msgpack from msgpack.ext import Timestamp -if sys.version_info[0] > 2: - from msgpack.ext import _utc - def test_timestamp(): # timestamp32 @@ -85,33 +82,33 @@ def test_timestamp_to(): assert t.to_unix_nano() == 42000014000 -@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only") def test_timestamp_datetime(): t = Timestamp(42, 14) - assert t.to_datetime() == datetime.datetime(1970, 1, 1, 0, 0, 42, 0, tzinfo=_utc) + utc = datetime.timezone.utc + assert t.to_datetime() == datetime.datetime(1970, 1, 1, 0, 0, 42, 0, tzinfo=utc) -@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only") def test_unpack_datetime(): t = Timestamp(42, 14) + utc = datetime.timezone.utc packed = msgpack.packb(t) unpacked = msgpack.unpackb(packed, timestamp=3) - assert unpacked == datetime.datetime(1970, 1, 1, 0, 0, 42, 0, tzinfo=_utc) + assert unpacked == datetime.datetime(1970, 1, 1, 0, 0, 42, 0, tzinfo=utc) -@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only") def test_pack_unpack_before_epoch(): - t_in = datetime.datetime(1960, 1, 1, tzinfo=_utc) + utc = datetime.timezone.utc + t_in = datetime.datetime(1960, 1, 1, tzinfo=utc) packed = msgpack.packb(t_in, datetime=True) unpacked = msgpack.unpackb(packed, timestamp=3) assert unpacked == t_in -@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only") def test_pack_datetime(): t = Timestamp(42, 14000) dt = t.to_datetime() - assert dt == datetime.datetime(1970, 1, 1, 0, 0, 42, 14, tzinfo=_utc) + utc = datetime.timezone.utc + assert dt == datetime.datetime(1970, 1, 1, 0, 0, 42, 14, tzinfo=utc) packed = msgpack.packb(dt, datetime=True) packed2 = msgpack.packb(t) @@ -131,10 +128,10 @@ def test_pack_datetime(): assert msgpack.unpackb(packed) is None -@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only") def test_issue451(): # https://github.com/msgpack/msgpack-python/issues/451 - dt = datetime.datetime(2100, 1, 1, 1, 1, tzinfo=_utc) + utc = datetime.timezone.utc + dt = datetime.datetime(2100, 1, 1, 1, 1, tzinfo=utc) packed = msgpack.packb(dt, datetime=True) assert packed == b"\xd6\xff\xf4\x86eL" @@ -142,7 +139,6 @@ def test_issue451(): assert dt == unpacked -@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only") def test_pack_datetime_without_tzinfo(): dt = datetime.datetime(1970, 1, 1, 0, 0, 42, 14) with pytest.raises(ValueError, match="where tzinfo=None"): @@ -152,7 +148,8 @@ def test_pack_datetime_without_tzinfo(): packed = msgpack.packb(dt, datetime=True, default=lambda x: None) assert packed == msgpack.packb(None) - dt = datetime.datetime(1970, 1, 1, 0, 0, 42, 14, tzinfo=_utc) + utc = datetime.timezone.utc + dt = datetime.datetime(1970, 1, 1, 0, 0, 42, 14, tzinfo=utc) packed = msgpack.packb(dt, datetime=True) unpacked = msgpack.unpackb(packed, timestamp=3) assert unpacked == dt diff --git a/test/test_unpack.py b/test/test_unpack.py index aa4c01f8..c7141024 100644 --- a/test/test_unpack.py +++ b/test/test_unpack.py @@ -70,7 +70,7 @@ def _hook(self, code, data): def test_unpacker_tell(): - objects = 1, 2, u"abc", u"def", u"ghi" + objects = 1, 2, "abc", "def", "ghi" packed = b"\x01\x02\xa3abc\xa3def\xa3ghi" positions = 1, 2, 6, 10, 14 unpacker = Unpacker(BytesIO(packed)) @@ -80,7 +80,7 @@ def test_unpacker_tell(): def test_unpacker_tell_read_bytes(): - objects = 1, u"abc", u"ghi" + objects = 1, "abc", "ghi" packed = b"\x01\x02\xa3abc\xa3def\xa3ghi" raw_data = b"\x02", b"\xa3def", b"" lenghts = 1, 4, 999 diff --git a/tox.ini b/tox.ini index 29c256d1..1ef2d189 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,7 @@ [tox] envlist = - py27-pure, {py35,py36,py37,py38}-{c,pure}, {pypy,pypy3}-pure, - py27-x86, py34-x86, isolated_build = true @@ -19,17 +17,6 @@ commands= setenv= pure: MSGPACK_PUREPYTHON=x -[testenv:py27-x86] -basepython=python2.7-x86 -deps= - pytest - -changedir=test -commands= - python -c 'import sys; print(hex(sys.maxsize))' - python -c 'from msgpack import _cmsgpack' - py.test - [testenv:py34-x86] basepython=python3.4-x86 deps= From c8d0751fe3375a5e8005b5edf955cd5904aaec2f Mon Sep 17 00:00:00 2001 From: Evgeny Markov Date: Tue, 23 May 2023 18:41:08 +0200 Subject: [PATCH 05/14] 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 --- Makefile | 8 ++++- msgpack/__init__.py | 1 - msgpack/ext.py | 21 ++++--------- msgpack/fallback.py | 70 ++++++++++++----------------------------- pyproject.toml | 5 +++ requirements.txt | 8 +++-- setup.cfg | 1 - setup.py | 9 ++---- test/test_buffer.py | 1 - test/test_case.py | 7 ++--- test/test_except.py | 1 - test/test_extension.py | 7 ++--- test/test_format.py | 5 +-- test/test_limits.py | 2 -- test/test_memoryview.py | 1 - test/test_newspec.py | 2 -- test/test_obj.py | 1 - test/test_pack.py | 12 +++---- test/test_seq.py | 1 - test/test_sequnpack.py | 1 - test/test_stricttype.py | 12 +++---- test/test_subtype.py | 1 - test/test_unpack.py | 2 +- 23 files changed, 60 insertions(+), 119 deletions(-) diff --git a/Makefile b/Makefile index 415dcfdd..e4f22da4 100644 --- a/Makefile +++ b/Makefile @@ -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: diff --git a/msgpack/__init__.py b/msgpack/__init__.py index 6c10dc23..638236fe 100644 --- a/msgpack/__init__.py +++ b/msgpack/__init__.py @@ -1,4 +1,3 @@ -# coding: utf-8 from .exceptions import * from .ext import ExtType, Timestamp diff --git a/msgpack/ext.py b/msgpack/ext.py index 07f96a58..97942949 100644 --- a/msgpack/ext.py +++ b/msgpack/ext.py @@ -1,4 +1,3 @@ -# coding: utf-8 from collections import namedtuple import datetime import sys @@ -15,10 +14,10 @@ def __new__(cls, 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 @@ def __init__(self, seconds, nanoseconds=0): 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 @@ def to_datetime(self): :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): diff --git a/msgpack/fallback.py b/msgpack/fallback.py index 618c3622..ac1eaf4c 100644 --- a/msgpack/fallback.py +++ b/msgpack/fallback.py @@ -4,23 +4,6 @@ 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 @@ def _is_recursionerror(e): 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): - raise StackError - raise + except RecursionError: + raise StackError if unpacker._got_extradata(): raise ExtraData(ret, unpacker._get_extradata()) return ret @@ -151,7 +132,7 @@ def unpackb(packed, **kwargs): } -class Unpacker(object): +class Unpacker: """Streaming unpacker. Arguments: @@ -334,9 +315,7 @@ def __init__( 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 @@ def _read_header(self): 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 @@ def _read_header(self): 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 @@ def _read_header(self): 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 @@ def _read_header(self): 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 @@ def _read_header(self): 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 @@ def _read_header(self): (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 @@ def _unpack(self, execute=EX_CONSTRUCT): 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 @@ def tell(self): return self._stream_offset -class Packer(object): +class Packer: """ MessagePack Packer @@ -844,9 +814,9 @@ def _pack( 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 @@ def _pack_map_header(self, n): 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) diff --git a/pyproject.toml b/pyproject.toml index 195795f0..86fae1c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 diff --git a/requirements.txt b/requirements.txt index 9f3c1a0d..88b5eb97 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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 diff --git a/setup.cfg b/setup.cfg index e3782842..d6888fcf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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 diff --git a/setup.py b/setup.py index 15ba7741..1cd1e8eb 100755 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 import io import os import sys @@ -25,7 +24,7 @@ class NoCython(Exception): 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 diff --git a/test/test_buffer.py b/test/test_buffer.py index 04470584..7ee674ae 100644 --- a/test/test_buffer.py +++ b/test/test_buffer.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 import sys import pytest diff --git a/test/test_case.py b/test/test_case.py index 1c4e3229..c4c615e3 100644 --- a/test/test_case.py +++ b/test/test_case.py @@ -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", ), ] diff --git a/test/test_except.py b/test/test_except.py index 745ebecb..8c0a9766 100644 --- a/test/test_except.py +++ b/test/test_except.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 from pytest import raises from msgpack import packb, unpackb, Unpacker, FormatError, StackError, OutOfData diff --git a/test/test_extension.py b/test/test_extension.py index dfbe4350..9e5e6aad 100644 --- a/test/test_extension.py +++ b/test/test_extension.py @@ -1,4 +1,3 @@ -from __future__ import print_function import array import msgpack from msgpack import ExtType @@ -17,9 +16,7 @@ def p(s): 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 default(obj): 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) diff --git a/test/test_format.py b/test/test_format.py index fbbc3f98..c06c87dc 100644 --- a/test/test_format.py +++ b/test/test_format.py @@ -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(): diff --git a/test/test_limits.py b/test/test_limits.py index 4314c2c0..533bc112 100644 --- a/test/test_limits.py +++ b/test/test_limits.py @@ -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 ( diff --git a/test/test_memoryview.py b/test/test_memoryview.py index 63beab10..eaadef73 100644 --- a/test/test_memoryview.py +++ b/test/test_memoryview.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 import pytest from array import array diff --git a/test/test_newspec.py b/test/test_newspec.py index b7da486e..a6f4251b 100644 --- a/test/test_newspec.py +++ b/test/test_newspec.py @@ -1,5 +1,3 @@ -# coding: utf-8 - from msgpack import packb, unpackb, ExtType diff --git a/test/test_obj.py b/test/test_obj.py index 86c557cd..d3f870d9 100644 --- a/test/test_obj.py +++ b/test/test_obj.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 from pytest import raises from msgpack import packb, unpackb diff --git a/test/test_pack.py b/test/test_pack.py index 65c9cb17..2753e469 100644 --- a/test/test_pack.py +++ b/test/test_pack.py @@ -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(): diff --git a/test/test_seq.py b/test/test_seq.py index 0d5d8065..def6630d 100644 --- a/test/test_seq.py +++ b/test/test_seq.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 import io import msgpack diff --git a/test/test_sequnpack.py b/test/test_sequnpack.py index c091076b..6b138aad 100644 --- a/test/test_sequnpack.py +++ b/test/test_sequnpack.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 import io from msgpack import Unpacker, BufferFull from msgpack import pack, packb diff --git a/test/test_stricttype.py b/test/test_stricttype.py index fe9ec6cd..9ffaff25 100644 --- a/test/test_stricttype.py +++ b/test/test_stricttype.py @@ -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 convert(code, payload): 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) diff --git a/test/test_subtype.py b/test/test_subtype.py index d91d4553..d5a9adb3 100644 --- a/test/test_subtype.py +++ b/test/test_subtype.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 from msgpack import packb, unpackb from collections import namedtuple diff --git a/test/test_unpack.py b/test/test_unpack.py index c7141024..bf3f960d 100644 --- a/test/test_unpack.py +++ b/test/test_unpack.py @@ -52,7 +52,7 @@ def hook(x): 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: From e5249f877c18c88a0009f21097d7e48819579e60 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 21 Jul 2023 02:53:58 +0900 Subject: [PATCH 06/14] ci: add Python 3.12 and drop 3.7 --- .github/workflows/test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 88781025..76fcf27e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "windows-latest", "macos-latest"] - py: ["3.11", "3.10", "3.9", "3.8", "3.7"] + py: ["3.12", "3.11", "3.10", "3.9", "3.8"] runs-on: ${{ matrix.os }} name: Run test with Python ${{ matrix.py }} on ${{ matrix.os }} @@ -23,6 +23,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.py }} + allow-prereleases: true cache: "pip" - name: Build From 427736bbcc5553b0754616b58154ed26733103b6 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 21 Jul 2023 11:11:04 +0900 Subject: [PATCH 07/14] try Cython 3.0 (#548) --- pyproject.toml | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 86fae1c7..dc8bbee3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ requires = [ # Also declared in requirements.txt, if updating here please also update # there - "Cython~=0.29.30", + "Cython~=3.0.0", "setuptools >= 35.0.2", ] build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt index 88b5eb97..e27df0f4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Also declared in pyproject.toml, if updating here please also update there. -Cython~=0.29.30 +Cython~=3.0.0 # Tools required only for development. No need to add it to pyproject.toml file. black==23.3.0 From 7cfced51501b8e0786da5d6b499331ef2f492b29 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 9 Aug 2023 18:09:42 +0900 Subject: [PATCH 08/14] start v1.0.6 development --- msgpack/__init__.py | 2 +- setup.cfg | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/msgpack/__init__.py b/msgpack/__init__.py index 638236fe..2540120b 100644 --- a/msgpack/__init__.py +++ b/msgpack/__init__.py @@ -6,7 +6,7 @@ version = (1, 0, 5) -__version__ = "1.0.5" +__version__ = "1.0.6dev1" if os.environ.get("MSGPACK_PUREPYTHON"): diff --git a/setup.cfg b/setup.cfg index d6888fcf..c2e16721 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,7 @@ [metadata] name = msgpack -#version = attr: msgpack.__version__ -version = attr: msgpack.version +version = attr: msgpack.__version__ +#version = attr: msgpack.version license = Apache 2.0 author = Inada Naoki author_email = songofacandy@gmail.com @@ -17,11 +17,11 @@ project_urls = classifiers = Programming Language :: Python :: 3 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy Intended Audience :: Developers From 715126c67b2339381f5ad02f45d8fe367400c749 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 9 Aug 2023 18:20:05 +0900 Subject: [PATCH 09/14] CI: update cibuildwheel to v2.15.0 (#551) --- .github/workflows/wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wheel.yml b/.github/workflows/wheel.yml index 6cf2fe94..c1eb2ed6 100644 --- a/.github/workflows/wheel.yml +++ b/.github/workflows/wheel.yml @@ -35,7 +35,7 @@ jobs: make cython - name: Build - uses: pypa/cibuildwheel@v2.12.0 + uses: pypa/cibuildwheel@v2.15.0 env: CIBW_TEST_REQUIRES: "pytest" CIBW_TEST_COMMAND: "pytest {package}/test" From 7b75b4f36819c77a12518929fecc09d94e82f5bd Mon Sep 17 00:00:00 2001 From: TW Date: Thu, 31 Aug 2023 05:56:24 +0200 Subject: [PATCH 10/14] sphinx-related work (#554) fixes #510 --- .github/workflows/docs.yaml | 32 ++++++++++++++++++++++++++++++++ docs/_static/README.txt | 1 + docs/api.rst | 8 ++++---- docs/conf.py | 2 +- msgpack/_packer.pyx | 3 ++- msgpack/_unpacker.pyx | 6 +++--- msgpack/ext.py | 4 ++-- msgpack/fallback.py | 9 +++++---- tox.ini | 9 +++++++++ 9 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/docs.yaml create mode 100644 docs/_static/README.txt diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 00000000..a393c6b8 --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,32 @@ +name: docs + +on: ["push", "pull_request"] + +jobs: + docs: + # We want to run on external PRs, but not on our own internal PRs as they'll be run + # by the push to the branch. + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + + runs-on: ubuntu-latest + steps: + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + architecture: 'x64' + + - name: Checkout + uses: actions/checkout@v3 + + - name: Build + shell: bash + run: | + pip install -r requirements.txt + make cython + pip install . + + - name: Sphinx Documentation Generator + run: | + pip install tox + tox -e sphinx diff --git a/docs/_static/README.txt b/docs/_static/README.txt new file mode 100644 index 00000000..1c70594f --- /dev/null +++ b/docs/_static/README.txt @@ -0,0 +1 @@ +Sphinx will copy the contents of docs/_static/ directory to the build location. diff --git a/docs/api.rst b/docs/api.rst index 93827e19..f5dfbbd2 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -5,19 +5,19 @@ API reference .. autofunction:: pack -:func:`dump` is alias for :func:`pack` +``dump()`` is an alias for :func:`pack` .. autofunction:: packb -:func:`dumps` is alias for :func:`packb` +``dumps()`` is an alias for :func:`packb` .. autofunction:: unpack -:func:`load` is alias for :func:`unpack` +``load()`` is an alias for :func:`unpack` .. autofunction:: unpackb -:func:`loads` is alias for :func:`unpackb` +``loads()`` is an alias for :func:`unpackb` .. autoclass:: Packer :members: diff --git a/docs/conf.py b/docs/conf.py index 91ce77f0..1c1895c7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,7 +16,7 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) +#sys.path.insert(0, os.path.abspath('..')) # -- General configuration ----------------------------------------------------- diff --git a/msgpack/_packer.pyx b/msgpack/_packer.pyx index 074b39fc..3c398672 100644 --- a/msgpack/_packer.pyx +++ b/msgpack/_packer.pyx @@ -71,7 +71,8 @@ cdef class Packer(object): Packer's constructor has some keyword arguments: - :param callable default: + :param default: + When specified, it should be callable. Convert user type to builtin type that Packer supports. See also simplejson's document. diff --git a/msgpack/_unpacker.pyx b/msgpack/_unpacker.pyx index d5dc5ea5..56126f43 100644 --- a/msgpack/_unpacker.pyx +++ b/msgpack/_unpacker.pyx @@ -217,7 +217,7 @@ cdef class Unpacker(object): :param file_like: File-like object having `.read(n)` method. - If specified, unpacker reads serialized data from it and :meth:`feed()` is not usable. + If specified, unpacker reads serialized data from it and `.feed()` is not usable. :param int read_size: Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`) @@ -241,12 +241,12 @@ cdef class Unpacker(object): :param bool strict_map_key: If true (default), only str or bytes are accepted for map (dict) keys. - :param callable object_hook: + :param object_hook: When specified, it should be callable. Unpacker calls it with a dict argument after unpacking msgpack map. (See also simplejson) - :param callable object_pairs_hook: + :param object_pairs_hook: When specified, it should be callable. Unpacker calls it with a list of key-value pairs after unpacking msgpack map. (See also simplejson) diff --git a/msgpack/ext.py b/msgpack/ext.py index 97942949..f7f2d77d 100644 --- a/msgpack/ext.py +++ b/msgpack/ext.py @@ -120,7 +120,7 @@ def from_unix(unix_sec): """Create a Timestamp from posix timestamp in seconds. :param unix_float: Posix timestamp in seconds. - :type unix_float: int or float. + :type unix_float: int or float """ seconds = int(unix_sec // 1) nanoseconds = int((unix_sec % 1) * 10**9) @@ -154,7 +154,7 @@ def to_unix_nano(self): def to_datetime(self): """Get the timestamp as a UTC datetime. - :rtype: datetime. + :rtype: `datetime.datetime` """ utc = datetime.timezone.utc return datetime.datetime.fromtimestamp(0, utc) + datetime.timedelta(seconds=self.to_unix()) diff --git a/msgpack/fallback.py b/msgpack/fallback.py index ac1eaf4c..84b2617a 100644 --- a/msgpack/fallback.py +++ b/msgpack/fallback.py @@ -139,7 +139,7 @@ class Unpacker: :param file_like: File-like object having `.read(n)` method. - If specified, unpacker reads serialized data from it and :meth:`feed()` is not usable. + If specified, unpacker reads serialized data from it and `.feed()` is not usable. :param int read_size: Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`) @@ -163,12 +163,12 @@ class Unpacker: :param bool strict_map_key: If true (default), only str or bytes are accepted for map (dict) keys. - :param callable object_hook: + :param object_hook: When specified, it should be callable. Unpacker calls it with a dict argument after unpacking msgpack map. (See also simplejson) - :param callable object_pairs_hook: + :param object_pairs_hook: When specified, it should be callable. Unpacker calls it with a list of key-value pairs after unpacking msgpack map. (See also simplejson) @@ -616,7 +616,8 @@ class Packer: Packer's constructor has some keyword arguments: - :param callable default: + :param default: + When specified, it should be callable. Convert user type to builtin type that Packer supports. See also simplejson's document. diff --git a/tox.ini b/tox.ini index 1ef2d189..369eddcf 100644 --- a/tox.ini +++ b/tox.ini @@ -3,6 +3,7 @@ envlist = {py35,py36,py37,py38}-{c,pure}, {pypy,pypy3}-pure, py34-x86, + sphinx, isolated_build = true [testenv] @@ -27,3 +28,11 @@ commands= python -c 'import sys; print(hex(sys.maxsize))' python -c 'from msgpack import _cmsgpack' py.test + + +[testenv:sphinx] +changedir = docs +deps = + sphinx +commands = + sphinx-build -n -v -W --keep-going -b html -d {envtmpdir}/doctrees . {envtmpdir}/html From 423c6df265d0f964733b31a7e835fe91e4b8ea89 Mon Sep 17 00:00:00 2001 From: TW Date: Tue, 5 Sep 2023 03:51:04 +0200 Subject: [PATCH 11/14] move project metadata to pyproject.toml (#555) also: replace flake8 by ruff. --- docs/conf.py | 4 ++-- msgpack/__init__.py | 1 - msgpack/ext.py | 8 ++++---- msgpack/fallback.py | 2 +- pyproject.toml | 45 +++++++++++++++++++++++++++++++++++++++++ setup.cfg | 32 ----------------------------- setup.py | 2 -- test/test_buffer.py | 2 -- test/test_memoryview.py | 2 -- test/test_obj.py | 4 ++-- test/test_pack.py | 4 +--- test/test_seq.py | 2 +- test/test_subtype.py | 2 +- test/test_timestamp.py | 1 - 14 files changed, 57 insertions(+), 54 deletions(-) delete mode 100644 setup.cfg diff --git a/docs/conf.py b/docs/conf.py index 1c1895c7..6eb472af 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,11 +11,11 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. +#import os +#import sys #sys.path.insert(0, os.path.abspath('..')) # -- General configuration ----------------------------------------------------- diff --git a/msgpack/__init__.py b/msgpack/__init__.py index 2540120b..9a96c982 100644 --- a/msgpack/__init__.py +++ b/msgpack/__init__.py @@ -2,7 +2,6 @@ from .ext import ExtType, Timestamp import os -import sys version = (1, 0, 5) diff --git a/msgpack/ext.py b/msgpack/ext.py index f7f2d77d..02c2c430 100644 --- a/msgpack/ext.py +++ b/msgpack/ext.py @@ -1,6 +1,5 @@ from collections import namedtuple import datetime -import sys import struct @@ -20,8 +19,9 @@ def __new__(cls, code, data): 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 - msgpack, :func:`to_bytes` and :func:`from_bytes` are used to pack and unpack `Timestamp`. + When built with Cython, msgpack uses C methods to pack and unpack `Timestamp`. + When using pure-Python msgpack, :func:`to_bytes` and :func:`from_bytes` are used to pack and + unpack `Timestamp`. This class is immutable: Do not override seconds and nanoseconds. """ @@ -39,7 +39,7 @@ def __init__(self, seconds, nanoseconds=0): Number of nanoseconds to add to `seconds` to get fractional time. Maximum is 999_999_999. Default is 0. - Note: Negative times (before the UNIX epoch) are represented as negative seconds + positive ns. + Note: Negative times (before the UNIX epoch) are represented as neg. seconds + pos. ns. """ if not isinstance(seconds, int): raise TypeError("seconds must be an integer") diff --git a/msgpack/fallback.py b/msgpack/fallback.py index 84b2617a..a174162a 100644 --- a/msgpack/fallback.py +++ b/msgpack/fallback.py @@ -530,7 +530,7 @@ def _unpack(self, execute=EX_CONSTRUCT): 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))) - if type(key) is str: + if isinstance(key, str): key = sys.intern(key) ret[key] = self._unpack(EX_CONSTRUCT) if self._object_hook is not None: diff --git a/pyproject.toml b/pyproject.toml index dc8bbee3..f37d213c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,52 @@ requires = [ ] build-backend = "setuptools.build_meta" +[project] +name = "msgpack" +dynamic = ["version"] +license = {text="Apache 2.0"} +authors = [{name="Inada Naoki", email="songofacandy@gmail.com"}] +description = "MessagePack serializer" +readme = "README.md" +#keywords = ["python", "msgpack", "messagepack", "serializer", "serialization", "binary"] +#requires-python = ">=3.8" +classifiers = [ +# "Development Status :: 5 - Production/Stable", +# "Operating System :: OS Independent", +# "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", +] + +[project.urls] +Homepage = "https://msgpack.org/" +Documentation = "https://msgpack-python.readthedocs.io/" +Repository = "https://github.com/msgpack/msgpack-python/" +Tracker = "https://github.com/msgpack/msgpack-python/issues" +#Changelog = "https://github.com/msgpack/msgpack-python/blob/main/ChangeLog.rst" + +[tool.setuptools.dynamic] +version = {attr = "msgpack.__version__"} + [tool.black] line-length = 100 target-version = ["py37"] skip_string_normalization = true + +[tool.ruff] +line-length = 100 +target-version = "py38" +ignore = [] + +[tool.ruff.per-file-ignores] +"msgpack/__init__.py" = ["F401", "F403"] +"msgpack/fallback.py" = ["E731"] +"test/test_seq.py" = ["E501"] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index c2e16721..00000000 --- a/setup.cfg +++ /dev/null @@ -1,32 +0,0 @@ -[metadata] -name = msgpack -version = attr: msgpack.__version__ -#version = attr: msgpack.version -license = Apache 2.0 -author = Inada Naoki -author_email = songofacandy@gmail.com -description = MessagePack serializer -long_description = file: README.md -long_description_content_type = text/markdown -url = https://msgpack.org/ - -project_urls = - Documentation = https://msgpack-python.readthedocs.io/ - Source = https://github.com/msgpack/msgpack-python - Tracker = https://github.com/msgpack/msgpack-python/issues - -classifiers = - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - Programming Language :: Python :: Implementation :: CPython - Programming Language :: Python :: Implementation :: PyPy - Intended Audience :: Developers - License :: OSI Approved :: Apache Software License - -[flake8] -max_line_length = 100 - diff --git a/setup.py b/setup.py index 1cd1e8eb..7a34c8cf 100755 --- a/setup.py +++ b/setup.py @@ -1,8 +1,6 @@ #!/usr/bin/env python -import io import os import sys -from glob import glob from setuptools import setup, Extension from setuptools.command.build_ext import build_ext from setuptools.command.sdist import sdist diff --git a/test/test_buffer.py b/test/test_buffer.py index 7ee674ae..a3db339c 100644 --- a/test/test_buffer.py +++ b/test/test_buffer.py @@ -1,7 +1,5 @@ #!/usr/bin/env python -import sys -import pytest from msgpack import packb, unpackb diff --git a/test/test_memoryview.py b/test/test_memoryview.py index eaadef73..dc319a63 100644 --- a/test/test_memoryview.py +++ b/test/test_memoryview.py @@ -1,9 +1,7 @@ #!/usr/bin/env python -import pytest from array import array from msgpack import packb, unpackb -import sys def make_array(f, data): diff --git a/test/test_obj.py b/test/test_obj.py index d3f870d9..f78bf426 100644 --- a/test/test_obj.py +++ b/test/test_obj.py @@ -33,7 +33,7 @@ def test_decode_pairs_hook(): prod_sum = 1 * 2 + 3 * 4 unpacked = unpackb( packed, - object_pairs_hook=lambda l: sum(k * v for k, v in l), + object_pairs_hook=lambda lst: sum(k * v for k, v in lst), use_list=1, strict_map_key=False, ) @@ -48,7 +48,7 @@ def test_only_one_obj_hook(): def test_bad_hook(): with raises(TypeError): packed = packb([3, 1 + 2j], default=lambda o: o) - unpacked = unpackb(packed, use_list=1) + unpackb(packed, use_list=1) def _arr_to_str(arr): diff --git a/test/test_pack.py b/test/test_pack.py index 2753e469..42325378 100644 --- a/test/test_pack.py +++ b/test/test_pack.py @@ -3,12 +3,10 @@ from collections import OrderedDict from io import BytesIO import struct -import sys import pytest -from pytest import raises, xfail -from msgpack import packb, unpackb, Unpacker, Packer, pack +from msgpack import packb, unpackb, Unpacker, Packer def check(data, use_list=False): diff --git a/test/test_seq.py b/test/test_seq.py index def6630d..16d9dde4 100644 --- a/test/test_seq.py +++ b/test/test_seq.py @@ -34,7 +34,7 @@ def test_exceeding_unpacker_read_size(): read_count = 0 for idx, o in enumerate(unpacker): - assert type(o) == bytes + assert isinstance(o, bytes) assert o == gen_binary_data(idx) read_count += 1 diff --git a/test/test_subtype.py b/test/test_subtype.py index d5a9adb3..0d1c41af 100644 --- a/test/test_subtype.py +++ b/test/test_subtype.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from msgpack import packb, unpackb +from msgpack import packb from collections import namedtuple diff --git a/test/test_timestamp.py b/test/test_timestamp.py index af84a2ff..db5cc57a 100644 --- a/test/test_timestamp.py +++ b/test/test_timestamp.py @@ -1,5 +1,4 @@ import pytest -import sys import datetime import msgpack from msgpack.ext import Timestamp From ef15f4a62c25114bec1db91aa4006ae2d3a9fb53 Mon Sep 17 00:00:00 2001 From: TW Date: Thu, 7 Sep 2023 14:25:07 +0200 Subject: [PATCH 12/14] add a basic .readthedocs.yaml file (#558) --- .readthedocs.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..8b5aaf16 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,12 @@ +# Read the Docs configuration file for Sphinx projects. +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details. + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +sphinx: + configuration: docs/conf.py From 41d6239c0a3bfb1daabe1a45ffdbecf4e9aa5469 Mon Sep 17 00:00:00 2001 From: TW Date: Tue, 12 Sep 2023 19:51:12 +0200 Subject: [PATCH 13/14] fix .readthedocs.yaml, fixes #559 (#560) --- .readthedocs.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 8b5aaf16..7447895d 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -7,6 +7,17 @@ build: os: ubuntu-22.04 tools: python: "3.11" + apt_packages: + - build-essential + jobs: + pre_install: + - pip install -r requirements.txt + - make cython + +python: + install: + - method: pip + path: . sphinx: configuration: docs/conf.py From 4e10c10aaa8350f23e4b85d27ff131f7b4fd13e2 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 13 Sep 2023 18:40:04 +0900 Subject: [PATCH 14/14] prepare for 1.0.6rc1 (#557) --- ChangeLog.rst | 9 +++++++++ msgpack/__init__.py | 4 ++-- pyproject.toml | 12 ++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ChangeLog.rst b/ChangeLog.rst index 53547996..bf345ddb 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -1,3 +1,12 @@ +1.0.6rc1 +======== + +Release Date: 2023-09-13 + +* Add Python 3.12 wheels (#517) +* Remove Python 2.7, 3.6, and 3.7 support + + 1.0.5 ===== diff --git a/msgpack/__init__.py b/msgpack/__init__.py index 9a96c982..2e201330 100644 --- a/msgpack/__init__.py +++ b/msgpack/__init__.py @@ -4,8 +4,8 @@ import os -version = (1, 0, 5) -__version__ = "1.0.6dev1" +version = (1, 0, 6, "rc", 1) +__version__ = "1.0.6rc1" if os.environ.get("MSGPACK_PUREPYTHON"): diff --git a/pyproject.toml b/pyproject.toml index f37d213c..a63009a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,12 +14,12 @@ license = {text="Apache 2.0"} authors = [{name="Inada Naoki", email="songofacandy@gmail.com"}] description = "MessagePack serializer" readme = "README.md" -#keywords = ["python", "msgpack", "messagepack", "serializer", "serialization", "binary"] -#requires-python = ">=3.8" +keywords = ["msgpack", "messagepack", "serializer", "serialization", "binary"] +requires-python = ">=3.8" classifiers = [ -# "Development Status :: 5 - Production/Stable", -# "Operating System :: OS Independent", -# "Programming Language :: Python", + "Development Status :: 5 - Production/Stable", + "Operating System :: OS Independent", + "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -37,7 +37,7 @@ Homepage = "https://msgpack.org/" Documentation = "https://msgpack-python.readthedocs.io/" Repository = "https://github.com/msgpack/msgpack-python/" Tracker = "https://github.com/msgpack/msgpack-python/issues" -#Changelog = "https://github.com/msgpack/msgpack-python/blob/main/ChangeLog.rst" +Changelog = "https://github.com/msgpack/msgpack-python/blob/main/ChangeLog.rst" [tool.setuptools.dynamic] version = {attr = "msgpack.__version__"}