mrkeyoor.com_
Sat 19 Sept 21:37 UTC
PyPIUtilsupdated 19 Sept 2026

pathspec review

pathspec 1.1.1 turns ordered gitignore-style lines into matchers for individual relative paths, path iterables, or directory trees. `PathSpec` implements the documented ignore pattern rules; `GitIgnoreSpec` covers places where Git's behavior differs, especially later rules that re-include paths. Version 1 added selectable regex backends and made `gitignore` the preferred pattern name. The 1.1.1 patch concentrates on type checking, including covariant PathSpec typing, pattern-factory hints, and addition operators.

Verdict

pathspec 1.1.1 installed in 0.2 seconds as 1 package using 1 MB, with typed metadata and 0 audit findings in our sandbox; use GitIgnoreSpec when a Python tool claims Git-like exclusions. Skip it for plain wildcards, and test ordered negations before any 0.x migration.

We installed it

Lab card: what happened when we installed pathspecScreenshot of pathspec documentation
Install✓ · 0.2s1 package on disk · 1 MB
Importimport pathspec in 0.21s · pure Python · py.typed · requires Python >=3.9
Known vulns0(pip-audit)

Answers from our run

Does pathspec install cleanly?

Yes. In a fresh container with an empty cache, pip install pathspec finished in 0.2s, leaving 1 package and 1 MB on disk. pip-audit reported no known vulnerabilities.

What does pathspec need to run?

Python >=3.9, and nothing compiled: it is pure Python. In our run import pathspec succeeded in 0.21s, and the package ships py.typed for type checkers.

pathspec or gitignore-parser: which should you use?

gitignore-parser: Choose its small file-oriented helper when one .gitignore file and a boolean matcher are enough. pathspec 1.1.1 installed in 0.2 seconds as 1 package using 1 MB, with typed metadata and 0 audit findings in our sandbox; use GitIgnoreSpec when a Python tool claims Git-like exclusions.

When should you not use pathspec?

The job is one or two shell wildcards; Python's fnmatch already handles that without another package.

API stability3/5Core calls such as from_lines(), match_file(), match_files(), and match_tree_files() remain recognizable, but version 1 renamed the preferred pattern style, introduced backend selection, and draws a meaningful line between PathSpec and GitIgnoreSpec results. Version 1.1.1 then corrected generic and operator typing. Existing 0.x code should run exact path fixtures before choosing the new semantic path.
Docs4/5Read the Docs includes a tutorial, API reference, change history, upgrade guide, backend discussion, and examples for file lists and trees. The README directly explains that Git sometimes differs from its documented ignore behavior and names GitIgnoreSpec as the closer implementation. More side-by-side cases for nested ignore files and directory reinclusion would make the hardest decisions easier.
Maintenance4/5GitHub showed a push on August 26, 2026, 13 open issues and pull requests, 233 stars, and an unarchived repository. PyPI lists 1.1.1, released after the larger version 1 backend and semantics work. The latest patch fixes several typing details rather than leaving the new generic API rough. The contributor base is still concentrated, which matters when exact Git parity is part of a product contract.
Ecosystem4/5PyPI Stats counted 175,451,140 downloads in the latest week. Ignore-rule handling is embedded transitively in formatters, documentation tools, packagers, and scanners, so usage far exceeds the repository's 233-star audience. The package is meant to be embedded rather than extended through plugins; optional re2 and Hyperscan backends are its main ecosystem boundary.

Discussed on

  1. hnShow HN: Follow lifetime changes of a pathspec in Git3 points

Use it if

  • A formatter, backup tool, packager, or scanner promises to honor familiar .gitignore-style rules.
  • Users need ordered negation rules rather than a fixed set of fnmatch wildcards.
  • One compiled specification will test many normalized paths or walk a directory tree.
  • Diagnostics need to identify the particular rule and position that produced a match decision.
Skip it if

Setup reality

We installed pathspec 1.1.1 in a fresh Python 3.12 Bookworm sandbox in 0.2 seconds. The install added 1 package and occupied 1 MB; pip-audit found 0 known vulnerabilities. import pathspec completed in 0.21 seconds. The distribution is pure Python, needs Python 3.9 or newer, reports 3 direct dependencies in our measurement, ships py.typed, and uses the Mozilla Public License 2.0.

Choose semantics before compiling rules. GitIgnoreSpec is the safer promise when output should match Git's observed edge cases. PathSpec.from_lines('gitignore', ...) follows the documented pattern implementation and supports the generic pattern abstraction. The older gitwildmatch style name is deprecated in version 1. Tests should cover leading slashes, directory suffixes, comments, escaped markers, and negations.

Rules operate on ordered, relative path text. Convert platform separators to forward slashes and make each path relative to the directory that owns the ignore file. Passing an absolute path often produces a believable but wrong miss. A trailing slash carries directory intent; standalone string matching does not inspect the filesystem, while tree methods can distinguish files during traversal.

Later lines can overturn earlier lines, so never sort or deduplicate a pattern file. check_file() can expose the deciding pattern for an explanation. The default best backend may select optional re2 or Hyperscan support when installed; the simple Python regex backend can be faster for only 1 or 2 patterns. Benchmark the real rule count before accepting native backend packaging and platform costs.

Patterns

Compile ordered ignore lines compile-rules

from pathspec import PathSpec

spec = PathSpec.from_lines('gitignore', [
    '*.pyc',
    'build/',
    '!build/keep.txt',
])
print(spec.match_file('module.pyc'))

Pattern order is observable. A later negation can reverse an earlier positive match.

Read rules with Git semantics load-gitignore

from pathspec import GitIgnoreSpec

with open('.gitignore', encoding='utf-8') as source:
    spec = GitIgnoreSpec.from_lines(source)

ignored = spec.match_file('dist/app.js')

Match paths relative to the directory containing this .gitignore file.

Match a portable relative path normalize-path

from pathlib import Path

root = Path('/srv/project')
candidate = Path('/srv/project/docs/guide.md')
relative = candidate.relative_to(root).as_posix()
ignored = spec.match_file(relative)

Anchored rules and directory patterns assume slash-separated names relative to their rule root.

Split ignored and kept files filter-paths

paths = ['src/app.py', 'cache/a.bin', 'notes.tmp']
ignored = set(spec.match_files(paths))
kept = [path for path in paths if path not in ignored]

match_files() yields paths that matched the specification; it does not return the kept side automatically.

Find matching files under a root walk-tree

for relative_path in spec.match_tree_files('/srv/project'):
    print(relative_path)

Tree methods return paths relative to the supplied root and still pay the cost of walking the filesystem.

Invert a tree selection select-kept-files

kept = set(
    spec.match_tree_files('/srv/project', negate=True)
)

`negate=True` reverses the final match decision, which is useful when assembling a package allowlist.

Append local overrides layer-rule-files

base = GitIgnoreSpec.from_lines(base_lines)
local = GitIgnoreSpec.from_lines(local_lines)
combined = base + local

Addition preserves line ordering, so patterns from `local` can change decisions made by `base`.

Inspect the deciding rule explain-match

result = spec.check_file('build/keep.txt')
print(result.include, result.index, result.pattern)

check_file() returns the last relevant pattern and its position, which is better for diagnostics than a bare boolean.

Alternatives

PackageRegistryPick it when
gitignore-parserPyPIChoose its small file-oriented helper when one .gitignore file and a boolean matcher are enough.
wcmatchPyPIChoose it for shell-style matching with brace expansion, extglob, and configurable globstar behavior.
glob2PyPIChoose it only for recursive include globs in older code that already depends on its pathlib-independent API.

More utils guides

lru-cache · type-fest · ajv · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.