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 <dmuel...@suse.com>
+
+- 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
+@functools.singledispatch
+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
-

Reply via email to