diff --git a/src/haddock/clis/cli_cfg.py b/src/haddock/clis/cli_cfg.py index 5e1e438ca..989ed7c1a 100644 --- a/src/haddock/clis/cli_cfg.py +++ b/src/haddock/clis/cli_cfg.py @@ -6,16 +6,19 @@ Usage:: - haddock3-cfg -m MODULE + haddock3-cfg # prints only the general parametes + haddock3-cfg -g # same as above + haddock3-cfg -m MODULE # prints only the module parameters haddock3-cfg -m MODULE -l LEVEL + haddock3-cfg -m topoaa -l all + haddock3-cfg -m rigidbody -l all -g # prints the module and the globals """ import argparse import importlib +import os import sys from haddock import config_expert_levels -from haddock.gear.yaml2cfg import yaml2cfg_text -from haddock.libs.libio import read_from_yaml from haddock.modules import modules_category @@ -29,8 +32,8 @@ "-m", dest="module", help="The module for which you want to retrieve the default configuration.", - required=True, choices=sorted(modules_category.keys()), + default=None, ) ap.add_argument( @@ -42,6 +45,14 @@ choices=config_expert_levels + ("all",), ) +ap.add_argument( + '-g', + '--globals', + dest='global_params', + help="Add also the optional module's general parameters.", + action="store_true", + ) + def _ap(): return ap @@ -57,6 +68,20 @@ def load_args(ap): def cli(ap, main): """Command-line interface entry point.""" cmd = load_args(ap) + + # I didn't want to to have the `--globals` param as a negative parameter + # ('store_false'). However, `module` and `globals` can't both be false. + # In order for the commands below performing the same: + # + # haddock3-cfg + # haddock3-cfg -g + # + # we need this quick if statement. Which basically adjust the argparse to + # the default values in the main function. + # @joaomcteixeira + if cmd.global_params is False and cmd.module is None: + cmd.global_params = True + main(**vars(cmd)) @@ -65,22 +90,69 @@ def maincli(): cli(ap, main) -def main(module, explevel): - """Extract the default configuration file for a given module.""" - module_name = ".".join(( - 'haddock', - 'modules', - modules_category[module], - module, - )) - - module_lib = importlib.import_module(module_name) - cfg = module_lib.DEFAULT_CONFIG - - ycfg = read_from_yaml(cfg) - - new_config = yaml2cfg_text(ycfg, module, explevel) - print(new_config, file=sys.stdout, flush=True) # noqa: T201 +def main(module=None, explevel="all", global_params=True): + """ + Extract the defaults in the form of a run configuration file. + + Parameters + ---------- + module : str or None + The module name to extract the defaults from. + If ``None`` given, we expect ``global_params`` to be ``True``, + otherwise nothing will be printed. + + explevel : str + Filter the parameters according to the expert level. Output all + parameters that belong to the referred level or below. Choices + are: all, easy, expert, and guru. + + global_params : bool + Whether to add the module's general global parameter. If + ``True`` and ``module`` is ``None``, outputs only the general + parameters. + """ + from haddock import modules_defaults_path + from haddock.gear.yaml2cfg import yaml2cfg_text + from haddock.libs.libio import read_from_yaml + + new_config = '' + + if global_params: + general_cfg = read_from_yaml(modules_defaults_path) + general_params_str = yaml2cfg_text( + general_cfg, + module=None, + explevel="all", + ) + comment = os.linesep.join(( + "# The parameters below are optional parameters. ", + "# They can either be used as global parameters or as part ", + "# of the module's parameters", + )) + + new_config = os.linesep.join(( + comment, + general_params_str, + )) + + if module: + + module_name = ".".join(( + 'haddock', + 'modules', + modules_category[module], + module, + )) + + module_lib = importlib.import_module(module_name) + cfg = module_lib.DEFAULT_CONFIG + + ycfg = read_from_yaml(cfg) + module_config = yaml2cfg_text(ycfg, module, explevel) + + new_config = os.linesep.join((new_config, module_config)) + + sys.stdout.write(new_config) return 0 diff --git a/src/haddock/gear/yaml2cfg.py b/src/haddock/gear/yaml2cfg.py index c545cc777..fb366b571 100644 --- a/src/haddock/gear/yaml2cfg.py +++ b/src/haddock/gear/yaml2cfg.py @@ -33,7 +33,8 @@ def yaml2cfg_text(ymlcfg, module, explevel): parameters will be considered. """ new_config = [] - new_config.append(f"[{module}]") + if module is not None: + new_config.append(f"[{module}]") new_config.append(_yaml2cfg_text(ymlcfg, module, explevel)) @@ -68,7 +69,10 @@ def _yaml2cfg_text(ycfg, module, explevel): if isinstance(param, Mapping) and "default" not in param: params.append("") # give extra space - curr_module = f"{module}.{param_name}" + if module is not None: + curr_module = f"{module}.{param_name}" + else: + curr_module = param_name params.append(f"[{curr_module}]") _ = _yaml2cfg_text(param, module=curr_module, explevel=explevel) params.append(_) diff --git a/tests/__init__.py b/tests/__init__.py index e0b6a6e47..86c1a50a3 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -11,6 +11,8 @@ emptycfg = Path(configs_data, 'empty.cfg') haddock3_yaml_cfg_examples = Path(configs_data, 'yml_example.yml') haddock3_yaml_converted = Path(configs_data, 'yaml2cfg_converted.cfg') +haddock3_yaml_converted_no_header = \ + Path(configs_data, 'yaml2cfg_converted_no_header.cfg') clean_steps_folder = Path(tests_path, 'clean_output_data') # defines which modules are already working diff --git a/tests/configs/yaml2cfg_converted_no_header.cfg b/tests/configs/yaml2cfg_converted_no_header.cfg new file mode 100644 index 000000000..c3d860a40 --- /dev/null +++ b/tests/configs/yaml2cfg_converted_no_header.cfg @@ -0,0 +1,32 @@ +autohis = True # $title Automatic HIS protonation state / $group molecule +delenph = True # $title Keep or remove non-polar hydrogen atoms / $group molecule +log_level = 'verbose' # $minchars 0 / $maxchars 100 / $title Log level verbosity for CNS / $group module +iniseed = 917 # $min 0 / $max 9999999999999999 / $precision 3 / $title Random seed / $group molecule +ligand_param_fname = '' # $title No title yet +ligand_top_fname = '' # $title No title yet +limit = True # $title No title yet +tolerance = 0 # $min -9999 / $max 9999 / $precision 3 / $title No title yet + +[mol1] +prot_segid = 'A' # $minchars 0 / $maxchars 100 / $title No title yet +fix_origin = False # $title No title yet +dna = False # $title No title yet +shape = False # $title No title yet +cg = False # $title No title yet +cyclicpept = False # $title No title yet +nhisd = 0 # $min -9999 / $max 9999 / $precision 3 / $title No title yet +hisd_1 = nan # $min -9999 / $max 9999 / $precision 3 / $title No title yet +nhise = 0 # $min -9999 / $max 9999 / $precision 3 / $title No title yet +hise_1 = nan # $min -9999 / $max 9999 / $precision 3 / $title No title yet + +[mol2] +prot_segid = 'B' # $minchars 0 / $maxchars 100 / $title No title yet +fix_origin = False # $title No title yet +dna = False # $title No title yet +shape = False # $title No title yet +cg = False # $title No title yet +cyclicpept = False # $title No title yet +nhisd = 0 # $min -9999 / $max 9999 / $precision 3 / $title No title yet +hisd_1 = nan # $min -9999 / $max 9999 / $precision 3 / $title No title yet +nhise = 0 # $min -9999 / $max 9999 / $precision 3 / $title No title yet +hise_1 = nan # $min -9999 / $max 9999 / $precision 3 / $title No title yet diff --git a/tests/test_cli_cfg.py b/tests/test_cli_cfg.py index 5c79e6f09..99cd8fdb7 100644 --- a/tests/test_cli_cfg.py +++ b/tests/test_cli_cfg.py @@ -12,10 +12,17 @@ def config_level(request): return request.param -@pytest.mark.parametrize( - "module", - list(modules_category.keys()), - ) -def test_export_cfgs(module, config_level): - """Test export all configs work.""" - cli_cfg.main(module, config_level) +@pytest.fixture(params=(True, False)) +def global_params(request): + """Haddock3 config levels.""" + return request.param + + +@pytest.fixture(params=list(modules_category.keys()) + [None]) +def module(request): + return request.param + + +def test_export_cfgs_add_global(module, config_level, global_params): + """Test export all configs work with `add_global` parameter.""" + cli_cfg.main(module, explevel=config_level, global_params=global_params) diff --git a/tests/test_yaml2cfg.py b/tests/test_gear_yaml2cfg.py similarity index 76% rename from tests/test_yaml2cfg.py rename to tests/test_gear_yaml2cfg.py index acccebf28..0535be4a2 100644 --- a/tests/test_yaml2cfg.py +++ b/tests/test_gear_yaml2cfg.py @@ -5,7 +5,11 @@ from haddock.gear.yaml2cfg import flat_yaml_cfg, yaml2cfg_text from haddock.libs.libio import read_from_yaml -from . import haddock3_yaml_cfg_examples, haddock3_yaml_converted +from . import ( + haddock3_yaml_cfg_examples, + haddock3_yaml_converted, + haddock3_yaml_converted_no_header, + ) complex_cfg = { @@ -76,3 +80,20 @@ def test_yaml2cfg_test(): assert filecmp.cmp(p, haddock3_yaml_converted, shallow=False) p.unlink() + + +def test_yaml2cfg_test_no_header(): + """Test yaml dict to cfg.""" + ycfg = read_from_yaml(haddock3_yaml_cfg_examples) + result = yaml2cfg_text(ycfg, None, "all") + assert isinstance(result, str) + + p = Path('dummy_test.cfg') + p.write_text(result) + + assert filecmp.cmp( + p, + haddock3_yaml_converted_no_header, + shallow=False, + ) + p.unlink()