abstract_search
Standalone string search across files and directories with allow/exclude filtering. Stdlib-only at import time — pdf, office, and spreadsheet readers load lazily and are optional extras.
from abstract_search import findContent, get_files_and_dirs, last_report
# 0.1.0: NO implicit filtering — searches EVERY readable file under the roots
hits = findContent("/path/to/project", strings=["needle"])
# opt into the old conveniences with a preset
hits = findContent("/path/to/project", strings=["needle"], preset="code")
# narrow explicitly; exclude a dir (exact segment, pruned)
hits = findContent("/path/to/project", strings=["needle"],
allowed_exts="py", exclude_dirs="tests")
# get the report inline (or call last_report())
res, rep = findContent("/path/to/project", strings=["needle"], report=True)
rep["effective_filters"]; rep["skipped"]
NO implicit filtering (0.1.0). With no filter kwargs you get EVERYTHING under
the roots — dotfiles, node_modules, .venv, binaries. There is no default
allow-whitelist, no default excluded dirs, no default hidden-file skipping.
define_defaults / get_file_filters reflect only user input + chosen presets.
Opt in explicitly with presets — preset="code" (CODE_TEXT_EXTS +
EXCLUDE_NOISE_DIRS, skip hidden), preset="noise" (EXCLUDE_NOISE_DIRS +
BINARY_EXTS, skip hidden), preset="text" — or pass the exported sets
CODE_TEXT_EXTS / EXCLUDE_NOISE_DIRS / BINARY_EXTS.
Preset merge = UNION (never be surprised): presets and your kwargs are
unioned field-by-field. Good for excludes; but the allow-whitelist is unioned
too, so a whitelist preset broadens — preset="code" + allowed_exts=[".rs"]
matches code/text AND .rs, not just .rs. To narrow by extension use
preset="noise" (excludes only) + your allowed_exts, or no preset.
When you do filter: exclude wins, include narrows, dir excludes are
exact path segments (pruned), globs match path AND basename, everything
case-insensitive. Content search skips binary files but reports them —
abstract_search.engine.last_report() (or report=True) carries the exact
effective_filters and skipped counts (binary/unreadable/too_large/
symlink_loop). The reader surface (search_files/read_paths, WalkConfig)
follows the same rule: DEFAULT_WALK is empty (searches everything); pass
preset=/filters to narrow; its report adds extract_failed for pdf/office read
errors. Remote/SSH search was removed in 0.1.0.
Search engine v2 (2026-09-24)
The search core is an isolated, stdlib-only engine in abstract_search/engine.py
(a pruned os.scandir walk that replaced the old find-subprocess design). The
public modules (filters, find_collect, find_content) are thin compat layers
over it. Identify the live engine at runtime:
import abstract_search
abstract_search.ENGINE # "abstract_search.engine v2 (2026-09-24)"
A byte-for-byte sibling copy lives at hugpy_tools.search and is kept in step
(abstract_* never imports hugpy_*).
Include / exclude semantics (now correct)
- Exclude always wins; include narrows. No include ⇒ everything not excluded.
- Directory excludes match an exact path segment and are pruned at
walk time (an excluded tree is never entered) —
builddrops.../build/...but not.../rebuild/.... - Globs (
allowed_patterns/exclude_patterns) match the root-relative path AND basename, so**/mct/*.pyand*session*work; exact names (session.py) match exactly. - Case: names/globs/extensions are case-insensitive; literal content search
is case-insensitive unless
case_sensitive=True, and matches inside comments and URLs (the old normalizer dropped those).
get_files_and_dirs(*args, recursive=True, include_files=True, **kwargs) is the
most-used entry point; its (dirs, files) shape and kwargs are unchanged. See
its docstring for the full include/exclude contract and examples.
Speed (best-of-2, 2026-09-24)
| tree | op | old (git HEAD) | engine v2 |
|---|---|---|---|
/srv/hugpy/src/hugpy |
get_files_and_dirs .py |
66.9 ms n=1046 | 19.4 ms n=1137 |
| literal | 327 ms | 96 ms | |
| regex | 133 ms | 52 ms | |
/srv/pyit/dev |
get_files_and_dirs .py |
366 ms n=4768 | 54 ms n=3351 |
| literal | 933 ms | 132 ms | |
| regex | 775 ms | 130 ms |
Count differences are bug fixes: v2 finds the __init__.py files the old
default dropped (91 / 818), and old returned .venv / site-packages /
hidden-backup files (2235 on /srv/pyit/dev) that v2 prunes. v2's enumerate
counts match the hugpy_tools.search sibling exactly.
from abstract_search import make_allowed_predicate, filter_allowed_items, search_files
allowed = make_allowed_predicate(exclude_exts=".log", add=True)
kept = filter_allowed_items(paths, allowed_exts=[".py", ".md"])
hits = search_files("needle", "/path/to/project") # line-level SearchHit records
Optional readers: pip install abstract_search[pdf] (pdfplumber),
[ocr], [xls], [xlsb], [dbf], [parquet], or [all].
Metadata
Release files for abstract-search 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| abstract_search-0.1.2.tar.gz | 34.9 kB | Without provenance | Details for abstract_search-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| abstract_search-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for abstract_search-0.1.2-py3-none-any.whl |
Total release size: 67.4 kB
Release files / abstract_search-0.1.2.tar.gz
| Download URL | abstract_search-0.1.2.tar.gz |
|---|---|
| Size | 34.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8250b4994e8842c2ceed93ca38a2dece3c35c56e37e381128009463154b6ec62
|
|
BLAKE2b-256 checksum How to use checksums |
94f6a0848d87f05c5fef9359d301a04cb140a7fd320233c5e73ab890843126cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / abstract_search-0.1.2-py3-none-any.whl
| Download URL | abstract_search-0.1.2-py3-none-any.whl |
|---|---|
| Size | 32.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6b967a1f235fab754f2083eea4bb31deb00f0aae9906b595d3d08300e87a2a33
|
|
BLAKE2b-256 checksum How to use checksums |
8d4adc95a22125d09d782ed78124cab4aa4e6c04865545bc7219d60ede983269
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for abstract-search 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.