Usage¶
To use ConfigAlchemy in a project.
Note
the configuration key should be uppercase.
from configalchemy import BaseConfig
class DefaultConfig(BaseConfig):
TEST = "test"
config = DefaultConfig()
How to Use the Config¶
Inherit from BaseConfig
to dynamic configure your configuration.
Note
Default Priority Environment Variables > File > Function Return Value > Default Value
Define the Default Config Class¶
Inherit from 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
Enable Environment Variables¶
Define the CONFIGALCHEMY_ENV_PREFIX to enable access config from environment variables:
Note
The 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
Enable Configure from File¶
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
Enable Configure with function return value¶
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
Auto Validation and Dynamic typecast¶
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
Json Type¶
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"}
Advanced Usage¶
Singleton¶
Nested Config for Modular Purpose¶
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
Lazy¶
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
Proxy¶
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
Pool¶
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
Access config from Apollo¶
Apollo - A reliable configuration management system
You can inherit from 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"