From 16bf07d90b51e24c35d9d5c21a3f107cbbb98d1c Mon Sep 17 00:00:00 2001 From: Ryan Galloway Date: Wed, 12 Aug 2026 06:15:27 -0700 Subject: [PATCH 1/4] Skip shell env noise when matching pathbase templates --- lib/pathbase/template.py | 12 +++++++++++- tests/test_template.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/pathbase/template.py b/lib/pathbase/template.py index 7b0c427..b60b337 100644 --- a/lib/pathbase/template.py +++ b/lib/pathbase/template.py @@ -88,6 +88,7 @@ def _default_scope(path: PathInput) -> str: def _iter_template_items(env: Mapping[str, Any]) -> List[Tuple[str, str]]: """Return environment entries that look like path templates.""" + formatter = string.Formatter() items = [] for key, value in env.items(): if not isinstance(value, str) or not value: @@ -96,6 +97,12 @@ def _iter_template_items(env: Mapping[str, Any]) -> List[Tuple[str, str]]: continue if "/" not in value and "\\" not in value: continue + try: + parts = tuple(formatter.parse(_escape_env_vars(value))) + except ValueError: + continue + if not any(field_name is not None for _, field_name, _, _ in parts): + continue items.append((key, value)) return items @@ -186,7 +193,10 @@ def __init__( raise InvalidTemplateError(str(err)) from err self._fields: List[str] = [] self._formats: Dict[str, FieldType] = {} - self._pattern: Pattern[str] = self._compile_pattern() + try: + self._pattern = self._compile_pattern() + except re.error as err: + raise InvalidTemplateError(str(err)) from err def __repr__(self) -> str: return f"Template({self._template!r})" diff --git a/tests/test_template.py b/tests/test_template.py index 7069539..bc47960 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -245,6 +245,37 @@ def test_find_matching_templates_from_environment(): assert [name for name, _ in matches] == ["FILEPATH"] +def test_find_matching_templates_ignores_shell_env_values(): + env = { + "FILEPATH": "/mnt/x/{show}/shots/{sequence}/{shot}/{name}.mp4", + "BASH_FUNC_module%%": ( + " () { typeset swfound=1;\n" + " if [ \"${MODULES_USE_COMPAT_VERSION:-0}\" = '1' ]; then\n" + " typeset swname='main';\n" + " if [ -e /usr/share/Modules/libexec/modulecmd.tcl ]; then\n" + " typeset swfound=0;\n" + " unset MODULES_USE_COMPAT_VERSION;\n" + " fi;\n" + " else\n" + " typeset swname='compatibility';\n" + " if [ -e /usr/share/Modules/libexec/modulecmd-compat ]; then\n" + " typeset swfound=0;\n" + " MODULES_USE_COMPAT_VERSION=1;\n" + " export MODULES_USE_COMPAT_VERSION;\n" + " fi;\n" + " fi\n" + "}" + ), + } + + matches = find_matching_templates( + "/mnt/x/rhps/shots/00cr/00cr_0010/00cr_0010_plate.mp4", + env=env, + ) + + assert [name for name, _ in matches] == ["FILEPATH"] + + def test_match_template_returns_unique_match(): env = { "FILEPATH": "{project}/{name}_v{version:03d}.txt", From a1f5ad4e119210774cce3ab65dfa365e5033fa7a Mon Sep 17 00:00:00 2001 From: Ryan Galloway Date: Wed, 12 Aug 2026 06:18:50 -0700 Subject: [PATCH 2/4] Ignore shell env noise during template matching --- tests/test_template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_template.py b/tests/test_template.py index bc47960..97b0ec2 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -247,7 +247,7 @@ def test_find_matching_templates_from_environment(): def test_find_matching_templates_ignores_shell_env_values(): env = { - "FILEPATH": "/mnt/x/{show}/shots/{sequence}/{shot}/{name}.mp4", + "FILEPATH": "/mnt/projects/{project}/shots/{sequence}/{shot}/{name}.mp4", "BASH_FUNC_module%%": ( " () { typeset swfound=1;\n" " if [ \"${MODULES_USE_COMPAT_VERSION:-0}\" = '1' ]; then\n" @@ -269,7 +269,7 @@ def test_find_matching_templates_ignores_shell_env_values(): } matches = find_matching_templates( - "/mnt/x/rhps/shots/00cr/00cr_0010/00cr_0010_plate.mp4", + "/mnt/projects/demo/shots/seq001/shot010/shot010_plate.mp4", env=env, ) From e137b55112da1d3d20b5dfd181a3425649e3489f Mon Sep 17 00:00:00 2001 From: Ryan Galloway Date: Wed, 12 Aug 2026 06:21:01 -0700 Subject: [PATCH 3/4] Bump version to 0.1.2 --- lib/pathbase/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pathbase/__init__.py b/lib/pathbase/__init__.py index 385af63..6c1d109 100644 --- a/lib/pathbase/__init__.py +++ b/lib/pathbase/__init__.py @@ -63,4 +63,4 @@ "__version__", ] -__version__ = "0.1.1" +__version__ = "0.1.2" From a3208193b801436d07b93c00be1cbcd98432bd19 Mon Sep 17 00:00:00 2001 From: Ryan Galloway Date: Wed, 12 Aug 2026 07:12:41 -0700 Subject: [PATCH 4/4] Fix CLI docs for ROOT environment variable usage --- README.md | 4 ++-- docs/examples.md | 4 ++-- docs/index.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cd770e7..b0fa662 100644 --- a/README.md +++ b/README.md @@ -141,8 +141,8 @@ Parsing output: `pathbase` also includes a lightweight CLI: ```bash -pathbase format --template '${ROOT}/{project}/{name}_v{version:03d}.txt' \ - ROOT=/mnt/projects project=demo name=report version=1 +ROOT=/mnt/projects pathbase format --template '${ROOT}/{project}/{name}_v{version:03d}.txt' \ + project=demo name=report version=1 ENVPATH=./examples/vfx/ pathbase parse \ '/mnt/projects/bigbuckbunny/seq001/shot010/lighting/render_beauty_v001.1001.exr' diff --git a/docs/examples.md b/docs/examples.md index 2f7f08b..ed8e86d 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -451,8 +451,8 @@ The `pathbase` CLI provides a thin wrapper around the same template operations. Format a path from fields: ```bash -pathbase format --template '${ROOT}/{project}/{name}_v{version:03d}.txt' \ - ROOT=/mnt/projects project=demo name=report version=1 +ROOT=/mnt/projects pathbase format --template '${ROOT}/{project}/{name}_v{version:03d}.txt' \ + project=demo name=report version=1 ``` Expected output: diff --git a/docs/index.md b/docs/index.md index 97a094d..224b7cf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -134,8 +134,8 @@ Parsing output: `pathbase` also includes a lightweight CLI: ```bash -pathbase format --template '${ROOT}/{project}/{name}_v{version:03d}.txt' \ - ROOT=/mnt/projects project=demo name=report version=1 +ROOT=/mnt/projects pathbase format --template '${ROOT}/{project}/{name}_v{version:03d}.txt' \ + project=demo name=report version=1 ENVPATH=./examples/vfx/ pathbase parse \ '/mnt/projects/bigbuckbunny/seq001/shot010/lighting/render_beauty_v001.1001.exr'