Add support for running in non-interactive mode

- Exits with non-zero exit status on errors.
- Does not hang on prompts.
- Just prints text without fancy terminal stuff.
This commit is contained in:
Jakub Jirutka 2023-11-21 21:36:57 +01:00
parent a93490cf99
commit 1e82ba0813
2 changed files with 76 additions and 47 deletions

View File

@ -9,8 +9,9 @@ else:
class Utils:
def __init__(self, name = "Python Script"):
def __init__(self, name = "Python Script", interactive = True):
self.name = name
self.interactive = interactive
# Init our colors before we need to print anything
cwd = os.getcwd()
os.chdir(os.path.dirname(os.path.realpath(__file__)))
@ -138,6 +139,8 @@ class Utils:
# returning the result
timeout = kwargs.get("timeout", 0)
default = kwargs.get("default", None)
if not self.interactive:
return default
# If we don't have a timeout - then skip the timed sections
if timeout <= 0:
if sys.version_info >= (3, 0):
@ -170,11 +173,13 @@ class Utils:
return default
def cls(self):
os.system('cls' if os.name=='nt' else 'clear')
if not self.interactive:
return
os.system('cls' if os.name=='nt' else 'clear')
def cprint(self, message, **kwargs):
strip_colors = kwargs.get("strip_colors", False)
if os.name == "nt":
if os.name == "nt" or not self.interactive:
strip_colors = True
reset = u"\u001b[0m"
# Requires sys import
@ -216,6 +221,9 @@ class Utils:
# Header drawing method
def head(self, text = None, width = 55):
if not self.interactive:
print(text)
return
if text == None:
text = self.name
self.cls()

View File

@ -2,10 +2,17 @@
from Scripts import downloader,utils,run,plist
import os, shutil, time, sys, argparse, re, json
class ProgramError(Exception):
def __init__(self, message, title = "Error"):
super().__init__(message)
self.title = title
class gibMacOS:
def __init__(self):
def __init__(self, interactive = True):
self.interactive = interactive
self.d = downloader.Downloader()
self.u = utils.Utils("gibMacOS")
self.u = utils.Utils("gibMacOS", interactive=interactive)
self.r = run.Run()
self.min_w = 80
self.min_h = 24
@ -73,6 +80,8 @@ class gibMacOS:
)
def resize(self, width=0, height=0):
if not self.interactive:
return
width = width if width > self.min_w else self.min_w
height = height if height > self.min_h else self.min_h
self.u.resize(width, height)
@ -84,22 +93,18 @@ class gibMacOS:
try:
json.dump(self.settings,open(self.settings_path,"w"),indent=2)
except Exception as e:
self.u.head("Error Saving Settings")
print("")
print("Failed to save settings to:\n\n{}\n\nWith error:\n\n - {}\n".format(self.settings_path,repr(e)))
self.u.grab("Press [enter] to continue...")
raise ProgramError(
"Failed to save settings to:\n\n{}\n\nWith error:\n\n - {}\n".format(self.settings_path,repr(e)),
title="Error Saving Settings")
def set_prods(self):
self.resize()
if not self.get_catalog_data(self.save_local):
self.u.head("Catalog Data Error")
print("")
print("The currently selected catalog ({}) was not reachable".format(self.current_catalog))
message += "The currently selected catalog ({}) was not reachable\n".format(self.current_catalog)
if self.save_local:
print("and I was unable to locate a valid {} file in the\n{} directory.".format(self.plist, self.scripts))
print("Please ensure you have a working internet connection.")
print("")
self.u.grab("Press [enter] to exit...")
message += "and I was unable to locate a valid {} file in the\n{} directory.\n".format(self.plist, self.scripts)
message += "Please ensure you have a working internet connection."
raise ProgramError(message, title="Catalog Data Error")
self.u.head("Parsing Data")
print("")
print("Scanning products after catalog download...\n")
@ -297,12 +302,7 @@ class gibMacOS:
# add it to the list
dl_list.append(x["URL"])
if not len(dl_list):
self.u.head("Error")
print("")
print("There were no files to download")
print("")
self.u.grab("Press [enter] to return...")
return
raise ProgramError("There were no files to download")
c = 0
done = []
if self.print_urls:
@ -310,8 +310,9 @@ class gibMacOS:
print("")
print("{}:\n".format(name))
print("\n".join([" - {} \n --> {}".format(os.path.basename(x), x) for x in dl_list]))
print("")
self.u.grab("Press [enter] to return...")
if self.interactive:
print("")
self.u.grab("Press [enter] to return...")
return
# Only check the dirs if we need to
cwd = os.getcwd()
@ -322,6 +323,8 @@ class gibMacOS:
print("")
print("It looks like you've already downloaded {}".format(name))
print("")
if not self.interactive:
return
menu = self.u.grab("Redownload? (y/n): ")
if not len(menu):
continue
@ -371,7 +374,10 @@ class gibMacOS:
print("Files saved to:")
print(" {}".format(os.path.join(os.getcwd(), self.saves, self.current_catalog, name)))
print("")
self.u.grab("Press [enter] to return...")
if self.interactive:
self.u.grab("Press [enter] to return...")
elif len(failed):
raise ProgramError("{} files failed to download".format(len(failed)))
def show_catalog_url(self):
self.resize()
@ -381,9 +387,9 @@ class gibMacOS:
print("Max macOS Version: {}".format(self.num_to_macos(self.current_macos,for_url=False)))
print("")
print("{}".format(self.build_url()))
print("")
menu = self.u.grab("Press [enter] to return...")
return
if self.interactive:
print("")
self.u.grab("Press [enter] to return...")
def pick_catalog(self):
self.resize()
@ -540,8 +546,7 @@ class gibMacOS:
if device_id:
prod = next(p for p in prods if device_id.lower() in p["device_ids"])
if not prod:
print("No version found for Device ID '{}'".format(device_id))
return
raise ProgramError("No version found for Device ID '{}'".format(device_id))
else:
prod = prods[0]
self.download_prod(prod, dmg)
@ -553,7 +558,7 @@ class gibMacOS:
if p["product"] == prod:
self.download_prod(p, dmg)
return
print("{} not found".format(prod))
raise ProgramError("{} not found".format(prod))
def get_for_version(self, vers, build = None, device_id = None, dmg = False):
self.u.head("Downloading for {} {}".format(vers, build or ""))
@ -593,7 +598,7 @@ class gibMacOS:
if (n in pt) and not len(name_match):
self.download_prod(p, dmg)
return
print("'{}' '{}' not found".format(vers, build))
raise ProgramError("'{}' '{}' not found".format(vers, build or ""))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
@ -609,9 +614,10 @@ if __name__ == '__main__':
parser.add_argument("-m", "--maxos", help="sets the max macOS version to consider when building the url - eg 10.14")
parser.add_argument("-D", "--device-id", help="use with --version or --latest to search for versions supporting the specified Device ID - eg VMM-x86_64 for any x86_64")
parser.add_argument("-i", "--print-urls", help="only prints the download URLs, does not actually download them", action="store_true")
parser.add_argument("--no-interactive", help="run in non-interactive mode", action="store_true")
args = parser.parse_args()
g = gibMacOS()
g = gibMacOS(interactive=not args.no_interactive)
if args.recovery:
args.dmg = False
g.find_recovery = args.recovery
@ -635,18 +641,33 @@ if __name__ == '__main__':
# Set the catalog
g.set_catalog(args.catalog)
# Done setting up pre-requisites
g.set_prods()
try:
# Done setting up pre-requisites
g.set_prods()
if args.latest:
g.get_latest(device_id=args.device_id, dmg=args.dmg)
exit()
if args.product != None:
g.get_for_product(args.product, args.dmg)
exit()
if args.version != None:
g.get_for_version(args.version, args.build, device_id=args.device_id, dmg=args.dmg)
exit()
while True:
g.main(args.dmg)
if args.latest:
g.get_latest(device_id=args.device_id, dmg=args.dmg)
elif args.product != None:
g.get_for_product(args.product, args.dmg)
elif args.version != None:
g.get_for_version(args.version, args.build, device_id=args.device_id, dmg=args.dmg)
elif g.interactive:
while True:
try:
g.main(args.dmg)
except ProgramError as e:
g.u.head(e.title)
print("")
print(str(e))
print("")
g.u.grab("Press [enter] to return...")
else:
raise ProgramError("No command specified")
except ProgramError as e:
print(str(e))
if g.interactive:
print("")
g.u.grab("Press [enter] to exit...")
else:
exit(1)
exit(0)