streaming-json-parser 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. streaming_json_parser-0.2.0/PKG-INFO +214 -0
  2. streaming_json_parser-0.2.0/README.md +159 -0
  3. {streaming_json_parser-0.1.0 → streaming_json_parser-0.2.0}/pyproject.toml +40 -9
  4. streaming_json_parser-0.2.0/src/streaming_json_parser/__init__.py +72 -0
  5. streaming_json_parser-0.2.0/src/streaming_json_parser/high_performance_parser.py +4483 -0
  6. streaming_json_parser-0.2.0/src/streaming_json_parser.egg-info/PKG-INFO +214 -0
  7. {streaming_json_parser-0.1.0 → streaming_json_parser-0.2.0}/src/streaming_json_parser.egg-info/SOURCES.txt +6 -3
  8. streaming_json_parser-0.2.0/src/streaming_json_parser.egg-info/requires.txt +34 -0
  9. streaming_json_parser-0.2.0/tests/test_benchmark_snapshot.py +1174 -0
  10. streaming_json_parser-0.2.0/tests/test_decode_helpers.py +1329 -0
  11. streaming_json_parser-0.2.0/tests/test_high_performance_parser.py +1140 -0
  12. streaming_json_parser-0.2.0/tests/test_native_incremental.py +498 -0
  13. streaming_json_parser-0.2.0/tests/test_packaging.py +25 -0
  14. streaming_json_parser-0.1.0/PKG-INFO +0 -156
  15. streaming_json_parser-0.1.0/README.md +0 -128
  16. streaming_json_parser-0.1.0/src/streaming_json_parser/__init__.py +0 -0
  17. streaming_json_parser-0.1.0/src/streaming_json_parser/iterative_state_machine.py +0 -552
  18. streaming_json_parser-0.1.0/src/streaming_json_parser/streaming_json_parser.py +0 -173
  19. streaming_json_parser-0.1.0/src/streaming_json_parser.egg-info/PKG-INFO +0 -156
  20. streaming_json_parser-0.1.0/src/streaming_json_parser.egg-info/requires.txt +0 -3
  21. streaming_json_parser-0.1.0/tests/test_streaming_json_parser.py +0 -498
  22. {streaming_json_parser-0.1.0 → streaming_json_parser-0.2.0}/LICENSE +0 -0
  23. {streaming_json_parser-0.1.0 → streaming_json_parser-0.2.0}/setup.cfg +0 -0
  24. {streaming_json_parser-0.1.0 → streaming_json_parser-0.2.0}/src/streaming_json_parser.egg-info/dependency_links.txt +0 -0
  25. {streaming_json_parser-0.1.0 → streaming_json_parser-0.2.0}/src/streaming_json_parser.egg-info/top_level.txt +0 -0
@@ -0,0 +1,214 @@
1
+ Metadata-Version: 2.4
2
+ Name: streaming-json-parser
3
+ Version: 0.2.0
4
+ Summary: High-performance JSON decoding and true incremental parsing for Python streams.
5
+ Author-email: Aramis Facchinetti <aramis.facchinetti16@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/aramisfacchinetti/streaming-json-parser
8
+ Project-URL: Repository, https://github.com/aramisfacchinetti/streaming-json-parser
9
+ Project-URL: Issues, https://github.com/aramisfacchinetti/streaming-json-parser/issues
10
+ Keywords: streaming,json,parser,llm,large language model,incremental parsing
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Development Status :: 4 - Beta
19
+ Classifier: Intended Audience :: Developers
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Text Processing
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Provides-Extra: test
26
+ Requires-Dist: pytest>=8.3.5; extra == "test"
27
+ Requires-Dist: msgspec>=0.18; extra == "test"
28
+ Requires-Dist: pydantic-core>=2.0; extra == "test"
29
+ Requires-Dist: jiter>=0.12; extra == "test"
30
+ Provides-Extra: accelerated
31
+ Requires-Dist: msgspec>=0.18; extra == "accelerated"
32
+ Requires-Dist: orjson>=3.9; extra == "accelerated"
33
+ Requires-Dist: pysimdjson>=5; extra == "accelerated"
34
+ Requires-Dist: ujson>=5; extra == "accelerated"
35
+ Requires-Dist: python-rapidjson>=1.23; extra == "accelerated"
36
+ Requires-Dist: yyjson>=4; extra == "accelerated"
37
+ Provides-Extra: partial
38
+ Requires-Dist: pydantic-core>=2.0; extra == "partial"
39
+ Requires-Dist: jiter>=0.12; extra == "partial"
40
+ Provides-Extra: benchmark
41
+ Requires-Dist: ijson>=3.3; extra == "benchmark"
42
+ Requires-Dist: partial-json-parser>=0.2; extra == "benchmark"
43
+ Requires-Dist: partialjson>=1.1; extra == "benchmark"
44
+ Requires-Dist: json-repair>=0.63; extra == "benchmark"
45
+ Requires-Dist: jsonriver>=1.0; extra == "benchmark"
46
+ Requires-Dist: untruncate-json>=1.1; extra == "benchmark"
47
+ Requires-Dist: ujson>=5; extra == "benchmark"
48
+ Requires-Dist: python-rapidjson>=1.23; extra == "benchmark"
49
+ Requires-Dist: yyjson>=4; extra == "benchmark"
50
+ Requires-Dist: pydantic-core>=2.0; extra == "benchmark"
51
+ Requires-Dist: jiter>=0.12; extra == "benchmark"
52
+ Provides-Extra: native-build
53
+ Requires-Dist: maturin<2,>=1; extra == "native-build"
54
+ Dynamic: license-file
55
+
56
+ # Streaming JSON Parser
57
+
58
+ High-performance JSON decoding and true incremental parsing for Python streams.
59
+ The package chooses an appropriate backend for complete documents, NDJSON, typed
60
+ decoding, selective extraction, and partial input. The strict incremental API
61
+ owns the semantics that ordinary JSON decoders do not provide.
62
+
63
+ The current release is `0.2.0` and is in beta while the public API settles.
64
+
65
+ ## Install
66
+
67
+ ```bash
68
+ python -m pip install streaming-json-parser
69
+ ```
70
+
71
+ Optional backend groups:
72
+
73
+ ```bash
74
+ python -m pip install 'streaming-json-parser[accelerated]'
75
+ python -m pip install 'streaming-json-parser[partial]'
76
+ ```
77
+
78
+ The Rust extension is optional. When a compatible wheel is available, install
79
+ it separately:
80
+
81
+ ```bash
82
+ python -m pip install streaming-json-parser-native
83
+ ```
84
+
85
+ The Python implementation remains functional without optional dependencies.
86
+
87
+ ## Choose An API
88
+
89
+ | Workload | API |
90
+ | --- | --- |
91
+ | Complete JSON document | `decode_complete_json` |
92
+ | Complete document with zero-copy view semantics | `decode_complete_json_view` |
93
+ | Newline-delimited JSON | `decode_ndjson` or `StreamingJsonParser(framing="ndjson")` |
94
+ | True incremental parsing | `StreamingJsonParser` |
95
+ | Structural partial snapshots | `decode_structural_partial_json` |
96
+ | Repeated selective extraction | `make_tuned_json_path_extractor` |
97
+
98
+ There is no universal fastest decoder for every payload. The tuned factories
99
+ calibrate compatible backends for a representative workload; the benchmark
100
+ [scorecard](docs/current-api-scorecard.md) records the current evidence.
101
+
102
+ ## Complete Documents
103
+
104
+ ```python
105
+ from streaming_json_parser import decode_complete_json
106
+
107
+ value = decode_complete_json(b'{"name":"example","ok":true}')
108
+ assert value == {"name": "example", "ok": True}
109
+ ```
110
+
111
+ For a stable repeated workload, bind a decoder once:
112
+
113
+ ```python
114
+ from streaming_json_parser import make_tuned_complete_json_decoder
115
+
116
+ decode = make_tuned_complete_json_decoder(
117
+ sample=b'{"id":1,"name":"example"}',
118
+ payload_size_hint=1024,
119
+ )
120
+ value = decode(b'{"id":2,"name":"another"}')
121
+ ```
122
+
123
+ ## Incremental Streams
124
+
125
+ `StreamingJsonParser` preserves state across chunks and reports
126
+ one of `EMPTY`, `PARTIAL`, `COMPLETE`, or `INVALID`.
127
+
128
+ ```python
129
+ from streaming_json_parser import StreamingJsonParser, ParseStatus
130
+
131
+ parser = StreamingJsonParser()
132
+ result = parser.feed(b'{"message":"hel')
133
+ assert result.status is ParseStatus.PARTIAL
134
+ assert result.value == {"message": "hel"}
135
+
136
+ result = parser.feed(b'lo"}')
137
+ assert result.status is ParseStatus.COMPLETE
138
+ assert result.value == {"message": "hello"}
139
+ ```
140
+
141
+ Call `finish()` when the input source ends. This is required for ambiguous root
142
+ scalars and for an NDJSON stream whose final record has no trailing newline.
143
+
144
+ ```python
145
+ parser = StreamingJsonParser()
146
+ parser.consume("12")
147
+ result = parser.finish()
148
+ assert result.value == 12
149
+ ```
150
+
151
+ For NDJSON, use `poll_many()` to drain complete records:
152
+
153
+ ```python
154
+ parser = StreamingJsonParser(framing="ndjson")
155
+ parser.consume(b'{"id":1}\n{"id":2}\n')
156
+ assert parser.poll_many() == [{"id": 1}, {"id": 2}]
157
+ ```
158
+
159
+ ## Partial JSON
160
+
161
+ Structural mode is useful when an unfinished string value does not need to be
162
+ returned. It is a cumulative finisher, not a resumable strict state machine:
163
+
164
+ ```python
165
+ from streaming_json_parser import decode_structural_partial_json
166
+
167
+ assert decode_structural_partial_json('{"items":[1,2') == {"items": [1, 2]}
168
+ assert decode_structural_partial_json('{"text":"hel') == {}
169
+ assert decode_structural_partial_json('{"text":"hel', trailing_strings=True) == {
170
+ "text": "hel"
171
+ }
172
+ ```
173
+
174
+ Use `StreamingJsonParser(partial_mode="structural")` when the
175
+ prefix arrives as many small chunks and a stateful parser is preferable.
176
+
177
+ ## Selective Extraction
178
+
179
+ ```python
180
+ from streaming_json_parser import make_tuned_json_path_extractor
181
+
182
+ extract = make_tuned_json_path_extractor(
183
+ ("meta", "name"),
184
+ ("meta", "count"),
185
+ framing="single",
186
+ sample={"meta": {"name": "example", "count": 1}},
187
+ payload_size_hint=1024,
188
+ )
189
+ assert extract(b'{"meta":{"name":"example","count":2}}') == ("example", 2)
190
+ ```
191
+
192
+ ## Development
193
+
194
+ ```bash
195
+ python -m pip install -e '.[test]'
196
+ pytest
197
+ ```
198
+
199
+ Build and inspect release artifacts locally:
200
+
201
+ ```bash
202
+ python -m build
203
+ python -m twine check dist/*
204
+ ```
205
+
206
+ Benchmark artifacts are optional and can be regenerated with:
207
+
208
+ ```bash
209
+ make benchmark-artifacts
210
+ make verify-benchmark-artifacts
211
+ ```
212
+
213
+ The package supports Python 3.10 and later. It is distributed under the MIT
214
+ license.
@@ -0,0 +1,159 @@
1
+ # Streaming JSON Parser
2
+
3
+ High-performance JSON decoding and true incremental parsing for Python streams.
4
+ The package chooses an appropriate backend for complete documents, NDJSON, typed
5
+ decoding, selective extraction, and partial input. The strict incremental API
6
+ owns the semantics that ordinary JSON decoders do not provide.
7
+
8
+ The current release is `0.2.0` and is in beta while the public API settles.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ python -m pip install streaming-json-parser
14
+ ```
15
+
16
+ Optional backend groups:
17
+
18
+ ```bash
19
+ python -m pip install 'streaming-json-parser[accelerated]'
20
+ python -m pip install 'streaming-json-parser[partial]'
21
+ ```
22
+
23
+ The Rust extension is optional. When a compatible wheel is available, install
24
+ it separately:
25
+
26
+ ```bash
27
+ python -m pip install streaming-json-parser-native
28
+ ```
29
+
30
+ The Python implementation remains functional without optional dependencies.
31
+
32
+ ## Choose An API
33
+
34
+ | Workload | API |
35
+ | --- | --- |
36
+ | Complete JSON document | `decode_complete_json` |
37
+ | Complete document with zero-copy view semantics | `decode_complete_json_view` |
38
+ | Newline-delimited JSON | `decode_ndjson` or `StreamingJsonParser(framing="ndjson")` |
39
+ | True incremental parsing | `StreamingJsonParser` |
40
+ | Structural partial snapshots | `decode_structural_partial_json` |
41
+ | Repeated selective extraction | `make_tuned_json_path_extractor` |
42
+
43
+ There is no universal fastest decoder for every payload. The tuned factories
44
+ calibrate compatible backends for a representative workload; the benchmark
45
+ [scorecard](docs/current-api-scorecard.md) records the current evidence.
46
+
47
+ ## Complete Documents
48
+
49
+ ```python
50
+ from streaming_json_parser import decode_complete_json
51
+
52
+ value = decode_complete_json(b'{"name":"example","ok":true}')
53
+ assert value == {"name": "example", "ok": True}
54
+ ```
55
+
56
+ For a stable repeated workload, bind a decoder once:
57
+
58
+ ```python
59
+ from streaming_json_parser import make_tuned_complete_json_decoder
60
+
61
+ decode = make_tuned_complete_json_decoder(
62
+ sample=b'{"id":1,"name":"example"}',
63
+ payload_size_hint=1024,
64
+ )
65
+ value = decode(b'{"id":2,"name":"another"}')
66
+ ```
67
+
68
+ ## Incremental Streams
69
+
70
+ `StreamingJsonParser` preserves state across chunks and reports
71
+ one of `EMPTY`, `PARTIAL`, `COMPLETE`, or `INVALID`.
72
+
73
+ ```python
74
+ from streaming_json_parser import StreamingJsonParser, ParseStatus
75
+
76
+ parser = StreamingJsonParser()
77
+ result = parser.feed(b'{"message":"hel')
78
+ assert result.status is ParseStatus.PARTIAL
79
+ assert result.value == {"message": "hel"}
80
+
81
+ result = parser.feed(b'lo"}')
82
+ assert result.status is ParseStatus.COMPLETE
83
+ assert result.value == {"message": "hello"}
84
+ ```
85
+
86
+ Call `finish()` when the input source ends. This is required for ambiguous root
87
+ scalars and for an NDJSON stream whose final record has no trailing newline.
88
+
89
+ ```python
90
+ parser = StreamingJsonParser()
91
+ parser.consume("12")
92
+ result = parser.finish()
93
+ assert result.value == 12
94
+ ```
95
+
96
+ For NDJSON, use `poll_many()` to drain complete records:
97
+
98
+ ```python
99
+ parser = StreamingJsonParser(framing="ndjson")
100
+ parser.consume(b'{"id":1}\n{"id":2}\n')
101
+ assert parser.poll_many() == [{"id": 1}, {"id": 2}]
102
+ ```
103
+
104
+ ## Partial JSON
105
+
106
+ Structural mode is useful when an unfinished string value does not need to be
107
+ returned. It is a cumulative finisher, not a resumable strict state machine:
108
+
109
+ ```python
110
+ from streaming_json_parser import decode_structural_partial_json
111
+
112
+ assert decode_structural_partial_json('{"items":[1,2') == {"items": [1, 2]}
113
+ assert decode_structural_partial_json('{"text":"hel') == {}
114
+ assert decode_structural_partial_json('{"text":"hel', trailing_strings=True) == {
115
+ "text": "hel"
116
+ }
117
+ ```
118
+
119
+ Use `StreamingJsonParser(partial_mode="structural")` when the
120
+ prefix arrives as many small chunks and a stateful parser is preferable.
121
+
122
+ ## Selective Extraction
123
+
124
+ ```python
125
+ from streaming_json_parser import make_tuned_json_path_extractor
126
+
127
+ extract = make_tuned_json_path_extractor(
128
+ ("meta", "name"),
129
+ ("meta", "count"),
130
+ framing="single",
131
+ sample={"meta": {"name": "example", "count": 1}},
132
+ payload_size_hint=1024,
133
+ )
134
+ assert extract(b'{"meta":{"name":"example","count":2}}') == ("example", 2)
135
+ ```
136
+
137
+ ## Development
138
+
139
+ ```bash
140
+ python -m pip install -e '.[test]'
141
+ pytest
142
+ ```
143
+
144
+ Build and inspect release artifacts locally:
145
+
146
+ ```bash
147
+ python -m build
148
+ python -m twine check dist/*
149
+ ```
150
+
151
+ Benchmark artifacts are optional and can be regenerated with:
152
+
153
+ ```bash
154
+ make benchmark-artifacts
155
+ make verify-benchmark-artifacts
156
+ ```
157
+
158
+ The package supports Python 3.10 and later. It is distributed under the MIT
159
+ license.
@@ -4,24 +4,23 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "streaming-json-parser"
7
- version = "0.1.0"
7
+ version = "0.2.0"
8
8
  authors = [
9
9
  { name = "Aramis Facchinetti", email = "aramis.facchinetti16@gmail.com" },
10
10
  ]
11
- description = "A streaming JSON parser that processes JSON data incrementally, handling partial states. Useful for incrementally parsing partial responses from streaming outputs of Large Language Models (LLMs)."
11
+ description = "High-performance JSON decoding and true incremental parsing for Python streams."
12
12
  readme = "README.md"
13
- requires-python = ">=3.8"
14
- license = { text = "MIT" }
13
+ requires-python = ">=3.10"
14
+ license = "MIT"
15
15
  classifiers = [
16
16
  "Programming Language :: Python :: 3",
17
- "Programming Language :: Python :: 3.8",
18
- "Programming Language :: Python :: 3.9",
19
17
  "Programming Language :: Python :: 3.10",
20
18
  "Programming Language :: Python :: 3.11",
21
19
  "Programming Language :: Python :: 3.12",
22
- "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Programming Language :: Python :: 3.14",
23
22
  "Operating System :: OS Independent",
24
- "Development Status :: 5 - Production/Stable",
23
+ "Development Status :: 4 - Beta",
25
24
  "Intended Audience :: Developers",
26
25
  "Topic :: Software Development :: Libraries :: Python Modules",
27
26
  "Topic :: Text Processing",
@@ -35,13 +34,45 @@ keywords = ["streaming", "json", "parser", "llm", "large language model", "incre
35
34
  [project.optional-dependencies]
36
35
  test = [
37
36
  "pytest>=8.3.5",
37
+ "msgspec>=0.18",
38
+ "pydantic-core>=2.0",
39
+ "jiter>=0.12",
40
+ ]
41
+ accelerated = [
42
+ "msgspec>=0.18",
43
+ "orjson>=3.9",
44
+ "pysimdjson>=5",
45
+ "ujson>=5",
46
+ "python-rapidjson>=1.23",
47
+ "yyjson>=4",
48
+ ]
49
+ partial = [
50
+ "pydantic-core>=2.0",
51
+ "jiter>=0.12",
52
+ ]
53
+ benchmark = [
54
+ "ijson>=3.3",
55
+ "partial-json-parser>=0.2",
56
+ "partialjson>=1.1",
57
+ "json-repair>=0.63",
58
+ "jsonriver>=1.0",
59
+ "untruncate-json>=1.1",
60
+ "ujson>=5",
61
+ "python-rapidjson>=1.23",
62
+ "yyjson>=4",
63
+ "pydantic-core>=2.0",
64
+ "jiter>=0.12",
65
+ ]
66
+ native-build = [
67
+ "maturin>=1,<2",
38
68
  ]
39
69
 
40
70
  [project.urls]
41
71
  Homepage = "https://github.com/aramisfacchinetti/streaming-json-parser"
42
72
  Repository = "https://github.com/aramisfacchinetti/streaming-json-parser"
73
+ Issues = "https://github.com/aramisfacchinetti/streaming-json-parser/issues"
43
74
 
44
75
  [tool.setuptools.packages.find]
45
76
  where = ["src"]
46
77
  include = ["streaming_json_parser*"]
47
- exclude = ["tests*"]
78
+ exclude = ["tests*"]
@@ -0,0 +1,72 @@
1
+ from .high_performance_parser import (
2
+ HighPerformanceStreamingJsonParser,
3
+ ParseResult,
4
+ ParseStatus,
5
+ decode_complete_json,
6
+ decode_complete_json_view,
7
+ decode_ndjson,
8
+ decode_ndjson_adaptive,
9
+ decode_structural_partial_json,
10
+ extract_complete_json_paths,
11
+ extract_complete_json_typed_paths,
12
+ extract_ndjson_paths,
13
+ extract_ndjson_paths_native,
14
+ extract_ndjson_typed_paths,
15
+ extract_tuned_complete_json_paths,
16
+ extract_tuned_json_paths,
17
+ extract_tuned_ndjson_paths,
18
+ make_complete_json_decoder,
19
+ make_complete_json_typed_path_extractor,
20
+ make_complete_json_view_decoder,
21
+ make_json_path_extractor,
22
+ make_ndjson_decoder,
23
+ make_ndjson_path_extractor,
24
+ make_ndjson_path_extractor_native,
25
+ make_ndjson_typed_path_extractor,
26
+ make_tuned_complete_json_decoder,
27
+ make_tuned_complete_json_path_extractor,
28
+ make_tuned_json_path_extractor,
29
+ make_tuned_ndjson_decoder,
30
+ make_tuned_ndjson_path_extractor,
31
+ make_tuned_structural_partial_decoder,
32
+ )
33
+
34
+ __version__ = "0.2.0"
35
+
36
+ # The canonical public name points to the strict incremental implementation.
37
+ StreamingJsonParser = HighPerformanceStreamingJsonParser
38
+
39
+ __all__ = [
40
+ "StreamingJsonParser",
41
+ "__version__",
42
+ "HighPerformanceStreamingJsonParser",
43
+ "ParseResult",
44
+ "ParseStatus",
45
+ "decode_complete_json",
46
+ "decode_complete_json_view",
47
+ "decode_ndjson",
48
+ "decode_ndjson_adaptive",
49
+ "decode_structural_partial_json",
50
+ "extract_complete_json_paths",
51
+ "extract_complete_json_typed_paths",
52
+ "extract_ndjson_paths",
53
+ "extract_ndjson_paths_native",
54
+ "extract_ndjson_typed_paths",
55
+ "extract_tuned_complete_json_paths",
56
+ "extract_tuned_json_paths",
57
+ "extract_tuned_ndjson_paths",
58
+ "make_complete_json_decoder",
59
+ "make_complete_json_typed_path_extractor",
60
+ "make_complete_json_view_decoder",
61
+ "make_json_path_extractor",
62
+ "make_ndjson_decoder",
63
+ "make_ndjson_path_extractor",
64
+ "make_ndjson_path_extractor_native",
65
+ "make_ndjson_typed_path_extractor",
66
+ "make_tuned_complete_json_decoder",
67
+ "make_tuned_complete_json_path_extractor",
68
+ "make_tuned_json_path_extractor",
69
+ "make_tuned_ndjson_decoder",
70
+ "make_tuned_ndjson_path_extractor",
71
+ "make_tuned_structural_partial_decoder",
72
+ ]