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.
Files changed (63) hide show
  1. EGG-INFO/PKG-INFO +1 -1
  2. EGG-INFO/SOURCES.txt +16 -1
  3. EGG-INFO/requires.txt +1 -1
  4. EGG-INFO/top_level.txt +1 -0
  5. scratch/__init__.py +1 -0
  6. scratch/__init__.pyc +0 -0
  7. scratch/bools.py +15 -0
  8. scratch/bools.pyc +0 -0
  9. scratch/cache-inconsistent.py +10 -0
  10. scratch/cache-inconsistent.pyc +0 -0
  11. scratch/dt.py +7 -0
  12. scratch/dt.pyc +0 -0
  13. scratch/emptyset.py +19 -0
  14. scratch/emptyset.pyc +0 -0
  15. scratch/frozendict.py +14 -0
  16. scratch/frozendict.pyc +0 -0
  17. scratch/int_issue.py +10 -0
  18. scratch/int_issue.pyc +0 -0
  19. scratch/issue.py +44 -0
  20. scratch/issue.pyc +0 -0
  21. scratch/mp_test.py +22 -0
  22. scratch/mp_test.pyc +0 -0
  23. scratch/msgpack_issue.py +19 -0
  24. scratch/msgpack_issue.pyc +0 -0
  25. scratch/newline.py +14 -0
  26. scratch/newline.pyc +0 -0
  27. scratch/streamit.py +56 -0
  28. scratch/streamit.pyc +0 -0
  29. scratch/testmprt.py +15 -0
  30. scratch/testmprt.pyc +0 -0
  31. scratch/unicodeme.py +21 -0
  32. scratch/unicodeme.pyc +0 -0
  33. tests/__init__.pyc +0 -0
  34. tests/exemplars_test.py +16 -11
  35. tests/exemplars_test.pyc +0 -0
  36. tests/helpers.pyc +0 -0
  37. tests/regression.py +80 -0
  38. tests/regression.pyc +0 -0
  39. tests/seattle_benchmark.pyc +0 -0
  40. transit/__init__.pyc +0 -0
  41. transit/class_hash.py +2 -2
  42. transit/class_hash.pyc +0 -0
  43. transit/constants.pyc +0 -0
  44. transit/decoder.py +33 -20
  45. transit/decoder.pyc +0 -0
  46. transit/helpers.pyc +0 -0
  47. transit/read_handlers.py +13 -3
  48. transit/read_handlers.pyc +0 -0
  49. transit/reader.py +34 -10
  50. transit/reader.pyc +0 -0
  51. transit/rolling_cache.py +3 -6
  52. transit/rolling_cache.pyc +0 -0
  53. transit/sosjson.py +74 -0
  54. transit/sosjson.pyc +0 -0
  55. transit/transit_types.py +33 -7
  56. transit/transit_types.pyc +0 -0
  57. transit/write_handlers.py +18 -11
  58. transit/write_handlers.pyc +0 -0
  59. transit/writer.py +83 -60
  60. transit/writer.pyc +0 -0
  61. tests/transit_types_test.py +0 -24
  62. tests/transit_types_test.pyc +0 -0
  63. /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
- """ The Decoder is the lowest level entry point for parsing, decoding, and
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
- """ Given a node of data (any supported decodeable obj - string, dict,
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
- else:
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
- """ Special case decodes map-as-array.
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
- decoded = self._decode(node[0], cache, as_map_key)
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
- # return {self._decode(k, cache, True):
108
- # self._decode(v, cache, as_map_key)
109
- # for k,v in pairs(node[1:])}
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
- """ Decode a string - arguments follow the same convention as the
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
- h[self._decode(k, cache, True)] = self._decode(v, cache, False)
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
- """ Register a custom Transit tag and new parsing function with the
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
- """ Given a string, return a UUID object"""
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
- """ Given a timestamp in ms, return a DateTime object"""
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
- """ The top-level object for reading in Transit data and converting it to
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
- """ Given a readable file descriptor object (something `load`able by
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
- """ Register a custom transit tag and decoder/parser function for use
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
- """ The top-level Unmarshaler used by the Reader for JSON payloads. While
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
- """ The top-level Unmarshaler used by the Reader for MsgPacke payloads.
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
- """ This is the internal cache used by python-transit for cacheing and
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
- # (1) should we use list or dict on read side? ##- probably dictionary is best for lookup by code.
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 b and 't' or 'f'
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
- i = u.int
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 long((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 1e3)
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
-
Binary file