-
Charlotte Hausman authoredCharlotte Hausman authored
null.py 5.75 KiB
#
# Copyright (C) 2021 Associated Universities, Inc. Washington DC, USA.
#
# This file is part of NRAO Workspaces.
#
# Workspaces is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Workspaces is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Workspaces. If not, see <https://www.gnu.org/licenses/>.
import argparse
import importlib.metadata
import logging
import os
import random
import sys
import time
from . import __version__ as version
_DESCRIPTION = """Workspaces null executable, a status capture test of the Workspaces system. Version {}"""
ERRORS = {
1: "ERROR: An error has been purposefully induced.",
2: "ERROR: Unable to breach the mainframe.",
3: "ERROR: Your standard run-of-the-mill error.",
4: "ERROR: Very special and specific heisenbug-caused error that will take several days and several programmers to debug.",
5: "ERROR: [insert hilarious error joke here]",
}
logger = logging.getLogger("null")
logger.setLevel(logging.INFO)
handler = logging.StreamHandler(stream=sys.stdout)
def change_to_error_handler():
logger.removeHandler(handler)
err_handler = logging.StreamHandler(stream=sys.stderr)
logger.addHandler(err_handler)
def print_error():
"""
Logs an error message to stderr.
"""
change_to_error_handler()
logger.error("ERROR: This is an error.")
def print_greeting():
"""
Prints a friendly greeting to stdout
"""
logger.info("Hello, world!")
logger.debug("And goodbye, world...")
def exit_with_failure():
"""
Exits with status code 1
"""
change_to_error_handler()
logger.error(ERRORS[1])
sys.exit(1)
def exit_randomly():
"""
Exits with a random status code between -50 and 50
"""
change_to_error_handler()
status_code = random.choice([*ERRORS.keys()])
logger.error("Exiting with status code {}: {}".format(status_code, ERRORS[status_code]))
sys.exit(status_code)
def take_nap():
"""
Sleeps for 5 seconds
"""
logger.debug("Going to sleep...")
time.sleep(5)
logger.debug("Waking up.")
def dump_core():
"""
Makes a call to os.abort() which dumps the core
"""
logger.debug("Aborting and dumping core...", stack_info=True)
os.abort()
class Null:
"""
Null executable that executes null functionality based on arguments given
"""
def __init__(self, args: argparse.Namespace, verbose: bool):
self.args = args
if verbose:
logger.setLevel(logging.DEBUG)
self.args_to_funcs = {
"print_error": print_error,
"greeting": print_greeting,
"exit_fail": exit_with_failure,
"exit_random": exit_randomly,
"nap": take_nap,
"dump": dump_core,
}
def execute(self):
"""
Executes command specified by CL arguments.
:return:
"""
for arg, val in vars(self.args).items():
if val and arg in self.args_to_funcs:
self.args_to_funcs[arg]()
def make_arg_parser() -> argparse.ArgumentParser:
"""
Creates an argparse arguments parser with appropriate options
:return: Said argument parser
"""
parser = argparse.ArgumentParser(
description=_DESCRIPTION.format(version),
formatter_class=argparse.RawTextHelpFormatter,
)
parser.add_argument("--version", action="version", version=importlib.metadata.version("ssa-null"))
options = parser.add_argument_group("options", "settings for altering program behavior")
options.add_argument(
"-v",
"--verbose",
action="store_true",
required=False,
dest="verbose",
default=False,
help="allow the program the gift of speech",
)
functions = parser.add_mutually_exclusive_group(required=False)
functions.add_argument(
"-pe",
"--print-error",
action="store_true",
required=False,
dest="print_error",
default=False,
help="print out aggressive message to stderr",
)
functions.add_argument(
"-g",
"--greeting",
action="store_true",
required=False,
dest="greeting",
default=False,
help="print out a friendly greeting to stdout",
)
functions.add_argument(
"-ef",
"--exit-fail",
action="store_true",
required=False,
dest="exit_fail",
default=False,
help="print error message and exit with status code -1",
)
functions.add_argument(
"-er",
"--exit-random",
action="store_true",
required=False,
dest="exit_random",
default=False,
help="print error message and exit with random status code within [-50, 50]",
)
functions.add_argument(
"-n",
"--nap",
action="store_true",
required=False,
dest="nap",
default=False,
help="take a short nap",
)
functions.add_argument(
"-d",
"--dump",
action="store_true",
required=False,
dest="dump",
default=False,
help="abort program and dump core",
)
return parser
def main():
arg_parser = make_arg_parser()
args = arg_parser.parse_args()
logger.addHandler(handler)
executable = Null(args, args.verbose)
executable.execute()
if __name__ == "__main__":
main()