simple_jsonpath 0.2.2__tar.gz → 0.4.2__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.
@@ -72,4 +72,6 @@ docs/_build/
72
72
  .python-version
73
73
 
74
74
  path.py
75
- device.json
75
+ device.json
76
+ ben
77
+ uv.lock
@@ -2,6 +2,18 @@
2
2
  # It is not intended for manual editing.
3
3
  version = 4
4
4
 
5
+ [[package]]
6
+ name = "ahash"
7
+ version = "0.8.12"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
10
+ dependencies = [
11
+ "cfg-if",
12
+ "once_cell",
13
+ "version_check",
14
+ "zerocopy",
15
+ ]
16
+
5
17
  [[package]]
6
18
  name = "aho-corasick"
7
19
  version = "1.1.4"
@@ -11,6 +23,18 @@ dependencies = [
11
23
  "memchr",
12
24
  ]
13
25
 
26
+ [[package]]
27
+ name = "bitflags"
28
+ version = "2.11.0"
29
+ source = "registry+https://github.com/rust-lang/crates.io-index"
30
+ checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
31
+
32
+ [[package]]
33
+ name = "byteorder"
34
+ version = "1.5.0"
35
+ source = "registry+https://github.com/rust-lang/crates.io-index"
36
+ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
37
+
14
38
  [[package]]
15
39
  name = "cfg-if"
16
40
  version = "1.0.4"
@@ -108,12 +132,27 @@ version = "1.0.17"
108
132
  source = "registry+https://github.com/rust-lang/crates.io-index"
109
133
  checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
110
134
 
135
+ [[package]]
136
+ name = "lazy_static"
137
+ version = "1.5.0"
138
+ source = "registry+https://github.com/rust-lang/crates.io-index"
139
+ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
140
+
111
141
  [[package]]
112
142
  name = "libc"
113
143
  version = "0.2.183"
114
144
  source = "registry+https://github.com/rust-lang/crates.io-index"
115
145
  checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
116
146
 
147
+ [[package]]
148
+ name = "lock_api"
149
+ version = "0.4.14"
150
+ source = "registry+https://github.com/rust-lang/crates.io-index"
151
+ checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
152
+ dependencies = [
153
+ "scopeguard",
154
+ ]
155
+
117
156
  [[package]]
118
157
  name = "memchr"
119
158
  version = "2.8.0"
@@ -142,6 +181,29 @@ version = "1.21.4"
142
181
  source = "registry+https://github.com/rust-lang/crates.io-index"
143
182
  checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
144
183
 
184
+ [[package]]
185
+ name = "parking_lot"
186
+ version = "0.12.5"
187
+ source = "registry+https://github.com/rust-lang/crates.io-index"
188
+ checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
189
+ dependencies = [
190
+ "lock_api",
191
+ "parking_lot_core",
192
+ ]
193
+
194
+ [[package]]
195
+ name = "parking_lot_core"
196
+ version = "0.9.12"
197
+ source = "registry+https://github.com/rust-lang/crates.io-index"
198
+ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
199
+ dependencies = [
200
+ "cfg-if",
201
+ "libc",
202
+ "redox_syscall",
203
+ "smallvec",
204
+ "windows-link",
205
+ ]
206
+
145
207
  [[package]]
146
208
  name = "pin-project-lite"
147
209
  version = "0.2.17"
@@ -240,6 +302,15 @@ dependencies = [
240
302
  "proc-macro2",
241
303
  ]
242
304
 
305
+ [[package]]
306
+ name = "redox_syscall"
307
+ version = "0.5.18"
308
+ source = "registry+https://github.com/rust-lang/crates.io-index"
309
+ checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
310
+ dependencies = [
311
+ "bitflags",
312
+ ]
313
+
243
314
  [[package]]
244
315
  name = "regex"
245
316
  version = "1.12.3"
@@ -319,6 +390,12 @@ version = "1.0.22"
319
390
  source = "registry+https://github.com/rust-lang/crates.io-index"
320
391
  checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
321
392
 
393
+ [[package]]
394
+ name = "scopeguard"
395
+ version = "1.2.0"
396
+ source = "registry+https://github.com/rust-lang/crates.io-index"
397
+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
398
+
322
399
  [[package]]
323
400
  name = "semver"
324
401
  version = "1.0.27"
@@ -416,7 +493,7 @@ dependencies = [
416
493
 
417
494
  [[package]]
418
495
  name = "simple_jsonpath"
419
- version = "0.2.2"
496
+ version = "0.4.2"
420
497
  dependencies = [
421
498
  "pyo3",
422
499
  "rstest",
@@ -424,6 +501,7 @@ dependencies = [
424
501
  "serde_json",
425
502
  "serde_json_path",
426
503
  "serde_json_path_core",
504
+ "ustr",
427
505
  ]
428
506
 
429
507
  [[package]]
@@ -432,6 +510,12 @@ version = "0.4.12"
432
510
  source = "registry+https://github.com/rust-lang/crates.io-index"
433
511
  checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
434
512
 
513
+ [[package]]
514
+ name = "smallvec"
515
+ version = "1.15.1"
516
+ source = "registry+https://github.com/rust-lang/crates.io-index"
517
+ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
518
+
435
519
  [[package]]
436
520
  name = "syn"
437
521
  version = "2.0.117"
@@ -505,6 +589,30 @@ version = "1.0.24"
505
589
  source = "registry+https://github.com/rust-lang/crates.io-index"
506
590
  checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
507
591
 
592
+ [[package]]
593
+ name = "ustr"
594
+ version = "1.1.0"
595
+ source = "registry+https://github.com/rust-lang/crates.io-index"
596
+ checksum = "18b19e258aa08450f93369cf56dd78063586adf19e92a75b338a800f799a0208"
597
+ dependencies = [
598
+ "ahash",
599
+ "byteorder",
600
+ "lazy_static",
601
+ "parking_lot",
602
+ ]
603
+
604
+ [[package]]
605
+ name = "version_check"
606
+ version = "0.9.5"
607
+ source = "registry+https://github.com/rust-lang/crates.io-index"
608
+ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
609
+
610
+ [[package]]
611
+ name = "windows-link"
612
+ version = "0.2.1"
613
+ source = "registry+https://github.com/rust-lang/crates.io-index"
614
+ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
615
+
508
616
  [[package]]
509
617
  name = "winnow"
510
618
  version = "0.7.15"
@@ -514,6 +622,26 @@ dependencies = [
514
622
  "memchr",
515
623
  ]
516
624
 
625
+ [[package]]
626
+ name = "zerocopy"
627
+ version = "0.8.47"
628
+ source = "registry+https://github.com/rust-lang/crates.io-index"
629
+ checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87"
630
+ dependencies = [
631
+ "zerocopy-derive",
632
+ ]
633
+
634
+ [[package]]
635
+ name = "zerocopy-derive"
636
+ version = "0.8.47"
637
+ source = "registry+https://github.com/rust-lang/crates.io-index"
638
+ checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89"
639
+ dependencies = [
640
+ "proc-macro2",
641
+ "quote",
642
+ "syn",
643
+ ]
644
+
517
645
  [[package]]
518
646
  name = "zmij"
519
647
  version = "1.0.21"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "simple_jsonpath"
3
- version = "0.2.2"
3
+ version = "0.4.2"
4
4
  edition = "2024"
5
5
  readme = "README.md"
6
6
 
@@ -15,7 +15,7 @@ serde_json_path = { git = "https://github.com/seojumper/serde_json_path.git", br
15
15
  serde_json_path_core = { git = "https://github.com/seojumper/serde_json_path.git", branch = "quotes" }
16
16
  serde_json = "1.0.149"
17
17
  serde = { version = "1.0.228", features = ["derive"] }
18
-
18
+ ustr = "1.1.0"
19
19
 
20
20
  [dev-dependencies]
21
21
  rstest = "0.26.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simple_jsonpath
3
- Version: 0.2.2
3
+ Version: 0.4.2
4
4
  Classifier: Intended Audience :: Developers
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: Implementation :: CPython
@@ -11,6 +11,7 @@ Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: Programming Language :: Python :: 3.12
12
12
  Classifier: Programming Language :: Python :: 3.13
13
13
  Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: orjson>=3.11.7
14
15
  License-File: LICENSE
15
16
  Summary: A simple - yet quick - JSONPath implementation for querying JSON data.
16
17
  Keywords: jsonpath
@@ -30,7 +31,8 @@ pip install simple_jsonpath
30
31
 
31
32
  ## About
32
33
 
33
- This module is a JSONPath [RFC9535 - JSONPath: Query Expressions for JSON](https://datatracker.ietf.org/doc/html/rfc9535) utility library.
34
+ This module is a JSONPath [RFC9535 - JSONPath: Query Expressions for JSON](https://datatracker.ietf.org/doc/html/rfc9535) utility library that supports performing querying for data in a JSON document. It does **NOT** supporting modifying data
35
+ in place.
34
36
 
35
37
  ## Use
36
38
 
@@ -39,6 +41,29 @@ This module exposes a single simple type - a ***JsonPath*** which has two method
39
41
  - ***set_data()***: sets the data that will be queried against. If multiple queries will be performed against a single piece of JSON data, this helps with the type conversion cost involved. This function can be called with providing new data whenever the inner data held is wished to be changed while retaining already complied paths (useful for querying multiple similarly structured documents).
40
42
  - ***find()***: given a path that is wished to be found in the previously set data, this function will perform the query logic. Mulitple calls to **find()** will query against the previously 'set' data.
41
43
  - ***find_located()***: given a path that is wished to be found in the previously set data, this function can return a list of ***LocatedNode*** objects. Each ***LocatedNode*** object will have attributes related to the path where the node was located as well as their corresponding data. This method is slower than ***find()***, so should ideally only be used when path information for the found nodes is needed.
44
+ - ***child()***: spawns a child instance of the ***JsonPath*** object that does not inherit its data, but maintains shared mutable access to the collection of
45
+ compiled paths.
46
+
47
+ ## Child behavior
48
+
49
+ When the ***child()*** method is invoked, a child will be spawned from the current instance of the ***JsonPath*** object.
50
+
51
+ The child will not inherit the data from the parent, so a call to ***set_data()*** needa to be called on it for it to function.
52
+
53
+ It does however retain shared mutable access to the parent's collection of pre-parsed path objects which is shared across all spawned children.
54
+
55
+ This is useful for the pattern of:
56
+
57
+ 1. Searching a document for a path query.
58
+
59
+ 2. Then using those results returned as the basis of a new 'root element' for 'deeper' searches into a document.
60
+
61
+ Instead of assigning the query results to current instance, it can be beneficial to spawn a child for each result, and assign the result
62
+ data to the child or multiple children if more than one query result was returned.
63
+
64
+ With this pattern the 'base' parent object will automatically contain all parsed paths for the document that were searched by any descendant instance spawned from it, and children will have access to updates to the 'base' instance that any of their siblings make.
65
+
66
+ Then the 'base' parent object can be efficiently used on the next similarly structured document as all previously complied queries against the document are retained.
42
67
 
43
68
  ## Examples
44
69
 
@@ -158,12 +183,16 @@ results: list[LocatedNode] = finder.find_located("$.items[*].address.'prefix-lis
158
183
  for data in results:
159
184
 
160
185
  # Print the normalized full path where the node was found
161
- print(f"{data.full_path}")
186
+ print(f"{data.path}")
162
187
  # $['items'][0]['address']['prefix-list'][0]['prefix']
163
188
 
189
+ # Print the normalized full path of the parent where the node was found
190
+ print(f"{data.parent_path}")
191
+ # $['items'][0]['address']['prefix-list'][0]
192
+
164
193
  # Iterate over the components of the found path
165
194
  # Returned elements will either be a 'str' for keys or 'int' for index values
166
- print(f"{', '.join([str(component) for component in data.path_components])}")
195
+ print(f"{', '.join([str(component) for component in data.path])}")
167
196
  # $, items, 0, adddress, prefix-list, 0, prefix
168
197
 
169
198
  # Access the found node.
@@ -171,3 +200,130 @@ for data in results:
171
200
  # 2001:db8::1/64
172
201
  ```
173
202
 
203
+ ### 'Child' Example
204
+
205
+ The child pattern can be useful for speeding up processing of multiple similarly structured documents to avoid overhead
206
+ of parsing the same query strings many times. Children are independent objects from the 'base' instancee, and children
207
+ can also spawn their own children.
208
+
209
+ ```python
210
+ from simple_jsonpath import JsonPath
211
+
212
+
213
+ json_data_1 = {
214
+ "items": [
215
+ {
216
+ "address": {
217
+ "prefix-list": [
218
+ {
219
+ "prefix": "2001:db8::1/64",
220
+ "eui-64": [
221
+ None
222
+ ]
223
+ }
224
+ ],
225
+ "link-local-address": [
226
+ {
227
+ "address": "fe80::1",
228
+ "link-local": [
229
+ None
230
+ ]
231
+ }
232
+ ]
233
+ }
234
+ },
235
+ {
236
+ "address": {
237
+ "prefix-list": [
238
+ {
239
+ "prefix": "2001:db8::1/64",
240
+ "eui-64": [
241
+ None
242
+ ]
243
+ }
244
+ ],
245
+ "link-local-address": [
246
+ {
247
+ "address": "fe80::1",
248
+ "link-local": [
249
+ None
250
+ ]
251
+ }
252
+ ]
253
+ }
254
+ }
255
+ ]
256
+ }
257
+
258
+ json_data_2 = {
259
+ "items": [
260
+ {
261
+ "address": {
262
+ "prefix-list": [
263
+ {
264
+ "prefix": "2001:db8::2/64",
265
+ "eui-64": [
266
+ None
267
+ ]
268
+ }
269
+ ]
270
+ }
271
+ },
272
+ {
273
+ "address": {
274
+ "prefix-list": [
275
+ {
276
+ "prefix": "2001:db8::2/64",
277
+ "eui-64": [
278
+ None
279
+ ]
280
+ }
281
+ ]
282
+ }
283
+ }
284
+ ]
285
+ }
286
+
287
+ def process_document(data, finder: JsonPath)
288
+ # The 'base' instance was instantiated outside of this fn below.
289
+
290
+ # Sets the data that is desired to be queried against
291
+ finder.set_data(json_data)
292
+
293
+ # Search for interested data. This pattern will be cached in the base instance, which will
294
+ # then be availble to all descendents of the base instance.
295
+ results: list[Any] = finder.find("$.items[*]")
296
+
297
+ # Iterate through each found result
298
+ for data in results:
299
+ # Spwn a child for each result
300
+ child = finder.child()
301
+ # Set the result data for the child
302
+ child.set_data(data)
303
+
304
+ # The first child that requests to find a pattern that has not yet been seen by the 'base' instance
305
+ # will parse the pattern and insert it into the 'base' instance's cache of compiled patterns.
306
+ #
307
+ # The 'base' instance now has the pre-compiled pattern should it need to search for it.
308
+ #
309
+ # All descendants of the 'base' instance now have access to the pre-compiled pattern to include
310
+ # the child that will be spawned on the next iteration of this loop which will allow it to
311
+ # process its own searches faster.
312
+ results = child.find("$.address.'prefix-list'[*]")
313
+
314
+ # .... further procesing....
315
+ all_documents = [json_data_1, json_data_2]
316
+
317
+ # create a single base JsonPath
318
+ finder = JsonPath()
319
+
320
+ for document in all_documents:
321
+ # For each document that will be processed known to be similar in structure > pass in the same 'base' instance.
322
+ #
323
+ # By the time it has processed the first document (depending on how deep either iteself, or its child instnaces were able to traverse the document)
324
+ # some/most/all of the possible paths that will need to be compiled have been. Which makes processing the next document in the series
325
+ # quicker.
326
+ process_document(document, finder)
327
+
328
+ ```
329
+