From eb5f2c564839a6f67be5352d740a9d77eb76a5e0 Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Mon, 13 Jan 2020 12:03:13 -0800 Subject: [PATCH] more on type hinting, remove unecessary function comments --- daemon/core/gui/coreclient.py | 39 +------ daemon/core/gui/dialogs/alerts.py | 2 +- daemon/core/gui/dialogs/canvassizeandscale.py | 2 - daemon/core/gui/dialogs/canvaswallpaper.py | 2 - daemon/core/gui/dialogs/colorpicker.py | 23 ++-- daemon/core/gui/dialogs/copyserviceconfig.py | 3 +- daemon/core/gui/dialogs/customnodes.py | 4 +- daemon/core/gui/dialogs/dialog.py | 3 +- daemon/core/gui/dialogs/emaneconfig.py | 11 +- daemon/core/gui/dialogs/hooks.py | 6 +- daemon/core/gui/dialogs/linkconfig.py | 9 +- daemon/core/gui/dialogs/marker.py | 4 +- daemon/core/gui/dialogs/nodeconfig.py | 6 +- daemon/core/gui/dialogs/nodeservice.py | 6 +- daemon/core/gui/dialogs/observers.py | 2 +- daemon/core/gui/dialogs/preferences.py | 2 +- daemon/core/gui/dialogs/servers.py | 2 +- daemon/core/gui/dialogs/serviceconfig.py | 19 ++-- daemon/core/gui/dialogs/sessions.py | 16 +-- daemon/core/gui/dialogs/wlanconfig.py | 4 - daemon/core/gui/graph/edges.py | 23 ++-- daemon/core/gui/graph/graph.py | 104 ++++++------------ daemon/core/gui/graph/node.py | 6 +- daemon/core/gui/graph/shape.py | 29 ++--- daemon/core/gui/graph/shapeutils.py | 6 +- daemon/core/gui/graph/tooltip.py | 7 +- daemon/core/gui/interface.py | 14 ++- daemon/core/gui/menuaction.py | 4 +- daemon/core/gui/menubar.py | 68 ------------ daemon/core/gui/nodeutils.py | 14 +-- daemon/core/gui/statusbar.py | 4 +- daemon/core/gui/toolbar.py | 26 ++--- daemon/core/gui/validation.py | 16 +-- daemon/core/gui/widgets.py | 9 +- 34 files changed, 169 insertions(+), 326 deletions(-) diff --git a/daemon/core/gui/coreclient.py b/daemon/core/gui/coreclient.py index b780e3ba..1e7c3731 100644 --- a/daemon/core/gui/coreclient.py +++ b/daemon/core/gui/coreclient.py @@ -204,7 +204,7 @@ class CoreClient: self.handling_throughputs.cancel() self.handling_throughputs = None - def handle_throughputs(self, event): + def handle_throughputs(self, event: core_pb2.ThroughputsEvent): if event.session_id != self.session_id: logging.warning( "ignoring throughput event session(%s) current(%s)", @@ -303,7 +303,7 @@ class CoreClient: def is_runtime(self) -> bool: return self.state == core_pb2.SessionState.RUNTIME - def parse_metadata(self, config): + def parse_metadata(self, config: Dict[str, str]): # canvas setting canvas_config = config.get("canvas") logging.info("canvas metadata: %s", canvas_config) @@ -367,8 +367,6 @@ class CoreClient: def create_new_session(self): """ Create a new session - - :return: nothing """ try: response = self.client.create_session() @@ -399,8 +397,6 @@ class CoreClient: def set_up(self): """ Query sessions, if there exist any, prompt whether to join one - - :return: existing sessions """ try: self.client.connect() @@ -534,9 +530,6 @@ class CoreClient: def save_xml(self, file_path: str): """ Save core session as to an xml file - - :param str file_path: file path that user pick - :return: nothing """ try: if self.state != core_pb2.SessionState.RUNTIME: @@ -552,9 +545,6 @@ class CoreClient: def open_xml(self, file_path: str): """ Open core xml - - :param str file_path: file to open - :return: session id """ try: response = self.client.open_xml(file_path) @@ -596,7 +586,7 @@ class CoreClient: return response.data def set_node_service_file( - self, node_id: int, service_name: str, file_name: str, data: str + self, node_id: int, service_name: str, file_name: str, data: bytes ): response = self.client.set_node_service_file( self.session_id, node_id, service_name, file_name, data @@ -606,8 +596,6 @@ class CoreClient: def create_nodes_and_links(self): """ create nodes and links that have not been created yet - - :return: nothing """ node_protos = [x.core_node for x in self.canvas_nodes.values()] link_protos = [x.link for x in self.links.values()] @@ -634,8 +622,6 @@ class CoreClient: def send_data(self): """ send to daemon all session info, but don't start the session - - :return: nothing """ self.create_nodes_and_links() for config_proto in self.get_wlan_configs_proto(): @@ -680,18 +666,13 @@ class CoreClient: def close(self): """ Clean ups when done using grpc - - :return: nothing """ logging.debug("close grpc") self.client.close() - def next_node_id(self): + def next_node_id(self) -> int: """ Get the next usable node id. - - :return: the next id to be used - :rtype: int """ i = 1 while True: @@ -743,9 +724,6 @@ class CoreClient: """ remove the nodes selected by the user and anything related to that node such as link, configurations, interfaces - - :param list canvas_nodes: list of nodes to delete - :return: nothing """ edges = set() for canvas_node in canvas_nodes: @@ -767,9 +745,6 @@ class CoreClient: if edge in edges: continue edges.add(edge) - # - # if edge.token not in self.links: - # logging.error("unknown edge: %s", edge.token) self.links.pop(edge.token, None) def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface: @@ -795,12 +770,6 @@ class CoreClient: """ Create core link for a pair of canvas nodes, with token referencing the canvas edge. - - :param edge: edge for link - :param canvas_src_node: canvas node one - :param canvas_dst_node: canvas node two - - :return: nothing """ src_node = canvas_src_node.core_node dst_node = canvas_dst_node.core_node diff --git a/daemon/core/gui/dialogs/alerts.py b/daemon/core/gui/dialogs/alerts.py index 7e82da73..38de8d38 100644 --- a/daemon/core/gui/dialogs/alerts.py +++ b/daemon/core/gui/dialogs/alerts.py @@ -110,7 +110,7 @@ class AlertsDialog(Dialog): dialog = DaemonLog(self, self.app) dialog.show() - def click_select(self, event): + def click_select(self, event: tk.Event): current = self.tree.selection()[0] alarm = self.alarm_map[current] self.codetext.text.config(state=tk.NORMAL) diff --git a/daemon/core/gui/dialogs/canvassizeandscale.py b/daemon/core/gui/dialogs/canvassizeandscale.py index 11cc97b4..b48f6296 100644 --- a/daemon/core/gui/dialogs/canvassizeandscale.py +++ b/daemon/core/gui/dialogs/canvassizeandscale.py @@ -14,8 +14,6 @@ class SizeAndScaleDialog(Dialog): def __init__(self, master, app): """ create an instance for size and scale object - - :param app: main application """ super().__init__(master, app, "Canvas Size and Scale", modal=True) self.canvas = self.app.canvas diff --git a/daemon/core/gui/dialogs/canvaswallpaper.py b/daemon/core/gui/dialogs/canvaswallpaper.py index 62fa8fe5..14e9ad26 100644 --- a/daemon/core/gui/dialogs/canvaswallpaper.py +++ b/daemon/core/gui/dialogs/canvaswallpaper.py @@ -140,8 +140,6 @@ class CanvasWallpaperDialog(Dialog): def click_clear(self): """ delete like shown in image link entry if there is any - - :return: nothing """ # delete entry self.filename.set("") diff --git a/daemon/core/gui/dialogs/colorpicker.py b/daemon/core/gui/dialogs/colorpicker.py index 28d21f42..cf24054d 100644 --- a/daemon/core/gui/dialogs/colorpicker.py +++ b/daemon/core/gui/dialogs/colorpicker.py @@ -31,7 +31,7 @@ class ColorPickerDialog(Dialog): self.draw() self.set_bindings() - def askcolor(self): + def askcolor(self) -> str: self.show() return self.color @@ -175,12 +175,9 @@ class ColorPickerDialog(Dialog): self.color = self.hex.get() self.destroy() - def get_hex(self): + def get_hex(self) -> str: """ convert current RGB values into hex color - - :rtype: str - :return: hex color """ red = self.red_entry.get() blue = self.blue_entry.get() @@ -210,35 +207,31 @@ class ColorPickerDialog(Dialog): self.set_entry(red, green, blue) self.set_scale(red, green, blue) self.display.config(background=hex_code) - self.set_label(red, green, blue) + self.set_label(str(red), str(green), str(blue)) - def scale_callback(self, var, color_var): + def scale_callback(self, var: tk.IntVar, color_var: tk.IntVar): color_var.set(var.get()) self.focus = "rgb" self.update_color() - def set_scale(self, red, green, blue): + def set_scale(self, red: int, green: int, blue: int): self.red_scale.set(red) self.green_scale.set(green) self.blue_scale.set(blue) - def set_entry(self, red, green, blue): + def set_entry(self, red: int, green: int, blue: int): self.red.set(red) self.green.set(green) self.blue.set(blue) - def set_label(self, red, green, blue): + def set_label(self, red: str, green: str, blue: str): self.red_label.configure(background="#%02x%02x%02x" % (int(red), 0, 0)) self.green_label.configure(background="#%02x%02x%02x" % (0, int(green), 0)) self.blue_label.configure(background="#%02x%02x%02x" % (0, 0, int(blue))) - def get_rgb(self, hex_code): + def get_rgb(self, hex_code: str) -> [int, int, int]: """ convert a valid hex code to RGB values - - :param string hex_code: color in hex - :rtype: tuple(int, int, int) - :return: the RGB values """ if len(hex_code) == 4: red = hex_code[1] diff --git a/daemon/core/gui/dialogs/copyserviceconfig.py b/daemon/core/gui/dialogs/copyserviceconfig.py index 68b04d03..39c40ef2 100644 --- a/daemon/core/gui/dialogs/copyserviceconfig.py +++ b/daemon/core/gui/dialogs/copyserviceconfig.py @@ -5,6 +5,7 @@ copy service config dialog import logging import tkinter as tk from tkinter import ttk +from typing import Tuple from core.gui.dialogs.dialog import Dialog from core.gui.themes import FRAME_PAD, PADX @@ -147,7 +148,7 @@ class CopyServiceConfigDialog(Dialog): dialog = ViewConfigDialog(self, self.app, self.node_id, data) dialog.show() - def get_node_service(self, selected): + def get_node_service(self, selected: Tuple[str]) -> [int, str]: service_tree_id = self.tree.parent(selected[0]) service_name = self.tree.item(service_tree_id)["text"] node_tree_id = self.tree.parent(service_tree_id) diff --git a/daemon/core/gui/dialogs/customnodes.py b/daemon/core/gui/dialogs/customnodes.py index 86303a69..1bf2a158 100644 --- a/daemon/core/gui/dialogs/customnodes.py +++ b/daemon/core/gui/dialogs/customnodes.py @@ -71,7 +71,7 @@ class ServicesSelectDialog(Dialog): # trigger group change self.groups.listbox.event_generate("<>") - def handle_group_change(self, event): + def handle_group_change(self, event: tk.Event): selection = self.groups.listbox.curselection() if selection: index = selection[0] @@ -81,7 +81,7 @@ class ServicesSelectDialog(Dialog): checked = name in self.current_services self.services.add(name, checked) - def service_clicked(self, name, var): + def service_clicked(self, name: str, var: tk.BooleanVar): if var.get() and name not in self.current_services: self.current_services.add(name) elif not var.get() and name in self.current_services: diff --git a/daemon/core/gui/dialogs/dialog.py b/daemon/core/gui/dialogs/dialog.py index 3e6d54f6..c392ba04 100644 --- a/daemon/core/gui/dialogs/dialog.py +++ b/daemon/core/gui/dialogs/dialog.py @@ -1,5 +1,6 @@ import tkinter as tk from tkinter import ttk +from typing import Optional from core.gui.images import ImageEnum, Images from core.gui.themes import DIALOG_PAD @@ -30,7 +31,7 @@ class Dialog(tk.Toplevel): self.grab_set() self.wait_window() - def draw_spacer(self, row=None): + def draw_spacer(self, row: Optional[int] = None): frame = ttk.Frame(self.top) frame.grid(row=row, sticky="nsew") frame.rowconfigure(0, weight=1) diff --git a/daemon/core/gui/dialogs/emaneconfig.py b/daemon/core/gui/dialogs/emaneconfig.py index 6f3dedd8..29bb4f74 100644 --- a/daemon/core/gui/dialogs/emaneconfig.py +++ b/daemon/core/gui/dialogs/emaneconfig.py @@ -116,8 +116,6 @@ class EmaneConfigDialog(Dialog): def draw_emane_configuration(self): """ draw the main frame for emane configuration - - :return: nothing """ label = ttk.Label( self.top, @@ -143,8 +141,6 @@ class EmaneConfigDialog(Dialog): def draw_emane_models(self): """ create a combobox that has all the known emane models - - :return: nothing """ frame = ttk.Frame(self.top) frame.grid(sticky="ew", pady=PADY) @@ -210,8 +206,6 @@ class EmaneConfigDialog(Dialog): def click_model_config(self): """ draw emane model configuration - - :return: nothing """ model_name = self.emane_model.get() logging.info("configuring emane model: %s", model_name) @@ -220,12 +214,9 @@ class EmaneConfigDialog(Dialog): ) dialog.show() - def emane_model_change(self, event): + def emane_model_change(self, event: tk.Event): """ update emane model options button - - :param event: - :return: nothing """ model_name = self.emane_model.get() self.emane_model_button.config(text=f"{model_name} options") diff --git a/daemon/core/gui/dialogs/hooks.py b/daemon/core/gui/dialogs/hooks.py index 79741add..97b58c3b 100644 --- a/daemon/core/gui/dialogs/hooks.py +++ b/daemon/core/gui/dialogs/hooks.py @@ -62,11 +62,11 @@ class HookDialog(Dialog): button = ttk.Button(frame, text="Cancel", command=lambda: self.destroy()) button.grid(row=0, column=1, sticky="ew") - def state_change(self, event): + def state_change(self, event: tk.Event): state_name = self.state.get() self.name.set(f"{state_name.lower()}_hook.sh") - def set(self, hook): + def set(self, hook: core_pb2.Hook): self.hook = hook self.name.set(hook.file) self.codetext.text.delete(1.0, tk.END) @@ -140,7 +140,7 @@ class HooksDialog(Dialog): self.edit_button.config(state=tk.DISABLED) self.delete_button.config(state=tk.DISABLED) - def select(self, event): + def select(self, event: tk.Event): if self.listbox.curselection(): index = self.listbox.curselection()[0] self.selected = self.listbox.get(index) diff --git a/daemon/core/gui/dialogs/linkconfig.py b/daemon/core/gui/dialogs/linkconfig.py index 9fd9130b..4c6960a8 100644 --- a/daemon/core/gui/dialogs/linkconfig.py +++ b/daemon/core/gui/dialogs/linkconfig.py @@ -4,6 +4,7 @@ link configuration import logging import tkinter as tk from tkinter import ttk +from typing import Union from core.api.grpc import core_pb2 from core.gui.dialogs.colorpicker import ColorPickerDialog @@ -11,7 +12,7 @@ from core.gui.dialogs.dialog import Dialog from core.gui.themes import PADX, PADY -def get_int(var): +def get_int(var: tk.StringVar) -> Union[int, None]: value = var.get() if value != "": return int(value) @@ -19,7 +20,7 @@ def get_int(var): return None -def get_float(var): +def get_float(var: tk.StringVar) -> Union[int, None]: value = var.get() if value != "": return float(value) @@ -103,7 +104,7 @@ class LinkConfigurationDialog(Dialog): button = ttk.Button(frame, text="Cancel", command=self.destroy) button.grid(row=0, column=1, sticky="ew") - def get_frame(self): + def get_frame(self) -> ttk.Frame: frame = ttk.Frame(self.top) frame.columnconfigure(1, weight=1) if self.is_symmetric: @@ -339,8 +340,6 @@ class LinkConfigurationDialog(Dialog): def load_link_config(self): """ populate link config to the table - - :return: nothing """ width = self.app.canvas.itemcget(self.edge.id, "width") self.width.set(width) diff --git a/daemon/core/gui/dialogs/marker.py b/daemon/core/gui/dialogs/marker.py index 159abd7f..6cc8d9c3 100644 --- a/daemon/core/gui/dialogs/marker.py +++ b/daemon/core/gui/dialogs/marker.py @@ -53,13 +53,13 @@ class MarkerDialog(Dialog): for i in canvas.find_withtag("marker"): canvas.delete(i) - def change_color(self, event): + def change_color(self, event: tk.Event): color_picker = ColorPickerDialog(self, self.app, self.color) color = color_picker.askcolor() event.widget.configure(background=color) self.color = color - def change_thickness(self, event): + def change_thickness(self, event: tk.Event): self.radius = self.marker_thickness.get() def show(self): diff --git a/daemon/core/gui/dialogs/nodeconfig.py b/daemon/core/gui/dialogs/nodeconfig.py index c3dd646a..030099e6 100644 --- a/daemon/core/gui/dialogs/nodeconfig.py +++ b/daemon/core/gui/dialogs/nodeconfig.py @@ -13,7 +13,7 @@ from core.gui.themes import FRAME_PAD, PADX, PADY from core.gui.widgets import ListboxScroll, image_chooser -def mac_auto(is_auto, entry): +def mac_auto(is_auto, entry: ttk.Entry): logging.info("mac auto clicked") if is_auto.get(): logging.info("disabling mac") @@ -217,7 +217,7 @@ class NodeConfigDialog(Dialog): button = ttk.Button(frame, text="Cancel", command=self.destroy) button.grid(row=0, column=1, sticky="ew") - def click_emane_config(self, emane_model, interface_id): + def click_emane_config(self, emane_model: str, interface_id: int): dialog = EmaneModelDialog(self, self.app, self.node, emane_model, interface_id) dialog.show() @@ -248,7 +248,7 @@ class NodeConfigDialog(Dialog): self.canvas_node.redraw() self.destroy() - def interface_select(self, event): + def interface_select(self, event: tk.Event): listbox = event.widget cur = listbox.curselection() if cur: diff --git a/daemon/core/gui/dialogs/nodeservice.py b/daemon/core/gui/dialogs/nodeservice.py index e0d36412..d7eec1fe 100644 --- a/daemon/core/gui/dialogs/nodeservice.py +++ b/daemon/core/gui/dialogs/nodeservice.py @@ -87,7 +87,7 @@ class NodeServiceDialog(Dialog): # trigger group change self.groups.listbox.event_generate("<>") - def handle_group_change(self, event=None): + def handle_group_change(self, event: tk.Event = None): selection = self.groups.listbox.curselection() if selection: index = selection[0] @@ -97,7 +97,7 @@ class NodeServiceDialog(Dialog): checked = name in self.current_services self.services.add(name, checked) - def service_clicked(self, name, var): + def service_clicked(self, name: str, var: tk.IntVar): if var.get() and name not in self.current_services: self.current_services.add(name) elif not var.get() and name in self.current_services: @@ -150,7 +150,7 @@ class NodeServiceDialog(Dialog): checkbutton.invoke() return - def is_custom_service(self, service): + def is_custom_service(self, service: str) -> bool: service_configs = self.app.core.service_configs file_configs = self.app.core.file_configs if self.node_id in service_configs and service in service_configs[self.node_id]: diff --git a/daemon/core/gui/dialogs/observers.py b/daemon/core/gui/dialogs/observers.py index 5f0f1b1e..2a3b8e43 100644 --- a/daemon/core/gui/dialogs/observers.py +++ b/daemon/core/gui/dialogs/observers.py @@ -126,7 +126,7 @@ class ObserverDialog(Dialog): self.save_button.config(state=tk.DISABLED) self.delete_button.config(state=tk.DISABLED) - def handle_observer_change(self, event): + def handle_observer_change(self, event: tk.Event): selection = self.observers.curselection() if selection: self.selected_index = selection[0] diff --git a/daemon/core/gui/dialogs/preferences.py b/daemon/core/gui/dialogs/preferences.py index 6208990a..614b149e 100644 --- a/daemon/core/gui/dialogs/preferences.py +++ b/daemon/core/gui/dialogs/preferences.py @@ -72,7 +72,7 @@ class PreferencesDialog(Dialog): button = ttk.Button(frame, text="Cancel", command=self.destroy) button.grid(row=0, column=1, sticky="ew") - def theme_change(self, event): + def theme_change(self, event: tk.Event): theme = self.theme.get() logging.info("changing theme: %s", theme) self.app.style.theme_use(theme) diff --git a/daemon/core/gui/dialogs/servers.py b/daemon/core/gui/dialogs/servers.py index a0eadec2..30495d5a 100644 --- a/daemon/core/gui/dialogs/servers.py +++ b/daemon/core/gui/dialogs/servers.py @@ -155,7 +155,7 @@ class ServersDialog(Dialog): self.save_button.config(state=tk.DISABLED) self.delete_button.config(state=tk.DISABLED) - def handle_server_change(self, event): + def handle_server_change(self, event: tk.Event): selection = self.servers.curselection() if selection: self.selected_index = selection[0] diff --git a/daemon/core/gui/dialogs/serviceconfig.py b/daemon/core/gui/dialogs/serviceconfig.py index 56c0a4c0..35d30033 100644 --- a/daemon/core/gui/dialogs/serviceconfig.py +++ b/daemon/core/gui/dialogs/serviceconfig.py @@ -1,6 +1,7 @@ "Service configuration dialog" import tkinter as tk from tkinter import ttk +from typing import List import grpc @@ -345,7 +346,7 @@ class ServiceConfigDialog(Dialog): button = ttk.Button(frame, text="Cancel", command=self.destroy) button.grid(row=0, column=3, sticky="ew") - def add_filename(self, event): + def add_filename(self, event: tk.Event): # not worry about it for now return frame_contains_button = event.widget.master @@ -354,7 +355,7 @@ class ServiceConfigDialog(Dialog): if filename not in combobox["values"]: combobox["values"] += (filename,) - def delete_filename(self, event): + def delete_filename(self, event: tk.Event): # not worry about it for now return frame_comntains_button = event.widget.master @@ -364,7 +365,7 @@ class ServiceConfigDialog(Dialog): combobox["values"] = tuple([x for x in combobox["values"] if x != filename]) combobox.set("") - def add_command(self, event): + def add_command(self, event: tk.Event): frame_contains_button = event.widget.master listbox = frame_contains_button.master.grid_slaves(row=1, column=0)[0].listbox command_to_add = frame_contains_button.grid_slaves(row=0, column=0)[0].get() @@ -375,7 +376,7 @@ class ServiceConfigDialog(Dialog): return listbox.insert(tk.END, command_to_add) - def update_entry(self, event): + def update_entry(self, event: tk.Event): listbox = event.widget current_selection = listbox.curselection() if len(current_selection) > 0: @@ -386,7 +387,7 @@ class ServiceConfigDialog(Dialog): entry.delete(0, "end") entry.insert(0, cmd) - def delete_command(self, event): + def delete_command(self, event: tk.Event): button = event.widget frame_contains_button = button.master listbox = frame_contains_button.master.grid_slaves(row=1, column=0)[0].listbox @@ -439,13 +440,13 @@ class ServiceConfigDialog(Dialog): show_grpc_error(e) self.destroy() - def display_service_file_data(self, event): + def display_service_file_data(self, event: tk.Event): combobox = event.widget filename = combobox.get() self.service_file_data.text.delete(1.0, "end") self.service_file_data.text.insert("end", self.temp_service_files[filename]) - def update_temp_service_file_data(self, event): + def update_temp_service_file_data(self, event: tk.Event): scrolledtext = event.widget filename = self.filename_combobox.get() self.temp_service_files[filename] = scrolledtext.get(1.0, "end") @@ -490,7 +491,9 @@ class ServiceConfigDialog(Dialog): dialog = CopyServiceConfigDialog(self, self.app, self.node_id) dialog.show() - def append_commands(self, commands, listbox, to_add): + def append_commands( + self, commands: List[str], listbox: tk.Listbox, to_add: List[str] + ): for cmd in to_add: commands.append(cmd) listbox.insert(tk.END, cmd) diff --git a/daemon/core/gui/dialogs/sessions.py b/daemon/core/gui/dialogs/sessions.py index ad348280..6fa6e04b 100644 --- a/daemon/core/gui/dialogs/sessions.py +++ b/daemon/core/gui/dialogs/sessions.py @@ -1,6 +1,7 @@ import logging import tkinter as tk from tkinter import ttk +from typing import Iterable import grpc @@ -21,7 +22,7 @@ class SessionsDialog(Dialog): self.sessions = self.get_sessions() self.draw() - def get_sessions(self): + def get_sessions(self) -> Iterable[core_pb2.SessionSummary]: try: response = self.app.core.client.get_sessions() logging.info("sessions: %s", response) @@ -40,7 +41,6 @@ class SessionsDialog(Dialog): def draw_description(self): """ write a short description - :return: nothing """ label = ttk.Label( self.top, @@ -129,7 +129,7 @@ class SessionsDialog(Dialog): self.app.core.create_new_session() self.destroy() - def click_select(self, event): + def click_select(self, event: tk.Event): item = self.tree.selection() session_id = int(self.tree.item(item, "text")) self.selected = True @@ -138,8 +138,6 @@ class SessionsDialog(Dialog): def click_connect(self): """ if no session is selected yet, create a new one else join that session - - :return: nothing """ if self.selected and self.selected_id is not None: self.join_session(self.selected_id) @@ -152,8 +150,6 @@ class SessionsDialog(Dialog): """ if no session is currently selected create a new session else shut the selected session down. - - :return: nothing """ if self.selected and self.selected_id is not None: self.shutdown_session(self.selected_id) @@ -162,18 +158,18 @@ class SessionsDialog(Dialog): else: logging.error("querysessiondrawing.py invalid state") - def join_session(self, session_id): + def join_session(self, session_id: int): self.app.statusbar.progress_bar.start(5) task = BackgroundTask(self.app, self.app.core.join_session, args=(session_id,)) task.start() self.destroy() - def on_selected(self, event): + def on_selected(self, event: tk.Event): item = self.tree.selection() sid = int(self.tree.item(item, "text")) self.join_session(sid) - def shutdown_session(self, sid): + def shutdown_session(self, sid: int): self.app.core.stop_session(sid) self.click_new() self.destroy() diff --git a/daemon/core/gui/dialogs/wlanconfig.py b/daemon/core/gui/dialogs/wlanconfig.py index 3ceaa7e8..1d74e3c1 100644 --- a/daemon/core/gui/dialogs/wlanconfig.py +++ b/daemon/core/gui/dialogs/wlanconfig.py @@ -38,8 +38,6 @@ class WlanConfigDialog(Dialog): def draw_apply_buttons(self): """ create node configuration options - - :return: nothing """ frame = ttk.Frame(self.top) frame.grid(sticky="ew") @@ -55,8 +53,6 @@ class WlanConfigDialog(Dialog): def click_apply(self): """ retrieve user's wlan configuration and store the new configuration values - - :return: nothing """ config = self.config_frame.parse_config() self.app.core.wlan_configs[self.node.id] = self.config diff --git a/daemon/core/gui/graph/edges.py b/daemon/core/gui/graph/edges.py index a9653e0c..197929de 100644 --- a/daemon/core/gui/graph/edges.py +++ b/daemon/core/gui/graph/edges.py @@ -14,7 +14,14 @@ EDGE_COLOR = "#ff0000" class CanvasWirelessEdge: - def __init__(self, token: Tuple[int, int], position, src: int, dst: int, canvas): + def __init__( + self, + token: Tuple[int, int], + position: Tuple[int, int, int, int], + src: int, + dst: int, + canvas, + ): self.token = token self.src = src self.dst = dst @@ -35,11 +42,6 @@ class CanvasEdge: def __init__(self, x1: int, y1: int, x2: int, y2: int, src: int, canvas): """ Create an instance of canvas edge object - :param int x1: source x-coord - :param int y1: source y-coord - :param int x2: destination x-coord - :param int y2: destination y-coord - :param int src: source id :param coretk.graph.graph.GraphCanvas canvas: canvas object """ self.src = src @@ -67,7 +69,7 @@ class CanvasEdge: self.link = link self.draw_labels() - def get_coordinates(self): + def get_coordinates(self) -> [int, int, int, int]: x1, y1, x2, y2 = self.canvas.coords(self.id) v1 = x2 - x1 v2 = y2 - y1 @@ -79,7 +81,7 @@ class CanvasEdge: y2 = y2 - uy return x1, y1, x2, y2 - def get_midpoint(self): + def get_midpoint(self) -> [float, float]: x1, y1, x2, y2 = self.canvas.coords(self.id) x = (x1 + x2) / 2 y = (y1 + y2) / 2 @@ -119,8 +121,6 @@ class CanvasEdge: def update_labels(self): """ Move edge labels based on current position. - - :return: nothing """ x1, y1, x2, y2 = self.get_coordinates() self.canvas.coords(self.text_src, x1, y1) @@ -158,7 +158,7 @@ class CanvasEdge: self.canvas.tag_raise(self.src) self.canvas.tag_raise(self.dst) - def is_wireless(self): + def is_wireless(self) -> [bool, bool]: src_node = self.canvas.nodes[self.src] dst_node = self.canvas.nodes[self.dst] src_node_type = src_node.core_node.type @@ -184,7 +184,6 @@ class CanvasEdge: dst_node.add_antenna() elif not is_src_wireless and is_dst_wireless: src_node.add_antenna() - # TODO: remove this? dont allow linking wireless nodes? else: src_node.add_antenna() diff --git a/daemon/core/gui/graph/graph.py b/daemon/core/gui/graph/graph.py index fb3279a5..d8b752b4 100644 --- a/daemon/core/gui/graph/graph.py +++ b/daemon/core/gui/graph/graph.py @@ -1,5 +1,6 @@ import logging import tkinter as tk +from typing import List, Optional from PIL import Image, ImageTk @@ -84,13 +85,11 @@ class CanvasGraph(tk.Canvas): ) self.configure(scrollregion=self.bbox(tk.ALL)) - def reset_and_redraw(self, session): + def reset_and_redraw(self, session: core_pb2.Session): """ Reset the private variables CanvasGraph object, redraw nodes given the new grpc client. - :param core.api.grpc.core_pb2.Session session: session to draw - :return: nothing """ # hide context self.hide_context() @@ -114,8 +113,6 @@ class CanvasGraph(tk.Canvas): def setup_bindings(self): """ Bind any mouse events or hot keys to the matching action - - :return: nothing """ self.bind("", self.click_press) self.bind("", self.click_release) @@ -135,28 +132,28 @@ class CanvasGraph(tk.Canvas): self.context.unpost() self.context = None - def get_actual_coords(self, x, y): + def get_actual_coords(self, x: float, y: float) -> [float, float]: actual_x = (x - self.offset[0]) / self.ratio actual_y = (y - self.offset[1]) / self.ratio return actual_x, actual_y - def get_scaled_coords(self, x, y): + def get_scaled_coords(self, x: float, y: float) -> [float, float]: scaled_x = (x * self.ratio) + self.offset[0] scaled_y = (y * self.ratio) + self.offset[1] return scaled_x, scaled_y - def inside_canvas(self, x, y): + def inside_canvas(self, x: float, y: float) -> [bool, bool]: x1, y1, x2, y2 = self.bbox(self.grid) valid_x = x1 <= x <= x2 valid_y = y1 <= y <= y2 return valid_x and valid_y - def valid_position(self, x1, y1, x2, y2): + def valid_position(self, x1: int, y1: int, x2: int, y2: int) -> [bool, bool]: valid_topleft = self.inside_canvas(x1, y1) valid_bottomright = self.inside_canvas(x2, y2) return valid_topleft and valid_bottomright - def set_throughputs(self, throughputs_event): + def set_throughputs(self, throughputs_event: core_pb2.ThroughputsEvent): for interface_throughput in throughputs_event.interface_throughputs: node_id = interface_throughput.node_id interface_id = interface_throughput.interface_id @@ -174,8 +171,6 @@ class CanvasGraph(tk.Canvas): def draw_grid(self): """ Create grid. - - :return: nothing """ width, height = self.width_and_height() width = int(width) @@ -187,13 +182,12 @@ class CanvasGraph(tk.Canvas): self.tag_lower(tags.GRIDLINE) self.tag_lower(self.grid) - def add_wireless_edge(self, src, dst): + def add_wireless_edge(self, src: CanvasNode, dst: CanvasNode): """ add a wireless edge between 2 canvas nodes :param CanvasNode src: source node :param CanvasNode dst: destination node - :return: nothing """ token = tuple(sorted((src.id, dst.id))) x1, y1 = self.coords(src.id) @@ -206,18 +200,16 @@ class CanvasGraph(tk.Canvas): self.tag_raise(src.id) self.tag_raise(dst.id) - def delete_wireless_edge(self, src, dst): + def delete_wireless_edge(self, src: CanvasNode, dst: CanvasNode): token = tuple(sorted((src.id, dst.id))) edge = self.wireless_edges.pop(token) edge.delete() src.wireless_edges.remove(edge) dst.wireless_edges.remove(edge) - def draw_session(self, session): + def draw_session(self, session: core_pb2.Session): """ Draw existing session. - - :return: nothing """ # draw existing nodes for core_node in session.nodes: @@ -296,25 +288,17 @@ class CanvasGraph(tk.Canvas): for edge in self.edges.values(): edge.reset() - def canvas_xy(self, event): + def canvas_xy(self, event: tk.Event) -> [float, float]: """ Convert window coordinate to canvas coordinate - - :param event: - :rtype: (int, int) - :return: x, y canvas coordinate """ x = self.canvasx(event.x) y = self.canvasy(event.y) return x, y - def get_selected(self, event): + def get_selected(self, event: tk.Event) -> int: """ Retrieve the item id that is on the mouse position - - :param event: mouse event - :rtype: int - :return: the item that the mouse point to """ x, y = self.canvas_xy(event) overlapping = self.find_overlapping(x, y, x, y) @@ -332,7 +316,7 @@ class CanvasGraph(tk.Canvas): return selected - def click_release(self, event): + def click_release(self, event: tk.Event): """ Draw a node or finish drawing an edge according to the current graph mode @@ -380,7 +364,7 @@ class CanvasGraph(tk.Canvas): self.mode = GraphMode.NODE self.selected = None - def handle_edge_release(self, event): + def handle_edge_release(self, event: tk.Event): edge = self.drawing_edge self.drawing_edge = None @@ -417,7 +401,7 @@ class CanvasGraph(tk.Canvas): node_dst.edges.add(edge) self.core.create_link(edge, node_src, node_dst) - def select_object(self, object_id, choose_multiple=False): + def select_object(self, object_id: int, choose_multiple: Optional[bool] = False): """ create a bounding box when a node is selected """ @@ -441,19 +425,17 @@ class CanvasGraph(tk.Canvas): def clear_selection(self): """ Clear current selection boxes. - - :return: nothing """ for _id in self.selection.values(): self.delete(_id) self.selection.clear() - def move_selection(self, object_id, x_offset, y_offset): + def move_selection(self, object_id: int, x_offset: float, y_offset: float): select_id = self.selection.get(object_id) if select_id is not None: self.move(select_id, x_offset, y_offset) - def delete_selection_objects(self): + def delete_selection_objects(self) -> List[CanvasNode]: edges = set() nodes = [] for object_id in self.selection: @@ -499,7 +481,7 @@ class CanvasGraph(tk.Canvas): self.selection.clear() return nodes - def zoom(self, event, factor=None): + def zoom(self, event: tk.Event, factor: Optional[float] = None): if not factor: factor = ZOOM_IN if event.delta > 0 else ZOOM_OUT event.x, event.y = self.canvasx(event.x), self.canvasy(event.y) @@ -517,12 +499,9 @@ class CanvasGraph(tk.Canvas): if self.wallpaper: self.redraw_wallpaper() - def click_press(self, event): + def click_press(self, event: tk.Event): """ Start drawing an edge if mouse click is on a node - - :param event: mouse event - :return: nothing """ x, y = self.canvas_xy(event) if not self.inside_canvas(x, y): @@ -581,7 +560,7 @@ class CanvasGraph(tk.Canvas): self.select_box = shape self.clear_selection() - def ctrl_click(self, event): + def ctrl_click(self, event: tk.Event): # update cursor location x, y = self.canvas_xy(event) if not self.inside_canvas(x, y): @@ -599,12 +578,9 @@ class CanvasGraph(tk.Canvas): ): self.select_object(selected, choose_multiple=True) - def click_motion(self, event): + def click_motion(self, event: tk.Event): """ Redraw drawing edge according to the current position of the mouse - - :param event: mouse event - :return: nothing """ x, y = self.canvas_xy(event) if not self.inside_canvas(x, y): @@ -658,7 +634,7 @@ class CanvasGraph(tk.Canvas): if self.select_box and self.mode == GraphMode.SELECT: self.select_box.shape_motion(x, y) - def click_context(self, event): + def click_context(self, event: tk.Event): logging.info("context event: %s", self.context) if not self.context: selected = self.get_selected(event) @@ -670,24 +646,22 @@ class CanvasGraph(tk.Canvas): else: self.hide_context() - def press_delete(self, event): + def press_delete(self, event: tk.Event): """ delete selected nodes and any data that relates to it - :param event: - :return: """ logging.debug("press delete key") nodes = self.delete_selection_objects() self.core.delete_graph_nodes(nodes) - def double_click(self, event): + def double_click(self, event: tk.Event): selected = self.get_selected(event) if selected is not None and selected in self.shapes: shape = self.shapes[selected] dialog = ShapeDialog(self.app, self.app, shape) dialog.show() - def add_node(self, x, y): + def add_node(self, x: float, y: float) -> CanvasNode: if self.selected is None or self.selected in self.shapes: actual_x, actual_y = self.get_actual_coords(x, y) core_node = self.core.create_node( @@ -701,26 +675,28 @@ class CanvasGraph(tk.Canvas): def width_and_height(self): """ retrieve canvas width and height in pixels - - :return: nothing """ x0, y0, x1, y1 = self.coords(self.grid) canvas_w = abs(x0 - x1) canvas_h = abs(y0 - y1) return canvas_w, canvas_h - def get_wallpaper_image(self): + def get_wallpaper_image(self) -> Image.Image: width = int(self.wallpaper.width * self.ratio) height = int(self.wallpaper.height * self.ratio) image = self.wallpaper.resize((width, height), Image.ANTIALIAS) return image - def draw_wallpaper(self, image, x=None, y=None): + def draw_wallpaper( + self, + image: ImageTk.PhotoImage, + x: Optional[float] = None, + y: Optional[float] = None, + ): if x is None and y is None: x1, y1, x2, y2 = self.bbox(self.grid) x = (x1 + x2) / 2 y = (y1 + y2) / 2 - self.wallpaper_id = self.create_image((x, y), image=image, tags=tags.WALLPAPER) self.wallpaper_drawn = image @@ -748,8 +724,6 @@ class CanvasGraph(tk.Canvas): def wallpaper_center(self): """ place the image at the center of canvas - - :return: nothing """ self.delete(self.wallpaper_id) @@ -773,8 +747,6 @@ class CanvasGraph(tk.Canvas): def wallpaper_scaled(self): """ scale image based on canvas dimension - - :return: nothing """ self.delete(self.wallpaper_id) canvas_w, canvas_h = self.width_and_height() @@ -788,7 +760,7 @@ class CanvasGraph(tk.Canvas): self.redraw_canvas((image.width(), image.height())) self.draw_wallpaper(image) - def redraw_canvas(self, dimensions=None): + def redraw_canvas(self, dimensions: Optional[List[int]] = None): logging.info("redrawing canvas to dimensions: %s", dimensions) # reset scale and move back to original position @@ -836,7 +808,7 @@ class CanvasGraph(tk.Canvas): else: self.itemconfig(tags.GRIDLINE, state=tk.HIDDEN) - def set_wallpaper(self, filename): + def set_wallpaper(self, filename: str): logging.info("setting wallpaper: %s", filename) if filename: img = Image.open(filename) @@ -849,16 +821,12 @@ class CanvasGraph(tk.Canvas): self.wallpaper = None self.wallpaper_file = None - def is_selection_mode(self): + def is_selection_mode(self) -> bool: return self.mode == GraphMode.SELECT - def create_edge(self, source, dest): + def create_edge(self, source: CanvasNode, dest: CanvasNode): """ create an edge between source node and destination node - - :param CanvasNode source: source node - :param CanvasNode dest: destination node - :return: nothing """ if (source.id, dest.id) not in self.edges: pos0 = source.core_node.position diff --git a/daemon/core/gui/graph/node.py b/daemon/core/gui/graph/node.py index a25c06ae..191f6d5f 100644 --- a/daemon/core/gui/graph/node.py +++ b/daemon/core/gui/graph/node.py @@ -20,7 +20,7 @@ NODE_TEXT_OFFSET = 5 class CanvasNode: - def __init__(self, app, x: int, y: int, core_node: core_pb2.Node, image): + def __init__(self, app, x: float, y: float, core_node: core_pb2.Node, image): self.app = app self.canvas = app.canvas self.image = image @@ -70,8 +70,6 @@ class CanvasNode: def delete_antenna(self): """ delete one antenna - - :return: nothing """ if self.antennae: antenna_id = self.antennae.pop() @@ -80,8 +78,6 @@ class CanvasNode: def delete_antennae(self): """ delete all antennas - - :return: nothing """ for antenna_id in self.antennae: self.canvas.delete(antenna_id) diff --git a/daemon/core/gui/graph/shape.py b/daemon/core/gui/graph/shape.py index ba630f5b..7e275ea3 100644 --- a/daemon/core/gui/graph/shape.py +++ b/daemon/core/gui/graph/shape.py @@ -1,4 +1,5 @@ import logging +from typing import List, Optional, Union from core.gui.dialogs.shapemod import ShapeDialog from core.gui.graph import tags @@ -8,16 +9,16 @@ from core.gui.graph.shapeutils import ShapeType class AnnotationData: def __init__( self, - text="", - font="Arial", - font_size=12, - text_color="#000000", - fill_color="", - border_color="#000000", - border_width=1, - bold=False, - italic=False, - underline=False, + text: Optional[str] = "", + font: Optional[str] = "Arial", + font_size: Optional[int] = 12, + text_color: Optional[str] = "#000000", + fill_color: Optional[str] = "", + border_color: Optional[str] = "#000000", + border_width: Optional[int] = 1, + bold: Optional[bool] = False, + italic: Optional[bool] = False, + underline: Optional[bool] = False, ): self.text = text self.font = font @@ -99,7 +100,7 @@ class Shape: logging.error("unknown shape type: %s", self.shape_type) self.created = True - def get_font(self): + def get_font(self) -> List[Union[int, str]]: font = [self.shape_data.font, self.shape_data.font_size] if self.shape_data.bold: font.append("bold") @@ -123,10 +124,10 @@ class Shape: font=font, ) - def shape_motion(self, x1: int, y1: int): + def shape_motion(self, x1: float, y1: float): self.canvas.coords(self.id, self.x1, self.y1, x1, y1) - def shape_complete(self, x, y): + def shape_complete(self, x: float, y: float): for component in tags.ABOVE_SHAPE: self.canvas.tag_raise(component) s = ShapeDialog(self.app, self.app, self) @@ -135,7 +136,7 @@ class Shape: def disappear(self): self.canvas.delete(self.id) - def motion(self, x_offset: int, y_offset: int): + def motion(self, x_offset: float, y_offset: float): original_position = self.canvas.coords(self.id) self.canvas.move(self.id, x_offset, y_offset) coords = self.canvas.coords(self.id) diff --git a/daemon/core/gui/graph/shapeutils.py b/daemon/core/gui/graph/shapeutils.py index 0e2cc29c..ce2b7f96 100644 --- a/daemon/core/gui/graph/shapeutils.py +++ b/daemon/core/gui/graph/shapeutils.py @@ -11,13 +11,13 @@ class ShapeType(enum.Enum): SHAPES = {ShapeType.OVAL, ShapeType.RECTANGLE} -def is_draw_shape(shape_type): +def is_draw_shape(shape_type: ShapeType) -> bool: return shape_type in SHAPES -def is_shape_text(shape_type): +def is_shape_text(shape_type: ShapeType) -> bool: return shape_type == ShapeType.TEXT -def is_marker(shape_type): +def is_marker(shape_type: ShapeType) -> bool: return shape_type == ShapeType.MARKER diff --git a/daemon/core/gui/graph/tooltip.py b/daemon/core/gui/graph/tooltip.py index 3cc5825c..1e9ee317 100644 --- a/daemon/core/gui/graph/tooltip.py +++ b/daemon/core/gui/graph/tooltip.py @@ -1,5 +1,6 @@ import tkinter as tk from tkinter import ttk +from typing import Optional from core.gui.themes import Styles @@ -30,10 +31,10 @@ class CanvasTooltip: self.id = None self.tw = None - def on_enter(self, event=None): + def on_enter(self, event: Optional[tk.Event] = None): self.schedule() - def on_leave(self, event=None): + def on_leave(self, event: Optional[tk.Event] = None): self.unschedule() self.hide() @@ -47,7 +48,7 @@ class CanvasTooltip: if id_: self.canvas.after_cancel(id_) - def show(self, event=None): + def show(self, event: Optional[tk.Event] = None): def tip_pos_calculator(canvas, label, *, tip_delta=(10, 5), pad=(5, 3, 5, 3)): c = canvas s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight() diff --git a/daemon/core/gui/interface.py b/daemon/core/gui/interface.py index fe08b0dd..a9b43220 100644 --- a/daemon/core/gui/interface.py +++ b/daemon/core/gui/interface.py @@ -1,8 +1,10 @@ import logging import random +from typing import Optional, Set from netaddr import IPNetwork +from core.gui.graph.node import CanvasNode from core.gui.nodeutils import NodeUtils @@ -11,7 +13,9 @@ def random_mac(): class InterfaceManager: - def __init__(self, app, address="10.0.0.0", mask=24): + def __init__( + self, app, address: Optional[str] = "10.0.0.0", mask: Optional[int] = 24 + ): self.app = app self.mask = mask self.base_prefix = max(self.mask - 8, 0) @@ -38,7 +42,7 @@ class InterfaceManager: def reset(self): self.current_subnet = None - def get_ips(self, node_id): + def get_ips(self, node_id: int): ip4 = self.current_subnet[node_id] ip6 = ip4.ipv6() prefix = self.current_subnet.prefixlen @@ -48,7 +52,9 @@ class InterfaceManager: def get_subnet(cls, interface): return IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr - def determine_subnet(self, canvas_src_node, canvas_dst_node): + def determine_subnet( + self, canvas_src_node: CanvasNode, canvas_dst_node: CanvasNode + ): src_node = canvas_src_node.core_node dst_node = canvas_dst_node.core_node is_src_container = NodeUtils.is_container_node(src_node.type) @@ -70,7 +76,7 @@ class InterfaceManager: else: logging.info("ignoring subnet change for link between network nodes") - def find_subnet(self, canvas_node, visited=None): + def find_subnet(self, canvas_node: CanvasNode, visited: Optional[Set[int]] = None): logging.info("finding subnet for node: %s", canvas_node.core_node.name) canvas = self.app.canvas cidr = None diff --git a/daemon/core/gui/menuaction.py b/daemon/core/gui/menuaction.py index 8fe9d4b4..ac6cfb32 100644 --- a/daemon/core/gui/menuaction.py +++ b/daemon/core/gui/menuaction.py @@ -32,14 +32,14 @@ class MenuAction: self.app = app self.canvas = app.canvas - def cleanup_old_session(self, quitapp: bool = False): + def cleanup_old_session(self, quitapp: Optional[bool] = False): logging.info("cleaning up old session") self.app.core.stop_session() self.app.core.delete_session() # if quitapp: # self.app.quit() - def prompt_save_running_session(self, quitapp: bool = False): + def prompt_save_running_session(self, quitapp: Optional[bool] = False): """ Prompt use to stop running session before application is closed diff --git a/daemon/core/gui/menubar.py b/daemon/core/gui/menubar.py index b28525ab..abacddbd 100644 --- a/daemon/core/gui/menubar.py +++ b/daemon/core/gui/menubar.py @@ -13,10 +13,6 @@ class Menubar(tk.Menu): def __init__(self, master, app, cnf={}, **kwargs): """ Create a CoreMenubar instance - - :param master: - :param tkinter.Menu menubar: menubar object - :param coretk.app.Application app: application object """ super().__init__(master, cnf, **kwargs) self.master.config(menu=self) @@ -27,8 +23,6 @@ class Menubar(tk.Menu): def draw(self): """ Create core menubar and bind the hot keys to their matching command - - :return: nothing """ self.draw_file_menu() self.draw_edit_menu() @@ -42,8 +36,6 @@ class Menubar(tk.Menu): def draw_file_menu(self): """ Create file menu - - :return: nothing """ menu = tk.Menu(self) menu.add_command( @@ -81,8 +73,6 @@ class Menubar(tk.Menu): def draw_edit_menu(self): """ Create edit menu - - :return: nothing """ menu = tk.Menu(self) menu.add_command(label="Preferences", command=self.menuaction.gui_preferences) @@ -112,8 +102,6 @@ class Menubar(tk.Menu): def draw_canvas_menu(self): """ Create canvas menu - - :return: nothing """ menu = tk.Menu(self) menu.add_command( @@ -136,8 +124,6 @@ class Menubar(tk.Menu): def draw_view_menu(self): """ Create view menu - - :return: nothing """ view_menu = tk.Menu(self) self.create_show_menu(view_menu) @@ -152,9 +138,6 @@ class Menubar(tk.Menu): def create_show_menu(self, view_menu: tk.Menu): """ Create the menu items in View/Show - - :param tkinter.Menu view_menu: the view menu - :return: nothing """ menu = tk.Menu(view_menu) menu.add_command(label="All", state=tk.DISABLED) @@ -172,9 +155,6 @@ class Menubar(tk.Menu): def create_experimental_menu(self, tools_menu: tk.Menu): """ Create experimental menu item and the sub menu items inside - - :param tkinter.Menu tools_menu: tools menu - :return: nothing """ menu = tk.Menu(tools_menu) menu.add_command(label="Plugins...", state=tk.DISABLED) @@ -185,9 +165,6 @@ class Menubar(tk.Menu): def create_random_menu(self, topology_generator_menu: tk.Menu): """ Create random menu item and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology generator menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) # list of number of random nodes to create @@ -200,9 +177,6 @@ class Menubar(tk.Menu): def create_grid_menu(self, topology_generator_menu: tk.Menu): """ Create grid menu item and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology_generator_menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) # list of number of nodes to create @@ -215,9 +189,6 @@ class Menubar(tk.Menu): def create_connected_grid_menu(self, topology_generator_menu: tk.Menu): """ Create connected grid menu items and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology generator menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) for i in range(1, 11, 1): @@ -232,9 +203,6 @@ class Menubar(tk.Menu): def create_chain_menu(self, topology_generator_menu: tk.Menu): """ Create chain menu item and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology generator menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) # number of nodes to create @@ -247,9 +215,6 @@ class Menubar(tk.Menu): def create_star_menu(self, topology_generator_menu: tk.Menu): """ Create star menu item and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology generator menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) for i in range(3, 26, 1): @@ -260,9 +225,6 @@ class Menubar(tk.Menu): def create_cycle_menu(self, topology_generator_menu: tk.Menu): """ Create cycle menu item and the sub items inside - - :param tkinter.Menu topology_generator_menu: topology generator menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) for i in range(3, 25, 1): @@ -273,9 +235,6 @@ class Menubar(tk.Menu): def create_wheel_menu(self, topology_generator_menu: tk.Menu): """ Create wheel menu item and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology generator menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) for i in range(4, 26, 1): @@ -286,9 +245,6 @@ class Menubar(tk.Menu): def create_cube_menu(self, topology_generator_menu: tk.Menu): """ Create cube menu item and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology generator menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) for i in range(2, 7, 1): @@ -299,9 +255,6 @@ class Menubar(tk.Menu): def create_clique_menu(self, topology_generator_menu: tk.Menu): """ Create clique menu item and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology generator menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) for i in range(3, 25, 1): @@ -312,9 +265,6 @@ class Menubar(tk.Menu): def create_bipartite_menu(self, topology_generator_menu: tk.Menu): """ Create bipartite menu item and the sub menu items inside - - :param tkinter.Menu topology_generator_menu: topology_generator_menu - :return: nothing """ menu = tk.Menu(topology_generator_menu) temp = 24 @@ -331,10 +281,6 @@ class Menubar(tk.Menu): def create_topology_generator_menu(self, tools_menu: tk.Menu): """ Create topology menu item and its sub menu items - - :param tkinter.Menu tools_menu: tools menu - - :return: nothing """ menu = tk.Menu(tools_menu) self.create_random_menu(menu) @@ -352,8 +298,6 @@ class Menubar(tk.Menu): def draw_tools_menu(self): """ Create tools menu - - :return: nothing """ menu = tk.Menu(self) menu.add_command(label="Auto rearrange all", state=tk.DISABLED) @@ -374,9 +318,6 @@ class Menubar(tk.Menu): def create_observer_widgets_menu(self, widget_menu: tk.Menu): """ Create observer widget menu item and create the sub menu items inside - - :param tkinter.Menu widget_menu: widget_menu - :return: nothing """ var = tk.StringVar(value="none") menu = tk.Menu(widget_menu) @@ -412,9 +353,6 @@ class Menubar(tk.Menu): def create_adjacency_menu(self, widget_menu: tk.Menu): """ Create adjacency menu item and the sub menu items inside - - :param tkinter.Menu widget_menu: widget menu - :return: nothing """ menu = tk.Menu(widget_menu) menu.add_command(label="OSPFv2", state=tk.DISABLED) @@ -426,8 +364,6 @@ class Menubar(tk.Menu): def draw_widgets_menu(self): """ Create widget menu - - :return: nothing """ menu = tk.Menu(self) self.create_observer_widgets_menu(menu) @@ -443,8 +379,6 @@ class Menubar(tk.Menu): def draw_session_menu(self): """ Create session menu - - :return: nothing """ menu = tk.Menu(self) menu.add_command( @@ -461,8 +395,6 @@ class Menubar(tk.Menu): def draw_help_menu(self): """ Create help menu - - :return: nothing """ menu = tk.Menu(self) menu.add_command( diff --git a/daemon/core/gui/nodeutils.py b/daemon/core/gui/nodeutils.py index 9867998a..71674325 100644 --- a/daemon/core/gui/nodeutils.py +++ b/daemon/core/gui/nodeutils.py @@ -53,31 +53,31 @@ class NodeUtils: ANTENNA_ICON = None @classmethod - def is_ignore_node(cls, node_type): + def is_ignore_node(cls, node_type) -> bool: return node_type in cls.IGNORE_NODES @classmethod - def is_container_node(cls, node_type): + def is_container_node(cls, node_type) -> bool: return node_type in cls.CONTAINER_NODES @classmethod - def is_model_node(cls, node_type): + def is_model_node(cls, node_type) -> bool: return node_type == NodeType.DEFAULT @classmethod - def is_image_node(cls, node_type): + def is_image_node(cls, node_type) -> bool: return node_type in cls.IMAGE_NODES @classmethod - def is_wireless_node(cls, node_type): + def is_wireless_node(cls, node_type) -> bool: return node_type in cls.WIRELESS_NODES @classmethod - def is_rj45_node(cls, node_type): + def is_rj45_node(cls, node_type) -> bool: return node_type in cls.RJ45_NODES @classmethod - def node_icon(cls, node_type, model): + def node_icon(cls, node_type, model: str) -> bool: if model == "": model = None return cls.NODE_ICONS[(node_type, model)] diff --git a/daemon/core/gui/statusbar.py b/daemon/core/gui/statusbar.py index a3e6228a..d0fac322 100644 --- a/daemon/core/gui/statusbar.py +++ b/daemon/core/gui/statusbar.py @@ -1,4 +1,6 @@ -"status bar" +""" +status bar +""" import tkinter as tk from tkinter import ttk diff --git a/daemon/core/gui/toolbar.py b/daemon/core/gui/toolbar.py index fbf50695..a879eacc 100644 --- a/daemon/core/gui/toolbar.py +++ b/daemon/core/gui/toolbar.py @@ -4,6 +4,9 @@ import tkinter as tk from functools import partial from tkinter import messagebox, ttk from tkinter.font import Font +from typing import Callable + +from PIL import ImageTk from core.api.grpc import core_pb2 from core.gui.dialogs.customnodes import CustomNodesDialog @@ -196,7 +199,9 @@ class Toolbar(ttk.Frame): self.wait_window(picker) self.app.unbind_all("") - def create_picker_button(self, image, func, frame: ttk.Frame, label: str): + def create_picker_button( + self, image: ImageTk.PhotoImage, func: Callable, frame: ttk.Frame, label: str + ): """ Create button and put it on the frame @@ -204,7 +209,6 @@ class Toolbar(ttk.Frame): :param func: the command that is executed when button is clicked :param tkinter.Frame frame: frame that contains the button :param str label: button label - :return: nothing """ button = ttk.Button( frame, image=image, text=label, compound=tk.TOP, style=Styles.picker_button @@ -213,7 +217,9 @@ class Toolbar(ttk.Frame): button.bind("", lambda e: func()) button.grid(pady=1) - def create_button(self, frame: ttk.Frame, image, func, tooltip: str): + def create_button( + self, frame: ttk.Frame, image: ImageTk.PhotoImage, func: Callable, tooltip: str + ): button = ttk.Button(frame, image=image, command=func) button.image = image button.grid(sticky="ew") @@ -234,8 +240,6 @@ class Toolbar(ttk.Frame): """ Start session handler redraw buttons, send node and link messages to grpc server. - - :return: nothing """ self.app.canvas.hide_context() self.app.statusbar.progress_bar.start(5) @@ -299,8 +303,6 @@ class Toolbar(ttk.Frame): def create_node_button(self): """ Create network layer button - - :return: nothing """ image = icon(ImageEnum.ROUTER) self.node_button = ttk.Button( @@ -313,8 +315,6 @@ class Toolbar(ttk.Frame): def draw_network_picker(self): """ Draw the options for link-layer button. - - :return: nothing """ self.hide_pickers() self.network_picker = ttk.Frame(self.master) @@ -338,8 +338,6 @@ class Toolbar(ttk.Frame): """ Create link-layer node button and the options that represent different link-layer node types. - - :return: nothing """ image = icon(ImageEnum.HUB) self.network_button = ttk.Button( @@ -352,8 +350,6 @@ class Toolbar(ttk.Frame): def draw_annotation_picker(self): """ Draw the options for marker button. - - :return: nothing """ self.hide_pickers() self.annotation_picker = ttk.Frame(self.master) @@ -380,8 +376,6 @@ class Toolbar(ttk.Frame): def create_annotation_button(self): """ Create marker button and options that represent different marker types - - :return: nothing """ image = icon(ImageEnum.MARKER) self.annotation_button = ttk.Button( @@ -418,8 +412,6 @@ class Toolbar(ttk.Frame): def click_stop(self): """ redraw buttons on the toolbar, send node and link messages to grpc server - - :return: nothing """ self.app.canvas.hide_context() self.app.statusbar.progress_bar.start(5) diff --git a/daemon/core/gui/validation.py b/daemon/core/gui/validation.py index c3b42cbc..aef8b09e 100644 --- a/daemon/core/gui/validation.py +++ b/daemon/core/gui/validation.py @@ -40,7 +40,7 @@ class InputValidation: if value == "": event.widget.insert(tk.END, default) - def check_positive_int(self, s: str): + def check_positive_int(self, s: str) -> bool: if len(s) == 0: return True try: @@ -51,7 +51,7 @@ class InputValidation: except ValueError: return False - def check_positive_float(self, s: str): + def check_positive_float(self, s: str) -> bool: if len(s) == 0: return True try: @@ -62,7 +62,7 @@ class InputValidation: except ValueError: return False - def check_node_name(self, s: str): + def check_node_name(self, s: str) -> bool: if len(s) < 0: return False if len(s) == 0: @@ -72,7 +72,7 @@ class InputValidation: return False return True - def check_canvas_int(self, s: str): + def check_canvas_int(self, s: str) -> bool: if len(s) == 0: return True try: @@ -83,7 +83,7 @@ class InputValidation: except ValueError: return False - def check_canvas_float(self, s: str): + def check_canvas_float(self, s: str) -> bool: if not s: return True try: @@ -94,7 +94,7 @@ class InputValidation: except ValueError: return False - def check_ip4(self, s: str): + def check_ip4(self, s: str) -> bool: if not s: return True pat = re.compile("^([0-9]+[.])*[0-9]*$") @@ -113,7 +113,7 @@ class InputValidation: else: return False - def check_rbg(self, s: str): + def check_rbg(self, s: str) -> bool: if not s: return True if s.startswith("0") and len(s) >= 2: @@ -127,7 +127,7 @@ class InputValidation: except ValueError: return False - def check_hex(self, s: str): + def check_hex(self, s: str) -> bool: if not s: return True pat = re.compile("^([#]([0-9]|[a-f])+)$|^[#]$") diff --git a/daemon/core/gui/widgets.py b/daemon/core/gui/widgets.py index d5257533..dc395023 100644 --- a/daemon/core/gui/widgets.py +++ b/daemon/core/gui/widgets.py @@ -1,6 +1,7 @@ import logging import tkinter as tk from functools import partial +from pathlib import PosixPath from tkinter import filedialog, font, ttk from core.api.grpc import core_pb2 @@ -19,7 +20,7 @@ INT_TYPES = { } -def file_button_click(value, parent): +def file_button_click(value: tk.StringVar, parent: tk.Widget): file_path = filedialog.askopenfilename(title="Select File", parent=parent) if file_path: value.set(file_path) @@ -49,13 +50,13 @@ class FrameScroll(ttk.Frame): self.frame.bind("", self._configure_frame) self.canvas.bind("", self._configure_canvas) - def _configure_frame(self, event): + def _configure_frame(self, event: tk.Event): req_width = self.frame.winfo_reqwidth() if req_width != self.canvas.winfo_reqwidth(): self.canvas.configure(width=req_width) self.canvas.configure(scrollregion=self.canvas.bbox("all")) - def _configure_canvas(self, event): + def _configure_canvas(self, event: tk.Event): self.canvas.itemconfig(self.frame_id, width=event.width) def clear(self): @@ -238,7 +239,7 @@ class Spinbox(ttk.Entry): self.tk.call(self._w, "set", value) -def image_chooser(parent, path): +def image_chooser(parent: tk.Widget, path: PosixPath): return filedialog.askopenfilename( parent=parent, initialdir=str(path),