Skip to content

Commit d53175d

Browse files
committed
Adding support for not passing a content handler.
Details: To make it closer to the yajl implementation where setting of callbacks is optional. This is useful when implementing json_verify such that it will be much faster if no callbacks are called.
1 parent dae845a commit d53175d

File tree

2 files changed

+41
-24
lines changed

2 files changed

+41
-24
lines changed

tests/test_yajl.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from yajl_test_lib import *
1+
from yajl_test_lib import *
22

33
class BaseContentHandler(yajl.YajlContentHandler):
44
def yajl_null(self, ctx):
@@ -89,7 +89,7 @@ def test_allCallbacksExceptNumber(self):
8989
"Called self.content_handler.yajl_end_array(None)\n"
9090
"Called self.content_handler.yajl_end_map(None)\n"
9191
)
92-
92+
9393
def test_largestNumberAcceptableInIntegerCallback(self):
9494
good_json = StringIO('[%s]' %(sys.maxint))
9595
bad_json = StringIO('[%s]' %(sys.maxint + 1))
@@ -129,3 +129,14 @@ def test_bufSizeLessThanZeroRaisesException(self):
129129
self.failUnlessRaises(
130130
yajl.YajlConfigError,
131131
yajl.YajlParser, self.content_handler, buf_siz=buf_siz)
132+
133+
def test_allowsNoCallbacks(self):
134+
parser = yajl.YajlParser()
135+
parser.parse(self.basic_json)
136+
137+
def test_raisesExceptionOnInvalidJson(self):
138+
parser = yajl.YajlParser()
139+
invalid_json = StringIO('{ "a": }')
140+
self.failUnlessRaises(
141+
yajl.YajlError,
142+
parser.parse, invalid_json)

yajl/yajl_parse.py

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class YajlParser(object):
124124
'''
125125
A class that utilizes the Yajl C Library
126126
'''
127-
def __init__(self, content_handler, allow_comments=True, check_utf8=True, buf_siz=65536):
127+
def __init__(self, content_handler=None, allow_comments=True, check_utf8=True, buf_siz=65536):
128128
'''
129129
`content_handler` an instance of a subclass of YajlContentHandler
130130
`allow_comments` specifies whether comments are allowed in the document
@@ -169,28 +169,31 @@ def dispatch(func, *args, **kwargs):
169169
self._exc_info = sys.exc_info()
170170
return 0
171171

172-
callbacks = [
173-
yajl_null, yajl_boolean, yajl_integer, yajl_double,
174-
yajl_number, yajl_string,
175-
yajl_start_map, yajl_map_key, yajl_end_map,
176-
yajl_start_array, yajl_end_array,
177-
]
178-
# cannot have both number and integer|double
179-
if hasattr(content_handler, 'yajl_number'):
180-
# if yajl_number is available, it takes precedence
181-
callbacks[2] = callbacks[3] = 0
172+
if content_handler is None:
173+
self.callbacks = None
182174
else:
183-
callbacks[4] = 0
184-
# cast the funcs to C-types
185-
callbacks = [
186-
c_func(callback)
187-
for c_func, callback in zip(c_funcs, callbacks)
188-
]
175+
callbacks = [
176+
yajl_null, yajl_boolean, yajl_integer, yajl_double,
177+
yajl_number, yajl_string,
178+
yajl_start_map, yajl_map_key, yajl_end_map,
179+
yajl_start_array, yajl_end_array,
180+
]
181+
# cannot have both number and integer|double
182+
if hasattr(content_handler, 'yajl_number'):
183+
# if yajl_number is available, it takes precedence
184+
callbacks[2] = callbacks[3] = 0
185+
else:
186+
callbacks[4] = 0
187+
# cast the funcs to C-types
188+
callbacks = [
189+
c_func(callback)
190+
for c_func, callback in zip(c_funcs, callbacks)
191+
]
192+
self.callbacks = byref(yajl_callbacks(*callbacks))
189193

190194
# set self's vars
191195
self.buf_siz = buf_siz
192196
self.cfg = yajl_parser_config(allow_comments, check_utf8)
193-
self.callbacks = yajl_callbacks(*callbacks)
194197
self.content_handler = content_handler
195198

196199
def parse(self, f=sys.stdin, ctx=None):
@@ -205,16 +208,18 @@ def parse(self, f=sys.stdin, ctx=None):
205208
returns 0 should set internal variables to denote
206209
why they cancelled the parsing.
207210
'''
208-
self.content_handler.parse_start()
209-
hand = yajl.yajl_alloc( byref(self.callbacks), byref(self.cfg), None, ctx)
211+
if self.content_handler:
212+
self.content_handler.parse_start()
213+
hand = yajl.yajl_alloc(self.callbacks, byref(self.cfg), None, ctx)
210214
try:
211215
while 1:
212216
fileData = f.read(self.buf_siz)
213217
if not fileData:
214218
stat = yajl.yajl_parse_complete(hand)
215219
else:
216220
stat = yajl.yajl_parse(hand, fileData, len(fileData))
217-
self.content_handler.parse_buf()
221+
if self.content_handler:
222+
self.content_handler.parse_buf()
218223
if stat not in (yajl_status_ok.value,
219224
yajl_status_insufficient_data.value):
220225
if stat == yajl_status_client_canceled.value:
@@ -230,7 +235,8 @@ def parse(self, f=sys.stdin, ctx=None):
230235
hand, 1, fileData, len(fileData))
231236
raise YajlError(error)
232237
if not fileData:
233-
self.content_handler.parse_complete()
238+
if self.content_handler:
239+
self.content_handler.parse_complete()
234240
break
235241
finally:
236242
yajl.yajl_free(hand)

0 commit comments

Comments
 (0)