summary refs log tree commit diff
diff options
context:
space:
mode:
authorOlivier Wilkinson (reivilibre) <oliverw@matrix.org>2022-05-25 12:26:55 +0100
committerOlivier Wilkinson (reivilibre) <oliverw@matrix.org>2022-05-25 12:26:55 +0100
commit038439a7d2102e019186a4c35b1688571d343270 (patch)
tree70b286d2b309f211b37d2f47a6b2eb7bb21b31b6
parentCorrect typo in changelog for #12858. (diff)
downloadsynapse-rei/strict_json_types.tar.xz
Signed-off-by: Olivier Wilkinson (reivilibre) <oliverw@matrix.org>
-rw-r--r--changelog.d/12873.misc1
-rw-r--r--synapse/types.py41
2 files changed, 42 insertions, 0 deletions
diff --git a/changelog.d/12873.misc b/changelog.d/12873.misc
new file mode 100644
index 0000000000..c441084264
--- /dev/null
+++ b/changelog.d/12873.misc
@@ -0,0 +1 @@
+Add stricter JSON type annotations to the Module API's account data manager.
\ No newline at end of file
diff --git a/synapse/types.py b/synapse/types.py
index 6f7128ddd6..7200dedf5f 100644
--- a/synapse/types.py
+++ b/synapse/types.py
@@ -26,6 +26,7 @@ from typing import (
     MutableMapping,
     NoReturn,
     Optional,
+    Protocol,
     Set,
     Tuple,
     Type,
@@ -77,6 +78,46 @@ JsonMapping = Mapping[str, Any]
 JsonSerializable = object
 
 
+if TYPE_CHECKING:
+    # This is a very hacky way to have a strongly-typed JSON object
+    # that doesn't stop short at Dict[str, Any].
+    # https://github.com/python/typing/issues/182#issuecomment-899624078
+
+    StrictJson = ...
+
+    class StrictJsonArray(List[StrictJson], Protocol):  # type: ignore
+        __class__: Type[List[StrictJson]]  # type: ignore
+
+    class StrictJsonDict(Dict[str, StrictJson], Protocol):  # type: ignore
+        __class__: Type[Dict[str, StrictJson]]  # type: ignore
+
+    StrictJson = Union[None, float, str, StrictJsonArray, StrictJsonDict]  # type: ignore[assignment]
+else:
+    # We need some types for runtime.
+    StrictJson = Union[None, float, str, List[Any], Dict[str, Any]]
+    StrictJsonDict = Dict[str, StrictJson]
+
+
+if TYPE_CHECKING:
+    # Analogous to StrictJson, this is a version that uses entirely frozen data.
+
+    StrictFrozenJson = ...
+
+    class StrictFrozenJsonArray(Tuple[StrictFrozenJson, ...], Protocol):  # type: ignore
+        __class__: Type[Tuple[StrictFrozenJson, ...]]  # type: ignore
+
+    class StrictFrozenJsonDict(frozendict[str, StrictFrozenJson], Protocol):  # type: ignore
+        __class__: Type[frozendict[str, StrictFrozenJson]]  # type: ignore
+
+    StrictFrozenJson = Union[  # type: ignore[assignment]
+        None, float, str, StrictFrozenJsonArray, StrictFrozenJsonDict
+    ]
+else:
+    # We need some types for runtime.
+    StrictFrozenJson = Union[None, float, str, Tuple[Any, ...], frozendict[str, Any]]
+    StrictFrozenJsonDict = frozendict[str, StrictFrozenJson]
+
+
 # Note that this seems to require inheriting *directly* from Interface in order
 # for mypy-zope to realize it is an interface.
 class ISynapseReactor(