No project description provided
Project description
Thatway is a simple, decentralized configuration manager.
Place your configuration settings throughout your application–not in a centralized file or submodule–and thatway collects them and allows you to modify them through configurations files. Decentralized configuration reduces the complexity of submodules and the coupling between submodules.
Quickstart
Create a package with settings.
examples/mypkg/moduleA/file.py
from thatway import Setting
class FirstClass:
my_attribute = Setting(True, desc="Whether 'my_attribute' is an attribute")
max_instances = Setting(3, desc="Maximum number of instances")
examples/mypkg/moduleB/file.py
from thatway import config, Setting
config.moduleB.msg = Setting("This is my message")
View settings:
import examples.mypkg
from thatway import config
print(config.dumps_yaml())
FirstClass:
my_attribute: true # Whether 'my_attribute' is an antribue
max_instances: 3 # Maximum number of instances
moduleB:
msg: This is my message
Load different settings:
examples/mypkg/new_settings.yaml
FirstClass:
my_attribute: false
max_instances: 2
with python:
from pathlib import Path
import examples.mypkg
from thatway import config
config.load_yaml(str(Path("examples") / "mypkg" / "new_settings.yaml"))
print(config.dumps_yaml())
FirstClass:
my_attribute: false # Whether 'my_attribute' is an antribue
max_instances: 2 # Maximum number of instances
moduleB:
msg: This is my message
Rules
The following are design decisions on the behavior of thatway’s configuration manager.
1. Configure directly
Settings can be set directly on the config object.
>>> from thatway import config, Setting
>>> config.a = Setting(3)
>>> config.a
3
>>> config.nested.b = Setting("nested")
>>> config.nested.b
'nested'
Trying to set an entry in the config without a setting raises an exception.
>>> from thatway import config
>>> config.new_value = 3
Traceback (most recent call last):
...
thatway.base.ConfigException: Only Settings can be inserted in the Config
2. Configure object attributes
Settings can be set as object attributes.
>>> from thatway import Setting
>>> class Obj:
... attribute = Setting("my value")
>>> obj = Obj()
>>> obj.attribute
'my value'
3. Configuration locking
Settings cannot be accidentally modified. Once they’re set, they’re set until the config’s update or load methods are used.
>>> from thatway import Setting
>>> config.b = Setting(3)
>>> config.b
3
>>> config.b = Setting(5) # oops!
Traceback (most recent call last):
...
thatway.base.ConfigException: Entry 'b' already in the Config--use a Config.update or load method to change its value.
>>> config.b = 5 # oops!
Traceback (most recent call last):
...
thatway.base.ConfigException: Only Settings can be inserted in the Config
>>> config.update({'b': 5})
>>> config.b
5
The one exception is that settings defined on a class can be replaced on the class itself–not a class instance. This is because settings act as descriptors for classes.
4. Type Enforcement
Setting types are checked and maintained with either the setting’s value type, or the allowed_types optional argument.
>>> from thatway import Setting
>>> config.c = Setting(5, allowed_types=(int, str))
>>> config.update({'c': 'my new c value'})
>>> config.c
'my new c value'
>>> config.d = Setting(6)
>>> config.update({'d': 'my new d value'})
Traceback (most recent call last):
...
ValueError: Could not convert 'my new d value' into any of the following types: [<class 'int'>]
6. Missing Settings
Trying to update a setting that doesn’t exist is not possible. This behavior is designed to avoid trying to change a setting but using an incorrect setting name and location.
>>> from thatway import Setting
>>> config.update({'e': 'unassigned'}) # 'f' doesn't exist in config
Traceback (most recent call last):
...
KeyError: "Tried assigning setting with name 'e' which does not exist in the Config"
Features
1. Setting descriptions
Settings can include descriptions.
>>> from thatway import Setting
>>> config.e = Setting(4, desc="The 'e' attribute")
2. Yaml processing
Settings can be dumped in yaml.
config.dumps_yaml()
Obj:
a: 1
b: name # The 'b' setting
nested:
c: true
And yaml strings or files can be loaded with config.loads_yaml(string) and config.load_yaml(filepath), respectively.
3. Toml processing
Settings can be dumped in toml.
config.dumps_toml()
[Obj]
a = 1
b = name # The 'b' setting
[nested]
c = true
And toml strings or files can be loaded with config.loads_toml(string) and config.load_toml(filepath), respectively.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.