Source code for zensols.grsync.config

"""Specialized application configuration.

"""
__author__ = 'Paul Landes'

from typing import List, Union
import logging
from pathlib import Path
import itertools as it
import re
from zensols.config import YamlConfig

logger = logging.getLogger(__name__)


[docs] class AppConfig(YamlConfig): """Application specific configuration access and parsing. Since much of the application centers around configuration of what to persist, this class does more heavy lifting than most configuraetion like classes. """ ROOT = 'discover' OBJECTS_PATH = f'{ROOT}.objects' PROFILES_PATH = f'{ROOT}.profiles' EMPTY_DIR_PATH = f'{ROOT}.empty_dirs' OBJECTS_PROFILE_PATH = f'{PROFILES_PATH}.{{}}.objects' EMPTY_DIR_PROFILE_PATH = f'{PROFILES_PATH}.{{}}.empty_dirs'
[docs] def __init__(self, config_file=None, default_vars=None): super(AppConfig, self).__init__( config_file, delimiter='^', default_vars=default_vars)
@property def _find_profiles(self): if not self.has_option(self.PROFILES_PATH): opts = () else: opts = self.get_options(self.PROFILES_PATH) return opts
[docs] @staticmethod def split_profiles(profile_str): return re.split(r'\s*,\s*', profile_str)
@property def _default_profiles(self): strlist = self.get_option(f'{self.ROOT}.default_profiles') if strlist is not None: return self.split_profiles(strlist)
[docs] def get_profiles(self, profile_overide: Union[str, List[str]] = None): if profile_overide is None: profiles = self._default_profiles else: if isinstance(profile_overide, str): profiles = self.split_profiles(profile_overide) else: profiles = profile_overide if profiles is None: profiles = self._find_profiles profiles = list(profiles) # protect user error if 'default' not in profiles: profiles = ['default'] + list(profiles) if 'nodefault' in profiles: profiles.pop(profiles.index('default')) profiles.pop(profiles.index('nodefault')) return profiles
def _iterate_objects(self, profile): if profile == 'default': path = self.OBJECTS_PATH else: path = self.OBJECTS_PROFILE_PATH.format(profile) opts = self.get_options(path) if opts is None and profile == 'default': opts = () if opts is None: logger.warning( f'no such profile for objects: {profile} for path {path}' + '--maybe entries exist in other profiles') opts = () return map(lambda x: x.strip(), opts)
[docs] def get_discoverable_objects(self, profiles): return it.chain(*map(self._iterate_objects, profiles))
[docs] def get_empty_dirs(self, profiles): paths = [] for profile in profiles: if profile == 'default': path = self.EMPTY_DIR_PATH else: path = self.EMPTY_DIR_PROFILE_PATH.format(profile) opts = self.get_options(path) if opts is None: ## warnings for missing empty directory entries is worth it # logger.warning( # f'no such profile for objects: {profile} for path {path}' + # '--maybe entries exist in other profiles') pass else: paths.extend(opts) return map(lambda x: Path(x).expanduser().absolute(), paths)
def _get_path(self, name): path = self.get_option(name) if path is None: raise ValueError('no path defined for option: {name}') return Path(path).expanduser().absolute() @property def dist_dir(self): return self._get_path(f'{self.ROOT}.local.dist_dir') @dist_dir.setter def dist_dir(self, dist_dir): if self.default_vars is None: self.default_vars = {} self.default_vars[f'{self.ROOT}.local.dist_dir'] = dist_dir @property def wheel_dir_name(self): return self._get_path(f'{self.ROOT}.local.wheels_dir') @property def bootstrap_script_file(self): return Path(self.dist_dir, 'bootstrap.sh')