From ed9d7d30383a1d896699c6e2740c70e0efae2e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Schneider?= Date: Sat, 1 Nov 2014 18:30:36 +0100 Subject: [PATCH] Initial import from tarball --- CHANGELOG | 66 ++++++++++++ LICENSE | 29 ++++++ MANIFEST.in | 4 + PKG-INFO | 85 +++++++++++++++ README | 59 +++++++++++ anyjson.egg-info/PKG-INFO | 85 +++++++++++++++ anyjson.egg-info/SOURCES.txt | 14 +++ anyjson.egg-info/dependency_links.txt | 1 + anyjson.egg-info/not-zip-safe | 1 + anyjson.egg-info/top_level.txt | 1 + anyjson/__init__.py | 142 +++++++++++++++++++++++++ debian/NEWS | 7 -- debian/changelog | 63 ------------ debian/clean | 2 - debian/compat | 1 - debian/control | 39 ------- debian/copyright | 39 ------- debian/python-anyjson.docs | 1 - debian/python3-anyjson.docs | 1 - debian/rules | 28 ----- debian/source/format | 1 - debian/watch | 2 - setup.cfg | 5 + setup.py | 100 ++++++++++++++++++ tests/benchmark.py | 143 ++++++++++++++++++++++++++ tests/test_implementations.py | 57 ++++++++++ tests/test_implementations.pyc | Bin 0 -> 2567 bytes 27 files changed, 792 insertions(+), 184 deletions(-) create mode 100644 CHANGELOG create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 PKG-INFO create mode 100644 README create mode 100644 anyjson.egg-info/PKG-INFO create mode 100644 anyjson.egg-info/SOURCES.txt create mode 100644 anyjson.egg-info/dependency_links.txt create mode 100644 anyjson.egg-info/not-zip-safe create mode 100644 anyjson.egg-info/top_level.txt create mode 100644 anyjson/__init__.py delete mode 100644 debian/NEWS delete mode 100644 debian/changelog delete mode 100644 debian/clean delete mode 100644 debian/compat delete mode 100644 debian/control delete mode 100644 debian/copyright delete mode 100644 debian/python-anyjson.docs delete mode 100644 debian/python3-anyjson.docs delete mode 100755 debian/rules delete mode 100644 debian/source/format delete mode 100644 debian/watch create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tests/benchmark.py create mode 100644 tests/test_implementations.py create mode 100644 tests/test_implementations.pyc diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..ea7a65d --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,66 @@ +0.1: + + * Initial release + +0.1.1 + + * Added benchmarking script + * Added support for more serializer modules + +0.2 + + * Added exception handling so that all supported modules will result in the + same exceptions being thrown. The exceptions are the same that are used + by the JSON module from python 2.7, TypeError for serialize and + ValueError for deserialize. + * '''NOTE''' API changed. the implementation property is now an object, not + a string + * Rewrote module loading code, so it's now easier to add and rearrange + JSON modules + +0.2.1 + + * Fixed bug that rendered the lib uninstalleable with easy_install if there + was no supported json module allready installed + +0.2.2 + + * Fixed bug #2. Installation failed if there were noe compatible json + implementations installed, because the module was loaeded, and threw import + exception during the install process. + +0.2.3 + + * Fixed bug #3 + * Fixed bug in benchmarking script + +0.2.4 + + * Added support for py-yajl (Thanks Benjamin Anderson) + * Improved benchmark script to test serialization performance and + to use real life data for tests. + +0.2.5 + + * Added loads and dumps methods so anyjson can be used interchangably + with the stdlib json module. Note: The original methods are still + in place. Nothing from the 0.2.4 API is changed, removed or deprecated + in this release. + +0.3 + + * Added support for python3 + +0.3.1 + + * Added deprecation warning for cjson and made it the least preferred + implementation. See: http://pypi.python.org/pypi/python-cjson/1.0.5 + +0.3.2 + + * Added support for buffer objects + +0.3.3 + + * Fixed bug in buffer object support related to differences between + stringIO and cStringIO diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..33c5627 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +This software is licensed under the ``New BSD License``: + +Copyright (c) 2009, by the authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +Neither the name of the authors nor the names of its contributors may be used +to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..6de8cdf --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include CHANGELOG +include README +include LICENSE +graft tests \ No newline at end of file diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..c8e8a3d --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,85 @@ +Metadata-Version: 1.1 +Name: anyjson +Version: 0.3.3 +Summary: Wraps the best available JSON implementation available in a common interface +Home-page: http://bitbucket.org/runeh/anyjson/ +Author: Rune Halvorsen +Author-email: runefh@gmail.com +License: BSD +Description: ############################## + anyjson - JSON library wrapper + ############################## + + Overview + -------- + + Anyjson loads whichever is the fastest JSON module installed and provides + a uniform API regardless of which JSON implementation is used. + + Originally part of carrot (http://github.com/ask/carrot/) + + Examples + -------- + + To serialize a python object to a JSON string, call the `serialize` function: + + >>> import anyjson + >>> anyjson.serialize(["test", 1, {"foo": 3.141592}, "bar"]) + '["test", 1, {"foo": 3.141592}, "bar"]' + + Conversion the other way is done with the `deserialize` call. + + >>> anyjson.deserialize("""["test", 1, {"foo": 3.141592}, "bar"]""") + ['test', 1, {'foo': 3.1415920000000002}, 'bar'] + + Regardless of the JSON implementation used, the exceptions will be the same. + This means that trying to serialize something not compatible with JSON + raises a TypeError: + + >>> anyjson.serialize([object()]) + Traceback (most recent call last): + + TypeError: object is not JSON encodable + + And deserializing a JSON string with invalid JSON raises a ValueError: + + >>> anyjson.deserialize("""['missing square brace!""") + Traceback (most recent call last): + + ValueError: cannot parse JSON description + + + Contact + ------- + + The module is maintaned by Rune F. Halvorsen . + The project resides at http://bitbucket.org/runeh/anyjson . Bugs and feature + requests can be submitted there. Patches are also very welcome. + + Changelog + --------- + + See CHANGELOG file + + License + ------- + + see the LICENSE file + +Keywords: json +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Intended Audience :: Developers +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.4 +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.1 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: Implementation :: Jython diff --git a/README b/README new file mode 100644 index 0000000..ef8eaa1 --- /dev/null +++ b/README @@ -0,0 +1,59 @@ +############################## +anyjson - JSON library wrapper +############################## + +Overview +-------- + +Anyjson loads whichever is the fastest JSON module installed and provides +a uniform API regardless of which JSON implementation is used. + +Originally part of carrot (http://github.com/ask/carrot/) + +Examples +-------- + +To serialize a python object to a JSON string, call the `serialize` function: + +>>> import anyjson +>>> anyjson.serialize(["test", 1, {"foo": 3.141592}, "bar"]) +'["test", 1, {"foo": 3.141592}, "bar"]' + +Conversion the other way is done with the `deserialize` call. + +>>> anyjson.deserialize("""["test", 1, {"foo": 3.141592}, "bar"]""") +['test', 1, {'foo': 3.1415920000000002}, 'bar'] + +Regardless of the JSON implementation used, the exceptions will be the same. +This means that trying to serialize something not compatible with JSON +raises a TypeError: + +>>> anyjson.serialize([object()]) +Traceback (most recent call last): + +TypeError: object is not JSON encodable + +And deserializing a JSON string with invalid JSON raises a ValueError: + +>>> anyjson.deserialize("""['missing square brace!""") +Traceback (most recent call last): + +ValueError: cannot parse JSON description + + +Contact +------- + +The module is maintaned by Rune F. Halvorsen . +The project resides at http://bitbucket.org/runeh/anyjson . Bugs and feature +requests can be submitted there. Patches are also very welcome. + +Changelog +--------- + +See CHANGELOG file + +License +------- + +see the LICENSE file diff --git a/anyjson.egg-info/PKG-INFO b/anyjson.egg-info/PKG-INFO new file mode 100644 index 0000000..c8e8a3d --- /dev/null +++ b/anyjson.egg-info/PKG-INFO @@ -0,0 +1,85 @@ +Metadata-Version: 1.1 +Name: anyjson +Version: 0.3.3 +Summary: Wraps the best available JSON implementation available in a common interface +Home-page: http://bitbucket.org/runeh/anyjson/ +Author: Rune Halvorsen +Author-email: runefh@gmail.com +License: BSD +Description: ############################## + anyjson - JSON library wrapper + ############################## + + Overview + -------- + + Anyjson loads whichever is the fastest JSON module installed and provides + a uniform API regardless of which JSON implementation is used. + + Originally part of carrot (http://github.com/ask/carrot/) + + Examples + -------- + + To serialize a python object to a JSON string, call the `serialize` function: + + >>> import anyjson + >>> anyjson.serialize(["test", 1, {"foo": 3.141592}, "bar"]) + '["test", 1, {"foo": 3.141592}, "bar"]' + + Conversion the other way is done with the `deserialize` call. + + >>> anyjson.deserialize("""["test", 1, {"foo": 3.141592}, "bar"]""") + ['test', 1, {'foo': 3.1415920000000002}, 'bar'] + + Regardless of the JSON implementation used, the exceptions will be the same. + This means that trying to serialize something not compatible with JSON + raises a TypeError: + + >>> anyjson.serialize([object()]) + Traceback (most recent call last): + + TypeError: object is not JSON encodable + + And deserializing a JSON string with invalid JSON raises a ValueError: + + >>> anyjson.deserialize("""['missing square brace!""") + Traceback (most recent call last): + + ValueError: cannot parse JSON description + + + Contact + ------- + + The module is maintaned by Rune F. Halvorsen . + The project resides at http://bitbucket.org/runeh/anyjson . Bugs and feature + requests can be submitted there. Patches are also very welcome. + + Changelog + --------- + + See CHANGELOG file + + License + ------- + + see the LICENSE file + +Keywords: json +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Intended Audience :: Developers +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.4 +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.1 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: Implementation :: Jython diff --git a/anyjson.egg-info/SOURCES.txt b/anyjson.egg-info/SOURCES.txt new file mode 100644 index 0000000..6f348ce --- /dev/null +++ b/anyjson.egg-info/SOURCES.txt @@ -0,0 +1,14 @@ +CHANGELOG +LICENSE +MANIFEST.in +README +setup.py +anyjson/__init__.py +anyjson.egg-info/PKG-INFO +anyjson.egg-info/SOURCES.txt +anyjson.egg-info/dependency_links.txt +anyjson.egg-info/not-zip-safe +anyjson.egg-info/top_level.txt +tests/benchmark.py +tests/test_implementations.py +tests/test_implementations.pyc \ No newline at end of file diff --git a/anyjson.egg-info/dependency_links.txt b/anyjson.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/anyjson.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/anyjson.egg-info/not-zip-safe b/anyjson.egg-info/not-zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/anyjson.egg-info/not-zip-safe @@ -0,0 +1 @@ + diff --git a/anyjson.egg-info/top_level.txt b/anyjson.egg-info/top_level.txt new file mode 100644 index 0000000..93fe7af --- /dev/null +++ b/anyjson.egg-info/top_level.txt @@ -0,0 +1 @@ +anyjson diff --git a/anyjson/__init__.py b/anyjson/__init__.py new file mode 100644 index 0000000..1f671be --- /dev/null +++ b/anyjson/__init__.py @@ -0,0 +1,142 @@ +"""Wraps the best available JSON implementation available in a common +interface""" + +import sys + +VERSION = (0, 3, 3) +__version__ = ".".join(map(str, VERSION[0:3])) + "".join(VERSION[3:]) +__author__ = "Rune Halvorsen" +__contact__ = "runefh@gmail.com" +__homepage__ = "http://bitbucket.org/runeh/anyjson/" +__docformat__ = "restructuredtext" + +# -eof meta- + +#: The json implementation object. This is probably not useful to you, +#: except to get the name of the implementation in use. The name is +#: available through ``implementation.name``. +implementation = None + +# json.loads does not support buffer() objects, +# so we load() and StringIO instead, and it won't copy. +if sys.version_info[0] == 3: + from io import StringIO +else: + try: + from cStringIO import StringIO # noqa + except ImportError: + from StringIO import StringIO # noqa + +#: List of known json modules, and the names of their loads/dumps +#: methods, as well as the exceptions they throw. Exception can be either +#: an exception class or a string. +_modules = [("yajl", "dumps", TypeError, "loads", ValueError, "load"), + ("jsonlib2", "write", "WriteError", "read", "ReadError", None), + ("jsonlib", "write", "WriteError", "read", "ReadError", None), + ("simplejson", "dumps", TypeError, "loads", ValueError, "load"), + ("json", "dumps", TypeError, "loads", ValueError, "load"), + ("django.utils.simplejson", "dumps", TypeError, "loads", ValueError, "load"), + ("cjson", "encode", "EncodeError", "decode", "DecodeError", None) + ] + +_fields = ("modname", "encoder", "encerror", + "decoder", "decerror", "filedecoder") + + +class _JsonImplementation(object): + """Incapsulates a JSON implementation""" + + def __init__(self, modspec): + modinfo = dict(zip(_fields, modspec)) + + if modinfo["modname"] == "cjson": + import warnings + warnings.warn("cjson is deprecated! See http://pypi.python.org/pypi/python-cjson/1.0.5", DeprecationWarning) + + # No try block. We want importerror to end up at caller + module = self._attempt_load(modinfo["modname"]) + + self.implementation = modinfo["modname"] + self._encode = getattr(module, modinfo["encoder"]) + self._decode = getattr(module, modinfo["decoder"]) + fdec = modinfo["filedecoder"] + self._filedecode = fdec and getattr(module, fdec) + self._encode_error = modinfo["encerror"] + self._decode_error = modinfo["decerror"] + + if isinstance(modinfo["encerror"], basestring): + self._encode_error = getattr(module, modinfo["encerror"]) + if isinstance(modinfo["decerror"], basestring): + self._decode_error = getattr(module, modinfo["decerror"]) + + self.name = modinfo["modname"] + + def __repr__(self): + return "<_JsonImplementation instance using %s>" % self.name + + def _attempt_load(self, modname): + """Attempt to load module name modname, returning it on success, + throwing ImportError if module couldn't be imported""" + __import__(modname) + return sys.modules[modname] + + def dumps(self, data): + """Serialize the datastructure to json. Returns a string. Raises + TypeError if the object could not be serialized.""" + try: + return self._encode(data) + except self._encode_error, exc: + raise TypeError, TypeError(*exc.args), sys.exc_info()[2] + serialize = dumps + + def loads(self, s): + """deserialize the string to python data types. Raises + ValueError if the string could not be parsed.""" + # uses StringIO to support buffer objects. + try: + if self._filedecode and not isinstance(s, basestring): + return self._filedecode(StringIO(s)) + return self._decode(s) + except self._decode_error, exc: + raise ValueError, ValueError(*exc.args), sys.exc_info()[2] + deserialize = loads + + +def force_implementation(modname): + """Forces anyjson to use a specific json module if it's available""" + global implementation + for name, spec in [(e[0], e) for e in _modules]: + if name == modname: + implementation = _JsonImplementation(spec) + return + raise ImportError("No module named: %s" % modname) + + +if __name__ == "__main__": + # If run as a script, we do nothing but print an error message. + # We do NOT try to load a compatible module because that may throw an + # exception, which renders the package uninstallable with easy_install + # (It trys to execfile the script when installing, to make sure it works) + print "Running anyjson as a stand alone script is not supported" + sys.exit(1) +else: + for modspec in _modules: + try: + implementation = _JsonImplementation(modspec) + break + except ImportError: + pass + else: + raise ImportError("No supported JSON module found") + + + def loads(value): + """Serialize the object to JSON.""" + return implementation.loads(value) + deserialize = loads # compat + + + def dumps(value): + """Deserialize JSON-encoded object to a Python object.""" + return implementation.dumps(value) + serialize = dumps diff --git a/debian/NEWS b/debian/NEWS deleted file mode 100644 index 9d137e5..0000000 --- a/debian/NEWS +++ /dev/null @@ -1,7 +0,0 @@ -python-anyjson (0.3.1-1) unstable; urgency=low - - cjson has been moved to the lowest priority of the JSON - implementations. This has happened due to several encoding/decoding - bugs and the vanishing performance gap to other implementations. - - -- Fladischer Michael Fri, 15 Apr 2011 16:29:44 +0200 diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 01f09ac..0000000 --- a/debian/changelog +++ /dev/null @@ -1,63 +0,0 @@ -python-anyjson (0.3.3-1) unstable; urgency=low - - [ Jakub Wilk ] - * Use canonical URIs for Vcs-* fields. - - [ Michael Fladischer ] - * New upstream release. - * Bump Standards version to 3.9.4. - * Bump debhelper Build-Depends to >= 8.1.0~. - * Update years in d/copyright. - - -- Michael Fladischer Wed, 05 Jun 2013 14:40:51 +0200 - -python-anyjson (0.3.1-2) unstable; urgency=low - - * Change order of my name. - * Add anyjson.egg-info/PKG-INFO to d/clean to allow the package to be - built tice in a row (Closes: #671146). - * Update years in d/copyright. - * Use DEP5 1.0 format URL. - * Bump Standards version to 3.9.3. - * Remove d/s/local-options from SVN. - - -- Michael Fladischer Fri, 01 Jun 2012 16:31:39 +0200 - -python-anyjson (0.3.1-1) unstable; urgency=low - - * New upstream version (Closes: #620959). - - Drop python-cjson from Depends. - * Set PMPT as maintainer and myself as uploader. - * Switch to dh_python2. - * Switch to source format 3.0 (quilt). - * Use DEP5 for copyright file. - * Clean up after build. - * Streamline packaging code with wrap-and-sort. - * Extend regex in d/watch. - * Bumped Standards-Version to 3.9.2 (no change necessary). - * Set X-P-V to >= 2.4. - * Recommend either python (>= 2.6) or python-simplejson. - * Build for python3. - * Clean build directory. - - -- Fladischer Michael Wed, 06 Jul 2011 16:33:28 +0200 - -python-anyjson (0.2.3-1) unstable; urgency=low - - * New upstream release - * Added dependencies on python json modules (Closes: #570648, #569824) - * Updated Stanards version, no changes needed - - -- David Watson Thu, 18 Mar 2010 21:38:27 +0000 - -python-anyjson (0.2.2-2) unstable; urgency=low - - * Improve the long description (Closes: #554467). - - -- David Watson Fri, 06 Nov 2009 09:24:13 +0000 - -python-anyjson (0.2.2-1) unstable; urgency=low - - * Initial release (Closes: #551886) - - -- David Watson Wed, 21 Oct 2009 14:25:29 +0100 diff --git a/debian/clean b/debian/clean deleted file mode 100644 index 7442c46..0000000 --- a/debian/clean +++ /dev/null @@ -1,2 +0,0 @@ -anyjson.egg-info/PKG-INFO -anyjson.egg-info/SOURCES.txt diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7f8f011..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -7 diff --git a/debian/control b/debian/control deleted file mode 100644 index a5e9d26..0000000 --- a/debian/control +++ /dev/null @@ -1,39 +0,0 @@ -Source: python-anyjson -Section: python -Priority: optional -Maintainer: Debian Python Modules Team -Uploaders: David Watson , - Michael Fladischer -Build-Depends: debhelper (>= 8.1.0~), - python-all (>= 2.6.6-3~), - python-setuptools, - python3-all (>= 3.1.2-12~), - python3-setuptools -Standards-Version: 3.9.4 -X-Python-Version: >= 2.4 -X-Python3-Version: >= 3.0 -Homepage: http://bitbucket.org/runeh/anyjson/ -Vcs-Svn: svn://anonscm.debian.org/python-modules/packages/python-anyjson/trunk/ -Vcs-Browser: http://anonscm.debian.org/viewvc/python-modules/packages/python-anyjson/trunk/ - -Package: python-anyjson -Architecture: all -Depends: ${misc:Depends}, ${python:Depends} -Recommends: python (>= 2.6) | python-simplejson -Description: Common interface for the best available JSON implementation - Loads whichever is the fastest JSON module installed and provides a uniform - API regardless of which JSON implementation is used. The exceptions will also - be the same whichever JSON module is used. - The ranking of the JSON implementations is based on a benchmark. - -Package: python3-anyjson -Architecture: all -Depends: ${misc:Depends}, ${python3:Depends} -Description: Common interface for the best available JSON implementation (Python3 version) - Loads whichever is the fastest JSON module installed and provides a uniform - API regardless of which JSON implementation is used. The exceptions will also - be the same whichever JSON module is used. - The ranking of the JSON implementations is based on a benchmark. - . - This package contains the Python 3 version of the library. - diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index c91783b..0000000 --- a/debian/copyright +++ /dev/null @@ -1,39 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: anyjson -Upstream-Contact: Rune Halvorsen -Source: http://pypi.python.org/pypi/anyjson/ - -Files: * -Copyright: 2009, Rune Halvorsen -License: BSD-anyjson - -Files: debian/* -Copyright: 2011-2013, Fladischer Michael - 2009, David Watson -License: BSD-anyjson - -License: BSD-anyjson - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - . - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - . - Neither the name of the authors nor the names of its contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. diff --git a/debian/python-anyjson.docs b/debian/python-anyjson.docs deleted file mode 100644 index e845566..0000000 --- a/debian/python-anyjson.docs +++ /dev/null @@ -1 +0,0 @@ -README diff --git a/debian/python3-anyjson.docs b/debian/python3-anyjson.docs deleted file mode 100644 index e845566..0000000 --- a/debian/python3-anyjson.docs +++ /dev/null @@ -1 +0,0 @@ -README diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 98974c8..0000000 --- a/debian/rules +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/make -f - -PYVERS := $(shell pyversions -r) -PY3VERS := $(shell py3versions -r) - -%: - dh $@ --with python2,python3 - -override_dh_auto_build: - set -e; \ - for py in $(PYVERS) $(PY3VERS); do \ - $$py setup.py build; \ - done - -override_dh_auto_clean: - rm -rf build - -override_dh_auto_install: - set -e; \ - for py in $(PYVERS); do \ - $$py setup.py install --skip-build --root debian/python-anyjson \ - --install-layout deb; \ - done - set -e; \ - for py in $(PY3VERS); do \ - $$py setup.py install --skip-build --root debian/python3-anyjson \ - --install-layout deb; \ - done diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 163aaf8..0000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/debian/watch b/debian/watch deleted file mode 100644 index f8f1e98..0000000 --- a/debian/watch +++ /dev/null @@ -1,2 +0,0 @@ -version=3 -http://pypi.python.org/packages/source/a/anyjson/anyjson-([\d\.]+)\.tar\.gz diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..861a9f5 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,5 @@ +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..9fe4902 --- /dev/null +++ b/setup.py @@ -0,0 +1,100 @@ +import os +import sys + +extra = {} +if sys.version_info >= (3, 0): + extra.update(use_2to3=True) + +try: + from setuptools import setup, find_packages +except ImportError: + from distutils.core import setup, find_packages + +# -*- Distribution Meta -*- +import re +re_meta = re.compile(r'__(\w+?)__\s*=\s*(.*)') +re_vers = re.compile(r'VERSION\s*=\s*\((.*?)\)') +re_doc = re.compile(r'^"""(.+?)"""', re.M|re.S) +rq = lambda s: s.strip("\"'") + +def add_default(m): + attr_name, attr_value = m.groups() + return ((attr_name, rq(attr_value)), ) + + +def add_version(m): + v = list(map(rq, m.groups()[0].split(", "))) + return (("VERSION", ".".join(v[0:3]) + "".join(v[3:])), ) + + +def add_doc(m): + return (("doc", m.groups()[0].replace("\n", " ")), ) + +pats = {re_meta: add_default, + re_vers: add_version} +here = os.path.abspath(os.path.dirname(__file__)) +meta_fh = open(os.path.join(here, "anyjson/__init__.py")) +try: + meta = {} + acc = [] + for line in meta_fh: + if line.strip() == '# -eof meta-': + break + acc.append(line) + for pattern, handler in pats.items(): + m = pattern.match(line.strip()) + if m: + meta.update(handler(m)) + m = re_doc.match("".join(acc).strip()) + if m: + meta.update(add_doc(m)) +finally: + meta_fh.close() + + +supported = ["yajl", "jsonlib2", "jsonlib", "simplejson", + "json", "django.utils.simplejson", "cjson"] +install_requires = [] +for module in supported: + try: + __import__(module) + break + except ImportError: + pass +else: + install_requires.append("simplejson") + + +setup(name='anyjson', + version=meta["VERSION"], + description=meta["doc"], + author=meta["author"], + author_email=meta["contact"], + url=meta["homepage"], + license='BSD', + long_description=open("README").read(), + install_requires=install_requires, + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent', + 'Intended Audience :: Developers', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.4', + 'Programming Language :: Python :: 2.5', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.1', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', + 'Programming Language :: Python :: Implementation :: Jython', + ], + keywords='json', + packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), + zip_safe=False, + platforms=["any"], + test_suite = 'nose.collector', + **extra +) diff --git a/tests/benchmark.py b/tests/benchmark.py new file mode 100644 index 0000000..220b2c1 --- /dev/null +++ b/tests/benchmark.py @@ -0,0 +1,143 @@ +""" +Simple benchmark script to do some basic speed tests of json libs +""" + +import sys +import time +import urllib + +_small = """ +{ + "name": "benchmark test", + "foo": "bar", + "age": 32, + "weight": 100, + "Height": 154.12, + "married": false, + "siblings": [], + "bar": null +} +""" + +_deep = """ +{ + "foo": "bar", + "nest": { + "foo": %(_small)s, + "nest": { + "foo": %(_small)s, + "nest": { + "foo": %(_small)s, + "nest": { + "foo": %(_small)s, + "nest": { + "foo": %(_small)s, + "nest": %(_small)s + } + } + } + } + } +} +""" % locals() + +_big = """ +{ + "biglist": [%(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_deep)s, %(_small)s, %(_deep)s, %(_small)s, %(_deep)s, + %(_small)s, %(_small)s, %(_small)s, %(_small)s, %(_small)s], + "entry1": %(_small)s, + "entry2": %(_deep)s, + "entry3": %(_small)s, + "entry4": %(_deep)s, + "entry5": %(_small)s, + "entry6": %(_deep)s +} +""" % locals() + +# The following two will contain real world json from twitter and reddit if +# script is run with the --download flag +_reddit = "[]" +_twitter = "[]" + +def load_external_json(): + global _reddit, _twitter + _reddit = urllib.urlopen("http://reddit.com/.json").read() + _twitter = urllib.urlopen("http://api.twitter.com/1/statuses/user_timeline.json?screen_name=twitterapi&count=200").read() + + +def do_benchmark(impspec, json, runs=10): + modulename, parsename, emitname = impspec + + try: + __import__(modulename) + mod = sys.modules[modulename] + reads = getattr(mod, parsename) + dumps = getattr(mod, emitname) + except: + return None + + start = time.time() + for n in xrange(runs): + data = reads(json) + + readtime = time.time() - start + + start = time.time() + for n in xrange(runs): + devnull = dumps(data) + + return readtime, time.time() - start # tuple (readtime, writetime) + + +modules = [("json", "loads", "dumps"), + ("simplejson", "loads", "dumps"), + ("yajl", "loads", "dumps"), + ("cjson", "decode", "encode"), + ("django.utils.simplejson", "loads", "dumps"), + ("jsonpickle", "decode", "encode"), + ("jsonlib", "read", "write"), + ("jsonlib2", "read", "write"), + #("demjson", "decode"), terribly slow. wont include it + ] + +if len(sys.argv) > 1 and sys.argv[1] == "--download": + load_external_json() + +res = [] +runs = 100 +for e in modules: + res.append((e[0], do_benchmark(e, _small, runs), + do_benchmark(e, _deep , runs), + do_benchmark(e, _big, runs), + do_benchmark(e, _reddit, runs), + do_benchmark(e, _twitter, runs), + )) + +no_res = set([e for e in res if e[1] is None]) +res = list(set(res) - no_res) +res = [(e[0], sum(map(lambda x:x[0], e[1:])), sum(map(lambda x:x[1], e[1:]))) for e in res] + +res.sort(lambda a,b: cmp((a[1]+a[2]), b[1]+b[2])) + +print "Total Read Write Implementation" +print "-----------------------------------" +for e in res: + print "%.3f %.3f %.3f %s" % (e[1]+e[2], e[1], e[2], e[0]) +for e in no_res: + print "Not installed:", e[0] diff --git a/tests/test_implementations.py b/tests/test_implementations.py new file mode 100644 index 0000000..c6f0df2 --- /dev/null +++ b/tests/test_implementations.py @@ -0,0 +1,57 @@ +from nose.tools import assert_raises +import anyjson + +modnames = [e[0] for e in anyjson._modules] + +def test_default_serialization(): + assert anyjson.dumps([1,2,3]).replace(" ", "") == "[1,2,3]" + assert anyjson.serialize([1,2,3]).replace(" ", "") == "[1,2,3]" + + +def test_default_deserialization(): + assert anyjson.loads("[1,2,3]") == [1,2,3] + assert anyjson.deserialize("[1,2,3]") == [1,2,3] + + +def test_forced_serialization(): + for name in modnames: + try: + anyjson.force_implementation(name) + except ImportError: + continue # module can't be tested, try next + + assert anyjson.dumps([1,2,3]).replace(" ", "") == "[1,2,3]" + assert anyjson.serialize([1,2,3]).replace(" ", "") == "[1,2,3]" + + +def test_forced_deserialization(): + for name in modnames: + try: + anyjson.force_implementation(name) + except ImportError: + continue # module can't be tested, try next + + assert anyjson.loads("[1,2,3]") == [1,2,3] + assert anyjson.deserialize("[1,2,3]") == [1,2,3] + + +def test_exceptions(): + for name in modnames: + try: + anyjson.force_implementation(name) + except ImportError: + continue # module can't be tested, try next + + assert_raises(TypeError, anyjson.dumps, [object()]) + assert_raises(TypeError, anyjson.serialize, [object()]) + assert_raises(ValueError, anyjson.loads, "[") + assert_raises(ValueError, anyjson.deserialize, "[") + + +def test_json_loads_unicode(): + try: + anyjson.force_implementation("json") + except ImportError: + return + + assert "foo" in anyjson.loads(u'{"foo": "bar"}') diff --git a/tests/test_implementations.pyc b/tests/test_implementations.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b54b4d3ff3d6c7d88c57a37e127fbbf1b4d99fd0 GIT binary patch literal 2567 zcmcIlU2hvz5S_dJP8vu`1q$#GMWymXRTs(=0z^eCfrN~-MYIG3v-RGj>#TR(z1L9! zlm`Ml_6^>6=7;eU_yKUvtR35ls|u7l$z*o!_}Cz@8cgJzEqt$t5@%gEK|~fx{ulv= z^2Cb_46DXYsAs<-Cq@SFQC>|>;MC=&?8TZ-^9Mnx%ToTY! zcrYKga6Ag(`qyt?f9LwG-F6MWXCTUs2QJS%1Mzq`avCk{D2@8ozl7**eaR%x?iNK} z_!dHV>m*8(?`#_nGBfT2Ja!)CL)$6FnSIoW?V(Nc(a>hTGdZc_t@BQ8FBy(f%f-lJ ze|KYa>|e(Y%;?2-FB+%5H$6*J>R5GE7%?}^d8j|*m#0tz;Sz0t48RHRRq??T-U{Je zlJm(VM>8zvPi!Q6WeL=F94`FdCELcv(pqR7BGS8Y6%so zz}l3Rf518VooL2;(8d0c_qM{k3~Q{4iuV`CBRiu#hEybfIIw-My!Y(H zmr**NXWG^Vr_Pl4Eydq7}738K7Ova%XS&JWpN7j8YSu z@OqHRaf-Wxl(FSxG9L2I2&q8f2F