initial commit of the Python utility menu
This commit is contained in:
39
README.md
Normal file
39
README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Utility Menu
|
||||
|
||||

|
||||
|
||||
## Description
|
||||
|
||||
A template for quickly generating a friendly console utility from a custom CLASS framework.
|
||||
|
||||
Windows:
|
||||
python menu.py
|
||||
|
||||
Linux:
|
||||
python3 menu.py
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Description](#description)
|
||||
- [Notes](#notes)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Installation](#installation)
|
||||
|
||||
## Notes
|
||||
|
||||
- Wraps custom CLASS methods in a user friendly UI
|
||||
- Follow the included template.py
|
||||
- Full ANSI encoding. SSH compatible
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Python 3.x
|
||||
PIP
|
||||
|
||||
## Installation
|
||||
|
||||
Windows:
|
||||
pip install -r requirements.txt
|
||||
|
||||
Linux:
|
||||
pip3 install -r requirements.txt
|
||||
BIN
__pycache__/desktop.ini
Normal file
BIN
__pycache__/desktop.ini
Normal file
Binary file not shown.
BIN
__pycache__/oahu.cpython-310.pyc
Normal file
BIN
__pycache__/oahu.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/template.cpython-310.pyc
Normal file
BIN
__pycache__/template.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/template.cpython-311.pyc
Normal file
BIN
__pycache__/template.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/therm.cpython-310.pyc
Normal file
BIN
__pycache__/therm.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/therm.cpython-311.pyc
Normal file
BIN
__pycache__/therm.cpython-311.pyc
Normal file
Binary file not shown.
BIN
desktop.ini
Normal file
BIN
desktop.ini
Normal file
Binary file not shown.
93
menu.py
Normal file
93
menu.py
Normal file
@@ -0,0 +1,93 @@
|
||||
# main.py
|
||||
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
from rich.console import Group
|
||||
from rich import print
|
||||
from rich.panel import Panel
|
||||
from rich.traceback import install
|
||||
|
||||
# ***edit here to assign Class for menu generation***
|
||||
from template import TEMPLATE as Class_For_Menu # Import the class(es) from specified file
|
||||
|
||||
def main_menu():
|
||||
obj = Class_For_Menu() # create object(s) of imported class(es)
|
||||
install()
|
||||
console = Console()
|
||||
INPUT_TXT = "[green]Input[/green] or [red][bold]q[/bold][/red] to quit:\n"
|
||||
while True:
|
||||
# display titles as menu options
|
||||
console.clear()
|
||||
menu_text = ""
|
||||
for i, method in enumerate(obj.methods, start=1):
|
||||
menu_text += f"{i}. {method['title']}\n"
|
||||
menu_text += f"{len(obj.methods) + 1}. Exit"
|
||||
console.print(print_panel(obj, menu_text))
|
||||
|
||||
# get and proceess menu choice
|
||||
choice = console.input("Select an option: ")
|
||||
try:
|
||||
# Convert the choice to an index
|
||||
choice_index = int(choice) - 1
|
||||
|
||||
if 0 <= choice_index < len(obj.methods):
|
||||
# print the method description, get input
|
||||
console.clear()
|
||||
method_description = obj.methods[choice_index]["description"]
|
||||
form_text = f"[green]{method_description}[/green]"
|
||||
console.print(print_panel(obj, form_text))
|
||||
input_string = console.input(INPUT_TXT)
|
||||
# Check for Quit / 'q'
|
||||
while input_string != "q":
|
||||
# dynamically call the method and print result
|
||||
console.clear()
|
||||
method_name = obj.methods[choice_index]["name"]
|
||||
method = getattr(obj, method_name)
|
||||
# print the results
|
||||
result_table = method(input_string)
|
||||
form_group = Group(format_results(result_table), form_text)
|
||||
console.print(print_panel(obj, form_group))
|
||||
input_string = console.input(INPUT_TXT)
|
||||
elif choice_index == len(obj.methods):
|
||||
console.print("[bold magenta]Goodbye![/bold magenta]")
|
||||
break
|
||||
else:
|
||||
console.print("[bold red]Invalid option, please try again.[/bold red]")
|
||||
|
||||
except ValueError:
|
||||
console.print("[bold red]Please enter a valid number.[/bold red]")
|
||||
except Exception as e:
|
||||
console.print(f"[bold red]An error occurred: {e}[/bold red]")
|
||||
|
||||
def format_results(result_array):
|
||||
"""print the result of the operation as a table"""
|
||||
table = Table()
|
||||
|
||||
# Add header with white color
|
||||
for header in result_array[0]:
|
||||
table.add_column(header, style="white", header_style="bold white")
|
||||
|
||||
# Define colors for up to 5 columns
|
||||
colors = ["cyan", "magenta", "green", "yellow", "blue"]
|
||||
|
||||
# Add the rest of the rows with colored columns
|
||||
for row in result_array[1:]:
|
||||
colored_row = [
|
||||
f"[{colors[i % len(colors)]}]{row[i]}[/{colors[i % len(colors)]}]"
|
||||
for i in range(len(row))
|
||||
]
|
||||
table.add_row(*colored_row)
|
||||
return table
|
||||
|
||||
def print_panel(object, form):
|
||||
"""print the output data in a panel"""
|
||||
panel = Panel.fit(
|
||||
form,
|
||||
title=object.title,
|
||||
border_style="blue",
|
||||
padding=(1, 2)
|
||||
)
|
||||
return panel
|
||||
|
||||
if __name__ == "__main__":
|
||||
main_menu()
|
||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
rich
|
||||
61
template.py
Normal file
61
template.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# template.py
|
||||
|
||||
# used for the examples. these imports can be removed later
|
||||
import os
|
||||
import time
|
||||
|
||||
class TEMPLATE:
|
||||
def __init__(self, initial_temp_c=25.0):
|
||||
# add self.[parameters] here and update method details
|
||||
self.title = "Template Utility"
|
||||
self.usage = """This template can be used to define the CLASS
|
||||
that menu.py will use to generate the utility UI"""
|
||||
|
||||
self.methods = [
|
||||
{
|
||||
"name": "os_info",
|
||||
"title": "Print OS information",
|
||||
"description": "Print basic information from the OS"
|
||||
},
|
||||
{
|
||||
"name": "add_one",
|
||||
"title": "Number incrementer with error checking",
|
||||
"description": "Add 1 to a number"
|
||||
},
|
||||
{
|
||||
"name": "divide_by_zero",
|
||||
"title": "Divide anything by 0",
|
||||
"description": "Returns the input divded by 0"
|
||||
}
|
||||
]
|
||||
|
||||
def os_info(self, unused_input=""):
|
||||
"""Print OS information"""
|
||||
return [
|
||||
["OS:", "Environment Variables:", "Local Time"], # Header row
|
||||
[f"{os.name}", f"{os.getenv('PATH')}", f"{time.localtime()}"]
|
||||
]
|
||||
|
||||
def add_one(self, input):
|
||||
"""Number incrementer with error checking!"""
|
||||
try:
|
||||
input_plus_one = float(input) + 1
|
||||
except:
|
||||
input_plus_one = "[red][bold]NAN[/bold][/red]"
|
||||
return [
|
||||
[f"{input} + 1"], # Header row
|
||||
[f"{input_plus_one}"]
|
||||
]
|
||||
|
||||
def divide_by_zero(self, input):
|
||||
"""Divide anything by 0"""
|
||||
return [
|
||||
[f"{input} / 0"], # Header row
|
||||
["more than 255"]
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
obj = TEMPLATE()
|
||||
# when not using menu.py, direct CLI calls can be handled here
|
||||
obj.os_info()
|
||||
|
||||
Reference in New Issue
Block a user