Skip to main content

fr_config - Floating Rock Cascading Config Resolver

fr_config is a hierarchical cascading config resolver that resolves configs based on hierarchy structure and schema.

This allows for a high degree of control over how configurations are loaded based on where they are in the filesystem.

Configs will load in the order of variant/default, parent.variant/parent.default until they either hit the root paths or a $parent redirect. A redirect allows for configs to jump or reference a shared directory.
For example a package config may have a manifests directory that can be referenced at any level of the hierarchy.

A Cascade is how the configs are applied via the schema. eg: given a list value, how is that resolved across configs? Do we append? prepend? replace?
If that list contains objects do we replace those? just where they conflict? or perhaps recursively update.
This cascade allows us to use the same config layer to apply to many data types while maintaining type coherence.

fr_config was designed to work with fr_env_resolver, Floating Rocks rez-based environment resolver for loading context dependent package lists.

Context Path Resolve

Contexts are .frconfigs that live in any directory, When a path is loaded, the variables "cascade" backwards up the tree for a final resolve.

This allows for per shot/asset variations.

It's important to note this is not restricted to production dirs, any directory can be used to cascade.

The process here is the same for Environment Contexts (packages, variables) and Tool Contexts (The subenvironment used by tools in the launcher)

Context Path Resolve

Variants

Inside the config resolve is something called "variants", By default, there is a "default" variant associated with each level in the hierarchy, but additional variants can be added to produce variations such as per department.

These variations are used in anything deriving from fr_config. Meaning you can have a variant for a context, manifest, workflow or tool.

If a variant is specified to a loader, it will attempt to load that variant any time it is available before loading the default variant. You cannot skip loading the default, if that is required then leave it blank and only use variants to provide details.

Context Path Resolve

Features

  • Hierarchical Configuration: Configs follow a filesystem path for resolving
  • Schema Validation: JSON Schema-based validation with custom type system
  • Version Management: Built-in versioning with tags (published, latest, deprecated, etc.)
  • Data Merging: Configurable cascade modes (replace, update, append, prepend)
  • Multi-Variant Support: Support for different configuration variants (departments, tasks, etc)

Quick Start

Important Note Any code inside the _internal/ folder is not gaurenteed to persist across versions and should not be used directly outside of debugging.

Installation

Local Installation

If you have the source code locally, navigate to the project directory and install it:

cd /path/to/fr_config
pip install .

or with rez:

cd /path/to/fr_config
rez-pip install .

Remote Installation

To install directly from this Git repository:

pip install git+https://github.com/FloatingRockStudio/fr_config.git

or with rez:

rez-pip install git+https://github.com/FloatingRockStudio/fr_config.git

Loading Configuration

from fr_config import ConfigLoader

# Load config from a specific path
config = ConfigLoader("simple", "/path/to/project")

# Access configuration data
fps = config.value("fps")
resolution = config.value("resolution")
tools = config.value("tools", [])  # With default value if not specified in schema

# Get all configuration keys
keys = config.keys()
key_paths = config.key_paths()  # Returns nested paths like "/playblast_settings/overscan"

Loading Specific Variants/Tags

# Load development variant
config = ConfigLoader("simple", "/path", variant="dev")

# Load with specific tags, first one in list that matches is used (if no wip, then latest is used)
config = ConfigLoader("simple", "/path", tags=["wip", "latest"])

# Load multiple variants, this will load /path/prod.fr_config then /path/default.fr_config.
config = ConfigLoader("simple", "/path", variant=["prod", "default"])
# If a string is passed then it will automatically change to [variant, "default"]
config = ConfigLoader("simple", "/path", variant="prod")

Writing Configuration

from fr_config import ConfigWriter

# Create or modify a config
writer = ConfigWriter("simple", "/path/to/project")
writer.set_data("fps", 30.0)
writer.set_data("resolution", [1920, 1080])

writer.commit("Updated resolution and fps")  # Save changes to disk

Schema Definition

fr_config uses json5 files to store schema, this allows for comments to be added in complex schemas

{
    __version__: 1,
    fps: {type: "float", default: 24.0},
    resolution: {
        type: "array",
        length: 2,
        items: {type: "int"}
    },
    publish_defaults: {
        type: "object",
        publish_type: {type: "string", default: "Publish"},
        handles: {
            type: "array",
            items: {type: "int"},
            default: [0, 0]
        }
    },
    tools: {
        type: "array",
        cascade: "append",
        items: {type: "string"}
    }
}

Data Flow

fr_config follows a hierarchical resolution pattern:

  1. Path Resolution: Starting from the specified path, walks up the directory tree
  2. Config Discovery: Looks for .fr_config/<name>/<variant>/ directories
  3. Version Selection: Chooses the appropriate version based on tags (published > latest)
  4. Schema Loading: Loads and validates against the schema file
  5. Data Cascading: Merges configurations based on cascade and schema rules
  6. Value Resolution: Resolves environment variables and applies type structure

Directory Structure Example

project/
├── .fr_config/
│   └── simple/
│       └── default/
│           ├── v1.fr_config
│           ├── v2.fr_config
│           ├── v3.fr_config
│           └── .v2.published
├── shots/
│   └── seq001/
│       └── shot010/
│           └── .fr_config/
│               └── simple/
│                   ├── default/
│                   │   └── v1.fr_config
│                   └── animation/
│                       └── v1.fr_config
└── schema/
    └── simple.fr_schema

Data Cascade Example

Given the directory structure above, loading the animation variant config from shots/seq001/shot010 will:

  1. Load shots/seq001/shot010/.fr_config/simple/variant/v1.fr_config
  2. Load shots/seq001/shot010/.fr_config/simple/default/v1.fr_config
  3. Load project/.fr_config/simple/default/v2.fr_config (published version)
  4. Merge them according to cascade rules

Configuration File Format

fr_config files use JSON5 format with special keys:

{
    // Reference parent config for inheritance
    "$parent": "${FR_PROJECTS_DIR}/../shared_config",

    // Regular configuration data
    fps: 30.0,
    resolution: [1920, 1080],

    // Complex cascading example
    environment_variables: {
        PATH: {
            cascade: "append",
            separator: "%pathsep%",  // Platform-specific path separator
            value: "/additional/bin/path"
        }
    },

    // Array with uniqueness constraints
    packages: {
        cascade: "append",
        unique: true,
        value: ["new-package-1.0+", "another-package-2.1+"]
    }
}

Schema System

Data Types

  • string: Text values
  • int: Integer numbers
  • float: Floating-point numbers
  • bool: Boolean true/false
  • array: Lists of values
  • object: Nested structures

Cascade Modes

  • replace: Replace entire value (default for primitives)
  • update: Merge object keys (default for objects)
  • append: Add to end of array/string
  • prepend: Add to beginning of array/string

Custom Types

Define reusable types in schema:

{
    __types__: {
        package: {
            type: "string",
            compare: "^([_a-zA-Z0-9]+)-.*"  // Regex for uniqueness comparison
        },
        environ: {
            type: "string",
            separator: "%pathsep%"
        }
    },

    packages: {
        type: "array",
        cascade: "append",
        unique: true,
        items: {type: "package"}
    },

    PATH: {type: "environ"}
}

Environment Setup

Set environment variables for schema and root path discovery:

# Path to schema files
export FR_CONFIG_SCHEMA_PATH="/path/to/schemas:/another/schema/path"

# Root paths that terminate config hierarchy traversal
export FR_CONFIG_ROOT_PATHS="/projects/root:/shared/configs"

Metadata

Release files for fr-config 0.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fr-config 0.2.4
File Size Uploaded
fr_config-0.2.4.tar.gz 99.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fr-config 0.2.4
File Interpreter ABI Platform
fr_config-0.2.4-py3-none-any.whl Python 3 none any Details

Total release size: 128.6 kB

Release files / fr_config-0.2.4.tar.gz

Download URL fr_config-0.2.4.tar.gz
Size 99.4 kB
Tags Source
SHA-256 checksum
How to use checksums
1ca43d922798f20a61597c572de1e6a6f9b12774e32580049cbd771147c30acc
BLAKE2b-256 checksum
How to use checksums
7266b67cbbc2679f5aa2d8f1a310dda0f72e3b9e2f8078349d65d358a821fb19
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.

Transparency log

Release files / fr_config-0.2.4-py3-none-any.whl

Download URL fr_config-0.2.4-py3-none-any.whl
Size 29.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
40792d7a1d121e34cb5034c64dfdf451e9216cd56fd579d8e35c88b199d1b611
BLAKE2b-256 checksum
How to use checksums
9972ebe40e5ed9f82ee4b8ffa57b7a53238f0ba01f80fb05b5a8c07e83e9f1c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.4 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page