Skip to main content

cabina

Codecov PyPI PyPI - Downloads Python Version

cabina is a Python library that simplifies building hierarchical, environment-driven configurations. It provides:

  • Simple class-based configurations
  • Automatic environment variable parsing
  • Type-safe defaults
  • Computed values
  • Flexible customization

Installation

pip3 install cabina

Quick Start

Here’s a minimal example showing how cabina handles environment variables, defaults, and computed properties:

import cabina
from cabina import computed, env

class Config(cabina.Config):
    class Main(cabina.Section):
        API_HOST: str = env.str("API_HOST", default="localhost")
        API_PORT: int = env.int("API_PORT", default=8080)

        @computed
        def API_URL(cls) -> str:
            return f"http://{cls.API_HOST}:{cls.API_PORT}"

# Usage
assert Config.Main.API_URL == "http://localhost:8080"
assert Config["Main"]["API_URL"] == "http://localhost:8080"

# Print
print(Config)
# class <Config>:
#     class <Main>:
#         API_HOST = 'localhost'
#         API_PORT = 8080
#         API_URL = 'http://localhost:8080'

Recipes

Below are some common patterns and features you can use with cabina:

Root Section

You can use cabina for simple, flat configurations by inheriting cabina.Section in your main config:

export API_HOST=localhost
export API_PORT=8080
import cabina
from cabina import env

class Config(cabina.Config, cabina.Section):  # Note the inheritance
    API_HOST = env.str("API_HOST")
    API_PORT = env.int("API_PORT")

assert Config.API_HOST == "localhost"
assert Config.API_PORT == 8080

Computed Values

You can define dynamic or derived config values via the @computed decorator:

export API_HOST=localhost
export API_PORT=8080
import cabina
from cabina import computed, env

class Config(cabina.Config, cabina.Section):
    API_HOST: str = env.str("API_HOST")
    API_PORT: int = env.int("API_PORT")

    @computed
    def API_URL(cls) -> str:
        return f"http://{cls.API_HOST}:{cls.API_PORT}"

assert Config.API_URL == "http://localhost:8080"

Default Values

Provide a default if an environment variable isn’t set:

export API_HOST=127.0.0.1
import cabina
from cabina import env

class Config(cabina.Config, cabina.Section):
    API_HOST = env.str("API_HOST", default="localhost")
    API_PORT = env.int("API_PORT", default=8080)

assert Config.API_HOST == "127.0.0.1"
assert Config.API_PORT == 8080

Raw Values

Get the raw, unprocessed string from an environment variable — even if it includes leading/trailing spaces:

export DEBUG=" yes"
import cabina
from cabina import env

class Config(cabina.Config, cabina.Section):
    DEBUG_RAW = env.raw("DEBUG")  # Same as env("DEBUG") without processing
    DEBUG_STR = env.str("DEBUG")  # Strips whitespace

assert Config.DEBUG_RAW == " yes"   # The raw value includes whitespace
assert Config.DEBUG_STR == "yes"    # Whitespace is stripped

Custom Parsers

Use custom parsing functions to handle special formats. For instance, parse a duration string with pytimeparse:

export HTTP_TIMEOUT=10s
import cabina
from cabina import env
from pytimeparse import parse as parse_duration

class Config(cabina.Config, cabina.Section):
    HTTP_TIMEOUT: int = env("HTTP_TIMEOUT", parser=parse_duration)

assert Config.HTTP_TIMEOUT == 10

JSON Parser

Easily load JSON data from an environment variable:

export IMAGE_SETTINGS='{"AllowedContentTypes": ["image/png", "image/jpeg"]}'
import json
import cabina
from cabina import env

class Config(cabina.Config, cabina.Section):
    IMAGE_SETTINGS = env("IMAGE_SETTINGS", parser=json.loads)

assert Config.IMAGE_SETTINGS == {
    "AllowedContentTypes": ["image/png", "image/jpeg"]
}

Lazy Env

Defer parsing environment variables until their first access. This can be useful if some variables may not exist at import time:

export DEBUG=yes
export API_PORT=80a  # Contains an invalid int "80a"
import cabina
from cabina import lazy_env

class Config(cabina.Config, cabina.Section):
    DEBUG = lazy_env.bool("DEBUG")
    API_HOST = lazy_env.str("API_HOST")  # Only fetched upon attribute access
    API_PORT = lazy_env.int("API_PORT")

# Attempt to fetch all at once
Config.prefetch()
# Raises ConfigEnvError with:
# - Config.API_HOST: 'API_HOST' does not exist
# - Config.API_PORT: Failed to parse '80a' as int

Env Vars Prefix

Use a prefix for all your environment variables to avoid collisions:

export APP_HOST=localhost
export APP_PORT=8080
import cabina

env = cabina.Environment(prefix="APP_")

class Config(cabina.Config, cabina.Section):
    API_HOST = env.str("HOST")  # 'APP_HOST' will be used
    API_PORT = env.int("PORT")  # 'APP_PORT' will be used

assert Config.API_HOST == "localhost"
assert Config.API_PORT == 8080

Inheritance

Create a base configuration and extend it for local or specialized use cases:

import cabina

class Config(cabina.Config, cabina.Section):
    DEBUG = False

    class Api(cabina.Section):
        API_HOST = "app.dev"
        API_PORT = 5000

class ConfigLocal(Config):
    DEBUG = True

    class Api(Config.Api):
        API_HOST = "localhost"

assert ConfigLocal.DEBUG is True
assert ConfigLocal.Api.API_HOST == "localhost"
assert ConfigLocal.Api.API_PORT == 5000

Contributing

Contributions, bug reports, and feature requests are welcome! Feel free to open an issue or submit a pull request.

Release files for cabina 1.1.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 cabina 1.1.2
File Size Uploaded
cabina-1.1.2.tar.gz 22.2 kB Details

Built distribution (wheel)

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

Total release size:41.1 kB

Release files / cabina-1.1.2.tar.gz

Download URL cabina-1.1.2.tar.gz
Size 22.2 kB
Tags Source
SHA-256 checksum
How to use checksums
91502936f2e75143403999be96bb199d4819825a462aabb8ffd2d8848b702bd5
BLAKE2b-256 checksum
How to use checksums
f542cb2fd18fb213823470ae5e6e40c3b68180e0e630f08fd836074e7fcbc7b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release files / cabina-1.1.2-py3-none-any.whl

Download URL cabina-1.1.2-py3-none-any.whl
Size 18.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1be6c0b7e411d91af7bbe3c0315ea6e31251cbd24e9d7fa8e3c1b3c78b90eb63
BLAKE2b-256 checksum
How to use checksums
54cc7db5582ec76688c65132265829ab56c1cea2d9f79755c91bd23a3762e61f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.8

Release history Release notifications | RSS feed

This release

1.1.2 This release

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

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