From ee9ad10b5cc9850c3e2ed1946f70e0cef429fb48 Mon Sep 17 00:00:00 2001 From: Hunt Date: Tue, 3 Jun 2025 11:58:25 -0700 Subject: Refactor --- dots_manager/config.py | 145 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 6 deletions(-) (limited to 'dots_manager/config.py') diff --git a/dots_manager/config.py b/dots_manager/config.py index d6194f6..96d3293 100644 --- a/dots_manager/config.py +++ b/dots_manager/config.py @@ -1,14 +1,147 @@ +import argparse +import os +import json +import logging from dataclasses import dataclass +from typing import Dict, Any, Optional from pathlib import Path -import os +from dots_manager.shell import run_shell_command +from dots_manager.utils import merge_dicts +from dots_manager.kawaii_logger import setup_logger + + +@dataclass(frozen=True) +class Environment: + platform: str + system_name: str + context: Dict[str, Any] + logger: logging.Logger + + @staticmethod + def from_argv(args: argparse.Namespace): + logger = setup_logger(verbose=args.verbose, logger_name="dots_manager") + + platform = args.platform or run_shell_command( + [str(args.helper_scripts / "platform.sh")], logger + ) + if not platform: + raise ValueError("failed to determine platform... ") + os.environ["PLATFORM"] = platform + + system_name: Optional[str] = args.system_name or run_shell_command( + [str(args.helper_scripts / "system_name.sh")], logger + ) + if not system_name: + raise ValueError("failed to determine system name... ") + + context = load_context(platform, system_name, args.context, logger) + return Environment(platform, system_name, context, logger) @dataclass(frozen=True) -class Config: +class Constants: default_target_dir: Path = Path.home() - default_source_dir: Path = Path(__file__).parent.parent / "dots" - default_compiled_dir: Path = Path("./.compiled_dotfiles/") - script_dir: Path = Path("home/scripts") - contexts: Path = Path("contexts.json") + + dots_repo_dir: Path = Path.home() / Path("dotfiles") + default_source_dir: Path = dots_repo_dir / Path("dots") + default_compiled_dir: Path = dots_repo_dir / Path(".compiled_dotfiles") + + default_script_dir: Path = default_source_dir / Path("home/scripts") + default_context: Path = dots_repo_dir / Path("context.json") + template_extension: str = ".j2" max_workers: int = (os.cpu_count() or 1) * 2 + + global_context_key: str = "_global" + platform_default_context_key: str = "_default" + + +def load_context( + platform: str, system_name: str, context_file: Path, logger: logging.Logger +): + logger.info(f"reading context file: {context_file} ✧*:。゚✧") + + context = json.loads(context_file.read_text()) + + global_context = context.get(Constants.global_context_key, {}) + platform_defaults = context.get(platform, {}).get( + Constants.platform_default_context_key, {} + ) + defaults = merge_dicts(global_context, platform_defaults) + + system_config = context.get(platform, {}).get(system_name, {}) + if not system_config: + logger.warning( + f"could not find context for 'contexts.{platform}.{system_name}' in {context_file.absolute()}" + ) + return { + "platform": platform, + "system_name": system_name, + **merge_dicts(defaults, system_config), + } + + +def parse_arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="૮ ․ ․ ྀིა emprespresso's dotfiles manager 🐧✧˖°" + ) + parser.add_argument( + "--verbose", + "-v", + action="store_true", + default=os.environ.get("DEBUG", "false").lower() in ("y", "yes", "true", "t"), + help="enables verbose logging.", + ) + + parser.add_argument("--compile", action="store_true", help="compile le dotfiles.") + parser.add_argument( + "--source", + type=Path, + default=Constants.default_source_dir, + help=f"where to look for templated dotfile packages. default: '{Constants.default_source_dir}'.", + ) + parser.add_argument( + "--output", + type=Path, + default=Constants.default_compiled_dir, + help=f"where to store compiled, stowable dotfile packages. default: '{Constants.default_compiled_dir}'.", + ) + parser.add_argument( + "--context", + type=Path, + default=Constants.default_context, + help=f"path to contexts, stored as json. default: '{Constants.default_context}'.", + ) + parser.add_argument( + "--helper-scripts", + type=Path, + default=Constants.default_script_dir, + help="where to find executable scripts to determine system info (device name, platform, etc.).", + ) + parser.add_argument( + "--system-name", + type=str, + default=None, + help="the system's name. when unspecified, inferred via the hostname, or on osx, computername.", + ) + parser.add_argument( + "--platform", + type=str, + default=None, + help="the system's os platform (i.e. osx, linux, bsd, windows, etc.). when unspecified, inferred via $OSTYPE.", + ) + + parser.add_argument( + "--stow", action="store_true", help="action: stow compiled dotfiles" + ) + parser.add_argument( + "--clean", action="store_true", help="action: clean stowed dotfiles" + ) + parser.add_argument( + "--target", + type=Path, + default=Constants.default_target_dir, + help=f"where the dotfile packages' symlinks will be stowed. default: '{Constants.default_target_dir}'", + ) + + return parser.parse_args() -- cgit v1.2.3-70-g09d2