From 31426c006bd2e5e4fda375c1e6f5ef2576993f56 Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Thu, 30 Apr 2026 10:49:46 +0200 Subject: [PATCH] feat(typing): Start adding python types for the configuration --- config.schema.json | 18 ++++----------- config.yml | 3 +-- config/__init__.py | 9 ++++---- config/dtype.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++ config/merger.py | 5 ++++- 5 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 config/dtype.py diff --git a/config.schema.json b/config.schema.json index 18e1a9b..648d1c8 100644 --- a/config.schema.json +++ b/config.schema.json @@ -183,20 +183,10 @@ "description": "The directory for the bootloader files. Has to end in slash", "pattern": "^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))\\/$" }, - "theme": { - "type": "object", - "description": "Configuration for the bootloader theme", - "properties": { - "folder": { - "type": "string", - "description": "Where the folder for the theme is found. Can be relative to the config repo or file system and has to end in slash", - "pattern": "^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))\\/$" - } - }, - "additionalProperties": false, - "required": [ - "folder" - ] + "theme_folder": { + "type": "string", + "description": "Where the folder for the theme is found. Can be relative to the config repo or file system and has to end in slash", + "pattern": "^(^(~|\\.|\\.\\.)?\\/)?([\\w\\/.-]+(?!.*[^\\w\\/.-]+))\\/$" }, "os_prober": { "type": "boolean", diff --git a/config.yml b/config.yml index 2cbab90..c62fb6e 100644 --- a/config.yml +++ b/config.yml @@ -23,8 +23,7 @@ users: boot: bootloader: grub esp_dir: /boot/ - theme: - folder: ~/.path/to/theme/ + theme_folder: ~/.path/to/theme/ os_prober: False # Also copies over the /etc/default/grub config or equivalent for other supported bootloaders diff --git a/config/__init__.py b/config/__init__.py index 85222ac..e52bb46 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -2,6 +2,7 @@ from typing import Any, cast import yaml from config import validator +from config.dtype import ArchMgrConfig from config.merger import merge_configs @@ -11,7 +12,7 @@ def _load_config_file(file: str): return parsed -def load_config(file: str): +def load_config(file: str) -> ArchMgrConfig: # Load and validate initial config try: loaded_conf = _load_config_file(file) @@ -20,9 +21,9 @@ def load_config(file: str): if not validator.validate(loaded_conf): return {} - conf = cast(dict[str, Any], loaded_conf) - requires = cast(list[str], conf["requires"]) - conf.pop("requires") + configuration = cast(dict[str, Any], loaded_conf) + requires = cast(list[str], configuration.pop("requires")) + conf = cast(ArchMgrConfig, configuration) # Recursively load files for conf_file in requires: diff --git a/config/dtype.py b/config/dtype.py new file mode 100644 index 0000000..ad88f85 --- /dev/null +++ b/config/dtype.py @@ -0,0 +1,56 @@ +from typing import Optional, TypedDict + + +class ArchMgrConfig(TypedDict): + pkgs: ArchMgrPkgConfig + users: list[ArchMgrUserConfig] + + +class ArchMgrPkgConfig(TypedDict): + individual: list[str] + bundles: list[object] # TODO: Better typing + repos: object # TODO: Repo typing + + +class ArchMgrUserConfig(TypedDict): + username: str + groups: list[str] + home_dir: bool + + +class ArchMgrBootConfig(TypedDict): + bootloader: str + esp_dir: str + theme_folder: str + os_prober: bool + + +class ArchMgrThemeConfig(TypedDict): + gtk: str + qt: str + font: str + icon_theme: str + cursor_theme: str + + +class ArchMgrGitConfig(TypedDict): + creds: object # TODO: + repos: object # TODO + + +class ArchMgrGitRepoConfig(TypedDict): + clone_path: str + url: str + + +class ArchMgrCmdsConfig(TypedDict): + always: ArchMgrCommand + once: ArchMgrCommand + + +class ArchMgrCommand(TypedDict): + cmd: str + name: Optional[str] + capture_output: Optional[bool] + hook: Optional[str] + user: Optional[str] diff --git a/config/merger.py b/config/merger.py index 6699e35..829da5e 100644 --- a/config/merger.py +++ b/config/merger.py @@ -1,4 +1,7 @@ -def merge_configs(config: dict, new_config: dict): +from config.dtype import ArchMgrConfig + + +def merge_configs(config: ArchMgrConfig, new_config: ArchMgrConfig) -> ArchMgrConfig: if len(new_config) == 0 or len(config) == 0: return config