changeset 8120:58b6e4cd6fe9

lib: clean up ext_json and how it is used - avoid monkey patching Note that py3 json.dumps will return ASCII (with all unicode escaped) encoded as str. But we generally want JSON as bytes (which json.loads also can read), so also wrap the result with ascii_bytes in many places.
author Mads Kiilerich <mads@kiilerich.com>
date Sat, 28 Dec 2019 13:38:22 +0100
parents 7e22c4b909b2
children 7aff9d527bf1
files kallithea/bin/base.py kallithea/bin/kallithea_api.py kallithea/bin/kallithea_gist.py kallithea/bin/ldap_sync.py kallithea/controllers/api/__init__.py kallithea/controllers/summary.py kallithea/lib/auth_modules/auth_crowd.py kallithea/lib/base.py kallithea/lib/celerylib/tasks.py kallithea/lib/compat.py kallithea/lib/ext_json.py kallithea/lib/utils2.py kallithea/model/db.py kallithea/model/gist.py kallithea/tests/api/api_base.py
diffstat 15 files changed, 94 insertions(+), 95 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/bin/base.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/bin/base.py	Sat Dec 28 13:38:22 2019 +0100
@@ -31,7 +31,8 @@
 import sys
 import urllib2
 
-from kallithea.lib.compat import json
+from kallithea.lib import ext_json
+from kallithea.lib.utils2 import ascii_bytes
 
 
 CONFIG_NAME = '.config/kallithea'
@@ -68,11 +69,11 @@
     apihost = apihost.rstrip('/')
     id_ = random.randrange(1, 9999)
     req = urllib2.Request('%s/_admin/api' % apihost,
-                      data=json.dumps(_build_data(id_)),
+                      data=ascii_bytes(ext_json.dumps(_build_data(id_))),
                       headers={'content-type': 'text/plain'})
     ret = urllib2.urlopen(req)
     raw_json = ret.read()
-    json_data = json.loads(raw_json)
+    json_data = ext_json.loads(raw_json)
     id_ret = json_data['id']
     if id_ret == id_:
         return json_data
@@ -128,7 +129,7 @@
         if os.path.exists(self._conf_name):
             update = True
         with open(self._conf_name, 'wb') as f:
-            json.dump(config, f, indent=4)
+            ext_json.dump(config, f, indent=4)
             f.write('\n')
 
         if update:
@@ -146,7 +147,7 @@
         config = {}
         try:
             with open(self._conf_name, 'rb') as conf:
-                config = json.load(conf)
+                config = ext_json.load(conf)
         except IOError as e:
             sys.stderr.write(str(e) + '\n')
 
@@ -159,7 +160,7 @@
         """
         try:
             with open(self._conf_name, 'rb') as conf:
-                return json.load(conf)
+                return ext_json.load(conf)
         except IOError as e:
             #sys.stderr.write(str(e) + '\n')
             pass
--- a/kallithea/bin/kallithea_api.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/bin/kallithea_api.py	Sat Dec 28 13:38:22 2019 +0100
@@ -28,9 +28,10 @@
 from __future__ import print_function
 
 import argparse
+import json
 import sys
 
-from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call, json
+from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call
 
 
 def argparser(argv):
--- a/kallithea/bin/kallithea_gist.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/bin/kallithea_gist.py	Sat Dec 28 13:38:22 2019 +0100
@@ -29,11 +29,12 @@
 
 import argparse
 import fileinput
+import json
 import os
 import stat
 import sys
 
-from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call, json
+from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call
 
 
 def argparser(argv):
--- a/kallithea/bin/ldap_sync.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/bin/ldap_sync.py	Sat Dec 28 13:38:22 2019 +0100
@@ -33,7 +33,8 @@
 
 import ldap
 
-from kallithea.lib.compat import json
+from kallithea.lib import ext_json
+from kallithea.lib.utils2 import ascii_bytes
 
 
 config = ConfigParser()
@@ -80,12 +81,12 @@
         uid = str(uuid.uuid1())
         data = self.get_api_data(uid, method, args)
 
-        data = json.dumps(data)
+        data = ascii_bytes(ext_json.dumps(data))
         headers = {'content-type': 'text/plain'}
         req = urllib2.Request(self.url, data, headers)
 
         response = urllib2.urlopen(req)
-        response = json.load(response)
+        response = ext_json.load(response)
 
         if uid != response["id"]:
             raise InvalidResponseIDError("UUID does not match.")
--- a/kallithea/controllers/api/__init__.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/controllers/api/__init__.py	Sat Dec 28 13:38:22 2019 +0100
@@ -35,11 +35,11 @@
 from tg import Response, TGController, request, response
 from webob.exc import HTTPError, HTTPException
 
+from kallithea.lib import ext_json
 from kallithea.lib.auth import AuthUser
 from kallithea.lib.base import _get_ip_addr as _get_ip
 from kallithea.lib.base import get_path_info
-from kallithea.lib.compat import json
-from kallithea.lib.utils2 import safe_str
+from kallithea.lib.utils2 import ascii_bytes, safe_str
 from kallithea.model.db import User
 
 
@@ -121,7 +121,7 @@
         raw_body = environ['wsgi.input'].read(length)
 
         try:
-            json_body = json.loads(raw_body)
+            json_body = ext_json.loads(raw_body)
         except ValueError as e:
             # catch JSON errors Here
             raise JSONRPCErrorResponse(retid=self._req_id,
@@ -238,16 +238,16 @@
 
         response = dict(id=self._req_id, result=raw_response, error=self._error)
         try:
-            return json.dumps(response)
+            return ascii_bytes(ext_json.dumps(response))
         except TypeError as e:
             log.error('API FAILED. Error encoding response for %s %s: %s\n%s', action, rpc_args, e, traceback.format_exc())
-            return json.dumps(
+            return ascii_bytes(ext_json.dumps(
                 dict(
                     id=self._req_id,
                     result=None,
-                    error="Error encoding response"
+                    error="Error encoding response",
                 )
-            )
+            ))
 
     def _find_method(self):
         """
--- a/kallithea/controllers/summary.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/controllers/summary.py	Sat Dec 28 13:38:22 2019 +0100
@@ -40,10 +40,10 @@
 
 import kallithea.lib.helpers as h
 from kallithea.config.conf import ALL_EXTS, ALL_READMES, LANGUAGES_EXTENSIONS_MAP
+from kallithea.lib import ext_json
 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
 from kallithea.lib.base import BaseRepoController, jsonify, render
 from kallithea.lib.celerylib.tasks import get_commits_stats
-from kallithea.lib.compat import json
 from kallithea.lib.markup_renderer import MarkupRenderer
 from kallithea.lib.page import Page
 from kallithea.lib.utils2 import safe_int, safe_unicode
@@ -139,7 +139,7 @@
 
         if stats and stats.languages:
             c.no_data = False is c.db_repo.enable_statistics
-            lang_stats_d = json.loads(stats.languages)
+            lang_stats_d = ext_json.loads(stats.languages)
 
             lang_stats = [(x, {"count": y,
                                "desc": LANGUAGES_EXTENSIONS_MAP.get(x, '?')})
@@ -191,9 +191,9 @@
         c.stats_percentage = 0
         if stats and stats.languages:
             c.no_data = False is c.db_repo.enable_statistics
-            lang_stats_d = json.loads(stats.languages)
-            c.commit_data = json.loads(stats.commit_activity)
-            c.overview_data = json.loads(stats.commit_activity_combined)
+            lang_stats_d = ext_json.loads(stats.languages)
+            c.commit_data = ext_json.loads(stats.commit_activity)
+            c.overview_data = ext_json.loads(stats.commit_activity_combined)
 
             lang_stats = ((x, {"count": y,
                                "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
--- a/kallithea/lib/auth_modules/auth_crowd.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/lib/auth_modules/auth_crowd.py	Sat Dec 28 13:38:22 2019 +0100
@@ -30,8 +30,9 @@
 import logging
 import urllib2
 
-from kallithea.lib import auth_modules
-from kallithea.lib.compat import formatted_json, hybrid_property, json
+from kallithea.lib import auth_modules, ext_json
+from kallithea.lib.compat import formatted_json, hybrid_property
+from kallithea.lib.utils2 import ascii_bytes
 
 
 log = logging.getLogger(__name__)
@@ -103,7 +104,7 @@
                 rval["status"] = True
                 rval["error"] = "Response body was empty"
             elif not noformat:
-                rval = json.loads(msg)
+                rval = ext_json.loads(msg)
                 rval["status"] = True
             else:
                 rval = "".join(rdoc.readlines())
@@ -121,7 +122,7 @@
         the user."""
         url = ("%s/rest/usermanagement/%s/authentication?username=%s"
                % (self._uri, self._version, urllib2.quote(username)))
-        body = json.dumps({"value": password})
+        body = ascii_bytes(ext_json.dumps({"value": password}))
         return self._request(url, body)
 
     def user_groups(self, username):
--- a/kallithea/lib/base.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/lib/base.py	Sat Dec 28 13:38:22 2019 +0100
@@ -45,12 +45,11 @@
 
 from kallithea import BACKENDS, __version__
 from kallithea.config.routing import url
-from kallithea.lib import auth_modules
+from kallithea.lib import auth_modules, ext_json
 from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware
-from kallithea.lib.compat import json
 from kallithea.lib.exceptions import UserCreationError
 from kallithea.lib.utils import get_repo_slug, is_valid_repo
-from kallithea.lib.utils2 import AttributeDict, safe_int, safe_str, safe_unicode, set_hook_environment, str2bool
+from kallithea.lib.utils2 import AttributeDict, ascii_bytes, safe_int, safe_str, safe_unicode, set_hook_environment, str2bool
 from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError
 from kallithea.model import meta
 from kallithea.model.db import PullRequest, Repository, Setting, User
@@ -630,7 +629,7 @@
         warnings.warn(msg, Warning, 2)
         log.warning(msg)
     log.debug("Returning JSON wrapped action output")
-    return json.dumps(data)
+    return ascii_bytes(ext_json.dumps(data))
 
 @decorator.decorator
 def IfSshEnabled(func, *args, **kwargs):
--- a/kallithea/lib/celerylib/tasks.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/lib/celerylib/tasks.py	Sat Dec 28 13:38:22 2019 +0100
@@ -37,13 +37,12 @@
 from tg import config
 
 from kallithea import CELERY_ON
-from kallithea.lib import celerylib
-from kallithea.lib.compat import json
+from kallithea.lib import celerylib, ext_json
 from kallithea.lib.helpers import person
 from kallithea.lib.hooks import log_create_repository
 from kallithea.lib.rcmail.smtp_mailer import SmtpMailer
 from kallithea.lib.utils import action_logger
-from kallithea.lib.utils2 import str2bool
+from kallithea.lib.utils2 import ascii_bytes, str2bool
 from kallithea.lib.vcs.utils import author_email
 from kallithea.model.db import RepoGroup, Repository, Statistics, User
 
@@ -118,9 +117,9 @@
             return True
 
         if cur_stats:
-            commits_by_day_aggregate = OrderedDict(json.loads(
+            commits_by_day_aggregate = OrderedDict(ext_json.loads(
                                         cur_stats.commit_activity_combined))
-            co_day_auth_aggr = json.loads(cur_stats.commit_activity)
+            co_day_auth_aggr = ext_json.loads(cur_stats.commit_activity)
 
         log.debug('starting parsing %s', parse_limit)
 
@@ -193,8 +192,8 @@
             }
 
         stats = cur_stats if cur_stats else Statistics()
-        stats.commit_activity = json.dumps(co_day_auth_aggr)
-        stats.commit_activity_combined = json.dumps(overview_data)
+        stats.commit_activity = ascii_bytes(ext_json.dumps(co_day_auth_aggr))
+        stats.commit_activity_combined = ascii_bytes(ext_json.dumps(overview_data))
 
         log.debug('last revision %s', last_rev)
         leftovers = len(repo.revisions[last_rev:])
@@ -202,7 +201,7 @@
 
         if last_rev == 0 or leftovers < parse_limit:
             log.debug('getting code trending stats')
-            stats.languages = json.dumps(__get_codes_stats(repo_name))
+            stats.languages = ascii_bytes(ext_json.dumps(__get_codes_stats(repo_name)))
 
         try:
             stats.repository = dbrepo
--- a/kallithea/lib/compat.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/lib/compat.py	Sat Dec 28 13:38:22 2019 +0100
@@ -42,15 +42,10 @@
 #==============================================================================
 # json
 #==============================================================================
-from kallithea.lib.ext_json import json
+from kallithea.lib import ext_json
 
 
-# alias for formatted json
-formatted_json = functools.partial(json.dumps, indent=4, sort_keys=True)
-
-
-
-
+formatted_json = functools.partial(ext_json.dumps, indent=4, sort_keys=True)
 
 
 #==============================================================================
--- a/kallithea/lib/ext_json.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/lib/ext_json.py	Sat Dec 28 13:38:22 2019 +0100
@@ -1,16 +1,16 @@
 """
-Extended JSON encoder for json
+Extended JSON encoder with support for more data types
 
-json.org does not specify how date time can be represented - monkeypatch it to do something.
+json.org does not specify how date time can be represented - just encode it somehow and ignore decoding ...
 """
 
 import datetime
 import decimal
 import functools
-import json  # is re-exported after monkey patching
+import json
 
 
-__all__ = ['json']
+__all__ = ['dumps', 'dump', 'load', 'loads']
 
 
 def _is_tz_aware(value):
@@ -70,10 +70,12 @@
         try:
             return _obj_dump(obj)
         except NotImplementedError:
-            pass
+            pass  # quiet skipping of unsupported types!
         raise TypeError("%r is not JSON serializable" % (obj,))
 
 
-# monkey-patch and export JSON encoder to use custom encoding method
-json.dumps = functools.partial(json.dumps, cls=ExtendedEncoder)
-json.dump = functools.partial(json.dump, cls=ExtendedEncoder)
+dumps = functools.partial(json.dumps, cls=ExtendedEncoder)
+dump = functools.partial(json.dump, cls=ExtendedEncoder)
+# No special support for loading these types back!!!
+load = json.load
+loads = json.loads
--- a/kallithea/lib/utils2.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/lib/utils2.py	Sat Dec 28 13:38:22 2019 +0100
@@ -31,6 +31,7 @@
 
 import binascii
 import datetime
+import json
 import os
 import pwd
 import re
@@ -42,7 +43,6 @@
 from tg.i18n import ungettext
 from webhelpers2.text import collapse, remove_formatting, strip_tags
 
-from kallithea.lib.compat import json
 from kallithea.lib.vcs.utils import ascii_bytes, ascii_str, safe_bytes, safe_str, safe_unicode  # re-export
 from kallithea.lib.vcs.utils.lazy import LazyProperty
 
--- a/kallithea/model/db.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/model/db.py	Sat Dec 28 13:38:22 2019 +0100
@@ -45,11 +45,11 @@
 from webob.exc import HTTPNotFound
 
 import kallithea
+from kallithea.lib import ext_json
 from kallithea.lib.caching_query import FromCache
-from kallithea.lib.compat import json
 from kallithea.lib.exceptions import DefaultUserException
 from kallithea.lib.utils2 import (
-    Optional, aslist, get_changeset_safe, get_clone_url, remove_prefix, safe_bytes, safe_int, safe_str, safe_unicode, str2bool, urlreadable)
+    Optional, ascii_bytes, aslist, get_changeset_safe, get_clone_url, remove_prefix, safe_bytes, safe_int, safe_str, safe_unicode, str2bool, urlreadable)
 from kallithea.lib.vcs import get_backend
 from kallithea.lib.vcs.backends.base import EmptyChangeset
 from kallithea.lib.vcs.utils.helpers import get_scm
@@ -521,14 +521,14 @@
             return {}
 
         try:
-            return json.loads(self._user_data)
+            return ext_json.loads(self._user_data)
         except TypeError:
             return {}
 
     @user_data.setter
     def user_data(self, val):
         try:
-            self._user_data = json.dumps(val)
+            self._user_data = ascii_bytes(ext_json.dumps(val))
         except Exception:
             log.error(traceback.format_exc())
 
@@ -833,14 +833,14 @@
             return {}
 
         try:
-            return json.loads(self._group_data)
+            return ext_json.loads(self._group_data)
         except TypeError:
             return {}
 
     @group_data.setter
     def group_data(self, val):
         try:
-            self._group_data = json.dumps(val)
+            self._group_data = ascii_bytes(ext_json.dumps(val))
         except Exception:
             log.error(traceback.format_exc())
 
@@ -1032,7 +1032,7 @@
     @hybrid_property
     def changeset_cache(self):
         try:
-            cs_cache = json.loads(self._changeset_cache) # might raise on bad data
+            cs_cache = ext_json.loads(self._changeset_cache) # might raise on bad data
             cs_cache['raw_id'] # verify data, raise exception on error
             return cs_cache
         except (TypeError, KeyError, ValueError):
@@ -1041,7 +1041,7 @@
     @changeset_cache.setter
     def changeset_cache(self, val):
         try:
-            self._changeset_cache = json.dumps(val)
+            self._changeset_cache = ascii_bytes(ext_json.dumps(val))
         except Exception:
             log.error(traceback.format_exc())
 
--- a/kallithea/model/gist.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/model/gist.py	Sat Dec 28 13:38:22 2019 +0100
@@ -32,8 +32,8 @@
 import time
 import traceback
 
-from kallithea.lib.compat import json
-from kallithea.lib.utils2 import AttributeDict, safe_int, safe_unicode, time_to_datetime
+from kallithea.lib import ext_json
+from kallithea.lib.utils2 import AttributeDict, ascii_bytes, safe_int, safe_unicode, time_to_datetime
 from kallithea.model.db import Gist, Session, User
 from kallithea.model.repo import RepoModel
 from kallithea.model.scm import ScmModel
@@ -82,7 +82,7 @@
             'gist_updated': time.time(),
         }
         with open(os.path.join(repo.path, '.hg', GIST_METADATA_FILE), 'wb') as f:
-            f.write(json.dumps(metadata))
+            f.write(ascii_bytes(ext_json.dumps(metadata)))
 
     def get_gist(self, gist):
         return Gist.guess_instance(gist)
--- a/kallithea/tests/api/api_base.py	Fri Dec 27 01:51:14 2019 +0100
+++ b/kallithea/tests/api/api_base.py	Sat Dec 28 13:38:22 2019 +0100
@@ -23,8 +23,9 @@
 import mock
 import pytest
 
+from kallithea.lib import ext_json
 from kallithea.lib.auth import AuthUser
-from kallithea.lib.compat import json
+from kallithea.lib.utils2 import ascii_bytes
 from kallithea.model.changeset_status import ChangesetStatusModel
 from kallithea.model.db import ChangesetStatus, PullRequest, RepoGroup, Repository, Setting, Ui, User
 from kallithea.model.gist import GistModel
@@ -48,11 +49,10 @@
 def _build_data(apikey, method, **kw):
     """
     Builds API data with given random ID
-
-    :param random_id:
+    For convenience, the json is returned as str
     """
     random_id = random.randrange(1, 9999)
-    return random_id, json.dumps({
+    return random_id, ext_json.dumps({
         "id": random_id,
         "api_key": apikey,
         "method": method,
@@ -60,7 +60,7 @@
     })
 
 
-jsonify = lambda obj: json.loads(json.dumps(obj))
+jsonify = lambda obj: ext_json.loads(ext_json.dumps(obj))
 
 
 def crash(*args, **kwargs):
@@ -127,7 +127,7 @@
             'error': None,
             'result': expected
         })
-        given = json.loads(given)
+        given = ext_json.loads(given)
         assert expected == given, (expected, given)
 
     def _compare_error(self, id_, expected, given):
@@ -136,7 +136,7 @@
             'error': expected,
             'result': None
         })
-        given = json.loads(given)
+        given = ext_json.loads(given)
         assert expected == given, (expected, given)
 
     def test_Optional_object(self):
@@ -2322,16 +2322,15 @@
                                   gist_type='public',
                                   files={'foobar': {'content': 'foo'}})
         response = api_call(self, params)
-        response_json = response.json
         expected = {
             'gist': {
-                'access_id': response_json['result']['gist']['access_id'],
-                'created_on': response_json['result']['gist']['created_on'],
+                'access_id': response.json['result']['gist']['access_id'],
+                'created_on': response.json['result']['gist']['created_on'],
                 'description': 'foobar-gist',
-                'expires': response_json['result']['gist']['expires'],
-                'gist_id': response_json['result']['gist']['gist_id'],
+                'expires': response.json['result']['gist']['expires'],
+                'gist_id': response.json['result']['gist']['gist_id'],
                 'type': 'public',
-                'url': response_json['result']['gist']['url']
+                'url': response.json['result']['gist']['url']
             },
             'msg': 'created new gist'
         }
@@ -2397,7 +2396,7 @@
         id_, params = _build_data(self.apikey, 'get_changesets',
                                   repoid=self.REPO, start=0, end=2)
         response = api_call(self, params)
-        result = json.loads(response.body)["result"]
+        result = ext_json.loads(response.body)["result"]
         assert len(result) == 3
         assert 'message' in result[0]
         assert 'added' not in result[0]
@@ -2406,7 +2405,7 @@
         id_, params = _build_data(self.apikey, 'get_changesets',
                                   repoid=self.REPO, start_date="2011-02-24T00:00:00", max_revisions=10)
         response = api_call(self, params)
-        result = json.loads(response.body)["result"]
+        result = ext_json.loads(response.body)["result"]
         assert len(result) == 10
         assert 'message' in result[0]
         assert 'added' not in result[0]
@@ -2419,7 +2418,7 @@
         id_, params = _build_data(self.apikey, 'get_changesets',
                                   repoid=self.REPO, branch_name=branch, start_date="2011-02-24T00:00:00")
         response = api_call(self, params)
-        result = json.loads(response.body)["result"]
+        result = ext_json.loads(response.body)["result"]
         assert len(result) == 5
         assert 'message' in result[0]
         assert 'added' not in result[0]
@@ -2428,7 +2427,7 @@
         id_, params = _build_data(self.apikey, 'get_changesets',
                                   repoid=self.REPO, start_date="2010-04-07T23:30:30", end_date="2010-04-08T00:31:14", with_file_list=True)
         response = api_call(self, params)
-        result = json.loads(response.body)["result"]
+        result = ext_json.loads(response.body)["result"]
         assert len(result) == 3
         assert 'message' in result[0]
         assert 'added' in result[0]
@@ -2438,7 +2437,7 @@
         id_, params = _build_data(self.apikey, 'get_changeset',
                                   repoid=self.REPO, raw_id=self.TEST_REVISION)
         response = api_call(self, params)
-        result = json.loads(response.body)["result"]
+        result = ext_json.loads(response.body)["result"]
         assert result["raw_id"] == self.TEST_REVISION
         assert "reviews" not in result
 
@@ -2448,7 +2447,7 @@
                                   repoid=self.REPO, raw_id=self.TEST_REVISION,
                                   with_reviews=True)
         response = api_call(self, params)
-        result = json.loads(response.body)["result"]
+        result = ext_json.loads(response.body)["result"]
         assert result["raw_id"] == self.TEST_REVISION
         assert "reviews" in result
         assert len(result["reviews"]) == 1
@@ -2484,12 +2483,12 @@
     def test_api_get_pullrequest(self):
         pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u'get test')
         random_id = random.randrange(1, 9999)
-        params = json.dumps({
+        params = ascii_bytes(ext_json.dumps({
             "id": random_id,
             "api_key": self.apikey,
             "method": 'get_pullrequest',
             "args": {"pullrequest_id": pull_request_id},
-        })
+        }))
         response = api_call(self, params)
         pullrequest = PullRequest().get(pull_request_id)
         expected = {
@@ -2515,12 +2514,12 @@
     def test_api_close_pullrequest(self):
         pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u'close test')
         random_id = random.randrange(1, 9999)
-        params = json.dumps({
+        params = ascii_bytes(ext_json.dumps({
             "id": random_id,
             "api_key": self.apikey,
             "method": "comment_pullrequest",
             "args": {"pull_request_id": pull_request_id, "close_pr": True},
-        })
+        }))
         response = api_call(self, params)
         self._compare_ok(random_id, True, given=response.body)
         pullrequest = PullRequest().get(pull_request_id)
@@ -2532,22 +2531,22 @@
         pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u"status test")
 
         random_id = random.randrange(1, 9999)
-        params = json.dumps({
+        params = ascii_bytes(ext_json.dumps({
             "id": random_id,
             "api_key": User.get_by_username(base.TEST_USER_REGULAR2_LOGIN).api_key,
             "method": "comment_pullrequest",
             "args": {"pull_request_id": pull_request_id, "status": ChangesetStatus.STATUS_APPROVED},
-        })
+        }))
         response = api_call(self, params)
         pullrequest = PullRequest().get(pull_request_id)
         self._compare_error(random_id, "No permission to change pull request status. User needs to be admin, owner or reviewer.", given=response.body)
         assert ChangesetStatus.STATUS_UNDER_REVIEW == ChangesetStatusModel().calculate_pull_request_result(pullrequest)[2]
-        params = json.dumps({
+        params = ascii_bytes(ext_json.dumps({
             "id": random_id,
             "api_key": User.get_by_username(base.TEST_USER_REGULAR_LOGIN).api_key,
             "method": "comment_pullrequest",
             "args": {"pull_request_id": pull_request_id, "status": ChangesetStatus.STATUS_APPROVED},
-        })
+        }))
         response = api_call(self, params)
         self._compare_ok(random_id, True, given=response.body)
         pullrequest = PullRequest().get(pull_request_id)
@@ -2556,12 +2555,12 @@
     def test_api_comment_pullrequest(self):
         pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u"comment test")
         random_id = random.randrange(1, 9999)
-        params = json.dumps({
+        params = ascii_bytes(ext_json.dumps({
             "id": random_id,
             "api_key": self.apikey,
             "method": "comment_pullrequest",
             "args": {"pull_request_id": pull_request_id, "comment_msg": "Looks good to me"},
-        })
+        }))
         response = api_call(self, params)
         self._compare_ok(random_id, True, given=response.body)
         pullrequest = PullRequest().get(pull_request_id)