diff options
author | Andrej Shadura <andrewsh@debian.org> | 2022-07-06 11:08:53 +0200 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2022-07-06 11:08:53 +0200 |
commit | 535bb2f00b624c9779c6d044f6fe020b7ed6bda3 (patch) | |
tree | 4d120aa15c946509d3eb2fd1d4ebaadf327466df | |
parent | a8d63ca6985a221eb7f45581bff88b8d018809b0 (diff) |
New upstream version 1.6.2
-rw-r--r-- | .github/CODEOWNERS | 2 | ||||
-rw-r--r-- | .github/workflows/tests.yaml | 65 | ||||
-rw-r--r-- | .travis.yml | 40 | ||||
-rwxr-xr-x | .travis/install.sh | 21 | ||||
-rw-r--r-- | CHANGES.md | 11 | ||||
-rw-r--r-- | MANIFEST.in | 1 | ||||
-rw-r--r-- | README.rst | 5 | ||||
-rw-r--r-- | canonicaljson.py | 113 | ||||
-rw-r--r-- | debian/changelog | 42 | ||||
-rw-r--r-- | debian/clean | 1 | ||||
-rw-r--r-- | debian/compat | 1 | ||||
-rw-r--r-- | debian/control | 56 | ||||
-rw-r--r-- | debian/copyright | 29 | ||||
-rw-r--r-- | debian/python-canonicaljson.docs | 1 | ||||
-rw-r--r-- | debian/python3-canonicaljson.docs | 1 | ||||
-rwxr-xr-x | debian/rules | 6 | ||||
-rw-r--r-- | debian/source/format | 1 | ||||
-rw-r--r-- | debian/source/options | 1 | ||||
-rw-r--r-- | pyproject.toml | 6 | ||||
-rw-r--r-- | releasing.md | 34 | ||||
-rwxr-xr-x | setup.py | 9 | ||||
-rw-r--r-- | test_canonicaljson.py | 48 | ||||
-rw-r--r-- | tox.ini | 22 |
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 @@ -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 @@ -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 @@ -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) @@ -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 |