Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

properly handle bad config and fail early #445

Merged
merged 5 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions dotdrop/cfg_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ class CfgYaml:
top_entries = [key_dotfiles, key_settings, key_profiles]

def __init__(self, path, profile=None, addprofiles=None,
reloading=False, debug=False, imported_configs=None):
reloading=False, debug=False, imported_configs=None,
fail_on_error=True):
"""
config parser
@path: config file path
Expand Down Expand Up @@ -168,7 +169,7 @@ def __init__(self, path, profile=None, addprofiles=None,
# live patch deprecated entries
self._fix_deprecated(self._yaml_dict)
# validate content
self._validate(self._yaml_dict)
self._validate(self._yaml_dict, fail_on_error)

##################################################
# parse the config and variables
Expand Down Expand Up @@ -1080,7 +1081,8 @@ def _import_config(self, path):
sub = CfgYaml(path, profile=self._profile,
addprofiles=self._inc_profiles,
debug=self._debug,
imported_configs=self.imported_configs)
imported_configs=self.imported_configs,
fail_on_error=False)

# settings are ignored from external file
# except for filter_file and func_file
Expand Down Expand Up @@ -1337,9 +1339,11 @@ def _load_yaml(self, path):
self._dbg(f'format: {self._config_format}')
return content

def _validate(self, yamldict):
def _validate(self, yamldict, fail_on_error):
"""validate entries"""
if not yamldict:
if fail_on_error:
raise YamlException('empty config file')
return

# check top entries
Expand All @@ -1352,21 +1356,24 @@ def _validate(self, yamldict):
# check link_dotfile_default
if self.key_settings not in yamldict:
# no configs top entry
if fail_on_error:
raise YamlException(f'no \"{self.key_settings}\" key found')
return
if not yamldict[self.key_settings]:
# configs empty
if fail_on_error:
raise YamlException(f'empty \"{self.key_settings}\" key')
return

# check settings values
settings = yamldict[self.key_settings]
if self.key_settings_link_dotfile_default not in settings:
return
val = settings[self.key_settings_link_dotfile_default]
if val not in self.allowed_link_val:
err = f'bad link value: {val}'
self._log.err(err)
self._log.err(f'allowed: {self.allowed_link_val}')
raise YamlException(f'config content error: {err}')
if self.key_settings_link_dotfile_default in settings:
val = settings[self.key_settings_link_dotfile_default]
if val not in self.allowed_link_val:
err = f'bad link value: {val}'
self._log.err(err)
self._log.err(f'allowed: {self.allowed_link_val}')
raise YamlException(f'config content error: {err}')

@classmethod
def _yaml_load(cls, path):
Expand Down
8 changes: 4 additions & 4 deletions dotdrop/dotdrop.py
Original file line number Diff line number Diff line change
Expand Up @@ -935,16 +935,16 @@ def main():
try:
opts = Options()
except YamlException as exc:
LOG.err(f'error (yaml): {exc}')
LOG.err(f'yaml error: {exc}')
return False
except ConfigException as exc:
LOG.err(f'error (config): {exc}')
LOG.err(f'config error: {exc}')
return False
except UndefinedException as exc:
LOG.err(f'error (deps): {exc}')
LOG.err(f'dependencies error: {exc}')
return False
except OptionsException as exc:
LOG.err(f'error (options): {exc}')
LOG.err(f'options error: {exc}')
return False

if opts.debug:
Expand Down
4 changes: 3 additions & 1 deletion dotdrop/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,14 @@ def __init__(self, args=None):
# selected profile
self.profile = self.args['--profile']
self.confpath = self._get_config_path()
if not self.confpath:
raise YamlException('no config file found')
self.confpath = os.path.abspath(self.confpath)
self.log.dbg(f'config abs path: {self.confpath}')
if not self.confpath:
raise YamlException('no config file found')
if not os.path.exists(self.confpath):
err = f'bad config file path: {self.confpath}'
err = f'config does not exist \"{self.confpath}\"'
raise YamlException(err)
self.log.dbg('#################################################')
self.log.dbg('#################### DOTDROP ####################')
Expand Down
Loading