configuration-file
A Python implementation of the Configuration File (CF) format - a human-readable, machine-parseable data serialization format for configuration files.
What is CF?
CF (Configuration File) is a modern configuration format designed to address common shortcomings of existing formats like JSON, YAML, TOML, and INI:
- Human-readable: Clean, minimal syntax with comments
- Machine-parseable: Simple, unambiguous LL(1) grammar
- Whitespace-independent: Structure uses explicit delimiters (
{ }and[ ]), not indentation - Copy-paste safe: Configuration survives email, chat, wikis, and forums
- Type-safe: Explicit typing with no implicit conversions
- Extensible: Includes for configuration reuse across files
See the official CF Specification for complete details, or the local copy included in this repository.
Installation
pip install configuration-file
For development:
pip install configuration-file[dev]
Usage
Simple API (dict-based)
import cf
# Parse a CF file
config = cf.load("config.cf")
# Parse a CF string
config = cf.loads('''
app_name = "my-service"
debug = true
''')
# Access values
print(config["app_name"]) # "my-service"
print(config["server"]["port"]) # 8080
# Serialize to CF format
cf_string = cf.dumps(config)
# Write to a file
cf.dump(config, "output.cf")
Roundtrip API (preserves formatting)
import cf
# Parse into a CFDocument that preserves comments, whitespace,
# quote styles, and separator choices
doc = cf.loads_document('''
# Server configuration
server {
host = "localhost"
port = 8080
}
''')
# Read values
host = doc.get("server.host") # "localhost"
# Modify values (only changed values are re-rendered)
doc.set("server.port", 9090)
# Serialize back with minimal diffs
output = doc.serialize()
# Comments, whitespace, and formatting are preserved
# Convert to plain dict when formatting isn't needed
config = doc.to_dict()
Features
- Full CF 1.0 specification support
- Comments: Hash (
#), double-slash (//), and block (/* */) comments - Data types: Strings, integers, floats, booleans, null, dates, times, datetimes
- Collections: Objects and arrays with flexible syntax
- String variants: Double-quoted, single-quoted, triple-quoted, and raw strings
- Environment variable substitution:
${VAR},${VAR:-default},${VAR:?error} - File includes:
include "path/to/file.cf" - Roundtrip preservation: Parse, modify, and serialize with minimal diffs
Development
Setup
- Clone the repository:
git clone https://codeberg.org/configuration-file/py.git
cd py
- Create a virtual environment and install dependencies:
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -e ".[dev]"
Running Tests
pytest
With coverage:
pytest --cov=cf --cov-report=html
Code Quality
Lint and format code:
ruff check .
ruff format .
Type checking:
mypy src/cf
Full Example
CF files use the .cf extension. Here is a comprehensive example demonstrating all features of the CF format:
# =============================================================================
# Complete CF 1.0 Feature Demonstration
# =============================================================================
# -----------------------------------------------------------------------------
# Comments
# -----------------------------------------------------------------------------
# Hash comments (like this one)
// Double-slash comments (C++ style)
/* Block comments
can span multiple
lines */
# -----------------------------------------------------------------------------
# String Types
# -----------------------------------------------------------------------------
strings {
double_quoted = "Hello, World!"
with_escapes = "Line 1\nLine 2\tTabbed"
with_unicode = "Caf\u00E9 \U0001F600"
with_quotes = "She said \"Hello\""
single_quoted = 'It\'s working'
contains_double = 'He said "hello"'
# Triple-quoted strings (no escape processing, preserves whitespace)
multiline = """
SELECT id, name, email
FROM users
WHERE active = true
ORDER BY created_at DESC
"""
# Raw strings (no escape processing)
raw_double = r"C:\Program Files\App\config.ini"
raw_single = r'^\d{3}-\d{4}$'
regex_pattern = r"https?://[\w\-\.]+\.[a-z]{2,}"
empty_double = ""
empty_single = ''
}
# -----------------------------------------------------------------------------
# Number Types
# -----------------------------------------------------------------------------
numbers {
decimal = 42
negative = -17
zero = 0
large = 9223372036854775807
with_separators = 1_000_000_000
hexadecimal = 0xFF
octal = 0o755
binary = 0b10101010
simple_float = 3.14159
negative_float = -273.15
scientific = 6.022e23
float_with_sep = 1_234.567_890
positive_infinity = inf
negative_infinity = -inf
not_a_number = nan
}
# -----------------------------------------------------------------------------
# Boolean and Null Types
# -----------------------------------------------------------------------------
primitives {
enabled = true
disabled = false
optional_value = null
}
# -----------------------------------------------------------------------------
# Date and Time Types (ISO 8601)
# -----------------------------------------------------------------------------
temporal {
release_date = 2024-06-15
meeting_time = 14:30:00
precise_time = 09:15:30.123456
local_datetime = 2024-06-15T10:30:00
utc_datetime = 2024-06-15T10:30:00Z
positive_offset = 2024-06-15T10:30:00+05:30
negative_offset = 2024-06-15T10:30:00-08:00
with_microseconds = 2024-06-15T10:30:00.123456Z
}
# -----------------------------------------------------------------------------
# Objects
# -----------------------------------------------------------------------------
# HCL-style (without =)
server {
host = "localhost"
port = 8080
}
# JSON-style (with =)
database = {
driver = "postgres"
host = "db.example.com"
}
# Inline with semicolons or commas
point = { x = 10; y = 20; z = 30 }
color = { r = 255, g = 128, b = 64 }
# Empty object
empty_config = {}
# Deeply nested
deeply_nested {
level1 {
level2 {
level3 {
value = "deep"
}
}
}
}
# -----------------------------------------------------------------------------
# Arrays
# -----------------------------------------------------------------------------
arrays {
numbers = [1, 2, 3, 4, 5]
strings = ["apple", "banana", "cherry"]
# Multi-line with newline separators
fruits = [
"apple"
"banana"
"cherry"
"date"
]
# Semicolon separators
ports = [8080; 8443; 9000]
# Heterogeneous arrays (mixed types)
mixed_types = [42, "hello", true, null, 3.14, 2024-06-15]
# Nested arrays (matrix)
matrix = [
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
]
# Array of objects
users = [
{ name = "Alice"; role = "admin"; active = true }
{ name = "Bob"; role = "user"; active = true }
{ name = "Charlie"; role = "user"; active = false }
]
empty = []
}
# -----------------------------------------------------------------------------
# Identifiers (Keys)
# -----------------------------------------------------------------------------
identifiers {
simple = "value"
with_underscore = "value"
_private = "value"
my-key = "value"
# Unicode identifiers
café = "coffee"
日本語 = "Japanese"
# Quoted keys for special characters
"123numeric" = "starts with digit"
"hello world" = "contains space"
"key=value" = "contains special char"
}
# -----------------------------------------------------------------------------
# Environment Variable Substitution
# -----------------------------------------------------------------------------
environment {
home_dir = ${HOME}
server_host = ${SERVER_HOST:-localhost}
server_port = ${SERVER_PORT:-8080}
# String interpolation
database_url = "postgresql://${DB_USER:-postgres}:${DB_PASS:-secret}@${DB_HOST:-localhost}:${DB_PORT:-5432}/${DB_NAME:-myapp}"
log_path = "${LOG_DIR:-/var/log}/app.log"
# Escaped (literal ${})
literal_syntax = "Use \${VAR} for variable syntax"
}
# -----------------------------------------------------------------------------
# Real-World Example
# -----------------------------------------------------------------------------
application {
name = "MyApplication"
version = "2.0.0"
server {
host = "0.0.0.0"
port = 8080
workers = 4
ssl {
enabled = true
cert = "/etc/ssl/certs/app.crt"
key = "/etc/ssl/private/app.key"
protocols = ["TLSv1.2", "TLSv1.3"]
}
timeouts { connect = 5; read = 30; write = 10 }
}
database {
primary {
driver = "postgres"
host = ${DB_HOST:-db.example.com}
port = 5432
pool = { min = 5, max = 20, idle_timeout = 300 }
}
}
features = ["auth", "api", "webhooks", "analytics"]
cron_jobs = [
{ name = "cleanup"; schedule = "0 2 * * *"; command = "cleanup.sh" }
{ name = "backup"; schedule = "0 3 * * *"; command = "backup.sh" }
]
metadata {
created = 2024-01-15T10:30:00Z
updated = 2024-06-15T14:45:00Z
maintainer = "devops@example.com"
}
}
License
This project is licensed under the BSD-3-Clause License - see the LICENSE file for details.
Copyright (c) 2026 Dejan Lekić.
Release files for configuration-file 2.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| configuration_file-2.1.2.tar.gz | 46.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| configuration_file-2.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 84.8 kB
Release files / configuration_file-2.1.2.tar.gz
| Download URL | configuration_file-2.1.2.tar.gz |
|---|---|
| Size | 46.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d279ead7cf1c61ca799f7244dd9e23e699d215de77cd81c2e2d150e867f7c9f6
|
|
BLAKE2b-256 checksum How to use checksums |
89d4307cf8ba3c65149f9258f18772f21fbbaa969b2e1eb825ec7b4cf3fe9297
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Release files / configuration_file-2.1.2-py3-none-any.whl
| Download URL | configuration_file-2.1.2-py3-none-any.whl |
|---|---|
| Size | 38.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
45298a3f2f19b36b85326ec3ed57504b77faa12cae22da0472aa9bed9e6810d3
|
|
BLAKE2b-256 checksum How to use checksums |
08cc554e9b4763ec67521804329de8c356906ac207b0b51b8a39ae905112bf3d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|