Merge pull request #37 from msgpack/exceptions

Split exceptions
This commit is contained in:
INADA Naoki 2012-12-10 03:13:21 -08:00
commit 0d63c67e98
5 changed files with 72 additions and 18 deletions

View file

@ -19,9 +19,15 @@ writing MessagePack data.
NOTE for msgpack 0.2.x users
----------------------------
The msgpack 0.3 have some incompatible changes.
The default value of ``use_list`` keyword argument is ``True`` from 0.3.x.
You should pass the argument explicitly for backward compatibility.
`Unpacker.unpack()` and some unpack methods now raises `OutOfData`
instead of `StopIteration`.
`StopIteration` is used for iterator protocol only.
HOW TO USE
-----------

View file

@ -38,8 +38,12 @@ cdef extern from "pack.h":
cdef int DEFAULT_RECURSE_LIMIT=511
class BufferFull(Exception):
pass
from msgpack.exceptions import (
BufferFull,
OutOfData,
UnpackValueError,
ExtraData,
)
cdef class Packer(object):
@ -102,7 +106,7 @@ cdef class Packer(object):
cdef dict d
if nest_limit < 0:
raise ValueError("Too deep.")
raise UnpackValueError("recursion limit exceeded.")
if o is None:
ret = msgpack_pack_nil(&self.pk)
@ -174,7 +178,9 @@ cdef class Packer(object):
cpdef pack(self, object obj):
cdef int ret
ret = self._pack(obj, DEFAULT_RECURSE_LIMIT)
if ret:
if ret == -1:
raise MemoryError
elif ret: # should not happen.
raise TypeError
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
self.pk.length = 0
@ -296,7 +302,7 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
if ret == 1:
obj = template_data(&ctx)
if off < buf_len:
raise ValueError("Extra data.")
raise ExtraData(obj, PyBytes_FromStringAndSize(buf+off, buf_len-off))
return obj
else:
return None
@ -421,11 +427,12 @@ cdef class Unpacker(object):
init_ctx(&self.ctx, object_hook, object_pairs_hook, list_hook, use_list, cenc, cerr)
def feed(self, object next_bytes):
"""Append `next_bytes` to internal buffer."""
cdef char* buf
cdef Py_ssize_t buf_len
if self.file_like is not None:
raise AssertionError(
"unpacker.feed() is not be able to use with`file_like`.")
"unpacker.feed() is not be able to use with `file_like`.")
PyObject_AsReadBuffer(next_bytes, <const_void_ptr*>&buf, &buf_len)
self.append_buffer(buf, buf_len)
@ -479,7 +486,7 @@ cdef class Unpacker(object):
else:
self.file_like = None
cdef object _unpack(self, execute_fn execute, object write_bytes):
cdef object _unpack(self, execute_fn execute, object write_bytes, bint iter=0):
cdef int ret
cdef object obj
cdef size_t prev_head
@ -497,7 +504,10 @@ cdef class Unpacker(object):
if self.file_like is not None:
self.read_from_file()
continue
raise StopIteration("No more data to unpack.")
if iter:
raise StopIteration("No more data to unpack.")
else:
raise OutOfData("No more data to unpack.")
else:
raise ValueError("Unpack failed: error = %d" % (ret,))
@ -515,7 +525,10 @@ cdef class Unpacker(object):
"""
unpack one object
If write_bytes is not None, it will be called with parts of the raw message as it is unpacked.
If write_bytes is not None, it will be called with parts of the raw
message as it is unpacked.
Raises `OutOfData` when there are no more bytes to unpack.
"""
return self._unpack(template_construct, write_bytes)
@ -523,23 +536,34 @@ cdef class Unpacker(object):
"""
read and ignore one object, returning None
If write_bytes is not None, it will be called with parts of the raw message as it is unpacked.
If write_bytes is not None, it will be called with parts of the raw
message as it is unpacked.
Raises `OutOfData` when there are no more bytes to unpack.
"""
return self._unpack(template_skip, write_bytes)
def read_array_header(self, object write_bytes=None):
"""assuming the next object is an array, return its size n, such that the next n unpack() calls will iterate over its contents."""
"""assuming the next object is an array, return its size n, such that
the next n unpack() calls will iterate over its contents.
Raises `OutOfData` when there are no more bytes to unpack.
"""
return self._unpack(read_array_header, write_bytes)
def read_map_header(self, object write_bytes=None):
"""assuming the next object is a map, return its size n, such that the next n * 2 unpack() calls will iterate over its key-value pairs."""
"""assuming the next object is a map, return its size n, such that the
next n * 2 unpack() calls will iterate over its key-value pairs.
Raises `OutOfData` when there are no more bytes to unpack.
"""
return self._unpack(read_map_header, write_bytes)
def __iter__(self):
return self
def __next__(self):
return self._unpack(template_construct, None)
return self._unpack(template_construct, None, 1)
# for debug.
#def _buf(self):

23
msgpack/exceptions.py Normal file
View file

@ -0,0 +1,23 @@
class UnpackException(Exception):
pass
class BufferFull(UnpackException):
pass
class OutOfData(UnpackException):
pass
class UnpackValueError(UnpackException, ValueError):
pass
class ExtraData(ValueError):
def __init__(self, unpacked, extra):
self.unpacked = unpacked
self.extra = extra
def __str__(self):
return "unpack(b) recieved extra data."

View file

@ -1,5 +1,5 @@
"""Test Unpacker's read_array_header and read_map_header methods"""
from msgpack import packb, Unpacker
from msgpack import packb, Unpacker, OutOfData
UnexpectedTypeException = ValueError
def test_read_array_header():
@ -12,7 +12,7 @@ def test_read_array_header():
try:
unpacker.unpack()
assert 0, 'should raise exception'
except StopIteration:
except OutOfData:
assert 1, 'okay'
@ -25,7 +25,7 @@ def test_read_map_header():
try:
unpacker.unpack()
assert 0, 'should raise exception'
except StopIteration:
except OutOfData:
assert 1, 'okay'
def test_incorrect_type_array():

View file

@ -3,6 +3,7 @@
import six
from msgpack import Unpacker, BufferFull
from msgpack.exceptions import OutOfData
import nose
def test_foobar():
@ -17,7 +18,7 @@ def test_foobar():
try:
o = unpacker.unpack()
assert 0, "should raise exception"
except StopIteration:
except OutOfData:
assert 1, "ok"
unpacker.feed(b'foo')
@ -41,7 +42,7 @@ def test_foobar_skip():
try:
o = unpacker.unpack()
assert 0, "should raise exception"
except StopIteration:
except OutOfData:
assert 1, "ok"
def test_maxbuffersize():