rgapi 0.2.2__tar.gz → 0.2.4__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.
- {rgapi-0.2.2 → rgapi-0.2.4}/.github/workflows/ci.yml +1 -1
- {rgapi-0.2.2 → rgapi-0.2.4}/Cargo.lock +37 -48
- {rgapi-0.2.2 → rgapi-0.2.4}/Cargo.toml +2 -2
- {rgapi-0.2.2 → rgapi-0.2.4}/DEV.md +6 -4
- {rgapi-0.2.2 → rgapi-0.2.4}/PKG-INFO +18 -17
- {rgapi-0.2.2 → rgapi-0.2.4}/README.md +17 -16
- {rgapi-0.2.2 → rgapi-0.2.4}/py/Cargo.toml +2 -2
- {rgapi-0.2.2 → rgapi-0.2.4}/py/src/lib.rs +77 -223
- {rgapi-0.2.2 → rgapi-0.2.4}/python/rgapi/__init__.py +29 -43
- {rgapi-0.2.2 → rgapi-0.2.4}/python/rgapi/skill.py +1 -1
- rgapi-0.2.4/rustfmt.toml +1 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/src/block.rs +16 -34
- rgapi-0.2.4/src/lib.rs +32 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/src/matcher.rs +46 -12
- {rgapi-0.2.2 → rgapi-0.2.4}/src/nb.rs +28 -60
- {rgapi-0.2.2 → rgapi-0.2.4}/src/search.rs +36 -103
- {rgapi-0.2.2 → rgapi-0.2.4}/src/walk.rs +63 -109
- {rgapi-0.2.2 → rgapi-0.2.4}/tests/test_async.py +11 -10
- {rgapi-0.2.2 → rgapi-0.2.4}/tests/test_rgapi.py +105 -76
- rgapi-0.2.2/rustfmt.toml +0 -4
- rgapi-0.2.2/src/lib.rs +0 -24
- {rgapi-0.2.2 → rgapi-0.2.4}/.gitignore +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/LICENSE +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/_config.yml +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/_layouts/default.html +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/py/build.rs +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/pyproject.toml +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/python/rgapi/_cli.py +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/python/rgapi/block.py +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/python/rgapi/nb.py +0 -0
- {rgapi-0.2.2 → rgapi-0.2.4}/tools/bench.py +0 -0
|
@@ -62,7 +62,7 @@ jobs:
|
|
|
62
62
|
- uses: dtolnay/rust-toolchain@stable
|
|
63
63
|
- id: crates-auth
|
|
64
64
|
uses: rust-lang/crates-io-auth-action@v1
|
|
65
|
-
- run: cargo publish -p rgapi
|
|
65
|
+
- run: cargo publish -p rgapi --no-verify
|
|
66
66
|
env:
|
|
67
67
|
CARGO_REGISTRY_TOKEN: ${{ steps.crates-auth.outputs.token }}
|
|
68
68
|
- uses: actions/download-artifact@v8
|
|
@@ -50,9 +50,9 @@ checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48"
|
|
|
50
50
|
|
|
51
51
|
[[package]]
|
|
52
52
|
name = "crc32fast"
|
|
53
|
-
version = "1.5.
|
|
53
|
+
version = "1.5.4"
|
|
54
54
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
55
|
-
checksum = "
|
|
55
|
+
checksum = "5f97d3416d5337d15c4b0d78c8c91df922ca143f57ec20e2d1c188333047ef04"
|
|
56
56
|
dependencies = [
|
|
57
57
|
"cfg-if",
|
|
58
58
|
]
|
|
@@ -84,9 +84,9 @@ checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
|
|
|
84
84
|
|
|
85
85
|
[[package]]
|
|
86
86
|
name = "encoding_rs"
|
|
87
|
-
version = "0.8.
|
|
87
|
+
version = "0.8.44"
|
|
88
88
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
89
|
-
checksum = "
|
|
89
|
+
checksum = "89253175e704ab869b04f9db224d38630e0211a53841a79181deae0889e169f5"
|
|
90
90
|
dependencies = [
|
|
91
91
|
"cfg-if",
|
|
92
92
|
"core_detect",
|
|
@@ -107,9 +107,9 @@ dependencies = [
|
|
|
107
107
|
|
|
108
108
|
[[package]]
|
|
109
109
|
name = "fancy-regex"
|
|
110
|
-
version = "0.
|
|
110
|
+
version = "0.20.0"
|
|
111
111
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
112
|
-
checksum = "
|
|
112
|
+
checksum = "20ed7f62ce0ae0da1a8b93c3c7104ab7e0760a74491e097c701fff966e945390"
|
|
113
113
|
dependencies = [
|
|
114
114
|
"bit-set",
|
|
115
115
|
"regex-automata",
|
|
@@ -118,9 +118,9 @@ dependencies = [
|
|
|
118
118
|
|
|
119
119
|
[[package]]
|
|
120
120
|
name = "globset"
|
|
121
|
-
version = "0.4.
|
|
121
|
+
version = "0.4.21"
|
|
122
122
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
123
|
-
checksum = "
|
|
123
|
+
checksum = "f98b0d85522dc0a824cfebbc9594ff4a9b289c568bea0370319dfbdf20ccdd2d"
|
|
124
124
|
dependencies = [
|
|
125
125
|
"aho-corasick",
|
|
126
126
|
"bstr",
|
|
@@ -161,9 +161,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
|
161
161
|
|
|
162
162
|
[[package]]
|
|
163
163
|
name = "ignore"
|
|
164
|
-
version = "0.4.
|
|
164
|
+
version = "0.4.34"
|
|
165
165
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
166
|
-
checksum = "
|
|
166
|
+
checksum = "484be5657551d7868d67587df967fb4fcbe9d266a761cc855aaa148fda0b3cc7"
|
|
167
167
|
dependencies = [
|
|
168
168
|
"crossbeam-deque",
|
|
169
169
|
"globset",
|
|
@@ -183,15 +183,15 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
|
183
183
|
|
|
184
184
|
[[package]]
|
|
185
185
|
name = "libc"
|
|
186
|
-
version = "0.2.
|
|
186
|
+
version = "0.2.191"
|
|
187
187
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
188
|
-
checksum = "
|
|
188
|
+
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
|
|
189
189
|
|
|
190
190
|
[[package]]
|
|
191
191
|
name = "log"
|
|
192
|
-
version = "0.4.
|
|
192
|
+
version = "0.4.35"
|
|
193
193
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
194
|
-
checksum = "
|
|
194
|
+
checksum = "5d15f86d12da44cd8d4ec3c73984537eb7f4cadcb9776a575a0a8a05ca11005c"
|
|
195
195
|
|
|
196
196
|
[[package]]
|
|
197
197
|
name = "memchr"
|
|
@@ -201,9 +201,9 @@ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
|
201
201
|
|
|
202
202
|
[[package]]
|
|
203
203
|
name = "memmap2"
|
|
204
|
-
version = "0.9.
|
|
204
|
+
version = "0.9.12"
|
|
205
205
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
206
|
-
checksum = "
|
|
206
|
+
checksum = "6b0ca1155a9ecc25aa12e8313a119f32edf0255fea2f44839c4ac0a12b2ac157"
|
|
207
207
|
dependencies = [
|
|
208
208
|
"libc",
|
|
209
209
|
]
|
|
@@ -237,9 +237,9 @@ dependencies = [
|
|
|
237
237
|
|
|
238
238
|
[[package]]
|
|
239
239
|
name = "pyo3"
|
|
240
|
-
version = "0.
|
|
240
|
+
version = "0.30.1"
|
|
241
241
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
242
|
-
checksum = "
|
|
242
|
+
checksum = "229ca13b8a15bb0d1487b81ab975bfcd97513416499a8312011b6036e42e0de4"
|
|
243
243
|
dependencies = [
|
|
244
244
|
"libc",
|
|
245
245
|
"once_cell",
|
|
@@ -251,18 +251,18 @@ dependencies = [
|
|
|
251
251
|
|
|
252
252
|
[[package]]
|
|
253
253
|
name = "pyo3-build-config"
|
|
254
|
-
version = "0.
|
|
254
|
+
version = "0.30.1"
|
|
255
255
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
256
|
-
checksum = "
|
|
256
|
+
checksum = "70130e2b6dd1ee589a8788026a429561ca5c40fa7a2fa7914c2282eddae24700"
|
|
257
257
|
dependencies = [
|
|
258
258
|
"target-lexicon",
|
|
259
259
|
]
|
|
260
260
|
|
|
261
261
|
[[package]]
|
|
262
262
|
name = "pyo3-ffi"
|
|
263
|
-
version = "0.
|
|
263
|
+
version = "0.30.1"
|
|
264
264
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
265
|
-
checksum = "
|
|
265
|
+
checksum = "5e7ff73c555c286d212d4ce7e5fbda845a973c4f61bd5f160f5f2c3c2a04d1c4"
|
|
266
266
|
dependencies = [
|
|
267
267
|
"libc",
|
|
268
268
|
"pyo3-build-config",
|
|
@@ -270,26 +270,26 @@ dependencies = [
|
|
|
270
270
|
|
|
271
271
|
[[package]]
|
|
272
272
|
name = "pyo3-macros"
|
|
273
|
-
version = "0.
|
|
273
|
+
version = "0.30.1"
|
|
274
274
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
275
|
-
checksum = "
|
|
275
|
+
checksum = "c46d2e5862c7bb8207e3b639f713dda3c499933444784154c11d013c5a691b60"
|
|
276
276
|
dependencies = [
|
|
277
277
|
"proc-macro2",
|
|
278
278
|
"pyo3-macros-backend",
|
|
279
279
|
"quote",
|
|
280
|
-
"syn
|
|
280
|
+
"syn",
|
|
281
281
|
]
|
|
282
282
|
|
|
283
283
|
[[package]]
|
|
284
284
|
name = "pyo3-macros-backend"
|
|
285
|
-
version = "0.
|
|
285
|
+
version = "0.30.1"
|
|
286
286
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
287
|
-
checksum = "
|
|
287
|
+
checksum = "38b89f066f2ae72a2aef52d1537ca2fcd104440ebfadee06e97aa90738a25b9b"
|
|
288
288
|
dependencies = [
|
|
289
289
|
"heck",
|
|
290
290
|
"proc-macro2",
|
|
291
291
|
"quote",
|
|
292
|
-
"syn
|
|
292
|
+
"syn",
|
|
293
293
|
]
|
|
294
294
|
|
|
295
295
|
[[package]]
|
|
@@ -320,7 +320,7 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
|
|
320
320
|
|
|
321
321
|
[[package]]
|
|
322
322
|
name = "rgapi"
|
|
323
|
-
version = "0.2.
|
|
323
|
+
version = "0.2.4"
|
|
324
324
|
dependencies = [
|
|
325
325
|
"crc32fast",
|
|
326
326
|
"fancy-regex",
|
|
@@ -335,7 +335,7 @@ dependencies = [
|
|
|
335
335
|
|
|
336
336
|
[[package]]
|
|
337
337
|
name = "rgapi-py"
|
|
338
|
-
version = "0.2.
|
|
338
|
+
version = "0.2.4"
|
|
339
339
|
dependencies = [
|
|
340
340
|
"grep-matcher",
|
|
341
341
|
"pyo3",
|
|
@@ -391,14 +391,14 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
|
|
391
391
|
dependencies = [
|
|
392
392
|
"proc-macro2",
|
|
393
393
|
"quote",
|
|
394
|
-
"syn
|
|
394
|
+
"syn",
|
|
395
395
|
]
|
|
396
396
|
|
|
397
397
|
[[package]]
|
|
398
398
|
name = "serde_json"
|
|
399
|
-
version = "1.0.
|
|
399
|
+
version = "1.0.154"
|
|
400
400
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
401
|
-
checksum = "
|
|
401
|
+
checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
|
|
402
402
|
dependencies = [
|
|
403
403
|
"itoa",
|
|
404
404
|
"memchr",
|
|
@@ -415,20 +415,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
|
|
415
415
|
|
|
416
416
|
[[package]]
|
|
417
417
|
name = "syn"
|
|
418
|
-
version = "
|
|
419
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
420
|
-
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
|
421
|
-
dependencies = [
|
|
422
|
-
"proc-macro2",
|
|
423
|
-
"quote",
|
|
424
|
-
"unicode-ident",
|
|
425
|
-
]
|
|
426
|
-
|
|
427
|
-
[[package]]
|
|
428
|
-
name = "syn"
|
|
429
|
-
version = "3.0.6"
|
|
418
|
+
version = "3.0.9"
|
|
430
419
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
431
|
-
checksum = "
|
|
420
|
+
checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"
|
|
432
421
|
dependencies = [
|
|
433
422
|
"proc-macro2",
|
|
434
423
|
"quote",
|
|
@@ -443,9 +432,9 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
|
443
432
|
|
|
444
433
|
[[package]]
|
|
445
434
|
name = "unicode-ident"
|
|
446
|
-
version = "1.0.
|
|
435
|
+
version = "1.0.27"
|
|
447
436
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
448
|
-
checksum = "
|
|
437
|
+
checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
|
|
449
438
|
|
|
450
439
|
[[package]]
|
|
451
440
|
name = "walkdir"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
members = ["py"]
|
|
3
3
|
|
|
4
4
|
[workspace.package]
|
|
5
|
-
version = "0.2.
|
|
5
|
+
version = "0.2.4"
|
|
6
6
|
edition = "2024"
|
|
7
7
|
|
|
8
8
|
[workspace.dependencies]
|
|
@@ -24,7 +24,7 @@ name = "rgapi"
|
|
|
24
24
|
|
|
25
25
|
[dependencies]
|
|
26
26
|
crc32fast = "1"
|
|
27
|
-
fancy-regex = "0.
|
|
27
|
+
fancy-regex = ">=0.20"
|
|
28
28
|
globset = ">=0.4.18"
|
|
29
29
|
grep-matcher.workspace = true
|
|
30
30
|
grep-searcher = ">=0.1.16"
|
|
@@ -23,7 +23,7 @@ cargo develop
|
|
|
23
23
|
pytest -q
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
`cargo develop` and bare `cargo test` use the same Cargo profile and share the core and binding libraries. Unit tests also build a separate `cfg(test)` executable. The published `rgapi` crate has no Python dependency; the unpublished `rgapi-py` crate in `py/` builds the extension. Run `cargo
|
|
26
|
+
`cargo develop` and bare `cargo test` use the same Cargo profile and share the core and binding libraries. Unit tests also build a separate `cfg(test)` executable. The published `rgapi` crate has no Python dependency; the unpublished `rgapi-py` crate in `py/` builds the extension. Run `cargo fastfmt` after Rust edits and `chkstyle` before committing Python edits.
|
|
27
27
|
|
|
28
28
|
## Release
|
|
29
29
|
|
|
@@ -41,7 +41,9 @@ The GitHub workflow builds wheels for Python 3.10-3.13 on Linux and macOS and pu
|
|
|
41
41
|
|
|
42
42
|
All user-supplied regexes use the shared `RegexMatcher` in `src/matcher.rs`, backed by `fancy-regex`. There is no separate fallback engine or native C dependency. The adapter implements `grep_matcher::Matcher` so `grep-searcher` continues to handle file scanning, line numbers, context, and binary detection. `compile_regex` returns rgapi's own exported `RegexMatcher` type.
|
|
43
43
|
|
|
44
|
-
The matcher centralizes smart-case analysis and line-ending policy. Line-safe patterns can search a whole buffer; patterns that can consume line endings
|
|
44
|
+
The matcher centralizes smart-case analysis and line-ending policy. Line-safe patterns can search a whole buffer; patterns that can consume line endings, inspect neighbouring lines or need the backtracking engine are evaluated on individual lines, so that engine's step budget covers one line, not a whole buffer. Notebook multiline matching instead uses the whole cell. Filename/path regexes match their whole input. Backtracking-limit errors propagate through the existing result channels, including directory-pruning errors; cancellation must not hide a queued error from async consumers.
|
|
45
|
+
|
|
46
|
+
A walk error, a file the walk can't read, or a notebook `nbrg` can't parse is a skipped error (`RgApiError::is_skipped`). `send_error` sends a skipped error without ending the walk. Any other error ends it. The Python bindings issue a `RuntimeWarning` for each skipped error and raise `ValueError` for any other (`skip_or_raise`, and `worker_error` on async worker threads). Rust's collecting functions, such as `find`, `rg`, `nb_search` and `StreamIter::collect_timeout`, return the first error of either kind. `entry_err` drops a permission error silently at the `max_depth` cap, where the walker opens a directory it never descends into.
|
|
45
47
|
|
|
46
48
|
Python discovery and `paths=True` results contain absolute `pathlib.Path` objects. Structured search rows hold base-relative string labels with `/` separators. Traversal uses `ignore::WalkParallel`, so result order is not part of the API contract. Search results are structured rows; collected result lists use rg-style `str()` and notebook display. `SearchLine.lnhash` is computed with the same CRC-32-based line-content hash format as exhash (`lineno|hash|`, low 12 bits of CRC-32 over the line's UTF-8 bytes, encoded as two Base64url characters); `lnhashs=True` only changes row display, not `line_number` or matching behavior. Path regexes filter returned/searched paths; `skip_dir` and `skip_dir_re` prune traversal through `ignore::WalkBuilder::filter_entry`. Depth, size, filesystem, hidden, and ignore options use `ignore::WalkBuilder` settings. The `ignore` walker follows every root it is given. Discovery checks each root with `symlink_metadata`. The worker sends each unfollowed link root as a result before walking the other roots. This also supports dangling roots, which the underlying walker would reject. `ls` sets `walk_root_links`, which gives a root link to a directory to the walker. The walker then reports paths under the link. Other discovery roots use absolute paths without canonicalizing. Content searches retain canonical root resolution. `rg_iter` exposes the same parallel search stream that `rg` collects by default; `paths=True` and `count=True` consume that stream with different reducers. Text search skips binary files and invalid UTF-8 content.
|
|
47
49
|
|
|
@@ -51,9 +53,9 @@ Streaming engine: `walk.rs` owns the generic machinery. `StreamIter<T>` is the w
|
|
|
51
53
|
|
|
52
54
|
Async API: `fda`, `fda_iter`, `rga`, `rga_iter`, `nbrga`, and `nbrga_iter` wrap the corresponding private core operations. `rga(summary=True)` uses `_core.block_search_async`; ordinary `rga` uses `_core.rg_async`. Each collected core function takes a Python callback, runs on Rust threads through the generic `stream_async` helper, and delivers with one GIL attach at the end. Iterator forms use `stream_iter_async` and attach once per batch. The Python side settles an `asyncio.Future` or feeds an `asyncio.Queue` via `loop.call_soon_threadsafe`; no Python thread blocks and `asyncio.to_thread` is not involved. `AsyncHandle.cancel()` sets the same atomic flag used by the Rust iterators.
|
|
53
55
|
|
|
54
|
-
Truncation is recorded on collected results: `max_results` sets `stop_reason="max_results"`, and `timeout_ms` on `rg`/`rga`/`nbrg`/`nbrga`/`fd`/`fda`/`
|
|
56
|
+
Truncation is recorded on collected results: `max_results` sets `stop_reason="max_results"`, and `timeout_ms` on `rg`/`rga`/`nbrg`/`nbrga`/`fd`/`fda`/`ls` sets `stop_reason="timeout"`. `SearchResults`, `BlockResults`, `PathResults`, and `NbResults` share this through `_Results`; `complete` means `stop_reason is None`. In block summary mode, `max_results` counts matching blocks and keeps their block context. `count` returns a plain int, or a dict for `count="file"`, so it rejects timeouts and block summary mode.
|
|
55
57
|
|
|
56
|
-
Rust discovery returns base-relative `PathBuf` values. Glob filters operate on native paths; only regex matching uses string labels. PyO3 converts discovery roots and results with its filesystem-path support. Python joins each result to the base from `_core.walk_base` without resolving links. `PathResults` stores that display base and completion status, including across slices. Its `__repr__` uses `Path.lstat()` for an `ls -l`-style listing capped at `MAX_REPR` rows. `str()` returns one base-relative name per line. `ls` is `fd` with shell-style defaults (one level, dirs, ignore rules off) and `walk_root_links`, sorted in place.
|
|
58
|
+
Rust discovery returns base-relative `PathBuf` values. Glob filters operate on native paths; only regex matching uses string labels. PyO3 converts discovery roots and results with its filesystem-path support. Python joins each result to the base from `_core.walk_base` without resolving links. `PathResults` stores that display base and completion status, including across slices. Its `__repr__` uses `Path.lstat()` for an `ls -l`-style listing capped at `MAX_REPR` rows. `str()` returns one base-relative name per line. `ls` is `fd` with shell-style defaults (one level, dirs, ignore rules off) and `walk_root_links`, sorted in place. `fd` takes `pattern` first, as `rg` does. `ls` takes `root` first, as the shell's `ls DIR` does.
|
|
57
59
|
|
|
58
60
|
Rust callers can consume a `StreamIter` with `cancel_and_join()` to cancel, drain queued results, and wait for the walk's workers to finish. `Drop` remains nonblocking. Since filesystem calls already in progress must return before joining completes, keep `cancel_and_join()` off async executors.
|
|
59
61
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rgapi
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Requires-Dist: fastcore>=2.2.29
|
|
@@ -32,7 +32,7 @@ For common file discovery and search:
|
|
|
32
32
|
```python
|
|
33
33
|
from rgapi import fd, ls, rg, rg_iter
|
|
34
34
|
|
|
35
|
-
fd(
|
|
35
|
+
fd(ext="py", exclude="test_*.py")
|
|
36
36
|
ls("src")
|
|
37
37
|
for row in rg_iter("TODO", ".", include="*.py", context=2): print(row.asdict())
|
|
38
38
|
rg("TODO", ".", ext="py", skip_dir=".venv", paths=True)
|
|
@@ -56,16 +56,15 @@ await rga("TODO", ".", ext="py", timeout_ms=200)
|
|
|
56
56
|
async for row in rga_iter("TODO", "."): print(row)
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Use the lower-level functions to compile a regex, search text or a single file
|
|
59
|
+
Use the lower-level functions to compile a regex, or to search text or a single file:
|
|
60
60
|
|
|
61
61
|
```python
|
|
62
|
-
from rgapi import compile, search_path, search_text
|
|
62
|
+
from rgapi import compile, search_path, search_text
|
|
63
63
|
|
|
64
64
|
matcher = compile("TODO")
|
|
65
65
|
matcher.is_match("TODO")
|
|
66
66
|
matcher.finditer("TODO TODO")
|
|
67
67
|
|
|
68
|
-
walk(".")
|
|
69
68
|
search_text(matcher, "alpha\nTODO\nomega\n", path="memory.txt", context=1)
|
|
70
69
|
search_path(matcher, "src/lib.rs", display_path="src/lib.rs")
|
|
71
70
|
```
|
|
@@ -78,7 +77,7 @@ pip install rgapi
|
|
|
78
77
|
|
|
79
78
|
## File discovery
|
|
80
79
|
|
|
81
|
-
`fd`
|
|
80
|
+
`fd` returns absolute `pathlib.Path` objects. Use them directly with `.read_text()`, `.open()`, `.stat()`, or other filesystem operations. Its collected results display names relative to `root`. Pass `root` as a `str` or `Path`, or as a list of them. The sync and async APIs expand `~` and accept `.`, `./`, and paths containing `..`.
|
|
82
81
|
|
|
83
82
|
A list of roots, such as `rg("TODO", ["src", "tests"])`, works with every walk and search function. The roots are searched as one walk that returns one result list. `timeout_ms` and `max_results` apply to the whole walk. Result paths are relative to the common ancestor of the roots. For example, rows read `src/app.py` and `tests/test_app.py`. `PathResults` displays use the same relative paths. Filters such as `include`, `path_re` and `skip_dir` match these relative paths. A file under more than one root, such as `src/app.py` with roots `[".", "src"]`, appears once.
|
|
84
83
|
|
|
@@ -86,9 +85,11 @@ Discovery uses the `ignore` crate with ripgrep's default filters. It reads `.git
|
|
|
86
85
|
|
|
87
86
|
Hidden files are skipped unless `hidden=True`. Discovery returns symlinks themselves, including explicitly named roots and dangling links. Set `follow_links=True` to traverse their targets. Paths retain the symlink spelling. Use `same_file_system=True` to avoid crossing filesystem boundaries.
|
|
88
87
|
|
|
88
|
+
A walk skips each directory or file that it can't read, such as one without read permission, and issues a `RuntimeWarning` that names it. The rest of the walk continues, as ripgrep's does.
|
|
89
|
+
|
|
89
90
|
Traversal runs in parallel without guaranteed result order. Use `sorted(...)` when order matters.
|
|
90
91
|
|
|
91
|
-
`fd`
|
|
92
|
+
`fd` takes `pattern` first and `root` second, as `rg` does. With no pattern, it returns every file under `root`. `pattern` is a smart-case regex matched against each basename. Lowercase patterns match case-insensitively. A pattern containing uppercase letters is case-sensitive. Use `path_re` to match the slash-separated relative path instead.
|
|
92
93
|
|
|
93
94
|
`include` and `exclude` use case-sensitive glob syntax. `glob=` is an alias for `include=`. Patterns without `/` match names at any depth, so `*.py` matches `src/app.py`. Patterns containing `/` are root-relative. `*` stays within a path component; `**` spans directories: `src/*` matches immediate children, whereas `src/**` also matches deeper descendants. Matching a directory with `exclude` prunes its entire subtree. Includes never prune traversal. Excludes always win, and includes do not override ignore rules.
|
|
94
95
|
|
|
@@ -96,7 +97,7 @@ Filter extensions with `ext="py"` or `ext=["py", "rs"]`. Extension and glob filt
|
|
|
96
97
|
|
|
97
98
|
Set `min_depth` and `max_depth` to bound recursion. `max_filesize` skips files above a byte limit.
|
|
98
99
|
|
|
99
|
-
`ls` follows the shell command's listing conventions. It uses `fd` with `max_depth=1`, includes directories, disables ignore rules, and sorts by name. Set `hidden=True` for `ls -a` behaviour. All `fd` filters remain available.
|
|
100
|
+
`ls` follows the shell command's listing conventions. It takes `root` first, as the shell's `ls DIR` does. It uses `fd` with `max_depth=1`, includes directories, disables ignore rules, and sorts by name. Set `hidden=True` for `ls -a` behaviour. All `fd` filters remain available.
|
|
100
101
|
|
|
101
102
|
`fd_iter` yields absolute `Path` objects as the walk finds them. It accepts every `fd` filter. Stopping iteration ends the walk. It does not accept `timeout_ms`.
|
|
102
103
|
|
|
@@ -113,10 +114,10 @@ Patterns support backreferences and lookaround everywhere, including filename an
|
|
|
113
114
|
```python
|
|
114
115
|
rg(r"\b(\w+)\s+\1\b", ".") # repeated words
|
|
115
116
|
rg(r"(?<=TODO: )\w+", ".") # word following TODO:
|
|
116
|
-
fd(
|
|
117
|
+
fd(r"^(\w+)_\1\.py$") # names such as utils_utils.py
|
|
117
118
|
```
|
|
118
119
|
|
|
119
|
-
All regex parameters use `fancy-regex
|
|
120
|
+
All regex parameters use `fancy-regex`, with no engine-selection flag and no C library. Ordinary patterns, including word boundaries (`\b`, `\B`) outside lookbehinds, use its non-backtracking engine. Patterns requiring backtracking have a step budget that allows lines of millions of characters. A search that exceeds the budget raises `ValueError`. It never silently skips a file or path.
|
|
120
121
|
|
|
121
122
|
Each `SearchLine` has these fields:
|
|
122
123
|
|
|
@@ -135,7 +136,7 @@ matches list of (start, end) byte offsets for match rows
|
|
|
135
136
|
|
|
136
137
|
Pass `lnhashs=True` to `rg` or `rg_iter` to display hash addresses instead of line numbers. The `line_number` field remains available.
|
|
137
138
|
|
|
138
|
-
For other result forms, use `rg(..., paths=True)` to return unique matched paths
|
|
139
|
+
For other result forms, use `rg(..., paths=True)` to return unique matched paths, `rg(..., count=True)` to count match spans, or `rg(..., count="file")` for a dict from each file's label to its count, sorted by label. `paths` and `count` cannot both be set.
|
|
139
140
|
|
|
140
141
|
`^` and `$` match at the start and end of each line. A line ends at `\n` or `\r\n`. `$` also matches before a `\r` that has no `\n` after it. `rg`, `rgstr`, and `compile` reject patterns containing a literal `\n` or `\r`. `nbrg` allows them with `multiline=True`.
|
|
141
142
|
|
|
@@ -143,10 +144,10 @@ Content searches and compiled content matchers are confined to individual lines:
|
|
|
143
144
|
|
|
144
145
|
### Path results
|
|
145
146
|
|
|
146
|
-
`fd
|
|
147
|
+
`fd` and `ls` return `PathResults`, a list of absolute `Path` objects. So do `rg` and `nbrg` with `paths=True`, and their async equivalents. Indexing or iterating returns ordinary Paths:
|
|
147
148
|
|
|
148
149
|
```python
|
|
149
|
-
for path in fd("src", ext="py"):
|
|
150
|
+
for path in fd(root="src", ext="py"):
|
|
150
151
|
text = path.read_text()
|
|
151
152
|
size = path.stat().st_size
|
|
152
153
|
```
|
|
@@ -163,13 +164,13 @@ Rust callers can set `FindOptions::special_files` to also discover FIFOs, socket
|
|
|
163
164
|
|
|
164
165
|
### Limits and timeouts
|
|
165
166
|
|
|
166
|
-
Set `timeout_ms` on `rg`, `fd
|
|
167
|
+
Set `timeout_ms` on `rg`, `fd` or `ls` to stop at a deadline and return the results collected so far. Their async versions accept it too. Results report why the operation stopped:
|
|
167
168
|
|
|
168
169
|
- `stop_reason=None` means the result is complete.
|
|
169
170
|
- `stop_reason="max_results"` means `max_results` truncated the result.
|
|
170
171
|
- `stop_reason="timeout"` means the deadline was reached.
|
|
171
172
|
|
|
172
|
-
`complete` is true exactly when `stop_reason` is `None`.
|
|
173
|
+
`complete` is true exactly when `stop_reason` is `None`. A count is a plain integer or dict, with no completion flag. Counting can't be combined with `timeout_ms`.
|
|
173
174
|
|
|
174
175
|
Deadlines stop result collection and request worker cancellation. Workers cannot interrupt a regex evaluation or filesystem call already in progress; a timeout is not a hard per-match execution limit.
|
|
175
176
|
|
|
@@ -236,7 +237,7 @@ A matching cell's display starts at its first matched line. Earlier lines are re
|
|
|
236
237
|
- `count=True` returns the number of matching cells.
|
|
237
238
|
- `timeout_ms` applies a deadline with the same `stop_reason` values as `rg`.
|
|
238
239
|
|
|
239
|
-
The parser reads only each cell's `id`, `cell_type`, and `source`. It skips outputs and metadata without loading embedded images or plots. `search_nb(pattern, path, ...)` searches a single notebook file in the same way.
|
|
240
|
+
The parser reads only each cell's `id`, `cell_type`, and `source`. It skips outputs and metadata without loading embedded images or plots. `search_nb(pattern, path, ...)` searches a single notebook file in the same way. `nbrg` skips a `.ipynb` file that isn't valid JSON and issues a `RuntimeWarning` naming the file and the parse error. `search_nb` raises `ValueError` for such a file.
|
|
240
241
|
|
|
241
242
|
`rgapi-nbrg` exposes notebook search without requiring a Python kernel:
|
|
242
243
|
|
|
@@ -256,7 +257,7 @@ Run `rgapi-nbrg --help` for its discovery, matching, and output options.
|
|
|
256
257
|
```python
|
|
257
258
|
from rgapi import fda, rga, rga_iter
|
|
258
259
|
|
|
259
|
-
await fda(
|
|
260
|
+
await fda(ext="py")
|
|
260
261
|
res = await rga("TODO", ".", timeout_ms=200)
|
|
261
262
|
if not res.complete: print(f"partial results: {res.stop_reason}")
|
|
262
263
|
async for row in rga_iter("TODO", "."): ...
|
|
@@ -11,7 +11,7 @@ For common file discovery and search:
|
|
|
11
11
|
```python
|
|
12
12
|
from rgapi import fd, ls, rg, rg_iter
|
|
13
13
|
|
|
14
|
-
fd(
|
|
14
|
+
fd(ext="py", exclude="test_*.py")
|
|
15
15
|
ls("src")
|
|
16
16
|
for row in rg_iter("TODO", ".", include="*.py", context=2): print(row.asdict())
|
|
17
17
|
rg("TODO", ".", ext="py", skip_dir=".venv", paths=True)
|
|
@@ -35,16 +35,15 @@ await rga("TODO", ".", ext="py", timeout_ms=200)
|
|
|
35
35
|
async for row in rga_iter("TODO", "."): print(row)
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
Use the lower-level functions to compile a regex, search text or a single file
|
|
38
|
+
Use the lower-level functions to compile a regex, or to search text or a single file:
|
|
39
39
|
|
|
40
40
|
```python
|
|
41
|
-
from rgapi import compile, search_path, search_text
|
|
41
|
+
from rgapi import compile, search_path, search_text
|
|
42
42
|
|
|
43
43
|
matcher = compile("TODO")
|
|
44
44
|
matcher.is_match("TODO")
|
|
45
45
|
matcher.finditer("TODO TODO")
|
|
46
46
|
|
|
47
|
-
walk(".")
|
|
48
47
|
search_text(matcher, "alpha\nTODO\nomega\n", path="memory.txt", context=1)
|
|
49
48
|
search_path(matcher, "src/lib.rs", display_path="src/lib.rs")
|
|
50
49
|
```
|
|
@@ -57,7 +56,7 @@ pip install rgapi
|
|
|
57
56
|
|
|
58
57
|
## File discovery
|
|
59
58
|
|
|
60
|
-
`fd`
|
|
59
|
+
`fd` returns absolute `pathlib.Path` objects. Use them directly with `.read_text()`, `.open()`, `.stat()`, or other filesystem operations. Its collected results display names relative to `root`. Pass `root` as a `str` or `Path`, or as a list of them. The sync and async APIs expand `~` and accept `.`, `./`, and paths containing `..`.
|
|
61
60
|
|
|
62
61
|
A list of roots, such as `rg("TODO", ["src", "tests"])`, works with every walk and search function. The roots are searched as one walk that returns one result list. `timeout_ms` and `max_results` apply to the whole walk. Result paths are relative to the common ancestor of the roots. For example, rows read `src/app.py` and `tests/test_app.py`. `PathResults` displays use the same relative paths. Filters such as `include`, `path_re` and `skip_dir` match these relative paths. A file under more than one root, such as `src/app.py` with roots `[".", "src"]`, appears once.
|
|
63
62
|
|
|
@@ -65,9 +64,11 @@ Discovery uses the `ignore` crate with ripgrep's default filters. It reads `.git
|
|
|
65
64
|
|
|
66
65
|
Hidden files are skipped unless `hidden=True`. Discovery returns symlinks themselves, including explicitly named roots and dangling links. Set `follow_links=True` to traverse their targets. Paths retain the symlink spelling. Use `same_file_system=True` to avoid crossing filesystem boundaries.
|
|
67
66
|
|
|
67
|
+
A walk skips each directory or file that it can't read, such as one without read permission, and issues a `RuntimeWarning` that names it. The rest of the walk continues, as ripgrep's does.
|
|
68
|
+
|
|
68
69
|
Traversal runs in parallel without guaranteed result order. Use `sorted(...)` when order matters.
|
|
69
70
|
|
|
70
|
-
`fd`
|
|
71
|
+
`fd` takes `pattern` first and `root` second, as `rg` does. With no pattern, it returns every file under `root`. `pattern` is a smart-case regex matched against each basename. Lowercase patterns match case-insensitively. A pattern containing uppercase letters is case-sensitive. Use `path_re` to match the slash-separated relative path instead.
|
|
71
72
|
|
|
72
73
|
`include` and `exclude` use case-sensitive glob syntax. `glob=` is an alias for `include=`. Patterns without `/` match names at any depth, so `*.py` matches `src/app.py`. Patterns containing `/` are root-relative. `*` stays within a path component; `**` spans directories: `src/*` matches immediate children, whereas `src/**` also matches deeper descendants. Matching a directory with `exclude` prunes its entire subtree. Includes never prune traversal. Excludes always win, and includes do not override ignore rules.
|
|
73
74
|
|
|
@@ -75,7 +76,7 @@ Filter extensions with `ext="py"` or `ext=["py", "rs"]`. Extension and glob filt
|
|
|
75
76
|
|
|
76
77
|
Set `min_depth` and `max_depth` to bound recursion. `max_filesize` skips files above a byte limit.
|
|
77
78
|
|
|
78
|
-
`ls` follows the shell command's listing conventions. It uses `fd` with `max_depth=1`, includes directories, disables ignore rules, and sorts by name. Set `hidden=True` for `ls -a` behaviour. All `fd` filters remain available.
|
|
79
|
+
`ls` follows the shell command's listing conventions. It takes `root` first, as the shell's `ls DIR` does. It uses `fd` with `max_depth=1`, includes directories, disables ignore rules, and sorts by name. Set `hidden=True` for `ls -a` behaviour. All `fd` filters remain available.
|
|
79
80
|
|
|
80
81
|
`fd_iter` yields absolute `Path` objects as the walk finds them. It accepts every `fd` filter. Stopping iteration ends the walk. It does not accept `timeout_ms`.
|
|
81
82
|
|
|
@@ -92,10 +93,10 @@ Patterns support backreferences and lookaround everywhere, including filename an
|
|
|
92
93
|
```python
|
|
93
94
|
rg(r"\b(\w+)\s+\1\b", ".") # repeated words
|
|
94
95
|
rg(r"(?<=TODO: )\w+", ".") # word following TODO:
|
|
95
|
-
fd(
|
|
96
|
+
fd(r"^(\w+)_\1\.py$") # names such as utils_utils.py
|
|
96
97
|
```
|
|
97
98
|
|
|
98
|
-
All regex parameters use `fancy-regex
|
|
99
|
+
All regex parameters use `fancy-regex`, with no engine-selection flag and no C library. Ordinary patterns, including word boundaries (`\b`, `\B`) outside lookbehinds, use its non-backtracking engine. Patterns requiring backtracking have a step budget that allows lines of millions of characters. A search that exceeds the budget raises `ValueError`. It never silently skips a file or path.
|
|
99
100
|
|
|
100
101
|
Each `SearchLine` has these fields:
|
|
101
102
|
|
|
@@ -114,7 +115,7 @@ matches list of (start, end) byte offsets for match rows
|
|
|
114
115
|
|
|
115
116
|
Pass `lnhashs=True` to `rg` or `rg_iter` to display hash addresses instead of line numbers. The `line_number` field remains available.
|
|
116
117
|
|
|
117
|
-
For other result forms, use `rg(..., paths=True)` to return unique matched paths
|
|
118
|
+
For other result forms, use `rg(..., paths=True)` to return unique matched paths, `rg(..., count=True)` to count match spans, or `rg(..., count="file")` for a dict from each file's label to its count, sorted by label. `paths` and `count` cannot both be set.
|
|
118
119
|
|
|
119
120
|
`^` and `$` match at the start and end of each line. A line ends at `\n` or `\r\n`. `$` also matches before a `\r` that has no `\n` after it. `rg`, `rgstr`, and `compile` reject patterns containing a literal `\n` or `\r`. `nbrg` allows them with `multiline=True`.
|
|
120
121
|
|
|
@@ -122,10 +123,10 @@ Content searches and compiled content matchers are confined to individual lines:
|
|
|
122
123
|
|
|
123
124
|
### Path results
|
|
124
125
|
|
|
125
|
-
`fd
|
|
126
|
+
`fd` and `ls` return `PathResults`, a list of absolute `Path` objects. So do `rg` and `nbrg` with `paths=True`, and their async equivalents. Indexing or iterating returns ordinary Paths:
|
|
126
127
|
|
|
127
128
|
```python
|
|
128
|
-
for path in fd("src", ext="py"):
|
|
129
|
+
for path in fd(root="src", ext="py"):
|
|
129
130
|
text = path.read_text()
|
|
130
131
|
size = path.stat().st_size
|
|
131
132
|
```
|
|
@@ -142,13 +143,13 @@ Rust callers can set `FindOptions::special_files` to also discover FIFOs, socket
|
|
|
142
143
|
|
|
143
144
|
### Limits and timeouts
|
|
144
145
|
|
|
145
|
-
Set `timeout_ms` on `rg`, `fd
|
|
146
|
+
Set `timeout_ms` on `rg`, `fd` or `ls` to stop at a deadline and return the results collected so far. Their async versions accept it too. Results report why the operation stopped:
|
|
146
147
|
|
|
147
148
|
- `stop_reason=None` means the result is complete.
|
|
148
149
|
- `stop_reason="max_results"` means `max_results` truncated the result.
|
|
149
150
|
- `stop_reason="timeout"` means the deadline was reached.
|
|
150
151
|
|
|
151
|
-
`complete` is true exactly when `stop_reason` is `None`.
|
|
152
|
+
`complete` is true exactly when `stop_reason` is `None`. A count is a plain integer or dict, with no completion flag. Counting can't be combined with `timeout_ms`.
|
|
152
153
|
|
|
153
154
|
Deadlines stop result collection and request worker cancellation. Workers cannot interrupt a regex evaluation or filesystem call already in progress; a timeout is not a hard per-match execution limit.
|
|
154
155
|
|
|
@@ -215,7 +216,7 @@ A matching cell's display starts at its first matched line. Earlier lines are re
|
|
|
215
216
|
- `count=True` returns the number of matching cells.
|
|
216
217
|
- `timeout_ms` applies a deadline with the same `stop_reason` values as `rg`.
|
|
217
218
|
|
|
218
|
-
The parser reads only each cell's `id`, `cell_type`, and `source`. It skips outputs and metadata without loading embedded images or plots. `search_nb(pattern, path, ...)` searches a single notebook file in the same way.
|
|
219
|
+
The parser reads only each cell's `id`, `cell_type`, and `source`. It skips outputs and metadata without loading embedded images or plots. `search_nb(pattern, path, ...)` searches a single notebook file in the same way. `nbrg` skips a `.ipynb` file that isn't valid JSON and issues a `RuntimeWarning` naming the file and the parse error. `search_nb` raises `ValueError` for such a file.
|
|
219
220
|
|
|
220
221
|
`rgapi-nbrg` exposes notebook search without requiring a Python kernel:
|
|
221
222
|
|
|
@@ -235,7 +236,7 @@ Run `rgapi-nbrg --help` for its discovery, matching, and output options.
|
|
|
235
236
|
```python
|
|
236
237
|
from rgapi import fda, rga, rga_iter
|
|
237
238
|
|
|
238
|
-
await fda(
|
|
239
|
+
await fda(ext="py")
|
|
239
240
|
res = await rga("TODO", ".", timeout_ms=200)
|
|
240
241
|
if not res.complete: print(f"partial results: {res.stop_reason}")
|
|
241
242
|
async for row in rga_iter("TODO", "."): ...
|
|
@@ -11,7 +11,7 @@ test = false
|
|
|
11
11
|
[dependencies]
|
|
12
12
|
rgapi = { path = ".." }
|
|
13
13
|
grep-matcher.workspace = true
|
|
14
|
-
pyo3 = { version = ">=0.
|
|
14
|
+
pyo3 = { version = ">=0.30", features = ["extension-module"] }
|
|
15
15
|
|
|
16
16
|
[build-dependencies]
|
|
17
|
-
pyo3-build-config = "0.29"
|
|
17
|
+
pyo3-build-config = ">=0.29"
|