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