transit-python 0.8.321__cp314-cp314t-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
transit/__init__.py ADDED
@@ -0,0 +1,16 @@
1
+ ## Copyright 2014 Cognitect. All Rights Reserved.
2
+ ## Copyright 2026 Vendekagon Labs LLC.
3
+ ##
4
+ ## Licensed under the Apache License, Version 2.0 (the "License");
5
+ ## you may not use this file except in compliance with the License.
6
+ ## You may obtain a copy of the License at
7
+ ##
8
+ ## http://www.apache.org/licenses/LICENSE-2.0
9
+ ##
10
+ ## Unless required by applicable law or agreed to in writing, software
11
+ ## distributed under the License is distributed on an "AS-IS" BASIS,
12
+ ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ ## See the License for the specific language governing permissions and
14
+ ## limitations under the License.
15
+
16
+ __version__ = "0.8.321"
transit/_accel.py ADDED
@@ -0,0 +1,27 @@
1
+ ## Copyright 2026 Vendekagon Labs LLC.
2
+ ##
3
+ ## Licensed under the Apache License, Version 2.0 (the "License");
4
+ ## you may not use this file except in compliance with the License.
5
+ ## You may obtain a copy of the License at
6
+ ##
7
+ ## http://www.apache.org/licenses/LICENSE-2.0
8
+ ##
9
+ ## Unless required by applicable law or agreed to in writing, software
10
+ ## distributed under the License is distributed on an "AS IS" BASIS,
11
+ ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ ## See the License for the specific language governing permissions and
13
+ ## limitations under the License.
14
+
15
+ # The optional native extension (transit._native, built from transit-format-c).
16
+ # Reader and Writer use it when it's available, unless TRANSIT_PUREPYTHON is
17
+ # set; otherwise, or for anything it doesn't handle, they use pure Python.
18
+ import os
19
+
20
+ native = None
21
+ if not os.environ.get("TRANSIT_PUREPYTHON"):
22
+ try:
23
+ from transit import _native as native
24
+ except ImportError:
25
+ native = None
26
+
27
+ FORMATS = {"json": 0, "json_verbose": 1, "msgpack": 2}
Binary file
transit/class_hash.py ADDED
@@ -0,0 +1,52 @@
1
+ ## Copyright 2014 Cognitect. All Rights Reserved.
2
+ ## Copyright 2026 Vendekagon Labs LLC.
3
+ ##
4
+ ## Licensed under the Apache License, Version 2.0 (the "License");
5
+ ## you may not use this file except in compliance with the License.
6
+ ## You may obtain a copy of the License at
7
+ ##
8
+ ## http://www.apache.org/licenses/LICENSE-2.0
9
+ ##
10
+ ## Unless required by applicable law or agreed to in writing, software
11
+ ## distributed under the License is distributed on an "AS-IS" BASIS,
12
+ ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ ## See the License for the specific language governing permissions and
14
+ ## limitations under the License.
15
+ from collections.abc import MutableMapping
16
+
17
+
18
+ class ClassDict(MutableMapping):
19
+ """A dictionary that looks up class/type keys with inheritance."""
20
+
21
+ def __init__(self, *args, **kwargs):
22
+ self.store = dict()
23
+ self.update(dict(*args, **kwargs))
24
+
25
+ def __getitem__(self, key):
26
+ key = key if isinstance(key, type) else type(key)
27
+ if key in self.store:
28
+ return self.store[key]
29
+ else:
30
+ for t in key.__bases__:
31
+ value = t in self.store and self.store[t]
32
+ if value:
33
+ return value
34
+ # only use mro if __bases__ doesn't work to
35
+ # avoid its perf overhead.
36
+ for t in key.mro():
37
+ value = t in self.store and self.store[t]
38
+ if value:
39
+ return value
40
+ raise KeyError("No handler found for: " + str(key))
41
+
42
+ def __setitem__(self, key, value):
43
+ self.store[key] = value
44
+
45
+ def __delitem__(self, key):
46
+ del self.store[key]
47
+
48
+ def __iter__(self):
49
+ return iter(self.store)
50
+
51
+ def __len__(self):
52
+ return len(self.store)
transit/constants.py ADDED
@@ -0,0 +1,23 @@
1
+ ## Copyright 2014 Cognitect. All Rights Reserved.
2
+ ##
3
+ ## Licensed under the Apache License, Version 2.0 (the "License");
4
+ ## you may not use this file except in compliance with the License.
5
+ ## You may obtain a copy of the License at
6
+ ##
7
+ ## http://www.apache.org/licenses/LICENSE-2.0
8
+ ##
9
+ ## Unless required by applicable law or agreed to in writing, software
10
+ ## distributed under the License is distributed on an "AS-IS" BASIS,
11
+ ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ ## See the License for the specific language governing permissions and
13
+ ## limitations under the License.
14
+
15
+ # These are constants used throughout the source code.
16
+ # They refer to Tag codes used when reading and wrting transit.
17
+
18
+ ESC = "~"
19
+ SUB = "^"
20
+ RES = "`"
21
+ TAG = "~#"
22
+ QUOTE = "'"
23
+ MAP_AS_ARR = "^ "
transit/decoder.py ADDED
@@ -0,0 +1,185 @@
1
+ ## Copyright 2014 Cognitect. All Rights Reserved.
2
+ ## Copyright 2026 Vendekagon Labs LLC.
3
+ ##
4
+ ## Licensed under the Apache License, Version 2.0 (the "License");
5
+ ## you may not use this file except in compliance with the License.
6
+ ## You may obtain a copy of the License at
7
+ ##
8
+ ## http://www.apache.org/licenses/LICENSE-2.0
9
+ ##
10
+ ## Unless required by applicable law or agreed to in writing, software
11
+ ## distributed under the License is distributed on an "AS-IS" BASIS,
12
+ ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ ## See the License for the specific language governing permissions and
14
+ ## limitations under the License.
15
+
16
+ from transit import transit_types
17
+ from transit import read_handlers as rh
18
+ from transit.constants import MAP_AS_ARR, ESC, SUB, RES
19
+ from transit.helpers import pairs
20
+ from transit.rolling_cache import RollingCache
21
+ from transit.transit_types import true, false
22
+
23
+
24
+ class Tag:
25
+ def __init__(self, tag):
26
+ self.tag = tag
27
+
28
+ default_options = {"decoders": {"_": rh.NoneHandler,
29
+ ":": rh.KeywordHandler,
30
+ "$": rh.SymbolHandler,
31
+ "?": rh.BooleanHandler,
32
+ "i": rh.IntHandler,
33
+ "d": rh.FloatHandler,
34
+ "f": rh.BigDecimalHandler,
35
+ "u": rh.UuidHandler,
36
+ "r": rh.UriHandler,
37
+ "t": rh.DateHandler,
38
+ "m": rh.DateHandler,
39
+ "n": rh.BigIntegerHandler,
40
+ "z": rh.SpecialNumbersHandler,
41
+ "link": rh.LinkHandler,
42
+ "list": rh.ListHandler,
43
+ "set": rh.SetHandler,
44
+ "cmap": rh.CmapHandler,
45
+ "'": rh.IdentityHandler},
46
+ "default_decoder": rh.DefaultHandler}
47
+
48
+ ground_decoders = {"_": rh.NoneHandler,
49
+ "?": rh.BooleanHandler,
50
+ "i": rh.IntHandler,
51
+ "'": rh.IdentityHandler}
52
+
53
+
54
+ class Decoder:
55
+ """The Decoder is the lowest level entry point for parsing, decoding, and
56
+ fully converting Transit data into Python objects.
57
+
58
+ During the creation of a Decoder object, you can specify custom options
59
+ in a dictionary. One such option is 'decoders'. Note that while you
60
+ can specify your own decoders and override many of the built in decoders,
61
+ some decoders are silently enforced and cannot be overriden. These are
62
+ known as Ground Decoders, and are needed to maintain bottom-tier
63
+ compatibility.
64
+ """
65
+ def __init__(self, options=None):
66
+ self.options = default_options.copy()
67
+ self.options.update(options or {})
68
+
69
+ # Copy so that registering decoders on one Decoder doesn't leak into
70
+ # default_options (and so every other Decoder).
71
+ self.decoders = dict(self.options["decoders"])
72
+ # Always ensure we control the ground decoders
73
+ self.decoders.update(ground_decoders)
74
+
75
+ def decode(self, node, cache=None, as_map_key=False):
76
+ """Given a node of data (any supported decodeable obj - string, dict,
77
+ list), return the decoded object. Optionally set the current decode
78
+ cache [None]. If None, a new RollingCache is instantiated and used.
79
+ You may also hit to the decoder that this node is to be treated as a
80
+ map key [False]. This is used internally.
81
+ """
82
+ if not cache:
83
+ cache = RollingCache()
84
+ return self._decode(node, cache, as_map_key)
85
+
86
+ def _decode(self, node, cache, as_map_key):
87
+ if isinstance(node, str):
88
+ return self.decode_string(node, cache, as_map_key)
89
+ elif isinstance(node, bytes):
90
+ return self.decode_string(node.decode("utf-8"), cache, as_map_key)
91
+ elif isinstance(node, dict):
92
+ return self.decode_hash(node, cache, as_map_key)
93
+ elif isinstance(node, list):
94
+ return self.decode_list(node, cache, as_map_key)
95
+ elif isinstance(node, bool):
96
+ return true if node else false
97
+ return node
98
+
99
+ def decode_list(self, node, cache, as_map_key):
100
+ """Special case decodes map-as-array.
101
+ Otherwise lists are treated as Python lists.
102
+
103
+ Arguments follow the same convention as the top-level 'decode'
104
+ function.
105
+ """
106
+ if node:
107
+ if node[0] == MAP_AS_ARR:
108
+ # key must be decoded before value for caching to work.
109
+ returned_dict = {}
110
+ for k, v in pairs(node[1:]):
111
+ key = self._decode(k, cache, True)
112
+ val = self._decode(v, cache, as_map_key)
113
+ returned_dict[key] = val
114
+ return transit_types.frozendict(returned_dict)
115
+
116
+ # Each element must be decoded exactly once, in order, to keep
117
+ # the cache in step with the writer.
118
+ decoded = self._decode(node[0], cache, as_map_key)
119
+ if isinstance(decoded, Tag):
120
+ return self.decode_tag(decoded.tag,
121
+ self._decode(node[1], cache, as_map_key))
122
+ return (decoded,) + tuple(self._decode(x, cache, as_map_key)
123
+ for x in node[1:])
124
+ return ()
125
+
126
+ def decode_string(self, string, cache, as_map_key):
127
+ """Decode a string - arguments follow the same convention as the
128
+ top-level 'decode' function.
129
+ """
130
+ return self.parse_string(cache.decode(string, as_map_key),
131
+ cache, as_map_key)
132
+
133
+ def decode_tag(self, tag, rep):
134
+ decoder = self.decoders.get(tag, None)
135
+ if decoder:
136
+ return decoder.from_rep(rep)
137
+ else:
138
+ return self.options["default_decoder"].from_rep(tag, rep)
139
+
140
+ def decode_hash(self, hash, cache, as_map_key):
141
+ if len(hash) != 1:
142
+ h = {}
143
+ for k, v in hash.items():
144
+ # crude/verbose implementation, but this is only version that
145
+ # plays nice w/cache for both msgpack and json thus far.
146
+ # -- e.g., we have to specify encode/decode order for key/val
147
+ # -- explicitly, all implicit ordering has broken in corner
148
+ # -- cases, thus these extraneous seeming assignments
149
+ key = self._decode(k, cache, True)
150
+ val = self._decode(v, cache, False)
151
+ h[key] = val
152
+ return transit_types.frozendict(h)
153
+ else:
154
+ key = list(hash)[0]
155
+ value = hash[key]
156
+ key = self._decode(key, cache, True)
157
+ if isinstance(key, Tag):
158
+ return self.decode_tag(key.tag,
159
+ self._decode(value, cache, as_map_key))
160
+ return transit_types.frozendict({key: self._decode(value, cache, False)})
161
+
162
+ def parse_string(self, string, cache, as_map_key):
163
+ if string.startswith(ESC):
164
+ m = string[1]
165
+ if m in self.decoders:
166
+ return self.decoders[m].from_rep(string[2:])
167
+ elif m == ESC or m == SUB or m == RES:
168
+ return string[1:]
169
+ elif m == "#":
170
+ return Tag(string[2:])
171
+ else:
172
+ return self.options["default_decoder"].from_rep(string[1],
173
+ string[2:])
174
+ return string
175
+
176
+ def register(self, key_or_tag, obj):
177
+ """Register a custom Transit tag and new parsing function with the
178
+ decoder. Also, you can optionally set the 'default_decoder' with
179
+ this function. Your new tag and parse/decode function will be added
180
+ to the interal dictionary of decoders for this Decoder object.
181
+ """
182
+ if key_or_tag == "default_decoder":
183
+ self.options["default_decoder"] = obj
184
+ else:
185
+ self.decoders[key_or_tag] = obj
transit/helpers.py ADDED
@@ -0,0 +1,41 @@
1
+ ## Copyright 2014 Cognitect. All Rights Reserved.
2
+ ## Copyright 2026 Vendekagon Labs LLC.
3
+ ##
4
+ ## Licensed under the Apache License, Version 2.0 (the "License");
5
+ ## you may not use this file except in compliance with the License.
6
+ ## You may obtain a copy of the License at
7
+ ##
8
+ ## http://www.apache.org/licenses/LICENSE-2.0
9
+ ##
10
+ ## Unless required by applicable law or agreed to in writing, software
11
+ ## distributed under the License is distributed on an "AS-IS" BASIS,
12
+ ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ ## See the License for the specific language governing permissions and
14
+ ## limitations under the License.
15
+
16
+ import itertools
17
+
18
+
19
+ def mapcat(f, i):
20
+ return itertools.chain.from_iterable(map(f, i))
21
+
22
+
23
+ def pairs(i):
24
+ return zip(*[iter(i)] * 2)
25
+
26
+
27
+ cycle = itertools.cycle
28
+
29
+
30
+ def take(n, i):
31
+ return itertools.islice(i, 0, n)
32
+
33
+
34
+ def require_msgpack():
35
+ """Import msgpack, which is only needed for the msgpack protocol."""
36
+ try:
37
+ import msgpack
38
+ except ImportError as e:
39
+ raise ImportError("The msgpack protocol requires the msgpack package; "
40
+ "install it with: pip install 'transit-python[msgpack]'") from e
41
+ return msgpack
@@ -0,0 +1,183 @@
1
+ ## Copyright 2014 Cognitect. All Rights Reserved.
2
+ ## Copyright 2026 Vendekagon Labs LLC.
3
+ ##
4
+ ## Licensed under the Apache License, Version 2.0 (the "License");
5
+ ## you may not use this file except in compliance with the License.
6
+ ## You may obtain a copy of the License at
7
+ ##
8
+ ## http://www.apache.org/licenses/LICENSE-2.0
9
+ ##
10
+ ## Unless required by applicable law or agreed to in writing, software
11
+ ## distributed under the License is distributed on an "AS-IS" BASIS,
12
+ ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ ## See the License for the specific language governing permissions and
14
+ ## limitations under the License.
15
+
16
+ import datetime
17
+ import re
18
+ import uuid
19
+ from decimal import Decimal
20
+
21
+ from transit import transit_types
22
+ from transit.helpers import pairs
23
+
24
+ ## Read handlers are used by the decoder when parsing/reading in Transit
25
+ ## data and returning Python objects
26
+
27
+ EPOCH = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)
28
+
29
+ _RFC3339 = re.compile(r"(\d{4}-\d\d-\d\d)[Tt ](\d\d:\d\d:\d\d)(?:\.(\d+))?"
30
+ r"([Zz]|[+-]\d\d:\d\d)?$")
31
+
32
+
33
+ def parse_rfc3339(s):
34
+ """Parse an RFC 3339 timestamp into a UTC datetime, to the millisecond
35
+ (transit times are points in time, with millisecond precision, as they
36
+ are for the other transit implementations).
37
+
38
+ Normalizes what datetime.fromisoformat can't handle on every supported
39
+ Python ("Z", fractional seconds that aren't 3 or 6 digits). A missing
40
+ offset is taken to be UTC.
41
+ """
42
+ m = _RFC3339.match(s)
43
+ if not m:
44
+ d = datetime.datetime.fromisoformat(s)
45
+ else:
46
+ date, time, frac, offset = m.groups()
47
+ if frac:
48
+ time += "." + frac[:6].ljust(6, "0")
49
+ if offset is None or offset in "Zz":
50
+ offset = "+00:00"
51
+ d = datetime.datetime.fromisoformat(date + "T" + time + offset)
52
+ if d.tzinfo is None:
53
+ d = d.replace(tzinfo=datetime.timezone.utc)
54
+ d = d.astimezone(datetime.timezone.utc)
55
+ return d.replace(microsecond=d.microsecond // 1000 * 1000)
56
+
57
+
58
+ class DefaultHandler:
59
+ @staticmethod
60
+ def from_rep(t, v):
61
+ return transit_types.TaggedValue(t, v)
62
+
63
+
64
+ class NoneHandler:
65
+ @staticmethod
66
+ def from_rep(_):
67
+ return None
68
+
69
+
70
+ class KeywordHandler:
71
+ @staticmethod
72
+ def from_rep(v):
73
+ return transit_types.Keyword(v)
74
+
75
+
76
+ class SymbolHandler:
77
+ @staticmethod
78
+ def from_rep(v):
79
+ return transit_types.Symbol(v)
80
+
81
+
82
+ class BigDecimalHandler:
83
+ @staticmethod
84
+ def from_rep(v):
85
+ return Decimal(v)
86
+
87
+
88
+ class BooleanHandler:
89
+ @staticmethod
90
+ def from_rep(x):
91
+ return transit_types.true if x == "t" else transit_types.false
92
+
93
+
94
+ class IntHandler:
95
+ @staticmethod
96
+ def from_rep(v):
97
+ return int(v)
98
+
99
+
100
+ class FloatHandler:
101
+ @staticmethod
102
+ def from_rep(v):
103
+ return float(v)
104
+
105
+
106
+ class UuidHandler:
107
+ @staticmethod
108
+ def from_rep(u):
109
+ """Given a string, or a pair of signed 64 bit ints (most significant
110
+ first), return a UUID object."""
111
+ if isinstance(u, str):
112
+ return uuid.UUID(u)
113
+ mask = (1 << 64) - 1
114
+ return uuid.UUID(int=(u[0] & mask) << 64 | (u[1] & mask))
115
+
116
+
117
+ class UriHandler:
118
+ @staticmethod
119
+ def from_rep(u):
120
+ return transit_types.URI(u)
121
+
122
+
123
+ class DateHandler:
124
+ @staticmethod
125
+ def from_rep(d):
126
+ if isinstance(d, int):
127
+ return DateHandler._convert_timestamp(d)
128
+ if "T" in d:
129
+ return parse_rfc3339(d)
130
+ return DateHandler._convert_timestamp(int(d))
131
+
132
+ @staticmethod
133
+ def _convert_timestamp(ms):
134
+ """Given a timestamp in ms, return a DateTime object."""
135
+ return EPOCH + datetime.timedelta(milliseconds=ms)
136
+
137
+
138
+ class BigIntegerHandler:
139
+ @staticmethod
140
+ def from_rep(d):
141
+ return int(d)
142
+
143
+
144
+ class LinkHandler:
145
+ @staticmethod
146
+ def from_rep(l):
147
+ return transit_types.Link(**l)
148
+
149
+
150
+ class ListHandler:
151
+ @staticmethod
152
+ def from_rep(l):
153
+ return l
154
+
155
+
156
+ class SetHandler:
157
+ @staticmethod
158
+ def from_rep(s):
159
+ return frozenset(s)
160
+
161
+
162
+ class CmapHandler:
163
+ @staticmethod
164
+ def from_rep(cmap):
165
+ return transit_types.frozendict(pairs(cmap))
166
+
167
+
168
+ class IdentityHandler:
169
+ @staticmethod
170
+ def from_rep(i):
171
+ return i
172
+
173
+
174
+ class SpecialNumbersHandler:
175
+ @staticmethod
176
+ def from_rep(z):
177
+ if z == 'NaN':
178
+ return float('Nan')
179
+ if z == 'INF':
180
+ return float('Inf')
181
+ if z == '-INF':
182
+ return float('-Inf')
183
+ raise ValueError("Don't know how to handle: " + str(z) + " as \"z\"")
transit/reader.py ADDED
@@ -0,0 +1,137 @@
1
+ ## Copyright 2014 Cognitect. All Rights Reserved.
2
+ ## Copyright 2026 Vendekagon Labs LLC.
3
+ ##
4
+ ## Licensed under the Apache License, Version 2.0 (the "License");
5
+ ## you may not use this file except in compliance with the License.
6
+ ## You may obtain a copy of the License at
7
+ ##
8
+ ## http://www.apache.org/licenses/LICENSE-2.0
9
+ ##
10
+ ## Unless required by applicable law or agreed to in writing, software
11
+ ## distributed under the License is distributed on an "AS-IS" BASIS,
12
+ ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ ## See the License for the specific language governing permissions and
14
+ ## limitations under the License.
15
+
16
+ import json
17
+
18
+ from transit import sosjson
19
+ from transit._accel import FORMATS, native
20
+ from transit.decoder import Decoder
21
+ from transit.helpers import require_msgpack
22
+
23
+
24
+ class Reader:
25
+ """The top-level object for reading in Transit data and converting it to
26
+ Python objects. During initialization, you must specify the protocol used
27
+ for unmarshalling the data- json or msgpack. The msgpack protocol requires
28
+ the msgpack package (pip install 'transit-python[msgpack]').
29
+ """
30
+ def __init__(self, protocol="json"):
31
+ self.protocol = protocol
32
+ self.customized = False
33
+ if protocol in ("json", "json_verbose"):
34
+ self.reader = JsonUnmarshaler()
35
+ elif protocol == "msgpack":
36
+ try:
37
+ self.reader = MsgPackUnmarshaler()
38
+ self.unpacker = self.reader.unpacker
39
+ except ImportError:
40
+ # the native extension reads msgpack without the package
41
+ if native is None:
42
+ raise
43
+ self.reader = None
44
+ else:
45
+ raise ValueError("'" + protocol + "' is not a supported. " +
46
+ "Protocol must be:" +
47
+ "'json', 'json_verbose', or 'msgpack'.")
48
+
49
+ def read(self, stream):
50
+ """Given a readable file descriptor object (something `load`able by
51
+ msgpack or json), read the data, and return the Python representation
52
+ of the contents. One-shot reader.
53
+ """
54
+ if native is not None and not self.customized:
55
+ return native.loads(stream.read(), FORMATS[self.protocol])
56
+ return self.reader.load(stream)
57
+
58
+ def register(self, key_or_tag, f_val):
59
+ """Register a custom transit tag and decoder/parser function for use
60
+ during reads.
61
+ """
62
+ self.customized = True
63
+ self.reader.decoder.register(key_or_tag, f_val)
64
+
65
+ def readeach(self, stream, **kwargs):
66
+ """Read each object from stream as it becomes available, as a
67
+ generator. Stops at the end of the stream.
68
+
69
+ Data is read from stream as it arrives rather than waiting for a full
70
+ buffer, so this works over pipes and sockets. For text streams wrapping
71
+ a binary buffer (like sys.stdin), the underlying buffer is read.
72
+
73
+ For msgpack, stream may be None, in which case the objects are taken
74
+ from data fed to the `unpacker` property with `unpacker.feed()`.
75
+ """
76
+ if native is not None and not self.customized and stream is not None:
77
+ yield from self._native_readeach(stream)
78
+ return
79
+ if self.reader is None:
80
+ require_msgpack()
81
+ for o in self.reader.loadeach(stream):
82
+ yield o
83
+
84
+
85
+ def _native_readeach(self, stream):
86
+ s = native.stream_new(FORMATS[self.protocol])
87
+ for chunk in sosjson.chunks_raw(stream):
88
+ native.stream_feed(s, chunk)
89
+ while True:
90
+ found, value = native.stream_read(s)
91
+ if not found:
92
+ break
93
+ yield value
94
+ native.stream_end(s)
95
+ while True:
96
+ found, value = native.stream_read(s)
97
+ if not found:
98
+ return
99
+ yield value
100
+
101
+
102
+ class JsonUnmarshaler:
103
+ """The top-level Unmarshaler used by the Reader for JSON payloads. While
104
+ you may use this directly, it is strongly discouraged.
105
+ """
106
+ def __init__(self):
107
+ self.decoder = Decoder()
108
+
109
+ def load(self, stream):
110
+ return self.decoder.decode(json.load(stream))
111
+
112
+ def loadeach(self, stream):
113
+ for o in sosjson.items(stream):
114
+ yield self.decoder.decode(o)
115
+
116
+
117
+ class MsgPackUnmarshaler:
118
+ """The top-level Unmarshaler used by the Reader for MsgPack payloads.
119
+ While you may use this directly, it is strongly discouraged.
120
+ """
121
+ def __init__(self):
122
+ self.msgpack = require_msgpack()
123
+ self.decoder = Decoder()
124
+ self.unpacker = self.msgpack.Unpacker(strict_map_key=False)
125
+
126
+ def load(self, stream):
127
+ return self.decoder.decode(self.msgpack.unpack(stream, strict_map_key=False))
128
+
129
+ def loadeach(self, stream):
130
+ for o in self.unpacker:
131
+ yield self.decoder.decode(o)
132
+ if stream is None:
133
+ return
134
+ for data in sosjson.chunks_raw(stream):
135
+ self.unpacker.feed(data)
136
+ for o in self.unpacker:
137
+ yield self.decoder.decode(o)