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ć.
Metadata
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 | Provenance | Actions |
|---|---|---|---|---|
| configuration_file-2.1.2.tar.gz | 46.4 kB | Without provenance | Details for configuration_file-2.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| configuration_file-2.1.2-py3-none-any.whl | Python 3 | none | any | Details for configuration_file-2.1.2-py3-none-any.whl |
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
|
Security for configuration-file 2.1.2
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.