diff --git a/bob/extension/scripts/click_helper.py b/bob/extension/scripts/click_helper.py index 8bdb097d71c9caac646071d6fbc562a2516e038c..a487a574fbb1cca674dc2e87385a3c29bd31d208 100644 --- a/bob/extension/scripts/click_helper.py +++ b/bob/extension/scripts/click_helper.py @@ -1,5 +1,6 @@ from ..log import set_verbosity_level from ..config import load, mod_to_context +import time import click import logging @@ -172,6 +173,9 @@ class ConfigCommand(click.Command): **kwargs) # Add the config argument to the command click.argument(config_argument_name, nargs=-1)(self) + # Option for config file generation + click.option('-dc', '--dump-config', type=click.Path(exists=False), + help="Name of the config file to be generated")(self) def invoke(self, ctx): config_files = ctx.params[self.config_argument_name.lower()] @@ -180,7 +184,7 @@ class ConfigCommand(click.Command): config_files, entry_point_group=self.entry_point_group) config_context = mod_to_context(config_context) for param in self.params: - if param.name not in ctx.params: + if param.name not in ctx.params or param.name == 'dump_config': continue value = ctx.params[param.name] if not hasattr(param, 'user_provided'): @@ -200,9 +204,27 @@ class ConfigCommand(click.Command): finally: # make sure to set this back to False for future invocations param.required = False + if 'dump_config' in ctx.params: + self.dump_config(ctx) return super(ConfigCommand, self).invoke(ctx) + def dump_config(self, ctx): + config_file = open(ctx.params.get('dump_config'), 'w') + config_file.write('# Configuration file automatically generated at %s ' + 'for %s.\n\n\n' % (time.strftime("%d/%m/%Y"), + ctx.command_path)) + for param in self.params: + if param.name not in ctx.params or param.name == 'dump_config': + continue + if not isinstance(param, click.Option): + continue + + config_file.write('# %s.\n\n' % param.help) + config_file.write('# %s = %s \n\n' % (param.name, + str(ctx.params[param.name]))) + config_file.write('\n\n\n') + class ResourceOption(click.Option): """A click.Option that is aware if the user actually provided this option diff --git a/bob/extension/scripts/main_cli.py b/bob/extension/scripts/main_cli.py index 46ab57f9b6196e8d8510f0dd6c1bc2e2019fb681..3f08db409d37045ee80ca99befa69b5ae22f5921 100644 --- a/bob/extension/scripts/main_cli.py +++ b/bob/extension/scripts/main_cli.py @@ -3,7 +3,7 @@ import pkg_resources import click from click_plugins import with_plugins -from .click_helper import AliasedGroup +from .click_helper import AliasedGroup, ConfigCommand from ..log import setup logger = setup('bob') diff --git a/bob/extension/test_click_helper.py b/bob/extension/test_click_helper.py index 2872fe1a01addac80d0f3a9f850f44c66d5d870f..dbdbb28e627ca53bd79559a821b7975c3e324466 100644 --- a/bob/extension/test_click_helper.py +++ b/bob/extension/test_click_helper.py @@ -171,3 +171,20 @@ def test_prefix_aliasing(): result = runner.invoke(cli, ['test_a'], catch_exceptions=False) assert result.exit_code == 0, (result.exit_code, result.output) assert 'AAA' in result.output, (result.exit_code, result.output) + + +def test_config_dump(): + @click.group(cls=AliasedGroup) + def cli(): + pass + + @click.command(cls=ConfigCommand) + @click.option('-t', '--test', required=True, default="/my/path/test.txt", + help="Path leading to test blablabla", cls=ResourceOption) + @verbosity_option() + def test(config, test, **kwargs): + pass + runner = CliRunner() + with runner.isolated_filesystem(): + result = runner.invoke(cli, ['test', '-dc', 'TEST_CONF'], catch_exceptions=False) + assert result.exit_code != 0, (result.exit_code, result.output)