diff -Nru simplejson-2.3.0/CHANGES.txt simplejson-2.3.2/CHANGES.txt --- simplejson-2.3.0/CHANGES.txt 2011-12-05 21:17:44.000000000 +0000 +++ simplejson-2.3.2/CHANGES.txt 2011-12-30 15:30:49.000000000 +0000 @@ -1,6 +1,16 @@ +Version 2.3.2 released 2011-12-30 + +* Fix crashing regression in speedups introduced in 2.3.1 + +Version 2.3.1 released 2011-12-29 + +* namedtuple_as_object now checks _asdict to ensure that it + is callable. + https://github.com/simplejson/simplejson/issues/26 + Version 2.3.0 released 2011-12-05 -* Any objects with _asdict() methods are now considered for +* Any objects with _asdict() methods are now considered for namedtuple_as_object. https://github.com/simplejson/simplejson/pull/22 diff -Nru simplejson-2.3.0/conf.py simplejson-2.3.2/conf.py --- simplejson-2.3.0/conf.py 2011-12-05 21:17:44.000000000 +0000 +++ simplejson-2.3.2/conf.py 2011-12-30 15:31:59.000000000 +0000 @@ -44,7 +44,7 @@ # The short X.Y version. version = '2.3' # The full version, including alpha/beta/rc tags. -release = '2.3.0' +release = '2.3.2' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff -Nru simplejson-2.3.0/debian/changelog simplejson-2.3.2/debian/changelog --- simplejson-2.3.0/debian/changelog 2011-12-08 17:28:47.000000000 +0000 +++ simplejson-2.3.2/debian/changelog 2012-01-08 18:36:05.000000000 +0000 @@ -1,3 +1,9 @@ +simplejson (2.3.2-1) unstable; urgency=low + + * New upstream release + + -- Piotr Ożarowski Sun, 08 Jan 2012 19:36:04 +0100 + simplejson (2.3.0-1) unstable; urgency=low * New upstream release diff -Nru simplejson-2.3.0/PKG-INFO simplejson-2.3.2/PKG-INFO --- simplejson-2.3.0/PKG-INFO 2011-12-05 21:18:27.000000000 +0000 +++ simplejson-2.3.2/PKG-INFO 2011-12-30 15:33:12.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: simplejson -Version: 2.3.0 +Version: 2.3.2 Summary: Simple, fast, extensible JSON encoder/decoder for Python Home-page: http://github.com/simplejson/simplejson Author: Bob Ippolito diff -Nru simplejson-2.3.0/setup.py simplejson-2.3.2/setup.py --- simplejson-2.3.0/setup.py 2011-12-05 21:17:44.000000000 +0000 +++ simplejson-2.3.2/setup.py 2011-12-30 15:32:09.000000000 +0000 @@ -7,7 +7,7 @@ DistutilsPlatformError IS_PYPY = hasattr(sys, 'pypy_translation_info') -VERSION = '2.3.0' +VERSION = '2.3.2' DESCRIPTION = "Simple, fast, extensible JSON encoder/decoder for Python" LONG_DESCRIPTION = open('README.rst', 'r').read() diff -Nru simplejson-2.3.0/simplejson/encoder.py simplejson-2.3.2/simplejson/encoder.py --- simplejson-2.3.0/simplejson/encoder.py 2011-12-05 21:17:44.000000000 +0000 +++ simplejson-2.3.2/simplejson/encoder.py 2011-12-29 18:38:58.000000000 +0000 @@ -157,7 +157,7 @@ If namedtuple_as_object is true (the default), objects with ``_asdict()`` methods will be encoded as JSON objects. - + If tuple_as_array is true (the default), tuple (and subclasses) will be encoded as JSON arrays. """ @@ -387,15 +387,17 @@ yield buf if isinstance(value, list): chunks = _iterencode_list(value, _current_indent_level) - elif (_namedtuple_as_object and hasattr(value, '_asdict')): - chunks = _iterencode_dict(value._asdict(), - _current_indent_level) - elif _tuple_as_array and isinstance(value, tuple): - chunks = _iterencode_list(value, _current_indent_level) - elif isinstance(value, dict): - chunks = _iterencode_dict(value, _current_indent_level) else: - chunks = _iterencode(value, _current_indent_level) + _asdict = _namedtuple_as_object and getattr(value, '_asdict', None) + if _asdict and callable(_asdict): + chunks = _iterencode_dict(_asdict(), + _current_indent_level) + elif _tuple_as_array and isinstance(value, tuple): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) for chunk in chunks: yield chunk if newline_indent is not None: @@ -471,15 +473,17 @@ else: if isinstance(value, list): chunks = _iterencode_list(value, _current_indent_level) - elif (_namedtuple_as_object and hasattr(value, '_asdict')): - chunks = _iterencode_dict(value._asdict(), - _current_indent_level) - elif _tuple_as_array and isinstance(value, tuple): - chunks = _iterencode_list(value, _current_indent_level) - elif isinstance(value, dict): - chunks = _iterencode_dict(value, _current_indent_level) else: - chunks = _iterencode(value, _current_indent_level) + _asdict = _namedtuple_as_object and getattr(value, '_asdict', None) + if _asdict and callable(_asdict): + chunks = _iterencode_dict(_asdict(), + _current_indent_level) + elif _tuple_as_array and isinstance(value, tuple): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) for chunk in chunks: yield chunk if newline_indent is not None: @@ -505,27 +509,29 @@ elif isinstance(o, list): for chunk in _iterencode_list(o, _current_indent_level): yield chunk - elif (_namedtuple_as_object and hasattr(o, '_asdict')): - for chunk in _iterencode_dict(o._asdict(), _current_indent_level): - yield chunk - elif (_tuple_as_array and isinstance(o, tuple)): - for chunk in _iterencode_list(o, _current_indent_level): - yield chunk - elif isinstance(o, dict): - for chunk in _iterencode_dict(o, _current_indent_level): - yield chunk - elif _use_decimal and isinstance(o, Decimal): - yield str(o) else: - if markers is not None: - markerid = id(o) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = o - o = _default(o) - for chunk in _iterencode(o, _current_indent_level): - yield chunk - if markers is not None: - del markers[markerid] + _asdict = _namedtuple_as_object and getattr(o, '_asdict', None) + if _asdict and callable(_asdict): + for chunk in _iterencode_dict(_asdict(), _current_indent_level): + yield chunk + elif (_tuple_as_array and isinstance(o, tuple)): + for chunk in _iterencode_list(o, _current_indent_level): + yield chunk + elif isinstance(o, dict): + for chunk in _iterencode_dict(o, _current_indent_level): + yield chunk + elif _use_decimal and isinstance(o, Decimal): + yield str(o) + else: + if markers is not None: + markerid = id(o) + if markerid in markers: + raise ValueError("Circular reference detected") + markers[markerid] = o + o = _default(o) + for chunk in _iterencode(o, _current_indent_level): + yield chunk + if markers is not None: + del markers[markerid] return _iterencode diff -Nru simplejson-2.3.0/simplejson/__init__.py simplejson-2.3.2/simplejson/__init__.py --- simplejson-2.3.0/simplejson/__init__.py 2011-12-05 21:17:44.000000000 +0000 +++ simplejson-2.3.2/simplejson/__init__.py 2011-12-30 15:32:15.000000000 +0000 @@ -97,7 +97,7 @@ $ echo '{ 1.2:3.4}' | python -m simplejson.tool Expecting property name: line 1 column 2 (char 2) """ -__version__ = '2.3.0' +__version__ = '2.3.2' __all__ = [ 'dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', diff -Nru simplejson-2.3.0/simplejson/_speedups.c simplejson-2.3.2/simplejson/_speedups.c --- simplejson-2.3.0/simplejson/_speedups.c 2011-12-05 21:17:44.000000000 +0000 +++ simplejson-2.3.2/simplejson/_speedups.c 2011-12-30 15:30:06.000000000 +0000 @@ -169,7 +169,15 @@ static int _is_namedtuple(PyObject *obj) { - return PyObject_HasAttrString(obj, "_asdict"); + int rval = 0; + PyObject *_asdict = PyObject_GetAttrString(obj, "_asdict"); + if (_asdict == NULL) { + PyErr_Clear(); + return 0; + } + rval = PyCallable_Check(_asdict); + Py_DECREF(_asdict); + return rval; } static int diff -Nru simplejson-2.3.0/simplejson/tests/test_namedtuple.py simplejson-2.3.2/simplejson/tests/test_namedtuple.py --- simplejson-2.3.0/simplejson/tests/test_namedtuple.py 2011-12-05 21:17:44.000000000 +0000 +++ simplejson-2.3.2/simplejson/tests/test_namedtuple.py 2011-12-29 18:38:58.000000000 +0000 @@ -23,17 +23,29 @@ class DuckValue(object): def __init__(self, *args): - self.value = Value(*args) + self.value = Value(*args) def _asdict(self): - return self.value._asdict() + return self.value._asdict() class DuckPoint(object): def __init__(self, *args): - self.point = Point(*args) + self.point = Point(*args) def _asdict(self): - return self.point._asdict() + return self.point._asdict() + +class DeadDuck(object): + _asdict = None + +class DeadDict(dict): + _asdict = None + +CONSTRUCTORS = [ + lambda v: v, + lambda v: [v], + lambda v: [{'key': v}], +] class TestNamedTuple(unittest.TestCase): def test_namedtuple_dumps(self): @@ -89,3 +101,21 @@ json.loads(sio.getvalue())) self.assertRaises(TypeError, json.dump, v, StringIO(), tuple_as_array=False, namedtuple_as_object=False) + + def test_asdict_not_callable_dump(self): + for f in CONSTRUCTORS: + self.assertRaises(TypeError, + json.dump, f(DeadDuck()), StringIO(), namedtuple_as_object=True) + sio = StringIO() + json.dump(f(DeadDict()), sio, namedtuple_as_object=True) + self.assertEqual( + json.dumps(f({})), + sio.getvalue()) + + def test_asdict_not_callable_dumps(self): + for f in CONSTRUCTORS: + self.assertRaises(TypeError, + json.dumps, f(DeadDuck()), namedtuple_as_object=True) + self.assertEqual( + json.dumps(f({})), + json.dumps(f(DeadDict()), namedtuple_as_object=True))