12
12
13
13
Serialization/deserialization
14
14
-----------------------------
15
+
16
+ .. autoclass:: SerializationKey
17
+ .. autoclass:: SerializedContainer
15
18
.. autofunction:: is_array_container_type
16
19
.. autofunction:: serialize_container
17
20
.. autofunction:: deserialize_container
39
42
.. class:: ArrayOrContainerT
40
43
41
44
:canonical: arraycontext.ArrayOrContainerT
45
+
46
+ .. class:: SerializationKey
47
+
48
+ :canonical: arraycontext.SerializationKey
49
+
50
+ .. class:: SerializedContainer
51
+
52
+ :canonical: arraycontext.SerializedContainer
42
53
"""
43
54
44
55
from __future__ import annotations
69
80
"""
70
81
71
82
from functools import singledispatch
72
- from typing import TYPE_CHECKING , Any , Iterable , Optional , Protocol , Tuple , TypeVar
83
+ from typing import (
84
+ TYPE_CHECKING ,
85
+ Any ,
86
+ Hashable ,
87
+ Iterable ,
88
+ Optional ,
89
+ Protocol ,
90
+ Sequence ,
91
+ Tuple ,
92
+ TypeVar ,
93
+ )
73
94
74
95
# For use in singledispatch type annotations, because sphinx can't figure out
75
96
# what 'np' is.
76
97
import numpy
77
98
import numpy as np
99
+ from typing_extensions import TypeAlias
78
100
79
101
from arraycontext .context import ArrayContext
80
102
@@ -142,23 +164,27 @@ class NotAnArrayContainerError(TypeError):
142
164
""":class:`TypeError` subclass raised when an array container is expected."""
143
165
144
166
167
+ SerializationKey : TypeAlias = Hashable
168
+ SerializedContainer : TypeAlias = Sequence [Tuple [SerializationKey , "ArrayOrContainer" ]]
169
+
170
+
145
171
@singledispatch
146
172
def serialize_container (
147
- ary : ArrayContainer ) -> Iterable [ Tuple [ Any , ArrayOrContainer ]] :
148
- r"""Serialize the array container into an iterable over its components.
173
+ ary : ArrayContainer ) -> SerializedContainer :
174
+ r"""Serialize the array container into a sequence over its components.
149
175
150
176
The order of the components and their identifiers are entirely under
151
177
the control of the container class. However, the order is required to be
152
178
deterministic, i.e. two calls to :func:`serialize_container` on
153
179
array containers of the same types with the same number of
154
- sub-arrays must result in an iterable with the keys in the same
180
+ sub-arrays must result in a sequence with the keys in the same
155
181
order.
156
182
157
183
If *ary* is mutable, the serialization function is not required to ensure
158
184
that the serialization result reflects the array state at the time of the
159
185
call to :func:`serialize_container`.
160
186
161
- :returns: an :class:`Iterable ` of 2-tuples where the first
187
+ :returns: an :class:`Sequence ` of 2-tuples where the first
162
188
entry is an identifier for the component and the second entry
163
189
is an array-like component of the :class:`ArrayContainer`.
164
190
Components can themselves be :class:`ArrayContainer`\ s, allowing
@@ -172,13 +198,13 @@ def serialize_container(
172
198
@singledispatch
173
199
def deserialize_container (
174
200
template : ArrayContainerT ,
175
- iterable : Iterable [ Tuple [ Any , Any ]] ) -> ArrayContainerT :
176
- """Deserialize an iterable into an array container.
201
+ serialized : SerializedContainer ) -> ArrayContainerT :
202
+ """Deserialize a sequence into an array container following a *template* .
177
203
178
204
:param template: an instance of an existing object that
179
205
can be used to aid in the deserialization. For a similar choice
180
206
see :attr:`~numpy.class.__array_finalize__`.
181
- :param iterable: an iterable that mirrors the output of
207
+ :param serialized: a sequence that mirrors the output of
182
208
:meth:`serialize_container`.
183
209
"""
184
210
raise NotAnArrayContainerError (
@@ -242,7 +268,7 @@ def get_container_context_opt(ary: ArrayContainer) -> Optional[ArrayContext]:
242
268
243
269
@serialize_container .register (np .ndarray )
244
270
def _serialize_ndarray_container (
245
- ary : numpy .ndarray ) -> Iterable [ Tuple [ Any , ArrayOrContainer ]] :
271
+ ary : numpy .ndarray ) -> SerializedContainer :
246
272
if ary .dtype .char != "O" :
247
273
raise NotAnArrayContainerError (
248
274
f"cannot serialize '{ type (ary ).__name__ } ' with dtype '{ ary .dtype } '" )
@@ -256,20 +282,20 @@ def _serialize_ndarray_container(
256
282
for j in range (ary .shape [1 ])
257
283
]
258
284
else :
259
- return np .ndenumerate (ary )
285
+ return list ( np .ndenumerate (ary ) )
260
286
261
287
262
288
@deserialize_container .register (np .ndarray )
263
289
# https://github.com/python/mypy/issues/13040
264
290
def _deserialize_ndarray_container ( # type: ignore[misc]
265
291
template : numpy .ndarray ,
266
- iterable : Iterable [ Tuple [ Any , ArrayOrContainer ]] ) -> numpy .ndarray :
292
+ serialized : SerializedContainer ) -> numpy .ndarray :
267
293
# disallow subclasses
268
294
assert type (template ) is np .ndarray
269
295
assert template .dtype .char == "O"
270
296
271
297
result = type (template )(template .shape , dtype = object )
272
- for i , subary in iterable :
298
+ for i , subary in serialized :
273
299
result [i ] = subary
274
300
275
301
return result
0 commit comments