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

Update qiime info to show parallel config info #340

Merged
merged 10 commits into from
Aug 14, 2024
38 changes: 37 additions & 1 deletion q2cli/builtin/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,20 @@ def _echo_plugins():

@click.command(help='Display information about current deployment.',
cls=ToolCommand)
def info():
@click.option('--config-level',
required=False,
default=1,
show_default=True,
type=click.IntRange(0, 3),
help='Specify the level of detail you want the config to be '
'displayed in')
def info(config_level):
import q2cli.util
# This import improves performance for repeated _echo_plugins
import q2cli.core.cache
from qiime2.sdk.parallel_config import (get_vendored_config,
load_config_from_dict)
from tomlkit import dumps

click.secho('System versions', fg='green')
_echo_version()
Expand All @@ -51,5 +61,31 @@ def info():
click.secho('\nApplication config directory', fg='green')
click.secho(q2cli.util.get_app_dir())

if config_level:
click.secho('\nConfig', fg='green')

config, action_executor_mapping, vendored_source = \
get_vendored_config()

click.secho(f'Config Source: {vendored_source}')

if action_executor_mapping:
config['parsl.executor_mapping'] = action_executor_mapping

if config_level > 1:
if config_level == 2:
config = dumps(config)
elif config_level == 3:
config['parsl'], _ = load_config_from_dict(config)

click.secho(f'\n{config}')

click.secho('\nGetting help', fg='green')
click.secho('To get help with QIIME 2, visit https://qiime2.org')

# When we have the final docs for this stuff up we should probably replace
# this with a reference to our docs which wil reference the parsl docs
if config_level:
click.secho('To get help with configuring/understanding QIIME 2 '
'parallelization visit '
'https://parsl.readthedocs.io/en/stable/')
92 changes: 92 additions & 0 deletions q2cli/tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,46 @@
from q2cli.click.type import QIIME2Type


CONFIG_LEVEL_2 = """[parsl]
strategy = "None"

[[parsl.executors]]
class = "ThreadPoolExecutor"
label = "default"
max_threads = 1

[[parsl.executors]]
class = "_TEST_EXECUTOR_"
label = "test"
max_threads = 1"""

# This is formatted this way to ensure the trailing spaces tomlkit.dumps throws
# at the end of a bunch of lines for no apparent reason are preserved here
CONFIG_LEVEL_3 = "{'parsl': Config(" +\
"\n app_cache=True, " +\
"\n checkpoint_files=None, " +\
"\n checkpoint_mode=None, " +\
"\n checkpoint_period=None, " +\
"\n executors=(ThreadPoolExecutor(" +\
"\n label='default', " +\
"\n max_threads=1, " +\
"\n storage_access=None, " +\
"\n thread_name_prefix='', " +\
"\n working_dir=None" +\
"\n ), _TEST_EXECUTOR_()), " +\
"\n garbage_collect=True, " +\
"\n initialize_logging=True, " +\
"\n internal_tasks_max_threads=10, " +\
"\n max_idletime=120.0, " +\
"\n monitoring=None, " +\
"\n retries=0, " +\
"\n retry_handler=None, " +\
"\n run_dir='runinfo', " +\
"\n strategy='none', " +\
"\n strategy_period=5, " +\
"\n usage_tracking=False" +\
"\n)}"

EXPECTED_CITATIONS = """% use `qiime tools citations` on a QIIME 2 result for complete list

@article{key0,
Expand Down Expand Up @@ -102,6 +142,58 @@ def test_info(self):
self.assertIn('Installed plugins', result.output)
self.assertIn('dummy-plugin', result.output)
self.assertIn('other-plugin', result.output)
self.assertIn('Config', result.output)
self.assertIn('Config Source: test config dict', result.output)

def test_info_level_0(self):
result = self.runner.invoke(info, '--config-level 0')
self.assertEqual(result.exit_code, 0)
# May not always start with "System versions" if cache updating message
# is printed.
self.assertIn('System versions', result.output)
self.assertIn('Installed plugins', result.output)
self.assertIn('dummy-plugin', result.output)
self.assertIn('other-plugin', result.output)
self.assertNotIn('Config', result.output)
self.assertNotIn('Config Source: test config dict', result.output)

def test_info_level_1(self):
result = self.runner.invoke(info, '--config-level 1')
self.assertEqual(result.exit_code, 0)
# May not always start with "System versions" if cache updating message
# is printed.
self.assertIn('System versions', result.output)
self.assertIn('Installed plugins', result.output)
self.assertIn('dummy-plugin', result.output)
self.assertIn('other-plugin', result.output)
self.assertIn('Config', result.output)
self.assertIn('Config Source: test config dict', result.output)

def test_info_level_2(self):
result = self.runner.invoke(info, '--config-level 2')
self.assertEqual(result.exit_code, 0)
# May not always start with "System versions" if cache updating message
# is printed.
self.assertIn('System versions', result.output)
self.assertIn('Installed plugins', result.output)
self.assertIn('dummy-plugin', result.output)
self.assertIn('other-plugin', result.output)
self.assertIn('Config', result.output)
self.assertIn('Config Source: test config dict', result.output)
self.assertIn(CONFIG_LEVEL_2, result.output)

def test_info_level_3(self):
result = self.runner.invoke(info, '--config-level 3')
self.assertEqual(result.exit_code, 0)
# May not always start with "System versions" if cache updating message
# is printed.
self.assertIn('System versions', result.output)
self.assertIn('Installed plugins', result.output)
self.assertIn('dummy-plugin', result.output)
self.assertIn('other-plugin', result.output)
self.assertIn('Config', result.output)
self.assertIn('Config Source: test config dict', result.output)
self.assertIn(CONFIG_LEVEL_3, result.output)

def test_list_commands(self):
# top level commands, including a plugin, are present
Expand Down
Loading