Initial import from tarball

This commit is contained in:
Jérôme Schneider 2014-10-31 18:25:51 +01:00
commit 49048a26cb
15 changed files with 792 additions and 0 deletions

66
CHANGELOG Normal file
View File

@ -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

29
LICENSE Normal file
View File

@ -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.

4
MANIFEST.in Normal file
View File

@ -0,0 +1,4 @@
include CHANGELOG
include README
include LICENSE
graft tests

85
PKG-INFO Normal file
View File

@ -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):
<snipped traceback>
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):
<snipped traceback>
ValueError: cannot parse JSON description
Contact
-------
The module is maintaned by Rune F. Halvorsen <runefh@gmail.com>.
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

59
README Normal file
View File

@ -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):
<snipped traceback>
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):
<snipped traceback>
ValueError: cannot parse JSON description
Contact
-------
The module is maintaned by Rune F. Halvorsen <runefh@gmail.com>.
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

85
anyjson.egg-info/PKG-INFO Normal file
View File

@ -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):
<snipped traceback>
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):
<snipped traceback>
ValueError: cannot parse JSON description
Contact
-------
The module is maintaned by Rune F. Halvorsen <runefh@gmail.com>.
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

View File

@ -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

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@
anyjson

142
anyjson/__init__.py Normal file
View File

@ -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

5
setup.cfg Normal file
View File

@ -0,0 +1,5 @@
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0

100
setup.py Normal file
View File

@ -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
)

143
tests/benchmark.py Normal file
View File

@ -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]

View File

@ -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"}')