Skip to main content

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) — build drops .../build/... but not .../rebuild/....
  • Globs (allowed_patterns / exclude_patterns) match the root-relative path AND basename, so **/mct/*.py and *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.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for abstract-search 0.1.1
File Size Uploaded Provenance Actions
abstract_search-0.1.1.tar.gz 34.9 kB Without provenance Details for abstract_search-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for abstract-search 0.1.1
File Interpreter ABI Platform Actions
abstract_search-0.1.1-py3-none-any.whl Python 3 none any Details for abstract_search-0.1.1-py3-none-any.whl

Total release size: 67.1 kB

Release files / abstract_search-0.1.1.tar.gz

Download URL abstract_search-0.1.1.tar.gz
Size 34.9 kB
Tags Source
SHA-256 checksum
How to use checksums
949f645691d1269c8fe19c8ac0162fbbae9b0c02283231173f4405a3e8faae2b
BLAKE2b-256 checksum
How to use checksums
d80d8f9dff04ee0929778e63fd8ada85457451162bc4e4c828c652ebd17645fd
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.1-py3-none-any.whl

Download URL abstract_search-0.1.1-py3-none-any.whl
Size 32.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
18393f9ac239818ad0eb7bfd13931dcb467861ea797293ce436681e0e11e02a1
BLAKE2b-256 checksum
How to use checksums
a979a8481b55a40d2db5a12ccd34627ff4626318fae9ae4f9eb10813b30a5ebe
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.1

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page