aka PEP 585, added in Python 3.9 - https://peps.python.org/pep-0585/ - https://docs.astral.sh/ruff/rules/non-pep585-annotation/
57 lines
1.8 KiB
Python
57 lines
1.8 KiB
Python
#
|
|
# This file is licensed under the Affero General Public License (AGPL) version 3.
|
|
#
|
|
# Copyright (C) 2025 New Vector, Ltd
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# See the GNU Affero General Public License for more details:
|
|
# <https://www.gnu.org/licenses/agpl_3.0.html>.
|
|
#
|
|
#
|
|
|
|
import json
|
|
from typing import (
|
|
Any,
|
|
)
|
|
|
|
from immutabledict import immutabledict
|
|
|
|
|
|
def _reject_invalid_json(val: Any) -> None:
|
|
"""Do not allow Infinity, -Infinity, or NaN values in JSON."""
|
|
raise ValueError("Invalid JSON value: '%s'" % val)
|
|
|
|
|
|
def _handle_immutabledict(obj: Any) -> dict[Any, Any]:
|
|
"""Helper for json_encoder. Makes immutabledicts serializable by returning
|
|
the underlying dict
|
|
"""
|
|
if type(obj) is immutabledict:
|
|
# fishing the protected dict out of the object is a bit nasty,
|
|
# but we don't really want the overhead of copying the dict.
|
|
try:
|
|
# Safety: we catch the AttributeError immediately below.
|
|
return obj._dict
|
|
except AttributeError:
|
|
# If all else fails, resort to making a copy of the immutabledict
|
|
return dict(obj)
|
|
raise TypeError(
|
|
"Object of type %s is not JSON serializable" % obj.__class__.__name__
|
|
)
|
|
|
|
|
|
# A custom JSON encoder which:
|
|
# * handles immutabledicts
|
|
# * produces valid JSON (no NaNs etc)
|
|
# * reduces redundant whitespace
|
|
json_encoder = json.JSONEncoder(
|
|
allow_nan=False, separators=(",", ":"), default=_handle_immutabledict
|
|
)
|
|
|
|
# Create a custom decoder to reject Python extensions to JSON.
|
|
json_decoder = json.JSONDecoder(parse_constant=_reject_invalid_json)
|