|
14 | 14 | that JSON does not support Numpy and more generally cannot be extended with |
15 | 15 | other data types while keeping a concise syntax. Here we can use the Python |
16 | 16 | function call syntax to express special data types. |
17 | | -""" |
18 | 17 |
|
| 18 | +PYON can be extended via encoding & decoding plugins to whatever types you would like to serialize. |
| 19 | +An example can be found in :mod:`sipyco.test.test_pyon_plugin`. |
| 20 | +""" |
19 | 21 |
|
| 22 | +import itertools |
| 23 | +import os |
| 24 | +import tempfile |
20 | 25 | from operator import itemgetter |
21 | 26 | from fractions import Fraction |
22 | 27 | from collections import OrderedDict |
23 | | -import os |
24 | | -import tempfile |
25 | 28 |
|
26 | 29 | import numpy |
27 | 30 | import pybase64 as base64 |
28 | 31 |
|
| 32 | +import sipyco |
| 33 | +import sipyco.plugins as plugin |
| 34 | + |
29 | 35 |
|
30 | 36 | _encode_map = { |
31 | 37 | type(None): "none", |
@@ -171,10 +177,28 @@ def encode(self, x): |
171 | 177 | return getattr(self, "encode_" + ty)(x) |
172 | 178 |
|
173 | 179 |
|
174 | | -def encode(x, pretty=False): |
| 180 | +@sipyco.hookimpl |
| 181 | +def sipyco_pyon_encode(value, pretty=False, indent_level=0): |
| 182 | + """Default PYON encoder implementation.""" |
| 183 | + try: |
| 184 | + return _Encoder(pretty=pretty, indent_level=indent_level).encode(value) |
| 185 | + except TypeError: |
| 186 | + return None |
| 187 | + |
| 188 | + |
| 189 | +def encode(x, pretty=False, indent_level=0): |
175 | 190 | """Serializes a Python object and returns the corresponding string in |
176 | 191 | Python syntax.""" |
177 | | - return _Encoder(pretty).encode(x) |
| 192 | + pm = plugin.get_plugin_manager() |
| 193 | + |
| 194 | + func_val = pm.hook.sipyco_pyon_encode( |
| 195 | + value=x, pretty=pretty, indent_level=indent_level |
| 196 | + ) |
| 197 | + |
| 198 | + if func_val is None: |
| 199 | + raise TypeError("`{!r}` ({}) is not PYON serializable".format(x, type(x))) |
| 200 | + else: |
| 201 | + return func_val |
178 | 202 |
|
179 | 203 |
|
180 | 204 | def _nparray(shape, dtype, data): |
@@ -204,10 +228,22 @@ def _npscalar(ty, data): |
204 | 228 | } |
205 | 229 |
|
206 | 230 |
|
| 231 | +@sipyco.hookimpl |
| 232 | +def sipyco_pyon_decoders(): |
| 233 | + """Default Sipyco PYON decoding valid types.""" |
| 234 | + return _eval_dict.items() |
| 235 | + |
| 236 | + |
207 | 237 | def decode(s): |
208 | 238 | """Parses a string in the Python syntax, reconstructs the corresponding |
209 | 239 | object, and returns it.""" |
210 | | - return eval(s, _eval_dict, {}) |
| 240 | + pm = plugin.get_plugin_manager() |
| 241 | + _decode_eval_dict = dict( |
| 242 | + itertools.chain.from_iterable( |
| 243 | + filter(lambda r: r is not None, pm.hook.sipyco_pyon_decoders()) |
| 244 | + ) |
| 245 | + ) |
| 246 | + return eval(s, _decode_eval_dict, {}) |
211 | 247 |
|
212 | 248 |
|
213 | 249 | def store_file(filename, x): |
|
0 commit comments