diff options
| author | Michael Williamson <mike@zwobble.org> | 2014-03-27 13:47:12 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2014-03-27 13:47:12 +0000 |
| commit | db174ba0448a0716daa2e661fafde7d236429b03 (patch) | |
| tree | d0f5e6af550f39c7cd071e71a01801f72a663182 | |
| parent | e852154e744381b9a18fdbc48ff5864e18dfb295 (diff) | |
Capture compilation errors
| -rw-r--r-- | jq.pyx | 39 | ||||
| -rw-r--r-- | makefile | 2 | ||||
| -rw-r--r-- | tests/jq_tests.py | 8 |
3 files changed, 46 insertions, 3 deletions
@@ -2,8 +2,19 @@ import json cdef extern from "jv.h": + ctypedef enum jv_kind: + JV_KIND_INVALID, + JV_KIND_NULL, + JV_KIND_FALSE, + JV_KIND_TRUE, + JV_KIND_NUMBER, + JV_KIND_STRING, + JV_KIND_ARRAY, + JV_KIND_OBJECT + ctypedef struct jv: pass + jv_kind jv_get_kind(jv) int jv_is_valid(jv) char* jv_string_value(jv) jv jv_dump_string(jv, int flags) @@ -24,12 +35,16 @@ cdef extern from "jv.h": cdef extern from "jq.h": ctypedef struct jq_state: pass + + ctypedef void (*jq_err_cb)(void *, jv) 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 *) + void jq_set_error_cb(jq_state *, jq_err_cb, void *) + void jq_get_error_cb(jq_state *, jq_err_cb *, void **) def jq(object program): @@ -39,9 +54,16 @@ def jq(object program): if not jq: raise Exception("jq_init failed") - # TODO: jq_compile prints error to stderr + cdef _ErrorStore error_store = _ErrorStore.__new__(_ErrorStore) + error_store._errors = [] + + jq_set_error_cb(jq, store_error, <void*>error_store) + cdef int compiled = jq_compile(jq, program_bytes) + if len(error_store._errors) > 0: + raise ValueError("\n".join(error_store._errors)) + if not compiled: raise ValueError("program was not valid") @@ -50,6 +72,20 @@ def jq(object program): return wrapped_program +cdef void store_error(void* store_ptr, jv error): + # TODO: handle errors not of JV_KIND_STRING + cdef _ErrorStore store = <_ErrorStore>store_ptr + if jv_get_kind(error) == JV_KIND_STRING: + store.store_error(jv_string_value(error)) + + +cdef class _ErrorStore(object): + cdef object _errors + + cdef store_error(self, char* error): + self._errors.append(error) + + cdef class _Program(object): cdef jq_state* _jq @@ -67,7 +103,6 @@ cdef class _Program(object): return [json.loads(s) for s in result_strings] else: return json.loads(next(iter(result_strings))) - cdef object _string_to_strings(self, char* input): cdef jv_parser* parser = jv_parser_new(<jv_parser_flags>0) @@ -1,6 +1,6 @@ .PHONY: test upload clean bootstrap setup assert-converted-readme -test: +test: bootstrap _virtualenv/bin/nosetests tests test-all: setup diff --git a/tests/jq_tests.py b/tests/jq_tests.py index 192c4db..dfb7112 100644 --- a/tests/jq_tests.py +++ b/tests/jq_tests.py @@ -71,6 +71,14 @@ def multiple_inputs_in_raw_input_are_separated_by_newlines(): @istest def value_error_is_raised_if_program_is_invalid(): + try: + jq("!") + assert False, "Expected error" + except ValueError as error: + expected_error_str = """error: syntax error, unexpected INVALID_CHARACTER, expecting $end +! +1 compile error""" + assert_equal(str(error), expected_error_str) assert_raises(ValueError, lambda: jq("!")) |
