Skip to main content

🎉 fetti: TOML-Powered Environment Injection

PyPI - Version PyPI - Python Version codecov

fetti is a lightweight CLI tool that loads environment variables from a TOML configuration file and executes any command with those variables injected. Think of it as dotenv for your TOML files, supercharged with live command execution and namespacing.


✨ Core Features

  • TOML Configuration: Leverages the clear and structured TOML format for defining environment variables.
  • Seamless Command Execution: Run any command or script, and fetti will provide it with the configured environment.
  • Variable Interpolation: Define dynamic values using ${VAR_NAME} syntax. Variables can reference:
    • Other values from the same (flattened) TOML configuration.
    • Existing operating system environment variables.
  • Namespace Scoping: Isolate specific sections of your configuration using the -n/--namespace option (e.g., load only variables from a [database] section).
  • Automatic Key Flattening: Nested TOML tables are automatically converted into flat environment variable names. For example, [service.db] with key host becomes SERVICE_DB_HOST. Keys are uppercased, and levels are joined by underscores (_).
  • Verbose Mode: Use -v/--verbose to see which variables are being injected.
  • Minimal & Fast: Built with Python and click, aiming for efficiency with minimal dependencies. Requires Python 3.11+ (for built-in tomllib).

📦 Installation

Ensure you have Python 3.11+ installed.

pip install fetti

(For Python versions older than 3.11, fetti will also install the toml package if tomllib is not available in the standard library.)


⚙️ CLI Usage

fetti [OPTIONS] FILE -- COMMAND [ARGS]...

Arguments:

Name Description
FILE Path to your TOML configuration file.
COMMAND The command to execute after loading the environment.
ARGS... Any arguments for the COMMAND.

Options:

Flag Description
-n, --namespace NAME Use only a specific top-level section (table) from the TOML file.
-k, --key NAME Use only a specific second-level section (subtable) from the TOML file.
-v, --verbose Print the environment variables loaded from TOML before running the command.
-h, --help Show the help message and exit.

Note: The -- separator is crucial. Everything after it is considered part of the command to be executed.


🧪 Quick Start Example

Given a config.toml:

# config.toml
APP_VERSION = "1.0"

[database]
host = "localhost"
port = 5432
user = "admin"
# Interpolates other values from this 'database' scope once flattened
url = "postgres://${DATABASE_USER}@${DATABASE_HOST}:${DATABASE_PORT}/mydb"

[api_service]
# Interpolates from OS environment if API_KEY_SECRET is set there
# Otherwise, if API_KEY_SECRET is also in this config, it uses that.
key = "${API_KEY_SECRET}"

1. Load variables from the database namespace:

fetti config.toml -n database -- python my_script.py

Inside my_script.py:

import os

print(f"DB URL: {os.environ.get('DATABASE_URL')}")
# Output (example): DB URL: postgres://admin@localhost:5432/mydb
print(f"App Version (not loaded): {os.environ.get('APP_VERSION')}") # Will be None

2. Load all variables (no namespace):

# Assuming API_KEY_SECRET is "mysecret" in your OS environment
export API_KEY_SECRET="mysecret"
fetti config.toml -- env | grep -E "(DATABASE_URL|APP_VERSION|API_SERVICE_KEY)"

Output:

APP_VERSION=1.0
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USER=admin
DATABASE_URL=postgres://admin@localhost:5432/mydb
API_SERVICE_KEY=mysecret

🛠 Advanced: Nested Configuration & Interpolation

fetti handles nested TOML tables by flattening their keys.

Consider settings.toml:

# settings.toml
project_name = "AwesomeProject"

[service.auth]
issuer = "auth.example.com"
token_expiry_minutes = 60

[service.env.db]
host = "db.internal"
port = 5432
# Interpolation uses already flattened keys from this config:
# SERVICE_AUTH_ISSUER, PROJECT_NAME, SERVICE_ENV_DB_PORT
# It will also check os.environ if a var isn't in the TOML.
connection_string = "user@${SERVICE_ENV_DB_HOST}:${SERVICE_ENV_DB_PORT}/${PROJECT_NAME}?issuer=${SERVICE_AUTH_ISSUER}"

Run with the service namespace:

fetti settings.toml -n service -- printenv | grep -E "(SERVICE_AUTH_ISSUER|SERVICE_ENV_DB_CONNECTION_STRING)"

Expected Output:

SERVICE_AUTH_ISSUER=auth.example.com
SERVICE_ENV_DB_HOST=db.internal
SERVICE_ENV_DB_PORT=5432
SERVICE_ENV_DB_CONNECTION_STRING=user@db.internal:5432/AwesomeProject?issuer=auth.example.com

💡 How Interpolation Works

  1. When fetti encounters ${VAR_NAME} in a string value from your TOML file:
  2. It first looks for VAR_NAME among the other flattened keys derived from your TOML file.
  3. If not found there, it looks for VAR_NAME in the existing operating system environment variables.
  4. If VAR_NAME is not found in either location, it's replaced with an empty string.
  5. The interpolation is a single pass. For chained dependencies (e.g., A=${B}, B=${C}), ensure B appears or is processed before A if B itself is also defined in the TOML.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Metadata

Release files for fetti 0.0.2

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

Source distribution (sdist)

Source distribution for fetti 0.0.2
File Size Uploaded
fetti-0.0.2.tar.gz 8.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fetti 0.0.2
File Interpreter ABI Platform
fetti-0.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 16.8 kB

Release files / fetti-0.0.2.tar.gz

Download URL fetti-0.0.2.tar.gz
Size 8.4 kB
Tags Source
SHA-256 checksum
How to use checksums
a642a588dcb697e62d6d77df73e4a8aef3d07ed27a3de6dd0454b621650d5f87
BLAKE2b-256 checksum
How to use checksums
5608edca0878d868d70e70fef100fde032f644a0ed32a58cd9e6c06481a71c64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-httpx/0.27.2

Release files / fetti-0.0.2-py3-none-any.whl

Download URL fetti-0.0.2-py3-none-any.whl
Size 8.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a2f82bd28459bc79f9c4617d1866caec7602264d617c0f2230cc05664cc9e93b
BLAKE2b-256 checksum
How to use checksums
fa1db21e1565e31e496c7999f578ded3efd762f50b98e1a351d237cc3939308b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-httpx/0.27.2

Release history Release notifications | RSS feed

This release

0.0.2 This release

2 release files

0.0.1

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