| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  | # coding: utf-8 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-03 03:11:00 +09:00
										 |  |  | from cpython cimport * | 
					
						
							| 
									
										
										
										
											2018-11-14 16:35:37 +09:00
										 |  |  | from cpython.bytearray cimport PyByteArray_Check, PyByteArray_CheckExact | 
					
						
							| 
									
										
										
										
											2019-12-11 23:48:16 +09:00
										 |  |  | from cpython.datetime cimport ( | 
					
						
							|  |  |  |     PyDateTime_CheckExact, PyDelta_CheckExact, | 
					
						
							|  |  |  |     datetime_tzinfo, timedelta_days, timedelta_seconds, timedelta_microseconds, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2012-07-13 21:28:16 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-18 18:15:09 +02:00
										 |  |  | cdef ExtType | 
					
						
							| 
									
										
										
										
											2019-12-05 18:29:15 +09:00
										 |  |  | cdef Timestamp | 
					
						
							| 
									
										
										
										
											2019-09-18 18:15:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-05 18:29:15 +09:00
										 |  |  | from .ext import ExtType, Timestamp | 
					
						
							| 
									
										
										
										
											2013-10-20 20:28:32 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-13 21:28:16 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-12 11:49:19 +01:00
										 |  |  | cdef extern from "Python.h": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int PyMemoryView_Check(object obj) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 00:23:38 +09:00
										 |  |  | cdef extern from "pack.h": | 
					
						
							| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  |     struct msgpack_packer: | 
					
						
							| 
									
										
										
										
											2009-07-01 00:57:46 +09:00
										 |  |  |         char* buf | 
					
						
							|  |  |  |         size_t length | 
					
						
							|  |  |  |         size_t buf_size | 
					
						
							| 
									
										
										
										
											2013-10-17 08:44:25 +09:00
										 |  |  |         bint use_bin_type | 
					
						
							| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |     int msgpack_pack_nil(msgpack_packer* pk) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_true(msgpack_packer* pk) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_false(msgpack_packer* pk) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_long_long(msgpack_packer* pk, long long d) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_unsigned_long_long(msgpack_packer* pk, unsigned long long d) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_float(msgpack_packer* pk, float d) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_double(msgpack_packer* pk, double d) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_array(msgpack_packer* pk, size_t l) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_map(msgpack_packer* pk, size_t l) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_raw(msgpack_packer* pk, size_t l) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_bin(msgpack_packer* pk, size_t l) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_raw_body(msgpack_packer* pk, char* body, size_t l) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_ext(msgpack_packer* pk, char typecode, size_t l) except -1 | 
					
						
							|  |  |  |     int msgpack_pack_timestamp(msgpack_packer* x, long long seconds, unsigned long nanoseconds) except -1 | 
					
						
							| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 20:55:13 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-26 02:09:52 +09:00
										 |  |  | cdef int DEFAULT_RECURSE_LIMIT=511 | 
					
						
							| 
									
										
										
										
											2018-01-11 17:02:41 +09:00
										 |  |  | cdef long long ITEM_LIMIT = (2**32)-1 | 
					
						
							| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-13 21:28:16 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-18 13:03:15 +02:00
										 |  |  | cdef inline int PyBytesLike_Check(object o): | 
					
						
							|  |  |  |     return PyBytes_Check(o) or PyByteArray_Check(o) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cdef inline int PyBytesLike_CheckExact(object o): | 
					
						
							|  |  |  |     return PyBytes_CheckExact(o) or PyByteArray_CheckExact(o) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 00:49:12 +09:00
										 |  |  | cdef class Packer: | 
					
						
							| 
									
										
										
										
											2013-02-26 09:20:44 +09:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     MessagePack Packer | 
					
						
							| 
									
										
										
										
											2011-04-15 17:36:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-04 17:23:09 +09:00
										 |  |  |     Usage:: | 
					
						
							| 
									
										
										
										
											2009-06-08 01:30:43 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-01 20:55:24 +09:00
										 |  |  |         packer = Packer() | 
					
						
							|  |  |  |         astream.write(packer.pack(a)) | 
					
						
							|  |  |  |         astream.write(packer.pack(b)) | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Packer's constructor has some keyword arguments: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-31 05:56:24 +02:00
										 |  |  |     :param default: | 
					
						
							|  |  |  |         When specified, it should be callable. | 
					
						
							| 
									
										
										
										
											2013-02-26 09:20:44 +09:00
										 |  |  |         Convert user type to builtin type that Packer supports. | 
					
						
							|  |  |  |         See also simplejson's document. | 
					
						
							| 
									
										
										
										
											2018-01-10 02:54:59 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-26 09:20:44 +09:00
										 |  |  |     :param bool use_single_float: | 
					
						
							|  |  |  |         Use single precision float type for float. (default: False) | 
					
						
							| 
									
										
										
										
											2018-01-10 02:54:59 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-26 09:20:44 +09:00
										 |  |  |     :param bool autoreset: | 
					
						
							| 
									
										
										
										
											2017-01-11 04:04:23 +01:00
										 |  |  |         Reset buffer after each pack and return its content as `bytes`. (default: True). | 
					
						
							| 
									
										
										
										
											2013-02-26 09:20:44 +09:00
										 |  |  |         If set this to false, use `bytes()` to get content and `.reset()` to clear buffer. | 
					
						
							| 
									
										
										
										
											2018-01-10 02:54:59 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 08:35:08 +09:00
										 |  |  |     :param bool use_bin_type: | 
					
						
							|  |  |  |         Use bin type introduced in msgpack spec 2.0 for bytes. | 
					
						
							| 
									
										
										
										
											2019-12-05 21:34:10 +09:00
										 |  |  |         It also enables str8 type for unicode. (default: True) | 
					
						
							| 
									
										
										
										
											2018-01-10 02:54:59 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 03:37:54 +09:00
										 |  |  |     :param bool strict_types: | 
					
						
							|  |  |  |         If set to true, types will be checked to be exact. Derived classes | 
					
						
							|  |  |  |         from serializeable types will not be serialized and will be | 
					
						
							|  |  |  |         treated as unsupported type and forwarded to default. | 
					
						
							|  |  |  |         Additionally tuples will not be serialized as lists. | 
					
						
							|  |  |  |         This is useful when trying to implement accurate serialization | 
					
						
							|  |  |  |         for python types. | 
					
						
							| 
									
										
										
										
											2019-12-03 20:53:11 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-04 17:23:09 +09:00
										 |  |  |     :param bool datetime: | 
					
						
							|  |  |  |         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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-03 20:53:11 +09:00
										 |  |  |     :param str unicode_errors: | 
					
						
							|  |  |  |         The error handler for encoding unicode. (default: 'strict') | 
					
						
							|  |  |  |         DO NOT USE THIS!!  This option is kept for very specific usage. | 
					
						
							| 
									
										
										
										
											2024-05-06 00:49:12 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     :param int buf_size: | 
					
						
							|  |  |  |         The size of the internal buffer. (default: 256*1024) | 
					
						
							|  |  |  |         Useful if serialisation size can be correctly estimated, | 
					
						
							|  |  |  |         avoid unnecessary reallocations. | 
					
						
							| 
									
										
										
										
											2009-06-08 01:30:43 +09:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  |     cdef msgpack_packer pk | 
					
						
							| 
									
										
										
										
											2011-01-29 07:27:10 +09:00
										 |  |  |     cdef object _default | 
					
						
							| 
									
										
										
										
											2019-12-03 20:53:11 +09:00
										 |  |  |     cdef object _berrors | 
					
						
							|  |  |  |     cdef const char *unicode_errors | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |     cdef size_t exports  # number of exported buffers | 
					
						
							| 
									
										
										
										
											2015-11-10 03:30:11 +09:00
										 |  |  |     cdef bint strict_types | 
					
						
							| 
									
										
										
										
											2019-12-11 23:48:16 +09:00
										 |  |  |     cdef bint use_float | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  |     cdef bint autoreset | 
					
						
							| 
									
										
										
										
											2019-12-11 23:48:16 +09:00
										 |  |  |     cdef bint datetime | 
					
						
							| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 00:49:12 +09:00
										 |  |  |     def __cinit__(self, buf_size=256*1024, **_kwargs): | 
					
						
							| 
									
										
										
										
											2016-04-30 17:07:14 +09:00
										 |  |  |         self.pk.buf = <char*> PyMem_Malloc(buf_size) | 
					
						
							| 
									
										
										
										
											2011-01-10 20:47:23 +09:00
										 |  |  |         if self.pk.buf == NULL: | 
					
						
							|  |  |  |             raise MemoryError("Unable to allocate internal buffer.") | 
					
						
							| 
									
										
										
										
											2009-07-01 00:57:46 +09:00
										 |  |  |         self.pk.buf_size = buf_size | 
					
						
							|  |  |  |         self.pk.length = 0 | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self.exports = 0 | 
					
						
							| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |     def __dealloc__(self): | 
					
						
							|  |  |  |         PyMem_Free(self.pk.buf) | 
					
						
							|  |  |  |         self.pk.buf = NULL | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         assert self.exports == 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cdef _check_exports(self): | 
					
						
							|  |  |  |         if self.exports > 0: | 
					
						
							|  |  |  |             raise BufferError("Existing exports of data: Packer cannot be changed") | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-11 23:48:16 +09:00
										 |  |  |     def __init__(self, *, default=None, | 
					
						
							| 
									
										
										
										
											2019-12-05 21:34:10 +09:00
										 |  |  |                  bint use_single_float=False, bint autoreset=True, bint use_bin_type=True, | 
					
						
							| 
									
										
										
										
											2024-05-06 00:49:12 +09:00
										 |  |  |                  bint strict_types=False, bint datetime=False, unicode_errors=None, | 
					
						
							|  |  |  |                  buf_size=256*1024): | 
					
						
							| 
									
										
										
										
											2012-09-21 14:08:34 +09:00
										 |  |  |         self.use_float = use_single_float | 
					
						
							| 
									
										
										
										
											2015-11-10 03:30:11 +09:00
										 |  |  |         self.strict_types = strict_types | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  |         self.autoreset = autoreset | 
					
						
							| 
									
										
										
										
											2019-12-11 23:48:16 +09:00
										 |  |  |         self.datetime = datetime | 
					
						
							| 
									
										
										
										
											2018-01-10 02:54:59 +09:00
										 |  |  |         self.pk.use_bin_type = use_bin_type | 
					
						
							| 
									
										
										
										
											2010-10-26 01:26:06 +09:00
										 |  |  |         if default is not None: | 
					
						
							|  |  |  |             if not PyCallable_Check(default): | 
					
						
							|  |  |  |                 raise TypeError("default must be a callable.") | 
					
						
							| 
									
										
										
										
											2011-01-29 07:27:10 +09:00
										 |  |  |         self._default = default | 
					
						
							| 
									
										
										
										
											2018-02-05 11:44:17 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-03 20:53:11 +09:00
										 |  |  |         self._berrors = unicode_errors | 
					
						
							|  |  |  |         if unicode_errors is None: | 
					
						
							|  |  |  |             self.unicode_errors = NULL | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.unicode_errors = self._berrors | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |     # returns -2 when default should(o) be called | 
					
						
							|  |  |  |     cdef int _pack_inner(self, object o, bint will_default, int nest_limit) except -1: | 
					
						
							| 
									
										
										
										
											2009-06-28 21:24:02 +09:00
										 |  |  |         cdef long long llval | 
					
						
							| 
									
										
										
										
											2009-06-29 10:09:04 +09:00
										 |  |  |         cdef unsigned long long ullval | 
					
						
							| 
									
										
										
										
											2019-12-05 18:29:15 +09:00
										 |  |  |         cdef unsigned long ulval | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |         cdef const char* rawval | 
					
						
							| 
									
										
										
										
											2018-01-11 17:02:41 +09:00
										 |  |  |         cdef Py_ssize_t L | 
					
						
							| 
									
										
										
										
											2015-11-12 11:49:19 +01:00
										 |  |  |         cdef Py_buffer view | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         cdef bint strict = self.strict_types | 
					
						
							| 
									
										
										
										
											2009-05-22 14:31:20 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |         if o is None: | 
					
						
							|  |  |  |             msgpack_pack_nil(&self.pk) | 
					
						
							|  |  |  |         elif o is True: | 
					
						
							|  |  |  |             msgpack_pack_true(&self.pk) | 
					
						
							|  |  |  |         elif o is False: | 
					
						
							|  |  |  |             msgpack_pack_false(&self.pk) | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         elif PyLong_CheckExact(o) if strict else PyLong_Check(o): | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 if o > 0: | 
					
						
							|  |  |  |                     ullval = o | 
					
						
							|  |  |  |                     msgpack_pack_unsigned_long_long(&self.pk, ullval) | 
					
						
							| 
									
										
										
										
											2013-10-20 20:28:32 +09:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |                     llval = o | 
					
						
							|  |  |  |                     msgpack_pack_long_long(&self.pk, llval) | 
					
						
							|  |  |  |             except OverflowError as oe: | 
					
						
							|  |  |  |                 if will_default: | 
					
						
							|  |  |  |                     return -2 | 
					
						
							| 
									
										
										
										
											2019-12-03 20:53:11 +09:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |                     raise OverflowError("Integer value out of range") | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         elif PyFloat_CheckExact(o) if strict else PyFloat_Check(o): | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |             if self.use_float: | 
					
						
							|  |  |  |                 msgpack_pack_float(&self.pk, <float>o) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 msgpack_pack_double(&self.pk, <double>o) | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         elif PyBytesLike_CheckExact(o) if strict else PyBytesLike_Check(o): | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |             L = Py_SIZE(o) | 
					
						
							|  |  |  |             if L > ITEM_LIMIT: | 
					
						
							|  |  |  |                 PyErr_Format(ValueError, b"%.200s object is too large", Py_TYPE(o).tp_name) | 
					
						
							|  |  |  |             rawval = o | 
					
						
							|  |  |  |             msgpack_pack_bin(&self.pk, L) | 
					
						
							|  |  |  |             msgpack_pack_raw_body(&self.pk, rawval, L) | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         elif PyUnicode_CheckExact(o) if strict else PyUnicode_Check(o): | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |             if self.unicode_errors == NULL: | 
					
						
							|  |  |  |                 rawval = PyUnicode_AsUTF8AndSize(o, &L) | 
					
						
							|  |  |  |                 if L >ITEM_LIMIT: | 
					
						
							|  |  |  |                     raise ValueError("unicode string is too large") | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 o = PyUnicode_AsEncodedString(o, NULL, self.unicode_errors) | 
					
						
							| 
									
										
										
										
											2019-09-19 13:20:57 +09:00
										 |  |  |                 L = Py_SIZE(o) | 
					
						
							| 
									
										
										
										
											2016-04-28 15:08:28 +02:00
										 |  |  |                 if L > ITEM_LIMIT: | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |                     raise ValueError("unicode string is too large") | 
					
						
							|  |  |  |                 rawval = o | 
					
						
							|  |  |  |             msgpack_pack_raw(&self.pk, L) | 
					
						
							|  |  |  |             msgpack_pack_raw_body(&self.pk, rawval, L) | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         elif PyDict_CheckExact(o) if strict else PyDict_Check(o): | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |             L = len(o) | 
					
						
							|  |  |  |             if L > ITEM_LIMIT: | 
					
						
							|  |  |  |                 raise ValueError("dict is too large") | 
					
						
							|  |  |  |             msgpack_pack_map(&self.pk, L) | 
					
						
							|  |  |  |             for k, v in o.items(): | 
					
						
							|  |  |  |                 self._pack(k, nest_limit) | 
					
						
							|  |  |  |                 self._pack(v, nest_limit) | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         elif type(o) is ExtType if strict else isinstance(o, ExtType): | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |             # This should be before Tuple because ExtType is namedtuple. | 
					
						
							|  |  |  |             rawval = o.data | 
					
						
							|  |  |  |             L = len(o.data) | 
					
						
							|  |  |  |             if L > ITEM_LIMIT: | 
					
						
							|  |  |  |                 raise ValueError("EXT data is too large") | 
					
						
							|  |  |  |             msgpack_pack_ext(&self.pk, <long>o.code, L) | 
					
						
							|  |  |  |             msgpack_pack_raw_body(&self.pk, rawval, L) | 
					
						
							|  |  |  |         elif type(o) is Timestamp: | 
					
						
							|  |  |  |             llval = o.seconds | 
					
						
							|  |  |  |             ulval = o.nanoseconds | 
					
						
							|  |  |  |             msgpack_pack_timestamp(&self.pk, llval, ulval) | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         elif PyList_CheckExact(o) if strict else (PyTuple_Check(o) or PyList_Check(o)): | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |             L = Py_SIZE(o) | 
					
						
							|  |  |  |             if L > ITEM_LIMIT: | 
					
						
							|  |  |  |                 raise ValueError("list is too large") | 
					
						
							|  |  |  |             msgpack_pack_array(&self.pk, L) | 
					
						
							|  |  |  |             for v in o: | 
					
						
							|  |  |  |                 self._pack(v, nest_limit) | 
					
						
							|  |  |  |         elif PyMemoryView_Check(o): | 
					
						
							|  |  |  |             PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) | 
					
						
							|  |  |  |             L = view.len | 
					
						
							|  |  |  |             if L > ITEM_LIMIT: | 
					
						
							| 
									
										
										
										
											2015-11-12 11:49:19 +01:00
										 |  |  |                 PyBuffer_Release(&view); | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |                 raise ValueError("memoryview is too large") | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 msgpack_pack_bin(&self.pk, L) | 
					
						
							|  |  |  |                 msgpack_pack_raw_body(&self.pk, <char*>view.buf, L) | 
					
						
							|  |  |  |             finally: | 
					
						
							|  |  |  |                 PyBuffer_Release(&view); | 
					
						
							|  |  |  |         elif self.datetime and PyDateTime_CheckExact(o) and datetime_tzinfo(o) is not None: | 
					
						
							|  |  |  |             delta = o - epoch | 
					
						
							|  |  |  |             if not PyDelta_CheckExact(delta): | 
					
						
							|  |  |  |                 raise ValueError("failed to calculate delta") | 
					
						
							|  |  |  |             llval = timedelta_days(delta) * <long long>(24*60*60) + timedelta_seconds(delta) | 
					
						
							|  |  |  |             ulval = timedelta_microseconds(delta) * 1000 | 
					
						
							|  |  |  |             msgpack_pack_timestamp(&self.pk, llval, ulval) | 
					
						
							|  |  |  |         elif will_default: | 
					
						
							|  |  |  |             return -2 | 
					
						
							|  |  |  |         elif self.datetime and PyDateTime_CheckExact(o): | 
					
						
							|  |  |  |             # this should be later than will_default | 
					
						
							|  |  |  |             PyErr_Format(ValueError, b"can not serialize '%.200s' object where tzinfo=None", Py_TYPE(o).tp_name) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             PyErr_Format(TypeError, b"can not serialize '%.200s' object", Py_TYPE(o).tp_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cdef int _pack(self, object o, int nest_limit=DEFAULT_RECURSE_LIMIT) except -1: | 
					
						
							|  |  |  |         cdef int ret | 
					
						
							|  |  |  |         if nest_limit < 0: | 
					
						
							|  |  |  |             raise ValueError("recursion limit exceeded.") | 
					
						
							|  |  |  |         nest_limit -= 1 | 
					
						
							|  |  |  |         if self._default is not None: | 
					
						
							|  |  |  |             ret = self._pack_inner(o, 1, nest_limit) | 
					
						
							|  |  |  |             if ret == -2: | 
					
						
							| 
									
										
										
										
											2013-10-20 20:28:32 +09:00
										 |  |  |                 o = self._default(o) | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |                 return ret | 
					
						
							|  |  |  |         return self._pack_inner(o, 0, nest_limit) | 
					
						
							| 
									
										
										
										
											2009-07-01 20:55:24 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |     def pack(self, object obj): | 
					
						
							| 
									
										
										
										
											2009-07-01 20:55:24 +09:00
										 |  |  |         cdef int ret | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self._check_exports() | 
					
						
							| 
									
										
										
										
											2018-01-11 23:50:41 +09:00
										 |  |  |         try: | 
					
						
							|  |  |  |             ret = self._pack(obj, DEFAULT_RECURSE_LIMIT) | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             self.pk.length = 0 | 
					
						
							|  |  |  |             raise | 
					
						
							|  |  |  |         if ret:  # should not happen. | 
					
						
							|  |  |  |             raise RuntimeError("internal error") | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  |         if self.autoreset: | 
					
						
							|  |  |  |             buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length) | 
					
						
							|  |  |  |             self.pk.length = 0 | 
					
						
							|  |  |  |             return buf | 
					
						
							| 
									
										
										
										
											2009-07-01 00:57:46 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-20 15:40:20 +09:00
										 |  |  |     def pack_ext_type(self, typecode, data): | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self._check_exports() | 
					
						
							|  |  |  |         if len(data) > ITEM_LIMIT: | 
					
						
							|  |  |  |             raise ValueError("ext data too large") | 
					
						
							| 
									
										
										
										
											2013-10-18 17:33:54 +02:00
										 |  |  |         msgpack_pack_ext(&self.pk, typecode, len(data)) | 
					
						
							|  |  |  |         msgpack_pack_raw_body(&self.pk, data, len(data)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-05 02:07:46 +09:00
										 |  |  |     def pack_array_header(self, long long size): | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self._check_exports() | 
					
						
							| 
									
										
										
										
											2016-04-28 15:08:28 +02:00
										 |  |  |         if size > ITEM_LIMIT: | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |             raise ValueError("array too large") | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |         msgpack_pack_array(&self.pk, size) | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  |         if self.autoreset: | 
					
						
							|  |  |  |             buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length) | 
					
						
							|  |  |  |             self.pk.length = 0 | 
					
						
							|  |  |  |             return buf | 
					
						
							| 
									
										
										
										
											2012-12-10 21:26:41 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-05 02:07:46 +09:00
										 |  |  |     def pack_map_header(self, long long size): | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self._check_exports() | 
					
						
							| 
									
										
										
										
											2016-04-28 15:08:28 +02:00
										 |  |  |         if size > ITEM_LIMIT: | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |             raise ValueError("map too learge") | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |         msgpack_pack_map(&self.pk, size) | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  |         if self.autoreset: | 
					
						
							|  |  |  |             buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length) | 
					
						
							|  |  |  |             self.pk.length = 0 | 
					
						
							|  |  |  |             return buf | 
					
						
							| 
									
										
										
										
											2012-09-23 17:26:16 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-10 21:26:41 +09:00
										 |  |  |     def pack_map_pairs(self, object pairs): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Pack *pairs* as msgpack map type. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:04:23 +01:00
										 |  |  |         *pairs* should be a sequence of pairs. | 
					
						
							| 
									
										
										
										
											2013-02-26 09:20:44 +09:00
										 |  |  |         (`len(pairs)` and `for k, v in pairs:` should be supported.) | 
					
						
							| 
									
										
										
										
											2012-12-10 21:26:41 +09:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self._check_exports() | 
					
						
							|  |  |  |         size = len(pairs) | 
					
						
							|  |  |  |         if size > ITEM_LIMIT: | 
					
						
							|  |  |  |             raise ValueError("map too large") | 
					
						
							|  |  |  |         msgpack_pack_map(&self.pk, size) | 
					
						
							| 
									
										
										
										
											2024-05-06 02:13:12 +09:00
										 |  |  |         for k, v in pairs: | 
					
						
							|  |  |  |             self._pack(k) | 
					
						
							|  |  |  |             self._pack(v) | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  |         if self.autoreset: | 
					
						
							|  |  |  |             buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length) | 
					
						
							|  |  |  |             self.pk.length = 0 | 
					
						
							|  |  |  |             return buf | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def reset(self): | 
					
						
							| 
									
										
										
										
											2018-11-09 20:55:13 +09:00
										 |  |  |         """Reset internal buffer.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 18:12:51 +09:00
										 |  |  |         This method is useful only when autoreset=False. | 
					
						
							| 
									
										
										
										
											2018-11-09 20:55:13 +09:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self._check_exports() | 
					
						
							| 
									
										
										
										
											2012-09-23 17:26:16 +10:00
										 |  |  |         self.pk.length = 0 | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def bytes(self): | 
					
						
							| 
									
										
										
										
											2018-11-09 20:55:13 +09:00
										 |  |  |         """Return internal buffer contents as bytes object""" | 
					
						
							| 
									
										
										
										
											2012-12-10 21:47:18 +09:00
										 |  |  |         return PyBytes_FromStringAndSize(self.pk.buf, self.pk.length) | 
					
						
							| 
									
										
										
										
											2018-11-09 20:55:13 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def getbuffer(self): | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         """Return memoryview of internal buffer.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Note: Packer now supports buffer protocol. You can use memoryview(packer). | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2024-05-05 23:14:27 +09:00
										 |  |  |         return memoryview(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __getbuffer__(self, Py_buffer *buffer, int flags): | 
					
						
							|  |  |  |         PyBuffer_FillInfo(buffer, self, self.pk.buf, self.pk.length, 1, flags) | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self.exports += 1 | 
					
						
							| 
									
										
										
										
											2024-05-05 23:14:27 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __releasebuffer__(self, Py_buffer *buffer): | 
					
						
							| 
									
										
										
										
											2024-05-06 03:33:48 +09:00
										 |  |  |         self.exports -= 1 |