1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-22 18:26:39 +00:00

host: add verbose output toggle

Provided as a checkbox in the GUI and a command line argument in the CLI.

Exception information is now also printed to the GUI textbox if the verbose output checkbox is enabled.
This commit is contained in:
Pablo Curiel 2023-06-03 17:27:24 +02:00
parent 961459fe01
commit 158d7c1e92

View file

@ -32,6 +32,8 @@
# Under MacOS, use `brew install libusb` to install libusb via Homebrew. # Under MacOS, use `brew install libusb` to install libusb via Homebrew.
# Under Linux, you should be good to go from the start. If not, just use the package manager from your distro to install libusb. # Under Linux, you should be good to go from the start. If not, just use the package manager from your distro to install libusb.
from __future__ import print_function
import sys import sys
import os import os
import platform import platform
@ -298,6 +300,7 @@ TASKBAR_LIB = b'TVNGVAIAAQAAAAAACQQAAAAAAABBAAAAAQAAAAAAAAAOAAAA/////wAAAAAAAAAA
# Global variables used throughout the code. # Global variables used throughout the code.
g_cliMode: bool = False g_cliMode: bool = False
g_outputDir: str = '' g_outputDir: str = ''
g_logLevelIntVar: Optional[tk.IntVar] = None
g_osType: str = '' g_osType: str = ''
g_osVersion: str = '' g_osVersion: str = ''
@ -313,6 +316,7 @@ g_tkChooseDirButton: Optional[tk.Button] = None
g_tkServerButton: Optional[tk.Button] = None g_tkServerButton: Optional[tk.Button] = None
g_tkTipMessage: Any = None g_tkTipMessage: Any = None
g_tkScrolledTextLog: Optional[scrolledtext.ScrolledText] = None g_tkScrolledTextLog: Optional[scrolledtext.ScrolledText] = None
g_tkVerboseCheckbox: Optional[tk.Checkbutton] = None
g_logger: Optional[logging.Logger] = None g_logger: Optional[logging.Logger] = None
@ -363,9 +367,11 @@ class LogConsole:
# Create a logging handler using a queue. # Create a logging handler using a queue.
self.log_queue: queue.Queue = queue.Queue() self.log_queue: queue.Queue = queue.Queue()
self.queue_handler = LogQueueHandler(self.log_queue) self.queue_handler = LogQueueHandler(self.log_queue)
#formatter = logging.Formatter('[%(asctime)s] -> %(message)s') #formatter = logging.Formatter('[%(asctime)s] -> %(message)s')
formatter = logging.Formatter('%(message)s') formatter = logging.Formatter('%(message)s')
self.queue_handler.setFormatter(formatter) self.queue_handler.setFormatter(formatter)
g_logger.addHandler(self.queue_handler) g_logger.addHandler(self.queue_handler)
# Start polling messages from the queue. # Start polling messages from the queue.
@ -536,6 +542,14 @@ class ProgressBarWindow:
g_progressBarWindow: Optional[ProgressBarWindow] = None g_progressBarWindow: Optional[ProgressBarWindow] = None
def eprint(*args, **kwargs) -> None:
print(*args, file=sys.stderr, **kwargs)
def utilsLogException(exception_str: str) -> None:
eprint(exception_str)
if g_logger is not None:
g_logger.debug(exception_str)
def utilsGetPath(path_arg: str, fallback_path: str, is_file: bool, create: bool = False) -> str: def utilsGetPath(path_arg: str, fallback_path: str, is_file: bool, create: bool = False) -> str:
path = os.path.abspath(os.path.expanduser(os.path.expandvars(path_arg if path_arg else fallback_path))) path = os.path.abspath(os.path.expanduser(os.path.expandvars(path_arg if path_arg else fallback_path)))
@ -656,7 +670,7 @@ def usbRead(size: int, timeout: int = -1) -> bytes:
rd = bytes(g_usbEpIn.read(size, timeout)) rd = bytes(g_usbEpIn.read(size, timeout))
except usb.core.USBError: except usb.core.USBError:
if not g_cliMode: if not g_cliMode:
traceback.print_exc(file=sys.stderr) utilsLogException(traceback.format_exc())
g_logger.error('\nUSB timeout triggered or console disconnected.') g_logger.error('\nUSB timeout triggered or console disconnected.')
return rd return rd
@ -670,7 +684,7 @@ def usbWrite(data: bytes, timeout: int = -1) -> int:
wr = g_usbEpOut.write(data, timeout) wr = g_usbEpOut.write(data, timeout)
except usb.core.USBError: except usb.core.USBError:
if not g_cliMode: if not g_cliMode:
traceback.print_exc(file=sys.stderr) utilsLogException(traceback.format_exc())
g_logger.error('\nUSB timeout triggered or console disconnected.') g_logger.error('\nUSB timeout triggered or console disconnected.')
return wr return wr
@ -1070,7 +1084,7 @@ def uiStartServer() -> None:
try: try:
os.makedirs(g_outputDir, exist_ok=True) os.makedirs(g_outputDir, exist_ok=True)
except: except:
traceback.print_exc(file=sys.stderr) utilsLogException(traceback.format_exc())
messagebox.showerror('Error', 'Unable to create full output directory tree!', parent=g_tkRoot) messagebox.showerror('Error', 'Unable to create full output directory tree!', parent=g_tkRoot)
return return
@ -1086,6 +1100,7 @@ def uiToggleElements(flag: bool) -> None:
#assert g_tkChooseDirButton is not None #assert g_tkChooseDirButton is not None
#assert g_tkServerButton is not None #assert g_tkServerButton is not None
#assert g_tkCanvas is not None #assert g_tkCanvas is not None
#assert g_tkVerboseCheckbox is not None
if flag: if flag:
g_tkRoot.protocol('WM_DELETE_WINDOW', uiHandleExitProtocol) g_tkRoot.protocol('WM_DELETE_WINDOW', uiHandleExitProtocol)
@ -1093,6 +1108,8 @@ def uiToggleElements(flag: bool) -> None:
g_tkChooseDirButton.configure(state='normal') g_tkChooseDirButton.configure(state='normal')
g_tkServerButton.configure(text='Start server', command=uiStartServer, state='normal') g_tkServerButton.configure(text='Start server', command=uiStartServer, state='normal')
g_tkCanvas.itemconfigure(g_tkTipMessage, state='hidden', text='') g_tkCanvas.itemconfigure(g_tkTipMessage, state='hidden', text='')
g_tkVerboseCheckbox.configure(state='normal')
else: else:
#assert g_tkScrolledTextLog is not None #assert g_tkScrolledTextLog is not None
@ -1106,6 +1123,8 @@ def uiToggleElements(flag: bool) -> None:
g_tkScrolledTextLog.delete('1.0', tk.END) g_tkScrolledTextLog.delete('1.0', tk.END)
g_tkScrolledTextLog.configure(state='disabled') g_tkScrolledTextLog.configure(state='disabled')
g_tkVerboseCheckbox.configure(state='disabled')
def uiChooseDirectory() -> None: def uiChooseDirectory() -> None:
dir = filedialog.askdirectory(parent=g_tkRoot, title='Select an output directory', initialdir=INITIAL_DIR, mustexist=True) dir = filedialog.askdirectory(parent=g_tkRoot, title='Select an output directory', initialdir=INITIAL_DIR, mustexist=True)
if dir: if dir:
@ -1128,9 +1147,14 @@ def uiHandleExitProtocolStub() -> None:
def uiScaleMeasure(measure: int) -> int: def uiScaleMeasure(measure: int) -> int:
return round(float(measure) * SCALE) return round(float(measure) * SCALE)
def uiHandleVerboseCheckbox() -> None:
#assert g_logger is not None
#assert g_logLevelIntVar is not None
g_logger.setLevel(g_logLevelIntVar.get())
def uiInitialize() -> None: def uiInitialize() -> None:
global SCALE global SCALE, g_logLevelIntVar
global g_tkRoot, g_tkCanvas, g_tkDirText, g_tkChooseDirButton, g_tkServerButton, g_tkTipMessage, g_tkScrolledTextLog global g_tkRoot, g_tkCanvas, g_tkDirText, g_tkChooseDirButton, g_tkServerButton, g_tkTipMessage, g_tkScrolledTextLog, g_tkVerboseCheckbox
global g_stopEvent, g_tlb, g_taskbar, g_progressBarWindow global g_stopEvent, g_tlb, g_taskbar, g_progressBarWindow
# Setup thread event. # Setup thread event.
@ -1146,7 +1170,7 @@ def uiInitialize() -> None:
if not dpi_aware: if not dpi_aware:
dpi_aware = (ctypes.windll.shcore.SetProcessDpiAwareness(1) == 0) dpi_aware = (ctypes.windll.shcore.SetProcessDpiAwareness(1) == 0)
except: except:
traceback.print_exc(file=sys.stderr) utilsLogException(traceback.format_exc())
# Enable taskbar features under Windows (if possible). # Enable taskbar features under Windows (if possible).
del_tlb = False del_tlb = False
@ -1165,7 +1189,7 @@ def uiInitialize() -> None:
g_taskbar = cc.CreateObject('{56FDF344-FD6D-11D0-958A-006097C9A090}', interface=g_tlb.ITaskbarList3) g_taskbar = cc.CreateObject('{56FDF344-FD6D-11D0-958A-006097C9A090}', interface=g_tlb.ITaskbarList3)
g_taskbar.HrInit() g_taskbar.HrInit()
except: except:
traceback.print_exc(file=sys.stderr) utilsLogException(traceback.format_exc())
if del_tlb: if del_tlb:
os.remove(TASKBAR_LIB_PATH) os.remove(TASKBAR_LIB_PATH)
@ -1181,7 +1205,7 @@ def uiInitialize() -> None:
icon_image = tk.PhotoImage(data=base64.b64decode(APP_ICON)) icon_image = tk.PhotoImage(data=base64.b64decode(APP_ICON))
g_tkRoot.wm_iconphoto(True, icon_image) g_tkRoot.wm_iconphoto(True, icon_image)
except: except:
traceback.print_exc(file=sys.stderr) utilsLogException(traceback.format_exc())
# Get screen resolution. # Get screen resolution.
screen_width_px = g_tkRoot.winfo_screenwidth() screen_width_px = g_tkRoot.winfo_screenwidth()
@ -1243,6 +1267,10 @@ def uiInitialize() -> None:
g_tkCanvas.create_text(uiScaleMeasure(5), uiScaleMeasure(WINDOW_HEIGHT - 10), text=COPYRIGHT_TEXT, anchor=tk.W) g_tkCanvas.create_text(uiScaleMeasure(5), uiScaleMeasure(WINDOW_HEIGHT - 10), text=COPYRIGHT_TEXT, anchor=tk.W)
g_logLevelIntVar = tk.IntVar()
g_tkVerboseCheckbox = tk.Checkbutton(g_tkRoot, text='Verbose output', variable=g_logLevelIntVar, onvalue=logging.DEBUG, offvalue=logging.INFO, command=uiHandleVerboseCheckbox)
g_tkCanvas.create_window(uiScaleMeasure(WINDOW_WIDTH - 55), uiScaleMeasure(WINDOW_HEIGHT - 10), window=g_tkVerboseCheckbox, anchor=tk.CENTER)
# Initialize console logger. # Initialize console logger.
console = LogConsole(g_tkScrolledTextLog) console = LogConsole(g_tkScrolledTextLog)
@ -1281,8 +1309,9 @@ def main() -> int:
# Parse command line arguments. # Parse command line arguments.
parser = ArgumentParser(description=SCRIPT_TITLE + '. ' + COPYRIGHT_TEXT + '.') parser = ArgumentParser(description=SCRIPT_TITLE + '. ' + COPYRIGHT_TEXT + '.')
parser.add_argument('-c', '--cli', required=False, action='store_true', help='Start the script in CLI mode.') parser.add_argument('-c', '--cli', required=False, action='store_true', default=False, help='Start the script in CLI mode.')
parser.add_argument('-o', '--outdir', required=False, type=str, metavar='DIR', help='Path to output directory. Defaults to "' + DEFAULT_DIR + '".') parser.add_argument('-o', '--outdir', required=False, type=str, metavar='DIR', help='Path to output directory. Defaults to "' + DEFAULT_DIR + '".')
parser.add_argument('-v', '--verbose', required=False, action='store_true', default=False, help='Enable verbose output.')
args = parser.parse_args() args = parser.parse_args()
# Update global flags. # Update global flags.
@ -1305,10 +1334,10 @@ def main() -> int:
g_isWindows7 = (True if (win_ver_major > 6) else (win_ver_major == 6 and win_ver_minor > 0)) g_isWindows7 = (True if (win_ver_major > 6) else (win_ver_major == 6 and win_ver_minor > 0))
# Setup logging mechanism. # Setup logging mechanism.
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=(logging.DEBUG if args.verbose else logging.INFO))
g_logger = logging.getLogger() g_logger = logging.getLogger()
if len(g_logger.handlers): if len(g_logger.handlers):
# Remove stderr output handler from logger. # Remove stderr output handler from logger. We'll control standard output on our own.
log_stderr = g_logger.handlers[0] log_stderr = g_logger.handlers[0]
g_logger.removeHandler(log_stderr) g_logger.removeHandler(log_stderr)
@ -1330,7 +1359,7 @@ if __name__ == "__main__":
time.sleep(0.2) time.sleep(0.2)
print('\nScript interrupted.') print('\nScript interrupted.')
except Exception as e: except Exception as e:
traceback.print_exc(file=sys.stderr) utilsLogException(traceback.format_exc())
try: try:
sys.exit(ret) sys.exit(ret)