cabina
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
- Computed Values
- Default Values
- Raw Values
- Custom Parsers
- JSON Parser
- Lazy Env
- Env Vars Prefix
- Inheritance
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.
Metadata
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)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cabina-1.1.2.tar.gz | 22.2 kB | Without provenance | Details for cabina-1.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cabina-1.1.2-py3-none-any.whl | Python 3 | none | any | Details for cabina-1.1.2-py3-none-any.whl |
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
|
Security for cabina 1.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.