rgapi 0.1.4__tar.gz → 0.1.6__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.1.4 → rgapi-0.1.6}/.github/workflows/ci.yml +7 -32
- {rgapi-0.1.4 → rgapi-0.1.6}/Cargo.lock +1 -1
- {rgapi-0.1.4 → rgapi-0.1.6}/Cargo.toml +3 -4
- {rgapi-0.1.4 → rgapi-0.1.6}/DEV.md +1 -1
- {rgapi-0.1.4 → rgapi-0.1.6}/PKG-INFO +1 -1
- {rgapi-0.1.4 → rgapi-0.1.6}/pyproject.toml +3 -0
- {rgapi-0.1.4 → rgapi-0.1.6}/src/lib.rs +0 -1
- {rgapi-0.1.4 → rgapi-0.1.6}/src/search.rs +0 -50
- {rgapi-0.1.4 → rgapi-0.1.6}/src/walk.rs +0 -40
- {rgapi-0.1.4 → rgapi-0.1.6}/tests/test_rgapi.py +8 -0
- {rgapi-0.1.4 → rgapi-0.1.6}/.gitignore +0 -0
- {rgapi-0.1.4 → rgapi-0.1.6}/README.md +0 -0
- {rgapi-0.1.4 → rgapi-0.1.6}/python/rgapi/__init__.py +0 -0
- {rgapi-0.1.4 → rgapi-0.1.6}/src/python.rs +0 -0
- {rgapi-0.1.4 → rgapi-0.1.6}/tools/bench.py +0 -0
|
@@ -7,45 +7,20 @@ on:
|
|
|
7
7
|
pull_request:
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
linux:
|
|
17
|
-
needs: test
|
|
18
|
-
runs-on: ubuntu-latest
|
|
10
|
+
build:
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
os: [ubuntu-latest, macos-latest]
|
|
14
|
+
runs-on: ${{ matrix.os }}
|
|
19
15
|
steps:
|
|
20
16
|
- uses: actions/checkout@v6
|
|
21
17
|
- uses: PyO3/maturin-action@v1
|
|
22
18
|
with:
|
|
23
19
|
args: --release --out dist -i python3.10 -i python3.11 -i python3.12 -i python3.13
|
|
24
20
|
manylinux: auto
|
|
25
|
-
before-script-linux: |
|
|
26
|
-
python3.13 -m pip install 'fastship>=0.0.13'
|
|
27
|
-
python3.13 -m fastship.rs_prep --release
|
|
28
|
-
- uses: actions/upload-artifact@v4
|
|
29
|
-
with:
|
|
30
|
-
name: wheels-linux
|
|
31
|
-
path: dist
|
|
32
|
-
|
|
33
|
-
macos:
|
|
34
|
-
needs: test
|
|
35
|
-
runs-on: macos-latest
|
|
36
|
-
steps:
|
|
37
|
-
- uses: actions/checkout@v6
|
|
38
|
-
- uses: actions/setup-python@v6
|
|
39
|
-
with:
|
|
40
|
-
python-version: '3.13'
|
|
41
|
-
- run: python -m pip install 'fastship>=0.0.13'
|
|
42
|
-
- run: python -m fastship.rs_prep --release
|
|
43
|
-
- uses: PyO3/maturin-action@v1
|
|
44
|
-
with:
|
|
45
|
-
args: --release --out dist -i python3.10 -i python3.11 -i python3.12 -i python3.13
|
|
46
21
|
- uses: actions/upload-artifact@v4
|
|
47
22
|
with:
|
|
48
|
-
name: wheels
|
|
23
|
+
name: wheels-${{ matrix.os }}
|
|
49
24
|
path: dist
|
|
50
25
|
|
|
51
26
|
sdist:
|
|
@@ -63,7 +38,7 @@ jobs:
|
|
|
63
38
|
|
|
64
39
|
publish:
|
|
65
40
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
66
|
-
needs: [
|
|
41
|
+
needs: [build, sdist]
|
|
67
42
|
runs-on: ubuntu-latest
|
|
68
43
|
permissions:
|
|
69
44
|
id-token: write
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "rgapi"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.6"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
license = "MIT OR Apache-2.0"
|
|
6
6
|
description = "Python API for ripgrep-style file walking and searching"
|
|
@@ -19,8 +19,7 @@ grep-matcher = ">=0.1.8"
|
|
|
19
19
|
grep-regex = ">=0.1.14"
|
|
20
20
|
grep-searcher = ">=0.1.16"
|
|
21
21
|
ignore = ">=0.4.26"
|
|
22
|
-
pyo3 =
|
|
22
|
+
pyo3 = ">=0.28"
|
|
23
23
|
|
|
24
24
|
[features]
|
|
25
|
-
extension-module = ["pyo3
|
|
26
|
-
pyo3 = ["dep:pyo3"]
|
|
25
|
+
extension-module = ["pyo3/extension-module"]
|
|
@@ -20,7 +20,7 @@ The public Python API lives in `python/rgapi/__init__.py`. The extension module
|
|
|
20
20
|
ship-rs-test
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Run `cargo fmt --check` and `cargo check` for Rust-only edits. Run `chkstyle` after Python edits once tests pass.
|
|
23
|
+
All tests are Python (`tests/`), run against the built extension; there are no `cargo test` unit tests. For a fast local loop use `maturin develop && pytest -q`. Run `cargo fmt --check` and `cargo check` for Rust-only edits. Run `chkstyle` after Python edits once tests pass.
|
|
24
24
|
|
|
25
25
|
## Release
|
|
26
26
|
|
|
@@ -23,6 +23,9 @@ Homepage = "https://github.com/AnswerDotAI/rgapi"
|
|
|
23
23
|
Repository = "https://github.com/AnswerDotAI/rgapi"
|
|
24
24
|
Issues = "https://github.com/AnswerDotAI/rgapi/issues"
|
|
25
25
|
|
|
26
|
+
[project.entry-points.fastaudit_safe_native]
|
|
27
|
+
rgapi = "rgapi"
|
|
28
|
+
|
|
26
29
|
[tool.maturin]
|
|
27
30
|
features = ["extension-module"]
|
|
28
31
|
python-source = "python"
|
|
@@ -490,53 +490,3 @@ pub(crate) fn spans_for(
|
|
|
490
490
|
.map_err(|e| SearchError::Message(e.to_string()))?;
|
|
491
491
|
Ok(spans)
|
|
492
492
|
}
|
|
493
|
-
#[cfg(test)]
|
|
494
|
-
mod tests {
|
|
495
|
-
use super::*;
|
|
496
|
-
#[test]
|
|
497
|
-
fn context_rows_keep_kind_enum_and_public_strings() {
|
|
498
|
-
let matcher = compile_regex("TODO", None, true).unwrap();
|
|
499
|
-
let lines = search_text(
|
|
500
|
-
"memory.txt".to_string(),
|
|
501
|
-
"alpha\nTODO here\nomega\n",
|
|
502
|
-
matcher,
|
|
503
|
-
1,
|
|
504
|
-
1,
|
|
505
|
-
)
|
|
506
|
-
.unwrap();
|
|
507
|
-
let got: Vec<_> = lines
|
|
508
|
-
.iter()
|
|
509
|
-
.map(|line| (line.kind.as_str(), line.line_number, line.line.as_str()))
|
|
510
|
-
.collect();
|
|
511
|
-
assert_eq!(
|
|
512
|
-
got,
|
|
513
|
-
vec![
|
|
514
|
-
("before", 1, "alpha"),
|
|
515
|
-
("match", 2, "TODO here"),
|
|
516
|
-
("after", 3, "omega")
|
|
517
|
-
]
|
|
518
|
-
);
|
|
519
|
-
assert_eq!(lines[1].matches, vec![MatchSpan { start: 0, end: 4 }]);
|
|
520
|
-
}
|
|
521
|
-
fn temp_path(name: &str) -> std::path::PathBuf {
|
|
522
|
-
std::env::temp_dir().join(format!("rgapi-{}-{name}", std::process::id()))
|
|
523
|
-
}
|
|
524
|
-
#[test]
|
|
525
|
-
fn search_path_skips_binary_files() {
|
|
526
|
-
let path = temp_path("binary.dat");
|
|
527
|
-
std::fs::write(&path, b"TODO before\n\0TODO after\n").unwrap();
|
|
528
|
-
let matcher = compile_regex("TODO", None, true).unwrap();
|
|
529
|
-
let lines = search_path(&path, "binary.dat".to_string(), matcher, 0, 0).unwrap();
|
|
530
|
-
let _ = std::fs::remove_file(&path);
|
|
531
|
-
assert!(lines.is_empty());
|
|
532
|
-
}
|
|
533
|
-
#[test]
|
|
534
|
-
fn search_path_skips_invalid_utf8_files() {
|
|
535
|
-
let path = temp_path("invalid.txt");
|
|
536
|
-
std::fs::write(&path, b"TODO\xff\n").unwrap();
|
|
537
|
-
let matcher = compile_regex("TODO", None, true).unwrap();
|
|
538
|
-
let lines = search_path(&path, "invalid.txt".to_string(), matcher, 0, 0).unwrap();
|
|
539
|
-
let _ = std::fs::remove_file(&path);
|
|
540
|
-
assert!(lines.is_empty());
|
|
541
|
-
}
|
|
542
|
-
}
|
|
@@ -297,43 +297,3 @@ fn build_path_re(pattern: Option<&str>) -> Result<Option<RegexMatcher>, RgApiErr
|
|
|
297
297
|
fn re_match(matcher: &RegexMatcher, rel: &str) -> bool {
|
|
298
298
|
matcher.is_match(rel.as_bytes()).unwrap_or(false)
|
|
299
299
|
}
|
|
300
|
-
|
|
301
|
-
#[cfg(test)]
|
|
302
|
-
mod tests {
|
|
303
|
-
use super::*;
|
|
304
|
-
use std::path::Path;
|
|
305
|
-
|
|
306
|
-
#[test]
|
|
307
|
-
fn basename_globs_match_nested_paths() {
|
|
308
|
-
let glob = build_globs(&["*.py".to_string()]).unwrap().unwrap();
|
|
309
|
-
assert!(glob.is_match(Path::new("app.py")));
|
|
310
|
-
assert!(glob.is_match(Path::new("src/app.py")));
|
|
311
|
-
assert!(!glob.is_match(Path::new("src/app.rs")));
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
#[test]
|
|
315
|
-
fn path_filters_include_exclude_and_regex_paths() {
|
|
316
|
-
let empty = Vec::new();
|
|
317
|
-
let filters = PathFilters::new(
|
|
318
|
-
&["*.py".to_string()],
|
|
319
|
-
&["skip.py".to_string()],
|
|
320
|
-
Some(r"src/"),
|
|
321
|
-
Some(r"test_"),
|
|
322
|
-
&empty,
|
|
323
|
-
None,
|
|
324
|
-
)
|
|
325
|
-
.unwrap();
|
|
326
|
-
assert!(filters.path_allowed("src/app.py"));
|
|
327
|
-
assert!(!filters.path_allowed("src/skip.py"));
|
|
328
|
-
assert!(!filters.path_allowed("src/app.rs"));
|
|
329
|
-
assert!(!filters.path_allowed("app.py"));
|
|
330
|
-
assert!(!filters.path_allowed("src/test_app.py"));
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
#[test]
|
|
334
|
-
fn relative_paths_use_slashes() {
|
|
335
|
-
let root = Path::new("project");
|
|
336
|
-
let path = root.join("src").join("app.py");
|
|
337
|
-
assert_eq!(rel_path(root, &path), "src/app.py");
|
|
338
|
-
}
|
|
339
|
-
}
|
|
@@ -121,6 +121,14 @@ def test_rg_returns_structured_matches_context_and_relative_paths(tmp_path):
|
|
|
121
121
|
assert str(stream) == repr(stream)
|
|
122
122
|
|
|
123
123
|
|
|
124
|
+
def test_search_path_skips_binary_and_invalid_utf8(tmp_path):
|
|
125
|
+
(tmp_path / "bin.dat").write_bytes(b"TODO before\n\0TODO after\n")
|
|
126
|
+
(tmp_path / "bad.txt").write_bytes(b"TODO\xff\n")
|
|
127
|
+
matcher = compile("TODO")
|
|
128
|
+
assert search_path(matcher, tmp_path / "bin.dat") == []
|
|
129
|
+
assert search_path(matcher, tmp_path / "bad.txt") == []
|
|
130
|
+
|
|
131
|
+
|
|
124
132
|
def test_rg_keyboard_interrupt_cancels(tmp_path):
|
|
125
133
|
(tmp_path / "big.txt").write_text("alpha beta gamma\n" * 1_000_000)
|
|
126
134
|
timer = threading.Timer(0.001, _thread.interrupt_main)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|