Drop python2 support (#519)

The PR removes python2 references and cases.

Close #518

Co-authored-by: Inada Naoki <songofacandy@gmail.com>
This commit is contained in:
sblondon 2023-05-21 09:26:39 +02:00 committed by GitHub
parent 45f848695c
commit feec06206c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 58 additions and 143 deletions

View file

@ -220,9 +220,9 @@ and `raw=True` options.
```pycon ```pycon
>>> import msgpack >>> 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'] [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'] [b'spam', 'eggs']
``` ```

View file

@ -40,8 +40,8 @@ source_suffix = ".rst"
master_doc = "index" master_doc = "index"
# General information about the project. # General information about the project.
project = u"msgpack" project = "msgpack"
copyright = u"Inada Naoki" copyright = "Inada Naoki"
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@ -181,7 +181,7 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]). # (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [ 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 # The name of an image file (relative to this directory) to place at the top of
@ -209,7 +209,7 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (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. # If true, show URL addresses after external links.
# man_show_urls = False # man_show_urls = False
@ -224,8 +224,8 @@ texinfo_documents = [
( (
"index", "index",
"msgpack", "msgpack",
u"msgpack Documentation", "msgpack Documentation",
u"Author", "Author",
"msgpack", "msgpack",
"One line description of project.", "One line description of project.",
"Miscellaneous", "Miscellaneous",
@ -245,10 +245,10 @@ texinfo_documents = [
# -- Options for Epub output --------------------------------------------------- # -- Options for Epub output ---------------------------------------------------
# Bibliographic Dublin Core info. # Bibliographic Dublin Core info.
epub_title = u"msgpack" epub_title = "msgpack"
epub_author = u"Author" epub_author = "Author"
epub_publisher = u"Author" epub_publisher = "Author"
epub_copyright = u"2013, Author" epub_copyright = "2013, Author"
# The language of the text. It defaults to the language option # The language of the text. It defaults to the language option
# or en if the language is not set. # or en if the language is not set.

View file

@ -10,7 +10,7 @@ version = (1, 0, 5)
__version__ = "1.0.5" __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 from .fallback import Packer, unpackb, Unpacker
else: else:
try: try:

View file

@ -98,7 +98,6 @@ cdef class Packer(object):
If set to true, datetime with tzinfo is packed into Timestamp type. If set to true, datetime with tzinfo is packed into Timestamp type.
Note that the tzinfo is stripped in the timestamp. Note that the tzinfo is stripped in the timestamp.
You can get UTC datetime with `timestamp=3` option of the Unpacker. You can get UTC datetime with `timestamp=3` option of the Unpacker.
(Python 2 is not supported).
:param str unicode_errors: :param str unicode_errors:
The error handler for encoding unicode. (default: 'strict') The error handler for encoding unicode. (default: 'strict')

View file

@ -236,7 +236,7 @@ cdef class Unpacker(object):
0 - Timestamp 0 - Timestamp
1 - float (Seconds from the EPOCH) 1 - float (Seconds from the EPOCH)
2 - int (Nanoseconds 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: :param bool strict_map_key:
If true (default), only str or bytes are accepted for map (dict) keys. If true (default), only str or bytes are accepted for map (dict) keys.

View file

@ -5,19 +5,6 @@ import sys
import struct 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")): class ExtType(namedtuple("ExtType", "code data")):
"""ExtType represents ext type in msgpack.""" """ExtType represents ext type in msgpack."""
@ -55,9 +42,9 @@ class Timestamp(object):
Note: Negative times (before the UNIX epoch) are represented as negative seconds + positive ns. 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") 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") raise TypeError("nanoseconds must be an integer")
if not (0 <= nanoseconds < 10**9): if not (0 <= nanoseconds < 10**9):
raise ValueError( raise ValueError(
@ -174,11 +161,10 @@ class Timestamp(object):
def to_datetime(self): def to_datetime(self):
"""Get the timestamp as a UTC datetime. """Get the timestamp as a UTC datetime.
Python 2 is not supported.
:rtype: datetime. :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() seconds=self.to_unix()
) )
@ -186,8 +172,6 @@ class Timestamp(object):
def from_datetime(dt): def from_datetime(dt):
"""Create a Timestamp from datetime with tzinfo. """Create a Timestamp from datetime with tzinfo.
Python 2 is not supported.
:rtype: Timestamp :rtype: Timestamp
""" """
return Timestamp.from_unix(dt.timestamp()) return Timestamp.from_unix(dt.timestamp())

View file

@ -4,22 +4,6 @@ import sys
import struct 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): if sys.version_info < (3, 5):
# Ugly hack... # Ugly hack...
RecursionError = RuntimeError RecursionError = RuntimeError
@ -134,15 +118,6 @@ def unpackb(packed, **kwargs):
return ret 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 = "" _NO_FORMAT_USED = ""
_MSGPACK_HEADERS = { _MSGPACK_HEADERS = {
0xC4: (1, _NO_FORMAT_USED, TYPE_BIN), 0xC4: (1, _NO_FORMAT_USED, TYPE_BIN),
@ -202,7 +177,7 @@ class Unpacker(object):
0 - Timestamp 0 - Timestamp
1 - float (Seconds from the EPOCH) 1 - float (Seconds from the EPOCH)
2 - int (Nanoseconds 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: :param bool strict_map_key:
If true (default), only str or bytes are accepted for map (dict) keys. If true (default), only str or bytes are accepted for map (dict) keys.
@ -477,7 +452,7 @@ class Unpacker(object):
size, fmt, typ = _MSGPACK_HEADERS[b] size, fmt, typ = _MSGPACK_HEADERS[b]
self._reserve(size) self._reserve(size)
if len(fmt) > 0: 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: else:
n = self._buffer[self._buff_i] n = self._buffer[self._buff_i]
self._buff_i += size self._buff_i += size
@ -487,7 +462,7 @@ class Unpacker(object):
elif 0xC7 <= b <= 0xC9: elif 0xC7 <= b <= 0xC9:
size, fmt, typ = _MSGPACK_HEADERS[b] size, fmt, typ = _MSGPACK_HEADERS[b]
self._reserve(size) 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 self._buff_i += size
if L > self._max_ext_len: if L > self._max_ext_len:
raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len))
@ -496,7 +471,7 @@ class Unpacker(object):
size, fmt = _MSGPACK_HEADERS[b] size, fmt = _MSGPACK_HEADERS[b]
self._reserve(size) self._reserve(size)
if len(fmt) > 0: 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: else:
obj = self._buffer[self._buff_i] obj = self._buffer[self._buff_i]
self._buff_i += size self._buff_i += size
@ -507,13 +482,13 @@ class Unpacker(object):
"%s exceeds max_ext_len(%s)" % (size, self._max_ext_len) "%s exceeds max_ext_len(%s)" % (size, self._max_ext_len)
) )
self._reserve(size + 1) 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 self._buff_i += size + 1
elif 0xD9 <= b <= 0xDB: elif 0xD9 <= b <= 0xDB:
size, fmt, typ = _MSGPACK_HEADERS[b] size, fmt, typ = _MSGPACK_HEADERS[b]
self._reserve(size) self._reserve(size)
if len(fmt) > 0: if len(fmt) > 0:
(n,) = _unpack_from(fmt, self._buffer, self._buff_i) (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i)
else: else:
n = self._buffer[self._buff_i] n = self._buffer[self._buff_i]
self._buff_i += size self._buff_i += size
@ -523,7 +498,7 @@ class Unpacker(object):
elif 0xDC <= b <= 0xDD: elif 0xDC <= b <= 0xDD:
size, fmt, typ = _MSGPACK_HEADERS[b] size, fmt, typ = _MSGPACK_HEADERS[b]
self._reserve(size) 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 self._buff_i += size
if n > self._max_array_len: if n > self._max_array_len:
raise ValueError( raise ValueError(
@ -532,7 +507,7 @@ class Unpacker(object):
elif 0xDE <= b <= 0xDF: elif 0xDE <= b <= 0xDF:
size, fmt, typ = _MSGPACK_HEADERS[b] size, fmt, typ = _MSGPACK_HEADERS[b]
self._reserve(size) 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 self._buff_i += size
if n > self._max_map_len: if n > self._max_map_len:
raise ValueError("%s exceeds max_map_len(%s)" % (n, self._max_map_len)) raise ValueError("%s exceeds max_map_len(%s)" % (n, self._max_map_len))
@ -554,12 +529,12 @@ class Unpacker(object):
# TODO should we eliminate the recursion? # TODO should we eliminate the recursion?
if typ == TYPE_ARRAY: if typ == TYPE_ARRAY:
if execute == EX_SKIP: if execute == EX_SKIP:
for i in xrange(n): for i in range(n):
# TODO check whether we need to call `list_hook` # TODO check whether we need to call `list_hook`
self._unpack(EX_SKIP) self._unpack(EX_SKIP)
return return
ret = newlist_hint(n) ret = newlist_hint(n)
for i in xrange(n): for i in range(n):
ret.append(self._unpack(EX_CONSTRUCT)) ret.append(self._unpack(EX_CONSTRUCT))
if self._list_hook is not None: if self._list_hook is not None:
ret = self._list_hook(ret) ret = self._list_hook(ret)
@ -567,7 +542,7 @@ class Unpacker(object):
return ret if self._use_list else tuple(ret) return ret if self._use_list else tuple(ret)
if typ == TYPE_MAP: if typ == TYPE_MAP:
if execute == EX_SKIP: if execute == EX_SKIP:
for i in xrange(n): for i in range(n):
# TODO check whether we need to call hooks # TODO check whether we need to call hooks
self._unpack(EX_SKIP) self._unpack(EX_SKIP)
self._unpack(EX_SKIP) self._unpack(EX_SKIP)
@ -575,17 +550,17 @@ class Unpacker(object):
if self._object_pairs_hook is not None: if self._object_pairs_hook is not None:
ret = self._object_pairs_hook( ret = self._object_pairs_hook(
(self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT)) (self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT))
for _ in xrange(n) for _ in range(n)
) )
else: else:
ret = {} ret = {}
for _ in xrange(n): for _ in range(n):
key = self._unpack(EX_CONSTRUCT) 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( raise ValueError(
"%s is not allowed for map key" % str(type(key)) "%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) key = sys.intern(key)
ret[key] = self._unpack(EX_CONSTRUCT) ret[key] = self._unpack(EX_CONSTRUCT)
if self._object_hook is not None: 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. If set to true, datetime with tzinfo is packed into Timestamp type.
Note that the tzinfo is stripped in the timestamp. Note that the tzinfo is stripped in the timestamp.
You can get UTC datetime with `timestamp=3` option of the Unpacker. You can get UTC datetime with `timestamp=3` option of the Unpacker.
(Python 2 is not supported).
:param str unicode_errors: :param str unicode_errors:
The error handler for encoding unicode. (default: 'strict') The error handler for encoding unicode. (default: 'strict')
@ -743,8 +717,6 @@ class Packer(object):
self._autoreset = autoreset self._autoreset = autoreset
self._use_bin_type = use_bin_type self._use_bin_type = use_bin_type
self._buffer = StringIO() self._buffer = StringIO()
if PY2 and datetime:
raise ValueError("datetime is not supported in Python 2")
self._datetime = bool(datetime) self._datetime = bool(datetime)
self._unicode_errors = unicode_errors or "strict" self._unicode_errors = unicode_errors or "strict"
if default is not None: if default is not None:
@ -774,7 +746,7 @@ class Packer(object):
if obj: if obj:
return self._buffer.write(b"\xc3") return self._buffer.write(b"\xc3")
return self._buffer.write(b"\xc2") return self._buffer.write(b"\xc2")
if check(obj, int_types): if check(obj, int):
if 0 <= obj < 0x80: if 0 <= obj < 0x80:
return self._buffer.write(struct.pack("B", obj)) return self._buffer.write(struct.pack("B", obj))
if -0x20 <= obj < 0: if -0x20 <= obj < 0:
@ -806,7 +778,7 @@ class Packer(object):
raise ValueError("%s is too large" % type(obj).__name__) raise ValueError("%s is too large" % type(obj).__name__)
self._pack_bin_header(n) self._pack_bin_header(n)
return self._buffer.write(obj) return self._buffer.write(obj)
if check(obj, unicode): if check(obj, str):
obj = obj.encode("utf-8", self._unicode_errors) obj = obj.encode("utf-8", self._unicode_errors)
n = len(obj) n = len(obj)
if n >= 2**32: if n >= 2**32:
@ -855,13 +827,11 @@ class Packer(object):
if check(obj, list_types): if check(obj, list_types):
n = len(obj) n = len(obj)
self._pack_array_header(n) self._pack_array_header(n)
for i in xrange(n): for i in range(n):
self._pack(obj[i], nest_limit - 1) self._pack(obj[i], nest_limit - 1)
return return
if check(obj, dict): if check(obj, dict):
return self._pack_map_pairs( return self._pack_map_pairs(len(obj), obj.items(), nest_limit - 1)
len(obj), dict_iteritems(obj), nest_limit - 1
)
if self._datetime and check(obj, _DateTime) and obj.tzinfo is not None: if self._datetime and check(obj, _DateTime) and obj.tzinfo is not None:
obj = Timestamp.from_datetime(obj) obj = Timestamp.from_datetime(obj)
@ -1004,7 +974,7 @@ class Packer(object):
def getbuffer(self): def getbuffer(self):
"""Return view of internal buffer.""" """Return view of internal buffer."""
if USING_STRINGBUILDER or PY2: if USING_STRINGBUILDER:
return memoryview(self.bytes()) return memoryview(self.bytes())
else: else:
return self._buffer.getbuffer() return self._buffer.getbuffer()

View file

@ -10,7 +10,6 @@ from setuptools.command.sdist import sdist
PYPY = hasattr(sys, "pypy_version_info") PYPY = hasattr(sys, "pypy_version_info")
PY2 = sys.version_info[0] == 2
class NoCython(Exception): class NoCython(Exception):
@ -79,7 +78,7 @@ if sys.platform == "win32":
macros = [("__LITTLE_ENDIAN__", "1")] macros = [("__LITTLE_ENDIAN__", "1")]
ext_modules = [] 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( ext_modules.append(
Extension( Extension(
"msgpack._cmsgpack", "msgpack._cmsgpack",

View file

@ -6,7 +6,6 @@ import pytest
from msgpack import packb, unpackb from msgpack import packb, unpackb
@pytest.mark.skipif(sys.version_info[0] == 2, reason="Python 2 is not supported")
def test_unpack_buffer(): def test_unpack_buffer():
from array import array from array import array

View file

@ -134,4 +134,4 @@ def test_match():
def test_unicode(): def test_unicode():
assert unpackb(packb(u"foobar"), use_list=1) == u"foobar" assert unpackb(packb("foobar"), use_list=1) == "foobar"

View file

@ -53,7 +53,7 @@ def test_invalidvalue():
def test_strict_map_key(): 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) packed = packb(valid, use_bin_type=True)
assert valid == unpackb(packed, raw=False, strict_map_key=True) assert valid == unpackb(packed, raw=False, strict_map_key=True)

View file

@ -55,10 +55,7 @@ def test_extension_type():
print("ext_hook called", code, data) print("ext_hook called", code, data)
assert code == 123 assert code == 123
obj = array.array("d") obj = array.array("d")
try: obj.frombytes(data)
obj.frombytes(data)
except AttributeError: # PY2
obj.fromstring(data)
return obj return obj
obj = [42, b"hello", array.array("d", [1.1, 2.2, 3.3])] obj = [42, b"hello", array.array("d", [1.1, 2.2, 3.3])]
@ -67,20 +64,14 @@ def test_extension_type():
assert obj == obj2 assert obj == obj2
import sys
if sys.version > "3":
long = int
def test_overriding_hooks(): def test_overriding_hooks():
def default(obj): def default(obj):
if isinstance(obj, long): if isinstance(obj, int):
return {"__type__": "long", "__data__": str(obj)} return {"__type__": "long", "__data__": str(obj)}
else: else:
return obj return obj
obj = {"testval": long(1823746192837461928374619)} obj = {"testval": 1823746192837461928374619}
refobj = {"testval": default(obj["testval"])} refobj = {"testval": default(obj["testval"])}
refout = msgpack.packb(refobj) refout = msgpack.packb(refobj)
assert isinstance(refout, (str, bytes)) assert isinstance(refout, (str, bytes))

View file

@ -7,11 +7,6 @@ from msgpack import packb, unpackb
import sys import sys
pytestmark = pytest.mark.skipif(
sys.version_info[0] < 3, reason="Only Python 3 supports buffer protocol"
)
def make_array(f, data): def make_array(f, data):
a = array(f) a = array(f)
a.frombytes(data) a.frombytes(data)

View file

@ -80,9 +80,6 @@ def testPackByteArrays():
check(td) check(td)
@pytest.mark.skipif(
sys.version_info < (3, 0), reason="Python 2 passes invalid surrogates"
)
def testIgnoreUnicodeErrors(): def testIgnoreUnicodeErrors():
re = unpackb( re = unpackb(
packb(b"abc\xeddef", use_bin_type=False), raw=False, unicode_errors="ignore" 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) unpackb(packed, raw=False, use_list=1)
@pytest.mark.skipif(
sys.version_info < (3, 0), reason="Python 2 passes invalid surrogates"
)
def testIgnoreErrorsPack(): def testIgnoreErrorsPack():
re = unpackb( re = unpackb(
packb("abc\uDC80\uDCFFdef", use_bin_type=True, unicode_errors="ignore"), packb("abc\uDC80\uDCFFdef", use_bin_type=True, unicode_errors="ignore"),

View file

@ -4,9 +4,6 @@ import datetime
import msgpack import msgpack
from msgpack.ext import Timestamp from msgpack.ext import Timestamp
if sys.version_info[0] > 2:
from msgpack.ext import _utc
def test_timestamp(): def test_timestamp():
# timestamp32 # timestamp32
@ -85,33 +82,33 @@ def test_timestamp_to():
assert t.to_unix_nano() == 42000014000 assert t.to_unix_nano() == 42000014000
@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only")
def test_timestamp_datetime(): def test_timestamp_datetime():
t = Timestamp(42, 14) 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(): def test_unpack_datetime():
t = Timestamp(42, 14) t = Timestamp(42, 14)
utc = datetime.timezone.utc
packed = msgpack.packb(t) packed = msgpack.packb(t)
unpacked = msgpack.unpackb(packed, timestamp=3) 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(): 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) packed = msgpack.packb(t_in, datetime=True)
unpacked = msgpack.unpackb(packed, timestamp=3) unpacked = msgpack.unpackb(packed, timestamp=3)
assert unpacked == t_in assert unpacked == t_in
@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only")
def test_pack_datetime(): def test_pack_datetime():
t = Timestamp(42, 14000) t = Timestamp(42, 14000)
dt = t.to_datetime() 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) packed = msgpack.packb(dt, datetime=True)
packed2 = msgpack.packb(t) packed2 = msgpack.packb(t)
@ -131,10 +128,10 @@ def test_pack_datetime():
assert msgpack.unpackb(packed) is None assert msgpack.unpackb(packed) is None
@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only")
def test_issue451(): def test_issue451():
# https://github.com/msgpack/msgpack-python/issues/451 # 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) packed = msgpack.packb(dt, datetime=True)
assert packed == b"\xd6\xff\xf4\x86eL" assert packed == b"\xd6\xff\xf4\x86eL"
@ -142,7 +139,6 @@ def test_issue451():
assert dt == unpacked assert dt == unpacked
@pytest.mark.skipif(sys.version_info[0] == 2, reason="datetime support is PY3+ only")
def test_pack_datetime_without_tzinfo(): def test_pack_datetime_without_tzinfo():
dt = datetime.datetime(1970, 1, 1, 0, 0, 42, 14) dt = datetime.datetime(1970, 1, 1, 0, 0, 42, 14)
with pytest.raises(ValueError, match="where tzinfo=None"): 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) packed = msgpack.packb(dt, datetime=True, default=lambda x: None)
assert packed == msgpack.packb(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) packed = msgpack.packb(dt, datetime=True)
unpacked = msgpack.unpackb(packed, timestamp=3) unpacked = msgpack.unpackb(packed, timestamp=3)
assert unpacked == dt assert unpacked == dt

View file

@ -70,7 +70,7 @@ def test_unpacker_ext_hook():
def test_unpacker_tell(): 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" packed = b"\x01\x02\xa3abc\xa3def\xa3ghi"
positions = 1, 2, 6, 10, 14 positions = 1, 2, 6, 10, 14
unpacker = Unpacker(BytesIO(packed)) unpacker = Unpacker(BytesIO(packed))
@ -80,7 +80,7 @@ def test_unpacker_tell():
def test_unpacker_tell_read_bytes(): def test_unpacker_tell_read_bytes():
objects = 1, u"abc", u"ghi" objects = 1, "abc", "ghi"
packed = b"\x01\x02\xa3abc\xa3def\xa3ghi" packed = b"\x01\x02\xa3abc\xa3def\xa3ghi"
raw_data = b"\x02", b"\xa3def", b"" raw_data = b"\x02", b"\xa3def", b""
lenghts = 1, 4, 999 lenghts = 1, 4, 999

13
tox.ini
View file

@ -1,9 +1,7 @@
[tox] [tox]
envlist = envlist =
py27-pure,
{py35,py36,py37,py38}-{c,pure}, {py35,py36,py37,py38}-{c,pure},
{pypy,pypy3}-pure, {pypy,pypy3}-pure,
py27-x86,
py34-x86, py34-x86,
isolated_build = true isolated_build = true
@ -19,17 +17,6 @@ commands=
setenv= setenv=
pure: MSGPACK_PUREPYTHON=x 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] [testenv:py34-x86]
basepython=python3.4-x86 basepython=python3.4-x86
deps= deps=