To use ConfigAlchemy in a project.
Note
the configuration key should be uppercase.
from configalchemy import BaseConfig
class DefaultConfig(BaseConfig):
TEST = "test"
config = DefaultConfig()
Inherit from :any:`BaseConfig` to dynamic configure your configuration.
Note
Default Priority Environment Variables > File > Function Return Value > Default Value
Inherit from :any:`BaseConfig` to define your config value explicitly:
Note
the config key should be uppercase.
from configalchemy import BaseConfig
class DefaultConfig(BaseConfig):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite:///:memory:'
class ProductionConfig(DefaultConfig):
DATABASE_URI = 'mysql://user@localhost/foo'
class DevelopmentConfig(DefaultConfig):
DEBUG = True
class TestingConfig(DefaultConfig):
TESTING = True
config = DevelopmentConfig()
>>> config.DEBUG
True
Define the CONFIGALCHEMY_ENV_PREFIX to enable access config from environment variables:
Note
The :any:`BaseConfig` will try to load config value with f'{CONFIGALCHEMY_ENV_PREFIX}{key}'.
from configalchemy import BaseConfig
import os
os.environ['TEST_NAME'] = 'env'
class DefaultConfig(BaseConfig):
CONFIGALCHEMY_ENV_PREFIX = 'TEST_'
NAME = 'base'
config = DefaultConfig()
>>> config['NAME']
env
Define CONFIGALCHEMY_CONFIG_FILE to enable access config from config file:
Note
Support JSON file
from configalchemy import BaseConfig
class DefaultConfig(BaseConfig):
CONFIGALCHEMY_CONFIG_FILE = 'test.json' #: etc: {'NAME': 'json'}
NAME = 'base'
config = DefaultConfig()
>>> config['NAME']
json
Define CONFIGALCHEMY_ENABLE_FUNCTION to configure from function return value (support coroutine):
from configalchemy import BaseConfig, ConfigType
class SyncDefaultConfig(BaseConfig):
CONFIGALCHEMY_ENABLE_FUNCTION = True
TYPE = "base"
def configuration_function(self) -> ConfigType:
return {"TYPE": "sync"}
class AsyncDefaultConfig(BaseConfig):
CONFIGALCHEMY_ENABLE_FUNCTION = True
TYPE = "base"
async def async_function(self) -> ConfigType:
return {"TYPE": "async"}
sync_config = SyncDefaultConfig()
async_config = AsyncDefaultConfig()
>>> sync_config['TYPE']
sync
>>> async_config['NAME']
async
When new value is assigned to config, the value will be validated and typecast if possible and the process bases on default value or type annotations.
from typing import Optional
from configalchemy import BaseConfig
class DefaultConfig(BaseConfig):
id = 1
name = "Tony"
limit: Optional[int] = None
config = DefaultConfig()
config.id = '10'
print(config.id) # 10
config.limit = 10
print(config.limit) # 10
You can use Json data type - configalchemy will use json.loads to typecast.
import json
from configalchemy import BaseConfig
from configalchemy.types import Json
class DefaultConfig(BaseConfig):
TEST_LIST: Json[list] = ["str"]
TEST_DICT: Json[dict] = {"name": "default"}
config = DefaultConfig()
config.TEST_LIST = json.dumps(["test"])
config.TEST_LIST
>>> ["test"]
config.TEST_DICT = json.dumps({"name": "test"})
config.TEST_DICT
>>> {"name": "test"}
class NestedConfig(BaseConfig):
NAME = "nested"
ADDRESS = "default"
class DefaultConfig(BaseConfig):
NESTED_CONFIG = NestedConfig()
config = DefaultConfig()
config.update(NESTED_CONFIG={"NAME": "updated"})
config["NESTED_CONFIG.ADDRESS"] = "address"
>>> config.NESTED_CONFIG.NAME
updated
>>> config.NESTED_CONFIG.ADDRESS
address
Use lazy to turn any callable into a lazy evaluated callable. Results are memoized; the function is evaluated on first access.
from configalchemy.lazy import lazy, reset_lazy
def get_name():
print("evaluating")
return "World"
lazy_name = lazy(get_name)
>>> print(f"Hello {lazy_name}")
evaluating
Hello World
>>> print(f"Hello {lazy_name}")
Hello World
>>> reset_lazy(lazy_name)
>>> print(f"Hello {lazy_name}")
evaluating
Hello World
Use proxy to turn any callable into a lazy evaluated callable. Results are not memoized; the function is evaluated on every access.
from configalchemy.lazy import proxy
def get_name():
print("evaluating")
return "World"
lazy_name = proxy(get_name)
>>> print(f"Hello {lazy_name}")
evaluating
Hello World
>>> print(f"Hello {lazy_name}")
evaluating
Hello World
Use Pool to turn any callable into a pool. Result will be return by a context manager. the function is evaluated on result first access.
from configalchemy.lazy import Pool
def connect():
print("connecting")
return socket
connect_pool = Pool(connect)
>>> with connect_pool as connect:
... connect.send("")
connecting
0
>>> with connect_pool as connect:
... connect.send("")
0
Apollo - A reliable configuration management system
You can inherit from :any:`ApolloBaseConfig` to access config from Apollo.
from configalchemy.contrib.apollo import ApolloBaseConfig
class DefaultConfig(ApolloBaseConfig):
#: apollo
ENABLE_LONG_POLL = True
APOLLO_SERVER_URL = ""
APOLLO_APP_ID = ""
APOLLO_CLUSTER = "default"
APOLLO_NAMESPACE = "application"