Ways to document, centeralize, retreive and validate settings.
Project description
Introduction
Helps document and centralizing settings in a python project/library.
Facilitates looking up BaseSettings from retrievers
, such as an environmental variable retriever.
Converts and standardizes any retrieved values to the type-hint on the setting attribute (such as bool, int, datetime, etc).
Interface to provide own custom retrievers, to grab settings/configuration from wherever you want.
Retrievers can be stacked, so multiple ones can be consulted when retrieving a setting.
See xsettings docs.
Documentation
📄 Detailed Documentation | 🐍 PyPi
Install
# via pip
pip install xsettings
# via poetry
poetry add xsettings
Quick Start
from xsettings import EnvVarSettings, SettingsField
from xsettings.errors import SettingsValueError
from typing import Optional
import dataclasses
import os
# Used to showcase looking up env-vars automatically:
os.environ['app_version'] = '1.2.3'
# Used to showcase complex setting types:
@dataclasses.dataclass
class DBConfig:
@classmethod
def from_dict(cls, values: dict):
return DBConfig(**values)
user: str
host: str
password: str
# Some defined settings:
class MySettings(EnvVarSettings):
app_env: str = 'dev'
app_version: str
api_endpoint_url: str
some_number: int
# For Full Customization, allocate SettingsField,
# In this case an alternate setting lookup-name
# if you want the attribute name to differ from lookup name:
token: Optional[str] = SettingsField(name='API_TOKEN')
# Or if you wanted a custom-converter for a more complex obj:
db_config: DBConfig = SettingsField(
converter=DBConfig.from_dict
)
# BaseSettings subclasses are singleton-like dependencies that are
# also injectables and lazily-created on first-use.
# YOu can use a special `BaseSettings.grab()` class-method to
# get the current settings object.
#
# So you can grab the current MySettings object lazily via
# its `grab` class method:
MySettings.grab().some_number = 3
assert MySettings.grab().some_number == 3
# You can also use a proxy-object, it will lookup and use
# the current settings object each time its used:
my_settings = MySettings.proxy()
# Here I showcase setting a dict here and using the converter
# I defined on the SettingsField to convert it for me:
my_settings.db_config = {
'user': 'my-user',
'password': 'my-password',
'host': 'my-host'
}
expected = DBConfig(
user='my-user',
password='my-password',
host='my-host'
)
# The dict gets converted automatically to the DBConfig obj:
assert MySettings.grab().db_config == expected
# If you set a setting with the same/exact type as
# it's type-hint, then it won't call the converter:
my_settings.db_config = expected
# It's the same exact object-instance still (ie: not changed/converted):
assert my_settings.db_config is expected
# Will use the default value of `dev` (default value on class)
# since it was not set to anything else and there is no env-var for it:
assert my_settings.app_env == 'dev'
# EnvVarSettings (superclass) is configured to use the EnvVar retriever,
# and so it will find this in the environmental vars since it was not
# explicitly set to anything on settings object:
assert my_settings.app_version == '1.2.3'
# Any BaseSettings subclass can use dependency-injection:
assert my_settings.token is None
with MySettings(token='my-token'):
assert my_settings.token == 'my-token'
# Parent is still consulted for any settings unset on child but set on parent:
assert my_settings.db_config == expected
# Can set settings like you expect,
# this will go into the child created in above `with` statement:
my_settings.app_env = 'prod'
assert my_settings.app_env == 'prod'
# After `with` child is not the current settings object anymore,
# reverts back to what it was before:
assert my_settings.token is None
try:
# If a setting is undefined and required (ie: not-optional),
# and it was not set to anything nor is there a default or an env-var for it;
# BaseSettings will raise an exception when getting it:
print(my_settings.api_endpoint_url)
except SettingsValueError as e:
assert True
else:
assert False
try:
# `SettingsValueError` inherits from both AttributeError and ValueError,
# as the error could be due to either aspect; so you can also do an except
# for either standard error:
print(my_settings.api_endpoint_url)
except ValueError as e:
assert True
else:
assert False
Licensing
This library is licensed under the MIT-0 License. See the LICENSE file.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file xsettings-1.2.1.tar.gz
.
File metadata
- Download URL: xsettings-1.2.1.tar.gz
- Upload date:
- Size: 21.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.3.2 CPython/3.10.6 Linux/5.15.0-1033-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 52be4bbf08b584b48f442603f8528ec25b2a0aa8d7b49be5279950bfddb34ca4 |
|
MD5 | a1018e3e1d68ce3d3a9652a825a89acc |
|
BLAKE2b-256 | 93db4a876e519d9582f69fb73ddfb7799a124df5f4c329a32e964f6fdf9422e3 |
File details
Details for the file xsettings-1.2.1-py3-none-any.whl
.
File metadata
- Download URL: xsettings-1.2.1-py3-none-any.whl
- Upload date:
- Size: 21.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.3.2 CPython/3.10.6 Linux/5.15.0-1033-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 38bd0fd24b992dba3647b869eb61ac777a96a4c4bf6d9c4e18edd09cf650e661 |
|
MD5 | 517fe6241a0e4f033739d8c9f694a5b0 |
|
BLAKE2b-256 | b3867e1e0d0bd162bef62f974808e604da0880f148978a6b98950d7a04585908 |