rgapi 0.2.0__tar.gz → 0.2.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.
- {rgapi-0.2.0 → rgapi-0.2.2}/.github/workflows/ci.yml +3 -2
- {rgapi-0.2.0 → rgapi-0.2.2}/Cargo.lock +51 -29
- {rgapi-0.2.0 → rgapi-0.2.2}/Cargo.toml +24 -11
- {rgapi-0.2.0 → rgapi-0.2.2}/DEV.md +12 -7
- {rgapi-0.2.0 → rgapi-0.2.2}/PKG-INFO +22 -6
- {rgapi-0.2.0 → rgapi-0.2.2}/README.md +20 -4
- rgapi-0.2.2/py/Cargo.toml +17 -0
- rgapi-0.2.2/py/build.rs +1 -0
- rgapi-0.2.0/src/python.rs → rgapi-0.2.2/py/src/lib.rs +55 -24
- {rgapi-0.2.0 → rgapi-0.2.2}/pyproject.toml +3 -3
- {rgapi-0.2.0 → rgapi-0.2.2}/python/rgapi/__init__.py +10 -2
- {rgapi-0.2.0 → rgapi-0.2.2}/python/rgapi/_cli.py +1 -1
- {rgapi-0.2.0 → rgapi-0.2.2}/python/rgapi/nb.py +4 -2
- {rgapi-0.2.0 → rgapi-0.2.2}/python/rgapi/skill.py +1 -1
- {rgapi-0.2.0 → rgapi-0.2.2}/src/block.rs +8 -12
- {rgapi-0.2.0 → rgapi-0.2.2}/src/lib.rs +4 -5
- rgapi-0.2.2/src/matcher.rs +142 -0
- {rgapi-0.2.0 → rgapi-0.2.2}/src/nb.rs +20 -35
- {rgapi-0.2.0 → rgapi-0.2.2}/src/search.rs +18 -42
- {rgapi-0.2.0 → rgapi-0.2.2}/src/walk.rs +68 -73
- {rgapi-0.2.0 → rgapi-0.2.2}/tests/test_async.py +10 -0
- {rgapi-0.2.0 → rgapi-0.2.2}/tests/test_rgapi.py +65 -4
- {rgapi-0.2.0 → rgapi-0.2.2}/tools/bench.py +17 -18
- {rgapi-0.2.0 → rgapi-0.2.2}/.gitignore +0 -0
- {rgapi-0.2.0 → rgapi-0.2.2}/LICENSE +0 -0
- {rgapi-0.2.0 → rgapi-0.2.2}/_config.yml +0 -0
- {rgapi-0.2.0 → rgapi-0.2.2}/_layouts/default.html +0 -0
- {rgapi-0.2.0 → rgapi-0.2.2}/python/rgapi/block.py +0 -0
- {rgapi-0.2.0 → rgapi-0.2.2}/rustfmt.toml +0 -0
|
@@ -12,11 +12,12 @@ jobs:
|
|
|
12
12
|
steps:
|
|
13
13
|
- uses: actions/checkout@v7
|
|
14
14
|
- uses: dtolnay/rust-toolchain@stable
|
|
15
|
-
- run: cargo test
|
|
16
15
|
- uses: actions/setup-python@v7
|
|
17
16
|
with:
|
|
18
17
|
python-version: '3.12'
|
|
18
|
+
- run: cargo test
|
|
19
19
|
- run: pip install -e '.[dev]'
|
|
20
|
+
- run: cargo develop
|
|
20
21
|
- run: pytest -q
|
|
21
22
|
|
|
22
23
|
build:
|
|
@@ -61,7 +62,7 @@ jobs:
|
|
|
61
62
|
- uses: dtolnay/rust-toolchain@stable
|
|
62
63
|
- id: crates-auth
|
|
63
64
|
uses: rust-lang/crates-io-auth-action@v1
|
|
64
|
-
- run: cargo publish
|
|
65
|
+
- run: cargo publish -p rgapi
|
|
65
66
|
env:
|
|
66
67
|
CARGO_REGISTRY_TOKEN: ${{ steps.crates-auth.outputs.token }}
|
|
67
68
|
- uses: actions/download-artifact@v8
|
|
@@ -11,6 +11,21 @@ dependencies = [
|
|
|
11
11
|
"memchr",
|
|
12
12
|
]
|
|
13
13
|
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "bit-set"
|
|
16
|
+
version = "0.8.0"
|
|
17
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
+
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"bit-vec",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "bit-vec"
|
|
25
|
+
version = "0.8.0"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
|
28
|
+
|
|
14
29
|
[[package]]
|
|
15
30
|
name = "bstr"
|
|
16
31
|
version = "1.13.1"
|
|
@@ -18,7 +33,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
18
33
|
checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f"
|
|
19
34
|
dependencies = [
|
|
20
35
|
"memchr",
|
|
21
|
-
"regex-automata",
|
|
22
36
|
"serde_core",
|
|
23
37
|
]
|
|
24
38
|
|
|
@@ -91,6 +105,17 @@ dependencies = [
|
|
|
91
105
|
"encoding_rs",
|
|
92
106
|
]
|
|
93
107
|
|
|
108
|
+
[[package]]
|
|
109
|
+
name = "fancy-regex"
|
|
110
|
+
version = "0.19.2"
|
|
111
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
112
|
+
checksum = "d301f5bf187b3c295fce6468d3875037a0bccc5f6b151c63cac2f85babf21912"
|
|
113
|
+
dependencies = [
|
|
114
|
+
"bit-set",
|
|
115
|
+
"regex-automata",
|
|
116
|
+
"regex-syntax",
|
|
117
|
+
]
|
|
118
|
+
|
|
94
119
|
[[package]]
|
|
95
120
|
name = "globset"
|
|
96
121
|
version = "0.4.20"
|
|
@@ -113,19 +138,6 @@ dependencies = [
|
|
|
113
138
|
"memchr",
|
|
114
139
|
]
|
|
115
140
|
|
|
116
|
-
[[package]]
|
|
117
|
-
name = "grep-regex"
|
|
118
|
-
version = "0.1.14"
|
|
119
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
120
|
-
checksum = "0ce0c256c3ad82bcc07b812c15a45ec1d398122e8e15124f96695234db7112ef"
|
|
121
|
-
dependencies = [
|
|
122
|
-
"bstr",
|
|
123
|
-
"grep-matcher",
|
|
124
|
-
"log",
|
|
125
|
-
"regex-automata",
|
|
126
|
-
"regex-syntax",
|
|
127
|
-
]
|
|
128
|
-
|
|
129
141
|
[[package]]
|
|
130
142
|
name = "grep-searcher"
|
|
131
143
|
version = "0.1.17"
|
|
@@ -171,9 +183,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
|
171
183
|
|
|
172
184
|
[[package]]
|
|
173
185
|
name = "libc"
|
|
174
|
-
version = "0.2.
|
|
186
|
+
version = "0.2.190"
|
|
175
187
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
176
|
-
checksum = "
|
|
188
|
+
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
|
|
177
189
|
|
|
178
190
|
[[package]]
|
|
179
191
|
name = "log"
|
|
@@ -225,9 +237,9 @@ dependencies = [
|
|
|
225
237
|
|
|
226
238
|
[[package]]
|
|
227
239
|
name = "pyo3"
|
|
228
|
-
version = "0.29.
|
|
240
|
+
version = "0.29.3"
|
|
229
241
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
230
|
-
checksum = "
|
|
242
|
+
checksum = "700d18fa267b73b9b521fd7e13580e2f446916f176cacee1ab63fcc8191f1655"
|
|
231
243
|
dependencies = [
|
|
232
244
|
"libc",
|
|
233
245
|
"once_cell",
|
|
@@ -239,18 +251,18 @@ dependencies = [
|
|
|
239
251
|
|
|
240
252
|
[[package]]
|
|
241
253
|
name = "pyo3-build-config"
|
|
242
|
-
version = "0.29.
|
|
254
|
+
version = "0.29.3"
|
|
243
255
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
244
|
-
checksum = "
|
|
256
|
+
checksum = "7b3fc0c4d08f6bb10e71fe39dfb9e2f59c6eb6854e22ec8092f50c69a4499adb"
|
|
245
257
|
dependencies = [
|
|
246
258
|
"target-lexicon",
|
|
247
259
|
]
|
|
248
260
|
|
|
249
261
|
[[package]]
|
|
250
262
|
name = "pyo3-ffi"
|
|
251
|
-
version = "0.29.
|
|
263
|
+
version = "0.29.3"
|
|
252
264
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
253
|
-
checksum = "
|
|
265
|
+
checksum = "dfc0b8e19df29aad7086cf977bb0c2a2f143e30567eb113e9cf72b62ca698330"
|
|
254
266
|
dependencies = [
|
|
255
267
|
"libc",
|
|
256
268
|
"pyo3-build-config",
|
|
@@ -258,9 +270,9 @@ dependencies = [
|
|
|
258
270
|
|
|
259
271
|
[[package]]
|
|
260
272
|
name = "pyo3-macros"
|
|
261
|
-
version = "0.29.
|
|
273
|
+
version = "0.29.3"
|
|
262
274
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
263
|
-
checksum = "
|
|
275
|
+
checksum = "6100e8a4b5eba53afaa5ed078364851a0b2499c553a44c31026b929049b49dc6"
|
|
264
276
|
dependencies = [
|
|
265
277
|
"proc-macro2",
|
|
266
278
|
"pyo3-macros-backend",
|
|
@@ -270,9 +282,9 @@ dependencies = [
|
|
|
270
282
|
|
|
271
283
|
[[package]]
|
|
272
284
|
name = "pyo3-macros-backend"
|
|
273
|
-
version = "0.29.
|
|
285
|
+
version = "0.29.3"
|
|
274
286
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
275
|
-
checksum = "
|
|
287
|
+
checksum = "6143877a16e82b5a727b7127ff4cd86858a24a28d745d72f43e6f227c7b1bdb3"
|
|
276
288
|
dependencies = [
|
|
277
289
|
"heck",
|
|
278
290
|
"proc-macro2",
|
|
@@ -308,19 +320,29 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
|
|
308
320
|
|
|
309
321
|
[[package]]
|
|
310
322
|
name = "rgapi"
|
|
311
|
-
version = "0.2.
|
|
323
|
+
version = "0.2.2"
|
|
312
324
|
dependencies = [
|
|
313
325
|
"crc32fast",
|
|
326
|
+
"fancy-regex",
|
|
314
327
|
"globset",
|
|
315
328
|
"grep-matcher",
|
|
316
|
-
"grep-regex",
|
|
317
329
|
"grep-searcher",
|
|
318
330
|
"ignore",
|
|
319
|
-
"
|
|
331
|
+
"regex-syntax",
|
|
320
332
|
"serde",
|
|
321
333
|
"serde_json",
|
|
322
334
|
]
|
|
323
335
|
|
|
336
|
+
[[package]]
|
|
337
|
+
name = "rgapi-py"
|
|
338
|
+
version = "0.2.2"
|
|
339
|
+
dependencies = [
|
|
340
|
+
"grep-matcher",
|
|
341
|
+
"pyo3",
|
|
342
|
+
"pyo3-build-config",
|
|
343
|
+
"rgapi",
|
|
344
|
+
]
|
|
345
|
+
|
|
324
346
|
[[package]]
|
|
325
347
|
name = "rustversion"
|
|
326
348
|
version = "1.0.23"
|
|
@@ -1,37 +1,44 @@
|
|
|
1
|
+
[workspace]
|
|
2
|
+
members = ["py"]
|
|
3
|
+
|
|
4
|
+
[workspace.package]
|
|
5
|
+
version = "0.2.2"
|
|
6
|
+
edition = "2024"
|
|
7
|
+
|
|
8
|
+
[workspace.dependencies]
|
|
9
|
+
grep-matcher = ">=0.1.8"
|
|
10
|
+
|
|
1
11
|
[package]
|
|
2
12
|
name = "rgapi"
|
|
3
|
-
version =
|
|
4
|
-
edition =
|
|
13
|
+
version.workspace = true
|
|
14
|
+
edition.workspace = true
|
|
5
15
|
rust-version = "1.91"
|
|
6
16
|
license = "Apache-2.0"
|
|
7
17
|
description = "Python API for ripgrep-style file walking and searching"
|
|
8
18
|
repository = "https://github.com/AnswerDotAI/rgapi"
|
|
9
19
|
homepage = "https://github.com/AnswerDotAI/rgapi"
|
|
10
20
|
documentation = "https://github.com/AnswerDotAI/rgapi"
|
|
11
|
-
readme = "README.md"
|
|
12
21
|
|
|
13
22
|
[lib]
|
|
14
23
|
name = "rgapi"
|
|
15
|
-
crate-type = ["cdylib", "rlib"]
|
|
16
24
|
|
|
17
25
|
[dependencies]
|
|
18
26
|
crc32fast = "1"
|
|
27
|
+
fancy-regex = "0.19"
|
|
19
28
|
globset = ">=0.4.18"
|
|
20
|
-
grep-matcher =
|
|
21
|
-
grep-regex = ">=0.1.14"
|
|
29
|
+
grep-matcher.workspace = true
|
|
22
30
|
grep-searcher = ">=0.1.16"
|
|
23
31
|
ignore = ">=0.4.26"
|
|
24
|
-
|
|
32
|
+
regex-syntax = "0.8"
|
|
25
33
|
serde = { version = "=1", features = ["derive"] }
|
|
26
34
|
serde_json = "=1"
|
|
27
35
|
|
|
28
|
-
[features]
|
|
29
|
-
python = ["dep:pyo3"]
|
|
30
|
-
extension-module = ["python", "pyo3/extension-module"]
|
|
31
|
-
|
|
32
36
|
[lints.clippy]
|
|
33
37
|
too_many_arguments = "allow"
|
|
34
38
|
|
|
39
|
+
[profile.test]
|
|
40
|
+
inherits = "release"
|
|
41
|
+
|
|
35
42
|
[profile.release]
|
|
36
43
|
lto = false
|
|
37
44
|
codegen-units = 16
|
|
@@ -39,6 +46,9 @@ codegen-units = 16
|
|
|
39
46
|
[profile.release.package.rgapi]
|
|
40
47
|
incremental = true
|
|
41
48
|
|
|
49
|
+
[profile.release.package.rgapi-py]
|
|
50
|
+
incremental = true
|
|
51
|
+
|
|
42
52
|
[profile.dist]
|
|
43
53
|
inherits = "release"
|
|
44
54
|
lto = true
|
|
@@ -48,3 +58,6 @@ strip = true
|
|
|
48
58
|
|
|
49
59
|
[profile.dist.package.rgapi]
|
|
50
60
|
incremental = false
|
|
61
|
+
|
|
62
|
+
[profile.dist.package.rgapi-py]
|
|
63
|
+
incremental = false
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
## Layout
|
|
6
6
|
|
|
7
7
|
```text
|
|
8
|
-
src/
|
|
9
|
-
src/
|
|
8
|
+
src/matcher.rs shared fancy-regex engine, smart-case policy, and grep-matcher adapter
|
|
9
|
+
src/walk.rs ignore/globset-backed path walking and filtering
|
|
10
|
+
src/search.rs grep-searcher-backed searching
|
|
10
11
|
src/block.rs blank-line-delimited block grouping, matching, and block context
|
|
11
|
-
src/
|
|
12
|
+
py/src/lib.rs PyO3 classes and private core functions
|
|
12
13
|
python/rgapi/ public Python wrappers over `rgapi._core`, plus the `rgapi-nbrg` CLI
|
|
13
14
|
tests/ pytest coverage for the Python API
|
|
14
15
|
```
|
|
@@ -18,11 +19,11 @@ The public Python API lives in `python/rgapi/__init__.py`. The extension module
|
|
|
18
19
|
## Commands
|
|
19
20
|
|
|
20
21
|
```bash
|
|
21
|
-
|
|
22
|
+
cargo develop
|
|
22
23
|
pytest -q
|
|
23
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 fmt` after Rust edits and `chkstyle` before committing Python edits.
|
|
26
27
|
|
|
27
28
|
## Release
|
|
28
29
|
|
|
@@ -30,14 +31,18 @@ The canonical version lives in `Cargo.toml`. `pyproject.toml` gets the Python pa
|
|
|
30
31
|
|
|
31
32
|
Release flow is: release first, then bump - `ship-release` does both.
|
|
32
33
|
|
|
33
|
-
1. Run `
|
|
34
|
-
2. Confirm the release version in `Cargo.toml` (`[package].version`).
|
|
34
|
+
1. Run `cargo develop && pytest -q`.
|
|
35
|
+
2. Confirm the release version in `Cargo.toml` (`[workspace.package].version`).
|
|
35
36
|
3. Run `ship-release`. It tags `v<version>`, pushes branch and tag (CI builds and publishes), then bumps `Cargo.toml`, refreshes the editable install, and pushes the bump without a tag.
|
|
36
37
|
|
|
37
38
|
The GitHub workflow builds wheels for Python 3.10-3.13 on Linux and macOS and publishes the Rust crate, GitHub release artifacts, and PyPI package when a `v*` tag is pushed.
|
|
38
39
|
|
|
39
40
|
## Design notes
|
|
40
41
|
|
|
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
|
+
|
|
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 or inspect neighbouring lines are evaluated on individual lines. 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
|
+
|
|
41
46
|
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.
|
|
42
47
|
|
|
43
48
|
Streaming engine: `walk.rs` owns the generic machinery. `StreamIter<T>` is the worker-thread-plus-bounded-channel iterator (`sync_channel(8192)`, so producers block rather than buffer without limit when a consumer lags), and `spawn_walk` owns the shared scaffold: walker config, panic catching, cancel flag, and worker thread. `rg_iter` (`T = SearchLine`), `block_iter` (`T = SearchBlock`), `nb_iter` (`T = NbCell`), and `find_iter` (`T = PathBuf`, the path walk) plug entry closures into that engine. Block search reads each file once, searches it once, groups nonblank lines into blocks, maps matching lines to their blocks, and expands context by block index. Each `SearchBlock` carries numeric boundaries plus hashes for its first and last source lines. Python keeps both and chooses the displayed address without another file read.
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rgapi
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Requires-Dist: fastcore>=2.2.29
|
|
7
|
+
Requires-Dist: fastws-cli>=0.0.20 ; extra == 'dev'
|
|
7
8
|
Requires-Dist: fastship>=0.0.12 ; extra == 'dev'
|
|
8
9
|
Requires-Dist: maturin>=1.0,<2.0 ; extra == 'dev'
|
|
9
10
|
Requires-Dist: pytest ; extra == 'dev'
|
|
10
11
|
Provides-Extra: dev
|
|
11
12
|
License-File: LICENSE
|
|
12
13
|
Summary: Python API for ripgrep-style file walking and searching
|
|
13
|
-
Home-Page: https://github.com/AnswerDotAI/rgapi
|
|
14
14
|
Author-email: Jeremy Howard <j@fast.ai>
|
|
15
15
|
License-Expression: Apache-2.0
|
|
16
16
|
Requires-Python: >=3.10
|
|
@@ -23,7 +23,7 @@ Project-URL: Repository, https://github.com/AnswerDotAI/rgapi
|
|
|
23
23
|
|
|
24
24
|
`rgapi` provides `fd`-style file discovery and `rg`-style text search from Python without starting a shell command.
|
|
25
25
|
|
|
26
|
-
It uses
|
|
26
|
+
It uses ripgrep's `ignore` and `grep-searcher` crates for walking and file scanning, with the pure-Rust `fancy-regex` engine for regex matching. Walking and searching run in parallel by default. Most expensive work stays in Rust.
|
|
27
27
|
|
|
28
28
|
## Overview
|
|
29
29
|
|
|
@@ -108,6 +108,16 @@ Set `min_depth` and `max_depth` to bound recursion. `max_filesize` skips files a
|
|
|
108
108
|
|
|
109
109
|
Search is case-sensitive by default, matching `rg`. Use `smart_case=True` for `rg --smart-case` behaviour. Use `case_sensitive=False` to force case-insensitive matching.
|
|
110
110
|
|
|
111
|
+
Patterns support backreferences and lookaround everywhere, including filename and path filters:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
rg(r"\b(\w+)\s+\1\b", ".") # repeated words
|
|
115
|
+
rg(r"(?<=TODO: )\w+", ".") # word following TODO:
|
|
116
|
+
fd(".", pattern=r"^(\w+)_\1\.py$") # names such as utils_utils.py
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
All regex parameters use `fancy-regex`; no engine-selection flag or C library is required. Ordinary patterns use its non-backtracking engine. Patterns requiring backtracking have a bounded backtracking budget; exceeding it raises `ValueError`, rather than silently skipping a file or path.
|
|
120
|
+
|
|
111
121
|
Each `SearchLine` has these fields:
|
|
112
122
|
|
|
113
123
|
```text
|
|
@@ -127,7 +137,9 @@ Pass `lnhashs=True` to `rg` or `rg_iter` to display hash addresses instead of li
|
|
|
127
137
|
|
|
128
138
|
For other result forms, use `rg(..., paths=True)` to return unique matched paths or `rg(..., count=True)` to count match spans. `paths` and `count` cannot both be set.
|
|
129
139
|
|
|
130
|
-
`^` 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 `
|
|
140
|
+
`^` 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
|
+
Content searches and compiled content matchers are confined to individual lines: whitespace classes, backreferences and lookaround cannot cross a line ending, and `\A`/`\z` refer to each line. With `nbrg(..., multiline=True)`, `\A`/`\z` refer to the whole cell, while `^`/`$` still anchor lines. Filename and path filters match the full name or path instead.
|
|
131
143
|
|
|
132
144
|
### Path results
|
|
133
145
|
|
|
@@ -159,6 +171,8 @@ Set `timeout_ms` on `rg`, `fd`, `walk`, or `ls` to stop at a deadline and return
|
|
|
159
171
|
|
|
160
172
|
`complete` is true exactly when `stop_reason` is `None`. `count=True` returns a plain integer without a completion flag. It cannot be combined with `timeout_ms`.
|
|
161
173
|
|
|
174
|
+
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
|
+
|
|
162
176
|
### Context lines
|
|
163
177
|
|
|
164
178
|
`before_context`, `after_context`, and `context` correspond to `rg -B`, `rg -A`, and `rg -C`. Files containing NUL bytes or invalid UTF-8 are skipped.
|
|
@@ -190,7 +204,9 @@ nbrg("read_csv", ".") # cells whose source matches, across all
|
|
|
190
204
|
nbrg("read_csv", ".", cell_context=1) # also include neighbouring cells as context
|
|
191
205
|
```
|
|
192
206
|
|
|
193
|
-
Notebook discovery, parsing, and matching run together in one parallel Rust pass. Matching uses `
|
|
207
|
+
Notebook discovery, parsing, and matching run together in one parallel Rust pass. Matching uses the same `fancy-regex` engine as `rgapi.rg`, including backreferences and lookaround, with the same `case_sensitive` and `smart_case` behaviour. `nbrg` accepts the discovery filters from `fd` and `rg`, including `include`, `exclude`, `glob`, `hidden`, `max_depth`, and `skip_dir`.
|
|
208
|
+
|
|
209
|
+
Matching is line-oriented by default. Use `nbrg(r"(foo)\n\1", ".", multiline=True)` to match across lines within a cell. Matches never cross cell boundaries.
|
|
194
210
|
|
|
195
211
|
`nbrg` returns `NbResults`, a list of `NbCell`. Each `NbCell` has:
|
|
196
212
|
|
|
@@ -248,7 +264,7 @@ async for row in rga_iter("TODO", "."): ...
|
|
|
248
264
|
|
|
249
265
|
Walking and searching use Rust threads, without `asyncio.to_thread` or the event loop's executor. A callback uses `loop.call_soon_threadsafe` to complete the awaited future or supply results to the generator's queue. The event loop remains unblocked, with normal `contextvars` behaviour.
|
|
250
266
|
|
|
251
|
-
Cancellation
|
|
267
|
+
Cancellation is checked between rows and files; it does not interrupt a regex evaluation or filesystem call already in progress. This includes timeouts from `asyncio.wait_for` or `asyncio.timeout`. It also includes task cancellation, such as starlette cancelling a disconnected client's request.
|
|
252
268
|
|
|
253
269
|
Wrap an async iterator in `contextlib.aclosing` when leaving its loop early. `break` alone delays generator finalization until garbage collection. The context manager provides prompt cleanup:
|
|
254
270
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`rgapi` provides `fd`-style file discovery and `rg`-style text search from Python without starting a shell command.
|
|
4
4
|
|
|
5
|
-
It uses
|
|
5
|
+
It uses ripgrep's `ignore` and `grep-searcher` crates for walking and file scanning, with the pure-Rust `fancy-regex` engine for regex matching. Walking and searching run in parallel by default. Most expensive work stays in Rust.
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
@@ -87,6 +87,16 @@ Set `min_depth` and `max_depth` to bound recursion. `max_filesize` skips files a
|
|
|
87
87
|
|
|
88
88
|
Search is case-sensitive by default, matching `rg`. Use `smart_case=True` for `rg --smart-case` behaviour. Use `case_sensitive=False` to force case-insensitive matching.
|
|
89
89
|
|
|
90
|
+
Patterns support backreferences and lookaround everywhere, including filename and path filters:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
rg(r"\b(\w+)\s+\1\b", ".") # repeated words
|
|
94
|
+
rg(r"(?<=TODO: )\w+", ".") # word following TODO:
|
|
95
|
+
fd(".", pattern=r"^(\w+)_\1\.py$") # names such as utils_utils.py
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
All regex parameters use `fancy-regex`; no engine-selection flag or C library is required. Ordinary patterns use its non-backtracking engine. Patterns requiring backtracking have a bounded backtracking budget; exceeding it raises `ValueError`, rather than silently skipping a file or path.
|
|
99
|
+
|
|
90
100
|
Each `SearchLine` has these fields:
|
|
91
101
|
|
|
92
102
|
```text
|
|
@@ -106,7 +116,9 @@ Pass `lnhashs=True` to `rg` or `rg_iter` to display hash addresses instead of li
|
|
|
106
116
|
|
|
107
117
|
For other result forms, use `rg(..., paths=True)` to return unique matched paths or `rg(..., count=True)` to count match spans. `paths` and `count` cannot both be set.
|
|
108
118
|
|
|
109
|
-
`^` 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 `
|
|
119
|
+
`^` 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
|
+
Content searches and compiled content matchers are confined to individual lines: whitespace classes, backreferences and lookaround cannot cross a line ending, and `\A`/`\z` refer to each line. With `nbrg(..., multiline=True)`, `\A`/`\z` refer to the whole cell, while `^`/`$` still anchor lines. Filename and path filters match the full name or path instead.
|
|
110
122
|
|
|
111
123
|
### Path results
|
|
112
124
|
|
|
@@ -138,6 +150,8 @@ Set `timeout_ms` on `rg`, `fd`, `walk`, or `ls` to stop at a deadline and return
|
|
|
138
150
|
|
|
139
151
|
`complete` is true exactly when `stop_reason` is `None`. `count=True` returns a plain integer without a completion flag. It cannot be combined with `timeout_ms`.
|
|
140
152
|
|
|
153
|
+
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
|
+
|
|
141
155
|
### Context lines
|
|
142
156
|
|
|
143
157
|
`before_context`, `after_context`, and `context` correspond to `rg -B`, `rg -A`, and `rg -C`. Files containing NUL bytes or invalid UTF-8 are skipped.
|
|
@@ -169,7 +183,9 @@ nbrg("read_csv", ".") # cells whose source matches, across all
|
|
|
169
183
|
nbrg("read_csv", ".", cell_context=1) # also include neighbouring cells as context
|
|
170
184
|
```
|
|
171
185
|
|
|
172
|
-
Notebook discovery, parsing, and matching run together in one parallel Rust pass. Matching uses `
|
|
186
|
+
Notebook discovery, parsing, and matching run together in one parallel Rust pass. Matching uses the same `fancy-regex` engine as `rgapi.rg`, including backreferences and lookaround, with the same `case_sensitive` and `smart_case` behaviour. `nbrg` accepts the discovery filters from `fd` and `rg`, including `include`, `exclude`, `glob`, `hidden`, `max_depth`, and `skip_dir`.
|
|
187
|
+
|
|
188
|
+
Matching is line-oriented by default. Use `nbrg(r"(foo)\n\1", ".", multiline=True)` to match across lines within a cell. Matches never cross cell boundaries.
|
|
173
189
|
|
|
174
190
|
`nbrg` returns `NbResults`, a list of `NbCell`. Each `NbCell` has:
|
|
175
191
|
|
|
@@ -227,7 +243,7 @@ async for row in rga_iter("TODO", "."): ...
|
|
|
227
243
|
|
|
228
244
|
Walking and searching use Rust threads, without `asyncio.to_thread` or the event loop's executor. A callback uses `loop.call_soon_threadsafe` to complete the awaited future or supply results to the generator's queue. The event loop remains unblocked, with normal `contextvars` behaviour.
|
|
229
245
|
|
|
230
|
-
Cancellation
|
|
246
|
+
Cancellation is checked between rows and files; it does not interrupt a regex evaluation or filesystem call already in progress. This includes timeouts from `asyncio.wait_for` or `asyncio.timeout`. It also includes task cancellation, such as starlette cancelling a disconnected client's request.
|
|
231
247
|
|
|
232
248
|
Wrap an async iterator in `contextlib.aclosing` when leaving its loop early. `break` alone delays generator finalization until garbage collection. The context manager provides prompt cleanup:
|
|
233
249
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "rgapi-py"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
publish = false
|
|
6
|
+
|
|
7
|
+
[lib]
|
|
8
|
+
crate-type = ["cdylib", "rlib"]
|
|
9
|
+
test = false
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
rgapi = { path = ".." }
|
|
13
|
+
grep-matcher.workspace = true
|
|
14
|
+
pyo3 = { version = ">=0.29", features = ["extension-module"] }
|
|
15
|
+
|
|
16
|
+
[build-dependencies]
|
|
17
|
+
pyo3-build-config = "0.29"
|
rgapi-0.2.2/py/build.rs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fn main() { pyo3_build_config::add_extension_module_link_args(); }
|