{"id":2814,"library":"trailrunner","title":"Trailrunner","description":"Trailrunner is a simple Python library for walking paths on the filesystem and executing functions for each file found. It efficiently handles large codebases by respecting project-level `.gitignore` files and leveraging a process pool for concurrent function execution. It's designed for use by linting, formatting, and other developer tools that need to find and operate on all files in a project in a predictable fashion with a minimal API. The current version is 1.4.0, and it generally sees a few releases per year, often for bug fixes or minor feature additions.","status":"active","version":"1.4.0","language":"en","source_language":"en","source_url":"https://github.com/omnilib/trailrunner","tags":["file system","path management","walk","runner","gitignore","multiprocessing","developer tools"],"install":[{"cmd":"pip install trailrunner","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Used for parsing .gitignore files and excluding paths.","package":"pathspec"}],"imports":[{"symbol":"walk","correct":"from trailrunner import walk"},{"symbol":"run","correct":"from trailrunner import run"},{"symbol":"walk_and_run","correct":"from trailrunner import walk_and_run"}],"quickstart":{"code":"import os\nfrom pathlib import Path\nfrom trailrunner import walk_and_run\n\n# Create a dummy directory structure for demonstration\nos.makedirs(\"my_project/src\", exist_ok=True)\nos.makedirs(\"my_project/tests\", exist_ok=True)\nwith open(\"my_project/src/app.py\", \"w\") as f:\n    f.write(\"print('Hello from app.py')\")\nwith open(\"my_project/tests/test_app.py\", \"w\") as f:\n    f.write(\"print('Running tests')\")\nwith open(\"my_project/.gitignore\", \"w\") as f:\n    f.write(\"*.tmp\\n\")\nwith open(\"my_project/temp.tmp\", \"w\") as f:\n    f.write(\"temp file\") # This should be ignored\n\ndef process_file(path: Path) -> str:\n    \"\"\"A simple function to process a file path.\"\"\"\n    return f\"Processed: {path.name}\"\n\n# Walk the 'my_project' directory and run 'process_file' on each non-ignored file\n# trailrunner respects .gitignore for exclusions\nresults = walk_and_run([Path(\"my_project\")], process_file)\n\nprint(\"--- Trailrunner Results ---\")\nfor path, result in results.items():\n    print(f\"{path}: {result}\")\n\n# Expected output for existing files, excluding 'temp.tmp'\n# (Order may vary due to multiprocessing)\n# my_project/src/app.py: Processed: app.py\n# my_project/tests/test_app.py: Processed: test_app.py\n","lang":"python","description":"This quickstart demonstrates how to use `walk_and_run` to find files within a directory, respecting `.gitignore` rules, and apply a custom function to each found file. It creates a dummy project structure to illustrate the functionality."},"warnings":[{"fix":"Upgrade your Python environment to 3.7 or higher.","message":"Python 3.6 support was dropped in Trailrunner v1.1.0 and again in v1.3.0. Users on Python 3.6 must upgrade to Python 3.7 or newer to use current versions of Trailrunner.","severity":"breaking","affected_versions":">=1.1.0, >=1.3.0"},{"fix":"Review existing scripts that rely on previous path exclusion behavior, especially those operating near the project root or with complex `.gitignore` rules, to ensure compatibility with the new logic.","message":"As of v1.4.0, Trailrunner modified its path resolution behavior to \"Always resolve and exclude paths relative to project root\". This ensures that paths are walked and excluded in a manner more consistent with `git`'s behavior, preventing exclusions based on path segments outside the project root.","severity":"gotcha","affected_versions":"1.4.0"},{"fix":"For advanced use cases, consult the documentation for the `Trailrunner` class. For basic usage, the wrapper functions `walk`, `run`, and `walk_and_run` remain stable and functional.","message":"Version 1.1.0 introduced a new, class-based API (`Trailrunner` class) internally. While the `walk()`, `run()`, and `walk_and_run()` functions continue to exist as simple wrappers around this new class, direct interaction with the `Trailrunner` class for advanced use cases (e.g., custom configuration or extensibility) might require familiarization with the new object-oriented structure.","severity":"gotcha","affected_versions":">=1.1.0"}],"env_vars":null,"last_verified":"2026-04-10T00:00:00.000Z","next_check":"2026-07-09T00:00:00.000Z"}