Created
November 14, 2023 02:52
-
-
Save snOm3ad/4b7a4d74fd88a92f56a2f45baa4b6886 to your computer and use it in GitHub Desktop.
Python utility orchestrator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import subprocess as sp | |
import os | |
import argparse | |
import sys | |
def clap(args, utils): | |
parser = argparse.ArgumentParser(prog='PyRun', description='Script orchestration utility.') | |
parser.add_argument('util', choices=utils, help='Script to be ran') | |
group = parser.add_mutually_exclusive_group() | |
group.add_argument('-s', '--silent', action='store_true', help='Suppress output from script, ignored if script failed (use -fs instead).') | |
group.add_argument('-fs', '--force-silent', action='store_true', help='Do not show output from script regardless of exit code.') | |
group.add_argument('--header', action='store_true', help='Include header specifying stream type.') | |
return parser.parse_known_args(args) | |
def walk_root_dir(root): | |
path = os.path | |
if not path.exists(root): | |
raise ValueError("NO") | |
utilities = [] | |
def recurse(dir): | |
entries = os.listdir(dir) | |
for entry in entries: | |
# append current dir | |
entry = dir + entry | |
if path.isfile(entry): | |
filename = path.basename(entry) | |
if path.splitext(filename)[1] == ".py": | |
utilities.append(entry) | |
elif path.isdir(entry): | |
recurse(entry + '/') | |
recurse(root) | |
return utilities | |
def main(): | |
if len(sys.argv) < 2: | |
raise ValueError("NO") | |
root_dir = os.getenv("PYSCRIPT_DIR") | |
ROOT_DIR = root_dir if root_dir[-1] == '/' else root_dir + '/' | |
utils_with_paths = walk_root_dir(ROOT_DIR) | |
utilities = { os.path.basename(util[:-3]): util for util in utils_with_paths } | |
utilities["list"] = "" | |
command, args = clap(sys.argv[1:], utilities.keys()) | |
if command.util == "list": | |
for util in utilities.keys(): | |
if util != "list": | |
print(util) | |
else: | |
filename = utilities[command.util] | |
with open(filename) as file: | |
lines = file.readlines() | |
# 012 | |
proc = lines[0][2:].rstrip() # e.g. #!/usr/bin/python3 | |
output = sp.run([proc, filename] + args, cwd=os.getcwd(), capture_output=True) | |
errors = output.stderr.decode('UTF-8').rstrip() | |
messages = output.stdout.decode('UTF-8').rstrip() | |
if output.returncode != 0 and not command.force_silent: | |
print(f'[ERROR]: {command.util} was not successfully executed.\nScript failed with message(s): "{errors}"', file=sys.stderr) | |
elif not command.silent and not command.force_silent: | |
# output management hell | |
title = "{p} {cmd}::{{sty}} {p}\n".format(p='=' * 10, cmd=command.util) | |
if len(messages) > 0: | |
outtitle = title.format(sty='stdout') | |
print(f"{outtitle if command.header else ''}{messages}") | |
if len(errors) > 0: | |
errtitle = title.format(sty='stderr') | |
print(f"{errtitle if command.header else ''}{errors}") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Do you keep multiple versions of python installed in your computer? Do you keep separate virtual environments for each script containing vastly different set of dependencies?
Do you spread your python scripts across multiple directories?
Do you dislike the idea of having to pollute your PATH (and by extension shell config file(s)) with even more directories? Does the idea of having to maintain symbolic links makes you sick?
Then boy is this the script for you. Just pass in your whatever directory where there is a python script (via the
PYSCRIPT_DIR
environment variable) and letpyrun
handle the rest. Note, however, that you must ensure that your scripts start with a shebang comment (i.e.#!/bin/python3
).CAVEAT: it currently only handles commands that are not interactive!