summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2022-07-06 11:08:53 +0200
committerAndrej Shadura <andrewsh@debian.org>2022-07-06 11:08:53 +0200
commit535bb2f00b624c9779c6d044f6fe020b7ed6bda3 (patch)
tree4d120aa15c946509d3eb2fd1d4ebaadf327466df
parenta8d63ca6985a221eb7f45581bff88b8d018809b0 (diff)
New upstream version 1.6.2
-rw-r--r--.github/CODEOWNERS2
-rw-r--r--.github/workflows/tests.yaml65
-rw-r--r--.travis.yml40
-rwxr-xr-x.travis/install.sh21
-rw-r--r--CHANGES.md11
-rw-r--r--MANIFEST.in1
-rw-r--r--README.rst5
-rw-r--r--canonicaljson.py113
-rw-r--r--debian/changelog42
-rw-r--r--debian/clean1
-rw-r--r--debian/compat1
-rw-r--r--debian/control56
-rw-r--r--debian/copyright29
-rw-r--r--debian/python-canonicaljson.docs1
-rw-r--r--debian/python3-canonicaljson.docs1
-rwxr-xr-xdebian/rules6
-rw-r--r--debian/source/format1
-rw-r--r--debian/source/options1
-rw-r--r--pyproject.toml6
-rw-r--r--releasing.md34
-rwxr-xr-xsetup.py9
-rw-r--r--test_canonicaljson.py48
-rw-r--r--tox.ini22
23 files changed, 204 insertions, 312 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..553ceec
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,2 @@
+# Automatically request reviews from the synapse-core team when a pull request comes in.
+* @matrix-org/synapse-core
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
new file mode 100644
index 0000000..c4bfa98
--- /dev/null
+++ b/.github/workflows/tests.yaml
@@ -0,0 +1,65 @@
+name: Tests
+on: [push, pull_request]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ toxenv:
+ - "pep8"
+ - "black"
+ - "mypy"
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: '3.7'
+ - run: pip install tox
+ - run: tox -e ${{ matrix.toxenv }}
+
+ unittest:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version: ['3.7', '3.8', '3.9', '3.10', 'pypy-3.7']
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+ - run: pip install tox
+ - run: tox -e py
+
+ packaging:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest]
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ - run: python -m pip install tox
+ - run: tox -e packaging
+
+ macos-tests:
+ runs-on: macos-latest
+ strategy:
+ matrix:
+ python-version: ["3.8", "3.9", "3.10"]
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+ - run: pip install tox
+ - run: tox -e py
+
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index a110082..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-language: python
-
-# tell travis to cache ~/.cache/pip
-cache: pip
-
-matrix:
- include:
- - python: 3.6
- env: TOXENV=packaging
-
- - python: 3.6
- env: TOXENV=pep8
-
- - python: 3.6
- env: TOXENV=black
-
- - python: 3.5
- env: TOXENV=py35
-
- - python: 3.6
- env: TOXENV=py36
-
- - python: 3.7
- env: TOXENV=py37
-
- - python: 3.8
- env: TOXENV=py38
-
- - os: osx
- language: generic
- env: TOXENV=py38
-
- - python: pypy3
- env: TOXENV=pypy3
-
-install:
-- ./.travis/install.sh
-
-script:
-- tox
diff --git a/.travis/install.sh b/.travis/install.sh
deleted file mode 100755
index 6d55809..0000000
--- a/.travis/install.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-set -xe
-
-if [[ $TRAVIS_OS_NAME == 'osx' ]]; then
- # osx build uses a 'generic' language which doesn't come with pip
- case "${TOXENV}" in
- py38)
- # for py38, use homebrew python, which comes with pip.
- # see also https://docs.brew.sh/Homebrew-and-Python
- brew upgrade python
- pip3 install tox
- ;;
- *)
- echo "TOXENV ${TOXENV} not supported on osx" >&2
- exit 1
- ;;
- esac
-else
- pip install tox
-fi
diff --git a/CHANGES.md b/CHANGES.md
index aaa9eb8..e652bb9 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,14 @@
+Version 1.6.0 released 2022-03-04
+
+* `frozendict` is now an optional dependency; it is no longer required.
+
+Version 1.5.0 released 2021-10-20
+
+* Switch CI from Travis to Github Actions
+* Add code to handle frozendict implementations using c-extension
+* Add tests for Python 3.10
+* Remove outdated Debian packaging code
+
Version 1.4.0 released 2020-09-03
* Fix producing non-standard JSON for Infinity, -Infinity, and NaN. This could
diff --git a/MANIFEST.in b/MANIFEST.in
index 0ac1524..63f6c5b 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -3,5 +3,6 @@ include *.py
include *.md
include LICENSE
include tox.ini
+include pyproject.toml
prune .travis
prune debian
diff --git a/README.rst b/README.rst
index a6887d6..af0c212 100644
--- a/README.rst
+++ b/README.rst
@@ -5,9 +5,6 @@ Canonical JSON
:target: https://pypi.python.org/pypi/canonicaljson/
:alt: Latest Version
-.. image:: https://img.shields.io/travis/matrix-org/python-canonicaljson.svg
- :target: https://travis-ci.org/matrix-org/python-canonicaljson
-
Features
--------
@@ -20,7 +17,7 @@ Features
* Encodes the JSON as UTF-8.
* Can encode ``frozendict`` immutable dictionaries.
-Supports Python versions 3.5 and newer.
+Supports Python versions 3.7 and newer.
.. _`RFC 7159`: https://tools.ietf.org/html/rfc7159
diff --git a/canonicaljson.py b/canonicaljson.py
index 8dee682..a2d8148 100644
--- a/canonicaljson.py
+++ b/canonicaljson.py
@@ -16,29 +16,53 @@
# limitations under the License.
import platform
+from typing import Any, Generator, Optional, Type
-from frozendict import frozendict
+try:
+ from typing import Protocol
+except ImportError: # pragma: no cover
+ from typing_extensions import Protocol # type: ignore[misc]
-__version__ = "1.4.0"
+frozendict_type: Optional[Type[Any]]
+try:
+ from frozendict import frozendict as frozendict_type
+except ImportError:
+ frozendict_type = None # pragma: no cover
+__version__ = "1.6.2"
-def _default(obj):
- if type(obj) is frozendict:
- # fishing the protected dict out of the object is a bit nasty,
- # but we don't really want the overhead of copying the dict.
- return obj._dict
+
+def _default(obj: object) -> object: # pragma: no cover
+ if type(obj) is frozendict_type:
+ # If frozendict is available and used, cast `obj` into a dict
+ return dict(obj) # type: ignore[call-overload]
raise TypeError(
"Object of type %s is not JSON serializable" % obj.__class__.__name__
)
+class Encoder(Protocol): # pragma: no cover
+ def encode(self, data: object) -> str:
+ pass
+
+ def iterencode(self, data: object) -> Generator[str, None, None]:
+ pass
+
+ def __call__(self, *args: Any, **kwargs: Any) -> "Encoder":
+ pass
+
+
+class JsonLibrary(Protocol):
+ JSONEncoder: Encoder
+
+
# Declare these in the module scope, but they get configured in
# set_json_library.
-_canonical_encoder = None
-_pretty_encoder = None
+_canonical_encoder: Encoder = None # type: ignore[assignment]
+_pretty_encoder: Encoder = None # type: ignore[assignment]
-def set_json_library(json_lib):
+def set_json_library(json_lib: JsonLibrary) -> None:
"""
Set the underlying JSON library that canonicaljson uses to json_lib.
@@ -57,59 +81,52 @@ def set_json_library(json_lib):
global _pretty_encoder
_pretty_encoder = json_lib.JSONEncoder(
- ensure_ascii=False, allow_nan=False, indent=4, sort_keys=True, default=_default,
+ ensure_ascii=False,
+ allow_nan=False,
+ indent=4,
+ sort_keys=True,
+ default=_default,
)
-def encode_canonical_json(json_object):
- """Encodes the shortest UTF-8 JSON encoding with dictionary keys
- lexicographically sorted by unicode code point.
-
- Args:
- json_object (dict): The JSON object to encode.
-
- Returns:
- bytes encoding the JSON object"""
- s = _canonical_encoder.encode(json_object)
- return s.encode("utf-8")
-
+def encode_canonical_json(data: object) -> bytes:
+ """Encodes the given `data` as a UTF-8 canonical JSON bytestring.
-def iterencode_canonical_json(json_object):
- """Encodes the shortest UTF-8 JSON encoding with dictionary keys
+ This encoding is the shortest possible. Dictionary keys are
lexicographically sorted by unicode code point.
+ """
+ s = _canonical_encoder.encode(data)
+ return s.encode("utf-8")
- Args:
- json_object (dict): The JSON object to encode.
- Returns:
- generator which yields bytes encoding the JSON object"""
- for chunk in _canonical_encoder.iterencode(json_object):
- yield chunk.encode("utf-8")
+def iterencode_canonical_json(data: object) -> Generator[bytes, None, None]:
+ """Iteratively encodes the given `data` as a UTF-8 canonical JSON bytestring.
+ This yields one or more bytestrings; concatenating them all together yields the
+ full encoding of `data`. Building up the encoding gradually in this way allows us to
+ encode large pieces of `data` without blocking other tasks.
-def encode_pretty_printed_json(json_object):
+ This encoding is the shortest possible. Dictionary keys are
+ lexicographically sorted by unicode code point.
"""
- Encodes the JSON object dict as human readable UTF-8 bytes.
-
- Args:
- json_object (dict): The JSON object to encode.
-
- Returns:
- bytes encoding the JSON object"""
+ for chunk in _canonical_encoder.iterencode(data):
+ yield chunk.encode("utf-8")
- return _pretty_encoder.encode(json_object).encode("utf-8")
+def encode_pretty_printed_json(data: object) -> bytes:
+ """Encodes the given `data` as a UTF-8 human-readable JSON bytestring."""
-def iterencode_pretty_printed_json(json_object):
- """Encodes the JSON object dict as human readable UTF-8 bytes.
+ return _pretty_encoder.encode(data).encode("utf-8")
- Args:
- json_object (dict): The JSON object to encode.
- Returns:
- generator which yields bytes encoding the JSON object"""
+def iterencode_pretty_printed_json(data: object) -> Generator[bytes, None, None]:
+ """Iteratively encodes the given `data` as a UTF-8 human-readable JSON bytestring.
- for chunk in _pretty_encoder.iterencode(json_object):
+ This yields one or more bytestrings; concatenating them all together yields the
+ full encoding of `data`. Building up the encoding gradually in this way allows us to
+ encode large pieces of `data` without blocking other tasks.
+ """
+ for chunk in _pretty_encoder.iterencode(data):
yield chunk.encode("utf-8")
@@ -124,7 +141,7 @@ else: # pragma: no cover
#
# Note that it seems performance is on par or better using json from the
# standard library as of Python 3.7.
- import simplejson as json
+ import simplejson as json # type: ignore[no-redef]
# Set the JSON library to the backwards compatible version.
set_json_library(json)
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 5178787..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,42 +0,0 @@
-python-canonicaljson (1.1.4) stable; urgency=medium
-
- * Fix error when encoding non-BMP characters on UCS-2 python builds
- (fixes issue #12).
-
- -- Richard van der Hoff <richard@matrix.org> Wed, 23 May 2018 09:07:26 +0100
-
-python-canonicaljson (1.1.3) stable; urgency=medium
-
- * Bump depencency on frozendict to >=1.0, to fix conflicts with older
- versions.
-
- -- Richard van der Hoff <richard@matrix.org> Fri, 13 Apr 2018 09:51:24 +0100
-
-python-canonicaljson (1.1.2) stable; urgency=medium
-
- * Fix escaping of control characters U+0000 to U+001F AGAIN, which was STILL
- broken in the previous release
-
- -- Richard van der Hoff <richard@matrix.org> Thu, 12 Apr 2018 15:53:56 +0100
-
-python-canonicaljson (1.1.1) stable; urgency=medium
-
- * Fix escaping of control characters U+0000 to U+001F, which was broken in
- the previous release
-
- -- Richard van der Hoff <richard@matrix.org> Wed, 11 Apr 2018 18:01:50 +0100
-
-python-canonicaljson (1.1.0) stable; urgency=medium
-
- * Significant performance improvements
- (https://github.com/matrix-org/python-canonicaljson/pull/7,
- https://github.com/matrix-org/python-canonicaljson/pull/8,
- https://github.com/matrix-org/python-canonicaljson/pull/9)
-
- -- Richard van der Hoff <richard@matrix.org> Tue, 10 Apr 2018 16:42:19 +0100
-
-canonicaljson (1.0.0-1) wheezy; urgency=low
-
- * source package automatically created by stdeb 0.6.0+git
-
- -- Erik Johnston <erikj@matrix.org> Fri, 13 Nov 2015 14:47:18 +0000
diff --git a/debian/clean b/debian/clean
deleted file mode 100644
index 45149aa..0000000
--- a/debian/clean
+++ /dev/null
@@ -1 +0,0 @@
-*.egg-info/*
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index e45aec8..0000000
--- a/debian/control
+++ /dev/null
@@ -1,56 +0,0 @@
-Source: python-canonicaljson
-Maintainer: Richard van der Hoff <richard@matrix.org>
-Section: python
-Priority: optional
-Build-Depends:
- debhelper (>= 9),
- dh-python,
- python-all (>= 2.6.6-3),
- python-setuptools (>= 0.6.24),
- python3-all,
- python3-setuptools (>= 0.6.24),
- python-frozendict (>= 0.4),
- python-simplejson (>= 3.6.5),
- python3-frozendict (>= 0.4),
- python3-simplejson (>= 3.6.5)
-Standards-Version: 3.9.7
-X-Python-Version: >= 2.7
-
-Package: python-canonicaljson
-Architecture: all
-Depends:
- python-frozendict (>= 0.4),
- python-simplejson (>= 3.6.5),
- ${misc:Depends},
- ${python:Depends}
-Provides: ${python:Provides}
-Description: canonical JSON implementation for Python 2
- Canonical JSON implementation for Python 2.
- .
- * Encodes objects and arrays as RFC 7159 JSON.
- * Sorts object keys so that you get the same result each time.
- * Has no inignificant whitespace to make the output as small as possible.
- * Escapes only the characters that must be escaped, U+0000 to U+0019 / U+0022 /
- U+0056, to keep the output as small as possible.
- * Uses the shortest escape sequence for each escaped character.
- * Encodes the JSON as UTF-8.
- * Can encode frozendict immutable dictionaries.
-
-Package: python3-canonicaljson
-Architecture: all
-Depends:
- python3-frozendict (>= 0.4),
- python3-simplejson (>= 3.6.5),
- ${misc:Depends},
- ${python3:Depends}
-Description: canonical JSON implementation for Python 3
- Canonical JSON implementation for Python 3.
- .
- * Encodes objects and arrays as RFC 7159 JSON.
- * Sorts object keys so that you get the same result each time.
- * Has no inignificant whitespace to make the output as small as possible.
- * Escapes only the characters that must be escaped, U+0000 to U+0019 / U+0022 /
- U+0056, to keep the output as small as possible.
- * Uses the shortest escape sequence for each escaped character.
- * Encodes the JSON as UTF-8.
- * Can encode frozendict immutable dictionaries.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index a6ccf35..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,29 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Contact: Richard van der Hoff <richard@matrix.org>
-
-Files: *
-Copyright: 2014-2015 OpenMarket Ltd
- 2018 New Vector Ltd
-License: Apache-2.0
-
-Files: debian/*
-Copyright: 2014-2015 OpenMarket Ltd
- 2017 Andrew Shadura <andrewsh@debian.org>
- 2018 New Vector Ltd
-License: Apache-2.0
-
-License: Apache-2.0
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- .
- http://www.apache.org/licenses/LICENSE-2.0
- .
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- .
- On Debian systems, the complete text of the Apache License,
- version 2.0 can be found in ‘/usr/share/common-licenses/Apache-2.0’.
diff --git a/debian/python-canonicaljson.docs b/debian/python-canonicaljson.docs
deleted file mode 100644
index a1320b1..0000000
--- a/debian/python-canonicaljson.docs
+++ /dev/null
@@ -1 +0,0 @@
-README.rst
diff --git a/debian/python3-canonicaljson.docs b/debian/python3-canonicaljson.docs
deleted file mode 100644
index a1320b1..0000000
--- a/debian/python3-canonicaljson.docs
+++ /dev/null
@@ -1 +0,0 @@
-README.rst
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index f9fe4f0..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/make -f
-
-export PYBUILD_NAME=canonicaljson
-
-%:
- dh $@ --with python2,python3 --buildsystem=pybuild
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 89ae9db..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (native)
diff --git a/debian/source/options b/debian/source/options
deleted file mode 100644
index 4d82e22..0000000
--- a/debian/source/options
+++ /dev/null
@@ -1 +0,0 @@
-extend-diff-ignore="\.egg-info" \ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..bd1d867
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,6 @@
+[tool.mypy]
+show_error_codes = true
+strict = true
+
+files = ["."]
+exclude = "setup.py"
diff --git a/releasing.md b/releasing.md
index a127f1b..73cb3ed 100644
--- a/releasing.md
+++ b/releasing.md
@@ -3,42 +3,10 @@ Releasing python-canonicaljson
* bump version in `canonicaljson.py`
* update changelog
-* update debian changelog:
- * Add new entry: `dch -v <ver>`
- * Mark as released: `dch --distribution stable -r`
* Build and upload to pypi:
* `rm -r dist`
* `python setup.py sdist bdist_wheel`
* `twine upload -s dist/*`
* `git tag -s v<ver>`
* `git push`
-* `git push --tags`
-* Follow instructions below to release debian packaging.
-
-Prerequisites for debian packaging
-----------------------------------
-
-```
-sudo apt-get install sbuild
-sudo apt-get install ubuntu-dev-tools # for mk-sbuild
-sudo sbuild-adduser $LOGNAME
-
-newgrp sbuild
-mk-sbuild stretch
-```
-
-If your kernel doesn't support `aufs`, you'll need to set `union-type=overlay`
-in `/etc/schroot/chroot.d/sbuild-stretch-amd64`.
-
-Debian release
---------------
-
-```
-# We need to build from a pristine copy of the repo (otherwise you end up with
-# your whole working copy in the source tarball), so:
-git clone git@github.com:matrix-org/python-canonicaljson.git -b v<ver> python-canonicaljson-clean
-
-cd python-canonicaljson-clean
-sbuild -s --arch-all -d stretch
-debsign
-```
+* `git push --tags` \ No newline at end of file
diff --git a/setup.py b/setup.py
index 1c2cc94..fec43db 100755
--- a/setup.py
+++ b/setup.py
@@ -49,8 +49,13 @@ setup(
# simplerjson versions before 3.14.0 had a bug with some characters
# (e.g. \u2028) if ensure_ascii was set to false.
"simplejson>=3.14.0",
- "frozendict>=1.0",
+ # typing.Protocol was only added to the stdlib in Python 3.8
+ "typing_extensions>=4.0.0; python_version < '3.8'",
],
+ extras_require={
+ # frozendict support can be enabled using the `canonicaljson[frozendict]` syntax
+ "frozendict": ["frozendict>=1.0"],
+ },
zip_safe=True,
long_description=read_file(("README.rst",)),
keywords="json",
@@ -58,7 +63,7 @@ setup(
author_email="team@matrix.org",
url="https://github.com/matrix-org/python-canonicaljson",
license="Apache License, Version 2.0",
- python_requires="~=3.5",
+ python_requires="~=3.7",
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
diff --git a/test_canonicaljson.py b/test_canonicaljson.py
index 003d108..fc19922 100644
--- a/test_canonicaljson.py
+++ b/test_canonicaljson.py
@@ -14,34 +14,36 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
from math import inf, nan
from canonicaljson import (
encode_canonical_json,
encode_pretty_printed_json,
+ frozendict_type,
iterencode_canonical_json,
iterencode_pretty_printed_json,
set_json_library,
)
-from frozendict import frozendict
-
import unittest
from unittest import mock
class TestCanonicalJson(unittest.TestCase):
- def test_encode_canonical(self):
+ def test_encode_canonical(self) -> None:
self.assertEqual(encode_canonical_json({}), b"{}")
# ctrl-chars should be encoded.
self.assertEqual(
- encode_canonical_json(u"text\u0003\r\n"), b'"text\\u0003\\r\\n"',
+ encode_canonical_json(u"text\u0003\r\n"),
+ b'"text\\u0003\\r\\n"',
)
# quotes and backslashes should be escaped.
self.assertEqual(
- encode_canonical_json(r'"\ test'), b'"\\"\\\\ test"',
+ encode_canonical_json(r'"\ test'),
+ b'"\\"\\\\ test"',
)
# non-ascii should come out utf8-encoded.
@@ -59,13 +61,14 @@ class TestCanonicalJson(unittest.TestCase):
# but we need to watch out for 'u1234' after backslash, which should
# get encoded to an escaped backslash, followed by u1234
self.assertEqual(
- encode_canonical_json(u"\\u1234"), b'"\\\\u1234"',
+ encode_canonical_json(u"\\u1234"),
+ b'"\\\\u1234"',
)
# Iteratively encoding should work.
self.assertEqual(list(iterencode_canonical_json({})), [b"{}"])
- def test_ascii(self):
+ def test_ascii(self) -> None:
"""
Ensure the proper ASCII characters are escaped.
@@ -92,10 +95,10 @@ class TestCanonicalJson(unittest.TestCase):
# And other characters are passed unescaped.
unescaped = [0x20, 0x21] + list(range(0x23, 0x5C)) + list(range(0x5D, 0x7E))
for c in unescaped:
- c = chr(c)
- self.assertEqual(encode_canonical_json(c), b'"' + c.encode("ascii") + b'"')
+ s = chr(c)
+ self.assertEqual(encode_canonical_json(s), b'"' + s.encode("ascii") + b'"')
- def test_encode_pretty_printed(self):
+ def test_encode_pretty_printed(self) -> None:
self.assertEqual(encode_pretty_printed_json({}), b"{}")
self.assertEqual(list(iterencode_pretty_printed_json({})), [b"{}"])
@@ -105,15 +108,23 @@ class TestCanonicalJson(unittest.TestCase):
b'{\n "la merde amus\xc3\xa9e": "\xF0\x9F\x92\xA9"\n}',
)
- def test_frozen_dict(self):
+ @unittest.skipIf(
+ frozendict_type is None,
+ "If `frozendict` is not available, skip test",
+ )
+ def test_frozen_dict(self) -> None:
+ # For mypy's benefit:
+ assert frozendict_type is not None
self.assertEqual(
- encode_canonical_json(frozendict({"a": 1})), b'{"a":1}',
+ encode_canonical_json(frozendict_type({"a": 1})),
+ b'{"a":1}',
)
self.assertEqual(
- encode_pretty_printed_json(frozendict({"a": 1})), b'{\n "a": 1\n}'
+ encode_pretty_printed_json(frozendict_type({"a": 1})),
+ b'{\n "a": 1\n}',
)
- def test_unknown_type(self):
+ def test_unknown_type(self) -> None:
class Unknown(object):
pass
@@ -124,9 +135,8 @@ class TestCanonicalJson(unittest.TestCase):
with self.assertRaises(Exception):
encode_pretty_printed_json(unknown_object)
- def test_invalid_float_values(self):
- """Infinity/-Infinity/NaN are not allowed in canonicaljson.
- """
+ def test_invalid_float_values(self) -> None:
+ """Infinity/-Infinity/NaN are not allowed in canonicaljson."""
with self.assertRaises(ValueError):
encode_canonical_json(inf)
@@ -146,7 +156,7 @@ class TestCanonicalJson(unittest.TestCase):
with self.assertRaises(ValueError):
encode_pretty_printed_json(nan)
- def test_set_json(self):
+ def test_set_json(self) -> None:
"""Ensure that changing the underlying JSON implementation works."""
mock_json = mock.Mock(spec=["JSONEncoder"])
mock_json.JSONEncoder.return_value.encode.return_value = "sentinel"
@@ -155,6 +165,6 @@ class TestCanonicalJson(unittest.TestCase):
self.assertEqual(encode_canonical_json({}), b"sentinel")
finally:
# Reset the JSON library to whatever was originally set.
- from canonicaljson import json
+ from canonicaljson import json # type: ignore[attr-defined]
set_json_library(json)
diff --git a/tox.ini b/tox.ini
index 74d6a79..00ae34c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,13 +1,13 @@
[tox]
-envlist = packaging, pep8, py35, py36, py37, py38, pypy3
+envlist = packaging, pep8, black, py37, py38, py39, py310, pypy3
[testenv]
deps =
coverage
- nose
+ nose2
commands =
- coverage run --source canonicaljson -m nose
+ coverage run --source canonicaljson -m nose2
coverage report -m --fail-under 100
[testenv:packaging]
@@ -16,13 +16,23 @@ deps =
commands = check-manifest
[testenv:pep8]
-basepython = python3.6
+basepython = python3.7
deps =
flake8
commands = flake8 .
[testenv:black]
-basepython = python3.6
+basepython = python3.7
deps =
- black
+ black==21.9b0
+ # Workaround black+click incompatability, see https://github.com/psf/black/issues/2964
+ click==8.0.4
commands = python -m black --check --diff .
+
+[testenv:mypy]
+deps =
+ mypy==0.942
+ types-frozendict==2.0.8
+ types-simplejson==3.17.5
+ types-setuptools==57.4.14
+commands = mypy