diff -Nru simplejson-3.12.0/CHANGES.txt simplejson-3.13.2/CHANGES.txt --- simplejson-3.12.0/CHANGES.txt 2017-11-05 18:26:25.000000000 +0000 +++ simplejson-3.13.2/CHANGES.txt 2017-11-24 17:47:05.000000000 +0000 @@ -1,3 +1,31 @@ +Version 3.13.2 released 2017-11-24 + +* Fix additional Python 2.x compilation issue on Windows + +Version 3.13.1 released 2017-11-24 + +* Improve CI to catch speedups build regressions +* Fix speedups build regression in Python 2.x + https://github.com/simplejson/simplejson/issues/193 + +Version 3.13.0 released 2017-11-23 + +* Workarounds for NamedTemporaryFile issues with Windows for tool tests +* Make TypeError messages contain type name instead of a repr. + https://github.com/simplejson/simplejson/pull/191 +* Ensure that encoding of text subtypes is consistent with or without speedups + https://github.com/simplejson/simplejson/issues/185 + +Version 3.12.1 released 2017-11-23 + +* Misc updates to build infrastructure +* Fix an assertion failure when make_encoder receives a bad encoder argument + https://github.com/simplejson/simplejson/pull/188 +* Fix potential crash during GC + https://github.com/simplejson/simplejson/pull/187 +* Fix a reference leak when sorting keys + https://github.com/simplejson/simplejson/pull/186 + Version 3.12.0 released 2017-11-05 * Fix threaded import race condition diff -Nru simplejson-3.12.0/conf.py simplejson-3.13.2/conf.py --- simplejson-3.12.0/conf.py 2017-11-05 18:26:48.000000000 +0000 +++ simplejson-3.13.2/conf.py 2017-11-24 17:47:05.000000000 +0000 @@ -42,9 +42,9 @@ # other places throughout the built documents. # # The short X.Y version. -version = '3.12' +version = '3.13' # The full version, including alpha/beta/rc tags. -release = '3.12.0' +release = '3.13.2' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff -Nru simplejson-3.12.0/debian/changelog simplejson-3.13.2/debian/changelog --- simplejson-3.12.0/debian/changelog 2017-11-13 20:47:35.000000000 +0000 +++ simplejson-3.13.2/debian/changelog 2017-11-30 12:45:55.000000000 +0000 @@ -1,3 +1,9 @@ +simplejson (3.13.2-1) unstable; urgency=medium + + * New upstream release + + -- Piotr Ożarowski Thu, 30 Nov 2017 13:45:55 +0100 + simplejson (3.12.0-1) unstable; urgency=medium * New upstream release diff -Nru simplejson-3.12.0/debian/.git-dpm simplejson-3.13.2/debian/.git-dpm --- simplejson-3.12.0/debian/.git-dpm 2017-11-13 20:47:17.000000000 +0000 +++ simplejson-3.13.2/debian/.git-dpm 2017-11-30 12:45:23.000000000 +0000 @@ -1,11 +1,11 @@ # see git-dpm(1) from git-dpm package -9aad39531ba75eb24ca6e3ca3c33f2ade48cd084 -9aad39531ba75eb24ca6e3ca3c33f2ade48cd084 -9aad39531ba75eb24ca6e3ca3c33f2ade48cd084 -9aad39531ba75eb24ca6e3ca3c33f2ade48cd084 -simplejson_3.12.0.orig.tar.gz -0de9e43973a315c98b7308c65416d4bae6074cc4 -77969 +26d9b037c2eb05aae73b116df8bfb1938167f071 +26d9b037c2eb05aae73b116df8bfb1938167f071 +26d9b037c2eb05aae73b116df8bfb1938167f071 +26d9b037c2eb05aae73b116df8bfb1938167f071 +simplejson_3.13.2.orig.tar.gz +f8a479361560fc5c50ce494058ba4dfedb4810b9 +79735 debianTag="debian/%e%v" patchedTag="patched/%e%v" upstreamTag="upstream/%e%u" diff -Nru simplejson-3.12.0/debian/watch simplejson-3.13.2/debian/watch --- simplejson-3.12.0/debian/watch 2017-11-13 20:47:17.000000000 +0000 +++ simplejson-3.13.2/debian/watch 2017-11-30 12:45:55.000000000 +0000 @@ -1,3 +1,3 @@ version=3 opts=uversionmangle=s/(rc|a|b|c)/~$1/ \ -http://pypi.debian.net/simplejson/simplejson-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) \ No newline at end of file +https://pypi.debian.net/simplejson/simplejson-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) diff -Nru simplejson-3.12.0/PKG-INFO simplejson-3.13.2/PKG-INFO --- simplejson-3.12.0/PKG-INFO 2017-11-05 18:39:27.000000000 +0000 +++ simplejson-3.13.2/PKG-INFO 2017-11-24 17:47:30.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: simplejson -Version: 3.12.0 +Version: 3.13.2 Summary: Simple, fast, extensible JSON encoder/decoder for Python Home-page: http://github.com/simplejson/simplejson Author: Bob Ippolito Author-email: bob@redivi.com License: MIT License +Description-Content-Type: UNKNOWN Description: simplejson ---------- @@ -43,20 +44,3 @@ .. _python2.2: https://github.com/simplejson/simplejson/tree/python2.2 Platform: any -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: License :: OSI Approved :: Academic Free License (AFL) -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Software Development :: Libraries :: Python Modules diff -Nru simplejson-3.12.0/scripts/artifacts.py simplejson-3.13.2/scripts/artifacts.py --- simplejson-3.12.0/scripts/artifacts.py 2017-11-05 18:04:11.000000000 +0000 +++ simplejson-3.13.2/scripts/artifacts.py 2017-11-24 17:47:05.000000000 +0000 @@ -1,13 +1,11 @@ -try: - from urllib.request import urlopen -except ImportError: - from urllib import urlopen +#!/usr/bin/env python3 +from urllib.request import urlopen import json import os -import re import subprocess import sys +import getpass def get_json(url): @@ -40,34 +38,63 @@ for asset in release['assets']: download_file(asset['browser_download_url'], 'dist/{name}'.format(**asset)) + def get_version(): - return subprocess.check_output([sys.executable, 'setup.py', '--version']).strip() + return subprocess.check_output( + [sys.executable, 'setup.py', '--version'], + encoding='utf8' + ).strip() + def artifact_matcher(version): - return re.compile('^simplejson-{}.*\\.(exe|whl)$'.format(re.escape(version))) + prefix = 'simplejson-{}'.format(version) + def matches(fn): + return ( + fn.startswith(prefix) and + os.path.splitext(fn)[1] in ('.exe', '.whl') and + not fn.endswith('-none-any.whl') + ) or fn == '{}.tar.gz'.format(prefix) + return matches + def sign_artifacts(version): artifacts = set(os.listdir('dist')) - pattern = artifact_matcher(version) + matches = artifact_matcher(version) + passphrase = getpass.getpass('\nGPG Passphrase:') for fn in artifacts: - if pattern.search(fn) and '{}.asc'.format(fn) not in artifacts: - sign_artifact(os.path.join('dist', fn)) + if matches(fn) and '{}.asc'.format(fn) not in artifacts: + sign_artifact(os.path.join('dist', fn), passphrase) + + +def sign_artifact(path, passphrase): + cmd = [ + 'gpg', + '--detach-sign', + '--batch', + '--passphrase-fd', '0', + '--armor', + path + ] + print(' '.join(cmd)) + subprocess.run(cmd, check=True, input=passphrase, encoding='utf8') -def sign_artifact(path): - print(' '.join(['gpg', '--detach-sign', '-a', path])) - subprocess.check_call(['gpg', '--detach-sign', '-a', path]) def upload_artifacts(version): artifacts = set(os.listdir('dist')) - pattern = artifact_matcher(version) + matches = artifact_matcher(version) args = ['twine', 'upload'] for fn in artifacts: - if pattern.search(fn): + if matches(fn): filename = os.path.join('dist', fn) args.extend([filename, filename + '.asc']) subprocess.check_call(args) + def main(): + try: + os.makedirs('dist') + except OSError: + pass download_appveyor_artifacts() download_github_artifacts() version = get_version() diff -Nru simplejson-3.12.0/setup.cfg simplejson-3.13.2/setup.cfg --- simplejson-3.12.0/setup.cfg 2017-11-05 18:39:27.000000000 +0000 +++ simplejson-3.13.2/setup.cfg 2017-11-24 17:47:30.000000000 +0000 @@ -1,5 +1,4 @@ [egg_info] tag_build = tag_date = 0 -tag_svn_revision = 0 diff -Nru simplejson-3.12.0/setup.py simplejson-3.13.2/setup.py --- simplejson-3.12.0/setup.py 2017-11-05 18:26:54.000000000 +0000 +++ simplejson-3.13.2/setup.py 2017-11-24 17:47:05.000000000 +0000 @@ -1,6 +1,7 @@ #!/usr/bin/env python from __future__ import with_statement +import os import sys try: from setuptools import setup, Extension, Command @@ -11,7 +12,7 @@ DistutilsPlatformError IS_PYPY = hasattr(sys, 'pypy_translation_info') -VERSION = '3.12.0' +VERSION = '3.13.2' DESCRIPTION = "Simple, fast, extensible JSON encoder/decoder for Python" with open('README.rst', 'r') as f: @@ -112,6 +113,8 @@ try: run_setup(not IS_PYPY) except BuildFailed: + if os.environ.get('REQUIRE_SPEEDUPS'): + raise BUILD_EXT_WARNING = ("WARNING: The C extension could not be compiled, " "speedups are not enabled.") print('*' * 75) diff -Nru simplejson-3.12.0/simplejson/encoder.py simplejson-3.13.2/simplejson/encoder.py --- simplejson-3.12.0/simplejson/encoder.py 2017-11-05 18:06:14.000000000 +0000 +++ simplejson-3.13.2/simplejson/encoder.py 2017-11-24 17:47:05.000000000 +0000 @@ -48,12 +48,15 @@ if isinstance(s, binary_type): s = s.decode('utf-8') if type(s) is not text_type: - s = text_type(s) + s = text_type.__str__(s) else: if isinstance(s, str) and HAS_UTF8.search(s) is not None: s = s.decode('utf-8') if type(s) not in string_types: - s = text_type(s) + if isinstance(s, str): + s = str.__str__(s) + else: + s = unicode.__getnewargs__(s)[0] def replace(match): return ESCAPE_DCT[match.group(0)] return _q + ESCAPE.sub(replace, s) + _q @@ -67,12 +70,15 @@ if isinstance(s, binary_type): s = s.decode('utf-8') if type(s) is not text_type: - s = text_type(s) + s = text_type.__str__(s) else: if isinstance(s, str) and HAS_UTF8.search(s) is not None: s = s.decode('utf-8') if type(s) not in string_types: - s = text_type(s) + if isinstance(s, str): + s = str.__str__(s) + else: + s = unicode.__getnewargs__(s)[0] def replace(match): s = match.group(0) try: @@ -258,7 +264,8 @@ return JSONEncoder.default(self, o) """ - raise TypeError(repr(o) + " is not JSON serializable") + raise TypeError('Object of type %s is not JSON serializable' % + o.__class__.__name__) def encode(self, o): """Return a JSON string representation of a Python data structure. @@ -541,7 +548,8 @@ elif _skipkeys: key = None else: - raise TypeError("key " + repr(key) + " is not a string") + raise TypeError('keys must be str, int, float, bool or None, ' + 'not %s' % key.__class__.__name__) return key def _iterencode_dict(dct, _current_indent_level): diff -Nru simplejson-3.12.0/simplejson/__init__.py simplejson-3.13.2/simplejson/__init__.py --- simplejson-3.12.0/simplejson/__init__.py 2017-11-05 18:26:34.000000000 +0000 +++ simplejson-3.13.2/simplejson/__init__.py 2017-11-24 17:47:05.000000000 +0000 @@ -77,7 +77,8 @@ >>> def encode_complex(obj): ... if isinstance(obj, complex): ... return [obj.real, obj.imag] - ... raise TypeError(repr(o) + " is not JSON serializable") + ... raise TypeError('Object of type %s is not JSON serializable' % + ... obj.__class__.__name__) ... >>> json.dumps(2 + 1j, default=encode_complex) '[2.0, 1.0]' @@ -97,7 +98,7 @@ Expecting property name: line 1 column 3 (char 2) """ from __future__ import absolute_import -__version__ = '3.12.0' +__version__ = '3.13.2' __all__ = [ 'dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', diff -Nru simplejson-3.12.0/simplejson/_speedups.c simplejson-3.13.2/simplejson/_speedups.c --- simplejson-3.12.0/simplejson/_speedups.c 2017-11-05 18:23:11.000000000 +0000 +++ simplejson-3.13.2/simplejson/_speedups.c 2017-11-24 17:47:05.000000000 +0000 @@ -680,7 +680,9 @@ Py_INCREF(Py_None); return Py_None; } - PyErr_SetString(PyExc_TypeError, "keys must be a string"); + PyErr_Format(PyExc_TypeError, + "keys must be str, int, float, bool or None, " + "not %.100s", key->ob_type->tp_name); return NULL; } @@ -692,7 +694,8 @@ PyObject *lst = NULL; PyObject *item = NULL; PyObject *kstr = NULL; - static PyObject *sortfun = NULL; + PyObject *sortfun = NULL; + PyObject *sortres; static PyObject *sortargs = NULL; if (sortargs == NULL) { @@ -763,8 +766,10 @@ sortfun = PyObject_GetAttrString(lst, "sort"); if (sortfun == NULL) goto bail; - if (!PyObject_Call(sortfun, sortargs, s->item_sort_kw)) + sortres = PyObject_Call(sortfun, sortargs, s->item_sort_kw); + if (!sortres) goto bail; + Py_DECREF(sortres); Py_CLEAR(sortfun); iter = PyObject_GetIter(lst); Py_CLEAR(lst); @@ -1355,7 +1360,8 @@ static void scanner_dealloc(PyObject *self) { - /* Deallocate scanner object */ + /* bpo-31095: UnTrack is needed before calling any callbacks */ + PyObject_GC_UnTrack(self); scanner_clear(self); Py_TYPE(self)->tp_free(self); } @@ -2807,10 +2813,25 @@ encoder_encode_string(PyEncoderObject *s, PyObject *obj) { /* Return the JSON representation of a string */ - if (s->fast_encode) + PyObject *encoded; + + if (s->fast_encode) { return py_encode_basestring_ascii(NULL, obj); - else - return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL); + } + encoded = PyObject_CallFunctionObjArgs(s->encoder, obj, NULL); + if (encoded != NULL && +#if PY_MAJOR_VERSION < 3 + !JSON_ASCII_Check(encoded) && +#endif /* PY_MAJOR_VERSION < 3 */ + !PyUnicode_Check(encoded)) + { + PyErr_Format(PyExc_TypeError, + "encoder() must return a string, not %.80s", + Py_TYPE(encoded)->tp_name); + Py_DECREF(encoded); + return NULL; + } + return encoded; } static int @@ -3205,7 +3226,8 @@ static void encoder_dealloc(PyObject *self) { - /* Deallocate Encoder */ + /* bpo-31095: UnTrack is needed before calling any callbacks */ + PyObject_GC_UnTrack(self); encoder_clear(self); Py_TYPE(self)->tp_free(self); } @@ -3335,10 +3357,11 @@ PyObject * import_dependency(char *module_name, char *attr_name) { + PyObject *rval; PyObject *module = PyImport_ImportModule(module_name); if (module == NULL) return NULL; - PyObject *rval = PyObject_GetAttrString(module, attr_name); + rval = PyObject_GetAttrString(module, attr_name); Py_DECREF(module); return rval; } diff -Nru simplejson-3.12.0/simplejson/tests/test_dump.py simplejson-3.13.2/simplejson/tests/test_dump.py --- simplejson-3.12.0/simplejson/tests/test_dump.py 2014-09-29 21:18:10.000000000 +0000 +++ simplejson-3.13.2/simplejson/tests/test_dump.py 2017-11-24 17:47:05.000000000 +0000 @@ -1,7 +1,11 @@ from unittest import TestCase -from simplejson.compat import StringIO, long_type, b, binary_type, PY3 +from simplejson.compat import StringIO, long_type, b, binary_type, text_type, PY3 import simplejson as json +class MisbehavingTextSubtype(text_type): + def __str__(self): + return "FAIL!" + def as_text_type(s): if PY3 and isinstance(s, binary_type): return s.decode('ascii') @@ -128,3 +132,11 @@ json.dump(p, sio, sort_keys=True) self.assertEqual(sio.getvalue(), json.dumps(p, sort_keys=True)) self.assertEqual(json.loads(sio.getvalue()), p) + + def test_misbehaving_text_subtype(self): + # https://github.com/simplejson/simplejson/issues/185 + text = "this is some text" + self.assertEqual( + json.dumps(MisbehavingTextSubtype(text)), + json.dumps(text) + ) diff -Nru simplejson-3.12.0/simplejson/tests/test_errors.py simplejson-3.13.2/simplejson/tests/test_errors.py --- simplejson-3.12.0/simplejson/tests/test_errors.py 2014-07-22 20:30:14.000000000 +0000 +++ simplejson-3.13.2/simplejson/tests/test_errors.py 2017-11-24 17:47:05.000000000 +0000 @@ -7,7 +7,24 @@ class TestErrors(TestCase): def test_string_keys_error(self): data = [{'a': 'A', 'b': (2, 4), 'c': 3.0, ('d',): 'D tuple'}] - self.assertRaises(TypeError, json.dumps, data) + try: + json.dumps(data) + except TypeError: + err = sys.exc_info()[1] + else: + self.fail('Expected TypeError') + self.assertEqual(str(err), + 'keys must be str, int, float, bool or None, not tuple') + + def test_not_serializable(self): + try: + json.dumps(json) + except TypeError: + err = sys.exc_info()[1] + else: + self.fail('Expected TypeError') + self.assertEqual(str(err), + 'Object of type module is not JSON serializable') def test_decode_error(self): err = None diff -Nru simplejson-3.12.0/simplejson/tests/test_speedups.py simplejson-3.13.2/simplejson/tests/test_speedups.py --- simplejson-3.12.0/simplejson/tests/test_speedups.py 2017-11-05 18:04:11.000000000 +0000 +++ simplejson-3.13.2/simplejson/tests/test_speedups.py 2017-11-24 17:47:05.000000000 +0000 @@ -60,6 +60,30 @@ ) @skip_if_speedups_missing + def test_bad_str_encoder(self): + # Issue #31505: There shouldn't be an assertion failure in case + # c_make_encoder() receives a bad encoder() argument. + import decimal + def bad_encoder1(*args): + return None + enc = encoder.c_make_encoder( + None, lambda obj: str(obj), + bad_encoder1, None, ': ', ', ', + False, False, False, {}, False, False, False, + None, None, 'utf-8', False, False, decimal.Decimal, False) + self.assertRaises(TypeError, enc, 'spam', 4) + self.assertRaises(TypeError, enc, {'spam': 42}, 4) + + def bad_encoder2(*args): + 1/0 + enc = encoder.c_make_encoder( + None, lambda obj: str(obj), + bad_encoder2, None, ': ', ', ', + False, False, False, {}, False, False, False, + None, None, 'utf-8', False, False, decimal.Decimal, False) + self.assertRaises(ZeroDivisionError, enc, 'spam', 4) + + @skip_if_speedups_missing def test_bad_bool_args(self): def test(name): encoder.JSONEncoder(**{name: BadBool()}).encode({}) diff -Nru simplejson-3.12.0/simplejson/tests/test_tool.py simplejson-3.13.2/simplejson/tests/test_tool.py --- simplejson-3.12.0/simplejson/tests/test_tool.py 2014-07-22 20:30:14.000000000 +0000 +++ simplejson-3.13.2/simplejson/tests/test_tool.py 2017-11-24 17:47:05.000000000 +0000 @@ -63,35 +63,43 @@ out, err = proc.communicate(data) self.assertEqual(strip_python_stderr(err), ''.encode()) self.assertEqual(proc.returncode, 0) - return out + return out.decode('utf8').splitlines() def test_stdin_stdout(self): self.assertEqual( self.runTool(data=self.data.encode()), - self.expect.encode()) + self.expect.splitlines()) def test_infile_stdout(self): - with tempfile.NamedTemporaryFile() as infile: + infile = tempfile.NamedTemporaryFile(delete=False) + try: infile.write(self.data.encode()) - infile.flush() + infile.close() self.assertEqual( self.runTool(args=[infile.name]), - self.expect.encode()) + self.expect.splitlines()) + finally: + os.unlink(infile.name) def test_infile_outfile(self): - with tempfile.NamedTemporaryFile() as infile: + infile = tempfile.NamedTemporaryFile(delete=False) + try: infile.write(self.data.encode()) - infile.flush() + infile.close() # outfile will get overwritten by tool, so the delete # may not work on some platforms. Do it manually. - outfile = tempfile.NamedTemporaryFile() + outfile = tempfile.NamedTemporaryFile(delete=False) try: + outfile.close() self.assertEqual( self.runTool(args=[infile.name, outfile.name]), - ''.encode()) + []) with open(outfile.name, 'rb') as f: - self.assertEqual(f.read(), self.expect.encode()) + self.assertEqual( + f.read().decode('utf8').splitlines(), + self.expect.splitlines() + ) finally: - outfile.close() - if os.path.exists(outfile.name): - os.unlink(outfile.name) + os.unlink(outfile.name) + finally: + os.unlink(infile.name) diff -Nru simplejson-3.12.0/simplejson.egg-info/PKG-INFO simplejson-3.13.2/simplejson.egg-info/PKG-INFO --- simplejson-3.12.0/simplejson.egg-info/PKG-INFO 2017-11-05 18:39:26.000000000 +0000 +++ simplejson-3.13.2/simplejson.egg-info/PKG-INFO 2017-11-24 17:47:30.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: simplejson -Version: 3.12.0 +Version: 3.13.2 Summary: Simple, fast, extensible JSON encoder/decoder for Python Home-page: http://github.com/simplejson/simplejson Author: Bob Ippolito Author-email: bob@redivi.com License: MIT License +Description-Content-Type: UNKNOWN Description: simplejson ----------