diff options
| author | Michael Williamson <mike@zwobble.org> | 2013-06-18 23:34:42 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2013-06-18 23:34:42 +0100 |
| commit | af6662377ce4048c2214787ee2a1104a9f33839d (patch) | |
| tree | e6f86bdcd439bc3167aad14dd1f716f3f67d2b10 | |
Basic bindings for jq
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | README.md | 0 | ||||
| -rw-r--r-- | jq.pyx | 74 | ||||
| -rw-r--r-- | makefile | 31 | ||||
| -rw-r--r-- | setup.py | 31 | ||||
| -rw-r--r-- | test-requirements.txt | 1 | ||||
| -rw-r--r-- | tests/jq_tests.py | 27 |
7 files changed, 166 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f14905 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +/README diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +cdef extern from "jv.h": + ctypedef struct jv: + pass + int jv_is_valid(jv) + char* jv_string_value(jv) + jv jv_dump_string(jv, int flags) + + +cdef extern from "jq.h": + ctypedef struct jq_state: + pass + + jq_state *jq_init() + void jq_teardown(jq_state **) + int jq_compile(jq_state *, const char* str) + void jq_start(jq_state *, jv value, int flags) + jv jq_next(jq_state *) + + +cdef extern from "jv_parse.h": + cdef struct jv_parser: + pass + + void jv_parser_init(jv_parser*) + void jv_parser_free(jv_parser*) + void jv_parser_set_buf(jv_parser*, const char*, int, int) + jv jv_parser_next(jv_parser*) + + + +def string_to_string(char* program, char* input): + cdef jq_state *jq + # TODO: error if !jq + jq = jq_init() + # TODO: error if !compiled + cdef int compiled = jq_compile(jq, program) + + cdef jv_parser parser + jv_parser_init(&parser) + # TODO: is len a suitable replacement for strlen (unicode)? + jv_parser_set_buf(&parser, input, len(input), 0) + cdef jv value + results = [] + while True: + value = jv_parser_next(&parser) + if jv_is_valid(value): + results.append(process(jq, value)) + else: + break + + jv_parser_free(&parser) + + jq_teardown(&jq) + return "".join(results) + + +cdef process(jq_state *jq, jv value): + cdef int jq_flags = 0 + + jq_start(jq, value, jq_flags); + cdef jv result + cdef int dumpopts = 0 + cdef jv dumped + + output = [] + + while True: + result = jq_next(jq) + if not jv_is_valid(result): + return "\n".join(output) + else: + dumped = jv_dump_string(result, dumpopts) + output.append(jv_string_value(dumped)) + # TODO: free dumped diff --git a/makefile b/makefile new file mode 100644 index 0000000..997b575 --- /dev/null +++ b/makefile @@ -0,0 +1,31 @@ +.PHONY: test upload clean bootstrap setup + +test: + sh -c '. _virtualenv/bin/activate; nosetests -m'\''^$$'\'' `find tests -name '\''*.py'\''`' + +upload: setup + python setup.py sdist upload + make clean + +register: setup + python setup.py register + +README: + pandoc --from=markdown --to=rst README.md > README + +clean: + rm -f README + rm -f MANIFEST + rm -rf dist + +bootstrap: _virtualenv setup + _virtualenv/bin/pip install -e . +ifneq ($(wildcard test-requirements.txt),) + _virtualenv/bin/pip install -r test-requirements.txt +endif + make clean + +setup: README + +_virtualenv: + virtualenv _virtualenv diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..3966809 --- /dev/null +++ b/setup.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +from distutils.extension import Extension +from Cython.Distutils import build_ext + + +def read(fname): + return open(os.path.join(os.path.dirname(__file__), fname)).read() + +jq_extension = Extension( + "jq", + #sources=["_jq.c", "jq.pyx"], + sources=["jq.pyx"], + include_dirs=["../jq/"], + libraries=["jq"], + library_dirs=["../jq/"], +) + +setup( + name='jq', + version='0.1.0', + description='jq is a lightweight and flexible command-line JSON processor.', + long_description=read("README"), + author='Michael Williamson', + url='http://github.com/mwilliamson/jq.py', + cmdclass={"build_ext": build_ext}, + ext_modules = [jq_extension] +) + diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..0798378 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +nose>=1.3.0,<2 diff --git a/tests/jq_tests.py b/tests/jq_tests.py new file mode 100644 index 0000000..0bef31f --- /dev/null +++ b/tests/jq_tests.py @@ -0,0 +1,27 @@ +from nose.tools import istest, assert_equal + +import jq + + +@istest +def dot_operator_does_nothing(): + assert_equal( + "42", + jq.string_to_string(".", "42") + ) + + +@istest +def can_add_one_to_each_element_of_an_array(): + assert_equal( + "[2,3,4]", + jq.string_to_string("[.[]+1]", "[1,2,3]") + ) + + +@istest +def output_elements_are_separated_by_newlines(): + assert_equal( + "1\n2\n3", + jq.string_to_string(".[]", "[1,2,3]") + ) |
