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 2023-05-30 22:02:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-canonicaljson (Old)
and /work/SRC/openSUSE:Factory/.python-canonicaljson.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-canonicaljson"
Tue May 30 22:02:18 2023 rev:17 rq:1089612 version:2.0.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-canonicaljson/python-canonicaljson.changes
2023-05-15 16:54:24.592202715 +0200
+++
/work/SRC/openSUSE:Factory/.python-canonicaljson.new.1533/python-canonicaljson.changes
2023-05-30 22:02:32.155043360 +0200
@@ -1,0 +2,13 @@
+Mon May 29 16:34:14 UTC 2023 - Dirk Müller <[email protected]>
+
+- update to 2.0.0:
+ * Add a generic `register_preserialisation_callback` mechanism,
+ which allows users to teach canonicaljson how to JSON-encode custom
+ types.
+ * Remove support for serialising `frozendict` instances. Use
+ the new `register_preserialisation_callback` mechanism to replace
+ this functionality if needed.
+ * Remove support for `simplejson` and the
+ `set_json_library`alternative json libraries.
+
+-------------------------------------------------------------------
Old:
----
v1.6.5.tar.gz
New:
----
v2.0.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-canonicaljson.spec ++++++
--- /var/tmp/diff_new_pack.CYrO3v/_old 2023-05-30 22:02:32.651046284 +0200
+++ /var/tmp/diff_new_pack.CYrO3v/_new 2023-05-30 22:02:32.663046354 +0200
@@ -27,7 +27,7 @@
%define github_user matrix-org
%define short_name canonicaljson
Name: python-%{short_name}%{psuffix}
-Version: 1.6.5
+Version: 2.0.0
Release: 0
Summary: Canonical JSON for Python
License: Apache-2.0
++++++ v1.6.5.tar.gz -> v2.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-canonicaljson-1.6.5/CHANGES.md
new/python-canonicaljson-2.0.0/CHANGES.md
--- old/python-canonicaljson-1.6.5/CHANGES.md 2023-02-15 23:34:05.000000000
+0100
+++ new/python-canonicaljson-2.0.0/CHANGES.md 2023-03-15 02:32:42.000000000
+0100
@@ -1,3 +1,18 @@
+Version 2.0.0 released 2023-03-15
+
+Additions:
+
+* Add a generic `register_preserialisation_callback` mechanism, which
+ allows users to teach canonicaljson how to JSON-encode custom types.
+
+Breaking changes:
+
+* Remove support for serialising `frozendict` instances. Use the new
+ `register_preserialisation_callback` mechanism to replace this
+ functionality if needed.
+* Remove support for `simplejson` and the `set_json_library`alternative
+ json libraries.
+
Version 1.6.5 released 2023-02-15
* Update type hints to pass under mypy 1.0.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-canonicaljson-1.6.5/README.rst
new/python-canonicaljson-2.0.0/README.rst
--- old/python-canonicaljson-1.6.5/README.rst 2023-02-15 23:34:05.000000000
+0100
+++ new/python-canonicaljson-2.0.0/README.rst 2023-03-15 02:32:42.000000000
+0100
@@ -15,7 +15,7 @@
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.
+* Can be configured to encode custom types unknown to the stdlib JSON encoder.
Supports Python versions 3.7 and newer.
@@ -59,3 +59,20 @@
which uses the standard library json module).
.. _simplejson: https://simplejson.readthedocs.io/
+
+A preserialisation hook allows you to encode objects which aren't encodable by
the
+standard library ``JSONEncoder``.
+
+.. code:: python
+
+ import canonicaljson
+ from typing import Dict
+
+ class CustomType:
+ pass
+
+ def callback(c: CustomType) -> Dict[str, str]:
+ return {"Hello": "world!"}
+
+ canonicaljson.register_preserialisation_callback(CustomType, callback)
+ assert canonicaljson.encode_canonical_json(CustomType()) ==
b'{"Hello":"world!"}'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-canonicaljson-1.6.5/setup.cfg
new/python-canonicaljson-2.0.0/setup.cfg
--- old/python-canonicaljson-1.6.5/setup.cfg 2023-02-15 23:34:05.000000000
+0100
+++ new/python-canonicaljson-2.0.0/setup.cfg 2023-03-15 02:32:42.000000000
+0100
@@ -26,20 +26,6 @@
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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python-canonicaljson-1.6.5/src/canonicaljson/__init__.py
new/python-canonicaljson-2.0.0/src/canonicaljson/__init__.py
--- old/python-canonicaljson-1.6.5/src/canonicaljson/__init__.py
2023-02-15 23:34:05.000000000 +0100
+++ new/python-canonicaljson-2.0.0/src/canonicaljson/__init__.py
2023-03-15 02:32:42.000000000 +0100
@@ -13,81 +13,66 @@
# 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 functools
+import json
+from typing import Callable, Generator, Type, TypeVar
-import platform
-from typing import Any, Generator, Iterator, Optional, Type
-
-try:
- from typing import Protocol
-except ImportError: # pragma: no cover
- from typing_extensions import Protocol # type: ignore[assignment]
-
-frozendict_type: Optional[Type[Any]]
-try:
- from frozendict import frozendict as frozendict_type
-except ImportError:
- frozendict_type = None # pragma: no cover
-
-__version__ = "1.6.5"
-
-
-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__
- )
+__version__ = "2.0.0"
-class Encoder(Protocol): # pragma: no cover
- def encode(self, data: object) -> str:
- pass
- def iterencode(self, data: object) -> Iterator[str]:
- pass
[email protected]
+def _preprocess_for_serialisation(obj: object) -> object: # pragma: no cover
+ """Transform an `obj` into something the JSON library knows how to encode.
- def __init__(self, *args: Any, **kwargs: Any) -> None:
- pass
+ This is only called for types that the JSON library does not recognise.
+ """
+ raise TypeError(
+ "Object of type %s is not JSON serializable" % obj.__class__.__name__
+ )
-class JsonLibrary(Protocol): # pragma: no cover
- @property
- def JSONEncoder(self) -> Type[Encoder]:
- pass
+T = TypeVar("T")
-# 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 register_preserialisation_callback(
+ data_type: Type[T], callback: Callable[[T], object]
+) -> None:
+ """
+ Register a `callback` to preprocess `data_type` objects unknown to the
JSON encoder.
+ When canonicaljson encodes an object `x` at runtime that its JSON library
does not
+ know how to encode, it will
+ - select a `callback`,
+ - compute `y = callback(x)`, then
+ - JSON-encode `y` and return the result.
-def set_json_library(json_lib: JsonLibrary) -> None:
- """
- Set the underlying JSON library that canonicaljson uses to json_lib.
+ The `callback` should return an object that is JSON-serialisable by the
stdlib
+ json module.
- Params:
- json_lib: The module to use for JSON encoding. Must have a
- `JSONEncoder` property.
+ If this is called multiple times with the same `data_type`, the most
recently
+ registered callback is used when serialising that `data_type`.
"""
- 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,
- )
+ if data_type is object:
+ raise ValueError("Cannot register callback for the `object` type")
+ _preprocess_for_serialisation.register(data_type, callback)
+
+
+# Declare these once for re-use.
+_canonical_encoder = json.JSONEncoder(
+ ensure_ascii=False,
+ allow_nan=False,
+ separators=(",", ":"),
+ sort_keys=True,
+ default=_preprocess_for_serialisation,
+)
+_pretty_encoder = json.JSONEncoder(
+ ensure_ascii=False,
+ allow_nan=False,
+ indent=4,
+ sort_keys=True,
+ default=_preprocess_for_serialisation,
+)
def encode_canonical_json(data: object) -> bytes:
@@ -129,20 +114,3 @@
"""
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.5/tests/test_canonicaljson.py
new/python-canonicaljson-2.0.0/tests/test_canonicaljson.py
--- old/python-canonicaljson-1.6.5/tests/test_canonicaljson.py 2023-02-15
23:34:05.000000000 +0100
+++ new/python-canonicaljson-2.0.0/tests/test_canonicaljson.py 2023-03-15
02:32:42.000000000 +0100
@@ -13,20 +13,19 @@
# 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 unittest.mock import Mock
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,
+ register_preserialisation_callback,
)
import unittest
-from unittest import mock
class TestCanonicalJson(unittest.TestCase):
@@ -107,22 +106,6 @@
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
@@ -155,15 +138,45 @@
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]
+ def test_encode_unknown_class_raises(self) -> None:
+ class C:
+ pass
+
+ with self.assertRaises(Exception):
+ encode_canonical_json(C())
+
+ def test_preserialisation_callback(self) -> None:
+ class C:
+ pass
+
+ # Naughty: this alters the global state of the module. However this
+ # `C` class is limited to this test only, so this shouldn't affect
+ # other types and other tests.
+ register_preserialisation_callback(C, lambda c: "I am a C instance")
+
+ result = encode_canonical_json(C())
+ self.assertEqual(result, b'"I am a C instance"')
+
+ def test_cannot_register_preserialisation_callback_for_object(self) ->
None:
+ with self.assertRaises(Exception):
+ register_preserialisation_callback(
+ object, lambda c: "shouldn't be able to do this"
+ )
+
+ def test_most_recent_preserialisation_callback_called(self) -> None:
+ class C:
+ pass
+
+ callback1 = Mock(return_value="callback 1 was called")
+ callback2 = Mock(return_value="callback 2 was called")
+
+ # Naughty: this alters the global state of the module. However this
+ # `C` class is limited to this test only, so this shouldn't affect
+ # other types and other tests.
+ register_preserialisation_callback(C, callback1)
+ register_preserialisation_callback(C, callback2)
+
+ encode_canonical_json(C())
- set_json_library(json)
+ callback1.assert_not_called()
+ callback2.assert_called_once()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-canonicaljson-1.6.5/tox.ini
new/python-canonicaljson-2.0.0/tox.ini
--- old/python-canonicaljson-1.6.5/tox.ini 2023-02-15 23:34:05.000000000
+0100
+++ new/python-canonicaljson-2.0.0/tox.ini 2023-03-15 02:32:42.000000000
+0100
@@ -33,8 +33,5 @@
[testenv:mypy]
deps =
mypy==1.0
- types-frozendict==2.0.8
- types-simplejson==3.17.5
types-setuptools==57.4.14
commands = mypy src tests
-