def test_init(self): root_menu = CursesMenu("root_menu", "test_init") submenu1 = CursesMenu("submenu1", "test_init") submenu2 = CursesMenu("submenu2", "test_init") submenu3 = CursesMenu("submenu2", "test_init") menu_item_1 = SubmenuItem("menu_item_1", submenu1) menu_item_2 = SubmenuItem("menu_item_2", submenu2, root_menu, True) menu_item_3 = SubmenuItem(text="menu_item_3", submenu=submenu3, menu=root_menu, should_exit=False) self.assertEqual(menu_item_1.text, "menu_item_1") self.assertEqual(menu_item_2.text, "menu_item_2") self.assertEqual(menu_item_3.text, "menu_item_3") self.assertIsNone(menu_item_1.menu) self.assertEqual(menu_item_2.menu, root_menu) self.assertEqual(menu_item_3.menu, root_menu) self.assertFalse(menu_item_1.should_exit) self.assertTrue(menu_item_2.should_exit) self.assertFalse(menu_item_3.should_exit) self.assertEqual(menu_item_1.submenu, submenu1) self.assertEqual(menu_item_2.submenu, submenu2) self.assertEqual(menu_item_3.submenu, submenu3) self.assertIsNone(menu_item_1.submenu.parent) self.assertEqual(menu_item_2.submenu.parent, root_menu) self.assertEqual(menu_item_3.submenu.parent, root_menu)
def setUp(self): super(TestSampleMenu, self).setUp() self.menu = CursesMenu("self.menu", "TestSampleMenu") self.item1 = MenuItem("self.item1", self.menu) self.item2 = MenuItem("self.item2", self.menu) self.menu.append_item(self.item1) self.menu.append_item(self.item2) self.menu.start() self.menu.wait_for_start(timeout=10)
def test_currently_active_menu(self): menu1 = CursesMenu("menu1", "test_currently_active_menu") menu2 = CursesMenu("menu2", "test_currently_active_menu") self.assertIsNone(CursesMenu.currently_active_menu) menu1.start() menu1.wait_for_start(10) self.assertIs(CursesMenu.currently_active_menu, menu1) menu2.start() menu2.wait_for_start(10) self.assertIs(CursesMenu.currently_active_menu, menu2)
def submenu_logging(menu_obj): submenu = CursesMenu("Logging Configuration") q1_item = FunctionItem("Do you want to turn enable logging?", input, ['yes']) q2_item = FunctionItem( "If yes, do you want logging to stdout or a log file?", input, ['FILE']) submenu.append_item(q1_item) submenu.append_item(q2_item) submenu_item = SubmenuItem("Show a submenu", submenu, menu=menu_obj) return submenu_item
def submenu_backup(menu_obj): submenu = CursesMenu("Access Key Backup") q1_item = FunctionItem( "Do you want to retain a copy of newly created access keys?", input, ["yes"]) q2_item = FunctionItem( "Enter the directory where a backup copy of the access keys should be stored", input, ["~/Backup"]) submenu.append_item(q1_item) submenu.append_item(q2_item) submenu_item = SubmenuItem("Show a submenu", submenu, menu=menu_obj) return submenu_item
def create_menu(list_dict_stories, type_new): title = 'Pynews - {} stories'.format(type_new.capitalize()) menu = CursesMenu(title, 'Select the new and press enter') msg = 'This new does not have an URL' for story in list_dict_stories: title = clean_title(story['title']) if 'url' in story: item = FunctionItem(title, url_open, args=[story['url']]) else: item = FunctionItem(title, lambda x: print(x), args=[msg]) menu.append_item(item) return menu
def show_menu(self): self.menu = CursesMenu('bust - Module Editor', self.set_subtitle()) self.menu.append_item(FunctionItem('Edit name', self.edit_name)) self.menu.append_item( FunctionItem('List registers', self.list_registers)) self.menu.append_item( FunctionItem('Add new register', self.add_register)) self.menu.append_item( FunctionItem('Remove register', self.remove_register)) self.menu.append_item( FunctionItem('Update addresses', self.update_addresses)) self.menu.append_item(FunctionItem('Save JSON', self.save_JSON)) self.menu.show()
def test_init(self): menu1 = CursesMenu() menu2 = CursesMenu("menu2", "test_init", True) menu3 = CursesMenu(title="menu3", subtitle="test_init", show_exit_option=False) self.assertIsNone(menu1.title) self.assertEqual(menu2.title, "menu2") self.assertEqual(menu3.title, "menu3") self.assertIsNone(menu1.subtitle) self.assertEqual(menu2.subtitle, "test_init") self.assertEqual(menu3.subtitle, "test_init") self.assertTrue(menu1.show_exit_option) self.assertTrue(menu2.show_exit_option) self.assertFalse(menu3.show_exit_option)
class Xfce: """ # # Модуль налаштувань для XFCE # """ # Основне меню menu = CursesMenu("XFCE soft") # Пункти меню _menu_items = [ CommandItem("All remove", "bash bash/xfce.sh"), CommandItem("Remove XFCE4-Notes", "sudo apt autoremove xfce4-notes"), CommandItem("Remove Pidgin", "sudo apt autoremove pidgin"), CommandItem("Remove Thunderbird", "sudo apt autoremove thunderird"), CommandItem("Remove Parole", "sudo apt autoremove parole"), CommandItem("Remove Sudoku", "sudo apt autoremove gnome-sudoku"), CommandItem("Remove Mines", "sudo apt autoremove gnome-mines"), CommandItem("Remove firefox", "sudo apt autoremove firefox") ] # Додавання пунктів до меню for item in _menu_items: menu.append_item(item)
class InstallSoft: """ # # Модуль встановлення програм # """ # Основне меню menu = CursesMenu("Install software", "DEPENDENCES!!!") # Пункти меню _menu_items = [ CommandItem("All software", "bash bash/install.sh"), CommandItem("ssh", "sudo apt install ssh"), CommandItem("Gparted", "sudo apt install gparted"), CommandItem("VLC", "sudo apt install vlc"), CommandItem("screenfetch", "sudo apt install screenfetch"), CommandItem("f.lux", "bash bash/f.lux.sh"), CommandItem("gimp", "sudo apt install gimp"), CommandItem("Kdenlive", "sudo apt install kdenlive"), CommandItem("Wine", "sudo apt install wine"), CommandItem("Rhythmbox", "sudo apt install rhythmbox") ] # Додавання пунктів до меню for item in _menu_items: menu.append_item(item)
class RemoveProgram: """ # # Видалення програм # """ # Основне меню menu = CursesMenu("Remove software", "YOU DELETE SOFT!!!") # Пункти меню _menu_items = [ CommandItem("All software", "bash bash/remove.sh"), CommandItem("ssh", "sudo apt autoremove ssh"), CommandItem("Gparted", "sudo apt autoremove gparted"), CommandItem("VLC", "sudo apt autoremove vlc"), CommandItem("screenfetch", "sudo apt autoremove screenfetch"), CommandItem("f.lux", "sudo apt autoremove flux"), CommandItem("gimp", "sudo apt autoremove gimp"), CommandItem("Kdenlive", "sudo apt autoremove kdenlive"), CommandItem("Wine", "sudo apt autoremove wine"), CommandItem("Rhythmbox", "sudo apt autoremove rhythmbox") ] # Додавання пунктів до меню for item in _menu_items: menu.append_item(item)
def step_impl(context): context.menu = CursesMenu("Test Menu", "Subtitle") context.menu_item = MenuItem("NORMAL", "Menu Item") context.menu.append_item(context.menu_item) context.function_item = FunctionItem("NORMAL", "Call a Python function", input, ["Enter an input"]) context.menu.append_item(context.function_item) pass
def setUp(self): super(TestSampleMenu, self).setUp() self.menu = CursesMenu("self.menu", "TestSampleMenu") self.item1 = MenuItem("self.item1", self.menu) self.item2 = MenuItem("self.item2", self.menu) self.menu.append_item(self.item1) self.menu.append_item(self.item2) self.menu.start() self.menu.wait_for_start(10)
class Menu: def __init__(self, recipes): self.recipes = recipes self.title = 'PyVegan - List of Recipes' self.menu = CursesMenu(self.title, 'Select one and press enter') self.error_msg = 'This search isn\'t a valid one' def build(self): for recipe in self.recipes: if recipe.link: item = FunctionItem(recipe.title, url_open, args=[recipe.link]) else: item = FunctionItem(recipe.title, lambda x: print(x), args=[self.error_msg]) self.menu.append_item(item) def show(self): self.menu.show()
def generate_menu(menu=None, menu_cfg=None, parent_title=None): if not menu_cfg: menu_cfg = c.get_menu() if not menu: title = get_string(menu_cfg, 'title') subtitle = get_string(menu_cfg, 'subtitle', params=parent_title) menu = CursesMenu(title, subtitle) options = menu_cfg['options'] if type(options) == str and get_string(menu_cfg, 'type') == 'submenu': options_list = c.get_config()[options] for option in options_list: if 'on_item_select' in menu_cfg: title = get_string(menu_cfg, 'title') subtitle = get_string(menu_cfg['on_item_select'], 'subtitle', params=option) submenu = CursesMenu(title, subtitle) option_menu = generate_menu(menu_cfg=menu_cfg['on_item_select'], parent_title=option) item = SubmenuItem(option, option_menu, menu=submenu) else: item = FunctionItem(option, getattr(c.get_action_module(), menu_cfg['action']), [option]) # TODO allow for customisation of module name menu.append_item(item) else: for option in menu_cfg['options']: cmd_type = get_string(option, 'type') title = get_string(option, 'title') action = get_string(option, 'action') subtitle = get_string(option, 'subtitle') if cmd_type == 'function': item = FunctionItem(title, getattr(actions, action)) elif cmd_type == 'submenu': submenu = CursesMenu(title, subtitle) item = SubmenuItem(title, submenu, menu=menu) generate_menu(submenu, option, title) else: item = MenuItem(title) menu.append_item(item) return menu
def test_init(self): menu = CursesMenu("menu", "test_init") exit_item_1 = ExitItem("exit_item_1") exit_item_2 = ExitItem("exit_item_2", menu) exit_item_3 = ExitItem(text="exit_item_3", menu=menu) self.assertEqual(exit_item_1.text, "exit_item_1") self.assertEqual(exit_item_2.text, "exit_item_2") self.assertEqual(exit_item_3.text, "exit_item_3") self.assertEqual(exit_item_1.menu, None) self.assertEqual(exit_item_2.menu, menu) self.assertEqual(exit_item_3.menu, menu) self.assertTrue(exit_item_1.should_exit) self.assertTrue(exit_item_2.should_exit) self.assertTrue(exit_item_3.should_exit)
def step_impl(context): context.menu = CursesMenu("Test Menu", "Subtitle") context.menu_item = MenuItem("NORMAL", "Menu Item") context.menu.append_item(context.menu_item) context.function_item = FunctionItem("NORMAL", "Call a Python function", input, ["Enter an input"]) context.menu.append_item(context.function_item) context.command_item = CommandItem("NORMAL", "Run a console command", "ipconfig /all") context.menu.append_item(context.command_item) context.selection_menu = SelectionMenu(["item1", "item2", "item3"]) context.selection_submenu_item = SubmenuItem("NORMAL", "Submenu item", context.selection_menu) context.menu.append_item(context.selection_submenu_item) pass
def main(): """ Builds main menu, branches to submenus """ # parent menu menu = CursesMenu("Local Configuration Menu", "keyup Project") try: submenu_backup = submenu_backup(menu) submenu_logging = submenu_logging(menu) # assemble main menu menu.append_item(submenu_backup) menu.append_item(submenu_logging) menu.show() user_selection = menu.selected_option except Exception as e: print('Unknown Exception: %s. Exit' % str(e)) return False return True
def generate_menu(tasks): """ Create menu for process selection """ menu = CursesMenu("Select something to kill him!") # a CommandItem runs a console command for pid, name in tasks.items(): label = "{:<8} - {}".format('[' + str(pid) + ']', name[:40]) command = "kill {}".format(pid) menu.append_item(cmitems.CommandItem(label, command)) # show the menu and allow the user to interact menu.show()
class SshX: """ # # Модуль підключення SSH з підтримкою запуска програм з графічним інтерфейсом # """ menu = CursesMenu("SSH connect with X-window support") # Пункти _menu_items = [ CommandItem("Home ms-7519(ivan)", "ssh -X [email protected]"), CommandItem("Acer-aspire V5-131(ivan)", "ssh -X [email protected]"), CommandItem("Lenovo B560(diana)", "ssh -X [email protected]"), CommandItem("Server(home)", "ssh -X [email protected]") ] # Додаваня пунктів до меню for item in _menu_items: menu.append_item(item)
class SSH: """ # # SSH підключення # """ # Основне меню menu = CursesMenu("SSH Connect") # Пунктии меню _menu_items = [ CommandItem("DIR 615-E4", "ssh [email protected]"), CommandItem("Home ms-7519(ivan)", "ssh [email protected]"), CommandItem("Acer-aspire V5-131(ivan)", "ssh [email protected]"), CommandItem("Lenovo B560(diana)", "ssh [email protected]"), CommandItem("Server(home)", "ssh [email protected]") ] # Додавання пунктів до меню for item in _menu_items: menu.append_item(item)
submenu_logging = submenu_logging(menu) # assemble main menu menu.append_item(submenu_backup) menu.append_item(submenu_logging) menu.show() user_selection = menu.selected_option except Exception as e: print('Unknown Exception: %s. Exit' % str(e)) return False return True if __name__ == '__main__': menu = CursesMenu("Local Configuration Menu", "xlines Project") # backup submenu = CursesMenu("Exclusions", 'Do you want to add a new file type exclusion?') q1_item1 = FunctionItem("Yes", input, ["yes"]) q1_item2 = FunctionItem("No", print('Exit'), ["no"]) submenu.append_item(q1_item1) submenu.append_item(q1_item2) submenu_exclusions = SubmenuItem("Configure Exclusion List", submenu, menu=menu) menu.append_item(submenu_exclusions) if q1_item1 == "yes": display_exclusions() submenu = CursesMenu( "Access Key Backup",
def setUp(self): super(TestCommandItem, self).setUp() self.menu = CursesMenu("self.menu", "TestCommandItem")
def run(self): menu = CursesMenu("Openstack Toolset", "Restore OpenStack Virtual Machine Block Device from SAN - By Real World") options = ['Restore State'] for idx, item in enumerate(options): menu.append_item(SelectionItem(item, idx)) submenu = CursesMenu("Contact the Author.") contact = SubmenuItem("Author: Karl Kloppenborg", submenu=submenu) contact2 = SubmenuItem("Email: [email protected]", submenu=submenu) submenu.append_item(contact) submenu.append_item(contact2) sub = SubmenuItem("Help!", submenu, menu=menu) menu.append_item(sub) menu.show() return menu.selected_option
def step_impl(context): context.menu = CursesMenu("Test Menu", "Subtitle") pass
def create_menu(self) -> None: # Create the menu self.menu = CursesMenu("PyMeterReader Configuration Wizard", "Choose item to configure") function_item = FunctionItem("Volkszähler Gateway", self.input_gw, ["Enter URL: "], should_exit=True) self.menu.append_item(function_item) for meter in self.meters: meter_menu = CursesMenu( f"Connect channels for meter {meter.meter_id} at {meter.meter_address}", "By channel") for channel in meter.channels: map_menu = CursesMenu( f"Choose uuid for {channel.channel_name}") for choice in self.gateway_channels: map_menu.append_item( FunctionItem(f"{choice.uuid}: {choice.title}", self.__assign, [meter, channel, choice.uuid, '30m'], should_exit=True)) map_menu.append_item( FunctionItem("Enter private UUID", self.__assign, [meter, channel, None, '30m'], should_exit=True)) meter_menu.append_item( SubmenuItem( f"{channel.channel_name}: {channel.value} {channel.unit}", map_menu, self.menu)) submenu_item = SubmenuItem(f"Meter {meter.meter_id}", meter_menu, self.menu) self.menu.append_item(submenu_item) view_item = FunctionItem("View current mapping", self.__view_mapping) self.menu.append_item(view_item) save_item = FunctionItem("Save current mapping", self.__safe_mapping) self.menu.append_item(save_item) register_service = FunctionItem( "Register PymeterReader as systemd service.", self.__register_service) self.menu.append_item(register_service) reset_item = FunctionItem("Reset all mappings", self.__clear) self.menu.append_item(reset_item) self.menu.show()
class Wizard: CONFIG_FILE_NAME = "pymeterreader.yaml" POSIX_CONFIG_PATH = Path("/etc") / CONFIG_FILE_NAME def __init__(self) -> None: logging.basicConfig(level=logging.INFO) self.url = "http://localhost/middleware.php" self.gateway = VolkszaehlerGateway(self.url) self.gateway_channels = self.gateway.get_channels() self.menu: CursesMenu print("Detecting meters...") self.meters = detect() self.channel_config: tp.Dict[str, tp.Dict[str, tp.Union[str, tp.Dict]]] = {} self.restart_ui = True while self.restart_ui: self.restart_ui = False self.create_menu() def input_gw(self, text) -> None: def is_valid_url(): return re.match(r"^https?://[/\w\d.]+.php$", self.url) self.restart_ui = True self.menu.clear_screen() self.url = "invalid" while self.url and not is_valid_url(): self.url = input(text) if not self.url: self.menu.stdscr.addstr( 3, 0, "Defaulting to http://localhost/middleware.php") self.url = "http://localhost/middleware.php" self.menu.stdscr.getkey() elif not is_valid_url(): self.menu.stdscr.addstr( 3, 0, "Entered url is not valid." " It must start with 'http://' or 'https://' and end with '.php'" ) self.menu.stdscr.getkey() self.gateway = VolkszaehlerGateway(self.url) self.gateway_channels = self.gateway.get_channels() if self.gateway_channels: self.menu.stdscr.addstr( 3, 0, f"Found {len(self.gateway_channels)} public channels at gateway '{self.url}'." ) else: self.menu.stdscr.addstr( 3, 0, f"Unable to find any public channels at '{self.url}'.") self.menu.stdscr.getkey() def create_menu(self) -> None: # Create the menu self.menu = CursesMenu("PyMeterReader Configuration Wizard", "Choose item to configure") function_item = FunctionItem("Volkszähler Gateway", self.input_gw, ["Enter URL: "], should_exit=True) self.menu.append_item(function_item) for meter in self.meters: meter_menu = CursesMenu( f"Connect channels for meter {meter.meter_id} at {meter.meter_address}", "By channel") for channel in meter.channels: map_menu = CursesMenu( f"Choose uuid for {channel.channel_name}") for choice in self.gateway_channels: map_menu.append_item( FunctionItem(f"{choice.uuid}: {choice.title}", self.__assign, [meter, channel, choice.uuid, '30m'], should_exit=True)) map_menu.append_item( FunctionItem("Enter private UUID", self.__assign, [meter, channel, None, '30m'], should_exit=True)) meter_menu.append_item( SubmenuItem( f"{channel.channel_name}: {channel.value} {channel.unit}", map_menu, self.menu)) submenu_item = SubmenuItem(f"Meter {meter.meter_id}", meter_menu, self.menu) self.menu.append_item(submenu_item) view_item = FunctionItem("View current mapping", self.__view_mapping) self.menu.append_item(view_item) save_item = FunctionItem("Save current mapping", self.__safe_mapping) self.menu.append_item(save_item) register_service = FunctionItem( "Register PymeterReader as systemd service.", self.__register_service) self.menu.append_item(register_service) reset_item = FunctionItem("Reset all mappings", self.__clear) self.menu.append_item(reset_item) self.menu.show() def __register_service(self) -> None: self.menu.clear_screen() if platform.system() != "Linux": self.menu.stdscr.addstr( 0, 0, "Systemd Service registration is only supported on Linux!") self.menu.stdscr.addstr(1, 0, "(press any key)") self.menu.stdscr.getkey() return self.menu.stdscr.addstr(0, 0, "Installing service...") run( 'sudo systemctl stop pymeterreader', # pylint: disable=subprocess-run-check universal_newlines=True, shell=True) target_service_file = "/etc/systemd/system/pymeterreader.service" service_str = SERVICE_TEMPLATE.format( f'pymeterreader -c {self.POSIX_CONFIG_PATH.absolute()}') try: with open(target_service_file, 'w') as target_file: target_file.write(service_str) run( 'systemctl daemon-reload', # pylint: disable=subprocess-run-check universal_newlines=True, shell=True) if not exists(self.POSIX_CONFIG_PATH): self.menu.stdscr.addstr( 1, 0, f"Copy example configuration file to '{self.POSIX_CONFIG_PATH.absolute()}'" ) with open('example_configuration.yaml', 'r') as file: example_config = file.read() with open(self.POSIX_CONFIG_PATH, 'w') as file: file.write(example_config) self.menu.stdscr.addstr( 2, 0, "Registered pymeterreader as service.\n" "Enable with 'sudo systemctl enable pymeterreader'\n." f"IMPORTANT: Create configuration file '{self.POSIX_CONFIG_PATH.absolute()}'" ) except FileNotFoundError as err: self.menu.stdscr.addstr(4, 0, f"Could not access file: {err}!") except PermissionError: self.menu.stdscr.addstr( 4, 0, "Cannot write service file to /etc/systemd/system. " "Run as root (sudo) to solve this.") self.menu.stdscr.addstr(6, 0, "(press any key)") self.menu.stdscr.getkey() def __clear(self) -> None: """ Remove channel mappings """ self.channel_config.clear() def __safe_mapping(self) -> None: """ Save yaml to system """ self.menu.clear_screen() result = generate_yaml(self.channel_config, self.url) try: if platform.system() in ["Linux", "Darwin"]: config_path = self.POSIX_CONFIG_PATH else: config_path = Path(".") / "pymeterreader.yaml" with open(config_path, "w") as config_file: config_file.write(result) self.menu.stdscr.addstr(0, 0, f"Saved to {config_path.absolute()}") except PermissionError: self.menu.stdscr.addstr( 0, 0, f"Insufficient permissions: cannot write to {config_path.absolute()}!" ) except FileNotFoundError: self.menu.stdscr.addstr( 0, 0, f"Could not access path: {config_path.absolute()}!") self.menu.stdscr.addstr(1, 0, "(press any key)") self.menu.stdscr.getkey() def __view_mapping(self) -> None: self.menu.clear_screen() self.menu.stdscr.addstr(0, 0, "Mapped channels:") row = 2 for meter in self.channel_config.values(): for channel, content in meter['channels'].items(): self.menu.stdscr.addstr( row, 2, f"{channel} at {meter.get('id')} mapped to UUID {content.get('uuid')}" ) row += 1 self.menu.stdscr.addstr(row, 0, "(press any key)") self.menu.stdscr.getkey() def __assign(self, meter: Device, channel: ChannelValue, uuid: tp.Optional[str], interval: str) -> None: if uuid is None: self.menu.clear_screen() uuid = input("Enter private UUID: ") if meter.meter_id not in self.channel_config: self.channel_config[meter.meter_id] = { 'channels': {}, 'protocol': meter.protocol, 'meter_address': meter.meter_address, 'meter_id': meter.meter_id } self.channel_config[meter.meter_id]['channels'][ channel.channel_name] = { 'uuid': uuid, 'interval': interval }
def parse_old_menu(menu_data): """ Take an old-style menuData dictionary and return a CursesMenu :param dict menu_data: :return: A new CursesMenu :rtype: CursesMenu """ menu_title = menu_data['title'] menu = CursesMenu(menu_title) for item in menu_data["options"]: item_type = item["type"] item_title = item["title"] if item_type == menuItem.COMMAND: item_command = item["command"] menu.append_item(CommandItem(item_title, item_command, menu)) elif item_type == menuItem.FUNCTION: item_function = item["function"] menu.append_item(FunctionItem(item_title, item_function, menu)) elif item_type == menuItem.EXITMENU: menu.append_item(ExitItem(item_title, menu)) elif item_type == menuItem.NUMBER: menu.append_item(SelectionItem(item_title, menu)) elif item_type == menuItem.MENU: new_menu = parse_old_menu(item) menu.append_item(SubmenuItem(item_title, menu, new_menu)) return menu
# Основне меню. Запускати програму з цього файла # # Класи для створення меню from cursesmenu import CursesMenu from cursesmenu.items import CommandItem, SubmenuItem import platform from modules import InstallSoft as soft from modules import RemoveProgram as remove from modules import SSH as ssh from modules import SshX as ssh_X from modules import Xfce as xfce # Створення основного меню menu = CursesMenu("Ubuntu universal script", platform.version()) # Створення основних пунктів _menu_items = [ CommandItem("Update paсkages", "sudo apt update"), CommandItem("Upgrade paсkages", "sudo apt upgrade"), CommandItem("Autoremove paсkages", "sudo apt autoremove"), CommandItem("Remove other kernel`s", "bash bash/remove_kernel.sh"), CommandItem( "Cleaning pickings removed paсkages", "sudo dpkg -l | awk '/^rc/ {print $2}' | xargs sudo dpkg --purge"), # Відображення підменю SubmenuItem("Install soft", soft.menu, menu), SubmenuItem("Remove software", remove.menu, menu), SubmenuItem("Xfce soft", xfce.menu, menu), SubmenuItem("SSH Connect", ssh.menu, menu),
def test_action(self): root_menu = CursesMenu("root_menu", "test_action") submenu1 = CursesMenu("submenu1", "test_action") submenu2 = CursesMenu("submenu2", "test_action") submenu_item_1 = SubmenuItem("submenu_item_1", submenu1, menu=root_menu) submenu_item_2 = SubmenuItem("submenu_item_2", submenu2, menu=root_menu) root_menu.append_item(submenu_item_1) root_menu.append_item(submenu_item_2) root_menu.start() root_menu.wait_for_start(timeout=10) self.assertIs(CursesMenu.currently_active_menu, root_menu) submenu_item_1.action() submenu1.wait_for_start(timeout=10) self.assertIs(CursesMenu.currently_active_menu, submenu1) CursesMenu.currently_active_menu.exit() submenu1.join(timeout=10) self.assertIs(CursesMenu.currently_active_menu, root_menu) submenu_item_2.action() submenu2.wait_for_start(timeout=10) self.assertIs(CursesMenu.currently_active_menu, submenu2)
def step_impl(context): context.menu = CursesMenu("Test Menu", "Subtitle") context.menu_item = MenuItem("NORMAL", "Menu Item") context.menu.append_item(context.menu_item) pass
class Editor(object): """A console-based menu system for creating and editing module descripting JSON files """ def __init__(self, edit, jsonfile, output_dir='output/'): """Constructor Either reconstructs a module object from JSON, or create a new based on user input """ self.jsonfile = jsonfile self.output_dir = output_dir self.recently_saved = False if edit: # Load the specified JSON file try: json = json_parser(jsonfile) self.settings = Settings(jsonfile, json['settings']) self.bus = Bus(json['bus']) self.mod = Module(json['module'], self.bus, self.settings) self.recently_saved = True except Exception as e: print('An unresolvable error has occurred:') print(str(e)) print('Exiting...') exit() else: bus_dic = OrderedDict() bus_dic['type'] = get_list_choice('Choose a bus type: ', Bus.supported_bus) bus_dic['addr_width'] = 32 bus_dic['data_width'] = 32 bus_dic['reset'] = 'async' self.bus = Bus(bus_dic) # Get name, addr_width, data_width and description mod = OrderedDict() mod['name'] = get_identifier('Enter a module name: ') '''! @todo Add int check''' mod['addr_width'] = 32 mod['data_width'] = 32 mod['description'] = input('Enter a description for the module: ') mod['register'] = [] self.settings = Settings(None, None) self.mod = Module(mod, self.bus, self.settings) def show_menu(self): self.menu = CursesMenu('bust - Module Editor', self.set_subtitle()) self.menu.append_item(FunctionItem('Edit name', self.edit_name)) self.menu.append_item( FunctionItem('List registers', self.list_registers)) self.menu.append_item( FunctionItem('Add new register', self.add_register)) self.menu.append_item( FunctionItem('Remove register', self.remove_register)) self.menu.append_item( FunctionItem('Update addresses', self.update_addresses)) self.menu.append_item(FunctionItem('Save JSON', self.save_JSON)) self.menu.show() def update_menu(self): self.menu.subtitle = self.set_subtitle() def edit_name(self): print('Change the module name from current: ' + self.mod.name) self.mod.name = get_identifier('Enter a new name: ') self.recently_saved = False self.update_menu() def return_registers(self): while True: clear_screen() if len(self.mod.registers) < 1: print('No registers created at this point...') cont() return else: table = PrettyTable() table.field_names = [ '#', 'Name', 'Mode', 'Address', 'Type', 'Length', 'Reset', 'Description' ] for i, reg in enumerate(self.mod.registers): table.add_row([ i, reg.name, reg.mode, hex(reg.address), reg.sig_type, reg.length, reg.reset, add_line_breaks(reg.description, 25) ]) return table def list_registers(self): table = self.return_registers() if table is None: return print(table) print( '\nEnter the register number for register details, or q to quit...' ) while True: choice = input('Choice: ') if self.valid_register_input(choice): break else: print(choice + ' is not a valid choice') if choice == 'q': return else: clear_screen() self.print_register(int(choice), table) cont() def print_register(self, reg_num, table): reg = self.mod.registers[reg_num] print(table.get_string(start=reg_num, end=(reg_num + 1))) if len(reg.fields) > 0: print('\nFields:') table_fields = PrettyTable() table_fields.field_names = [ '#', 'Name', 'Type', 'Position', 'Length', 'Reset', 'Description' ] for i, field in enumerate(reg.fields): table_fields.add_row([ i, field.name, field.sig_type, field.get_pos_str(), field.length, field.reset, add_line_breaks(field.description, 25) ]) print(table_fields) def add_register(self): """Adds a register to the module object Get user input to create a register that may or may not consists of individual fields """ reg = OrderedDict() reg_names = [regs.name for regs in self.mod.registers] print('Input register information: ') try: reg['name'] = get_identifier('Name: ', reg_names) reg['description'] = input('Description: ') reg['mode'] = get_list_choice("Choose register mode: ", Register.supported_modes, 'lower', 0) fields = [] width_consumed = 0 while True: field_dic = OrderedDict() add_fields = input('Do you want to add a field? (Y/n): ') field_names = [field['name'] for field in fields] if add_fields.upper() == 'N': break elif add_fields.upper() == 'Y' or add_fields == '': field_dic['name'] = get_identifier('Field name: ', field_names) field_dic['type'] = get_list_choice( 'Field type: ', Field.supported_types) if field_dic['type'] == 'slv': max_width = self.mod.data_width - width_consumed field_dic['length'] = get_int( 'Field length: ', 10, 1, max_width, "The minimum width of a field is 1!", "The maximum width of this field cannot extend" + " the module data width minus the width already" + " consumed by other fields: " + str(max_width)) width_consumed += field_dic['length'] else: width_consumed += 1 field_dic['length'] = 1 max_reset = 2**field_dic['length'] - 1 field_dic['reset'] = hex( get_int( 'Field reset in hex (default=0x0): ', 16, 0x0, max_reset, "The minimum reset value is 0x0", "The maximum reset value is based on the field width, " + "and is " + str(hex(max_reset)), 0x0)) field_dic['description'] = input('Field description: ') fields.append(field_dic) # Check if all available data bits are use if width_consumed == self.mod.data_width: print( "All available bits (" + str(self.mod.data_width) + ") is consumed.\n" + "No more fields can be added to this register.\n") break elif width_consumed > self.mod.data_width: raise RuntimeError( "More bits used by fields than available...") else: print(add_fields + ' is not a valid choice...') if len(fields) > 0: reg['type'] = 'fields' reg['fields'] = fields else: reg['type'] = get_list_choice('Register type: ', Register.supported_types, None, 0) # Make sure reg length is set to help calculate max reset later # Registers of field type will get an auto reset based on the field resets if reg['type'] == 'default': reg['length'] = self.mod.data_width elif reg['type'] == 'sl': reg['length'] = 1 elif reg['type'] == 'slv': while True: try: reg['length'] = int(input('Length: ')) break except Exception: print('That is not a valid length...') if input('Auto-assign address? (Y/n): ').upper() == 'N': # Make sure the address is not out of range and that it is free max_address = 2**self.mod.addr_width - 1 while True: reg['address'] = get_int( "Address in hex: ", 16, 0x0, max_address, "The minimum address is 0x0", "The maximum address is based on the module address width, " + "and is " + str(hex(max_address)), 0x0) # Perform an extra check of address range, although redundant if self.mod.is_address_out_of_range(reg['address']): print("Address is out of range...") continue # Check if the address has not been taken if not self.mod.is_address_free(reg['address']): print( "The chosen address is already assigned to another register..." ) continue # Check whether the address is not byte-addressed, and give the user a choice to continue if not self.mod.is_address_byte_based(reg['address']): choice = input( "The selected address is not byte-based. Continue? (y/N): " ) if not choice.upper() == 'Y': continue break if reg['type'] != 'fields': max_reset = 2**reg['length'] - 1 reg['reset'] = hex( get_int( 'Register reset in hex (default=0x0): ', 16, 0x0, max_reset, "The minimum reset value is 0x0", "The maximum reset value is based on the register width, " + "and is " + str(hex(max_reset)), 0x0)) table = PrettyTable() table.field_names = [ '#', 'Name', 'Mode', 'Address', 'Type', 'Length', 'Reset', 'Description' ] # Table values based on what values exists table_name = reg['name'] table_mode = reg['mode'] if 'address' in reg: table_address = reg['address'] else: table_address = 'auto' table_type = reg['type'] if reg['type'] == 'fields': table_length = 'auto' elif 'length' in reg: table_length = reg['length'] else: table_length = self.mod.bus.data_width if reg['type'] == 'fields': table_reset = 'auto' elif 'reset' in reg: table_reset = reg['reset'] else: table_reset = 'auto' table_description = add_line_breaks(reg['description'], 25) table.add_row([ len(self.mod.registers), table_name, table_mode, table_address, table_type, table_length, table_reset, table_description ]) print(table) if 'fields' in reg: print('\nFields:') table_fields = PrettyTable() table_fields.field_names = [ '#', 'Name', 'Type', 'Length', 'Reset', 'Description' ] for i, field in enumerate(reg['fields']): table_fields.add_row([ i, field['name'], field['type'], field['length'], field['reset'], field['description'] ]) print(table_fields) if input('Confirm creation of register? (Y/n): ').upper() != 'N': self.mod.add_register(reg) self.recently_saved = False self.update_menu() else: return except KeyboardInterrupt: print('\nAdding register aborted!') cont() except Exception as e: print('\nAdding register failed!') print(str(e)) cont() def remove_register(self): table = self.return_registers() if table is None: return print(table) print('\nEnter the register number for removal, or q to quit...') while True: choice = input('Choice: ') if self.valid_register_input(choice): break else: print(choice + ' is not a valid choice') if choice == 'q': return else: clear_screen() self.print_register(int(choice), table) if input('Are you sure you want to delete this register? (y/N): ' ).upper() == 'Y': del self.mod.registers[int(choice)] self.recently_saved = False self.update_menu() def update_addresses(self): self.mod.update_addresses() print("Addresses are updated..") self.recently_saved = False self.update_menu() cont() def save_JSON(self): print('Saving ' + self.jsonfile + ' ...') # Get JSON with addresses json = self.mod.return_JSON(True) try: write_string_to_file(json, self.jsonfile, ".") except Exception as e: print('Saving failed...') print(e) cont() return self.recently_saved = True cont() self.update_menu() def set_subtitle(self): if self.recently_saved: s = ' - SAVED' else: s = ' - NOT SAVED' string = self.mod.name string += ' / ' + str(self.mod.addr_width) string += ' / ' + str(self.mod.data_width) string += ' / ' + str(hex(self.mod.baseaddr)) string += s return string def valid_register_input(self, s): """ Returns boolean determining if a choice of register is valid The input is first checked against the quit-character, and then checked if it matches any valid indexes of the mod.registers list. """ if s.upper() == 'Q': return True elif is_int(s): index = int(s) for i, reg in enumerate(self.mod.registers): if index == i: return True return False
class TestSampleMenu(BaseTestCase): def setUp(self): super(TestSampleMenu, self).setUp() self.menu = CursesMenu("self.menu", "TestSampleMenu") self.item1 = MenuItem("self.item1", self.menu) self.item2 = MenuItem("self.item2", self.menu) self.menu.append_item(self.item1) self.menu.append_item(self.item2) self.menu.start() self.menu.wait_for_start(10) def tearDown(self): super(TestSampleMenu, self).tearDown() self.menu.exit() self.menu.join() def test_go_down(self): self.menu.go_down() self.assertEqual(self.menu.current_option, 1) self.assertIs(self.menu.current_item, self.item2) self.menu.go_down() self.assertEqual(self.menu.current_option, 2) self.assertEqual(self.menu.current_item, self.menu.exit_item) self.menu.go_down() self.assertEqual(self.menu.current_option, 0) self.assertIs(self.menu.current_item, self.item1) def test_go_up(self): self.menu.go_up() self.assertEqual(self.menu.current_option, 2) self.assertIs(self.menu.current_item, self.menu.exit_item) self.menu.go_up() self.assertEqual(self.menu.current_option, 1) self.assertEqual(self.menu.current_item, self.item2) self.menu.go_up() self.assertEqual(self.menu.current_option, 0) self.assertIs(self.menu.current_item, self.item1) def test_go_to(self): self.menu.go_to(1) self.assertEqual(self.menu.current_option, 1) self.assertEqual(self.menu.current_item, self.item2) def test_select(self): self.menu.select() self.assertEqual(self.menu.selected_option, 0) self.assertIs(self.menu.selected_item, self.item1) self.menu.go_down() self.menu.select() self.assertEqual(self.menu.selected_option, 1) self.assertIs(self.menu.selected_item, self.item2) self.menu.go_down() self.menu.select() self.assertEqual(self.menu.selected_option, 2) self.assertIs(self.menu.selected_item, self.menu.exit_item) self.menu.join(timeout=5) self.assertFalse(self.menu.is_alive()) def test_exit(self): self.menu.exit() self.menu.join(timeout=5) self.assertFalse(self.menu.is_alive())
from cursesmenu import CursesMenu from cursesmenu.items import * from scriptku import menucurse #Top Level Menu toplv_menu = CursesMenu("Menu Raspberry Legend! - written by Pratama", "pilih satu") #Youtube Menu yt_menu = CursesMenu("Utility utk download youtube video", "pilih salah satu") toplv_yt_item = SubmenuItem("Youtube Video Downloader", yt_menu, menu=toplv_menu) yt1 = FunctionItem("Download single youtube video", menucurse.yt1) yt_edit_links = FunctionItem("Edit list download", menucurse.yt_edit_links) yt_bulk = FunctionItem("Bulk download youtube videos", menucurse.yt_bulk) #Bulk rename menu bulk_rename_item = FunctionItem("Bulk rename - WARNING(DANGEROUS TOOLS, USE AT YOUR OWN RISK)", menucurse.bulk_rename) #Top Level Menu Append toplv_menu.append_item(toplv_yt_item) toplv_menu.append_item(bulk_rename_item) #Youtube Menu Append yt_menu.append_item(yt1) yt_menu.append_item(yt_edit_links) yt_menu.append_item(yt_bulk) #Show the Top Level Menu toplv_menu.show()