From 10d900248ed9ea99d9a2688927844f77c20d8858 Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Sat, 13 Apr 2024 17:52:05 +0200 Subject: [PATCH] config: Add ask_value() helper to section & config objects --- mylib/config.py | 97 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 26 deletions(-) diff --git a/mylib/config.py b/mylib/config.py index eea6cd4..c0d5d89 100644 --- a/mylib/config.py +++ b/mylib/config.py @@ -247,14 +247,22 @@ class BaseOption: # pylint: disable=too-many-instance-attributes value = self._get_user_input(prompt) return default_value if value == "" else value - def ask_value(self, set_it=True): + def ask_value(self, set_it=True, return_value=False): """ - Ask to user to enter value of this option and set or - return it regarding set parameter + Ask to user to enter value of this option and set it if set_it parameter is True + + :param set_it: If True (default), option value will be updated with user input + :param return_value: If True, force return option value even if set_it is True + + :return: If set_it is True, return True if a valid value have been retrieved and + set. If False, return configuration option value. + :rtype: mixed """ value = self._ask_value() if set_it: - return self.set(value) + if self.set(value): + return value if return_value else True + return False return value @@ -508,10 +516,16 @@ class PasswordOption(StringOption): value = getpass(prompt) return default_value if value == "" else value - def ask_value(self, set_it=True): + def ask_value(self, set_it=True, return_value=False): """ - Ask to user to enter value of this option and set or - return it regarding set parameter + Ask to user to enter value of this option and set it if set_it parameter is True + + :param set_it: If True (default), option value will be updated with user input + :param return_value: If True, force return option value even if set_it is True + + :return: If set_it is True, return True if a valid value have been retrieved and + set. If False, return configuration option value. + :rtype: mixed """ value = self._ask_value() if set_it: @@ -530,7 +544,9 @@ class PasswordOption(StringOption): use_keyring = False else: print("Invalid answer. Possible values: Y or N (case insensitive)") - return self.set(value, use_keyring=use_keyring) + if self.set(value, use_keyring=use_keyring): + return value if return_value else True + return False return value @@ -604,11 +620,12 @@ class ConfigSection: lines.append(self.options[option].export_to_config()) return "\n".join(lines) - def ask_values(self, set_it=True): + def ask_values(self, set_it=True, return_value=False): """ Ask user to enter value for each configuration option of the section :param set_it: If True (default), option value will be updated with user input + :param return_value: If True, force return options value even if set_it is True :return: If set_it is True, return True if valid value for each configuration option have been retrieved and set. If False, return a dict of configuration @@ -621,17 +638,30 @@ class ConfigSection: result = {} error = False for name, option in self.options.items(): - option_result = option.ask_value(set_it=set_it) - if set_it: - result[name] = option_result - elif not option_result: + result[name] = option.ask_value(set_it=set_it, return_value=return_value) + if set_it and not return_value and not result[name]: error = True print() print() - if set_it: + if set_it and not return_value: return not error return result + def ask_value(self, option, set_it=True, return_value=False): + """ + Ask user to enter value for the specified configuration option of the section + + :param options: The configuration option name + :param set_it: If True (default), option value will be updated with user input + :param return_value: If True, force return option value even if set_it is True + + :return: If set_it is True, return True if a valid value have been retrieved and + set. If False, return configuration option value. + :rtype: mixed + """ + assert self.defined(option), f"Option {option} unknown" + return self.options[option].ask_value(set_it=set_it, return_value=return_value) + class RawWrappedTextHelpFormatter(argparse.RawDescriptionHelpFormatter): """ @@ -1092,11 +1122,12 @@ class Config: # pylint: disable=too-many-instance-attributes for section in self._ordered_section_names: self.sections[section].add_options_to_parser(parser) - def ask_values(self, set_it=True, execute_callback=False): + def ask_values(self, set_it=True, return_value=False, execute_callback=False): """ Ask user to enter value for each configuration option :param set_it: If True (default), option value will be updated with user input + :param return_value: If True, force return options value even if set_it is True :param execute_callback: Sections's loaded callbacks will be finally executed (only if set_it is True, default: False) @@ -1108,18 +1139,32 @@ class Config: # pylint: disable=too-many-instance-attributes result = {} error = False for name, section in self.sections.items(): - section_result = section.ask_values(set_it=set_it) - if not set_it: - result[name] = section_result - elif not section_result: + result[name] = section.ask_values(set_it=set_it, return_value=return_value) + if set_it and not return_value and not result[name]: error = True - if set_it: - if error: - return False - if execute_callback: - self._loaded() - return True - return result + + if set_it and execute_callback and not error: + self._loaded() + + if set_it and not return_value: + return not error + return not error if set_it and not return_value else result + + def ask_value(self, section, option, set_it=True, return_value=False): + """ + Ask user to enter value for the specified configuration option + + :param section: The configuration section name + :param option: The configuration option name + :param set_it: If True (default), option value will be updated with user input + :param return_value: If True, force return option value even if set_it is True + + :return: If set_it is True, return True if a valid value have been retrieved and + set. If False, return configuration option value. + :rtype: mixed + """ + assert self.defined(section, option), f"Unknown option {section}.{option}" + return self.sections[section].ask_value(option, set_it=set_it, return_value=return_value) def configure(self, argv=None, description=False): """