Source code for orion.core.cli.base

"""
Base class and function utilities for cli
=========================================
"""
import argparse
import logging
import os
import sys
import textwrap

import orion
import orion.core
from orion.core.io.database import DatabaseError
from orion.core.utils.exceptions import (
    BranchingEvent,
    InexecutableUserScript,
    MissingResultFile,
    NoConfigurationError,
    NoNameError,
)

logger = logging.getLogger(__name__)

CLI_DOC_HEADER = "Oríon CLI for asynchronous distributed optimization"


[docs]class OrionArgsParser: """Parser object handling the upper-level parsing of Oríon's arguments.""" def __init__(self, description=CLI_DOC_HEADER): """Create the pre-command arguments""" self.description = description self.parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent(description), ) self.parser.add_argument( "-V", "--version", action="version", version="orion " + orion.core.__version__, ) self.parser.add_argument( "-v", "--verbose", action="count", default=0, help="logging levels of information about the process (-v: INFO. -vv: DEBUG)", ) self.parser.add_argument( "--logdir", type=str, default=None, help="Path to a directory to store logs", ) self.parser.add_argument( "-d", "--debug", action="store_true", help="Use debugging mode with EphemeralDB.", ) self.subparsers = self.parser.add_subparsers(dest="command")
[docs] def get_subparsers(self): """Return the subparser object for this parser.""" return self.subparsers
[docs] def parse(self, argv): """Call argparse and generate a dictionary of arguments' value""" args = vars(self.parser.parse_args(argv)) verbose = args.pop("verbose", 0) levels = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG} logdir = args.pop("logdir") logfile = None if logdir is not None: os.makedirs(logdir, exist_ok=True) pid = os.getpid() logfile = os.path.join(logdir, f"orion_{pid}.log") logging.basicConfig( format="%(asctime)-15s::%(levelname)s::%(name)s::%(message)s", level=levels.get(verbose, logging.DEBUG), filename=logfile, ) logger.debug("Orion version : %s", orion.core.__version__) if args["command"] is None: self.parser.parse_args(["--help"]) function = args.pop("func", None) empty_command = (argv[-1] if argv else sys.argv[-1]) == args["command"] if function is None or (empty_command and args.pop("help_empty", False)): self.parser.parse_args([args["command"], "--help"]) return args, function
[docs] def execute(self, argv): """Execute main function of the subparser""" try: args, function = self.parse(argv) returncode = function(args) except ( NoConfigurationError, NoNameError, DatabaseError, MissingResultFile, BranchingEvent, InexecutableUserScript, ) as e: print("Error:", e, file=sys.stderr) if args.get("verbose", 0) >= 2: raise e return 1 except KeyboardInterrupt: print("Orion is interrupted.") return 130 return 0 if returncode is None else returncode
[docs]def get_basic_args_group( parser, group_name="Oríon arguments", group_help="These arguments determine orion's behaviour", ): """Return the basic arguments for any command.""" basic_args_group = parser.add_argument_group(group_name, description=group_help) basic_args_group.add_argument( "-n", "--name", type=str, metavar="stringID", help="experiment's unique name; " "(default: None - specified either here or in a config)", ) basic_args_group.add_argument( "-u", "--user", type=str, help="user associated to experiment's unique name; " "(default: $USER - can be overridden either here or in a config)", ) basic_args_group.add_argument( "-v", "--version", type=int, help="specific version of experiment to fetch; " "(default: None - latest experiment.)", ) basic_args_group.add_argument( "-c", "--config", type=argparse.FileType("r"), metavar="path-to-config", help="user provided " "orion configuration file", ) return basic_args_group
[docs]def get_user_args_group(parser): """ Return the user group arguments for any command. User group arguments are composed of the user script and the user args """ usergroup = parser.add_argument_group( "User script related arguments", description="These arguments determine user's script behaviour " "and they can serve as orion's parameter declaration.", ) usergroup.add_argument( "user_args", nargs=argparse.REMAINDER, metavar="...", help="Command line of user script. A configuration " "file intended to be used with 'userscript' must be given as a path " "in the **first positional** argument OR using `--config=<path>` " "keyword argument.", ) return usergroup