filefilter 0.2.4__tar.gz → 0.2.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.
- {filefilter-0.2.4/src/filefilter.egg-info → filefilter-0.2.6}/PKG-INFO +58 -40
- {filefilter-0.2.4 → filefilter-0.2.6}/README.md +57 -39
- {filefilter-0.2.4 → filefilter-0.2.6}/pyproject.toml +1 -1
- {filefilter-0.2.4 → filefilter-0.2.6}/src/filefilter/__init__.py +14 -52
- {filefilter-0.2.4 → filefilter-0.2.6}/src/filefilter/collector.py +158 -55
- {filefilter-0.2.4 → filefilter-0.2.6}/src/filefilter/ruleset.py +3 -3
- {filefilter-0.2.4 → filefilter-0.2.6}/src/filefilter/utilities.py +21 -37
- {filefilter-0.2.4 → filefilter-0.2.6/src/filefilter.egg-info}/PKG-INFO +58 -40
- {filefilter-0.2.4 → filefilter-0.2.6}/src/filefilter.egg-info/SOURCES.txt +2 -0
- {filefilter-0.2.4 → filefilter-0.2.6}/tests/test_comprehensive.py +5 -5
- filefilter-0.2.6/tests/test_dry_run.py +136 -0
- {filefilter-0.2.4 → filefilter-0.2.6}/tests/test_inclusion_logic.py +2 -2
- {filefilter-0.2.4 → filefilter-0.2.6}/tests/test_matcher.py +3 -3
- {filefilter-0.2.4 → filefilter-0.2.6}/tests/test_ruleset.py +3 -6
- filefilter-0.2.6/tests/test_three_pass.py +436 -0
- {filefilter-0.2.4 → filefilter-0.2.6}/tests/test_utilities.py +28 -32
- {filefilter-0.2.4 → filefilter-0.2.6}/LICENSE +0 -0
- {filefilter-0.2.4 → filefilter-0.2.6}/setup.cfg +0 -0
- {filefilter-0.2.4 → filefilter-0.2.6}/src/filefilter.egg-info/dependency_links.txt +0 -0
- {filefilter-0.2.4 → filefilter-0.2.6}/src/filefilter.egg-info/requires.txt +0 -0
- {filefilter-0.2.4 → filefilter-0.2.6}/src/filefilter.egg-info/top_level.txt +0 -0
- {filefilter-0.2.4 → filefilter-0.2.6}/tests/test_readme_verification.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: filefilter
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.6
|
|
4
4
|
Summary: Filter files in a directory tree based on configurable glob rules.
|
|
5
5
|
Author-email: "Ioannis D (devcoons)" <support@devcoons.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -159,40 +159,55 @@ When scanning files, the library applies filters in this exact sequence:
|
|
|
159
159
|
|
|
160
160
|
1️⃣ **Extension excludes (hard)**
|
|
161
161
|
- If the file extension matches `exclude.extensions` → **excluded immediately**.
|
|
162
|
-
-
|
|
163
|
-
|
|
164
|
-
2️⃣ **
|
|
165
|
-
- If
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
> Use `include.dirs` for normal scoping
|
|
178
|
-
> Use `include.odirs`
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
3️⃣ **Include-file fast path**
|
|
162
|
+
- Not overridden by `odirs`, `ofiles`, or any other include rule.
|
|
163
|
+
|
|
164
|
+
2️⃣ **Pass 1 — Scope (`include.dirs`, `include.files`)**
|
|
165
|
+
- If any `include.dirs` or `include.files` patterns are set, the file must match **at least one** of them.
|
|
166
|
+
- Otherwise → **excluded** (excludes are not evaluated).
|
|
167
|
+
- `include.odirs` and `include.ofiles` do **not** define scope.
|
|
168
|
+
|
|
169
|
+
3️⃣ **Pass 2 — Path excludes (`exclude.dirs`, `exclude.files`)**
|
|
170
|
+
- If the file path matches `exclude.files`, or its parent directory matches `exclude.dirs` → **marked excluded**.
|
|
171
|
+
|
|
172
|
+
4️⃣ **Pass 3 — Overrides (`include.odirs`, `include.ofiles`)**
|
|
173
|
+
- If pass 2 excluded the file, a matching `include.odirs` or `include.ofiles` pattern → **exclude is undone**.
|
|
174
|
+
- If no override matches → **excluded**.
|
|
175
|
+
- Any matching override wins (no specificity scoring).
|
|
176
|
+
|
|
177
|
+
> Use `include.dirs` / `include.files` for normal scoping.
|
|
178
|
+
> Use `include.odirs` / `include.ofiles` only to carve exceptions out of pass-2 excludes.
|
|
179
|
+
|
|
180
|
+
5️⃣ **Include-file fast path**
|
|
182
181
|
- If the file matches any `include.files` pattern → **included immediately**,
|
|
183
182
|
even if its extension isn’t in `include.extensions`.
|
|
184
183
|
|
|
185
|
-
|
|
186
|
-
- If there are *any* include patterns (dirs or files), the file must match
|
|
187
|
-
at least one of them.
|
|
188
|
-
Otherwise, it’s excluded.
|
|
189
|
-
|
|
190
|
-
5️⃣ **Extension whitelist**
|
|
184
|
+
6️⃣ **Extension whitelist**
|
|
191
185
|
- If `include.extensions` is not empty, only matching extensions are included.
|
|
192
186
|
|
|
193
|
-
|
|
187
|
+
7️⃣ **Everything else**
|
|
194
188
|
- Included by default.
|
|
195
189
|
|
|
190
|
+
### Dry-run / rule hit report
|
|
191
|
+
|
|
192
|
+
`dry_run(rules)` walks the tree like `scan`, but also records how many files each rule pattern matched. Rule keys use the form `category:pattern`, e.g. `include.dirs:**`, `exclude.files:**/test_*.py`.
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from filefilter import dry_run, load
|
|
196
|
+
|
|
197
|
+
rules = load(cfg_json, base="cwd")
|
|
198
|
+
report = dry_run(rules)
|
|
199
|
+
|
|
200
|
+
report.scanned # files walked
|
|
201
|
+
report.included # paths that would be selected
|
|
202
|
+
report.excluded # scanned - included
|
|
203
|
+
report.hits # {"include.dirs:**": 42, ...}
|
|
204
|
+
report.was_hit("exclude.dirs:**/build/**")
|
|
205
|
+
report.has_rule("include.extensions:.py") # configured (may be 0)
|
|
206
|
+
report.count("include.extensions:.py")
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Hits count **pattern matches per file** during the walk. Path rules (`dirs`, `files`, …) match on every scanned file. `include.extensions` only counts files that **reach the extension whitelist** (not skipped by `include.files` fast path or earlier excludes). `exclude.extensions` matches on any scanned file. Configured extension patterns always appear in `report.hits` (with count `0` when unused). Keys use parsed form, e.g. `include.extensions:.py` for JSON `"py"`.
|
|
210
|
+
|
|
196
211
|
---
|
|
197
212
|
|
|
198
213
|
## Configuration Schema
|
|
@@ -220,10 +235,10 @@ When scanning files, the library applies filters in this exact sequence:
|
|
|
220
235
|
| Field | Description |
|
|
221
236
|
|-------|--------------|
|
|
222
237
|
| `root_dir` | Base directory (absolute or relative). |
|
|
223
|
-
| `filters.include.dirs` | Directory
|
|
224
|
-
| `filters.include.
|
|
225
|
-
| `filters.include.
|
|
226
|
-
| `filters.include.
|
|
238
|
+
| `filters.include.dirs` | Directory scope patterns. When set, files must live under a matching directory. Never overrides excludes. |
|
|
239
|
+
| `filters.include.files` | File scope patterns. When set (alone or with dirs), matching files pass pass 1. Also forces inclusion (skips extension whitelist) once later passes succeed. Does not override excludes. |
|
|
240
|
+
| `filters.include.odirs` | Optional override directory patterns (defaults to `[]`). Undo pass-2 `exclude.dirs` / `exclude.files` when matched. Do not define scope. |
|
|
241
|
+
| `filters.include.ofiles` | Optional override file patterns (defaults to `[]`). Undo pass-2 excludes when matched. Do not define scope or skip extension whitelist. |
|
|
227
242
|
| `filters.include.extensions` | Extension whitelist. |
|
|
228
243
|
| `filters.exclude.*` | Same structure, but acts as exclusion filters. |
|
|
229
244
|
|
|
@@ -466,7 +481,7 @@ Use `include.dirs` for the broad scope and `include.odirs` for the exception:
|
|
|
466
481
|
|------------|---------|--------|
|
|
467
482
|
| `src/foo.c` | ✅ | broad `**` include + `.c` extension |
|
|
468
483
|
| `src/KLM/skip.c` | ❌ | `**/KLM/**` exclude; no matching `odirs` |
|
|
469
|
-
| `src/KLM/ABC/keep.c` | ✅ | `**/KLM/ABC/**` odir
|
|
484
|
+
| `src/KLM/ABC/keep.c` | ✅ | `**/KLM/ABC/**` odir undoes `**/KLM/**` exclude |
|
|
470
485
|
| `src/x/KLM/ABC/deep/keep.c` | ✅ | odir exception works at any depth |
|
|
471
486
|
| `src/KLM/ABC/keep.txt` | ❌ | wrong extension (still inside the allowed dir) |
|
|
472
487
|
|
|
@@ -501,7 +516,7 @@ Exclude all `test_*.py` files, but keep `test_keep.py`:
|
|
|
501
516
|
|------------|---------|--------|
|
|
502
517
|
| `src/app.py` | ✅ | broad include + `.py` extension |
|
|
503
518
|
| `src/test_foo.py` | ❌ | `**/test_*.py` exclude; no matching `ofiles` |
|
|
504
|
-
| `src/test_keep.py` | ✅ | `**/test_keep.py` ofile
|
|
519
|
+
| `src/test_keep.py` | ✅ | `**/test_keep.py` ofile undoes `**/test_*.py` exclude |
|
|
505
520
|
| `nested/test_keep.py` | ✅ | ofile exception works at any depth |
|
|
506
521
|
|
|
507
522
|
---
|
|
@@ -509,9 +524,11 @@ Exclude all `test_*.py` files, but keep `test_keep.py`:
|
|
|
509
524
|
## Summary of Behavior
|
|
510
525
|
|
|
511
526
|
- `exclude.extensions` are always applied first (hard exclude).
|
|
512
|
-
- `include.dirs`
|
|
513
|
-
-
|
|
514
|
-
-
|
|
527
|
+
- **Pass 1:** `include.dirs` / `include.files` define scope (when set).
|
|
528
|
+
- **Pass 2:** `exclude.dirs` / `exclude.files` remove files.
|
|
529
|
+
- **Pass 3:** `include.odirs` / `include.ofiles` undo pass-2 excludes when matched.
|
|
530
|
+
- `include.dirs` and `include.files` **never** override excludes — use `odirs` / `ofiles`.
|
|
531
|
+
- A matching `include.files` pattern forces inclusion (skips extension whitelist) after passes 1–3.
|
|
515
532
|
- If any include filters exist, at least one must match (inclusion gating).
|
|
516
533
|
- Extensions act as a **final whitelist** when not bypassed by `include.files`.
|
|
517
534
|
- Matching is **case-insensitive** and normalized.
|
|
@@ -532,9 +549,6 @@ cfg_json = """{
|
|
|
532
549
|
}
|
|
533
550
|
}"""
|
|
534
551
|
|
|
535
|
-
# Deprecated option
|
|
536
|
-
files = filter_paths(cfg_json)
|
|
537
|
-
|
|
538
552
|
# Option 1: one-liner convenience
|
|
539
553
|
matched_files = select(cfg_json)
|
|
540
554
|
|
|
@@ -542,6 +556,10 @@ matched_files = select(cfg_json)
|
|
|
542
556
|
rules = load(cfg_json, base="cwd")
|
|
543
557
|
matched_files = scan(rules)
|
|
544
558
|
|
|
559
|
+
# Dry-run: same selection plus per-rule hit counts
|
|
560
|
+
report = dry_run(rules)
|
|
561
|
+
print(report.scanned, report.excluded, report.count("include.dirs:**"))
|
|
562
|
+
|
|
545
563
|
# Print any matched file
|
|
546
564
|
for f in matched_files:
|
|
547
565
|
print(f)
|
|
@@ -126,40 +126,55 @@ When scanning files, the library applies filters in this exact sequence:
|
|
|
126
126
|
|
|
127
127
|
1️⃣ **Extension excludes (hard)**
|
|
128
128
|
- If the file extension matches `exclude.extensions` → **excluded immediately**.
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
2️⃣ **
|
|
132
|
-
- If
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
> Use `include.dirs` for normal scoping
|
|
145
|
-
> Use `include.odirs`
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
3️⃣ **Include-file fast path**
|
|
129
|
+
- Not overridden by `odirs`, `ofiles`, or any other include rule.
|
|
130
|
+
|
|
131
|
+
2️⃣ **Pass 1 — Scope (`include.dirs`, `include.files`)**
|
|
132
|
+
- If any `include.dirs` or `include.files` patterns are set, the file must match **at least one** of them.
|
|
133
|
+
- Otherwise → **excluded** (excludes are not evaluated).
|
|
134
|
+
- `include.odirs` and `include.ofiles` do **not** define scope.
|
|
135
|
+
|
|
136
|
+
3️⃣ **Pass 2 — Path excludes (`exclude.dirs`, `exclude.files`)**
|
|
137
|
+
- If the file path matches `exclude.files`, or its parent directory matches `exclude.dirs` → **marked excluded**.
|
|
138
|
+
|
|
139
|
+
4️⃣ **Pass 3 — Overrides (`include.odirs`, `include.ofiles`)**
|
|
140
|
+
- If pass 2 excluded the file, a matching `include.odirs` or `include.ofiles` pattern → **exclude is undone**.
|
|
141
|
+
- If no override matches → **excluded**.
|
|
142
|
+
- Any matching override wins (no specificity scoring).
|
|
143
|
+
|
|
144
|
+
> Use `include.dirs` / `include.files` for normal scoping.
|
|
145
|
+
> Use `include.odirs` / `include.ofiles` only to carve exceptions out of pass-2 excludes.
|
|
146
|
+
|
|
147
|
+
5️⃣ **Include-file fast path**
|
|
149
148
|
- If the file matches any `include.files` pattern → **included immediately**,
|
|
150
149
|
even if its extension isn’t in `include.extensions`.
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
- If there are *any* include patterns (dirs or files), the file must match
|
|
154
|
-
at least one of them.
|
|
155
|
-
Otherwise, it’s excluded.
|
|
156
|
-
|
|
157
|
-
5️⃣ **Extension whitelist**
|
|
151
|
+
6️⃣ **Extension whitelist**
|
|
158
152
|
- If `include.extensions` is not empty, only matching extensions are included.
|
|
159
153
|
|
|
160
|
-
|
|
154
|
+
7️⃣ **Everything else**
|
|
161
155
|
- Included by default.
|
|
162
156
|
|
|
157
|
+
### Dry-run / rule hit report
|
|
158
|
+
|
|
159
|
+
`dry_run(rules)` walks the tree like `scan`, but also records how many files each rule pattern matched. Rule keys use the form `category:pattern`, e.g. `include.dirs:**`, `exclude.files:**/test_*.py`.
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from filefilter import dry_run, load
|
|
163
|
+
|
|
164
|
+
rules = load(cfg_json, base="cwd")
|
|
165
|
+
report = dry_run(rules)
|
|
166
|
+
|
|
167
|
+
report.scanned # files walked
|
|
168
|
+
report.included # paths that would be selected
|
|
169
|
+
report.excluded # scanned - included
|
|
170
|
+
report.hits # {"include.dirs:**": 42, ...}
|
|
171
|
+
report.was_hit("exclude.dirs:**/build/**")
|
|
172
|
+
report.has_rule("include.extensions:.py") # configured (may be 0)
|
|
173
|
+
report.count("include.extensions:.py")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Hits count **pattern matches per file** during the walk. Path rules (`dirs`, `files`, …) match on every scanned file. `include.extensions` only counts files that **reach the extension whitelist** (not skipped by `include.files` fast path or earlier excludes). `exclude.extensions` matches on any scanned file. Configured extension patterns always appear in `report.hits` (with count `0` when unused). Keys use parsed form, e.g. `include.extensions:.py` for JSON `"py"`.
|
|
177
|
+
|
|
163
178
|
---
|
|
164
179
|
|
|
165
180
|
## Configuration Schema
|
|
@@ -187,10 +202,10 @@ When scanning files, the library applies filters in this exact sequence:
|
|
|
187
202
|
| Field | Description |
|
|
188
203
|
|-------|--------------|
|
|
189
204
|
| `root_dir` | Base directory (absolute or relative). |
|
|
190
|
-
| `filters.include.dirs` | Directory
|
|
191
|
-
| `filters.include.
|
|
192
|
-
| `filters.include.
|
|
193
|
-
| `filters.include.
|
|
205
|
+
| `filters.include.dirs` | Directory scope patterns. When set, files must live under a matching directory. Never overrides excludes. |
|
|
206
|
+
| `filters.include.files` | File scope patterns. When set (alone or with dirs), matching files pass pass 1. Also forces inclusion (skips extension whitelist) once later passes succeed. Does not override excludes. |
|
|
207
|
+
| `filters.include.odirs` | Optional override directory patterns (defaults to `[]`). Undo pass-2 `exclude.dirs` / `exclude.files` when matched. Do not define scope. |
|
|
208
|
+
| `filters.include.ofiles` | Optional override file patterns (defaults to `[]`). Undo pass-2 excludes when matched. Do not define scope or skip extension whitelist. |
|
|
194
209
|
| `filters.include.extensions` | Extension whitelist. |
|
|
195
210
|
| `filters.exclude.*` | Same structure, but acts as exclusion filters. |
|
|
196
211
|
|
|
@@ -433,7 +448,7 @@ Use `include.dirs` for the broad scope and `include.odirs` for the exception:
|
|
|
433
448
|
|------------|---------|--------|
|
|
434
449
|
| `src/foo.c` | ✅ | broad `**` include + `.c` extension |
|
|
435
450
|
| `src/KLM/skip.c` | ❌ | `**/KLM/**` exclude; no matching `odirs` |
|
|
436
|
-
| `src/KLM/ABC/keep.c` | ✅ | `**/KLM/ABC/**` odir
|
|
451
|
+
| `src/KLM/ABC/keep.c` | ✅ | `**/KLM/ABC/**` odir undoes `**/KLM/**` exclude |
|
|
437
452
|
| `src/x/KLM/ABC/deep/keep.c` | ✅ | odir exception works at any depth |
|
|
438
453
|
| `src/KLM/ABC/keep.txt` | ❌ | wrong extension (still inside the allowed dir) |
|
|
439
454
|
|
|
@@ -468,7 +483,7 @@ Exclude all `test_*.py` files, but keep `test_keep.py`:
|
|
|
468
483
|
|------------|---------|--------|
|
|
469
484
|
| `src/app.py` | ✅ | broad include + `.py` extension |
|
|
470
485
|
| `src/test_foo.py` | ❌ | `**/test_*.py` exclude; no matching `ofiles` |
|
|
471
|
-
| `src/test_keep.py` | ✅ | `**/test_keep.py` ofile
|
|
486
|
+
| `src/test_keep.py` | ✅ | `**/test_keep.py` ofile undoes `**/test_*.py` exclude |
|
|
472
487
|
| `nested/test_keep.py` | ✅ | ofile exception works at any depth |
|
|
473
488
|
|
|
474
489
|
---
|
|
@@ -476,9 +491,11 @@ Exclude all `test_*.py` files, but keep `test_keep.py`:
|
|
|
476
491
|
## Summary of Behavior
|
|
477
492
|
|
|
478
493
|
- `exclude.extensions` are always applied first (hard exclude).
|
|
479
|
-
- `include.dirs`
|
|
480
|
-
-
|
|
481
|
-
-
|
|
494
|
+
- **Pass 1:** `include.dirs` / `include.files` define scope (when set).
|
|
495
|
+
- **Pass 2:** `exclude.dirs` / `exclude.files` remove files.
|
|
496
|
+
- **Pass 3:** `include.odirs` / `include.ofiles` undo pass-2 excludes when matched.
|
|
497
|
+
- `include.dirs` and `include.files` **never** override excludes — use `odirs` / `ofiles`.
|
|
498
|
+
- A matching `include.files` pattern forces inclusion (skips extension whitelist) after passes 1–3.
|
|
482
499
|
- If any include filters exist, at least one must match (inclusion gating).
|
|
483
500
|
- Extensions act as a **final whitelist** when not bypassed by `include.files`.
|
|
484
501
|
- Matching is **case-insensitive** and normalized.
|
|
@@ -499,9 +516,6 @@ cfg_json = """{
|
|
|
499
516
|
}
|
|
500
517
|
}"""
|
|
501
518
|
|
|
502
|
-
# Deprecated option
|
|
503
|
-
files = filter_paths(cfg_json)
|
|
504
|
-
|
|
505
519
|
# Option 1: one-liner convenience
|
|
506
520
|
matched_files = select(cfg_json)
|
|
507
521
|
|
|
@@ -509,6 +523,10 @@ matched_files = select(cfg_json)
|
|
|
509
523
|
rules = load(cfg_json, base="cwd")
|
|
510
524
|
matched_files = scan(rules)
|
|
511
525
|
|
|
526
|
+
# Dry-run: same selection plus per-rule hit counts
|
|
527
|
+
report = dry_run(rules)
|
|
528
|
+
print(report.scanned, report.excluded, report.count("include.dirs:**"))
|
|
529
|
+
|
|
512
530
|
# Print any matched file
|
|
513
531
|
for f in matched_files:
|
|
514
532
|
print(f)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "filefilter"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.6"
|
|
8
8
|
description = "Filter files in a directory tree based on configurable glob rules."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Ioannis D (devcoons)", email = "support@devcoons.com" }]
|
|
@@ -24,78 +24,40 @@
|
|
|
24
24
|
# #
|
|
25
25
|
#########################################################################################
|
|
26
26
|
|
|
27
|
-
__version__ = '0.2.
|
|
27
|
+
__version__ = '0.2.6'
|
|
28
28
|
|
|
29
29
|
#########################################################################################
|
|
30
30
|
# IMPORTS #
|
|
31
31
|
#########################################################################################
|
|
32
32
|
|
|
33
33
|
import json
|
|
34
|
-
import
|
|
35
|
-
from .
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
from .ruleset import Ruleset
|
|
35
|
+
from .collector import (
|
|
36
|
+
DryRunResult,
|
|
37
|
+
dry_run,
|
|
38
|
+
match_dir,
|
|
39
|
+
match_file,
|
|
40
|
+
matches,
|
|
41
|
+
scan,
|
|
42
|
+
)
|
|
38
43
|
|
|
39
44
|
__all__ = [
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
# Legacy API (still supported)
|
|
43
|
-
"filter_paths"
|
|
45
|
+
"Ruleset", "load", "scan", "matches", "select", "dry_run",
|
|
46
|
+
"DryRunResult", "match_dir", "match_file",
|
|
44
47
|
]
|
|
45
|
-
#########################################################################################
|
|
46
|
-
|
|
47
|
-
def _warn(old: str, new: str):
|
|
48
|
-
warnings.warn(
|
|
49
|
-
f"'filefilter.{old}' is deprecated and will be removed in 0.2.0; "
|
|
50
|
-
f"use 'filefilter.{new}'",
|
|
51
|
-
DeprecationWarning,
|
|
52
|
-
stacklevel=2,
|
|
53
|
-
)
|
|
54
48
|
|
|
55
49
|
#########################################################################################
|
|
56
50
|
|
|
57
51
|
def load(config_json: str, base: str = "cwd") -> Ruleset:
|
|
58
|
-
"""
|
|
59
|
-
Parse the config JSON and return a RuleSet resolved against `base`.
|
|
60
|
-
Equivalent to: RuleSet(json.loads(config_json), resolve_base=base)
|
|
61
|
-
"""
|
|
52
|
+
"""Parse config JSON and return a Ruleset resolved against `base`."""
|
|
62
53
|
data = json.loads(config_json)
|
|
63
54
|
return Ruleset(data, resolve_base=base)
|
|
64
55
|
|
|
65
56
|
#########################################################################################
|
|
66
57
|
|
|
67
|
-
def scan(rules: Ruleset) -> list[str]:
|
|
68
|
-
"""
|
|
69
|
-
Walk rules.root_dir and return files accepted by the rules.
|
|
70
|
-
Equivalent to: collect_files(rules)
|
|
71
|
-
"""
|
|
72
|
-
return collect_files(rules)
|
|
73
|
-
|
|
74
|
-
#########################################################################################
|
|
75
|
-
|
|
76
|
-
def matches(path: str, rules: Ruleset) -> bool:
|
|
77
|
-
"""
|
|
78
|
-
Return True if `path` would be included by `rules`.
|
|
79
|
-
Equivalent to: should_include(path, rules)
|
|
80
|
-
"""
|
|
81
|
-
return should_include(path, rules)
|
|
82
|
-
|
|
83
|
-
#########################################################################################
|
|
84
|
-
|
|
85
58
|
def select(config_json: str, base: str = "cwd") -> list[str]:
|
|
86
|
-
"""
|
|
87
|
-
Convenience: load(...) + scan(...).
|
|
88
|
-
"""
|
|
59
|
+
"""Convenience: load(...) + scan(...)."""
|
|
89
60
|
return scan(load(config_json, base=base))
|
|
90
61
|
|
|
91
62
|
#########################################################################################
|
|
92
|
-
|
|
93
|
-
def filter_paths(config_json: str, resolve_base: str = 'cwd'):
|
|
94
|
-
"""Load config JSON, build Config, and return collected files."""
|
|
95
|
-
_warn("filter_paths", "select")
|
|
96
|
-
data = json.loads(config_json)
|
|
97
|
-
cfg = Ruleset(data, resolve_base=resolve_base)
|
|
98
|
-
return collect_files(cfg)
|
|
99
|
-
|
|
100
63
|
#########################################################################################
|
|
101
|
-
#########################################################################################
|