Route filesystem paths through pattern -> handler -> pattern rules with visibility.
Project description
prouter
Route filesystem paths through pattern -> handler -> pattern rules with visibility.
The idea is simple. You define routes, each one an input pattern, a handler that rewrites a path, and an output pattern the result has to match. prouter walks a directory tree and runs every path through the route whose input pattern matches its basename, keeping track of what it did along the way.
It never touches the filesystem. Nothing gets moved or renamed. What you get back is a set of CSVs describing the transform it would apply, so you can look it over before committing to anything.
The tree is walked bottom-up, deepest paths first and the root last. This is deliberate: renaming children before their parents means a directory rename never invalidates paths you haven't reached yet. The CSVs preserve that order, so applying the rows top to bottom is always safe.
If the route-building syntax feels familiar, that's on purpose: it's inspired by LangGraph's way of wiring up nodes.
Install
pip install prouter
Requires Python 3.12+.
Usage
import re
from pathlib import Path
from prouter import GraphBuilder
# An input pattern, a handler (Path -> Path), and the output pattern the result must match.
draft = re.compile(r"(\d+)_draft\.wav")
final = re.compile(r"\d+_final\.wav")
def rename(path: Path) -> Path:
return path.with_name(path.name.replace("_draft", "_final"))
builder = GraphBuilder(root_path=Path("/path/to/draw/from"), results_folder=Path("/Folder/to/save/results"))
builder.add_route(draft, rename, final)
builder.build() # walk the tree, match routes, apply handlers in memory
builder.save() # write the result CSVs
[!NOTE] When adding a route with
add_routeYou can't register the same input pattern twice (a ValueError raises). Matching against those patterns is afullmatchagainst the whole basename, so a pattern has to account for the entire filename, not just part of it. And at build() time, only one input pattern may match a given path. If two would match, that's ambiguous and prouter raises rather than guess.
Output
save() drops four CSVs into the folder you give it:
routable_paths.csv— matched a route, and the handler's output lined up with the output pattern.problem_paths.csv— matched a route, but the handler's output did not match the output pattern. These are the ones to look at.clean_paths.csv— matched nothing, left alone.routes.csv— the routes you configured, on their own.
The path CSVs share the same columns: path, node, input_pattern, output_pattern, new_path. routes.csv just has input_pattern, node, output_pattern.
[!NOTE] In those columns, things show up under the names you gave them. Handlers use the function's
__name__, sorenamelands in the CSV asrename. Patterns are trickier, since a compiled regex has no name of its own, so prouter peeks at the calling frame and recovers the variable you bound it to:draftandfinalabove come out asdraftandfinal. Pass a barere.compile(...)inline with no variable and it falls back to the raw regex source.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file prouter-0.1.0.tar.gz.
File metadata
- Download URL: prouter-0.1.0.tar.gz
- Upload date:
- Size: 22.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fab8d0e24fe7246dc3c7a4b030f528c4fad2dfcfec3982389c8da1dc482a57d4
|
|
| MD5 |
9b2510747586c53e32deaf99ff133d7c
|
|
| BLAKE2b-256 |
aad41a3c7fe66480f0eb515e83f36b551529a2c6d68bd94355d118e1cb6159c7
|
Provenance
The following attestation bundles were made for prouter-0.1.0.tar.gz:
Publisher:
cd.yml on WISCLab/prouter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
prouter-0.1.0.tar.gz -
Subject digest:
fab8d0e24fe7246dc3c7a4b030f528c4fad2dfcfec3982389c8da1dc482a57d4 - Sigstore transparency entry: 1735597195
- Sigstore integration time:
-
Permalink:
WISCLab/prouter@f03163ce45375e4a3c7638e9d8b409a1e3effe90 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/WISCLab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cd.yml@f03163ce45375e4a3c7638e9d8b409a1e3effe90 -
Trigger Event:
release
-
Statement type:
File details
Details for the file prouter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: prouter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a14643505ad94123666030c2b2fb5a42920edf4e5c02fe4d0d55cd93086a63d3
|
|
| MD5 |
27b3f37c6a9aaf21b0917881fbd821a8
|
|
| BLAKE2b-256 |
63460c53238f962e6bea594dfb5f2417b23062498f65c7720fd2787f1a939b69
|
Provenance
The following attestation bundles were made for prouter-0.1.0-py3-none-any.whl:
Publisher:
cd.yml on WISCLab/prouter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
prouter-0.1.0-py3-none-any.whl -
Subject digest:
a14643505ad94123666030c2b2fb5a42920edf4e5c02fe4d0d55cd93086a63d3 - Sigstore transparency entry: 1735597265
- Sigstore integration time:
-
Permalink:
WISCLab/prouter@f03163ce45375e4a3c7638e9d8b409a1e3effe90 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/WISCLab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cd.yml@f03163ce45375e4a3c7638e9d8b409a1e3effe90 -
Trigger Event:
release
-
Statement type: