Add getall/getrawall for nested params, ROOT_KEY constant, tests and docs
This commit is contained in:
@@ -12,6 +12,10 @@ config = src.utils.config_manager.config
|
||||
- `config.register(name, val, default, desc, cat, env, validator)` - register a parameter
|
||||
- `config.get(name, cat)` - get parameter value
|
||||
- `config.set(name, value, cat)` - set parameter value (triggers validator if present)
|
||||
- `config.getraw(key)` - get by full key path (no cat substitution)
|
||||
- `config.setraw(key, value)` - set by full key path
|
||||
- `config.getall(name, cat)` - get root + all nested params as dict with `ROOT_KEY`
|
||||
- `config.getrawall(cat)` - get all params under category as nested dict
|
||||
- `config.get_parameter(name, cat)` - get ConfigParameter object
|
||||
- `config.get_description(name, cat)` - get parameter description
|
||||
- `config.load(path?)` - load from file or env
|
||||
@@ -31,6 +35,19 @@ On failure: logs error via `logger.error()` and raises exception. Value unchange
|
||||
- `DEFAULT_CONFIG_FILE = "config/global.yaml"`
|
||||
- `DEFAULT_CONFIG_ENV = "KOMAI_CONFIG_FILE"`
|
||||
- `DEFAULT_CATEGORY = "global"`
|
||||
- `ROOT_KEY = "$root$"` - key name for root value in nested getall/getrawall results
|
||||
|
||||
## Nested Parameters
|
||||
|
||||
Params with dots in name create nested structures:
|
||||
```python
|
||||
config.register(name="coder", val="llama-coder", cat="models")
|
||||
config.register(name="coder.thinking", val="full", cat="models")
|
||||
|
||||
config.get("coder", cat="models") # "llama-coder"
|
||||
config.getall("coder", cat="models") # {"$root$": "llama-coder", "thinking": "full"}
|
||||
config.getrawall("models") # {"coder": {"$root$": "llama-coder", "thinking": "full"}}
|
||||
```
|
||||
|
||||
## ConfigParameter Properties
|
||||
|
||||
@@ -40,6 +57,6 @@ On failure: logs error via `logger.error()` and raises exception. Value unchange
|
||||
## Implementation Notes
|
||||
|
||||
- Single global instance created at module import (`config` object in `__init__.py`)
|
||||
- All `__init__.py` files re-export only `config`
|
||||
- `ROOT_KEY` exported from module for custom notation if needed
|
||||
- Validator called via property setter on `_val` attribute
|
||||
- `reset()` re-creates params dict and reloads from file
|
||||
|
||||
@@ -7,6 +7,7 @@ from typing import Callable, Optional
|
||||
DEFAULT_CONFIG_FILE = "config/global.yaml"
|
||||
DEFAULT_CONFIG_ENV = "KOMAI_CONFIG_FILE"
|
||||
DEFAULT_CATEGORY = "global"
|
||||
ROOT_KEY = "$root$"
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -121,32 +122,97 @@ class ConfigManager:
|
||||
self._params[key] = param
|
||||
return param
|
||||
|
||||
def get(self, name: str, cat: str = DEFAULT_CATEGORY) -> Optional[str]:
|
||||
def get(self, name: str, cat: str = None) -> Optional[str]:
|
||||
cat = cat or DEFAULT_CATEGORY
|
||||
key = f"{cat}.{name}"
|
||||
param = self._params.get(key)
|
||||
if param is None:
|
||||
return None
|
||||
return param.val
|
||||
|
||||
def get_description(self, name: str, cat: str = DEFAULT_CATEGORY) -> Optional[str]:
|
||||
def getraw(self, key: str):
|
||||
param = self._params.get(key)
|
||||
if param is None:
|
||||
return None
|
||||
return param.val
|
||||
|
||||
def get_description(self, name: str, cat: str = None) -> Optional[str]:
|
||||
cat = cat or DEFAULT_CATEGORY
|
||||
key = f"{cat}.{name}"
|
||||
param = self._params.get(key)
|
||||
if param is None:
|
||||
return None
|
||||
return param.desc
|
||||
|
||||
def get_parameter(
|
||||
self, name: str, cat: str = DEFAULT_CATEGORY
|
||||
) -> Optional[ConfigParameter]:
|
||||
def get_parameter(self, name: str, cat: str = None) -> Optional[ConfigParameter]:
|
||||
cat = cat or DEFAULT_CATEGORY
|
||||
key = f"{cat}.{name}"
|
||||
return self._params.get(key)
|
||||
|
||||
def set(self, name: str, value, cat: str = DEFAULT_CATEGORY) -> None:
|
||||
def set(self, name: str, value, cat: str = None) -> None:
|
||||
cat = cat or DEFAULT_CATEGORY
|
||||
key = f"{cat}.{name}"
|
||||
param = self._params.get(key)
|
||||
if param is not None:
|
||||
param.val = value
|
||||
|
||||
def setraw(self, key: str, value) -> None:
|
||||
param = self._params.get(key)
|
||||
if param is not None:
|
||||
param.val = value
|
||||
|
||||
def getall(self, name: str, cat: str = None) -> Optional[dict]:
|
||||
cat = cat or DEFAULT_CATEGORY
|
||||
root_key = f"{cat}.{name}"
|
||||
root_param = self._params.get(root_key)
|
||||
if root_param is None:
|
||||
return None
|
||||
|
||||
result = {ROOT_KEY: root_param.val}
|
||||
prefix = root_key + "."
|
||||
|
||||
for key, param in self._params.items():
|
||||
if key.startswith(prefix):
|
||||
nested_key = key[len(prefix) :]
|
||||
parts = nested_key.split(".")
|
||||
if len(parts) == 1:
|
||||
result[parts[0]] = param.val
|
||||
else:
|
||||
current = result
|
||||
for part in parts[:-1]:
|
||||
if part not in current:
|
||||
current[part] = {}
|
||||
current = current[part]
|
||||
current[parts[-1]] = param.val
|
||||
|
||||
return result
|
||||
|
||||
def getrawall(self, key: str) -> Optional[dict]:
|
||||
if not key.endswith("."):
|
||||
key = key + "."
|
||||
result = {}
|
||||
|
||||
for param_key, param in self._params.items():
|
||||
if not param_key.startswith(key):
|
||||
continue
|
||||
|
||||
nested_key = param_key[len(key) :]
|
||||
parts = nested_key.split(".")
|
||||
|
||||
if len(parts) == 1:
|
||||
result[parts[0]] = param.val
|
||||
else:
|
||||
current = result
|
||||
for i, part in enumerate(parts[:-1]):
|
||||
if part not in current:
|
||||
current[part] = {}
|
||||
elif isinstance(current[part], str):
|
||||
current[part] = {ROOT_KEY: current[part]}
|
||||
current = current[part]
|
||||
current[parts[-1]] = param.val
|
||||
|
||||
return result if result else None
|
||||
|
||||
def load(self, path: str = None) -> dict:
|
||||
if path:
|
||||
self._config_path = Path(path)
|
||||
|
||||
Reference in New Issue
Block a user