Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace ujson #2737

Merged
merged 15 commits into from
Jul 2, 2021
4 changes: 3 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ This document describes changes between each past release.
14.3.0 (unreleased)
-------------------

- Nothing changed yet.
**Internal changes**

- Replace ujson with rapidjson. (#2677)


14.2.0 (2021-02-22)
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,4 @@ Contributors
* Victor Zhuang <[email protected]>
* Shivasheesh Yadav <[email protected]>
* Fabian Chong <@feiming>
* Dan Milgram <[email protected]>
4 changes: 2 additions & 2 deletions kinto/core/initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ def setup_json_serializer(config):
import requests
import webob

# Monkey patch to use ujson
# Monkey patch to use rapidjson
webob.request.json = utils.json
requests.models.json = utils.json

# Override json renderer using ujson
# Override json renderer using rapidjson
renderer = JSONRenderer(serializer=utils.json_serializer)
config.add_renderer("ultrajson", renderer) # See `kinto.core.Service`

Expand Down
19 changes: 16 additions & 3 deletions kinto/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from urllib.parse import unquote

import jsonpatch
import ujson as json
import rapidjson
from colander import null
from cornice import cors
from pyramid import httpexceptions
Expand All @@ -32,8 +32,21 @@
memcache = None


def json_serializer(v, **kw):
return json.dumps(v, escape_forward_slashes=False)
class json:
def dumps(v, **kw):
kw.setdefault("bytes_mode", rapidjson.BM_NONE)
return rapidjson.dumps(v, **kw)

def load(v, **kw):
kw.setdefault("number_mode", rapidjson.NM_NATIVE)
return rapidjson.load(v, **kw)

def loads(v, **kw):
kw.setdefault("number_mode", rapidjson.NM_NATIVE)
return rapidjson.loads(v, **kw)


json_serializer = json.dumps


def strip_whitespace(v):
Expand Down
2 changes: 1 addition & 1 deletion kinto/plugins/quotas/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@


def record_size(record):
# We cannot use ultrajson here, since the `separator` option is not available.
# We cannot use rapidjson here, since the `separator` option is not available.
canonical_json = json.dumps(record, sort_keys=True, separators=(",", ":"))
return len(canonical_json)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ requests==2.25.1
SQLAlchemy==1.4.9
statsd==3.3.0
transaction==3.0.1
ujson==4.0.2
python-rapidjson==1.0.0
waitress==2.0.0
Werkzeug==1.0.1
zope.sqlalchemy==1.3
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ install_requires =
pyramid_tm
requests
waitress
ujson
python-rapidjson
tests_require =
bravado_core
pytest
Expand Down
24 changes: 24 additions & 0 deletions tests/test_views_schema_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,3 +385,27 @@ def setUp(self):

def test_records_are_valid_if_match_schema(self):
self.app.post_json(RECORDS_URL, {"data": {"title": "b"}}, headers=self.headers, status=400)


class RecordsWithLargeNumbers(BaseWebTestWithSchema, unittest.TestCase):
def setUp(self):
super().setUp()
self.app.put_json(COLLECTION_URL, {"data": {"schema": SCHEMA}}, headers=self.headers)

def test_record_with_number_less_than_64_bits(self):
size = 2 ** 63
self.app.post_json(
RECORDS_URL,
{"data": {"title": "Very large file", "file": {"size": size}}},
headers=self.headers,
status=201,
)

def test_record_with_number_greater_than_64_bits(self):
size = 2 ** 65
self.app.post_json(
RECORDS_URL,
{"data": {"title": "Very large file", "file": {"size": size}}},
headers=self.headers,
status=201,
)