Commit 54a45cdd authored by André Anjos's avatar André Anjos 💬

Merge branch 'resource-option' into 'master'

[click] ResourceOption can be used without ConfigCommand

See merge request !110
parents f3ead456 df27e233
Pipeline #36165 passed with stages
in 8 minutes and 21 seconds
...@@ -299,9 +299,21 @@ file.""".format( ...@@ -299,9 +299,21 @@ file.""".format(
class ResourceOption(click.Option): class ResourceOption(click.Option):
"""A click.Option that is aware if the user actually provided this option """A click.Option that automatically loads resources.
through command-line or it holds a default value. The option can also be a It uses :any:`load` to convert provided strings in the command line into Python
resource that will be automatically loaded. objects.
It also integrates with the ConfigCommand class.
You may use this class in three ways:
1. Using this class without using :any:`ConfigCommand` AND providing
`entry_point_group`.
2. Using this class with :any:`ConfigCommand` AND providing `entry_point_group`.
3. Using this class with :any:`ConfigCommand` AND without providing
`entry_point_group`.
Using this class without :any:`ConfigCommand` and without providing
`entry_point_group` does nothing and is not allowed.
Attributes Attributes
---------- ----------
...@@ -355,11 +367,25 @@ class ResourceOption(click.Option): ...@@ -355,11 +367,25 @@ class ResourceOption(click.Option):
) )
def consume_value(self, ctx, opts): def consume_value(self, ctx, opts):
logger.debug("consuming resource option for option %s", self.name) if (not hasattr(ctx, "config_context")) and self.entry_point_group is None:
raise TypeError(
"The ResourceOption class is not meant to be used this way. "
"Please see the docs of the class."
)
logger.debug("consuming resource option for %s", self.name)
value = opts.get(self.name) value = opts.get(self.name)
# if value is not given from command line, lookup the config files # if value is not given from command line, lookup the config files given as
# arguments (not options).
if value is None: if value is None:
value = ctx.config_context.get(self.name) # if this class is used with the ConfigCommand class. This is not always
# true.
if hasattr(ctx, "config_context"):
value = ctx.config_context.get(self.name)
else:
logger.debug(
"config_context attribute not found in context. Did you mean to "
"use the ConfigCommand class with this ResourceOption class?"
)
# if not from config files, lookup the environment variables # if not from config files, lookup the environment variables
if value is None: if value is None:
value = self.value_from_envvar(ctx) value = self.value_from_envvar(ctx)
...@@ -426,7 +452,7 @@ def log_parameters(logger_handle, ignore=tuple()): ...@@ -426,7 +452,7 @@ def log_parameters(logger_handle, ignore=tuple()):
logger_handle.debug("%s: %s", k, v) logger_handle.debug("%s: %s", k, v)
def assert_click_runner_result(result, exit_code=0): def assert_click_runner_result(result, exit_code=0, exception_type=None):
"""Helper for asserting click runner results""" """Helper for asserting click runner results"""
m = "Click command exited with code `{}' and exception:\n{}" "\nThe output was:\n{}" m = "Click command exited with code `{}' and exception:\n{}" "\nThe output was:\n{}"
exception = ( exception = (
...@@ -438,3 +464,5 @@ def assert_click_runner_result(result, exit_code=0): ...@@ -438,3 +464,5 @@ def assert_click_runner_result(result, exit_code=0):
assert result.exit_code == exit_code, m assert result.exit_code == exit_code, m
if exit_code == 0: if exit_code == 0:
assert not result.exception, m assert not result.exception, m
if exception_type is not None:
assert isinstance(result.exception, exception_type), m
...@@ -274,3 +274,27 @@ def test_config_command_with_callback_options(): ...@@ -274,3 +274,27 @@ def test_config_command_with_callback_options():
runner = CliRunner(env=dict(VERBOSE='2')) runner = CliRunner(env=dict(VERBOSE='2'))
result = runner.invoke(cli, catch_exceptions=False) result = runner.invoke(cli, catch_exceptions=False)
assert_click_runner_result(result) assert_click_runner_result(result)
def test_resource_option():
# tests of ResourceOption used with ConfigCommand are done in other tests.
# test usage without ConfigCommand and with entry_point_group
@click.command()
@click.option('-a', '--a', cls=ResourceOption, entry_point_group='bob.extension.test_config_load')
def cli(a):
assert a == 1, a
runner = CliRunner()
result = runner.invoke(cli, ['-a', 'bob.extension.data.resource_config2'], catch_exceptions=False)
assert_click_runner_result(result)
# test usage without ConfigCommand and without entry_point_group
# should raise a TypeError
@click.command()
@click.option('-a', '--a', cls=ResourceOption)
def cli(a):
raise ValueError("Should not have reached here!")
runner = CliRunner()
result = runner.invoke(cli, ['-a', '1'], catch_exceptions=True)
assert_click_runner_result(result, exit_code=1, exception_type=TypeError)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment