Skip to content

Commit

Permalink
Merge pull request #407 from pepkit/cli-reorg
Browse files Browse the repository at this point in the history
refactor CLI code
  • Loading branch information
donaldcampbelljr committed Aug 16, 2023
2 parents 699e489 + 046c4a6 commit df15cbd
Show file tree
Hide file tree
Showing 10 changed files with 965 additions and 931 deletions.
497 changes: 0 additions & 497 deletions looper/__init__.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions looper/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import sys

from .looper import main
from .divvy import main as divvy_main
from .cli_looper import main
from .cli_divvy import main as divvy_main

if __name__ == "__main__":
try:
Expand Down
182 changes: 182 additions & 0 deletions looper/cli_divvy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import logmuse
import os
import sys
import yaml
from yaml import SafeLoader
from ubiquerg import is_writable, VersionInHelpParser
from .const import (
DEFAULT_COMPUTE_RESOURCES_NAME,
DEFAULT_CONFIG_FILEPATH,
)
from .divvy import select_divvy_config, ComputingConfiguration, divvy_init


def build_argparser():
"""
Builds argument parser.
:return argparse.ArgumentParser
"""

banner = (
"%(prog)s - write compute job scripts that can be submitted to "
"any computing resource"
)
additional_description = "\nhttps://divvy.databio.org"

parser = VersionInHelpParser(
prog="divvy",
description=banner,
epilog=additional_description,
# version=__version__,
)

subparsers = parser.add_subparsers(dest="command")

def add_subparser(cmd, description):
return subparsers.add_parser(cmd, description=description, help=description)

subparser_messages = {
"init": "Initialize a new divvy config file",
"list": "List available compute packages",
"write": "Write a job script",
"submit": "Write and then submit a job script",
"inspect": "Inspect compute package",
}

sps = {}
for cmd, desc in subparser_messages.items():
sps[cmd] = add_subparser(cmd, desc)
# sps[cmd].add_argument(
# "config", nargs="?", default=None,
# help="Divvy configuration file.")

for sp in [sps["list"], sps["write"], sps["submit"], sps["inspect"]]:
sp.add_argument(
"config", nargs="?", default=None, help="Divvy configuration file."
)

sps["init"].add_argument("config", default=None, help="Divvy configuration file.")

for sp in [sps["inspect"]]:
sp.add_argument(
"-p",
"--package",
default=DEFAULT_COMPUTE_RESOURCES_NAME,
help="Select from available compute packages",
)

for sp in [sps["write"], sps["submit"]]:
sp.add_argument(
"-s",
"--settings",
help="YAML file with job settings to populate the template",
)

sp.add_argument(
"-p",
"--package",
default=DEFAULT_COMPUTE_RESOURCES_NAME,
help="Select from available compute packages",
)

sp.add_argument(
"-c",
"--compute",
nargs="+",
default=None,
help="Extra key=value variable pairs",
)

# sp.add_argument(
# "-t", "--template",
# help="Provide a template file (not yet implemented).")

sp.add_argument(
"-o", "--outfile", required=False, default=None, help="Output filepath"
)

return parser


def main():
"""Primary workflow for divvy CLI"""

parser = logmuse.add_logging_options(build_argparser())
# args, remaining_args = parser.parse_known_args()
args = parser.parse_args()

logger_kwargs = {"level": args.verbosity, "devmode": args.logdev}
logmuse.init_logger("yacman", **logger_kwargs)
global _LOGGER
_LOGGER = logmuse.logger_via_cli(args)

if not args.command:
parser.print_help()
_LOGGER.error("No command given")
sys.exit(1)

if args.command == "init":
divcfg = args.config
_LOGGER.debug("Initializing divvy configuration")
is_writable(os.path.dirname(divcfg), check_exist=False)
divvy_init(divcfg, DEFAULT_CONFIG_FILEPATH)
sys.exit(0)

_LOGGER.debug("Divvy config: {}".format(args.config))
divcfg = select_divvy_config(args.config)
_LOGGER.info("Using divvy config: {}".format(divcfg))
dcc = ComputingConfiguration(filepath=divcfg)

if args.command == "list":
# Output header via logger and content via print so the user can
# redirect the list from stdout if desired without the header as clutter
_LOGGER.info("Available compute packages:\n")
print("{}".format("\n".join(dcc.list_compute_packages())))
sys.exit(1)

if args.command == "inspect":
# Output contents of selected compute package
_LOGGER.info("Your compute package template for: " + args.package + "\n")
found = False
for pkg_name, pkg in dcc.compute_packages.items():
if pkg_name == args.package:
found = True
with open(pkg.submission_template, "r") as f:
print(f.read())
_LOGGER.info("Submission command is: " + pkg.submission_command + "\n")
if pkg_name == "docker":
print("Docker args are: " + pkg.docker_args)

if not found:
_LOGGER.info("Package not found. Use 'divvy list' to see list of packages.")
sys.exit(1)

# Any non-divvy arguments will be passed along as key-value pairs
# that can be used to populate the template.
# keys = [str.replace(x, "--", "") for x in remaining_args[::2]]
# cli_vars = dict(zip(keys, remaining_args[1::2]))
if args.compute:
cli_vars = {y[0]: y[1] for y in [x.split("=") for x in args.compute]}
else:
cli_vars = {}

if args.command == "write" or args.command == "submit":
try:
dcc.activate_package(args.package)
except AttributeError:
parser.print_help(sys.stderr)
sys.exit(1)

if args.settings:
_LOGGER.info("Loading settings file: %s", args.settings)
with open(args.settings, "r") as f:
vars_groups = [cli_vars, yaml.load(f, SafeLoader)]
else:
vars_groups = [cli_vars]

_LOGGER.debug(vars_groups)
if args.command == "write":
dcc.write_script(args.outfile, vars_groups)
elif args.command == "submit":
dcc.submit(args.outfile, vars_groups)

0 comments on commit df15cbd

Please sign in to comment.