From 8dd85471a10e19e4513b76ba2b6011dd2104e253 Mon Sep 17 00:00:00 2001 From: Marek Wiese Date: Sun, 5 Apr 2026 23:27:14 +0200 Subject: [PATCH 1/3] add pxd & pyi files (python stubs) --- cysimdjson/cysimdjson.pxd | 153 +++++++++++++++++++++++++++++++++++++ cysimdjson/cysimdjson.pyi | 45 +++++++++++ cysimdjson/cysimdjson.pyx | 156 ++++---------------------------------- cysimdjson/py.typed | 0 setup.py | 3 + 5 files changed, 217 insertions(+), 140 deletions(-) create mode 100644 cysimdjson/cysimdjson.pxd create mode 100644 cysimdjson/cysimdjson.pyi create mode 100644 cysimdjson/py.typed diff --git a/cysimdjson/cysimdjson.pxd b/cysimdjson/cysimdjson.pxd new file mode 100644 index 0000000..3dd113c --- /dev/null +++ b/cysimdjson/cysimdjson.pxd @@ -0,0 +1,153 @@ +# cython: language_level=3 + +from libc.stdint cimport int64_t, uint64_t +from libcpp cimport bool +from libcpp.string cimport string + + +cdef extern from "" namespace "std": + cppclass string_view: + pass + + +cdef extern from "pysimdjson/errors.h": + cdef void simdjson_error_handler() + + +cdef extern from "simdjson/simdjson.h" namespace "simdjson": + + cdef size_t SIMDJSON_MAXSIZE_BYTES + cdef size_t SIMDJSON_PADDING + + cdef enum: + SIMDJSON_VERSION_MAJOR + SIMDJSON_VERSION_MINOR + SIMDJSON_VERSION_REVISION + + +cdef extern from "simdjson/simdjson.h" namespace "simdjson::dom": + + cdef cppclass simdjson_object "simdjson::dom::object": + + cppclass iterator: + iterator() + + simdjson_object operator*() + iterator operator++() + bint operator==(iterator) + bint operator!=(iterator) + + string_view key() + simdjson_element value() + + simdjson_object() + + iterator begin() + iterator end() + + size_t size() + + simdjson_element at_pointer(const char*) except +simdjson_error_handler + simdjson_element operator[](const char*) except +simdjson_error_handler + + + cdef cppclass simdjson_array "simdjson::dom::array": + + cppclass iterator: + iterator() + + operator++() + bint operator!=(iterator) + simdjson_element operator*() + + simdjson_array() + + iterator begin() + iterator end() + + size_t size() + + simdjson_element at(int) except +simdjson_error_handler + simdjson_element at_pointer(const char*) except +simdjson_error_handler + + + cdef cppclass simdjson_element "simdjson::dom::element": + + simdjson_element() + + simdjson_element_type type() except +simdjson_error_handler + + bool get_bool() except +simdjson_error_handler + int64_t get_int64() except +simdjson_error_handler + uint64_t get_uint64() except +simdjson_error_handler + double get_double() except +simdjson_error_handler + simdjson_array get_array() except +simdjson_error_handler + simdjson_object get_object() except +simdjson_error_handler + + simdjson_element at_pointer(const char*) except +simdjson_error_handler + + + cdef cppclass simdjson_parser "simdjson::dom::parser": + + simdjson_parser() + simdjson_parser(size_t max_capacity) + + simdjson_element load(string) except +simdjson_error_handler nogil + simdjson_element parse(const char * buf, size_t len, bool realloc_if_needed) except +simdjson_error_handler nogil + + +cdef extern from "simdjson/simdjson.h" namespace "simdjson::dom::element_type": + cdef enum simdjson_element_type "simdjson::dom::element_type": + OBJECT, + ARRAY, + STRING, + INT64, + UINT64, + DOUBLE, + BOOL, + NULL_VALUE + + +cdef class JSONObject: + + cdef: + simdjson_element Element + simdjson_object Object + + cpdef object at_pointer(self, key) + cpdef object get_value(self) + cpdef object export(self) + + +cdef class JSONArray: + + cdef: + simdjson_element Element + simdjson_array Array + + cpdef object at_pointer(self, key) + cpdef object get_value(self) + cpdef object export(self) + + +cdef class JSONElement: + + cdef: + simdjson_element Element + + @staticmethod + cdef from_element(simdjson_element element) + + cpdef object at_pointer(self, key) + cpdef object get_value(self) + cpdef object export(self) + + +cdef class JSONParser: + + cdef: + simdjson_parser Parser + + cpdef object parse(self, bytes event) + cpdef object parse_in_place(self, bytes event) + cpdef object parse_string(self, str event) diff --git a/cysimdjson/cysimdjson.pyi b/cysimdjson/cysimdjson.pyi new file mode 100644 index 0000000..1e53242 --- /dev/null +++ b/cysimdjson/cysimdjson.pyi @@ -0,0 +1,45 @@ +from typing import Any, Iterator + +class JSONObject: + def __contains__(self, key: str) -> bool: ... + def __iter__(self) -> Iterator[str]: ... + def __getitem__(self, key: str) -> Any: ... + def __len__(self) -> int: ... + def items(self) -> Iterator[tuple[str, Any]]: ... + def get(self, key: str, default: Any = None) -> Any: ... + def keys(self) -> Iterator[str]: ... + def at_pointer(self, key: str) -> Any: ... + def get_value(self) -> "JSONObject": ... + def export(self) -> dict: ... + def get_addr(self) -> int: ... + +class JSONArray: + def __contains__(self, item: Any) -> bool: ... + def __getitem__(self, key: int) -> Any: ... + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[Any]: ... + def at_pointer(self, key: str) -> Any: ... + def get_value(self) -> "JSONArray": ... + def export(self) -> list: ... + def get_addr(self) -> int: ... + +class JSONElement: + def at_pointer(self, key: str) -> "JSONElement": ... + def get_value(self) -> Any: ... + def export(self) -> Any: ... + def get_addr(self) -> int: ... + +class JSONParser: + def __init__(self, max_capacity: int | None = None) -> None: ... + def parse(self, event: bytes) -> JSONObject | JSONArray | JSONElement: ... + def parse_in_place(self, event: bytes) -> JSONObject | JSONArray | JSONElement: ... + def parse_string(self, event: str) -> JSONObject | JSONArray | JSONElement: ... + def load(self, path: str) -> Any: ... + def loads(self, content: str) -> Any: ... + def active_implementation(self) -> str: ... + +def addr_to_element(element_addr: int) -> JSONElement: ... + +MAXSIZE_BYTES: int +PADDING: int +SIMDJSON_VERSION: str diff --git a/cysimdjson/cysimdjson.pyx b/cysimdjson/cysimdjson.pyx index 41289f2..7d68e89 100644 --- a/cysimdjson/cysimdjson.pyx +++ b/cysimdjson/cysimdjson.pyx @@ -1,118 +1,11 @@ # cython: language_level=3 -from libc.stdint cimport int64_t, uint64_t -from libcpp cimport bool -from libcpp.string cimport string - from cpython.bytes cimport PyBytes_AsStringAndSize from cython.operator cimport preincrement from cython.operator cimport dereference -cdef extern from "" namespace "std": - cppclass string_view: - pass - - -cdef extern from "pysimdjson/errors.h": - cdef void simdjson_error_handler() - - -cdef extern from "simdjson/simdjson.h" namespace "simdjson": - - cdef size_t SIMDJSON_MAXSIZE_BYTES - cdef size_t SIMDJSON_PADDING - - cdef enum: - SIMDJSON_VERSION_MAJOR - SIMDJSON_VERSION_MINOR - SIMDJSON_VERSION_REVISION - - -cdef extern from "simdjson/simdjson.h" namespace "simdjson::dom": - - cdef cppclass simdjson_object "simdjson::dom::object": - - cppclass iterator: - iterator() - - simdjson_object operator*() - iterator operator++() - bint operator==(iterator) - bint operator!=(iterator) - - string_view key() - simdjson_element value() - - simdjson_object() - - iterator begin() - iterator end() - - size_t size() - - simdjson_element at_pointer(const char*) except +simdjson_error_handler - simdjson_element operator[](const char*) except +simdjson_error_handler - - - cdef cppclass simdjson_array "simdjson::dom::array": - - cppclass iterator: - iterator() - - operator++() - bint operator!=(iterator) - simdjson_element operator*() - - simdjson_array() - - iterator begin() - iterator end() - - size_t size() - - simdjson_element at(int) except +simdjson_error_handler - simdjson_element at_pointer(const char*) except +simdjson_error_handler - - - cdef cppclass simdjson_element "simdjson::dom::element": - - simdjson_element() - - simdjson_element_type type() except +simdjson_error_handler - - bool get_bool() except +simdjson_error_handler - int64_t get_int64() except +simdjson_error_handler - uint64_t get_uint64() except +simdjson_error_handler - double get_double() except +simdjson_error_handler - simdjson_array get_array() except +simdjson_error_handler - simdjson_object get_object() except +simdjson_error_handler - - simdjson_element at_pointer(const char*) except +simdjson_error_handler - - - cdef cppclass simdjson_parser "simdjson::dom::parser": - - simdjson_parser() - simdjson_parser(size_t max_capacity) - - simdjson_element load(string) except + simdjson_error_handler nogil - simdjson_element parse(const char * buf, size_t len, bool realloc_if_needed) except + simdjson_error_handler nogil - - -cdef extern from "simdjson/simdjson.h" namespace "simdjson::dom::element_type": - cdef enum simdjson_element_type "simdjson::dom::element_type": - OBJECT, - ARRAY, - STRING, - INT64, - UINT64, - DOUBLE, - BOOL, - NULL_VALUE - - cdef extern from "jsoninter.h": cdef bool object_contains(simdjson_object & obj, const char * key) except + simdjson_error_handler @@ -131,11 +24,6 @@ cdef extern from "jsoninter.h": cdef class JSONObject: - cdef: - simdjson_element Element - simdjson_object Object - - def __contains__(JSONObject self, key): key_raw = key.encode('utf-8') return object_contains(self.Object, key_raw) @@ -177,7 +65,7 @@ cdef class JSONObject: if not found: return default return JSONElement.from_element(v).get_value() - + def __len__(JSONObject self): return self.Object.size() @@ -193,20 +81,20 @@ cdef class JSONObject: preincrement(it) - def at_pointer(JSONObject self, key): + cpdef object at_pointer(JSONObject self, key): key_raw = key.encode('utf-8') cdef simdjson_element v = self.Object.at_pointer(key_raw) return JSONElement.from_element(v).get_value() - def get_value(JSONElement self): + cpdef object get_value(JSONObject self): ''' Get the python value ''' return self - def export(self): + cpdef object export(JSONObject self): ''' Export the JSON object to a Python dictionary. WARNING: This is expensive operation. @@ -214,17 +102,12 @@ cdef class JSONObject: return _export_object(self.Object) - def get_addr(JSONElement self): + def get_addr(JSONObject self): return element_addrof(self.Element) cdef class JSONArray: - cdef: - simdjson_element Element - simdjson_array Array - - def __contains__(JSONArray self, item): # This is a full scan for i in range(len(self)): @@ -256,20 +139,20 @@ cdef class JSONArray: preincrement(it) - def at_pointer(JSONArray self, key): + cpdef object at_pointer(JSONArray self, key): key_raw = key.encode('utf-8') cdef simdjson_element v = self.Array.at_pointer(key_raw) return JSONElement.from_element(v).get_value() - def get_value(JSONElement self): + cpdef object get_value(JSONArray self): ''' Get the python value ''' return self - def export(self): + cpdef object export(JSONArray self): ''' Export the JSON array to a Python list. WARNING: This is expensive operation. @@ -277,17 +160,14 @@ cdef class JSONArray: return _export_array(self.Array) - def get_addr(JSONElement self): + def get_addr(JSONArray self): return element_addrof(self.Element) cdef class JSONElement: - cdef: - simdjson_element Element - @staticmethod - cdef inline from_element(simdjson_element element): + cdef from_element(simdjson_element element): ''' This is the correct factory method ''' @@ -312,17 +192,17 @@ cdef class JSONElement: - def at_pointer(JSONElement self, key: str): + cpdef object at_pointer(JSONElement self, key): key_raw = key.encode('utf-8') cdef simdjson_element v = self.Element.at_pointer(key_raw) return JSONElement.from_element(v) - def get_value(JSONElement self): + cpdef object get_value(JSONElement self): return _get_element(self.Element) - def export(JSONElement self): + cpdef object export(JSONElement self): return _export_element(self.Element) @@ -394,10 +274,6 @@ cdef inline object _get_element(simdjson_element v): cdef class JSONParser: - cdef: - simdjson_parser Parser - - def __cinit__(JSONParser self, max_capacity=None): if max_capacity is not None: self.Parser = simdjson_parser.simdjson_parser(int(max_capacity)) @@ -405,7 +281,7 @@ cdef class JSONParser: self.Parser = simdjson_parser.simdjson_parser() - def parse(JSONParser self, event: bytes): + cpdef object parse(JSONParser self, bytes event): cdef Py_ssize_t pysize cdef char * data_ptr cdef int rc = PyBytes_AsStringAndSize(event, &data_ptr, &pysize) @@ -416,7 +292,7 @@ cdef class JSONParser: return JSONElement.from_element(element) - def parse_in_place(JSONParser self, event: bytes): + cpdef object parse_in_place(JSONParser self, bytes event): ''' Skip the reallocation of the input event buffer. This method is little bit faster than parse() but you have to ensure proper padding of the event. @@ -431,7 +307,7 @@ cdef class JSONParser: return JSONElement.from_element(element) - def parse_string(JSONParser self, event: str): + cpdef object parse_string(JSONParser self, str event): cdef Py_ssize_t pysize cdef const char * data_ptr = PyUnicode_AsUTF8AndSize(event, &pysize) diff --git a/cysimdjson/py.typed b/cysimdjson/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/setup.py b/setup.py index e870bd2..270a8f3 100644 --- a/setup.py +++ b/setup.py @@ -66,6 +66,9 @@ ], package_data={ "cysimdjson": [ + "py.typed", + "cysimdjson.pxd", + "cysimdjson.pyi", "cysimdjson.pyx", "cysimdjson.h", "cysimdjsonc.h", From 76bddfdbe317043dd0edc73a0bef2f5f68d274aa Mon Sep 17 00:00:00 2001 From: Marek Wiese Date: Tue, 7 Apr 2026 15:22:13 +0200 Subject: [PATCH 2/3] CR changes --- cysimdjson/cysimdjson.pxd | 8 ++++++-- cysimdjson/cysimdjson.pyi | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cysimdjson/cysimdjson.pxd b/cysimdjson/cysimdjson.pxd index 3dd113c..30c5902 100644 --- a/cysimdjson/cysimdjson.pxd +++ b/cysimdjson/cysimdjson.pxd @@ -27,12 +27,16 @@ cdef extern from "simdjson/simdjson.h" namespace "simdjson": cdef extern from "simdjson/simdjson.h" namespace "simdjson::dom": + cdef cppclass key_value_pair "simdjson::dom::key_value_pair": + string_view key + simdjson_element value + cdef cppclass simdjson_object "simdjson::dom::object": cppclass iterator: iterator() - simdjson_object operator*() + key_value_pair operator*() iterator operator++() bint operator==(iterator) bint operator!=(iterator) @@ -56,7 +60,7 @@ cdef extern from "simdjson/simdjson.h" namespace "simdjson::dom": cppclass iterator: iterator() - operator++() + iterator operator++() bint operator!=(iterator) simdjson_element operator*() diff --git a/cysimdjson/cysimdjson.pyi b/cysimdjson/cysimdjson.pyi index 1e53242..d1b9fb8 100644 --- a/cysimdjson/cysimdjson.pyi +++ b/cysimdjson/cysimdjson.pyi @@ -38,7 +38,7 @@ class JSONParser: def loads(self, content: str) -> Any: ... def active_implementation(self) -> str: ... -def addr_to_element(element_addr: int) -> JSONElement: ... +def addr_to_element(element_addr: int) -> JSONObject | JSONArray | JSONElement: ... MAXSIZE_BYTES: int PADDING: int From 0eac96129781199999a59cd0c13be89c62a9d15d Mon Sep 17 00:00:00 2001 From: Marek Wiese Date: Tue, 7 Apr 2026 15:28:16 +0200 Subject: [PATCH 3/3] fix ref types --- cysimdjson/cysimdjson.pxd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cysimdjson/cysimdjson.pxd b/cysimdjson/cysimdjson.pxd index 30c5902..c1d0f29 100644 --- a/cysimdjson/cysimdjson.pxd +++ b/cysimdjson/cysimdjson.pxd @@ -37,7 +37,7 @@ cdef extern from "simdjson/simdjson.h" namespace "simdjson::dom": iterator() key_value_pair operator*() - iterator operator++() + iterator& operator++() bint operator==(iterator) bint operator!=(iterator) @@ -60,7 +60,7 @@ cdef extern from "simdjson/simdjson.h" namespace "simdjson::dom": cppclass iterator: iterator() - iterator operator++() + iterator& operator++() bint operator!=(iterator) simdjson_element operator*()