Source code for mdacli.cli

#!/usr/bin/env python3
# -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*-
#
# Copyright (c) 2021 Authors and contributors
#
# Released under the GNU Public Licence, v2 or any higher version
# SPDX-License-Identifier: GPL-2.0-or-later

"""The toplevel command line interface."""
import logging
import sys
import traceback
import warnings

from .colors import Emphasise
from .libcli import (
    find_AnalysisBase_members,
    init_base_argparse,
    run_analsis,
    setup_clients,
    split_argparse_into_groups,
    )
from .logger import setup_logging
from .utils import _exit_if_a_is_b


logger = logging.getLogger(__name__)


[docs]def cli(name, module_list, version="", description="", skip_modules=None, ignore_warnings=False): """Create the command-line interface. This function creates a command line interface with a given `name` based on a module list. Parameters ---------- name : str name of the interface module_list : list list of module from which the cli is build up. description : str description of the cli skip_modules : list list of strings containing modules that should be ommited ignore_warnings : bool ignore warnings when importing modules Examples -------- This example code creates the command line interface of MDAnalysis:: from MDAnalysis.analysis import __all__ import mdacli skip_mods = ['AnalysisFromFunction', 'HydrogenBondAnalysis', 'WaterBridgeAnalysis', 'Contacts', 'Dihedral', 'PersistenceLength', 'InterRDF_s'] mdacli.cli(name="MDAnalysis", module_list=__all__, version=mdacli.__version__, description=__doc__, skip_modules=skip_mods, ignore_warnings=True) """ modules = find_AnalysisBase_members(module_list, ignore_warnings=ignore_warnings) modules = [mod for mod in modules if mod.__name__ not in skip_modules] _exit_if_a_is_b(modules, None, "No analysis modules founds.") ap = init_base_argparse(name=name, version=version, description=description) if len(sys.argv) < 2: ap.error("A subcommand is required.") # There is to much useless code execution done here: # 1. We do not have to setup all possible clients all the time. # i.e. for `mda RMSD` only the RMSD client should be build. # 2. for something like `mdacli -h` We do not have to build every # sub parser in complete detail. setup_clients(ap, title=f"{name} Analysis Modules", members=modules) # Be case insensitive for the subcommand sys.argv[1] = sys.argv[1].lower() args = ap.parse_args() if args.debug: args.verbose = True else: # Ignore all warnings if not in debug mode warnings.filterwarnings("ignore") with setup_logging(logger, logfile=args.logfile, debug=args.debug): # Execute the main client interface. try: analysis_callable = args.analysis_callable # Get the correct ArgumentParser instance from all subparsers # `[0]` selects the first subparser where our analysises live in. _key = analysis_callable.__name__.lower() ap_sup = ap._subparsers._group_actions[0].choices[_key] arg_grouped_dict = split_argparse_into_groups(ap_sup, args) # Some parameters may not exist arg_grouped_dict.setdefault("Optional Parameters", {}) arg_grouped_dict.setdefault("Reference Universe Parameters", None) run_analsis(analysis_callable, arg_grouped_dict["Mandatory Parameters"], arg_grouped_dict["Optional Parameters"], arg_grouped_dict["Reference Universe Parameters"], arg_grouped_dict["Analysis Run Parameters"], arg_grouped_dict["Output Parameters"]) except Exception as e: if args.debug: traceback.print_exc() else: sys.exit(Emphasise.error(f"Error: {e}"))