From 8cfa61607336ddb154933c11a591ae65fb910b4b Mon Sep 17 00:00:00 2001 From: Nils Philippsen Date: Nov 21 2019 09:55:28 +0000 Subject: [PATCH 1/2] fix console script entry point In the course, clean up how execution errors are processed, i.e. use exceptions rather than integer return codes to indicate errors. Signed-off-by: Nils Philippsen --- diff --git a/distgit_bugzilla_sync/script.py b/distgit_bugzilla_sync/script.py index 093d99b..ea53c2c 100644 --- a/distgit_bugzilla_sync/script.py +++ b/distgit_bugzilla_sync/script.py @@ -401,6 +401,13 @@ def _is_retired(product, project): return True +class ScriptExecError(RuntimeError): + + def __init__(self, *args, **kwargs): + self.errorcode = kwargs.pop('errorcode', 1) + super().__init__(*args, **kwargs) + + class DistgitBugzillaSync: def notify_users(self, errors): @@ -587,8 +594,20 @@ class DistgitBugzillaSync: return override_yaml.get('bugzilla_contact', {}) return {} - def main(self): - """The entrypoint to the script.""" + @classmethod + def main(cls): + """The entrypoint for running the script.""" + dbs = cls() + try: + dbs.run() + except ScriptExecError as e: + print(str(e), file=sys.stderr) + sys.exit(e.errorcode) + else: + sys.exit(0) + + def run(self): + """Run the script.""" global envname, env, projects_dict times = { "start": time.time(), @@ -604,8 +623,7 @@ class DistgitBugzillaSync: if self.args.env in self.config['environments']: envname = self.args.env else: - print(f"Invalid environment specified: {self.args.env}") - return 1 + raise ScriptExecError(f"Invalid environment specified: {self.args.env}") self.env = self.config['environments'][envname] @@ -736,9 +754,6 @@ class DistgitBugzillaSync: delta = times["end"] - times["start"] print(f" Ran on {delta:.2f} seconds -- ie: {delta/60:.2f} minutes") - return 0 - if __name__ == '__main__': - dbs = DistgitBugzillaSync() - sys.exit(dbs.main()) + DistgitBugzillaSync.main() diff --git a/setup.py b/setup.py index b1fd094..8c14918 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ setup( tests_require=TESTS_REQUIRE, entry_points={ 'console_scripts': [ - 'distgit-bugzilla-sync = distgit_bugzilla_sync.script:main', + 'distgit-bugzilla-sync = distgit_bugzilla_sync.script:DistgitBugzillaSync.main', ], }, ) From 4ccfc9b5e6ad914205e7acdf15686e57c4b1a79d Mon Sep 17 00:00:00 2001 From: Nils Philippsen Date: Nov 21 2019 10:15:48 +0000 Subject: [PATCH 2/2] expose additional configuration files to CLI This adds the --add-config-file, --add-email-overrides-file options and as a side effect allows to specify any number of either which will be applied in order to the respective configuration objects. Signed-off-by: Nils Philippsen --- diff --git a/distgit_bugzilla_sync/config.py b/distgit_bugzilla_sync/config.py index 004a480..a5bb03d 100644 --- a/distgit_bugzilla_sync/config.py +++ b/distgit_bugzilla_sync/config.py @@ -17,6 +17,7 @@ import copy import os +from typing import Optional, Sequence import toml @@ -84,12 +85,18 @@ class ConfigDict(dict): self[k] = v -def load_configuration(addl_config_file=None, addl_email_overrides_file=None): +def load_configuration(addl_config_files: Optional[Sequence[str]] = None, + addl_email_overrides_files: Optional[Sequence[str]] = None): """Load stored configuration. This function loads default, system-wide, and if specified, additional configuration files into the `config` and `email_overrides` dictionaries.""" + if addl_config_files is None: + addl_config_files = () + if addl_email_overrides_files is None: + addl_email_overrides_files = () + # Load default files. try: default_config = toml.load(config_files['default']['configuration']) @@ -117,25 +124,23 @@ def load_configuration(addl_config_file=None, addl_email_overrides_file=None): system_email_overrides = {} # Load additional files (say, specified on the command line), if any. - if addl_config_file: + addl_config = ConfigDict() + for addl_config_file in addl_config_files: try: - addl_config = toml.load(addl_config_file) + addl_config.update(toml.load(addl_config_file)) except FileNotFoundError as e: raise RuntimeError( f"Additional configuration file {addl_config_file} not found." ) from e - else: - addl_config = {} - if addl_email_overrides_file: + addl_email_overrides = ConfigDict() + for addl_email_overrides_file in addl_email_overrides_files: try: - addl_email_overrides = toml.load(addl_email_overrides_file) + addl_email_overrides.update(toml.load(addl_email_overrides_file)) except FileNotFoundError as e: raise RuntimeError( f"Additional email overrides file {addl_email_overrides_file} not found." ) from e - else: - addl_email_overrides = {} config.clear() config.update(default_config) diff --git a/distgit_bugzilla_sync/script.py b/distgit_bugzilla_sync/script.py index ea53c2c..8767ebf 100644 --- a/distgit_bugzilla_sync/script.py +++ b/distgit_bugzilla_sync/script.py @@ -486,6 +486,12 @@ class DistgitBugzillaSync: '--env', dest='env', help='Run the script for a specific environment, overrides the one ' 'set in the configuration file') + parser.add_argument('--add-config-file', metavar='CONFIG_FILE', + dest='addl_config_files', action='append', + help="File(s) from which to read overriding configuration") + parser.add_argument('--add-email-overrides-file', metavar='EMAIL_OVERRIDES_FILE', + dest='addl_email_overrides_files', action='append', + help="File(s) from which to read additional email overrides") self.args = parser.parse_args() @@ -615,7 +621,8 @@ class DistgitBugzillaSync: self.get_cli_arguments() - load_configuration() + load_configuration(addl_config_files=self.args.addl_config_files, + addl_email_overrides_files=self.args.addl_email_overrides_files) self.config = config envname = self.config['environment']