Skip to content

Latest commit

 

History

History
184 lines (145 loc) · 5.54 KB

overrides.md

File metadata and controls

184 lines (145 loc) · 5.54 KB
layout default
title Overrides
description Patterns for layering shared and project-specific pathbase templates.

Overrides

pathbase works especially well with envstack-managed environments, where template strings, overrides, and platform-specific roots can be layered through ENVPATH. For envstack documentation, see envstack.dev.

A common pattern is:

  • keep a shared production pathbase.env with opinionated baseline templates
  • make sure the shared env directory is present in ENVPATH
  • override only the values that differ for that project in higher-priority env files
  • avoid relying on ambient shell variables for template behavior

If envstack is not installed, pathbase can still consume direct environment variables or explicit env= mappings from Python, but the examples in this guide assume envstack is the primary workflow.

Shared Production Baseline

A shared production template file might look like this:

#!/usr/bin/env envstack
include: [default]
all: &all
  SHOW_ROOT: ${ROOT}/{show}
  SEQUENCE_ROOT: ${SHOW_ROOT}/{sequence}
  SHOT_ROOT: ${SEQUENCE_ROOT}/{shot}
  STEP_ROOT: ${SHOT_ROOT}/{step}
  FILEPATH: ${STEP_ROOT}/{task}_{descriptor}_v{version:03d}.{frame:04d}.{ext}
linux:
  <<: *all
  ROOT: /mnt/projects
darwin:
  <<: *all
  ROOT: /Volumes/projects
windows:
  <<: *all
  ROOT: D:/projects

This gives every project a stable naming model without depending on whatever ambient variables happen to be present in the shell.

Project-Specific Overrides

A project can then provide its own pathbase.env in a higher-priority env directory and override only the templates that differ. Because envstack is hierarchical, the project override does not need to re-include the shared pathbase file as long as the default env directory is already present in ENVPATH.

For example, bigbuckbunny/env/pathbase.env could look like this:

#!/usr/bin/env envstack
include: [default]
all: &all
  SHOW: bigbuckbunny
  SHOW_ROOT: ${ROOT}/bigbuckbunny
  # This show uses department-specific work areas under a tasks folder.
  STEP_ROOT: ${SHOT_ROOT}/tasks/{step}
  # This show also includes the shot in the filename itself.
  FILEPATH: ${STEP_ROOT}/{shot}_{task}_{descriptor}_v{version:03d}.{frame:04d}.{ext}
linux:
  <<: *all
darwin:
  <<: *all
windows:
  <<: *all

That override keeps the shared vocabulary, pins the show root, changes the step folder layout, and changes the filename pattern for one project.

Overrides should come from envstack hierarchy, not from ad hoc shell exports.

Token Rules

Token rules layer in the same way. List the shared rules file first and the project's after it in PATHBASE_RULES. The project's rules then replace the shared ones token by token, and leave the rest in force. In examples/overrides, shared/rules.json allows any lower-case sequence and shot names, and bigbuckbunny/rules.json narrows them for one show:

{
  "rules": {
    "sequence": "^seq[0-9]{3}$",
    "shot": "^shot[0-9]{3}$",
    "step": "^(layout|anim|fx|lighting|comp|render)$"
  }
}

With both files listed, .../sq1/shot010/... no longer matches for bigbuckbunny, while other shows keep the shared rules.

Current and Legacy Templates

Sometimes a production changes its filepath spec over time but still needs to parse older paths. A practical pattern is to keep one canonical write template and one or more legacy read templates in the same environment.

For example:

#!/usr/bin/env envstack
include: [default]
all: &all
  SHOW_ROOT: ${ROOT}/{show}
  SEQUENCE_ROOT: ${SHOW_ROOT}/{sequence}
  SHOT_ROOT: ${SEQUENCE_ROOT}/{shot}
  STEP_ROOT: ${SHOT_ROOT}/{step}
  # Current template used for formatting new paths.
  FILEPATH: ${STEP_ROOT}/{task}_{descriptor}_v{version:03d}.{frame:04d}.{ext}
  # Older layouts kept around for parsing historical data.
  FILEPATH_V1: ${SHOT_ROOT}/{task}/{task}_{descriptor}.{frame:04d}.{ext}
  FILEPATH_V2: ${STEP_ROOT}/{task}_{descriptor}.{frame:04d}.{ext}

This gives you a simple convention:

  • FILEPATH is the current authoritative write template
  • FILEPATH_V* values remain available for parsing older paths
  • new publishes use the current layout, while old files still round-trip cleanly

In application code, formatting can stay explicit:

from pathbase import Template

template = Template.from_env("FILEPATH")

For parsing, pathbase parse PATH and match_template(path) can match against any compatible template present in the environment.

A few conventions help keep this maintainable:

  • keep field names stable across template generations when the meaning is the same
  • prefer one current write template instead of writing through multiple variants
  • expect legacy templates to omit some newer fields
  • watch for ambiguity when two historical templates can both match the same path

Using the Resolved Template in Python

Once the environment is activated or resolved outside of pathbase, the application code stays simple:

import os

from pathbase import Template

template = Template.from_env("FILEPATH")

path = template.format(
    show="bigbuckbunny",
    sequence="seq001",
    shot="shot010",
    step="lighting",
    task="render",
    descriptor="beauty",
    version=1,
    frame=1001,
    ext="exr",
)

Why This Split Helps

  • shared defaults keep naming conventions consistent across projects
  • project overrides stay small and readable
  • pathbase remains dependency-free and only consumes the final template string
  • envstack remains responsible for inheritance, overrides, and platform roots