launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #29346
[Merge] ~cjwatson/launchpad:remove-simplejson into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:remove-simplejson into launchpad:master.
Commit message:
Remove simplejson dependency
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/431994
The only things that `simplejson` still gave us compared with the standard library's `json` were more consistently accepting both bytes and text input across all supported Python versions. It isn't really worth a whole dependency just for that.
I normalized how `json.dumps` and `json.loads` are spelled; this makes the diff longer (sorry), but it makes it easier to grep for certain patterns.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:remove-simplejson into launchpad:master.
diff --git a/lib/lp/answers/browser/questionsubscription.py b/lib/lp/answers/browser/questionsubscription.py
index cc2ea58..990e1a3 100644
--- a/lib/lp/answers/browser/questionsubscription.py
+++ b/lib/lp/answers/browser/questionsubscription.py
@@ -7,9 +7,10 @@ __all__ = [
"QuestionPortletSubscribersWithDetails",
]
+import json
+
from lazr.delegates import delegate_to
from lazr.restful.interfaces import IWebServiceClientRequest
-from simplejson import dumps
from zope.traversing.browser import absoluteURL
from lp.answers.interfaces.question import IQuestion
@@ -78,7 +79,7 @@ class QuestionPortletSubscribersWithDetails(LaunchpadView):
"subscription_level": "Indirect",
}
data.append(record)
- return dumps(data)
+ return json.dumps(data)
def render(self):
"""Override the default render() to return only JSON."""
diff --git a/lib/lp/answers/browser/questiontarget.py b/lib/lp/answers/browser/questiontarget.py
index bbb6d26..8682cf9 100644
--- a/lib/lp/answers/browser/questiontarget.py
+++ b/lib/lp/answers/browser/questiontarget.py
@@ -18,11 +18,11 @@ __all__ = [
"UserSupportLanguagesMixin",
]
+import json
from operator import attrgetter
from urllib.parse import urlencode
from lazr.restful.interfaces import IJSONRequestCache, IWebServiceClientRequest
-from simplejson import dumps
from zope.browserpage import ViewPageTemplateFile
from zope.component import getMultiAdapter, getUtility, queryMultiAdapter
from zope.formlib import form
@@ -965,7 +965,7 @@ class QuestionTargetPortletAnswerContactsWithDetails(LaunchpadView):
"""Return subscriber_ids in a form suitable for JavaScript use."""
questiontarget = IQuestionTarget(self.context)
data = self.answercontact_data(questiontarget)
- return dumps(data)
+ return json.dumps(data)
def render(self):
"""Override the default render() to return only JSON."""
diff --git a/lib/lp/answers/model/questionjob.py b/lib/lp/answers/model/questionjob.py
index 2f2d794..3a7277c 100644
--- a/lib/lp/answers/model/questionjob.py
+++ b/lib/lp/answers/model/questionjob.py
@@ -7,7 +7,8 @@ __all__ = [
"QuestionJob",
]
-import simplejson
+import json
+
import six
from lazr.delegates import delegate_to
from storm.expr import And
@@ -70,7 +71,7 @@ class QuestionJob(StormBase):
self.job = Job()
self.job_type = job_type
self.question = question
- json_data = simplejson.dumps(metadata)
+ json_data = json.dumps(metadata)
self._json_data = six.ensure_text(json_data)
def __repr__(self):
@@ -82,7 +83,7 @@ class QuestionJob(StormBase):
@property
def metadata(self):
"""See `IQuestionJob`."""
- return simplejson.loads(self._json_data)
+ return json.loads(self._json_data)
def makeDerived(self):
if self.job_type != QuestionJobType.EMAIL:
diff --git a/lib/lp/answers/tests/test_question_webservice.py b/lib/lp/answers/tests/test_question_webservice.py
index 2acee73..1d92cc7 100644
--- a/lib/lp/answers/tests/test_question_webservice.py
+++ b/lib/lp/answers/tests/test_question_webservice.py
@@ -3,10 +3,10 @@
"""Webservice unit tests related to Launchpad Questions."""
+import json
from datetime import datetime, timedelta
import pytz
-from simplejson import dumps
from testtools.matchers import EndsWith
from lp.answers.enums import QuestionStatus
@@ -132,7 +132,7 @@ class TestQuestionRepresentation(TestCaseWithFactory):
response = self.webservice.patch(
question_json["self_link"],
"application/json",
- dumps(dict(title=new_title)),
+ json.dumps(dict(title=new_title)),
headers=dict(accept="application/xhtml+xml"),
)
diff --git a/lib/lp/app/browser/launchpadform.py b/lib/lp/app/browser/launchpadform.py
index 01ed055..126eb3f 100644
--- a/lib/lp/app/browser/launchpadform.py
+++ b/lib/lp/app/browser/launchpadform.py
@@ -14,9 +14,9 @@ __all__ = [
"safe_action",
]
+import json
from typing import List, Optional, Type
-import simplejson
import transaction
from lazr.lifecycle.event import ObjectModifiedEvent
from lazr.lifecycle.snapshot import Snapshot
@@ -140,7 +140,7 @@ class LaunchpadFormView(LaunchpadView):
]
if notifications:
request.response.setHeader(
- "X-Lazr-Notifications", simplejson.dumps(notifications)
+ "X-Lazr-Notifications", json.dumps(notifications)
)
def render(self):
@@ -387,7 +387,7 @@ class LaunchpadFormView(LaunchpadView):
errors=errors,
error_summary=self.error_count,
)
- return simplejson.dumps(return_data)
+ return json.dumps(return_data)
def validate(self, data):
"""Validate the form.
diff --git a/lib/lp/app/browser/lazrjs.py b/lib/lp/app/browser/lazrjs.py
index 23a6bc0..2d3a6f3 100644
--- a/lib/lp/app/browser/lazrjs.py
+++ b/lib/lp/app/browser/lazrjs.py
@@ -15,7 +15,8 @@ __all__ = [
"vocabulary_to_choice_edit_items",
]
-import simplejson
+import json
+
from lazr.enum import IEnumeratedType
from lazr.restful.declarations import LAZR_WEBSERVICE_EXPORTED
from lazr.restful.utils import get_current_browser_request
@@ -81,7 +82,7 @@ class WidgetBase:
if mutator_info is not None:
mutator_method, mutator_extra = mutator_info
self.mutator_method_name = mutator_method.__name__
- self.json_attribute = simplejson.dumps(self.api_attribute)
+ self.json_attribute = json.dumps(self.api_attribute)
@property
def resource_uri(self):
@@ -95,7 +96,7 @@ class WidgetBase:
@property
def json_resource_uri(self):
- return simplejson.dumps(self.resource_uri)
+ return json.dumps(self.resource_uri)
@property
def can_write(self):
@@ -132,13 +133,13 @@ class TextWidgetBase(WidgetBase):
edit_url,
edit_title,
)
- self.accept_empty = simplejson.dumps(self.optional_field)
+ self.accept_empty = json.dumps(self.optional_field)
self.title = title
- self.widget_css_selector = simplejson.dumps("#" + self.content_box_id)
+ self.widget_css_selector = json.dumps("#" + self.content_box_id)
@property
def json_attribute_uri(self):
- return simplejson.dumps(self.resource_uri + "/" + self.api_attribute)
+ return json.dumps(self.resource_uri + "/" + self.api_attribute)
class DefinedTagMixin:
@@ -221,8 +222,8 @@ class TextLineEditorWidget(TextWidgetBase, DefinedTagMixin):
self.max_width = max_width
self.truncate_lines = truncate_lines
self.default_text = default_text
- self.initial_value_override = simplejson.dumps(initial_value_override)
- self.width = simplejson.dumps(width)
+ self.initial_value_override = json.dumps(initial_value_override)
+ self.width = json.dumps(width)
@property
def value(self):
@@ -364,9 +365,9 @@ class InlineEditPickerWidget(WidgetBase):
self.help_link = help_link
# JSON encoded attributes.
- self.json_content_box_id = simplejson.dumps(self.content_box_id)
- self.json_attribute = simplejson.dumps(self.api_attribute + "_link")
- self.json_vocabulary_name = simplejson.dumps(
+ self.json_content_box_id = json.dumps(self.content_box_id)
+ self.json_attribute = json.dumps(self.api_attribute + "_link")
+ self.json_vocabulary_name = json.dumps(
self.exported_field.vocabularyName
)
@@ -409,7 +410,7 @@ class InlineEditPickerWidget(WidgetBase):
@property
def json_config(self):
- return simplejson.dumps(self.config)
+ return json.dumps(self.config)
@cachedproperty
def vocabulary(self):
@@ -628,13 +629,11 @@ class InlineMultiCheckboxWidget(WidgetBase):
self.has_choices = len(items)
# JSON encoded attributes.
- self.json_content_box_id = simplejson.dumps(self.content_box_id)
- self.json_attribute = simplejson.dumps(self.api_attribute)
- self.json_attribute_type = simplejson.dumps(attribute_type)
- self.json_items = simplejson.dumps(items)
- self.json_description = simplejson.dumps(
- self.exported_field.description
- )
+ self.json_content_box_id = json.dumps(self.content_box_id)
+ self.json_attribute = json.dumps(self.api_attribute)
+ self.json_attribute_type = json.dumps(attribute_type)
+ self.json_items = json.dumps(items)
+ self.json_description = json.dumps(self.exported_field.description)
@property
def config(self):
@@ -644,7 +643,7 @@ class InlineMultiCheckboxWidget(WidgetBase):
@property
def json_config(self):
- return simplejson.dumps(self.config)
+ return json.dumps(self.config)
def vocabulary_to_choice_edit_items(
@@ -708,7 +707,7 @@ def vocabulary_to_choice_edit_items(
items.append(new_item)
if as_json:
- return simplejson.dumps(items)
+ return json.dumps(items)
else:
return items
@@ -812,7 +811,7 @@ class BooleanChoiceWidget(WidgetBase, DefinedTagMixin):
@property
def json_config(self):
- return simplejson.dumps(self.config)
+ return json.dumps(self.config)
class EnumChoiceWidget(WidgetBase):
@@ -883,4 +882,4 @@ class EnumChoiceWidget(WidgetBase):
@property
def json_config(self):
- return simplejson.dumps(self.config)
+ return json.dumps(self.config)
diff --git a/lib/lp/app/browser/linkchecker.py b/lib/lp/app/browser/linkchecker.py
index 2ad22eb..5eac333 100644
--- a/lib/lp/app/browser/linkchecker.py
+++ b/lib/lp/app/browser/linkchecker.py
@@ -5,7 +5,8 @@ __all__ = [
"LinkCheckerAPI",
]
-import simplejson
+import json
+
from zope.component import getUtility
from lp.app.errors import NotFoundError
@@ -56,8 +57,8 @@ class LinkCheckerAPI(LaunchpadView):
result = {}
links_to_check_data = self.request.get("link_hrefs")
if links_to_check_data is None:
- return simplejson.dumps(result)
- links_to_check = simplejson.loads(links_to_check_data)
+ return json.dumps(result)
+ links_to_check = json.loads(links_to_check_data)
for link_type in links_to_check:
links = links_to_check[link_type]
@@ -65,7 +66,7 @@ class LinkCheckerAPI(LaunchpadView):
result[link_type] = link_info
self.request.response.setHeader("Content-type", "application/json")
- return simplejson.dumps(result)
+ return json.dumps(result)
def check_branch_links(self, links):
"""Check links of the form /+code/foo/bar"""
diff --git a/lib/lp/app/browser/tests/test_inlinemulticheckboxwidget.py b/lib/lp/app/browser/tests/test_inlinemulticheckboxwidget.py
index 2e0af72..3222fa4 100644
--- a/lib/lp/app/browser/tests/test_inlinemulticheckboxwidget.py
+++ b/lib/lp/app/browser/tests/test_inlinemulticheckboxwidget.py
@@ -3,7 +3,8 @@
"""Tests for the InlineMultiCheckboxWidget."""
-import simplejson
+import json
+
from lazr.enum import EnumeratedType, Item
from zope.interface import Interface
from zope.schema import List
@@ -58,18 +59,18 @@ class TestInlineMultiCheckboxWidget(TestCaseWithFactory):
item.value, force_local_path=True
)
expected_items = self._makeExpectedItems(vocab, value_fn=value_fn)
- self.assertEqual(simplejson.dumps(expected_items), widget.json_items)
+ self.assertEqual(json.dumps(expected_items), widget.json_items)
def test_items_for_custom_vocabulary(self):
widget = self._getWidget(vocabulary=Alphabet)
expected_items = self._makeExpectedItems(Alphabet)
- self.assertEqual(simplejson.dumps(expected_items), widget.json_items)
+ self.assertEqual(json.dumps(expected_items), widget.json_items)
def test_items_for_custom_vocabulary_name(self):
widget = self._getWidget(vocabulary="CountryName")
vocab = getVocabularyRegistry().get(None, "CountryName")
expected_items = self._makeExpectedItems(vocab)
- self.assertEqual(simplejson.dumps(expected_items), widget.json_items)
+ self.assertEqual(json.dumps(expected_items), widget.json_items)
def test_selected_items_checked(self):
widget = self._getWidget(
@@ -78,4 +79,4 @@ class TestInlineMultiCheckboxWidget(TestCaseWithFactory):
expected_items = self._makeExpectedItems(
Alphabet, selected=[Alphabet.A]
)
- self.assertEqual(simplejson.dumps(expected_items), widget.json_items)
+ self.assertEqual(json.dumps(expected_items), widget.json_items)
diff --git a/lib/lp/app/browser/tests/test_launchpadform.py b/lib/lp/app/browser/tests/test_launchpadform.py
index 56f7f91..7ca3863 100644
--- a/lib/lp/app/browser/tests/test_launchpadform.py
+++ b/lib/lp/app/browser/tests/test_launchpadform.py
@@ -3,9 +3,9 @@
"""Tests for the lp.app.browser.launchpadform module."""
+import json
from os.path import dirname, join
-import simplejson
from lxml import html
from testtools.content import text_content
from zope.browserpage import ViewPageTemplateFile
@@ -246,7 +246,7 @@ class TestAjaxValidator(TestCase):
"errors": {"field.single_line": "An error occurred"},
"form_wide_errors": ["A form error"],
},
- simplejson.loads(view.form_result),
+ json.loads(view.form_result),
)
def test_non_ajax_failure_handler(self):
@@ -293,5 +293,5 @@ class TestAjaxValidator(TestCase):
"errors": {},
"form_wide_errors": ["An action error"],
},
- simplejson.loads(view.form_result),
+ json.loads(view.form_result),
)
diff --git a/lib/lp/app/browser/tests/test_linkchecker.py b/lib/lp/app/browser/tests/test_linkchecker.py
index 9393a2e..0215c41 100644
--- a/lib/lp/app/browser/tests/test_linkchecker.py
+++ b/lib/lp/app/browser/tests/test_linkchecker.py
@@ -3,9 +3,9 @@
"""Unit tests for the LinkCheckerAPI."""
+import json
from random import shuffle
-import simplejson
from zope.security.proxy import removeSecurityProxy
from lp.app.browser.linkchecker import LinkCheckerAPI
@@ -22,13 +22,13 @@ class TestLinkCheckerAPI(TestCaseWithFactory):
BRANCH_URL_TEMPLATE = "/+code/%s"
def check_invalid_links(self, result_json, link_type, invalid_links):
- link_dict = simplejson.loads(result_json)
+ link_dict = json.loads(result_json)
links_to_check = link_dict[link_type]["invalid"]
self.assertEqual(len(invalid_links), len(links_to_check))
self.assertEqual(set(invalid_links), set(links_to_check))
def check_valid_links(self, result_json, link_type, valid_links):
- link_dict = simplejson.loads(result_json)
+ link_dict = json.loads(result_json)
links_to_check = link_dict[link_type]["valid"]
self.assertEqual(len(valid_links), len(links_to_check))
self.assertEqual(set(valid_links), set(links_to_check))
@@ -109,7 +109,7 @@ class TestLinkCheckerAPI(TestCaseWithFactory):
shuffle(bug_urls)
links_to_check = dict(branch_links=branch_urls, bug_links=bug_urls)
- link_json = simplejson.dumps(links_to_check)
+ link_json = json.dumps(links_to_check)
request = LaunchpadTestRequest(link_hrefs=link_json)
link_checker = LinkCheckerAPI(object(), request)
@@ -124,7 +124,7 @@ class TestLinkCheckerAPI(TestCaseWithFactory):
request = LaunchpadTestRequest()
link_checker = LinkCheckerAPI(object(), request)
result_json = link_checker()
- link_dict = simplejson.loads(result_json)
+ link_dict = json.loads(result_json)
self.assertEqual(link_dict, {})
def test_only_valid_links(self):
diff --git a/lib/lp/app/browser/tests/test_vocabulary.py b/lib/lp/app/browser/tests/test_vocabulary.py
index 35676e0..4b81a7e 100644
--- a/lib/lp/app/browser/tests/test_vocabulary.py
+++ b/lib/lp/app/browser/tests/test_vocabulary.py
@@ -3,12 +3,12 @@
"""Test vocabulary adapters."""
+import json
from datetime import datetime
from typing import List
from urllib.parse import urlencode
import pytz
-import simplejson
from zope.component import getSiteManager, getUtility
from zope.formlib.interfaces import MissingInputError
from zope.interface import implementer
@@ -609,7 +609,7 @@ class HugeVocabularyJSONViewTestCase(TestCaseWithFactory):
bugtask = self.factory.makeBugTask(target=product)
form = dict(name="TestPerson", search_text="xpting")
view = self.create_vocabulary_view(form, context=bugtask)
- result = simplejson.loads(view())
+ result = json.loads(view())
expected = [
{
"alt_title": team.name,
@@ -669,7 +669,7 @@ class HugeVocabularyJSONViewTestCase(TestCaseWithFactory):
name="TestPerson", search_text="xpting", search_filter=vocab_filter
)
view = self.create_vocabulary_view(form, context=product)
- result = simplejson.loads(view())
+ result = json.loads(view())
entries = result["entries"]
self.assertEqual(1, len(entries))
self.assertEqual("xpting-person", entries[0]["value"])
@@ -684,7 +684,7 @@ class HugeVocabularyJSONViewTestCase(TestCaseWithFactory):
login_person(person)
form = dict(name="TestPerson", search_text="pting-n")
view = self.create_vocabulary_view(form)
- result = simplejson.loads(view())
+ result = json.loads(view())
expected = email[: MAX_DESCRIPTION_LENGTH - 3] + "..."
self.assertEqual("pting-n", result["entries"][0]["value"])
self.assertEqual(expected, result["entries"][0]["description"])
@@ -693,7 +693,7 @@ class HugeVocabularyJSONViewTestCase(TestCaseWithFactory):
# The results are batched.
form = dict(name="TestPerson", search_text="pting")
view = self.create_vocabulary_view(form)
- result = simplejson.loads(view())
+ result = json.loads(view())
total_size = result["total_size"]
entries = len(result["entries"])
self.assertTrue(
@@ -707,7 +707,7 @@ class HugeVocabularyJSONViewTestCase(TestCaseWithFactory):
name="TestPerson", search_text="pting", start="0", batch="1"
)
view = self.create_vocabulary_view(form)
- result = simplejson.loads(view())
+ result = json.loads(view())
self.assertEqual(6, result["total_size"])
self.assertEqual(1, len(result["entries"]))
@@ -717,7 +717,7 @@ class HugeVocabularyJSONViewTestCase(TestCaseWithFactory):
name="TestPerson", search_text="pting", start="1", batch="1"
)
view = self.create_vocabulary_view(form)
- result = simplejson.loads(view())
+ result = json.loads(view())
self.assertEqual(6, result["total_size"])
self.assertEqual(1, len(result["entries"]))
self.assertEqual("pting-2", result["entries"][0]["value"])
diff --git a/lib/lp/app/browser/vocabulary.py b/lib/lp/app/browser/vocabulary.py
index 126881c..04d0599 100644
--- a/lib/lp/app/browser/vocabulary.py
+++ b/lib/lp/app/browser/vocabulary.py
@@ -10,10 +10,11 @@ __all__ = [
"vocabulary_filters",
]
+import json
+
# This registers the registry.
import zope.vocabularyregistry.registry # noqa: F401 # isort: split
-import simplejson
from lazr.restful.interfaces import IWebServiceClientRequest
from zope.component import adapter, getUtility
from zope.formlib.interfaces import MissingInputError
@@ -533,7 +534,7 @@ class HugeVocabularyJSONView:
result.append(entry)
self.request.response.setHeader("Content-type", "application/json")
- return simplejson.dumps(dict(total_size=total_size, entries=result))
+ return json.dumps(dict(total_size=total_size, entries=result))
def vocabulary_filters(vocabulary):
diff --git a/lib/lp/app/widgets/popup.py b/lib/lp/app/widgets/popup.py
index 3b879ee..b2524ef 100644
--- a/lib/lp/app/widgets/popup.py
+++ b/lib/lp/app/widgets/popup.py
@@ -13,7 +13,8 @@ __all__ = [
"VocabularyPickerWidget",
]
-import simplejson
+import json
+
from zope.browserpage import ViewPageTemplateFile
from zope.component import getUtility
from zope.formlib.interfaces import ConversionError
@@ -160,7 +161,7 @@ class VocabularyPickerWidget(SingleDataHelper, ItemsWidgetBase):
@property
def json_config(self):
- return simplejson.dumps(self.config)
+ return json.dumps(self.config)
@property
def extra_no_results_message(self):
diff --git a/lib/lp/app/widgets/tests/test_popup.py b/lib/lp/app/widgets/tests/test_popup.py
index 51b7162..0a4ce99 100644
--- a/lib/lp/app/widgets/tests/test_popup.py
+++ b/lib/lp/app/widgets/tests/test_popup.py
@@ -1,7 +1,8 @@
# Copyright 2010-2016 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
-import simplejson
+import json
+
from zope.interface import Interface
from zope.interface.interface import InterfaceClass
from zope.schema import Choice
@@ -65,7 +66,7 @@ class TestVocabularyPickerWidget(TestCaseWithFactory):
bound_field, self.vocabulary, self.request
)
- widget_config = simplejson.loads(picker_widget.json_config)
+ widget_config = json.loads(picker_widget.json_config)
self.assertEqual("ValidTeamOwner", picker_widget.vocabulary_name)
self.assertEqual(
[
@@ -112,7 +113,7 @@ class TestVocabularyPickerWidget(TestCaseWithFactory):
bound_field, vocabulary, self.request
)
- widget_config = simplejson.loads(picker_widget.json_config)
+ widget_config = json.loads(picker_widget.json_config)
self.assertEqual(
[
{
diff --git a/lib/lp/blueprints/browser/specificationsubscription.py b/lib/lp/blueprints/browser/specificationsubscription.py
index bb93933..c4e15ae 100644
--- a/lib/lp/blueprints/browser/specificationsubscription.py
+++ b/lib/lp/blueprints/browser/specificationsubscription.py
@@ -9,10 +9,10 @@ __all__ = [
"SpecificationSubscriptionEditView",
]
+import json
from typing import List
from lazr.delegates import delegate_to
-from simplejson import dumps
from zope.component import getUtility
from lp import _
@@ -211,7 +211,7 @@ class SpecificationPortletSubcribersIds(LaunchpadView):
@property
def subscriber_ids_js(self):
"""Return subscriber_ids in a form suitable for JavaScript use."""
- return dumps(self.subscriber_ids)
+ return json.dumps(self.subscriber_ids)
def render(self):
"""Override the default render() to return only JSON."""
diff --git a/lib/lp/bugs/browser/bugsubscription.py b/lib/lp/bugs/browser/bugsubscription.py
index 642b14b..eaf3ea6 100644
--- a/lib/lp/bugs/browser/bugsubscription.py
+++ b/lib/lp/bugs/browser/bugsubscription.py
@@ -11,11 +11,11 @@ __all__ = [
"BugSubscriptionListView",
]
+import json
from typing import List
from lazr.delegates import delegate_to
from lazr.restful.interfaces import IJSONRequestCache, IWebServiceClientRequest
-from simplejson import dumps
from zope import formlib
from zope.formlib.itemswidgets import RadioWidget
from zope.formlib.widget import CustomWidgetFactory
@@ -663,7 +663,7 @@ class BugPortletSubscribersWithDetails(LaunchpadView):
@property
def subscriber_data_js(self):
- return dumps(self.subscriber_data)
+ return json.dumps(self.subscriber_data)
def render(self):
"""Override the default render() to return only JSON."""
diff --git a/lib/lp/bugs/browser/bugtarget.py b/lib/lp/bugs/browser/bugtarget.py
index e7b3dc6..7c5e70a 100644
--- a/lib/lp/bugs/browser/bugtarget.py
+++ b/lib/lp/bugs/browser/bugtarget.py
@@ -18,6 +18,7 @@ __all__ = [
]
import http.client
+import json
from datetime import datetime
from functools import partial
from io import BytesIO
@@ -26,7 +27,6 @@ from urllib.parse import quote, urlencode
from lazr.restful.interface import copy_field
from lazr.restful.interfaces import IJSONRequestCache
from pytz import timezone
-from simplejson import dumps
from zope.browserpage import ViewPageTemplateFile
from zope.component import getUtility
from zope.formlib.form import Fields
@@ -1361,8 +1361,8 @@ class OfficialBugTagsManageView(LaunchpadEditFormView):
@property
def tags_js_data(self):
"""Return the JSON representation of the bug tags."""
- # The model returns dict and list respectively but dumps blows up on
- # security proxied objects.
+ # The model returns dict and list respectively, but json.dumps blows
+ # up on security proxied objects.
used_tags = removeSecurityProxy(
self.context.getUsedBugTagsWithOpenCounts(self.user)
)
@@ -1373,9 +1373,9 @@ class OfficialBugTagsManageView(LaunchpadEditFormView):
var valid_name_pattern = %s;
</script>
""" % (
- dumps(used_tags),
- dumps(official_tags),
- dumps(valid_name_pattern.pattern),
+ json.dumps(used_tags),
+ json.dumps(official_tags),
+ json.dumps(valid_name_pattern.pattern),
)
@property
diff --git a/lib/lp/bugs/browser/bugtask.py b/lib/lp/bugs/browser/bugtask.py
index d000562..161e405 100644
--- a/lib/lp/bugs/browser/bugtask.py
+++ b/lib/lp/bugs/browser/bugtask.py
@@ -25,6 +25,7 @@ __all__ = [
"get_visible_comments",
]
+import json
import re
from collections import defaultdict
from datetime import datetime, timedelta
@@ -46,7 +47,6 @@ from lazr.restful.interfaces import (
)
from lazr.restful.utils import smartquote
from pytz import utc
-from simplejson import dumps
from zope import formlib
from zope.browserpage import ViewPageTemplateFile
from zope.component import adapter, getAdapter, getMultiAdapter, getUtility
@@ -962,7 +962,7 @@ class BugTaskView(LaunchpadView, BugViewMixin, FeedsMixin):
# Unwrap the security proxy. - official_tags is a security proxy
# wrapped list.
available_tags = list(self.context.bug.official_tags)
- return "var available_official_tags = %s;" % dumps(available_tags)
+ return "var available_official_tags = %s;" % json.dumps(available_tags)
@property
def user_is_admin(self):
@@ -1775,7 +1775,7 @@ class BugTaskDeletionView(ReturnToReferrerMixin, LaunchpadFormView):
self.request.response.setHeader(
"Content-type", "application/json"
)
- return dumps(None)
+ return json.dumps(None)
launchbag = getUtility(ILaunchBag)
launchbag.add(bug.default_bugtask)
# If we are deleting the current highlighted bugtask via ajax,
@@ -1788,7 +1788,7 @@ class BugTaskDeletionView(ReturnToReferrerMixin, LaunchpadFormView):
self.request.response.setHeader(
"Content-type", "application/json"
)
- return dumps(dict(bugtask_url=next_url))
+ return json.dumps(dict(bugtask_url=next_url))
# No redirect required so return the new bugtask table HTML.
view = getMultiAdapter(
(bug, self.request), name="+bugtasks-and-nominations-table"
diff --git a/lib/lp/bugs/browser/tests/test_bug_views.py b/lib/lp/bugs/browser/tests/test_bug_views.py
index 2264af4..927c93c 100644
--- a/lib/lp/bugs/browser/tests/test_bug_views.py
+++ b/lib/lp/bugs/browser/tests/test_bug_views.py
@@ -3,11 +3,11 @@
"""Tests for Bug Views."""
+import json
import re
from datetime import datetime, timedelta
import pytz
-import simplejson
from soupmatchers import HTMLContains, Tag, Within
from storm.store import Store
from testtools.matchers import Contains, Equals, MatchesAll, Not
@@ -484,7 +484,7 @@ class TestBugSecrecyViews(TestCaseWithFactory):
**extra,
)
view = self.createInitializedSecrecyView(person, bug, request)
- result_data = simplejson.loads(view.render())
+ result_data = json.loads(view.render())
cache_data = result_data["cache_data"]
self.assertFalse(cache_data["other_subscription_notifications"])
diff --git a/lib/lp/bugs/browser/tests/test_bugtask.py b/lib/lp/bugs/browser/tests/test_bugtask.py
index b816cdf..724af22 100644
--- a/lib/lp/bugs/browser/tests/test_bugtask.py
+++ b/lib/lp/bugs/browser/tests/test_bugtask.py
@@ -1,11 +1,11 @@
# Copyright 2009-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+import json
import re
from datetime import datetime, timedelta
from urllib.parse import urlencode
-import simplejson
import soupmatchers
import transaction
from lazr.restful.interfaces import IJSONRequestCache
@@ -1166,9 +1166,9 @@ class TestBugTaskDeleteView(TestCaseWithFactory):
principal=bugtask.owner,
**extra,
)
- result_data = simplejson.loads(view.render())
+ result_data = json.loads(view.render())
self.assertEqual([bug.default_bugtask], bug.bugtasks)
- notifications = simplejson.loads(
+ notifications = json.loads(
view.request.response.getHeader("X-Lazr-Notifications")
)
self.assertEqual(1, len(notifications))
@@ -1198,9 +1198,9 @@ class TestBugTaskDeleteView(TestCaseWithFactory):
principal=bug.owner,
**extra,
)
- result_data = simplejson.loads(view.render())
+ result_data = json.loads(view.render())
self.assertEqual([bug.default_bugtask], bug.bugtasks)
- notifications = simplejson.loads(
+ notifications = json.loads(
view.request.response.getHeader("X-Lazr-Notifications")
)
self.assertEqual(1, len(notifications))
diff --git a/lib/lp/bugs/browser/widgets/bug.py b/lib/lp/bugs/browser/widgets/bug.py
index 08dad8e..5c327b1 100644
--- a/lib/lp/bugs/browser/widgets/bug.py
+++ b/lib/lp/bugs/browser/widgets/bug.py
@@ -8,9 +8,9 @@ __all__ = [
"LargeBugTagsWidget",
]
+import json
import re
-from simplejson import dumps
from zope.component import getUtility
from zope.formlib.interfaces import ConversionError, WidgetInputError
from zope.formlib.textwidgets import IntWidget, TextAreaWidget, TextWidget
@@ -168,7 +168,7 @@ class BugTagsWidget(BugTagsWidgetBase, TextWidget):
official_tags = list(pillar_target.official_bug_tags)
else:
official_tags = []
- return "var official_tags = %s;" % dumps(official_tags)
+ return "var official_tags = %s;" % json.dumps(official_tags)
class BugTagsFrozenSetWidget(BugTagsWidget):
diff --git a/lib/lp/bugs/model/apportjob.py b/lib/lp/bugs/model/apportjob.py
index caf0fbd..a4612d5 100644
--- a/lib/lp/bugs/model/apportjob.py
+++ b/lib/lp/bugs/model/apportjob.py
@@ -8,9 +8,9 @@ __all__ = [
"ApportJobDerived",
]
+import json
from io import BytesIO
-import simplejson
import six
from lazr.delegates import delegate_to
from storm.expr import And
@@ -60,10 +60,10 @@ class ApportJob(StormBase):
# only delegates to ApportJob we can't simply directly access the
# _json_data property, so we use a getter and setter here instead.
def _set_metadata(self, metadata):
- self._json_data = six.ensure_text(simplejson.dumps(metadata, "utf-8"))
+ self._json_data = six.ensure_text(json.dumps(metadata, "utf-8"))
def _get_metadata(self):
- return simplejson.loads(self._json_data)
+ return json.loads(self._json_data)
metadata = property(_get_metadata, _set_metadata)
@@ -76,7 +76,7 @@ class ApportJob(StormBase):
dict.
"""
super().__init__()
- json_data = simplejson.dumps(metadata)
+ json_data = json.dumps(metadata)
self.job = Job()
self.blob = blob
self.job_type = job_type
diff --git a/lib/lp/bugs/stories/webservice/xx-bug-target.rst b/lib/lp/bugs/stories/webservice/xx-bug-target.rst
index f1fa5f2..8fb47c7 100644
--- a/lib/lp/bugs/stories/webservice/xx-bug-target.rst
+++ b/lib/lp/bugs/stories/webservice/xx-bug-target.rst
@@ -16,12 +16,12 @@ All bug targets have a read/write bug_reporting_guidelines property.
>>> print(product["bug_reporting_guidelines"])
None
- >>> from simplejson import dumps
+ >>> import json
>>> patch = {
... "bug_reporting_guidelines": "Please run `ubuntu-bug -p firefox`."
... }
>>> response = webservice.patch(
- ... product["self_link"], "application/json", dumps(patch)
+ ... product["self_link"], "application/json", json.dumps(patch)
... )
>>> product = webservice.get(product_url).jsonBody()
@@ -36,7 +36,7 @@ Not everyone can modify it however:
... )
... }
>>> response = user_webservice.patch(
- ... product["self_link"], "application/json", dumps(patch)
+ ... product["self_link"], "application/json", json.dumps(patch)
... )
>>> print(response)
HTTP/1.1 401 Unauthorized...
@@ -109,7 +109,7 @@ The bug supervisor of a product can also add tags.
... webservice.patch(
... "/tags-test-product2",
... "application/json",
- ... dumps({"bug_supervisor_link": ws_salgado["self_link"]}),
+ ... json.dumps({"bug_supervisor_link": ws_salgado["self_link"]}),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -144,7 +144,6 @@ Official tags must conform to the same format as ordinary tags.
We can also access official tags as a list.
- >>> from simplejson import dumps
>>> tags_test_product = webservice.get("/tags-test-product").jsonBody()
>>> tags_test_product["official_bug_tags"]
[]
@@ -152,7 +151,7 @@ We can also access official tags as a list.
... webservice.patch(
... "/tags-test-product",
... "application/json",
- ... dumps({"official_bug_tags": ["foo", "bar"]}),
+ ... json.dumps({"official_bug_tags": ["foo", "bar"]}),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -171,7 +170,7 @@ We can also access official tags as a list.
... webservice.patch(
... "/testix",
... "application/json",
- ... dumps({"official_bug_tags": ["foo", "bar"]}),
+ ... json.dumps({"official_bug_tags": ["foo", "bar"]}),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -189,7 +188,9 @@ We can retrieve or set a person or team as the bug supervisor for projects.
... webservice.patch(
... "/firefox",
... "application/json",
- ... dumps({"bug_supervisor_link": firefox_project["owner_link"]}),
+ ... json.dumps(
+ ... {"bug_supervisor_link": firefox_project["owner_link"]}
+ ... ),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -208,7 +209,9 @@ We can also do this for distributions.
... webservice.patch(
... "/ubuntutest",
... "application/json",
- ... dumps({"bug_supervisor_link": ubuntutest_dist["owner_link"]}),
+ ... json.dumps(
+ ... {"bug_supervisor_link": ubuntutest_dist["owner_link"]}
+ ... ),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -223,7 +226,7 @@ Setting the bug supervisor is restricted to owners and launchpad admins.
... user_webservice.patch(
... "/ubuntutest",
... "application/json",
- ... dumps({"bug_supervisor_link": None}),
+ ... json.dumps({"bug_supervisor_link": None}),
... )
... )
HTTP/1.1 401 Unauthorized
diff --git a/lib/lp/bugs/stories/webservice/xx-bug.rst b/lib/lp/bugs/stories/webservice/xx-bug.rst
index 80c2f24..851aad5 100644
--- a/lib/lp/bugs/stories/webservice/xx-bug.rst
+++ b/lib/lp/bugs/stories/webservice/xx-bug.rst
@@ -195,7 +195,7 @@ distribution in which the bug exists.
To mark a bug as private, we patch the `private` attribute of the bug.
- >>> from simplejson import dumps
+ >>> import json
>>> bug_twelve = webservice.get("/bugs/12").jsonBody()
>>> bug_twelve["private"]
False
@@ -203,7 +203,7 @@ To mark a bug as private, we patch the `private` attribute of the bug.
... webservice.patch(
... bug_twelve["self_link"],
... "application/json",
- ... dumps(dict(private=True)),
+ ... json.dumps(dict(private=True)),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -214,7 +214,7 @@ To mark a bug as private, we patch the `private` attribute of the bug.
... webservice.patch(
... bug_twelve["self_link"],
... "application/json",
- ... dumps(dict(private=False)),
+ ... json.dumps(dict(private=False)),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -228,7 +228,7 @@ attribute of the bug.
... webservice.patch(
... bug_twelve["self_link"],
... "application/json",
- ... dumps(dict(duplicate_of_link=bug_one["self_link"])),
+ ... json.dumps(dict(duplicate_of_link=bug_one["self_link"])),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -242,7 +242,7 @@ Now set it back to none:
... webservice.patch(
... bug_twelve["self_link"],
... "application/json",
- ... dumps(dict(duplicate_of_link=None)),
+ ... json.dumps(dict(duplicate_of_link=None)),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -259,7 +259,7 @@ Due to bug #1088358 the error is escaped as if it was HTML.
... webservice.patch(
... dupe_url,
... "application/json",
- ... dumps(
+ ... json.dumps(
... dict(
... duplicate_of_link=webservice.getAbsoluteUrl("/bugs/5")
... )
@@ -272,7 +272,7 @@ Due to bug #1088358 the error is escaped as if it was HTML.
... webservice.patch(
... webservice.getAbsoluteUrl("/bugs/5"),
... "application/json",
- ... dumps(dict(duplicate_of_link=dupe_url)),
+ ... json.dumps(dict(duplicate_of_link=dupe_url)),
... )
... )
HTTP/1.1 400 Bad Request
@@ -285,7 +285,7 @@ Due to bug #1088358 the error is escaped as if it was HTML.
... webservice.patch(
... dupe_url,
... "application/json",
- ... dumps(dict(duplicate_of_link=None)),
+ ... json.dumps(dict(duplicate_of_link=None)),
... )
... )
HTTP/1.1 209 Content Returned...
@@ -444,7 +444,9 @@ It's possible to change the task's assignee.
>>> patch = {"assignee_link": webservice.getAbsoluteUrl("/~cprov")}
>>> bugtask_path = bug_one_bugtasks[0]["self_link"]
>>> print(
- ... webservice.patch(bugtask_path, "application/json", dumps(patch))
+ ... webservice.patch(
+ ... bugtask_path, "application/json", json.dumps(patch)
+ ... )
... )
HTTP/1.1 209 Content Returned...
@@ -460,7 +462,9 @@ The task's importance can be modified directly.
>>> patch = {"importance": "High"}
>>> print(
- ... webservice.patch(bugtask_path, "application/json", dumps(patch))
+ ... webservice.patch(
+ ... bugtask_path, "application/json", json.dumps(patch)
+ ... )
... )
HTTP/1.1 209 Content Returned...
@@ -489,7 +493,9 @@ The task's status can also be modified directly.
>>> patch = {"status": "Fix Committed"}
>>> print(
- ... webservice.patch(bugtask_path, "application/json", dumps(patch))
+ ... webservice.patch(
+ ... bugtask_path, "application/json", json.dumps(patch)
+ ... )
... )
HTTP/1.1 209 Content Returned...
@@ -507,7 +513,9 @@ If an error occurs during a request that sets both 'status' and
>>> patch = {"importance": "High", "status": "No Such Status"}
>>> print(
- ... webservice.patch(bugtask_path, "application/json", dumps(patch))
+ ... webservice.patch(
+ ... bugtask_path, "application/json", json.dumps(patch)
+ ... )
... )
HTTP/1.1 400 Bad Request...
@@ -528,7 +536,9 @@ The milestone can only be set by appropriately privileged users.
... )
... }
>>> print(
- ... webservice.patch(bugtask_path, "application/json", dumps(patch))
+ ... webservice.patch(
+ ... bugtask_path, "application/json", json.dumps(patch)
+ ... )
... )
HTTP/1.1 209 Content Returned...
@@ -546,7 +556,7 @@ unchanged value.
... }
>>> print(
... user_webservice.patch(
- ... bugtask_path, "application/json", dumps(patch)
+ ... bugtask_path, "application/json", json.dumps(patch)
... )
... )
HTTP/1.1 401 Unauthorized...
@@ -583,7 +593,7 @@ We can also PATCH the target attribute to accomplish the same thing.
... webservice.patch(
... task["self_link"].replace("mozilla-firefox", "evolution"),
... "application/json",
- ... dumps(
+ ... json.dumps(
... {
... "target_link": webservice.getAbsoluteUrl(
... "/debian/+source/alsa-utils"
@@ -636,7 +646,9 @@ target, we reset it in order to avoid data inconsistencies.
... }
>>> print(
... webservice.patch(
- ... firefox_bugtask["self_link"], "application/json", dumps(patch)
+ ... firefox_bugtask["self_link"],
+ ... "application/json",
+ ... json.dumps(patch),
... )
... )
HTTP/1.1 209 Content Returned
@@ -1104,7 +1116,7 @@ They can also update the subscription's bug_notification_level directly.
... webservice.patch(
... new_subscription["self_link"],
... "application/json",
- ... dumps(patch),
+ ... json.dumps(patch),
... api_version="devel",
... ).jsonBody()
... )
@@ -1347,7 +1359,7 @@ We can modify the remote bug.
>>> patch = {"remote_bug": "1234"}
>>> response = webservice.patch(
- ... bug_watch_2000["self_link"], "application/json", dumps(patch)
+ ... bug_watch_2000["self_link"], "application/json", json.dumps(patch)
... )
>>> bug_watch = webservice.get(bug_watch_2000["self_link"]).jsonBody()
@@ -1358,7 +1370,7 @@ But we can't change other things, like the URL.
>>> patch = {"url": "http://www.example.com/"}
>>> response = webservice.patch(
- ... bug_watch_2000["self_link"], "application/json", dumps(patch)
+ ... bug_watch_2000["self_link"], "application/json", json.dumps(patch)
... )
>>> print(response)
HTTP/1.1 400 Bad Request...
@@ -1443,7 +1455,7 @@ We can change various aspects of bug trackers.
... "contact_details": "bob@xxxxxxxxxxx",
... }
>>> response = webservice.patch(
- ... bug_tracker["self_link"], "application/json", dumps(patch)
+ ... bug_tracker["self_link"], "application/json", json.dumps(patch)
... )
>>> print(response)
HTTP/1.1 301 Moved Permanently...
@@ -1493,7 +1505,7 @@ Non-admins can't disable a bugtracker through the API.
... public_webservice.patch(
... bug_tracker_path,
... "application/json",
- ... dumps(dict(active=False)),
+ ... json.dumps(dict(active=False)),
... )
... )
HTTP/1.1 401 Unauthorized
@@ -1503,7 +1515,9 @@ Non-admins can't disable a bugtracker through the API.
Admins can, however.
>>> bug_tracker = webservice.patch(
- ... bug_tracker_path, "application/json", dumps(dict(active=False))
+ ... bug_tracker_path,
+ ... "application/json",
+ ... json.dumps(dict(active=False)),
... ).jsonBody()
>>> pprint_entry(bug_tracker)
active: False...
diff --git a/lib/lp/bugs/tests/bug.py b/lib/lp/bugs/tests/bug.py
index acfa1a2..3cc9b4b 100644
--- a/lib/lp/bugs/tests/bug.py
+++ b/lib/lp/bugs/tests/bug.py
@@ -3,6 +3,7 @@
"""Helper functions for bug-related doctests and pagetests."""
+import json
import re
import textwrap
from datetime import datetime, timedelta
@@ -40,9 +41,7 @@ def print_also_notified(bug_page):
def print_subscribers(bug_page, subscription_level=None, reverse=False):
"""Print the subscribers listed in the subscribers JSON portlet."""
- from simplejson import loads
-
- details = loads(bug_page)
+ details = json.loads(bug_page.decode())
if details is None:
# No subscribers at all.
diff --git a/lib/lp/bugs/tests/test_bugs_webservice.py b/lib/lp/bugs/tests/test_bugs_webservice.py
index 92664a4..fcd29c0 100644
--- a/lib/lp/bugs/tests/test_bugs_webservice.py
+++ b/lib/lp/bugs/tests/test_bugs_webservice.py
@@ -11,7 +11,6 @@ from datetime import datetime, timedelta
import pytz
import six
from lazr.lifecycle.interfaces import IDoNotSnapshot
-from simplejson import dumps
from storm.store import Store
from testtools.matchers import Equals, LessThan
from zope.component import getMultiAdapter
@@ -121,7 +120,7 @@ class TestBugDescriptionRepresentation(TestCaseWithFactory):
response = self.webservice.patch(
bug_two_json["self_link"],
"application/json",
- dumps(dict(description=new_description)),
+ json.dumps(dict(description=new_description)),
headers=dict(accept="application/xhtml+xml"),
)
@@ -517,7 +516,7 @@ class TestBugDateLastUpdated(TestCaseWithFactory):
date_last_updated = bug.date_last_updated
logout()
response = webservice.patch(
- task_url, "application/json", dumps(dict(status="Invalid"))
+ task_url, "application/json", json.dumps(dict(status="Invalid"))
)
self.assertEqual(209, response.status)
with person_logged_in(owner):
diff --git a/lib/lp/code/browser/branch.py b/lib/lp/code/browser/branch.py
index 1ecf228..5ecce7e 100644
--- a/lib/lp/code/browser/branch.py
+++ b/lib/lp/code/browser/branch.py
@@ -22,10 +22,10 @@ __all__ = [
"RegisterBranchMergeProposalView",
]
+import json
from datetime import datetime
import pytz
-import simplejson
from lazr.lifecycle.event import ObjectModifiedEvent
from lazr.lifecycle.snapshot import Snapshot
from lazr.restful.fields import Reference
@@ -1354,7 +1354,7 @@ class RegisterBranchMergeProposalView(LaunchpadFormView):
if self.request.is_ajax and len(visible_branches) < 2:
self.request.response.setStatus(400, "Branch Visibility")
self.request.response.setHeader("Content-Type", "application/json")
- return simplejson.dumps(
+ return json.dumps(
{
"person_name": visibility_info["person_name"],
"branches_to_check": branch_names,
diff --git a/lib/lp/code/browser/branchmergeproposal.py b/lib/lp/code/browser/branchmergeproposal.py
index a2fe57e..a789afb 100644
--- a/lib/lp/code/browser/branchmergeproposal.py
+++ b/lib/lp/code/browser/branchmergeproposal.py
@@ -24,11 +24,11 @@ __all__ = [
"latest_proposals_for_each_branch",
]
+import json
import operator
from functools import wraps
from urllib.parse import urlsplit, urlunsplit
-import simplejson
from lazr.delegates import delegate_to
from lazr.restful.interface import copy_field
from lazr.restful.interfaces import IJSONRequestCache, IWebServiceClientRequest
@@ -851,7 +851,7 @@ class BranchMergeProposalView(
@property
def status_config(self):
"""The config to configure the ChoiceSource JS widget."""
- return simplejson.dumps(
+ return json.dumps(
{
"status_widget_items": vocabulary_to_choice_edit_items(
self._createStatusVocabulary(),
diff --git a/lib/lp/code/browser/sourcepackagerecipe.py b/lib/lp/code/browser/sourcepackagerecipe.py
index be599c4..002520d 100644
--- a/lib/lp/code/browser/sourcepackagerecipe.py
+++ b/lib/lp/code/browser/sourcepackagerecipe.py
@@ -14,8 +14,8 @@ __all__ = [
]
import itertools
+import json
-import simplejson
from brzbuildrecipe.recipe import ForbiddenInstructionError, RecipeParseError
from lazr.lifecycle.event import ObjectModifiedEvent
from lazr.lifecycle.snapshot import Snapshot
@@ -485,7 +485,7 @@ class SourcePackageRecipeRequestBuildsAjaxView(
return_data = dict(builds=builds, errors=errors)
if informational:
return_data.update(informational)
- return simplejson.dumps(return_data)
+ return json.dumps(return_data)
def failure(self, action, data, errors):
"""Called by the form if validate() finds any errors.
diff --git a/lib/lp/code/browser/tests/test_branchmergeproposal.py b/lib/lp/code/browser/tests/test_branchmergeproposal.py
index b481374..e624054 100644
--- a/lib/lp/code/browser/tests/test_branchmergeproposal.py
+++ b/lib/lp/code/browser/tests/test_branchmergeproposal.py
@@ -5,12 +5,12 @@
import doctest
import hashlib
+import json
import re
from datetime import datetime, timedelta
from difflib import diff_bytes, unified_diff
import pytz
-import simplejson
import transaction
from fixtures import FakeLogger
from lazr.lifecycle.event import ObjectModifiedEvent
@@ -877,7 +877,7 @@ class TestRegisterBranchMergeProposalViewBzr(
self.assertEqual(
"400 Branch Visibility", view.request.response.getStatusString()
)
- self.assertEqual(expected_data, simplejson.loads(result_data))
+ self.assertEqual(expected_data, json.loads(result_data))
def test_register_ajax_request_with_validation_errors(self):
# Ajax submits where there is a validation error in the submitted data
@@ -917,7 +917,7 @@ class TestRegisterBranchMergeProposalViewBzr(
},
"form_wide_errors": [],
},
- simplejson.loads(view.form_result),
+ json.loads(view.form_result),
)
@@ -1013,7 +1013,7 @@ class TestRegisterBranchMergeProposalViewGit(
"400 Repository Visibility",
view.request.response.getStatusString(),
)
- self.assertEqual(expected_data, simplejson.loads(result_data))
+ self.assertEqual(expected_data, json.loads(result_data))
def test_register_ajax_request_with_validation_errors(self):
# Ajax submits where there is a validation error in the submitted data
@@ -1053,7 +1053,7 @@ class TestRegisterBranchMergeProposalViewGit(
},
"form_wide_errors": [],
},
- simplejson.loads(view.form_result),
+ json.loads(view.form_result),
)
def test_register_ajax_request_with_missing_target_git_repository(self):
@@ -1086,7 +1086,7 @@ class TestRegisterBranchMergeProposalViewGit(
},
"form_wide_errors": [],
},
- simplejson.loads(view.form_result),
+ json.loads(view.form_result),
)
def test_register_ajax_request_with_missing_target_git_path(self):
@@ -1123,7 +1123,7 @@ class TestRegisterBranchMergeProposalViewGit(
},
"form_wide_errors": [],
},
- simplejson.loads(view.form_result),
+ json.loads(view.form_result),
)
def test_register_ajax_request_with_missing_prerequisite_git_path(self):
@@ -1170,7 +1170,7 @@ class TestRegisterBranchMergeProposalViewGit(
},
"form_wide_errors": [],
},
- simplejson.loads(view.form_result),
+ json.loads(view.form_result),
)
diff --git a/lib/lp/code/model/branchmergeproposaljob.py b/lib/lp/code/model/branchmergeproposaljob.py
index d120ebe..35c8bdf 100644
--- a/lib/lp/code/model/branchmergeproposaljob.py
+++ b/lib/lp/code/model/branchmergeproposaljob.py
@@ -19,11 +19,11 @@ __all__ = [
"UpdatePreviewDiffJob",
]
+import json
from contextlib import ExitStack
from datetime import datetime, timedelta
import pytz
-import simplejson
import six
from lazr.delegates import delegate_to
from lazr.enum import DBEnumeratedType, DBItem
@@ -155,7 +155,7 @@ class BranchMergeProposalJob(StormBase):
@property
def metadata(self):
- return simplejson.loads(self._json_data)
+ return json.loads(self._json_data)
def __init__(self, branch_merge_proposal, job_type, metadata):
"""Constructor.
@@ -166,7 +166,7 @@ class BranchMergeProposalJob(StormBase):
dict.
"""
super().__init__()
- json_data = simplejson.dumps(metadata)
+ json_data = json.dumps(metadata)
self.job = Job()
self.branch_merge_proposal = branch_merge_proposal
self.job_type = job_type
diff --git a/lib/lp/code/model/diff.py b/lib/lp/code/model/diff.py
index 21e9968..7def5fd 100644
--- a/lib/lp/code/model/diff.py
+++ b/lib/lp/code/model/diff.py
@@ -10,12 +10,12 @@ __all__ = [
]
import io
+import json
import sys
from contextlib import ExitStack
from operator import attrgetter
from uuid import uuid1
-import simplejson
import six
from breezy import trace
from breezy.diff import show_diff_trees
@@ -60,7 +60,7 @@ class Diff(SQLBase):
return None
return {
key: tuple(value)
- for key, value in simplejson.loads(self._diffstat).items()
+ for key, value in json.loads(self._diffstat).items()
}
def _set_diffstat(self, diffstat):
@@ -69,7 +69,7 @@ class Diff(SQLBase):
return
# diffstats should be mappings of path to line counts.
assert isinstance(diffstat, dict)
- self._diffstat = simplejson.dumps(diffstat)
+ self._diffstat = json.dumps(diffstat)
diffstat = property(_get_diffstat, _set_diffstat)
diff --git a/lib/lp/registry/browser/team.py b/lib/lp/registry/browser/team.py
index 32afa9a..8de222c 100644
--- a/lib/lp/registry/browser/team.py
+++ b/lib/lp/registry/browser/team.py
@@ -30,13 +30,12 @@ __all__ = [
"TeamReassignmentView",
]
-
+import json
import math
from datetime import datetime, timedelta
from urllib.parse import unquote
import pytz
-import simplejson
from lazr.restful.interface import copy_field
from lazr.restful.interfaces import IJSONRequestCache
from lazr.restful.utils import smartquote
@@ -1061,7 +1060,7 @@ class TeamMailingListArchiveView(LaunchpadView):
# XXX: jcsackett 18-1-2012: This needs to be updated to use the
# grackle client, once that is available, instead of returning
# an empty list as it does now.
- return simplejson.loads("[]")
+ return json.loads("[]")
class TeamAddView(TeamFormMixin, HasRenewalPolicyMixin, LaunchpadFormView):
diff --git a/lib/lp/registry/browser/tests/test_pillar_sharing.py b/lib/lp/registry/browser/tests/test_pillar_sharing.py
index c295f6d..75abf61 100644
--- a/lib/lp/registry/browser/tests/test_pillar_sharing.py
+++ b/lib/lp/registry/browser/tests/test_pillar_sharing.py
@@ -3,7 +3,8 @@
"""Test views that manage sharing."""
-import simplejson
+import json
+
from fixtures import FakeLogger
from lazr.restful.interfaces import IJSONRequestCache
from lazr.restful.utils import get_current_web_service_request
@@ -307,7 +308,7 @@ class PillarSharingViewTestMixin:
def test_picker_config(self):
# Test the config passed to the disclosure sharing picker.
view = create_view(self.pillar, name="+sharing")
- picker_config = simplejson.loads(view.json_sharing_picker_config)
+ picker_config = json.loads(view.json_sharing_picker_config)
self.assertTrue("vocabulary_filters" in picker_config)
self.assertEqual("Share project information", picker_config["header"])
self.assertEqual(
diff --git a/lib/lp/registry/browser/tests/test_team.py b/lib/lp/registry/browser/tests/test_team.py
index fdbef5a..6330233 100644
--- a/lib/lp/registry/browser/tests/test_team.py
+++ b/lib/lp/registry/browser/tests/test_team.py
@@ -2,8 +2,8 @@
# GNU Affero General Public License version 3 (see the file LICENSE).
import contextlib
+import json
-import simplejson
import soupmatchers
import transaction
from lazr.restful.interfaces import IJSONRequestCache
@@ -740,7 +740,7 @@ class TestMailingListArchiveView(TestCaseWithFactory):
@contextlib.contextmanager
def _override_messages(self, view_class, messages):
def _message_shim(self):
- return simplejson.loads(messages)
+ return json.loads(messages)
tmp = TeamMailingListArchiveView._get_messages
TeamMailingListArchiveView._get_messages = _message_shim
diff --git a/lib/lp/registry/model/persontransferjob.py b/lib/lp/registry/model/persontransferjob.py
index 14eaa9d..78bf6a9 100644
--- a/lib/lp/registry/model/persontransferjob.py
+++ b/lib/lp/registry/model/persontransferjob.py
@@ -9,10 +9,10 @@ __all__ = [
"PersonTransferJob",
]
+import json
from datetime import datetime
import pytz
-import simplejson
import six
import transaction
from lazr.delegates import delegate_to
@@ -84,7 +84,7 @@ class PersonTransferJob(StormBase):
@property
def metadata(self):
- return simplejson.loads(self._json_data)
+ return json.loads(self._json_data)
def __init__(
self, minor_person, major_person, job_type, metadata, requester=None
@@ -105,7 +105,7 @@ class PersonTransferJob(StormBase):
self.major_person = major_person
self.minor_person = minor_person
- json_data = simplejson.dumps(metadata)
+ json_data = json.dumps(metadata)
# XXX AaronBentley 2009-01-29 bug=322819: This should be a bytestring,
# but the DB representation is unicode.
self._json_data = six.ensure_text(json_data)
diff --git a/lib/lp/registry/model/productjob.py b/lib/lp/registry/model/productjob.py
index 5ca685d..107ffac 100644
--- a/lib/lp/registry/model/productjob.py
+++ b/lib/lp/registry/model/productjob.py
@@ -11,9 +11,9 @@ __all__ = [
"ThirtyDayCommercialExpirationJob",
]
+import json
from datetime import datetime, timedelta
-import simplejson
import six
from lazr.delegates import delegate_to
from pytz import utc
@@ -125,7 +125,7 @@ class ProductJob(StormBase):
@property
def metadata(self):
- return simplejson.loads(self._json_data)
+ return json.loads(self._json_data)
def __init__(self, product, job_type, metadata):
"""Constructor.
@@ -138,7 +138,7 @@ class ProductJob(StormBase):
self.job = Job()
self.product = product
self.job_type = job_type
- json_data = simplejson.dumps(metadata)
+ json_data = json.dumps(metadata)
self._json_data = six.ensure_text(json_data)
diff --git a/lib/lp/registry/model/sharingjob.py b/lib/lp/registry/model/sharingjob.py
index bd9ba75..3dc412d 100644
--- a/lib/lp/registry/model/sharingjob.py
+++ b/lib/lp/registry/model/sharingjob.py
@@ -7,9 +7,9 @@ __all__ = [
"RemoveArtifactSubscriptionsJob",
]
+import json
import logging
-import simplejson
import six
from lazr.delegates import delegate_to
from lazr.enum import DBEnumeratedType, DBItem
@@ -124,7 +124,7 @@ class SharingJob(StormBase):
@property
def metadata(self):
- return simplejson.loads(self._json_data)
+ return json.loads(self._json_data)
def __init__(self, job_type, pillar, grantee, metadata):
"""Constructor.
@@ -134,7 +134,7 @@ class SharingJob(StormBase):
dict.
"""
super().__init__()
- json_data = simplejson.dumps(metadata)
+ json_data = json.dumps(metadata)
self.job = Job()
self.job_type = job_type
self.grantee = grantee
diff --git a/lib/lp/registry/stories/webservice/xx-distribution-mirror.rst b/lib/lp/registry/stories/webservice/xx-distribution-mirror.rst
index 871d46b..057ac11 100644
--- a/lib/lp/registry/stories/webservice/xx-distribution-mirror.rst
+++ b/lib/lp/registry/stories/webservice/xx-distribution-mirror.rst
@@ -81,11 +81,11 @@ Security checks
People who are not mirror listing admins or the mirrors registrar may not
change the owner's of mirrors:
+ >>> import json
>>> from zope.component import getUtility
>>> from lp.testing.pages import webservice_for_person
>>> from lp.services.webapp.interfaces import OAuthPermission
>>> from lp.registry.interfaces.person import IPersonSet
- >>> from simplejson import dumps
>>> login(ANONYMOUS)
>>> karl_db = getUtility(IPersonSet).getByName("karl")
>>> test_db = getUtility(IPersonSet).getByName("name12")
@@ -187,7 +187,9 @@ authorized.
>>> karl = webservice.get("/~karl").jsonBody()
>>> patch = {"owner_link": karl["self_link"]}
>>> response = test_webservice.patch(
- ... canonical_archive["self_link"], "application/json", dumps(patch)
+ ... canonical_archive["self_link"],
+ ... "application/json",
+ ... json.dumps(patch),
... )
>>> response.status
401
@@ -196,7 +198,9 @@ But if we use Karl, the mirror listing admin's, webservice, we can update
the owner.
>>> response = karl_webservice.patch(
- ... canonical_archive["self_link"], "application/json", dumps(patch)
+ ... canonical_archive["self_link"],
+ ... "application/json",
+ ... json.dumps(patch),
... )
>>> response.status
209
@@ -216,7 +220,9 @@ Some attributes are read-only via the API:
... "reviewer_link": karl["self_link"],
... }
>>> response = karl_webservice.patch(
- ... canonical_releases["self_link"], "application/json", dumps(patch)
+ ... canonical_releases["self_link"],
+ ... "application/json",
+ ... json.dumps(patch),
... )
>>> print(response)
HTTP/1.1 400 Bad Request
@@ -237,13 +243,17 @@ While others can be set with the appropriate authorization:
... "whiteboard": "This mirror is too shiny to be true",
... }
>>> response = test_webservice.patch(
- ... canonical_releases["self_link"], "application/json", dumps(patch)
+ ... canonical_releases["self_link"],
+ ... "application/json",
+ ... json.dumps(patch),
... )
>>> response.status
401
>>> response = karl_webservice.patch(
- ... canonical_releases["self_link"], "application/json", dumps(patch)
+ ... canonical_releases["self_link"],
+ ... "application/json",
+ ... json.dumps(patch),
... ).jsonBody()
>>> pprint_entry(response)
base_url: 'http://releases.ubuntu.com/'
diff --git a/lib/lp/registry/stories/webservice/xx-distribution.rst b/lib/lp/registry/stories/webservice/xx-distribution.rst
index aa2b91e..79a1450 100644
--- a/lib/lp/registry/stories/webservice/xx-distribution.rst
+++ b/lib/lp/registry/stories/webservice/xx-distribution.rst
@@ -197,12 +197,12 @@ returning None if there isn't one.
Prepare stuff.
+ >>> import json
>>> from zope.component import getUtility
>>> from lp.testing.pages import webservice_for_person
>>> from lp.services.webapp.interfaces import OAuthPermission
>>> from lp.registry.interfaces.distribution import IDistributionSet
>>> from lp.registry.interfaces.person import IPersonSet
- >>> from simplejson import dumps
>>> login("admin@xxxxxxxxxxxxx")
>>> ubuntu_distro = getUtility(IDistributionSet).getByName("ubuntu")
@@ -235,7 +235,7 @@ Mark new mirror as official and a country mirror.
>>> response = karl_webservice.patch(
... antarctica_patch_target["self_link"],
... "application/json",
- ... dumps(patch),
+ ... json.dumps(patch),
... )
>>> antarctica = webservice.get("/+countries/AQ").jsonBody()
diff --git a/lib/lp/registry/stories/webservice/xx-person.rst b/lib/lp/registry/stories/webservice/xx-person.rst
index 93bcbba..1249d3e 100644
--- a/lib/lp/registry/stories/webservice/xx-person.rst
+++ b/lib/lp/registry/stories/webservice/xx-person.rst
@@ -576,10 +576,10 @@ to, obviously.
Wiki names can be modified.
- >>> from simplejson import dumps
+ >>> import json
>>> patch = {"wiki": "http://www.example.com/", "wikiname": "MrExample"}
>>> response = webservice.patch(
- ... wiki_name["self_link"], "application/json", dumps(patch)
+ ... wiki_name["self_link"], "application/json", json.dumps(patch)
... )
>>> wiki_name = sorted(webservice.get(wikis_link).jsonBody()["entries"])[
... 0
@@ -592,7 +592,7 @@ escaped as if it was HTML.
>>> patch = {"wiki": "javascript:void/**/", "wikiname": "MrExample"}
>>> response = webservice.patch(
- ... wiki_name["self_link"], "application/json", dumps(patch)
+ ... wiki_name["self_link"], "application/json", json.dumps(patch)
... )
>>> print(response)
HTTP/1.1 400 Bad Request
@@ -969,12 +969,9 @@ Restrictions
A team can't be its own owner.
- >>> import simplejson
>>> doc = {"team_owner_link": webservice.getAbsoluteUrl("/~admins")}
>>> print(
- ... webservice.patch(
- ... "/~admins", "application/json", simplejson.dumps(doc)
- ... )
+ ... webservice.patch("/~admins", "application/json", json.dumps(doc))
... )
HTTP/1.1 400 Bad Request
...
diff --git a/lib/lp/registry/stories/webservice/xx-private-team.rst b/lib/lp/registry/stories/webservice/xx-private-team.rst
index 43e1e16..b69f5c1 100644
--- a/lib/lp/registry/stories/webservice/xx-private-team.rst
+++ b/lib/lp/registry/stories/webservice/xx-private-team.rst
@@ -130,13 +130,11 @@ Create a webservice object for commercial-admins.
A commercial admin may change the visibility. There is no helper
method to do it, but it can be changed via a patch.
- >>> import simplejson
+ >>> import json
>>> def modify_team(team, representation, method, service):
... "A helper function to send a PUT or PATCH request to a team."
... headers = {"Content-type": "application/json"}
- ... return service(
- ... team, method, simplejson.dumps(representation), headers
- ... )
+ ... return service(team, method, json.dumps(representation), headers)
...
>>> print(
diff --git a/lib/lp/registry/stories/webservice/xx-project-registry.rst b/lib/lp/registry/stories/webservice/xx-project-registry.rst
index 4ab95f4..796f357 100644
--- a/lib/lp/registry/stories/webservice/xx-project-registry.rst
+++ b/lib/lp/registry/stories/webservice/xx-project-registry.rst
@@ -371,7 +371,7 @@ development_focus_link.
Attributes can be edited via the webservice.patch() method.
- >>> from simplejson import dumps
+ >>> import json
>>> patch = {
... "driver_link": webservice.getAbsoluteUrl("/~mark"),
... "homepage_url": "http://sf.net/firefox",
@@ -380,7 +380,11 @@ Attributes can be edited via the webservice.patch() method.
... "/bugs/bugtrackers/mozilla.org"
... ),
... }
- >>> print(webservice.patch("/firefox", "application/json", dumps(patch)))
+ >>> print(
+ ... webservice.patch(
+ ... "/firefox", "application/json", json.dumps(patch)
+ ... )
+ ... )
HTTP/1.1 209 Content Returned
...
@@ -434,7 +438,7 @@ changed as well.
... }
>>> print(
... webservice.patch(
- ... "/test-project", "application/json", dumps(patch)
+ ... "/test-project", "application/json", json.dumps(patch)
... )
... )
HTTP/1.1 209 Content Returned
@@ -450,7 +454,11 @@ webservice.patch() method.
>>> patch = {
... "registrant_link": webservice.getAbsoluteUrl("/~mark"),
... }
- >>> print(webservice.patch("/firefox", "application/json", dumps(patch)))
+ >>> print(
+ ... webservice.patch(
+ ... "/firefox", "application/json", json.dumps(patch)
+ ... )
+ ... )
HTTP/1.1 400 Bad Request
...
registrant_link: You tried to modify a read-only attribute.
@@ -463,7 +471,11 @@ Similarly the date_created attribute cannot be modified.
>>> original_date_created = firefox["date_created"]
>>> patch = {"date_created": "2000-01-01T01:01:01+00:00Z"}
- >>> print(webservice.patch("/firefox", "application/json", dumps(patch)))
+ >>> print(
+ ... webservice.patch(
+ ... "/firefox", "application/json", json.dumps(patch)
+ ... )
+ ... )
HTTP/1.1 400 Bad Request
...
date_created: You tried to modify a read-only attribute.
@@ -478,7 +490,7 @@ hierarchy of series, milestones, and releases.
>>> patch = {"status": "Obsolete"}
>>> print(
... webservice.patch(
- ... "/firefox/trunk", "application/json", dumps(patch)
+ ... "/firefox/trunk", "application/json", json.dumps(patch)
... )
... )
HTTP/1.1 209 Content Returned...
diff --git a/lib/lp/scripts/garbo.py b/lib/lp/scripts/garbo.py
index 348b7a7..3b974a8 100644
--- a/lib/lp/scripts/garbo.py
+++ b/lib/lp/scripts/garbo.py
@@ -11,6 +11,7 @@ __all__ = [
"save_garbo_job_state",
]
+import json
import logging
import multiprocessing
import os
@@ -20,7 +21,6 @@ from datetime import datetime, timedelta
import iso8601
import pytz
-import simplejson
import six
import transaction
from contrib.glock import GlobalLock, LockAlreadyAcquired
@@ -168,14 +168,14 @@ def load_garbo_job_state(job_name):
.get_one()
)
if job_data:
- return simplejson.loads(job_data[0])
+ return json.loads(job_data[0])
return None
def save_garbo_job_state(job_name, job_data):
# Save the json state data for the given job name.
store = IMasterStore(Person)
- json_data = simplejson.dumps(job_data, ensure_ascii=False)
+ json_data = json.dumps(job_data, ensure_ascii=False)
result = store.execute(
"UPDATE GarboJobState SET json_data = ? WHERE name = ?",
params=(json_data, six.ensure_text(job_name)),
diff --git a/lib/lp/services/oauth/browser/__init__.py b/lib/lp/services/oauth/browser/__init__.py
index 0b70209..2a67f72 100644
--- a/lib/lp/services/oauth/browser/__init__.py
+++ b/lib/lp/services/oauth/browser/__init__.py
@@ -8,10 +8,10 @@ __all__ = [
"lookup_oauth_context",
]
+import json
from datetime import datetime, timedelta
import pytz
-import simplejson
from lazr.restful import HTTPResource
from zope.component import getUtility
from zope.formlib.form import Action, Actions, expandPrefix
@@ -58,7 +58,7 @@ class JSONTokenMixin:
]
structure["access_levels"] = access_levels
self.request.response.setHeader("Content-Type", HTTPResource.JSON_TYPE)
- return simplejson.dumps(structure)
+ return json.dumps(structure)
class OAuthRequestTokenView(LaunchpadFormView, JSONTokenMixin):
diff --git a/lib/lp/services/oauth/stories/authorize-token.rst b/lib/lp/services/oauth/stories/authorize-token.rst
index f71bd0b..39ce2bc 100644
--- a/lib/lp/services/oauth/stories/authorize-token.rst
+++ b/lib/lp/services/oauth/stories/authorize-token.rst
@@ -158,7 +158,7 @@ by the user is restricted to things related to that context.
A client other than a web browser may request a JSON representation of
the list of authentication levels.
- >>> import simplejson
+ >>> import json
>>> from lp.testing.pages import setupBrowser
>>> json_browser = setupBrowser()
@@ -169,7 +169,7 @@ the list of authentication levels.
>>> json_browser.open(
... "http://launchpad.test/+authorize-token?%s" % urlencode(params)
... )
- >>> json_token = simplejson.loads(json_browser.contents)
+ >>> json_token = json.loads(json_browser.contents.decode())
>>> sorted(json_token.keys())
['access_levels', 'oauth_token', 'oauth_token_consumer']
@@ -190,7 +190,7 @@ the list of authentication levels.
... )
... % urlencode(params)
... )
- >>> json_token = simplejson.loads(json_browser.contents)
+ >>> json_token = json.loads(json_browser.contents.decode())
>>> sorted(
... (level["value"], level["title"])
... for level in json_token["access_levels"]
diff --git a/lib/lp/services/oauth/stories/request-token.rst b/lib/lp/services/oauth/stories/request-token.rst
index 1496f13..2bc110a 100644
--- a/lib/lp/services/oauth/stories/request-token.rst
+++ b/lib/lp/services/oauth/stories/request-token.rst
@@ -22,7 +22,7 @@ The consumer can ask for a JSON representation of the request token,
which will also include information about the available permission
levels.
- >>> import simplejson
+ >>> import json
>>> from lp.testing.pages import setupBrowser
>>> json_browser = setupBrowser()
@@ -30,7 +30,7 @@ levels.
>>> json_browser.open(
... "http://launchpad.test/+request-token", data=urlencode(data)
... )
- >>> token = simplejson.loads(json_browser.contents)
+ >>> token = json.loads(json_browser.contents.decode())
>>> sorted(token.keys())
['access_levels', 'oauth_token', 'oauth_token_consumer',
'oauth_token_secret']
diff --git a/lib/lp/services/webapp/batching.py b/lib/lp/services/webapp/batching.py
index 61fbc6f..35eb313 100644
--- a/lib/lp/services/webapp/batching.py
+++ b/lib/lp/services/webapp/batching.py
@@ -1,13 +1,13 @@
# Copyright 2011 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+import json
import re
from collections.abc import Sequence
from datetime import datetime
from functools import reduce
import lazr.batchnavigator
-import simplejson
from iso8601 import ParseError, parse_date
from lazr.batchnavigator.interfaces import IRangeFactory
from storm import Undef
@@ -194,7 +194,7 @@ class TableBatchNavigator(BatchNavigator):
self.show_column[column_to_show] = True
-class DateTimeJSONEncoder(simplejson.JSONEncoder):
+class DateTimeJSONEncoder(json.JSONEncoder):
"""A JSON encoder that understands datetime objects.
Datetime objects are formatted according to ISO 1601.
@@ -203,7 +203,7 @@ class DateTimeJSONEncoder(simplejson.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
- return simplejson.JSONEncoder.default(self, obj)
+ return json.JSONEncoder.default(self, obj)
class ShadowedList:
@@ -381,8 +381,8 @@ class StormRangeFactory:
lower = self.getOrderValuesFor(plain_slice[0])
upper = self.getOrderValuesFor(plain_slice[batch.trueSize - 1])
return (
- simplejson.dumps(lower, cls=DateTimeJSONEncoder),
- simplejson.dumps(upper, cls=DateTimeJSONEncoder),
+ json.dumps(lower, cls=DateTimeJSONEncoder),
+ json.dumps(upper, cls=DateTimeJSONEncoder),
)
def reportError(self, message):
@@ -404,8 +404,8 @@ class StormRangeFactory:
if memo == "":
return None
try:
- parsed_memo = simplejson.loads(memo)
- except simplejson.JSONDecodeError:
+ parsed_memo = json.loads(memo)
+ except json.JSONDecodeError:
self.reportError("memo is not a valid JSON string.")
return None
if not isinstance(parsed_memo, list):
@@ -429,7 +429,7 @@ class StormRangeFactory:
except TypeError as error:
# A TypeError is raised when the type of value cannot
# be used for expression. All expected types are
- # properly created by simplejson.loads() above, except
+ # properly created by json.loads() above, except
# time stamps which are represented as strings in
# ISO format. If value is a string and if it can be
# converted into a datetime object, we have a valid
diff --git a/lib/lp/services/webapp/tests/test_batching.py b/lib/lp/services/webapp/tests/test_batching.py
index fdbf3f0..bc461db 100644
--- a/lib/lp/services/webapp/tests/test_batching.py
+++ b/lib/lp/services/webapp/tests/test_batching.py
@@ -1,10 +1,10 @@
# Copyright 2011-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+import json
from datetime import datetime
import pytz
-import simplejson
from lazr.batchnavigator.interfaces import IRangeFactory
from storm.expr import Desc, compile
from storm.store import EmptyResultSet
@@ -177,12 +177,12 @@ class TestStormRangeFactory(TestCaseWithFactory):
# where the value is represented in the ISO time format.
self.assertEqual(
'"2011-07-25T00:00:00"',
- simplejson.dumps(datetime(2011, 7, 25), cls=DateTimeJSONEncoder),
+ json.dumps(datetime(2011, 7, 25), cls=DateTimeJSONEncoder),
)
# DateTimeJSONEncoder works for the regular Python types that can
# represented as JSON strings.
- encoded = simplejson.dumps(
+ encoded = json.dumps(
("foo", 1, 2.0, [3, 4], {5: "bar"}, datetime(2011, 7, 24)),
cls=DateTimeJSONEncoder,
)
@@ -199,16 +199,16 @@ class TestStormRangeFactory(TestCaseWithFactory):
range_factory = StormRangeFactory(resultset)
memo_value = range_factory.getOrderValuesFor(resultset[0])
request = LaunchpadTestRequest(
- QUERY_STRING="memo=%s" % simplejson.dumps(memo_value)
+ QUERY_STRING="memo=%s" % json.dumps(memo_value)
)
batchnav = BatchNavigator(
resultset, request, size=3, range_factory=range_factory
)
first, last = range_factory.getEndpointMemos(batchnav.batch)
- expected_first = simplejson.dumps(
+ expected_first = json.dumps(
[resultset[1].name], cls=DateTimeJSONEncoder
)
- expected_last = simplejson.dumps(
+ expected_last = json.dumps(
[resultset[3].name], cls=DateTimeJSONEncoder
)
self.assertEqual(expected_first, first)
@@ -225,11 +225,11 @@ class TestStormRangeFactory(TestCaseWithFactory):
resultset, request, size=3, range_factory=range_factory
)
first, last = range_factory.getEndpointMemos(batchnav.batch)
- expected_first = simplejson.dumps(
+ expected_first = json.dumps(
[resultset.get_plain_result_set()[0][1].id],
cls=DateTimeJSONEncoder,
)
- expected_last = simplejson.dumps(
+ expected_last = json.dumps(
[resultset.get_plain_result_set()[2][1].id],
cls=DateTimeJSONEncoder,
)
@@ -260,7 +260,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
# parseMemo() accepts only JSON representations of lists.
resultset = self.makeStormResultSet()
range_factory = StormRangeFactory(resultset, self.logError)
- self.assertIs(None, range_factory.parseMemo(simplejson.dumps(1)))
+ self.assertIs(None, range_factory.parseMemo(json.dumps(1)))
self.assertEqual(
["memo must be the JSON representation of a list."],
self.error_messages,
@@ -273,7 +273,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
resultset = self.makeStormResultSet()
resultset.order_by(Person.name, Person.id)
range_factory = StormRangeFactory(resultset, self.logError)
- self.assertIs(None, range_factory.parseMemo(simplejson.dumps([1])))
+ self.assertIs(None, range_factory.parseMemo(json.dumps([1])))
expected_message = (
"Invalid number of elements in memo string. Expected: 2, got: 1"
)
@@ -286,7 +286,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
resultset.order_by(Person.datecreated, Person.name, Person.id)
range_factory = StormRangeFactory(resultset, self.logError)
invalid_memo = [datetime(2011, 7, 25, 11, 30, 30, 45), "foo", "bar"]
- json_data = simplejson.dumps(invalid_memo, cls=DateTimeJSONEncoder)
+ json_data = json.dumps(invalid_memo, cls=DateTimeJSONEncoder)
self.assertIs(None, range_factory.parseMemo(json_data))
self.assertEqual(["Invalid parameter: 'bar'"], self.error_messages)
@@ -300,7 +300,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
"foo",
1,
]
- json_data = simplejson.dumps(valid_memo, cls=DateTimeJSONEncoder)
+ json_data = json.dumps(valid_memo, cls=DateTimeJSONEncoder)
self.assertEqual(valid_memo, range_factory.parseMemo(json_data))
self.assertEqual(0, len(self.error_messages))
@@ -392,7 +392,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
resultset = self.makeStormResultSet()
resultset.order_by(Desc(Person.id))
range_factory = StormRangeFactory(resultset, self.logError)
- self.assertEqual([1], range_factory.parseMemo(simplejson.dumps([1])))
+ self.assertEqual([1], range_factory.parseMemo(json.dumps([1])))
def test_reverseSortOrder(self):
# reverseSortOrder() wraps a plain PropertyColumn instance into
@@ -584,7 +584,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
resultset = self.makeStormResultSet()
resultset.order_by(Person.name, Person.id)
all_results = list(resultset)
- memo = simplejson.dumps([all_results[0].name, all_results[0].id])
+ memo = json.dumps([all_results[0].name, all_results[0].id])
range_factory = StormRangeFactory(resultset)
sliced_result = range_factory.getSlice(3, memo)
self.assertEqual(all_results[1:4], list(sliced_result))
@@ -605,7 +605,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
all_results = list(resultset)
expected = all_results[1:4]
expected.reverse()
- memo = simplejson.dumps([all_results[4].name, all_results[4].id])
+ memo = json.dumps([all_results[4].name, all_results[4].id])
range_factory = StormRangeFactory(resultset)
sliced_result = range_factory.getSlice(3, memo, forwards=False)
self.assertEqual(expected, list(sliced_result))
@@ -646,9 +646,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
# for a forward batch, the slice of this btach starts with
# the fourth row of the entire result set.
memo_lfa = all_results[2].libraryfile
- memo = simplejson.dumps(
- [memo_lfa.mimetype, memo_lfa.filename, memo_lfa.id]
- )
+ memo = json.dumps([memo_lfa.mimetype, memo_lfa.filename, memo_lfa.id])
range_factory = StormRangeFactory(resultset)
sliced_result = range_factory.getSlice(3, memo)
self.assertEqual(all_results[3:6], list(sliced_result))
@@ -658,7 +656,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
resultset.order_by(LibraryFileAlias.id)
all_results = list(resultset)
plain_results = list(resultset.get_plain_result_set())
- memo = simplejson.dumps([resultset.get_plain_result_set()[0][1].id])
+ memo = json.dumps([resultset.get_plain_result_set()[0][1].id])
range_factory = StormRangeFactory(resultset)
sliced_result = range_factory.getSlice(3, memo)
self.assertEqual(all_results[1:4], list(sliced_result))
@@ -677,7 +675,7 @@ class TestStormRangeFactory(TestCaseWithFactory):
resultset = self.makeStormResultSet()
resultset.order_by(Person.id)
all_results = list(resultset)
- memo = simplejson.dumps([all_results[2].id])
+ memo = json.dumps([all_results[2].id])
range_factory = StormRangeFactory(resultset)
backward_slice = range_factory.getSlice(
size=2, endpoint_memo=memo, forwards=False
diff --git a/lib/lp/services/webapp/tests/test_view_model.py b/lib/lp/services/webapp/tests/test_view_model.py
index 15ce566..f7cc65a 100644
--- a/lib/lp/services/webapp/tests/test_view_model.py
+++ b/lib/lp/services/webapp/tests/test_view_model.py
@@ -3,9 +3,10 @@
"""Tests for the user requested oops using ++oops++ traversal."""
+import json
+
from lazr.restful.interfaces import IJSONRequestCache
from lazr.restful.utils import get_current_browser_request
-from simplejson import loads
from testtools.matchers import KeysEqual
from zope.configuration import xmlconfig
@@ -123,7 +124,7 @@ class TestJsonModelView(BrowserTestCase):
lp.services.webapp.tests.ProductModelTestView = ProductModelTestView
self.configZCML()
browser = self.getUserBrowser(self.url)
- cache = loads(browser.contents)
+ cache = json.loads(browser.contents.decode())
self.assertThat(cache, KeysEqual("related_features", "context"))
def test_JsonModel_custom_cache(self):
@@ -140,7 +141,7 @@ class TestJsonModelView(BrowserTestCase):
lp.services.webapp.tests.ProductModelTestView = ProductModelTestView
self.configZCML()
browser = self.getUserBrowser(self.url)
- cache = loads(browser.contents)
+ cache = json.loads(browser.contents.decode())
self.assertThat(
cache, KeysEqual("related_features", "context", "target_info")
)
@@ -165,7 +166,7 @@ class TestJsonModelView(BrowserTestCase):
lp.services.webapp.tests.ProductModelTestView = ProductModelTestView
self.configZCML()
browser = self.getUserBrowser(self.url)
- cache = loads(browser.contents)
+ cache = json.loads(browser.contents.decode())
self.assertThat(
cache, KeysEqual("related_features", "context", "target_info")
)
diff --git a/lib/lp/services/webservice/stories/conditional-write.rst b/lib/lp/services/webservice/stories/conditional-write.rst
index 2ee3197..6e25c81 100644
--- a/lib/lp/services/webservice/stories/conditional-write.rst
+++ b/lib/lp/services/webservice/stories/conditional-write.rst
@@ -70,8 +70,8 @@ modify directly.
So long as the second part of the submitted ETag matches, a
conditional write will succeed.
- >>> import simplejson
- >>> data = simplejson.dumps({"title": "New title"})
+ >>> import json
+ >>> data = json.dumps({"title": "New title"})
>>> headers = {"If-Match": old_etag}
>>> print(
... webservice.patch(url, "application/json", data, headers=headers)
diff --git a/lib/lp/services/webservice/stories/xx-service.rst b/lib/lp/services/webservice/stories/xx-service.rst
index 11eef09..8e655d5 100644
--- a/lib/lp/services/webservice/stories/xx-service.rst
+++ b/lib/lp/services/webservice/stories/xx-service.rst
@@ -86,8 +86,8 @@ Anonymous requests can't access certain data.
Anonymous requests can't change the dataset.
- >>> import simplejson
- >>> data = simplejson.dumps({"display_name": "This won't work"})
+ >>> import json
+ >>> data = json.dumps({"display_name": "This won't work"})
>>> response = anon_webservice.patch(
... root + "/~salgado", "application/json", data
... )
diff --git a/lib/lp/soyuz/model/packagediffjob.py b/lib/lp/soyuz/model/packagediffjob.py
index b673c35..f4c20ac 100644
--- a/lib/lp/soyuz/model/packagediffjob.py
+++ b/lib/lp/soyuz/model/packagediffjob.py
@@ -5,7 +5,8 @@ __all__ = [
"PackageDiffJob",
]
-import simplejson
+import json
+
from lazr.delegates import delegate_to
from zope.component import getUtility
from zope.interface import implementer, provider
@@ -38,7 +39,7 @@ class PackageDiffJobDerived(BaseRunnableJob, metaclass=EnumeratedSubclass):
job = Job(
base_job_type=JobType.GENERATE_PACKAGE_DIFF,
requester=packagediff.requester,
- base_json_data=simplejson.dumps({"packagediff": packagediff.id}),
+ base_json_data=json.dumps({"packagediff": packagediff.id}),
)
derived = cls(job)
derived.celeryRunOnCommit()
@@ -75,7 +76,7 @@ class PackageDiffJob(PackageDiffJobDerived):
@property
def packagediff_id(self):
- return simplejson.loads(self.base_json_data)["packagediff"]
+ return json.loads(self.base_json_data)["packagediff"]
@property
def packagediff(self):
diff --git a/lib/lp/soyuz/stories/webservice/xx-archive.rst b/lib/lp/soyuz/stories/webservice/xx-archive.rst
index 0510710..9ea0d65 100644
--- a/lib/lp/soyuz/stories/webservice/xx-archive.rst
+++ b/lib/lp/soyuz/stories/webservice/xx-archive.rst
@@ -1391,14 +1391,11 @@ Non-virtualized archives
Modifying the require_virtualized flag through the API is not allowed except
for admins, commercial admins, and PPA admins.
- >>> import simplejson
+ >>> import json
>>> def modify_archive(service, archive):
... headers = {"Content-type": "application/json"}
... return service(
- ... archive["self_link"],
- ... "PUT",
- ... simplejson.dumps(archive),
- ... headers,
+ ... archive["self_link"], "PUT", json.dumps(archive), headers
... )
...
diff --git a/lib/lp/soyuz/stories/webservice/xx-archivedependency.rst b/lib/lp/soyuz/stories/webservice/xx-archivedependency.rst
index defcf2f..46b5c5e 100644
--- a/lib/lp/soyuz/stories/webservice/xx-archivedependency.rst
+++ b/lib/lp/soyuz/stories/webservice/xx-archivedependency.rst
@@ -12,7 +12,7 @@ We'll use Celso's PPA, and give it a custom dependency on the primary
archive, and then create a private PPA for Celso with a similar custom
dependency.
- >>> import simplejson
+ >>> import json
>>> from zope.component import getUtility
>>> from lp.registry.interfaces.person import IPersonSet
>>> from lp.registry.interfaces.pocket import PackagePublishingPocket
@@ -95,7 +95,7 @@ But even he can't write to a dependency.
... cprov_webservice.patch(
... "/~cprov/+archive/ubuntu/ppa/+dependency/1",
... "application/json",
- ... simplejson.dumps({"archive_link": mark_ppa["self_link"]}),
+ ... json.dumps({"archive_link": mark_ppa["self_link"]}),
... )
... )
HTTP/1.1 400 Bad Request
@@ -107,7 +107,7 @@ But even he can't write to a dependency.
... cprov_webservice.patch(
... "/~cprov/+archive/ubuntu/ppa/+dependency/1",
... "application/json",
- ... simplejson.dumps({"dependency_link": mark_ppa["self_link"]}),
+ ... json.dumps({"dependency_link": mark_ppa["self_link"]}),
... )
... )
HTTP/1.1 400 Bad Request
@@ -119,7 +119,7 @@ But even he can't write to a dependency.
... cprov_webservice.patch(
... "/~cprov/+archive/ubuntu/ppa/+dependency/1",
... "application/json",
- ... simplejson.dumps({"pocket": "Security"}),
+ ... json.dumps({"pocket": "Security"}),
... )
... )
HTTP/1.1 400 Bad Request
diff --git a/lib/lp/soyuz/stories/webservice/xx-packageset.rst b/lib/lp/soyuz/stories/webservice/xx-packageset.rst
index 4ea90ed..b9bb81a 100644
--- a/lib/lp/soyuz/stories/webservice/xx-packageset.rst
+++ b/lib/lp/soyuz/stories/webservice/xx-packageset.rst
@@ -113,7 +113,7 @@ Let's create another set.
We can modify it, and even give it away.
- >>> from simplejson import dumps
+ >>> import json
>>> name16 = webservice.get("/~name16").jsonBody()
>>> patch = {
... "name": "renamed",
@@ -123,7 +123,7 @@ We can modify it, and even give it away.
>>> response = webservice.patch(
... "/package-sets/ubuntu/hoary/shortlived",
... "application/json",
- ... dumps(patch),
+ ... json.dumps(patch),
... )
>>> print(response)
HTTP/1.1 301 Moved Permanently
diff --git a/lib/lp/soyuz/tests/test_binarypackagebuild.py b/lib/lp/soyuz/tests/test_binarypackagebuild.py
index 41791bd..ef513d3 100644
--- a/lib/lp/soyuz/tests/test_binarypackagebuild.py
+++ b/lib/lp/soyuz/tests/test_binarypackagebuild.py
@@ -3,11 +3,11 @@
"""Test Build features."""
+import json
from datetime import datetime, timedelta
import pytz
from pymacaroons import Macaroon
-from simplejson import dumps
from testtools.matchers import Equals, MatchesListwise, MatchesStructure
from zope.component import getUtility
from zope.publisher.xmlrpc import TestRequest
@@ -647,7 +647,7 @@ class TestBinaryPackageBuildWebservice(TestCaseWithFactory):
response = webservice.patch(
entry["self_link"],
"application/json",
- dumps({"external_dependencies": "random"}),
+ json.dumps({"external_dependencies": "random"}),
)
self.assertEqual(401, response.status)
@@ -660,7 +660,7 @@ class TestBinaryPackageBuildWebservice(TestCaseWithFactory):
response = self.webservice.patch(
entry["self_link"],
"application/json",
- dumps({"external_dependencies": "random"}),
+ json.dumps({"external_dependencies": "random"}),
)
self.assertEqual(401, response.status)
@@ -678,7 +678,7 @@ class TestBinaryPackageBuildWebservice(TestCaseWithFactory):
response = webservice.patch(
entry["self_link"],
"application/json",
- dumps({"external_dependencies": "random"}),
+ json.dumps({"external_dependencies": "random"}),
)
self.assertEqual(400, response.status)
self.assertIn(b"Invalid external dependencies", response.body)
@@ -698,7 +698,7 @@ class TestBinaryPackageBuildWebservice(TestCaseWithFactory):
response = webservice.patch(
entry["self_link"],
"application/json",
- dumps({"external_dependencies": dependencies}),
+ json.dumps({"external_dependencies": dependencies}),
)
self.assertEqual(209, response.status)
self.assertEqual(
@@ -958,7 +958,7 @@ class TestCalculateScore(TestCaseWithFactory):
response = webservice.patch(
entry["self_link"],
"application/json",
- dumps(dict(relative_build_score=100)),
+ json.dumps(dict(relative_build_score=100)),
)
self.assertEqual(401, response.status)
new_entry = webservice.get(obj_url, api_version="devel").jsonBody()
@@ -976,7 +976,7 @@ class TestCalculateScore(TestCaseWithFactory):
response = webservice.patch(
entry["self_link"],
"application/json",
- dumps(dict(relative_build_score=100)),
+ json.dumps(dict(relative_build_score=100)),
)
self.assertEqual(209, response.status)
self.assertEqual(100, response.jsonBody()["relative_build_score"])
diff --git a/lib/lp/testing/__init__.py b/lib/lp/testing/__init__.py
index 4133a2a..4b78f9a 100644
--- a/lib/lp/testing/__init__.py
+++ b/lib/lp/testing/__init__.py
@@ -52,6 +52,7 @@ __all__ = [
]
import io
+import json
import logging
import os
import re
@@ -72,7 +73,6 @@ import fixtures
import lp_sitecustomize
import oops_datedir_repo.serializer_rfc822
import pytz
-import simplejson
import six
import subunit
import testtools
@@ -1544,7 +1544,7 @@ def extract_lp_cache(text):
match = re.search(r"<script[^>]*>LP.cache = (\{.*\});</script>", text)
if match is None:
raise ValueError("No JSON cache found.")
- return simplejson.loads(match.group(1))
+ return json.loads(match.group(1))
def nonblocking_readline(instream, timeout):
diff --git a/lib/lp/testing/tests/test_yuixhr.py b/lib/lp/testing/tests/test_yuixhr.py
index eea4635..3e93964 100644
--- a/lib/lp/testing/tests/test_yuixhr.py
+++ b/lib/lp/testing/tests/test_yuixhr.py
@@ -3,6 +3,7 @@
"""Tests for the lp.testing.yuixhr."""
+import json
import os
import re
import sys
@@ -10,7 +11,6 @@ import tempfile
import types
from shutil import rmtree
-import simplejson
import transaction
from storm.exceptions import DisconnectionError
from testtools.testcase import ExpectedException
@@ -207,7 +207,7 @@ class TestYUITestFixtureController(TestCase):
method="POST",
)
content = view()
- self.assertEqual({"hello": "world"}, simplejson.loads(content))
+ self.assertEqual({"hello": "world"}, json.loads(content))
self.assertEqual(
"application/json", view.request.response.getHeader("Content-Type")
)
@@ -218,7 +218,7 @@ class TestYUITestFixtureController(TestCase):
form={"action": "setup", "fixtures": "make_product"},
method="POST",
)
- data = simplejson.loads(view())
+ data = json.loads(view())
# The licenses is just an example.
self.assertEqual(["GNU GPL v2"], data["product"]["licenses"])
@@ -228,7 +228,7 @@ class TestYUITestFixtureController(TestCase):
form={"action": "setup", "fixtures": "make_product"},
method="POST",
)
- data = simplejson.loads(view())
+ data = json.loads(view())
self.assertEqual(
"tag:launchpad.net:2008:redacted",
data["product"]["project_reviewed"],
@@ -240,7 +240,7 @@ class TestYUITestFixtureController(TestCase):
form={"action": "setup", "fixtures": "naughty_make_product"},
method="POST",
)
- data = simplejson.loads(view())
+ data = json.loads(view())
self.assertEqual(
"tag:launchpad.net:2008:redacted",
data["product"]["project_reviewed"],
@@ -252,7 +252,7 @@ class TestYUITestFixtureController(TestCase):
form={"action": "setup", "fixtures": "make_product_loggedin"},
method="POST",
)
- data = simplejson.loads(view())
+ data = json.loads(view())
self.assertEqual(False, data["product"]["project_reviewed"])
def test_add_cleanup_decorator(self):
@@ -288,7 +288,7 @@ class TestYUITestFixtureController(TestCase):
form={
"action": "teardown",
"fixtures": "baseline",
- "data": simplejson.dumps({"bonjour": "monde"}),
+ "data": json.dumps({"bonjour": "monde"}),
},
method="POST",
)
@@ -317,7 +317,7 @@ class TestYUITestFixtureController(TestCase):
# Committing the transaction makes sure that we are not just seeing
# the effect of an abort, below.
transaction.commit()
- name = simplejson.loads(data)["product"]["name"]
+ name = json.loads(data)["product"]["name"]
products = getUtility(IProductSet)
# The new product exists after the setup.
self.assertFalse(products.getByName(name) is None)
@@ -350,7 +350,7 @@ class TestYUITestFixtureController(TestCase):
form={
"action": "teardown",
"fixtures": "baseline,second",
- "data": simplejson.dumps({"bonjour": "monde"}),
+ "data": json.dumps({"bonjour": "monde"}),
},
method="POST",
)
diff --git a/lib/lp/translations/browser/hastranslationimports.py b/lib/lp/translations/browser/hastranslationimports.py
index c86d1c3..c1f7623 100644
--- a/lib/lp/translations/browser/hastranslationimports.py
+++ b/lib/lp/translations/browser/hastranslationimports.py
@@ -8,9 +8,9 @@ __all__ = [
]
import datetime
+import json
import pytz
-import simplejson
from zope.browserpage import ViewPageTemplateFile
from zope.component import getUtility
from zope.formlib import form
@@ -379,7 +379,7 @@ class HasTranslationImportsView(LaunchpadFormView):
for entry in self.batchnav.batch:
if check_permission("launchpad.Edit", entry):
confs.append(self.generateChoiceConfForEntry(entry))
- return "var choice_confs = %s;" % simplejson.dumps(confs)
+ return "var choice_confs = %s;" % json.dumps(confs)
def generateChoiceConfForEntry(self, entry):
disabled_items = [
diff --git a/lib/lp/translations/stories/webservice/xx-translationfocus.rst b/lib/lp/translations/stories/webservice/xx-translationfocus.rst
index fcd393a..110f6a1 100644
--- a/lib/lp/translations/stories/webservice/xx-translationfocus.rst
+++ b/lib/lp/translations/stories/webservice/xx-translationfocus.rst
@@ -15,12 +15,12 @@ outside the scope of this test.
It's possible to set the translation focus through the API
if you're an admin. The translation focus should be a project series.
- >>> from simplejson import dumps
+ >>> import json
>>> print(
... webservice.patch(
... evolution["self_link"],
... "application/json",
- ... dumps(
+ ... json.dumps(
... {
... "translation_focus_link": evolution[
... "development_focus_link"
@@ -43,7 +43,7 @@ Unprivileged users cannot set the translation focus.
... user_webservice.patch(
... evolution["self_link"],
... "application/json",
- ... dumps({"translation_focus_link": None}),
+ ... json.dumps({"translation_focus_link": None}),
... )
... )
HTTP... 401 Unauthorized
diff --git a/lib/lp/translations/stories/webservice/xx-translationimportqueue.rst b/lib/lp/translations/stories/webservice/xx-translationimportqueue.rst
index 63339d0..a17875a 100644
--- a/lib/lp/translations/stories/webservice/xx-translationimportqueue.rst
+++ b/lib/lp/translations/stories/webservice/xx-translationimportqueue.rst
@@ -85,7 +85,7 @@ Entry fields
Most of the fields in a translation import queue entry are immutable
from the web service's point of view.
- >>> from simplejson import dumps
+ >>> import json
Path
@@ -96,7 +96,9 @@ An entry's file path can be changed by the entry's owner or an admin.
>>> first_entry = queue["entries"][0]["self_link"]
>>> print(
... webservice.patch(
- ... first_entry, "application/json", dumps({"path": "foo.pot"})
+ ... first_entry,
+ ... "application/json",
+ ... json.dumps({"path": "foo.pot"}),
... )
... )
HTTP/1.1 209 Content Returned
@@ -110,7 +112,9 @@ A regular user is not allowed to make this change.
>>> first_entry = queue["entries"][0]["self_link"]
>>> print(
... user_webservice.patch(
- ... first_entry, "application/json", dumps({"path": "bar.pot"})
+ ... first_entry,
+ ... "application/json",
+ ... json.dumps({"path": "bar.pot"}),
... )
... )
HTTP... Unauthorized
@@ -125,7 +129,9 @@ For now, it is not possible to set an entry's status through the API.
>>> first_entry = queue["entries"][0]["self_link"]
>>> print(
... webservice.patch(
- ... first_entry, "application/json", dumps({"status": "Approved"})
+ ... first_entry,
+ ... "application/json",
+ ... json.dumps({"status": "Approved"}),
... )
... )
HTTP... Bad Request
diff --git a/requirements/launchpad.txt b/requirements/launchpad.txt
index f1efa07..30b4cfe 100644
--- a/requirements/launchpad.txt
+++ b/requirements/launchpad.txt
@@ -156,7 +156,6 @@ service-identity==18.1.0
setproctitle==1.1.7
setuptools-git==1.2
setuptools-scm==3.4.3
-simplejson==3.8.2
soupmatchers==0.4
soupsieve==1.9
statsd==3.3.0
diff --git a/requirements/types.txt b/requirements/types.txt
index 79b6d5e..752d982 100644
--- a/requirements/types.txt
+++ b/requirements/types.txt
@@ -4,5 +4,4 @@ types-beautifulsoup4==4.9.0
types-bleach==3.3.1
types-pytz==0.1.0
types-requests==0.1.13
-types-simplejson==0.1.0
types-six==0.1.9
diff --git a/setup.cfg b/setup.cfg
index e69cbc5..a13cb50 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -100,7 +100,6 @@ install_requires =
selenium
setproctitle
setuptools
- simplejson
six
soupmatchers
Sphinx