From 6f6dbfadefa68d44e3acb042d8da5411575f6925 Mon Sep 17 00:00:00 2001 From: Stephen Finucane <stephenfin@redhat.com> Date: Tue, 30 Apr 2019 17:36:40 -0600 Subject: [PATCH] Remove simplejson support This was allegedly included back when simplejson was more performant that the 'json' library in Python's library. It's additional complexity that we simple don't need. Remove it. This also allows us to clean up the tox file significantly. Note that we must also rename the 'json' module to 'json_utils', as this was shadowing a built-in library. This is a latent issue that was highlighted by removing of 'simplejson' imports. Change-Id: Id9faa9859993e598e2fd08133de576b740790bf3 Signed-off-by: Stephen Finucane <stephenfin@redhat.com> --- README.rst | 3 +-- tox.ini | 39 ---------------------------- wsme/rest/args.py | 4 +-- wsme/rest/{json.py => json_utils.py} | 11 ++------ wsme/rest/protocol.py | 4 +-- wsme/rest/{xml.py => xml_utils.py} | 0 wsme/tests/test_api.py | 8 +++--- wsme/tests/test_restjson.py | 22 ++++++---------- wsme/tests/test_restxml.py | 11 ++++---- wsmeext/flask.py | 20 +++++++------- wsmeext/pecan.py | 17 ++++++------ wsmeext/sphinxext.py | 19 ++++++-------- 12 files changed, 50 insertions(+), 108 deletions(-) rename wsme/rest/{json.py => json_utils.py} (98%) rename wsme/rest/{xml.py => xml_utils.py} (100%) diff --git a/README.rst b/README.rst index fbae79f..dd56e13 100644 --- a/README.rst +++ b/README.rst @@ -60,8 +60,7 @@ Main features - Framework independence : adapters are provided to easily integrate your API in any web framework, for example a wsgi container, Pecan_, Flask_, ... -- Very few runtime dependencies: webob, simplegeneric. Optionally - simplejson if you need better performances. +- Very few runtime dependencies: webob, simplegeneric. - Integration in `Sphinx`_ for making clean documentation with ``wsmeext.sphinxext``. diff --git a/tox.ini b/tox.ini index c3eb013..f4c4452 100644 --- a/tox.ini +++ b/tox.ini @@ -87,16 +87,6 @@ deps = {[common]basedeps} basepython = python2.7 -[testenv:py27-simplejson] -commands = - {envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests tests/pecantest tests/test_sphinxext.py tests/test_flask.py --verbose {posargs} - {envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py -deps = - {[common]testtools} - {[common]basedeps} - simplejson -basepython = python2.7 - [testenv:py35] commands = {envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests tests/pecantest tests/test_sphinxext.py tests/test_flask.py --verbose {posargs} @@ -106,16 +96,6 @@ deps = {[common]basedeps} basepython = python3.5 -[testenv:py35-simplejson] -commands = - {envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests tests/pecantest tests/test_sphinxext.py tests/test_flask.py --verbose {posargs} - {envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py -deps = - {[common]testtools} - {[common]basedeps} - simplejson -basepython = python3.5 - [testenv:py36] commands = {envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests tests/pecantest tests/test_sphinxext.py tests/test_flask.py --verbose {posargs} @@ -125,16 +105,6 @@ deps = {[common]basedeps} basepython = python3.6 -[testenv:py36-simplejson] -commands = - {envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests tests/pecantest tests/test_sphinxext.py tests/test_flask.py --verbose {posargs} - {envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py -deps = - {[common]testtools} - {[common]basedeps} - simplejson -basepython = python3.6 - [testenv:pypy] commands = {envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests tests/pecantest tests/test_sphinxext.py tests/test_flask.py --verbose {posargs} @@ -142,12 +112,3 @@ commands = deps = {[common]testtools} {[common]basedeps} - -[testenv:pypy-simplejson] -commands = - {envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests tests/pecantest tests/test_sphinxext.py tests/test_flask.py --verbose {posargs} - {envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py -deps = - {[common]testtools} - {[common]basedeps} - simplejson diff --git a/wsme/rest/args.py b/wsme/rest/args.py index 9dc16c7..2a49672 100644 --- a/wsme/rest/args.py +++ b/wsme/rest/args.py @@ -216,8 +216,8 @@ def args_from_params(funcdef, params): def args_from_body(funcdef, body, mimetype): - from wsme.rest import json as restjson - from wsme.rest import xml as restxml + from wsme.rest import json_utils as restjson + from wsme.rest import xml_utils as restxml if funcdef.body_type is not None: datatypes = {funcdef.arguments[-1].name: funcdef.body_type} diff --git a/wsme/rest/json.py b/wsme/rest/json_utils.py similarity index 98% rename from wsme/rest/json.py rename to wsme/rest/json_utils.py index 48bd082..a7c2f4f 100644 --- a/wsme/rest/json.py +++ b/wsme/rest/json_utils.py @@ -1,11 +1,10 @@ """REST+Json protocol implementation.""" -from __future__ import absolute_import import datetime import decimal - -import six +import json from simplegeneric import generic +import six import wsme.exc import wsme.types @@ -13,12 +12,6 @@ from wsme.types import Unset import wsme.utils -try: - import simplejson as json -except ImportError: - import json # noqa - - content_type = 'application/json' accept_content_types = [ content_type, diff --git a/wsme/rest/protocol.py b/wsme/rest/protocol.py index 5201ccf..7748635 100644 --- a/wsme/rest/protocol.py +++ b/wsme/rest/protocol.py @@ -25,8 +25,8 @@ class RestProtocol(Protocol): self.content_types = [] for dataformat in dataformats: - __import__('wsme.rest.' + dataformat) - dfmod = getattr(wsme.rest, dataformat) + __import__('wsme.rest.' + dataformat + '_utils') + dfmod = getattr(wsme.rest, dataformat + '_utils') self.dataformats[dataformat] = dfmod self.content_types.extend(dfmod.accept_content_types) diff --git a/wsme/rest/xml.py b/wsme/rest/xml_utils.py similarity index 100% rename from wsme/rest/xml.py rename to wsme/rest/xml_utils.py diff --git a/wsme/tests/test_api.py b/wsme/tests/test_api.py index fc1e157..f371340 100644 --- a/wsme/tests/test_api.py +++ b/wsme/tests/test_api.py @@ -80,8 +80,8 @@ class TestController(unittest.TestCase): headers={'Accept': 'application/json'}) self.assertTrue( res.json_body['faultstring'].startswith( - "Invalid input for field/attribute number. Value: 'arf'. \ -Value should be one of:")) + "Invalid input for field/attribute number. Value: 'arf'. " + "Value should be one of:")) self.assertIn('v1', res.json_body['faultstring']) self.assertIn('v2', res.json_body['faultstring']) self.assertIn('None', res.json_body['faultstring']) @@ -104,8 +104,8 @@ Value should be one of:")) headers={'Accept': 'application/json'}) self.assertTrue( res.json_body['faultstring'].startswith( - "Invalid input for field/attribute number. Value: '1'. \ -Value should be one of:")) + "Invalid input for field/attribute number. Value: '1'. " + "Value should be one of:")) self.assertIn('v1', res.json_body['faultstring']) self.assertIn('v2', res.json_body['faultstring']) self.assertIn('None', res.json_body['faultstring']) diff --git a/wsme/tests/test_restjson.py b/wsme/tests/test_restjson.py index 7afbb86..eca8e47 100644 --- a/wsme/tests/test_restjson.py +++ b/wsme/tests/test_restjson.py @@ -1,21 +1,15 @@ import base64 import datetime import decimal +import json -import wsme.tests.protocol - -try: - import simplejson as json -except ImportError: - import json # noqa - -from wsme.rest.json import fromjson, tojson, parse -from wsme.utils import parse_isodatetime, parse_isotime, parse_isodate +from wsme.exc import ClientSideError, InvalidInput from wsme.types import isarray, isdict, isusertype, register_type from wsme.types import UserType, ArrayType, DictType from wsme.rest import expose, validate -from wsme.exc import ClientSideError, InvalidInput - +from wsme.rest.json_utils import fromjson, tojson, parse +import wsme.tests.protocol +from wsme.utils import parse_isodatetime, parse_isotime, parse_isodate import six from six import b, u @@ -569,7 +563,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): v.aint = 4 v.astr = 's' - r = wsme.rest.json.encode_sample_value(MyType, v, True) + r = wsme.rest.json_utils.encode_sample_value(MyType, v, True) print(r) assert r[0] == ('javascript') assert r[1] == json.dumps({'aint': 4, 'astr': 's'}, ensure_ascii=False, @@ -580,7 +574,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): assert tojson(wsme.types.bytes, b('ascii')) == u('ascii') def test_encode_sample_params(self): - r = wsme.rest.json.encode_sample_params( + r = wsme.rest.json_utils.encode_sample_params( [('a', int, 2)], True ) assert r[0] == 'javascript', r[0] @@ -589,7 +583,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): }''', r[1] def test_encode_sample_result(self): - r = wsme.rest.json.encode_sample_result( + r = wsme.rest.json_utils.encode_sample_result( int, 2, True ) assert r[0] == 'javascript', r[0] diff --git a/wsme/tests/test_restxml.py b/wsme/tests/test_restxml.py index b677a65..3fc01fe 100644 --- a/wsme/tests/test_restxml.py +++ b/wsme/tests/test_restxml.py @@ -5,11 +5,10 @@ import base64 from six import u, b import six +from wsme.rest.xml_utils import fromxml, toxml import wsme.tests.protocol -from wsme.utils import parse_isodatetime, parse_isodate, parse_isotime from wsme.types import isarray, isdict, isusertype, register_type - -from wsme.rest.xml import fromxml, toxml +from wsme.utils import parse_isodatetime, parse_isodate, parse_isotime try: import xml.etree.ElementTree as et @@ -165,7 +164,7 @@ class TestRestXML(wsme.tests.protocol.RestOnlyProtocolTestCase): value.aint = 5 value.atext = u('test') - language, sample = wsme.rest.xml.encode_sample_value( + language, sample = wsme.rest.xml_utils.encode_sample_value( MyType, value, True) print(language, sample) @@ -176,13 +175,13 @@ class TestRestXML(wsme.tests.protocol.RestOnlyProtocolTestCase): </value>""") def test_encode_sample_params(self): - lang, content = wsme.rest.xml.encode_sample_params( + lang, content = wsme.rest.xml_utils.encode_sample_params( [('a', int, 2)], True) assert lang == 'xml', lang assert content == b('<parameters>\n <a>2</a>\n</parameters>'), content def test_encode_sample_result(self): - lang, content = wsme.rest.xml.encode_sample_result(int, 2, True) + lang, content = wsme.rest.xml_utils.encode_sample_result(int, 2, True) assert lang == 'xml', lang assert content == b('<result>2</result>'), content diff --git a/wsmeext/flask.py b/wsmeext/flask.py index 4d9e446..d6e57ab 100644 --- a/wsmeext/flask.py +++ b/wsmeext/flask.py @@ -5,22 +5,22 @@ import logging import sys import inspect +import flask + import wsme import wsme.api -import wsme.rest.json -import wsme.rest.xml import wsme.rest.args +import wsme.rest.json_utils +import wsme.rest.xml_utils from wsme.utils import is_valid_code -import flask - log = logging.getLogger(__name__) TYPES = { - 'application/json': wsme.rest.json, - 'application/xml': wsme.rest.xml, - 'text/xml': wsme.rest.xml + 'application/json': wsme.rest.json_utils, + 'application/xml': wsme.rest.xml_utils, + 'text/xml': wsme.rest.xml_utils, } @@ -35,9 +35,9 @@ def get_dataformat(): if req_dataformat in TYPES: return TYPES[req_dataformat] - log.info('''Could not determine what format is wanted by the - caller, falling back to json''') - return wsme.rest.json + log.info('Could not determine what format is wanted by the caller, ' + 'falling back to JSON') + return wsme.rest.json_utils def signature(*args, **kw): diff --git a/wsmeext/pecan.py b/wsmeext/pecan.py index 9d63dde..474c45e 100644 --- a/wsmeext/pecan.py +++ b/wsmeext/pecan.py @@ -4,13 +4,12 @@ import functools import inspect import sys -import wsme -import wsme.rest.args -import wsme.rest.json -import wsme.rest.xml - import pecan +import wsme +import wsme.rest.args +import wsme.rest.json_utils +import wsme.rest.xml_utils from wsme.utils import is_valid_code @@ -22,8 +21,8 @@ class JSonRenderer(object): @staticmethod def render(template_path, namespace): if 'faultcode' in namespace: - return wsme.rest.json.encode_error(None, namespace) - return wsme.rest.json.encode_result( + return wsme.rest.json_utils.encode_error(None, namespace) + return wsme.rest.json_utils.encode_result( namespace['result'], namespace['datatype'] ) @@ -37,8 +36,8 @@ class XMLRenderer(object): @staticmethod def render(template_path, namespace): if 'faultcode' in namespace: - return wsme.rest.xml.encode_error(None, namespace) - return wsme.rest.xml.encode_result( + return wsme.rest.xml_utils.encode_error(None, namespace) + return wsme.rest.xml_utils.encode_result( namespace['result'], namespace['datatype'] ) diff --git a/wsmeext/sphinxext.py b/wsmeext/sphinxext.py index 7c45a0f..4ca5370 100644 --- a/wsmeext/sphinxext.py +++ b/wsmeext/sphinxext.py @@ -2,26 +2,23 @@ import inspect import re import sys +from docutils.parsers.rst import Directive +from docutils.parsers.rst import directives import six - from sphinx import addnodes from sphinx.ext import autodoc from sphinx.domains.python import PyClasslike, PyClassmember from sphinx.domains import Domain, ObjType from sphinx.directives import ObjectDescription +from sphinx.locale import l_, _ +from sphinx.roles import XRefRole from sphinx.util.docfields import Field from sphinx.util.nodes import make_refnode -from sphinx.roles import XRefRole -from sphinx.locale import l_, _ - -from docutils.parsers.rst import Directive -from docutils.parsers.rst import directives - import wsme +import wsme.rest.json_utils +import wsme.rest.xml_utils import wsme.types -import wsme.rest.json -import wsme.rest.xml field_re = re.compile(r':(?P<field>\w+)(\s+(?P<name>\w+))?:') @@ -56,10 +53,10 @@ def get_protocols(names): protocols.extend('restjson', 'restxml') if 'restjson' in names: names.remove('restjson') - protocols.append(('Json', wsme.rest.json)) + protocols.append(('Json', wsme.rest.json_utils)) if 'restxml' in names: names.remove('restxml') - protocols.append(('XML', wsme.rest.xml)) + protocols.append(('XML', wsme.rest.xml_utils)) for name in names: p = wsme.protocol.getprotocol(name) protocols.append((p.displayname or p.name, p))