transit-python 0.8.174-__py2.7.egg → 0.8.240__py2.7.egg
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.
- EGG-INFO/PKG-INFO +1 -1
- EGG-INFO/SOURCES.txt +16 -1
- EGG-INFO/requires.txt +1 -1
- EGG-INFO/top_level.txt +1 -0
- scratch/__init__.py +1 -0
- scratch/__init__.pyc +0 -0
- scratch/bools.py +15 -0
- scratch/bools.pyc +0 -0
- scratch/cache-inconsistent.py +10 -0
- scratch/cache-inconsistent.pyc +0 -0
- scratch/dt.py +7 -0
- scratch/dt.pyc +0 -0
- scratch/emptyset.py +19 -0
- scratch/emptyset.pyc +0 -0
- scratch/frozendict.py +14 -0
- scratch/frozendict.pyc +0 -0
- scratch/int_issue.py +10 -0
- scratch/int_issue.pyc +0 -0
- scratch/issue.py +44 -0
- scratch/issue.pyc +0 -0
- scratch/mp_test.py +22 -0
- scratch/mp_test.pyc +0 -0
- scratch/msgpack_issue.py +19 -0
- scratch/msgpack_issue.pyc +0 -0
- scratch/newline.py +14 -0
- scratch/newline.pyc +0 -0
- scratch/streamit.py +56 -0
- scratch/streamit.pyc +0 -0
- scratch/testmprt.py +15 -0
- scratch/testmprt.pyc +0 -0
- scratch/unicodeme.py +21 -0
- scratch/unicodeme.pyc +0 -0
- tests/__init__.pyc +0 -0
- tests/exemplars_test.py +16 -11
- tests/exemplars_test.pyc +0 -0
- tests/helpers.pyc +0 -0
- tests/regression.py +80 -0
- tests/regression.pyc +0 -0
- tests/seattle_benchmark.pyc +0 -0
- transit/__init__.pyc +0 -0
- transit/class_hash.py +2 -2
- transit/class_hash.pyc +0 -0
- transit/constants.pyc +0 -0
- transit/decoder.py +33 -20
- transit/decoder.pyc +0 -0
- transit/helpers.pyc +0 -0
- transit/read_handlers.py +13 -3
- transit/read_handlers.pyc +0 -0
- transit/reader.py +34 -10
- transit/reader.pyc +0 -0
- transit/rolling_cache.py +3 -6
- transit/rolling_cache.pyc +0 -0
- transit/sosjson.py +74 -0
- transit/sosjson.pyc +0 -0
- transit/transit_types.py +33 -7
- transit/transit_types.pyc +0 -0
- transit/write_handlers.py +18 -11
- transit/write_handlers.pyc +0 -0
- transit/writer.py +83 -60
- transit/writer.pyc +0 -0
- tests/transit_types_test.py +0 -24
- tests/transit_types_test.pyc +0 -0
- /EGG-INFO/{not-zip-safe → zip-safe} +0 -0
transit/decoder.py
CHANGED
|
@@ -18,6 +18,7 @@ from collections import OrderedDict
|
|
|
18
18
|
from helpers import pairs
|
|
19
19
|
import read_handlers as rh
|
|
20
20
|
from rolling_cache import RollingCache, is_cacheable, is_cache_key
|
|
21
|
+
from transit_types import true, false
|
|
21
22
|
|
|
22
23
|
class Tag(object):
|
|
23
24
|
def __init__(self, tag):
|
|
@@ -34,6 +35,7 @@ default_options = {"decoders": {"_": rh.NoneHandler,
|
|
|
34
35
|
"t": rh.DateHandler,
|
|
35
36
|
"m": rh.DateHandler,
|
|
36
37
|
"n": rh.BigIntegerHandler,
|
|
38
|
+
"z": rh.SpecialNumbersHandler,
|
|
37
39
|
"link": rh.LinkHandler,
|
|
38
40
|
"list": rh.ListHandler,
|
|
39
41
|
"set": rh.SetHandler,
|
|
@@ -47,7 +49,7 @@ ground_decoders = {"_": rh.NoneHandler,
|
|
|
47
49
|
"'": rh.IdentityHandler}
|
|
48
50
|
|
|
49
51
|
class Decoder(object):
|
|
50
|
-
"""
|
|
52
|
+
"""The Decoder is the lowest level entry point for parsing, decoding, and
|
|
51
53
|
fully converting Transit data into Python objects.
|
|
52
54
|
|
|
53
55
|
During the creation of a Decoder object, you can specify custom options
|
|
@@ -55,7 +57,8 @@ class Decoder(object):
|
|
|
55
57
|
can specify your own decoders and override many of the built in decoders,
|
|
56
58
|
some decoders are silently enforced and cannot be overriden. These are
|
|
57
59
|
known as Ground Decoders, and are needed to maintain bottom-tier
|
|
58
|
-
compatibility.
|
|
60
|
+
compatibility.
|
|
61
|
+
"""
|
|
59
62
|
|
|
60
63
|
def __init__(self, options={}):
|
|
61
64
|
self.options = default_options.copy()
|
|
@@ -66,11 +69,12 @@ class Decoder(object):
|
|
|
66
69
|
self.decoders.update(ground_decoders)
|
|
67
70
|
|
|
68
71
|
def decode(self, node, cache=None, as_map_key=False):
|
|
69
|
-
"""
|
|
72
|
+
"""Given a node of data (any supported decodeable obj - string, dict,
|
|
70
73
|
list), return the decoded object. Optionally set the current decode
|
|
71
74
|
cache [None]. If None, a new RollingCache is instantiated and used.
|
|
72
75
|
You may also hit to the decoder that this node is to be treated as a
|
|
73
|
-
map key [False]. This is used internally.
|
|
76
|
+
map key [False]. This is used internally.
|
|
77
|
+
"""
|
|
74
78
|
if not cache:
|
|
75
79
|
cache = RollingCache()
|
|
76
80
|
return self._decode(node, cache, as_map_key)
|
|
@@ -85,18 +89,19 @@ class Decoder(object):
|
|
|
85
89
|
return self.decode_list(node, cache, as_map_key)
|
|
86
90
|
elif tp is str:
|
|
87
91
|
return self.decode_string(unicode(node, "utf-8"), cache, as_map_key)
|
|
88
|
-
|
|
89
|
-
return node
|
|
92
|
+
elif tp is bool:
|
|
93
|
+
return true if node else false
|
|
94
|
+
return node
|
|
90
95
|
|
|
91
96
|
def decode_list(self, node, cache, as_map_key):
|
|
92
|
-
"""
|
|
97
|
+
"""Special case decodes map-as-array.
|
|
93
98
|
Otherwise lists are treated as Python lists.
|
|
94
99
|
|
|
95
100
|
Arguments follow the same convention as the top-level 'decode'
|
|
96
|
-
function
|
|
101
|
+
function.
|
|
102
|
+
"""
|
|
97
103
|
if node:
|
|
98
|
-
|
|
99
|
-
if decoded == MAP_AS_ARR:
|
|
104
|
+
if node[0] == MAP_AS_ARR:
|
|
100
105
|
# key must be decoded before value for caching to work.
|
|
101
106
|
returned_dict = {}
|
|
102
107
|
for k,v in pairs(node[1:]):
|
|
@@ -104,16 +109,16 @@ class Decoder(object):
|
|
|
104
109
|
val = self._decode(v, cache, as_map_key)
|
|
105
110
|
returned_dict[key] = val
|
|
106
111
|
return returned_dict
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
elif isinstance(decoded, Tag):
|
|
112
|
+
|
|
113
|
+
decoded = self._decode(node[0], cache, as_map_key)
|
|
114
|
+
if isinstance(decoded, Tag):
|
|
111
115
|
return self.decode_tag(decoded.tag, self._decode(node[1], cache, as_map_key))
|
|
112
116
|
return tuple(self._decode(x, cache, as_map_key) for x in node)
|
|
113
117
|
|
|
114
118
|
def decode_string(self, string, cache, as_map_key):
|
|
115
|
-
"""
|
|
116
|
-
top-level 'decode' function
|
|
119
|
+
"""Decode a string - arguments follow the same convention as the
|
|
120
|
+
top-level 'decode' function.
|
|
121
|
+
"""
|
|
117
122
|
if is_cache_key(string):
|
|
118
123
|
return self.parse_string(cache.decode(string, as_map_key), cache, as_map_key)
|
|
119
124
|
if is_cacheable(string, as_map_key):
|
|
@@ -131,7 +136,14 @@ class Decoder(object):
|
|
|
131
136
|
if len(hash) != 1:
|
|
132
137
|
h = {}
|
|
133
138
|
for k, v in hash.items():
|
|
134
|
-
|
|
139
|
+
# crude/verbose implementation, but this is only version that
|
|
140
|
+
# plays nice w/cache for both msgpack and json thus far.
|
|
141
|
+
# -- e.g., we have to specify encode/decode order for key/val
|
|
142
|
+
# -- explicitly, all implicit ordering has broken in corner
|
|
143
|
+
# -- cases, thus these extraneous seeming assignments
|
|
144
|
+
key = self._decode(k, cache, True)
|
|
145
|
+
val = self._decode(v, cache, False)
|
|
146
|
+
h[key] = val
|
|
135
147
|
return transit_types.frozendict(h)
|
|
136
148
|
else:
|
|
137
149
|
key,value = hash.items()[0]
|
|
@@ -139,7 +151,7 @@ class Decoder(object):
|
|
|
139
151
|
if isinstance(key, Tag):
|
|
140
152
|
return self.decode_tag(key.tag, self._decode(value, cache, as_map_key))
|
|
141
153
|
else:
|
|
142
|
-
return {key: self._decode(value, cache, False)}
|
|
154
|
+
return transit_types.frozendict({key: self._decode(value, cache, False)})
|
|
143
155
|
|
|
144
156
|
def parse_string(self, string, cache, as_map_key):
|
|
145
157
|
if string.startswith(ESC):
|
|
@@ -155,10 +167,11 @@ class Decoder(object):
|
|
|
155
167
|
return string
|
|
156
168
|
|
|
157
169
|
def register(self, key_or_tag, obj):
|
|
158
|
-
"""
|
|
170
|
+
"""Register a custom Transit tag and new parsing function with the
|
|
159
171
|
decoder. Also, you can optionally set the 'default_decoder' with
|
|
160
172
|
this function. Your new tag and parse/decode function will be added
|
|
161
|
-
to the interal dictionary of decoders for this Decoder object
|
|
173
|
+
to the interal dictionary of decoders for this Decoder object.
|
|
174
|
+
"""
|
|
162
175
|
if key_or_tag == "default_decoder":
|
|
163
176
|
self.options["default_decoder"] = obj
|
|
164
177
|
else:
|
transit/decoder.pyc
CHANGED
|
Binary file
|
transit/helpers.pyc
CHANGED
|
Binary file
|
transit/read_handlers.py
CHANGED
|
@@ -47,7 +47,7 @@ class SymbolHandler(object):
|
|
|
47
47
|
class BooleanHandler(object):
|
|
48
48
|
@staticmethod
|
|
49
49
|
def from_rep(x):
|
|
50
|
-
return x == "t"
|
|
50
|
+
return transit_types.true if x == "t" else transit_types.false
|
|
51
51
|
|
|
52
52
|
class IntHandler(object):
|
|
53
53
|
@staticmethod
|
|
@@ -62,7 +62,7 @@ class FloatHandler(object):
|
|
|
62
62
|
class UuidHandler(object):
|
|
63
63
|
@staticmethod
|
|
64
64
|
def from_rep(u):
|
|
65
|
-
"""
|
|
65
|
+
"""Given a string, return a UUID object."""
|
|
66
66
|
if isinstance(u, basestring):
|
|
67
67
|
return uuid.UUID(u)
|
|
68
68
|
|
|
@@ -87,7 +87,7 @@ class DateHandler(object):
|
|
|
87
87
|
return DateHandler._convert_timestamp(long(d))
|
|
88
88
|
@staticmethod
|
|
89
89
|
def _convert_timestamp(ms):
|
|
90
|
-
"""
|
|
90
|
+
"""Given a timestamp in ms, return a DateTime object."""
|
|
91
91
|
return datetime.datetime.fromtimestamp(ms/1000.0, dateutil.tz.tzutc())
|
|
92
92
|
|
|
93
93
|
class BigIntegerHandler(object):
|
|
@@ -120,3 +120,13 @@ class IdentityHandler(object):
|
|
|
120
120
|
def from_rep(i):
|
|
121
121
|
return i
|
|
122
122
|
|
|
123
|
+
class SpecialNumbersHandler(object):
|
|
124
|
+
@staticmethod
|
|
125
|
+
def from_rep(z):
|
|
126
|
+
if z == 'NaN':
|
|
127
|
+
return float('Nan')
|
|
128
|
+
if z == 'INF':
|
|
129
|
+
return float('Inf')
|
|
130
|
+
if z == '-INF':
|
|
131
|
+
return float('-Inf')
|
|
132
|
+
raise ValueError("Don't know how to handle: " + str(z) + " as \"z\"")
|
transit/read_handlers.pyc
CHANGED
|
Binary file
|
transit/reader.py
CHANGED
|
@@ -13,47 +13,71 @@
|
|
|
13
13
|
## limitations under the License.
|
|
14
14
|
|
|
15
15
|
import json
|
|
16
|
+
import sosjson
|
|
16
17
|
import msgpack
|
|
17
18
|
from decoder import Decoder
|
|
18
19
|
from collections import OrderedDict
|
|
19
20
|
|
|
20
21
|
class Reader(object):
|
|
21
|
-
"""
|
|
22
|
+
"""The top-level object for reading in Transit data and converting it to
|
|
22
23
|
Python objects. During initialization, you must specify the protocol used
|
|
23
|
-
for unmarshalling the data- json or msgpack.
|
|
24
|
+
for unmarshalling the data- json or msgpack.
|
|
25
|
+
"""
|
|
24
26
|
def __init__(self, protocol="json"):
|
|
25
27
|
if protocol in ("json", "json_verbose"):
|
|
26
28
|
self.reader = JsonUnmarshaler()
|
|
27
29
|
else:
|
|
28
30
|
self.reader = MsgPackUnmarshaler()
|
|
31
|
+
self.unpacker = self.reader.unpacker
|
|
29
32
|
|
|
30
33
|
def read(self, stream):
|
|
31
|
-
"""
|
|
34
|
+
"""Given a readable file descriptor object (something `load`able by
|
|
32
35
|
msgpack or json), read the data, and return the Python representation
|
|
33
|
-
of the contents.
|
|
36
|
+
of the contents. One-shot reader.
|
|
37
|
+
"""
|
|
34
38
|
return self.reader.load(stream)
|
|
35
39
|
|
|
36
40
|
def register(self, key_or_tag, f_val):
|
|
37
|
-
"""
|
|
38
|
-
during reads.
|
|
41
|
+
"""Register a custom transit tag and decoder/parser function for use
|
|
42
|
+
during reads.
|
|
43
|
+
"""
|
|
39
44
|
self.reader.decoder.register(key_or_tag, f_val)
|
|
40
45
|
|
|
46
|
+
def readeach(self, stream, **kwargs):
|
|
47
|
+
"""Temporary hook for API while streaming reads are in experimental
|
|
48
|
+
phase. Read each object from stream as available with generator.
|
|
49
|
+
JSON blocks indefinitely waiting on JSON entities to arrive. MsgPack
|
|
50
|
+
requires unpacker property to be fed stream using unpacker.feed()
|
|
51
|
+
method.
|
|
52
|
+
"""
|
|
53
|
+
for o in self.reader.loadeach(stream):
|
|
54
|
+
yield o
|
|
55
|
+
|
|
41
56
|
class JsonUnmarshaler(object):
|
|
42
|
-
"""
|
|
43
|
-
you may use this directly, it is strongly discouraged.
|
|
57
|
+
"""The top-level Unmarshaler used by the Reader for JSON payloads. While
|
|
58
|
+
you may use this directly, it is strongly discouraged.
|
|
59
|
+
"""
|
|
44
60
|
def __init__(self):
|
|
45
61
|
self.decoder = Decoder()
|
|
46
62
|
|
|
47
63
|
def load(self, stream):
|
|
48
64
|
return self.decoder.decode(json.load(stream, object_pairs_hook=OrderedDict))
|
|
49
65
|
|
|
66
|
+
def loadeach(self, stream):
|
|
67
|
+
for o in sosjson.items(stream, object_pairs_hook=OrderedDict):
|
|
68
|
+
yield self.decoder.decode(o)
|
|
50
69
|
|
|
51
70
|
class MsgPackUnmarshaler(object):
|
|
52
|
-
"""
|
|
53
|
-
While you may use this directly, it is strongly discouraged.
|
|
71
|
+
"""The top-level Unmarshaler used by the Reader for MsgPack payloads.
|
|
72
|
+
While you may use this directly, it is strongly discouraged.
|
|
73
|
+
"""
|
|
54
74
|
def __init__(self):
|
|
55
75
|
self.decoder = Decoder()
|
|
76
|
+
self.unpacker = msgpack.Unpacker(object_pairs_hook=OrderedDict)
|
|
56
77
|
|
|
57
78
|
def load(self, stream):
|
|
58
79
|
return self.decoder.decode(msgpack.load(stream, object_pairs_hook=OrderedDict))
|
|
59
80
|
|
|
81
|
+
def loadeach(self, stream):
|
|
82
|
+
for o in self.unpacker:
|
|
83
|
+
yield self.decoder.decode(o)
|
transit/reader.pyc
CHANGED
|
Binary file
|
transit/rolling_cache.py
CHANGED
|
@@ -42,15 +42,12 @@ def is_cacheable(string, as_map_key=False):
|
|
|
42
42
|
or (string[:2] in ["~#", "~$", "~:"]))
|
|
43
43
|
|
|
44
44
|
class RollingCache(object):
|
|
45
|
-
"""
|
|
45
|
+
"""This is the internal cache used by python-transit for cacheing and
|
|
46
46
|
expanding map keys during writing and reading. The cache enables transit
|
|
47
47
|
to minimize the amount of duplicate data sent over the wire, effectively
|
|
48
48
|
compressing down the overall payload size. The cache is not intended to
|
|
49
|
-
be used directly.
|
|
50
|
-
|
|
51
|
-
# dict lookup should be amortized O(1), for list O(n)
|
|
52
|
-
# (2) currently stores value read from the wire, should probably store value after decoding
|
|
53
|
-
# so we don't do multiple decodes. Sped up parsing in ruby by 30%.
|
|
49
|
+
be used directly.
|
|
50
|
+
"""
|
|
54
51
|
def __init__(self):
|
|
55
52
|
self.key_to_value = {}
|
|
56
53
|
self.value_to_key = {}
|
transit/rolling_cache.pyc
CHANGED
|
Binary file
|
transit/sosjson.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
# Simple object streaming in Python - just reads one complete JSON object
|
|
15
|
+
# at a time and returns json.loads of that string.
|
|
16
|
+
|
|
17
|
+
# Ugly implementation at moment
|
|
18
|
+
from copy import copy
|
|
19
|
+
import json
|
|
20
|
+
|
|
21
|
+
SKIP = [" ", "\n", "\t"]
|
|
22
|
+
ESCAPE = "\\"
|
|
23
|
+
|
|
24
|
+
def read_chunk(stream):
|
|
25
|
+
"""Ignore whitespace outside of strings. If we hit a string, read it in
|
|
26
|
+
its entirety.
|
|
27
|
+
"""
|
|
28
|
+
chunk = stream.read(1)
|
|
29
|
+
while chunk in SKIP:
|
|
30
|
+
chunk = stream.read(1)
|
|
31
|
+
if chunk == "\"":
|
|
32
|
+
chunk += stream.read(1)
|
|
33
|
+
while not chunk.endswith("\""):
|
|
34
|
+
if chunk[-1] == ESCAPE:
|
|
35
|
+
chunk += stream.read(2)
|
|
36
|
+
else:
|
|
37
|
+
chunk += stream.read(1)
|
|
38
|
+
return chunk
|
|
39
|
+
|
|
40
|
+
def items(stream, **kwargs):
|
|
41
|
+
"""External facing items. Will return item from stream as available.
|
|
42
|
+
Currently waits in loop waiting for next item. Can pass keywords that
|
|
43
|
+
json.loads accepts (such as object_pairs_hook)
|
|
44
|
+
"""
|
|
45
|
+
for s in yield_json(stream):
|
|
46
|
+
yield json.loads(s, **kwargs)
|
|
47
|
+
|
|
48
|
+
def yield_json(stream):
|
|
49
|
+
"""Uses array and object delimiter counts for balancing.
|
|
50
|
+
"""
|
|
51
|
+
buff = u""
|
|
52
|
+
arr_count = 0
|
|
53
|
+
obj_count = 0
|
|
54
|
+
while True:
|
|
55
|
+
buff += read_chunk(stream)
|
|
56
|
+
|
|
57
|
+
# If we finish parsing all objs or arrays, yield a finished JSON
|
|
58
|
+
# entity.
|
|
59
|
+
if buff.endswith('{'):
|
|
60
|
+
obj_count += 1
|
|
61
|
+
if buff.endswith('['):
|
|
62
|
+
arr_count += 1
|
|
63
|
+
if buff.endswith(']'):
|
|
64
|
+
arr_count -= 1
|
|
65
|
+
if obj_count == arr_count == 0:
|
|
66
|
+
json_item = copy(buff)
|
|
67
|
+
buff = u""
|
|
68
|
+
yield json_item
|
|
69
|
+
if buff.endswith('}'):
|
|
70
|
+
obj_count -= 1
|
|
71
|
+
if obj_count == arr_count == 0:
|
|
72
|
+
json_item = copy(buff)
|
|
73
|
+
buff = u""
|
|
74
|
+
yield json_item
|
transit/sosjson.pyc
ADDED
|
Binary file
|
transit/transit_types.py
CHANGED
|
@@ -141,15 +141,15 @@ class frozendict(Mapping, Hashable):
|
|
|
141
141
|
|
|
142
142
|
class Link(object):
|
|
143
143
|
# Class property constants for rendering types
|
|
144
|
-
LINK = "link"
|
|
145
|
-
IMAGE = "image"
|
|
144
|
+
LINK = u"link"
|
|
145
|
+
IMAGE = u"image"
|
|
146
146
|
|
|
147
147
|
# Class property constants for keywords/obj properties.
|
|
148
|
-
HREF = "href"
|
|
149
|
-
REL = "rel"
|
|
150
|
-
PROMPT = "prompt"
|
|
151
|
-
NAME = "name"
|
|
152
|
-
RENDER = "render"
|
|
148
|
+
HREF = u"href"
|
|
149
|
+
REL = u"rel"
|
|
150
|
+
PROMPT = u"prompt"
|
|
151
|
+
NAME = u"name"
|
|
152
|
+
RENDER = u"render"
|
|
153
153
|
|
|
154
154
|
def __init__(self, href=None, rel=None, name=None, render=None, prompt=None):
|
|
155
155
|
self._dict = frozendict()
|
|
@@ -188,3 +188,29 @@ class Link(object):
|
|
|
188
188
|
@property
|
|
189
189
|
def as_array(self):
|
|
190
190
|
return [self.href, self.rel, self.name, self.render, self.prompt]
|
|
191
|
+
|
|
192
|
+
class Boolean(object):
|
|
193
|
+
"""To allow a separate t/f that won't hash as 1/0. Don't call directly,
|
|
194
|
+
instead use true and false as singleton objects. Can use with type check.
|
|
195
|
+
|
|
196
|
+
Note that the Booleans are for preserving hash/set bools that duplicate 1/0
|
|
197
|
+
and not designed for use in Python outside of logical evaluation (don't treat
|
|
198
|
+
as an int, they're not). You can get a Python bool using bool(x)
|
|
199
|
+
where x is a true or false Boolean.
|
|
200
|
+
"""
|
|
201
|
+
def __init__(self, name):
|
|
202
|
+
self.v = True if name == "true" else False
|
|
203
|
+
self.name = name
|
|
204
|
+
|
|
205
|
+
def __nonzero__(self):
|
|
206
|
+
return self.v
|
|
207
|
+
|
|
208
|
+
def __repr__(self):
|
|
209
|
+
return self.name
|
|
210
|
+
|
|
211
|
+
def __str__(self):
|
|
212
|
+
return self.name
|
|
213
|
+
|
|
214
|
+
# lowercase rep matches java/clojure
|
|
215
|
+
false = Boolean("false")
|
|
216
|
+
true = Boolean("true")
|
transit/transit_types.pyc
CHANGED
|
Binary file
|
transit/write_handlers.py
CHANGED
|
@@ -14,10 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
from constants import *
|
|
16
16
|
from class_hash import ClassDict
|
|
17
|
-
from transit_types import Keyword, Symbol, URI, frozendict, TaggedValue, Link
|
|
17
|
+
from transit_types import Keyword, Symbol, URI, frozendict, TaggedValue, Link, Boolean
|
|
18
18
|
import uuid
|
|
19
19
|
import datetime, time
|
|
20
20
|
from dateutil import tz
|
|
21
|
+
from math import isnan
|
|
22
|
+
import struct
|
|
21
23
|
|
|
22
24
|
## This file contains Write Handlers - all the top-level objects used when
|
|
23
25
|
## writing Transit data. These object must all be immutable and pickleable.
|
|
@@ -69,10 +71,16 @@ class BigIntHandler(object):
|
|
|
69
71
|
|
|
70
72
|
class FloatHandler(object):
|
|
71
73
|
@staticmethod
|
|
72
|
-
def tag(
|
|
73
|
-
return "f"
|
|
74
|
+
def tag(f):
|
|
75
|
+
return "z" if isnan(f) or f in (float('Inf'), float('-Inf')) else "f"
|
|
74
76
|
@staticmethod
|
|
75
77
|
def rep(f):
|
|
78
|
+
if isnan(f):
|
|
79
|
+
return "NaN"
|
|
80
|
+
if f == float('Inf'):
|
|
81
|
+
return "INF"
|
|
82
|
+
if f == float("-Inf"):
|
|
83
|
+
return "-INF"
|
|
76
84
|
return str(f)
|
|
77
85
|
@staticmethod
|
|
78
86
|
def string_rep(f):
|
|
@@ -95,10 +103,10 @@ class BooleanHandler(object):
|
|
|
95
103
|
return '?'
|
|
96
104
|
@staticmethod
|
|
97
105
|
def rep(b):
|
|
98
|
-
return b
|
|
106
|
+
return bool(b)
|
|
99
107
|
@staticmethod
|
|
100
108
|
def string_rep(b):
|
|
101
|
-
return
|
|
109
|
+
return 't' if b else 'f'
|
|
102
110
|
|
|
103
111
|
class ArrayHandler(object):
|
|
104
112
|
@staticmethod
|
|
@@ -145,14 +153,12 @@ class SymbolHandler(object):
|
|
|
145
153
|
return str(s)
|
|
146
154
|
|
|
147
155
|
class UuidHandler(object):
|
|
148
|
-
mask = pow(2, 64) - 1
|
|
149
156
|
@staticmethod
|
|
150
157
|
def tag(_):
|
|
151
158
|
return "u"
|
|
152
159
|
@staticmethod
|
|
153
160
|
def rep(u):
|
|
154
|
-
|
|
155
|
-
return (i >> 64, i & UuidHandler.mask)
|
|
161
|
+
return struct.unpack('>qq', u.bytes)
|
|
156
162
|
@staticmethod
|
|
157
163
|
def string_rep(u):
|
|
158
164
|
return str(u)
|
|
@@ -176,7 +182,7 @@ class DateTimeHandler(object):
|
|
|
176
182
|
@staticmethod
|
|
177
183
|
def rep(d):
|
|
178
184
|
td = d - DateTimeHandler.epoch
|
|
179
|
-
return
|
|
185
|
+
return int((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 1e3)
|
|
180
186
|
@staticmethod
|
|
181
187
|
def verbose_handler():
|
|
182
188
|
return VerboseDateTimeHandler
|
|
@@ -245,12 +251,14 @@ class WriteHandler(ClassDict):
|
|
|
245
251
|
The Handler itself is a dispatch map, that resolves on full type/object
|
|
246
252
|
inheritance.
|
|
247
253
|
|
|
248
|
-
These handlers can be overriden during the creation of a Transit Writer.
|
|
254
|
+
These handlers can be overriden during the creation of a Transit Writer.
|
|
255
|
+
"""
|
|
249
256
|
|
|
250
257
|
def __init__(self):
|
|
251
258
|
super(WriteHandler, self).__init__()
|
|
252
259
|
self[type(None)] = NoneHandler
|
|
253
260
|
self[bool] = BooleanHandler
|
|
261
|
+
self[Boolean] = BooleanHandler
|
|
254
262
|
self[str] = StringHandler
|
|
255
263
|
self[unicode] = StringHandler
|
|
256
264
|
self[list] = ArrayHandler
|
|
@@ -271,4 +279,3 @@ class WriteHandler(ClassDict):
|
|
|
271
279
|
self[frozendict] = MapHandler
|
|
272
280
|
self[TaggedValue] = TaggedValueHandler
|
|
273
281
|
self[Link] = LinkHandler
|
|
274
|
-
|
transit/write_handlers.pyc
CHANGED
|
Binary file
|