Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-canonicaljson for openSUSE:Factory checked in at 2022-11-23 09:48:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-canonicaljson (Old) and /work/SRC/openSUSE:Factory/.python-canonicaljson.new.1597 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-canonicaljson" Wed Nov 23 09:48:14 2022 rev:13 rq:1037402 version:1.6.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-canonicaljson/python-canonicaljson.changes 2022-06-09 14:10:28.652422239 +0200 +++ /work/SRC/openSUSE:Factory/.python-canonicaljson.new.1597/python-canonicaljson.changes 2022-11-23 09:48:35.235191982 +0100 @@ -1,0 +2,8 @@ +Tue Nov 22 13:31:34 UTC 2022 - Marcus Rueckert <mrueck...@suse.de> + +- Update to 1.6.4 + - Remove unused setuptools_scm build requirement. + - Properly package the canonicaljson module (#52) +- switch to pyproject build + +------------------------------------------------------------------- Old: ---- v1.6.2.tar.gz New: ---- v1.6.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-canonicaljson.spec ++++++ --- /var/tmp/diff_new_pack.NXFbgl/_old 2022-11-23 09:48:35.655194173 +0100 +++ /var/tmp/diff_new_pack.NXFbgl/_new 2022-11-23 09:48:35.659194194 +0100 @@ -25,26 +25,23 @@ %bcond_with test %endif %{?!python_module:%define python_module() python-%{**} python3-%{**}} -%bcond_with pyproject %define github_user matrix-org %define short_name canonicaljson Name: python-%{short_name}%{psuffix} -Version: 1.6.2 +Version: 1.6.4 Release: 0 Summary: Canonical JSON for Python License: Apache-2.0 Group: Development/Languages/Python URL: https://github.com/matrix-org/python-canonicaljson Source: https://github.com/matrix-org/python-canonicaljson/archive/v%{version}.tar.gz -%if %{with pyproject} BuildRequires: %{python_module flit-core} -BuildRequires: %{python_module pip} -BuildRequires: %{python_module wheel} -%endif BuildRequires: %{python_module frozendict >= 2.1.3} +BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} BuildRequires: %{python_module simplejson >= 3.14.0} BuildRequires: %{python_module typing_extensions} +BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-frozendict >= 1.0 @@ -73,19 +70,11 @@ %setup -q -n python-canonicaljson-%{version} %build -%if %{with pyproject} %pyproject_wheel -%else -%python_build -%endif %install %if !%{with test} -%if %{with pyproject} %pyproject_install -%else -%python_install -%endif %python_expand %fdupes %{buildroot}%{$python_sitelib} %endif @@ -102,8 +91,7 @@ %files %{python_files} %license LICENSE %doc README.rst -%pycache_only %{python_sitelib}/__pycache__/%{short_name}*.pyc -%{python_sitelib}/%{short_name}.py +%{python_sitelib}/%{short_name}/ %{python_sitelib}/%{short_name}-%{version}*-info %endif ++++++ v1.6.2.tar.gz -> v1.6.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/.github/workflows/tests.yaml new/python-canonicaljson-1.6.4/.github/workflows/tests.yaml --- old/python-canonicaljson-1.6.2/.github/workflows/tests.yaml 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/.github/workflows/tests.yaml 2022-11-04 19:24:39.000000000 +0100 @@ -1,5 +1,8 @@ name: Tests -on: [push, pull_request] +on: + push: + branches: ["main"] + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/CHANGES.md new/python-canonicaljson-1.6.4/CHANGES.md --- old/python-canonicaljson-1.6.2/CHANGES.md 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/CHANGES.md 2022-11-04 19:24:39.000000000 +0100 @@ -1,3 +1,25 @@ +Version 1.6.4 released 2022-11-04 + +* Remove unused `setuptools_scm` build requirement. + +Version 1.6.3 released 2022-09-23 + +* Properly package the `canonicaljson` module. + +Version 1.6.2 released 2022-06-08 + +* Bump version to 1.6.2 + +The v1.6.1 tag was created without having bumped the version in +`canonicaljson.py`. This means that installing from source at the `v1.6.1` tag will +install the package with the wrong version in its metadata. The 1.6.1 artefacts +uploaded to PyPI did have the correct version; `pip install`ing +directly from the archive resulted in a consistent version number. + +Version 1.6.1 released 2022-05-02 + +* Add type annotations. + Version 1.6.0 released 2022-03-04 * `frozendict` is now an optional dependency; it is no longer required. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/MANIFEST.in new/python-canonicaljson-1.6.4/MANIFEST.in --- old/python-canonicaljson-1.6.2/MANIFEST.in 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/MANIFEST.in 2022-11-04 19:24:39.000000000 +0100 @@ -1,8 +1,4 @@ -include *.in -include *.py +prune .github include *.md -include LICENSE include tox.ini -include pyproject.toml -prune .travis -prune debian +recursive-include tests *.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/canonicaljson.py new/python-canonicaljson-1.6.4/canonicaljson.py --- old/python-canonicaljson-1.6.2/canonicaljson.py 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/canonicaljson.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,147 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 OpenMarket Ltd -# Copyright 2018 New Vector Ltd -# -# 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. - -import platform -from typing import Any, Generator, Optional, Type - -try: - from typing import Protocol -except ImportError: # pragma: no cover - from typing_extensions import Protocol # type: ignore[misc] - -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: 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: Encoder = None # type: ignore[assignment] -_pretty_encoder: Encoder = None # type: ignore[assignment] - - -def set_json_library(json_lib: JsonLibrary) -> None: - """ - Set the underlying JSON library that canonicaljson uses to json_lib. - - Params: - json_lib: The module to use for JSON encoding. Must have a - `JSONEncoder` property. - """ - global _canonical_encoder - _canonical_encoder = json_lib.JSONEncoder( - ensure_ascii=False, - allow_nan=False, - separators=(",", ":"), - sort_keys=True, - default=_default, - ) - - global _pretty_encoder - _pretty_encoder = json_lib.JSONEncoder( - ensure_ascii=False, - allow_nan=False, - indent=4, - sort_keys=True, - default=_default, - ) - - -def encode_canonical_json(data: object) -> bytes: - """Encodes the given `data` as a UTF-8 canonical JSON bytestring. - - 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") - - -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. - - This encoding is the shortest possible. Dictionary keys are - lexicographically sorted by unicode code point. - """ - for chunk in _canonical_encoder.iterencode(data): - yield chunk.encode("utf-8") - - -def encode_pretty_printed_json(data: object) -> bytes: - """Encodes the given `data` as a UTF-8 human-readable JSON bytestring.""" - - return _pretty_encoder.encode(data).encode("utf-8") - - -def iterencode_pretty_printed_json(data: object) -> Generator[bytes, None, None]: - """Iteratively encodes the given `data` as a UTF-8 human-readable 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. - """ - for chunk in _pretty_encoder.iterencode(data): - yield chunk.encode("utf-8") - - -if platform.python_implementation() == "PyPy": # pragma: no cover - # pypy ships with an optimised JSON encoder/decoder that is faster than - # simplejson's C extension. - import json -else: # pragma: no cover - # using simplejson rather than regular json on CPython for backwards - # compatibility (simplejson on Python 3.5 handles parsing of bytes while - # the standard library json does not). - # - # 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 # type: ignore[no-redef] - -# Set the JSON library to the backwards compatible version. -set_json_library(json) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/pyproject.toml new/python-canonicaljson-1.6.4/pyproject.toml --- old/python-canonicaljson-1.6.2/pyproject.toml 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/pyproject.toml 2022-11-04 19:24:39.000000000 +0100 @@ -3,4 +3,9 @@ strict = true files = ["."] -exclude = "setup.py" + +[build-system] +requires = [ + "setuptools >= 35.0.2", +] +build-backend = "setuptools.build_meta" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/releasing.md new/python-canonicaljson-1.6.4/releasing.md --- old/python-canonicaljson-1.6.2/releasing.md 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/releasing.md 2022-11-04 19:24:39.000000000 +0100 @@ -1,11 +1,12 @@ Releasing python-canonicaljson ============================== -* bump version in `canonicaljson.py` +* bump version in `src/canonicaljson/__init__.py` * update changelog * Build and upload to pypi: + * `rm -r ./**/*.egg-info` * `rm -r dist` - * `python setup.py sdist bdist_wheel` + * `python -m build` * `twine upload -s dist/*` * `git tag -s v<ver>` * `git push` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/setup.cfg new/python-canonicaljson-1.6.4/setup.cfg --- old/python-canonicaljson-1.6.2/setup.cfg 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/setup.cfg 2022-11-04 19:24:39.000000000 +0100 @@ -1,3 +1,49 @@ +[metadata] +name = canonicaljson +description = Canonical JSON +long_description = file: README.rst +long_description_content_type = text/x-rst +version = attr: canonicaljson.__version__ +keywords = json +url = https://github.com/matrix-org/python-canonicaljson +license = Apache License, Version 2.0 +author = Matrix.org Team and Contributors +author_email = packa...@matrix.org +license_file = LICENSE +classifiers = + Development Status :: 5 - Production/Stable + Intended Audience :: Developers + License :: OSI Approved :: Apache Software License + Programming Language :: Python :: 2 + Programming Language :: Python :: 3 + + +[options] +zip_safe = true +python_requires = >=3.7 + +package_dir = =src +packages = + canonicaljson + +install_requires = + # simplejson 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 + # typing.Protocol was only added to the stdlib in Python 3.8 + typing_extensions>=4.0.0; python_version < '3.8' + + +[options.extras_require] +# frozendict support can be enabled using the `canonicaljson[frozendict]` syntax +frozendict = + frozendict>=1.0 + + +[options.package_data] +canonicaljson = py.typed + + [flake8] # see https://pycodestyle.readthedocs.io/en/latest/intro.html#error-codes # for error codes. The ones we ignore are: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/setup.py new/python-canonicaljson-1.6.4/setup.py --- old/python-canonicaljson-1.6.2/setup.py 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/setup.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,74 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2015 OpenMarket Ltd -# Copyright 2018 New Vector Ltd -# -# 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. - -from setuptools import setup -from codecs import open -import os - -here = os.path.abspath(os.path.dirname(__file__)) - - -def read_file(path_segments): - """Read a UTF-8 file from the package. Takes a list of strings to join to - make the path""" - file_path = os.path.join(here, *path_segments) - with open(file_path, encoding="utf-8") as f: - return f.read() - - -def exec_file(path_segments, name): - """Extract a constant from a python file by looking for a line defining - the constant and executing it.""" - result = {} - code = read_file(path_segments) - lines = [line for line in code.split("\n") if line.startswith(name)] - exec("\n".join(lines), result) - return result[name] - - -setup( - name="canonicaljson", - version=exec_file(("canonicaljson.py",), "__version__"), - py_modules=["canonicaljson"], - description="Canonical JSON", - install_requires=[ - # 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", - # 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", - author="The Matrix.org Team", - author_email="t...@matrix.org", - url="https://github.com/matrix-org/python-canonicaljson", - license="Apache License, Version 2.0", - python_requires="~=3.7", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 3", - ], -) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/src/canonicaljson/__init__.py new/python-canonicaljson-1.6.4/src/canonicaljson/__init__.py --- old/python-canonicaljson-1.6.2/src/canonicaljson/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-canonicaljson-1.6.4/src/canonicaljson/__init__.py 2022-11-04 19:24:39.000000000 +0100 @@ -0,0 +1,146 @@ +# Copyright 2014 OpenMarket Ltd +# Copyright 2018 New Vector Ltd +# Copyright 2022 The Matrix.org Foundation C.I.C. +# +# 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. + +import platform +from typing import Any, Generator, Optional, Type + +try: + from typing import Protocol +except ImportError: # pragma: no cover + from typing_extensions import Protocol # type: ignore[misc] + +frozendict_type: Optional[Type[Any]] +try: + from frozendict import frozendict as frozendict_type +except ImportError: + frozendict_type = None # pragma: no cover + +__version__ = "1.6.4" + + +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: Encoder = None # type: ignore[assignment] +_pretty_encoder: Encoder = None # type: ignore[assignment] + + +def set_json_library(json_lib: JsonLibrary) -> None: + """ + Set the underlying JSON library that canonicaljson uses to json_lib. + + Params: + json_lib: The module to use for JSON encoding. Must have a + `JSONEncoder` property. + """ + global _canonical_encoder + _canonical_encoder = json_lib.JSONEncoder( + ensure_ascii=False, + allow_nan=False, + separators=(",", ":"), + sort_keys=True, + default=_default, + ) + + global _pretty_encoder + _pretty_encoder = json_lib.JSONEncoder( + ensure_ascii=False, + allow_nan=False, + indent=4, + sort_keys=True, + default=_default, + ) + + +def encode_canonical_json(data: object) -> bytes: + """Encodes the given `data` as a UTF-8 canonical JSON bytestring. + + 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") + + +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. + + This encoding is the shortest possible. Dictionary keys are + lexicographically sorted by unicode code point. + """ + for chunk in _canonical_encoder.iterencode(data): + yield chunk.encode("utf-8") + + +def encode_pretty_printed_json(data: object) -> bytes: + """Encodes the given `data` as a UTF-8 human-readable JSON bytestring.""" + + return _pretty_encoder.encode(data).encode("utf-8") + + +def iterencode_pretty_printed_json(data: object) -> Generator[bytes, None, None]: + """Iteratively encodes the given `data` as a UTF-8 human-readable 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. + """ + for chunk in _pretty_encoder.iterencode(data): + yield chunk.encode("utf-8") + + +if platform.python_implementation() == "PyPy": # pragma: no cover + # pypy ships with an optimised JSON encoder/decoder that is faster than + # simplejson's C extension. + import json +else: # pragma: no cover + # using simplejson rather than regular json on CPython for backwards + # compatibility (simplejson on Python 3.5 handles parsing of bytes while + # the standard library json does not). + # + # 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 # type: ignore[no-redef] + +# Set the JSON library to the backwards compatible version. +set_json_library(json) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/test_canonicaljson.py new/python-canonicaljson-1.6.4/test_canonicaljson.py --- old/python-canonicaljson-1.6.2/test_canonicaljson.py 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/test_canonicaljson.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,170 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 OpenMarket Ltd -# Copyright 2018 New Vector Ltd -# -# 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. - -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, -) - -import unittest -from unittest import mock - - -class TestCanonicalJson(unittest.TestCase): - 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"', - ) - - # quotes and backslashes should be escaped. - self.assertEqual( - encode_canonical_json(r'"\ test'), - b'"\\"\\\\ test"', - ) - - # non-ascii should come out utf8-encoded. - self.assertEqual( - encode_canonical_json({u"la merde amusée": u"ð©"}), - b'{"la merde amus\xc3\xa9e":"\xF0\x9F\x92\xA9"}', - ) - - # so should U+2028 and U+2029 - self.assertEqual( - encode_canonical_json({u"spaces": u"\u2028 \u2029"}), - b'{"spaces":"\xe2\x80\xa8 \xe2\x80\xa9"}', - ) - - # 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"', - ) - - # Iteratively encoding should work. - self.assertEqual(list(iterencode_canonical_json({})), [b"{}"]) - - def test_ascii(self) -> None: - """ - Ensure the proper ASCII characters are escaped. - - See https://matrix.org/docs/spec/appendices#grammar. - """ - # Some characters go to their common shorthands. - escaped = { - 0x08: b'"\\b"', - 0x09: b'"\\t"', - 0x0A: b'"\\n"', - 0x0C: b'"\\f"', - 0x0D: b'"\\r"', - 0x22: b'"\\""', - 0x5C: b'"\\\\"', - } - for c, expected in escaped.items(): - self.assertEqual(encode_canonical_json(chr(c)), expected) - - # Others go to the \uXXXX. - hex_escaped = list(range(0x08)) + [0x0B] + list(range(0x0E, 0x20)) - for c in hex_escaped: - self.assertEqual(encode_canonical_json(chr(c)), b'"\\u00%02x"' % (c,)) - - # And other characters are passed unescaped. - unescaped = [0x20, 0x21] + list(range(0x23, 0x5C)) + list(range(0x5D, 0x7E)) - for c in unescaped: - s = chr(c) - self.assertEqual(encode_canonical_json(s), b'"' + s.encode("ascii") + b'"') - - def test_encode_pretty_printed(self) -> None: - self.assertEqual(encode_pretty_printed_json({}), b"{}") - self.assertEqual(list(iterencode_pretty_printed_json({})), [b"{}"]) - - # non-ascii should come out utf8-encoded. - self.assertEqual( - encode_pretty_printed_json({u"la merde amusée": u"ð©"}), - b'{\n "la merde amus\xc3\xa9e": "\xF0\x9F\x92\xA9"\n}', - ) - - @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_type({"a": 1})), - b'{"a":1}', - ) - self.assertEqual( - encode_pretty_printed_json(frozendict_type({"a": 1})), - b'{\n "a": 1\n}', - ) - - def test_unknown_type(self) -> None: - class Unknown(object): - pass - - unknown_object = Unknown() - with self.assertRaises(Exception): - encode_canonical_json(unknown_object) - - with self.assertRaises(Exception): - encode_pretty_printed_json(unknown_object) - - def test_invalid_float_values(self) -> None: - """Infinity/-Infinity/NaN are not allowed in canonicaljson.""" - - with self.assertRaises(ValueError): - encode_canonical_json(inf) - - with self.assertRaises(ValueError): - encode_pretty_printed_json(inf) - - with self.assertRaises(ValueError): - encode_canonical_json(-inf) - - with self.assertRaises(ValueError): - encode_pretty_printed_json(-inf) - - with self.assertRaises(ValueError): - encode_canonical_json(nan) - - with self.assertRaises(ValueError): - encode_pretty_printed_json(nan) - - 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" - try: - set_json_library(mock_json) - self.assertEqual(encode_canonical_json({}), b"sentinel") - finally: - # Reset the JSON library to whatever was originally set. - from canonicaljson import json # type: ignore[attr-defined] - - set_json_library(json) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/tests/__init__.py new/python-canonicaljson-1.6.4/tests/__init__.py --- old/python-canonicaljson-1.6.2/tests/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-canonicaljson-1.6.4/tests/__init__.py 2022-11-04 19:24:39.000000000 +0100 @@ -0,0 +1,13 @@ +# Copyright 2022 The Matrix.org Foundation C.I.C. +# +# 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. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/tests/test_canonicaljson.py new/python-canonicaljson-1.6.4/tests/test_canonicaljson.py --- old/python-canonicaljson-1.6.2/tests/test_canonicaljson.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-canonicaljson-1.6.4/tests/test_canonicaljson.py 2022-11-04 19:24:39.000000000 +0100 @@ -0,0 +1,169 @@ +# Copyright 2015 OpenMarket Ltd +# Copyright 2018 New Vector Ltd +# Copyright 2022 The Matrix.org Foundation C.I.C. +# +# 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. + +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, +) + +import unittest +from unittest import mock + + +class TestCanonicalJson(unittest.TestCase): + 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"', + ) + + # quotes and backslashes should be escaped. + self.assertEqual( + encode_canonical_json(r'"\ test'), + b'"\\"\\\\ test"', + ) + + # non-ascii should come out utf8-encoded. + self.assertEqual( + encode_canonical_json({u"la merde amusée": u"ð©"}), + b'{"la merde amus\xc3\xa9e":"\xF0\x9F\x92\xA9"}', + ) + + # so should U+2028 and U+2029 + self.assertEqual( + encode_canonical_json({u"spaces": u"\u2028 \u2029"}), + b'{"spaces":"\xe2\x80\xa8 \xe2\x80\xa9"}', + ) + + # 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"', + ) + + # Iteratively encoding should work. + self.assertEqual(list(iterencode_canonical_json({})), [b"{}"]) + + def test_ascii(self) -> None: + """ + Ensure the proper ASCII characters are escaped. + + See https://matrix.org/docs/spec/appendices#grammar. + """ + # Some characters go to their common shorthands. + escaped = { + 0x08: b'"\\b"', + 0x09: b'"\\t"', + 0x0A: b'"\\n"', + 0x0C: b'"\\f"', + 0x0D: b'"\\r"', + 0x22: b'"\\""', + 0x5C: b'"\\\\"', + } + for c, expected in escaped.items(): + self.assertEqual(encode_canonical_json(chr(c)), expected) + + # Others go to the \uXXXX. + hex_escaped = list(range(0x08)) + [0x0B] + list(range(0x0E, 0x20)) + for c in hex_escaped: + self.assertEqual(encode_canonical_json(chr(c)), b'"\\u00%02x"' % (c,)) + + # And other characters are passed unescaped. + unescaped = [0x20, 0x21] + list(range(0x23, 0x5C)) + list(range(0x5D, 0x7E)) + for c in unescaped: + s = chr(c) + self.assertEqual(encode_canonical_json(s), b'"' + s.encode("ascii") + b'"') + + def test_encode_pretty_printed(self) -> None: + self.assertEqual(encode_pretty_printed_json({}), b"{}") + self.assertEqual(list(iterencode_pretty_printed_json({})), [b"{}"]) + + # non-ascii should come out utf8-encoded. + self.assertEqual( + encode_pretty_printed_json({u"la merde amusée": u"ð©"}), + b'{\n "la merde amus\xc3\xa9e": "\xF0\x9F\x92\xA9"\n}', + ) + + @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_type({"a": 1})), + b'{"a":1}', + ) + self.assertEqual( + encode_pretty_printed_json(frozendict_type({"a": 1})), + b'{\n "a": 1\n}', + ) + + def test_unknown_type(self) -> None: + class Unknown(object): + pass + + unknown_object = Unknown() + with self.assertRaises(Exception): + encode_canonical_json(unknown_object) + + with self.assertRaises(Exception): + encode_pretty_printed_json(unknown_object) + + def test_invalid_float_values(self) -> None: + """Infinity/-Infinity/NaN are not allowed in canonicaljson.""" + + with self.assertRaises(ValueError): + encode_canonical_json(inf) + + with self.assertRaises(ValueError): + encode_pretty_printed_json(inf) + + with self.assertRaises(ValueError): + encode_canonical_json(-inf) + + with self.assertRaises(ValueError): + encode_pretty_printed_json(-inf) + + with self.assertRaises(ValueError): + encode_canonical_json(nan) + + with self.assertRaises(ValueError): + encode_pretty_printed_json(nan) + + 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" + try: + set_json_library(mock_json) + self.assertEqual(encode_canonical_json({}), b"sentinel") + finally: + # Reset the JSON library to whatever was originally set. + from canonicaljson import json # type: ignore[attr-defined] + + set_json_library(json) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-canonicaljson-1.6.2/tox.ini new/python-canonicaljson-1.6.4/tox.ini --- old/python-canonicaljson-1.6.2/tox.ini 2022-06-08 11:33:29.000000000 +0200 +++ new/python-canonicaljson-1.6.4/tox.ini 2022-11-04 19:24:39.000000000 +0100 @@ -1,7 +1,8 @@ [tox] envlist = packaging, pep8, black, py37, py38, py39, py310, pypy3 +isolated_build = True -[testenv] +[testenv:py] deps = coverage nose2 @@ -19,7 +20,7 @@ basepython = python3.7 deps = flake8 -commands = flake8 . +commands = flake8 src tests [testenv:black] basepython = python3.7 @@ -27,7 +28,7 @@ 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 . +commands = python -m black --check --diff src tests [testenv:mypy] deps = @@ -35,4 +36,5 @@ types-frozendict==2.0.8 types-simplejson==3.17.5 types-setuptools==57.4.14 -commands = mypy +commands = mypy src tests +