Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Yajl-Py 1.0.7 -> full wrapper to Yajl 1.0.7
- Loading branch information
Showing
7 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
Copyright © 2009 | ||
|
||
Hatem Nassrat <nassrat@cs.dal.ca> | ||
|
||
These programs are free software; you can redistribute it | ||
and/or modify it under the terms of the GNU General Public | ||
License as published by the Free Software Foundation; either | ||
version 3 of the License, or (at your option) any later | ||
version. | ||
|
||
These programs are distributed in the hope that it will be | ||
useful, but WITHOUT ANY WARRANTY; without even the implied | ||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
PURPOSE. See the GNU General Public License for more | ||
details. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
======= | ||
yajl-py | ||
======= | ||
|
||
`yajl-py` is a Pure Python wrapper (implemented using | ||
ctypes) to the excellent Yajl (Yet Another JSON Library) C | ||
library. | ||
|
||
Dependencies | ||
------------ | ||
|
||
- python 2.5 (or compatible) | ||
- yajl: http://lloydforge.org/projects/yajl/ | ||
|
||
Install | ||
------- | ||
|
||
From within the current directory run:: | ||
|
||
python setup.py install | ||
|
||
- OR Alternatively - | ||
|
||
easy_install . | ||
|
||
Usage | ||
----- | ||
|
||
The examples directory contains a full featured JSON Parser | ||
built using `yajl` and `yajl-py`. The code also prints some | ||
output to stdout after parsing json from stdin. The printing | ||
is more or less debug messages to show how the parser works. | ||
See `examples/README.rst` for more info. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
To run the sample parser, from within this dir, run:: | ||
|
||
python yajl-test-run.py <doc.json | ||
|
||
the example can also be run from ../ as:: | ||
python example/yajl-test-run.py <doc.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import sys | ||
import yajl_py_example | ||
|
||
if __name__ == "__main__": | ||
raise SystemExit(yajl_py_example.main(sys.argv[1:])) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import sys; sys.path = ['.', '..'] + sys.path | ||
from yajl import * | ||
|
||
# Sample callbacks, which reprint invalid json | ||
# these are examples to show off the yajl parser | ||
|
||
def yajl_null(ctx): | ||
print "null" | ||
return 1 | ||
|
||
def yajl_boolean(ctx, boolVal): | ||
if boolVal: | ||
print "true," | ||
else: | ||
print "false," | ||
return 1 | ||
|
||
def yajl_integer(ctx, integerVal): | ||
print "%s,"%integerVal | ||
return 1 | ||
|
||
def yajl_double(ctx, doubleVal): | ||
print "%s,"%doubleVal | ||
return 1 | ||
|
||
def yajl_number(ctx, stringNum, stringLen): | ||
nstr = string_at(stringNum, stringLen) | ||
if '.' in nstr: | ||
num = float(nstr) | ||
else: | ||
num = int(nstr) | ||
print '%s(%s)'%(num,type(num)) | ||
return 1 | ||
|
||
def yajl_string(ctx, stringVal, stringLen): | ||
print '"%s",'%string_at(stringVal, stringLen) | ||
return 1 | ||
|
||
def yajl_start_map(ctx): | ||
print "{" | ||
return 1 | ||
|
||
def yajl_map_key(ctx, stringVal, stringLen): | ||
print '"%s":'%string_at(stringVal, stringLen), | ||
return 1 | ||
|
||
def yajl_end_map(ctx): | ||
print "}," | ||
return 1 | ||
|
||
def yajl_start_array(ctx): | ||
print "[" | ||
return 1 | ||
|
||
def yajl_end_array(ctx): | ||
print "]," | ||
return 1 | ||
|
||
|
||
def main(args): | ||
callbacks = [ | ||
yajl_null, | ||
yajl_boolean, | ||
#yajl_integer, | ||
#yajl_double, | ||
0, #replacing integer callback with NULL | ||
0, #replacing double callback with NULL | ||
yajl_number, # cannot have this and (double or integer) | ||
yajl_string, | ||
yajl_start_map, | ||
yajl_map_key, | ||
yajl_end_map, | ||
yajl_start_array, | ||
yajl_end_array | ||
] | ||
parser = YajlParser(callbacks) | ||
if args: | ||
for fn in args: | ||
f = open(fn) | ||
parser.parse(f=f) | ||
f.close() | ||
else: | ||
parser.parse() | ||
return 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from setuptools import setup, find_packages | ||
import sys, os | ||
|
||
from yajl import __version__ as version | ||
|
||
setup(name='yajl-py', | ||
version=version, | ||
description="Pure Python Yajl Wrapper", | ||
long_description="""\ | ||
Pure Python wrapper to the excellent Yajl (Yet Another Json Library) C library""", | ||
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers | ||
keywords='yajl,json', | ||
author='Hatem Nassrat', | ||
author_email='hnassrat@gmail.com', | ||
url='http://github.com/pykler/yajl-py', | ||
license='GPLv3', | ||
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), | ||
include_package_data=True, | ||
zip_safe=True, | ||
install_requires=[ | ||
# -*- Extra requirements: -*- | ||
], | ||
entry_points=""" | ||
# -*- Entry points: -*- | ||
""", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
''' | ||
Pure Python wrapper to the Yajl C library | ||
''' | ||
__version__ = '1.0.7' | ||
|
||
import sys | ||
from ctypes import * | ||
|
||
for yajlso in 'libyajl.so', 'libyajl.dylib': | ||
try: | ||
yajl = cdll.LoadLibrary(yajlso) | ||
except OSError: | ||
pass | ||
else: | ||
break | ||
else: | ||
raise OSError('Yajl shared object cannot be found. ' | ||
'Please install Yajl and confirm it is on your shared lib path.') | ||
|
||
# from yajl_parse.h | ||
class yajl_parser_config(Structure): | ||
_fields_ = [ | ||
("allowComments", c_uint), | ||
("checkUTF8", c_uint) | ||
] | ||
|
||
# Callback Functions | ||
YAJL_NULL = CFUNCTYPE(c_int, c_void_p) | ||
YAJL_BOOL = CFUNCTYPE(c_int, c_void_p, c_int) | ||
YAJL_INT = c_int | ||
YAJL_DBL = c_int | ||
YAJL_NUM = CFUNCTYPE(c_int, c_void_p, POINTER(c_ubyte), c_uint) | ||
YAJL_STR = CFUNCTYPE(c_int, c_void_p, POINTER(c_ubyte), c_uint) | ||
YAJL_SDCT = CFUNCTYPE(c_int, c_void_p) | ||
YAJL_DCTK = CFUNCTYPE(c_int, c_void_p, POINTER(c_ubyte), c_uint) | ||
YAJL_EDCT = CFUNCTYPE(c_int, c_void_p) | ||
YAJL_SARR = CFUNCTYPE(c_int, c_void_p) | ||
YAJL_EARR = CFUNCTYPE(c_int, c_void_p) | ||
class yajl_callbacks(Structure): | ||
_fields_ = [ | ||
("yajl_null", YAJL_NULL), | ||
("yajl_boolean", YAJL_BOOL), | ||
("yajl_integer", YAJL_INT ), | ||
("yajl_double", YAJL_DBL ), | ||
("yajl_number", YAJL_NUM ), | ||
("yajl_string", YAJL_STR ), | ||
("yajl_start_map", YAJL_SDCT), | ||
("yajl_map_key", YAJL_DCTK), | ||
("yajl_end_map", YAJL_EDCT), | ||
("yajl_start_array", YAJL_SARR), | ||
("yajl_end_array", YAJL_EARR), | ||
] | ||
|
||
# yajl_status | ||
( | ||
yajl_status_ok, | ||
yajl_status_client_canceled, | ||
yajl_status_insufficient_data, | ||
yajl_status_error | ||
) = map(c_int, xrange(4)) | ||
|
||
class YajlConfigError(Exception): | ||
pass | ||
|
||
class YajlError(Exception): | ||
def __init__(self, value): | ||
self.value = value | ||
def __str__(self): | ||
return self.value | ||
|
||
class YajlParseCancelled(YajlError): | ||
def __init__(self): | ||
self.value = 'Client Callback Cancelled Parse' | ||
|
||
class YajlParser(object): | ||
''' | ||
A class that utilizes the Yajl C Library | ||
''' | ||
def __init__(self, c, buf_siz=65536): | ||
''' | ||
Takes a list of callback functions `c`. The functions | ||
need to be in order and accepting the correct number | ||
of parameters, they should also reutrn an int. See | ||
yajl doc for more info on parameters and return | ||
values. | ||
Callbacks must return an integer return code | ||
A callback return code of: | ||
- 0 will cancel the parse. | ||
- 1 will allow the parse to continue. | ||
''' | ||
c_funcs = ( | ||
YAJL_NULL, YAJL_BOOL, YAJL_INT, YAJL_DBL, YAJL_NUM, | ||
YAJL_STR, YAJL_SDCT, YAJL_DCTK, YAJL_EDCT, YAJL_SARR, | ||
YAJL_EARR | ||
) | ||
if len(c) != len(c_funcs): | ||
raise Exception("Must Pass %d Functions."%(len(c_funcs))) | ||
for i in range(len(c)): | ||
c[i] = c_funcs[i](c[i]) | ||
self.callbacks = yajl_callbacks(*c) | ||
self.buf_siz = buf_siz | ||
self.cfg = yajl_parser_config(1,1) | ||
|
||
def parse(self, f=sys.stdin, ctx=None): | ||
'''Function to parse a JSON stream. | ||
Parameters: | ||
`f` : file stream to read from | ||
`buf_size` : size in bytes of read buffer | ||
`ctx` : A ctypes pointer that will be passed to | ||
all callback functions as the first param | ||
Raises an expception upon error or return value of 0 | ||
from callback functions. A callback function that | ||
returns 0 should set internal variables to denote | ||
why they cancelled the parsing. | ||
''' | ||
hand = yajl.yajl_alloc( byref(self.callbacks), byref(self.cfg), ctx) | ||
try: | ||
while 1: | ||
fileData = f.read(self.buf_siz-1) | ||
if not fileData: | ||
break | ||
stat = yajl.yajl_parse(hand, fileData, len(fileData)) | ||
if stat not in (yajl_status_ok.value, | ||
yajl_status_insufficient_data.value): | ||
if stat == yajl_status_client_canceled.value: | ||
raise YajlParseCancelled() | ||
else: | ||
yajl.yajl_get_error.restype = c_char_p | ||
error = yajl.yajl_get_error( | ||
hand, 1, fileData, len(fileData)) | ||
raise YajlError(error) | ||
finally: | ||
yajl.yajl_free(hand) |