Skip to main content

CBT – Configuration with Bounded Types

A Python library for lexing, parsing, and interpreting the CBT configuration language.

CBT is an S-expression based configuration language with a type system featuring schemas, constraints, generics, union types, lazy self-references, and cycle detection.

Quick Start

from cbt import interpret, load

# Interpret CBT source text directly
result = interpret("""
    (define-schema server
        (host Str)
        (port (constraint Int (range 1 65535)))
        (tls (default Bool false)))

    (server
        (host "example.com")
        (port 443))
""")

# result == {"server": {"host": "example.com", "port": 443, "tls": False}}

# Or load from a .cbt file
result = load("config.cbt")

Multi-File Configs with Environment

When you need to evaluate multiple files that share schema definitions, or inject Python values into the CBT runtime, use the Environment class:

from cbt import Environment

env = Environment()

# Register custom validators from Python
env.add_native_module("validators", {
    "is_url": lambda v, **kw: isinstance(v, str) and "://" in v,
})

# Inject Python constants
env.add_global("default_port", 8080)

# Define schemas once, reuse across files
env.load("schemas.cbt")
result = env.load("prod.cbt")

See the Environment API docs for full documentation.

CLI Usage

python main.py examples/test.cbt

Outputs the interpreted configuration as JSON.

Language Features

Schemas (Structs)

Schemas define typed, named collections of fields:

(define-schema training
    (model_path Str)
    (lr Float)
    (epochs Int)
    (batch_size Int))

(training
    (model_path "openai/gpt2")
    (lr 1e-3)
    (epochs 3)
    (batch_size 16))

Schema Extensions (Inheritance)

Schemas can extend other schemas, inheriting all their fields:

(define-schema base-config
    (lr Float)
    (epochs Int))

(define-schema training-config extends base-config
    (batch_size Int)
    (optimizer Str))

; training-config has all fields: lr, epochs, batch_size, optimizer
(training-config
    (lr 1e-3)
    (epochs 10)
    (batch_size 32)
    (optimizer "adamw"))

Child fields override parent fields with the same name. Deep inheritance chains are supported. Parent ensure clauses are not inherited (each schema defines its own validation):

(define-schema base
    (port (constraint Int (gt 0))))

(define-schema server extends base
    (host Str)
    (ensure (= (self host) "production-server")))

Primitive Types

Type Description Example
Str String "hello"
Int Integer (not bool) 42, -7
Float Float (also accepts int) 3.14, 1e-3
Bool Boolean true, false
Nil Null / none nil

Union Types

Combine multiple types with |:

(define-schema config
    (value (| Str Int)))  ; accepts either a string or an integer

Default Values

Fields can have default values that are computed lazily:

(define-schema config
    (name (default Str "unnamed"))
    (lr (default Float 1e-3)))

Constraints

Add validation predicates on top of a base type:

(define-func range (min max) (all (gt min) (lt max)))

(define-schema config
    (port (constraint Int (range 1 65535)))
    (lr (constraint Float (all (gt 0.0) (lt 1.0)))))

Generics (Type-Level Functions)

Define parameterized types:

(define-generic optional (a) (default (| a Nil) nil))

(define-schema config
    (name (optional Str))   ; expands to (default (| Str Nil) nil)
    (value (optional Int))) ; expands to (default (| Int Nil) nil)

Self-References

Fields can reference sibling fields lazily:

(define-schema training
    (batch_size Int)
    (micro_batch_size Int)
    (gradient_accumulation_steps
        (default Int (// (self batch_size) (self micro_batch_size)))))

Cycle detection prevents infinite recursion when two defaults reference each other.

Lists

Fields can hold lists of typed values. Single values are auto-wrapped:

(define-schema dataset (path Str))

(define-schema config
    (datasets (List dataset)))

; Single item (auto-wrapped in a list):
(config (datasets (dataset (path "data.jsonl"))))

; Multiple items (variadic):
(config
    (datasets
        (dataset (path "train.jsonl"))
        (dataset (path "val.jsonl"))))

Nested Schemas

Schema instances can be nested inline without extra wrapping:

(define-schema address
    (street Str)
    (city Str))

(define-schema person
    (name Str)
    (address address))

(person
    (name "Alice")
    (address
        (street "123 Main St")
        (city "Springfield")))

Ensure Clauses

Validate meta-properties like "was this field explicitly provided?":

(define-schema config
    (batch_size (default Int 0))
    (gradient_accumulation_steps (default Int 0))
    (ensure (one-of (provided batch_size)
                    (provided gradient_accumulation_steps))))

Conditional Fields (when)

Fields can be conditionally required based on other field values using when:

(define-schema config
    (mode Str)
    ; momentum is only present when mode is "sgd"
    (momentum (when Float (= (self mode) "sgd"))))

When the predicate is true, the field behaves according to its inner type. When the predicate is false, the field is absent from the output.

when composes with default and constraint:

(define-schema config
    (mode Str)
    ; When mode is "train", lr is required Float; otherwise field is absent
    (lr (when Float (= (self mode) "train")))
    ; When mode is "production", port has constraint; otherwise field is absent
    (port (when (constraint Int (range 1 65535)) (= (self mode) "production")))
    ; When mode is "train", momentum defaults to 0.9; otherwise field is absent
    (momentum (when (default Float 0.9) (= (self mode) "train"))))

A common pattern (mutually exclusive required fields):

(define-schema config
    (batch_size (when Int (not (provided gradient_accumulation_steps))))
    (gradient_accumulation_steps (when Int (not (provided batch_size))))
    (ensure (any (provided batch_size) (provided gradient_accumulation_steps))))

If a user provides a field whose when predicate is false, a ValidationError is raised.

Boolean Predicates

Boolean expressions for use in when, ensure, and other predicate contexts:

(= a b)           ; equality comparison
(not expr)        ; logical negation
(all expr ...)    ; logical conjunction (all must be true)
(any expr ...)    ; logical disjunction (at least one must be true)
(one-of expr ...) ; exactly one must be true
(provided field)  ; true if field was explicitly provided

Imports

Import native functions from built-in modules:

(import (core fs) is_path)

(define-type File (constraint Str (fs is_path)))

Binary Operations

Arithmetic in value expressions:

(* a b)   ; multiplication
(// a b)  ; integer division
(+ a b)   ; addition
(- a b)   ; subtraction

Requirements

Python ≥ 3.10 (uses match patterns and modern type hints)

License

Copyright (C) 2026 Fizz

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cbt_cfg-0.2.0.tar.gz (58.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cbt_cfg-0.2.0-py3-none-any.whl (47.9 kB view details)

Uploaded Python 3

File details

Details for the file cbt_cfg-0.2.0.tar.gz.

File metadata

  • Download URL: cbt_cfg-0.2.0.tar.gz
  • Upload date:
  • Size: 58.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"openSUSE Tumbleweed","version":"20260618","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for cbt_cfg-0.2.0.tar.gz
Algorithm Hash digest
SHA256 46040a03a89849a8013ea621bb1d23f449594389e6884a27ec7e55d91380ca27
MD5 62dc3ae2beb6d79d3342dbd1f781f110
BLAKE2b-256 2c23b56afed6af98cc2cbcccb148a565c984560189049d0a606b1fa6706b01a1

See more details on using hashes here.

File details

Details for the file cbt_cfg-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: cbt_cfg-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 47.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"openSUSE Tumbleweed","version":"20260618","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for cbt_cfg-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dbdf934e9fee35fe1134f7b7017e92da7cd80322b55be43111e39650184a55d3
MD5 0497c04c729bd39f923ec47a3364a993
BLAKE2b-256 12c7e182a6f89fee2e67e6ddcde9dc3de079528b5fabedeb2c78e128625d3d00

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 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