gui: updated core.gui to not use deprecated type hinting

This commit is contained in:
Blake Harnden 2023-04-13 15:53:16 -07:00
parent 69f05a6712
commit e7351b594d
40 changed files with 268 additions and 257 deletions

View file

@ -3,7 +3,7 @@ import math
import tkinter as tk import tkinter as tk
from tkinter import PhotoImage, font, messagebox, ttk from tkinter import PhotoImage, font, messagebox, ttk
from tkinter.ttk import Progressbar from tkinter.ttk import Progressbar
from typing import Any, Dict, Optional, Type from typing import Any, Optional
import grpc import grpc
@ -45,7 +45,7 @@ class Application(ttk.Frame):
self.show_infobar: tk.BooleanVar = tk.BooleanVar(value=False) self.show_infobar: tk.BooleanVar = tk.BooleanVar(value=False)
# fonts # fonts
self.fonts_size: Dict[str, int] = {} self.fonts_size: dict[str, int] = {}
self.icon_text_font: Optional[font.Font] = None self.icon_text_font: Optional[font.Font] = None
self.edge_font: Optional[font.Font] = None self.edge_font: Optional[font.Font] = None
@ -145,7 +145,7 @@ class Application(ttk.Frame):
self.statusbar = StatusBar(self.right_frame, self) self.statusbar = StatusBar(self.right_frame, self)
self.statusbar.grid(sticky=tk.EW, columnspan=2) self.statusbar.grid(sticky=tk.EW, columnspan=2)
def display_info(self, frame_class: Type[InfoFrameBase], **kwargs: Any) -> None: def display_info(self, frame_class: type[InfoFrameBase], **kwargs: Any) -> None:
if not self.show_infobar.get(): if not self.show_infobar.get():
return return
self.clear_info() self.clear_info()

View file

@ -1,7 +1,7 @@
import os import os
import shutil import shutil
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Type from typing import Optional
import yaml import yaml
@ -26,7 +26,7 @@ LOCAL_XMLS_PATH: Path = DATA_PATH.joinpath("xmls").absolute()
LOCAL_MOBILITY_PATH: Path = DATA_PATH.joinpath("mobility").absolute() LOCAL_MOBILITY_PATH: Path = DATA_PATH.joinpath("mobility").absolute()
# configuration data # configuration data
TERMINALS: Dict[str, str] = { TERMINALS: dict[str, str] = {
"xterm": "xterm -e", "xterm": "xterm -e",
"aterm": "aterm -e", "aterm": "aterm -e",
"eterm": "eterm -e", "eterm": "eterm -e",
@ -36,7 +36,7 @@ TERMINALS: Dict[str, str] = {
"xfce4-terminal": "xfce4-terminal -x", "xfce4-terminal": "xfce4-terminal -x",
"gnome-terminal": "gnome-terminal --window --", "gnome-terminal": "gnome-terminal --window --",
} }
EDITORS: List[str] = ["$EDITOR", "vim", "emacs", "gedit", "nano", "vi"] EDITORS: list[str] = ["$EDITOR", "vim", "emacs", "gedit", "nano", "vi"]
class IndentDumper(yaml.Dumper): class IndentDumper(yaml.Dumper):
@ -46,17 +46,17 @@ class IndentDumper(yaml.Dumper):
class CustomNode(yaml.YAMLObject): class CustomNode(yaml.YAMLObject):
yaml_tag: str = "!CustomNode" yaml_tag: str = "!CustomNode"
yaml_loader: Type[yaml.SafeLoader] = yaml.SafeLoader yaml_loader: type[yaml.SafeLoader] = yaml.SafeLoader
def __init__(self, name: str, image: str, services: List[str]) -> None: def __init__(self, name: str, image: str, services: list[str]) -> None:
self.name: str = name self.name: str = name
self.image: str = image self.image: str = image
self.services: List[str] = services self.services: list[str] = services
class CoreServer(yaml.YAMLObject): class CoreServer(yaml.YAMLObject):
yaml_tag: str = "!CoreServer" yaml_tag: str = "!CoreServer"
yaml_loader: Type[yaml.SafeLoader] = yaml.SafeLoader yaml_loader: type[yaml.SafeLoader] = yaml.SafeLoader
def __init__(self, name: str, address: str) -> None: def __init__(self, name: str, address: str) -> None:
self.name: str = name self.name: str = name
@ -65,7 +65,7 @@ class CoreServer(yaml.YAMLObject):
class Observer(yaml.YAMLObject): class Observer(yaml.YAMLObject):
yaml_tag: str = "!Observer" yaml_tag: str = "!Observer"
yaml_loader: Type[yaml.SafeLoader] = yaml.SafeLoader yaml_loader: type[yaml.SafeLoader] = yaml.SafeLoader
def __init__(self, name: str, cmd: str) -> None: def __init__(self, name: str, cmd: str) -> None:
self.name: str = name self.name: str = name
@ -74,7 +74,7 @@ class Observer(yaml.YAMLObject):
class PreferencesConfig(yaml.YAMLObject): class PreferencesConfig(yaml.YAMLObject):
yaml_tag: str = "!PreferencesConfig" yaml_tag: str = "!PreferencesConfig"
yaml_loader: Type[yaml.SafeLoader] = yaml.SafeLoader yaml_loader: type[yaml.SafeLoader] = yaml.SafeLoader
def __init__( def __init__(
self, self,
@ -95,7 +95,7 @@ class PreferencesConfig(yaml.YAMLObject):
class LocationConfig(yaml.YAMLObject): class LocationConfig(yaml.YAMLObject):
yaml_tag: str = "!LocationConfig" yaml_tag: str = "!LocationConfig"
yaml_loader: Type[yaml.SafeLoader] = yaml.SafeLoader yaml_loader: type[yaml.SafeLoader] = yaml.SafeLoader
def __init__( def __init__(
self, self,
@ -118,17 +118,17 @@ class LocationConfig(yaml.YAMLObject):
class IpConfigs(yaml.YAMLObject): class IpConfigs(yaml.YAMLObject):
yaml_tag: str = "!IpConfigs" yaml_tag: str = "!IpConfigs"
yaml_loader: Type[yaml.SafeLoader] = yaml.SafeLoader yaml_loader: type[yaml.SafeLoader] = yaml.SafeLoader
def __init__(self, **kwargs) -> None: def __init__(self, **kwargs) -> None:
self.__setstate__(kwargs) self.__setstate__(kwargs)
def __setstate__(self, kwargs): def __setstate__(self, kwargs):
self.ip4s: List[str] = kwargs.get( self.ip4s: list[str] = kwargs.get(
"ip4s", ["10.0.0.0", "192.168.0.0", "172.16.0.0"] "ip4s", ["10.0.0.0", "192.168.0.0", "172.16.0.0"]
) )
self.ip4: str = kwargs.get("ip4", self.ip4s[0]) self.ip4: str = kwargs.get("ip4", self.ip4s[0])
self.ip6s: List[str] = kwargs.get("ip6s", ["2001::", "2002::", "a::"]) self.ip6s: list[str] = kwargs.get("ip6s", ["2001::", "2002::", "a::"])
self.ip6: str = kwargs.get("ip6", self.ip6s[0]) self.ip6: str = kwargs.get("ip6", self.ip6s[0])
self.enable_ip4: bool = kwargs.get("enable_ip4", True) self.enable_ip4: bool = kwargs.get("enable_ip4", True)
self.enable_ip6: bool = kwargs.get("enable_ip6", True) self.enable_ip6: bool = kwargs.get("enable_ip6", True)
@ -136,16 +136,16 @@ class IpConfigs(yaml.YAMLObject):
class GuiConfig(yaml.YAMLObject): class GuiConfig(yaml.YAMLObject):
yaml_tag: str = "!GuiConfig" yaml_tag: str = "!GuiConfig"
yaml_loader: Type[yaml.SafeLoader] = yaml.SafeLoader yaml_loader: type[yaml.SafeLoader] = yaml.SafeLoader
def __init__( def __init__(
self, self,
preferences: PreferencesConfig = None, preferences: PreferencesConfig = None,
location: LocationConfig = None, location: LocationConfig = None,
servers: List[CoreServer] = None, servers: list[CoreServer] = None,
nodes: List[CustomNode] = None, nodes: list[CustomNode] = None,
recentfiles: List[str] = None, recentfiles: list[str] = None,
observers: List[Observer] = None, observers: list[Observer] = None,
scale: float = 1.0, scale: float = 1.0,
ips: IpConfigs = None, ips: IpConfigs = None,
mac: str = "00:00:00:aa:00:00", mac: str = "00:00:00:aa:00:00",
@ -158,16 +158,16 @@ class GuiConfig(yaml.YAMLObject):
self.location: LocationConfig = location self.location: LocationConfig = location
if servers is None: if servers is None:
servers = [] servers = []
self.servers: List[CoreServer] = servers self.servers: list[CoreServer] = servers
if nodes is None: if nodes is None:
nodes = [] nodes = []
self.nodes: List[CustomNode] = nodes self.nodes: list[CustomNode] = nodes
if recentfiles is None: if recentfiles is None:
recentfiles = [] recentfiles = []
self.recentfiles: List[str] = recentfiles self.recentfiles: list[str] = recentfiles
if observers is None: if observers is None:
observers = [] observers = []
self.observers: List[Observer] = observers self.observers: list[Observer] = observers
self.scale: float = scale self.scale: float = scale
if ips is None: if ips is None:
ips = IpConfigs() ips = IpConfigs()

View file

@ -6,9 +6,10 @@ import json
import logging import logging
import os import os
import tkinter as tk import tkinter as tk
from collections.abc import Iterable
from pathlib import Path from pathlib import Path
from tkinter import messagebox from tkinter import messagebox
from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Tuple from typing import TYPE_CHECKING, Optional
import grpc import grpc
@ -55,7 +56,7 @@ GUI_SOURCE = "gui"
CPU_USAGE_DELAY = 3 CPU_USAGE_DELAY = 3
def to_dict(config: Dict[str, ConfigOption]) -> Dict[str, str]: def to_dict(config: dict[str, ConfigOption]) -> dict[str, str]:
return {x: y.value for x, y in config.items()} return {x: y.value for x, y in config.items()}
@ -74,26 +75,26 @@ class CoreClient:
self.show_throughputs: tk.BooleanVar = tk.BooleanVar(value=False) self.show_throughputs: tk.BooleanVar = tk.BooleanVar(value=False)
# global service settings # global service settings
self.services: Dict[str, Set[str]] = {} self.services: dict[str, set[str]] = {}
self.config_services_groups: Dict[str, Set[str]] = {} self.config_services_groups: dict[str, set[str]] = {}
self.config_services: Dict[str, ConfigService] = {} self.config_services: dict[str, ConfigService] = {}
# loaded configuration data # loaded configuration data
self.emane_models: List[str] = [] self.emane_models: list[str] = []
self.servers: Dict[str, CoreServer] = {} self.servers: dict[str, CoreServer] = {}
self.custom_nodes: Dict[str, NodeDraw] = {} self.custom_nodes: dict[str, NodeDraw] = {}
self.custom_observers: Dict[str, Observer] = {} self.custom_observers: dict[str, Observer] = {}
self.read_config() self.read_config()
# helpers # helpers
self.iface_to_edge: Dict[Tuple[int, ...], CanvasEdge] = {} self.iface_to_edge: dict[tuple[int, ...], CanvasEdge] = {}
self.ifaces_manager: InterfaceManager = InterfaceManager(self.app) self.ifaces_manager: InterfaceManager = InterfaceManager(self.app)
self.observer: Optional[str] = None self.observer: Optional[str] = None
# session data # session data
self.mobility_players: Dict[int, MobilityPlayer] = {} self.mobility_players: dict[int, MobilityPlayer] = {}
self.canvas_nodes: Dict[int, CanvasNode] = {} self.canvas_nodes: dict[int, CanvasNode] = {}
self.links: Dict[str, CanvasEdge] = {} self.links: dict[str, CanvasEdge] = {}
self.handling_throughputs: Optional[grpc.Future] = None self.handling_throughputs: Optional[grpc.Future] = None
self.handling_cpu_usage: Optional[grpc.Future] = None self.handling_cpu_usage: Optional[grpc.Future] = None
self.handling_events: Optional[grpc.Future] = None self.handling_events: Optional[grpc.Future] = None
@ -372,7 +373,7 @@ class CoreClient:
# existing session # existing session
sessions = self.client.get_sessions() sessions = self.client.get_sessions()
if session_id: if session_id:
session_ids = set(x.id for x in sessions) session_ids = {x.id for x in sessions}
if session_id not in session_ids: if session_id not in session_ids:
self.app.show_error( self.app.show_error(
"Join Session Error", "Join Session Error",
@ -401,7 +402,7 @@ class CoreClient:
except grpc.RpcError as e: except grpc.RpcError as e:
self.app.show_grpc_exception("Edit Node Error", e) self.app.show_grpc_exception("Edit Node Error", e)
def get_links(self, definition: bool = False) -> List[Link]: def get_links(self, definition: bool = False) -> list[Link]:
if not definition: if not definition:
self.ifaces_manager.set_macs([x.link for x in self.links.values()]) self.ifaces_manager.set_macs([x.link for x in self.links.values()])
links = [] links = []
@ -419,7 +420,7 @@ class CoreClient:
links.append(edge.asymmetric_link) links.append(edge.asymmetric_link)
return links return links
def start_session(self, definition: bool = False) -> Tuple[bool, List[str]]: def start_session(self, definition: bool = False) -> tuple[bool, list[str]]:
self.session.links = self.get_links(definition) self.session.links = self.get_links(definition)
self.session.metadata = self.get_metadata() self.session.metadata = self.get_metadata()
self.session.servers.clear() self.session.servers.clear()
@ -461,7 +462,7 @@ class CoreClient:
self.mobility_players[node.id] = mobility_player self.mobility_players[node.id] = mobility_player
mobility_player.show() mobility_player.show()
def get_metadata(self) -> Dict[str, str]: def get_metadata(self) -> dict[str, str]:
# create canvas data # create canvas data
canvas_config = self.app.manager.get_metadata() canvas_config = self.app.manager.get_metadata()
canvas_config = json.dumps(canvas_config) canvas_config = json.dumps(canvas_config)
@ -652,7 +653,7 @@ class CoreClient:
self.session.nodes[node.id] = node self.session.nodes[node.id] = node
return node return node
def deleted_canvas_nodes(self, canvas_nodes: List[CanvasNode]) -> None: def deleted_canvas_nodes(self, canvas_nodes: list[CanvasNode]) -> None:
""" """
remove the nodes selected by the user and anything related to that node remove the nodes selected by the user and anything related to that node
such as link, configurations, interfaces such as link, configurations, interfaces
@ -680,7 +681,7 @@ class CoreClient:
dst_iface_id = edge.link.iface2.id dst_iface_id = edge.link.iface2.id
self.iface_to_edge[(dst_node.id, dst_iface_id)] = edge self.iface_to_edge[(dst_node.id, dst_iface_id)] = edge
def get_wlan_configs(self) -> List[Tuple[int, Dict[str, str]]]: def get_wlan_configs(self) -> list[tuple[int, dict[str, str]]]:
configs = [] configs = []
for node in self.session.nodes.values(): for node in self.session.nodes.values():
if node.type != NodeType.WIRELESS_LAN: if node.type != NodeType.WIRELESS_LAN:
@ -691,7 +692,7 @@ class CoreClient:
configs.append((node.id, config)) configs.append((node.id, config))
return configs return configs
def get_mobility_configs(self) -> List[Tuple[int, Dict[str, str]]]: def get_mobility_configs(self) -> list[tuple[int, dict[str, str]]]:
configs = [] configs = []
for node in self.session.nodes.values(): for node in self.session.nodes.values():
if not nutils.is_mobility(node): if not nutils.is_mobility(node):
@ -702,7 +703,7 @@ class CoreClient:
configs.append((node.id, config)) configs.append((node.id, config))
return configs return configs
def get_emane_model_configs(self) -> List[EmaneModelConfig]: def get_emane_model_configs(self) -> list[EmaneModelConfig]:
configs = [] configs = []
for node in self.session.nodes.values(): for node in self.session.nodes.values():
for key, config in node.emane_model_configs.items(): for key, config in node.emane_model_configs.items():
@ -716,7 +717,7 @@ class CoreClient:
configs.append(config) configs.append(config)
return configs return configs
def get_service_configs(self) -> List[ServiceConfig]: def get_service_configs(self) -> list[ServiceConfig]:
configs = [] configs = []
for node in self.session.nodes.values(): for node in self.session.nodes.values():
if not nutils.is_container(node): if not nutils.is_container(node):
@ -736,7 +737,7 @@ class CoreClient:
configs.append(config) configs.append(config)
return configs return configs
def get_service_file_configs(self) -> List[ServiceFileConfig]: def get_service_file_configs(self) -> list[ServiceFileConfig]:
configs = [] configs = []
for node in self.session.nodes.values(): for node in self.session.nodes.values():
if not nutils.is_container(node): if not nutils.is_container(node):
@ -749,12 +750,12 @@ class CoreClient:
configs.append(config) configs.append(config)
return configs return configs
def get_config_service_rendered(self, node_id: int, name: str) -> Dict[str, str]: def get_config_service_rendered(self, node_id: int, name: str) -> dict[str, str]:
return self.client.get_config_service_rendered(self.session.id, node_id, name) return self.client.get_config_service_rendered(self.session.id, node_id, name)
def get_config_service_configs_proto( def get_config_service_configs_proto(
self, self,
) -> List[configservices_pb2.ConfigServiceConfig]: ) -> list[configservices_pb2.ConfigServiceConfig]:
config_service_protos = [] config_service_protos = []
for node in self.session.nodes.values(): for node in self.session.nodes.values():
if not nutils.is_container(node): if not nutils.is_container(node):
@ -776,7 +777,7 @@ class CoreClient:
_, output = self.client.node_command(self.session.id, node_id, self.observer) _, output = self.client.node_command(self.session.id, node_id, self.observer)
return output return output
def get_wlan_config(self, node_id: int) -> Dict[str, ConfigOption]: def get_wlan_config(self, node_id: int) -> dict[str, ConfigOption]:
config = self.client.get_wlan_config(self.session.id, node_id) config = self.client.get_wlan_config(self.session.id, node_id)
logger.debug( logger.debug(
"get wlan configuration from node %s, result configuration: %s", "get wlan configuration from node %s, result configuration: %s",
@ -785,10 +786,10 @@ class CoreClient:
) )
return config return config
def get_wireless_config(self, node_id: int) -> Dict[str, ConfigOption]: def get_wireless_config(self, node_id: int) -> dict[str, ConfigOption]:
return self.client.get_wireless_config(self.session.id, node_id) return self.client.get_wireless_config(self.session.id, node_id)
def get_mobility_config(self, node_id: int) -> Dict[str, ConfigOption]: def get_mobility_config(self, node_id: int) -> dict[str, ConfigOption]:
config = self.client.get_mobility_config(self.session.id, node_id) config = self.client.get_mobility_config(self.session.id, node_id)
logger.debug( logger.debug(
"get mobility config from node %s, result configuration: %s", "get mobility config from node %s, result configuration: %s",
@ -799,7 +800,7 @@ class CoreClient:
def get_emane_model_config( def get_emane_model_config(
self, node_id: int, model: str, iface_id: int = None self, node_id: int, model: str, iface_id: int = None
) -> Dict[str, ConfigOption]: ) -> dict[str, ConfigOption]:
if iface_id is None: if iface_id is None:
iface_id = -1 iface_id = -1
config = self.client.get_emane_model_config( config = self.client.get_emane_model_config(

View file

@ -3,7 +3,7 @@ check engine light
""" """
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Dict, Optional from typing import TYPE_CHECKING, Optional
from core.api.grpc.wrappers import ExceptionEvent, ExceptionLevel from core.api.grpc.wrappers import ExceptionEvent, ExceptionLevel
from core.gui.dialogs.dialog import Dialog from core.gui.dialogs.dialog import Dialog
@ -19,7 +19,7 @@ class AlertsDialog(Dialog):
super().__init__(app, "Alerts") super().__init__(app, "Alerts")
self.tree: Optional[ttk.Treeview] = None self.tree: Optional[ttk.Treeview] = None
self.codetext: Optional[CodeText] = None self.codetext: Optional[CodeText] = None
self.alarm_map: Dict[int, ExceptionEvent] = {} self.alarm_map: dict[int, ExceptionEvent] = {}
self.draw() self.draw()
def draw(self) -> None: def draw(self) -> None:

View file

@ -4,7 +4,7 @@ set wallpaper
import logging import logging
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, List, Optional from typing import TYPE_CHECKING, Optional
from core.gui import images from core.gui import images
from core.gui.appconfig import BACKGROUNDS_PATH from core.gui.appconfig import BACKGROUNDS_PATH
@ -32,7 +32,7 @@ class CanvasWallpaperDialog(Dialog):
) )
self.filename: tk.StringVar = tk.StringVar(value=self.canvas.wallpaper_file) self.filename: tk.StringVar = tk.StringVar(value=self.canvas.wallpaper_file)
self.image_label: Optional[ttk.Label] = None self.image_label: Optional[ttk.Label] = None
self.options: List[ttk.Radiobutton] = [] self.options: list[ttk.Radiobutton] = []
self.draw() self.draw()
def draw(self) -> None: def draw(self) -> None:

View file

@ -3,7 +3,7 @@ custom color picker
""" """
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Optional, Tuple from typing import TYPE_CHECKING, Optional
from core.gui import validation from core.gui import validation
from core.gui.dialogs.dialog import Dialog from core.gui.dialogs.dialog import Dialog
@ -66,7 +66,9 @@ class ColorPickerDialog(Dialog):
) )
scale.grid(row=0, column=2, sticky=tk.EW, padx=PADX) scale.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
self.red_label = ttk.Label( self.red_label = ttk.Label(
frame, background="#%02x%02x%02x" % (self.red.get(), 0, 0), width=5 frame,
background="#{:02x}{:02x}{:02x}".format(self.red.get(), 0, 0),
width=5,
) )
self.red_label.grid(row=0, column=3, sticky=tk.EW) self.red_label.grid(row=0, column=3, sticky=tk.EW)
@ -89,7 +91,9 @@ class ColorPickerDialog(Dialog):
) )
scale.grid(row=0, column=2, sticky=tk.EW, padx=PADX) scale.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
self.green_label = ttk.Label( self.green_label = ttk.Label(
frame, background="#%02x%02x%02x" % (0, self.green.get(), 0), width=5 frame,
background="#{:02x}{:02x}{:02x}".format(0, self.green.get(), 0),
width=5,
) )
self.green_label.grid(row=0, column=3, sticky=tk.EW) self.green_label.grid(row=0, column=3, sticky=tk.EW)
@ -112,7 +116,9 @@ class ColorPickerDialog(Dialog):
) )
scale.grid(row=0, column=2, sticky=tk.EW, padx=PADX) scale.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
self.blue_label = ttk.Label( self.blue_label = ttk.Label(
frame, background="#%02x%02x%02x" % (0, 0, self.blue.get()), width=5 frame,
background="#{:02x}{:02x}{:02x}".format(0, 0, self.blue.get()),
width=5,
) )
self.blue_label.grid(row=0, column=3, sticky=tk.EW) self.blue_label.grid(row=0, column=3, sticky=tk.EW)
@ -157,7 +163,7 @@ class ColorPickerDialog(Dialog):
red = self.red_entry.get() red = self.red_entry.get()
blue = self.blue_entry.get() blue = self.blue_entry.get()
green = self.green_entry.get() green = self.green_entry.get()
return "#%02x%02x%02x" % (int(red), int(green), int(blue)) return "#{:02x}{:02x}{:02x}".format(int(red), int(green), int(blue))
def current_focus(self, focus: str) -> None: def current_focus(self, focus: str) -> None:
self.focus = focus self.focus = focus
@ -169,7 +175,7 @@ class ColorPickerDialog(Dialog):
green = self.green_entry.get() green = self.green_entry.get()
self.set_scale(red, green, blue) self.set_scale(red, green, blue)
if red and blue and green: if red and blue and green:
hex_code = "#%02x%02x%02x" % (int(red), int(green), int(blue)) hex_code = "#{:02x}{:02x}{:02x}".format(int(red), int(green), int(blue))
self.hex.set(hex_code) self.hex.set(hex_code)
self.display.config(background=hex_code) self.display.config(background=hex_code)
self.set_label(red, green, blue) self.set_label(red, green, blue)
@ -200,11 +206,17 @@ class ColorPickerDialog(Dialog):
self.blue.set(blue) self.blue.set(blue)
def set_label(self, red: str, green: str, blue: str) -> None: def set_label(self, red: str, green: str, blue: str) -> None:
self.red_label.configure(background="#%02x%02x%02x" % (int(red), 0, 0)) self.red_label.configure(
self.green_label.configure(background="#%02x%02x%02x" % (0, int(green), 0)) background="#{:02x}{:02x}{:02x}".format(int(red), 0, 0)
self.blue_label.configure(background="#%02x%02x%02x" % (0, 0, int(blue))) )
self.green_label.configure(
background="#{:02x}{:02x}{:02x}".format(0, int(green), 0)
)
self.blue_label.configure(
background="#{:02x}{:02x}{:02x}".format(0, 0, int(blue))
)
def get_rgb(self, hex_code: str) -> Tuple[int, int, int]: def get_rgb(self, hex_code: str) -> tuple[int, int, int]:
""" """
convert a valid hex code to RGB values convert a valid hex code to RGB values
""" """

View file

@ -4,7 +4,7 @@ Service configuration dialog
import logging import logging
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Dict, List, Optional, Set from typing import TYPE_CHECKING, Optional
import grpc import grpc
@ -35,22 +35,22 @@ class ConfigServiceConfigDialog(Dialog):
self.node: Node = node self.node: Node = node
self.service_name: str = service_name self.service_name: str = service_name
self.radiovar: tk.IntVar = tk.IntVar(value=2) self.radiovar: tk.IntVar = tk.IntVar(value=2)
self.directories: List[str] = [] self.directories: list[str] = []
self.templates: List[str] = [] self.templates: list[str] = []
self.rendered: Dict[str, str] = {} self.rendered: dict[str, str] = {}
self.dependencies: List[str] = [] self.dependencies: list[str] = []
self.executables: List[str] = [] self.executables: list[str] = []
self.startup_commands: List[str] = [] self.startup_commands: list[str] = []
self.validation_commands: List[str] = [] self.validation_commands: list[str] = []
self.shutdown_commands: List[str] = [] self.shutdown_commands: list[str] = []
self.default_startup: List[str] = [] self.default_startup: list[str] = []
self.default_validate: List[str] = [] self.default_validate: list[str] = []
self.default_shutdown: List[str] = [] self.default_shutdown: list[str] = []
self.validation_mode: Optional[ServiceValidationMode] = None self.validation_mode: Optional[ServiceValidationMode] = None
self.validation_time: Optional[int] = None self.validation_time: Optional[int] = None
self.validation_period: tk.DoubleVar = tk.DoubleVar() self.validation_period: tk.DoubleVar = tk.DoubleVar()
self.modes: List[str] = [] self.modes: list[str] = []
self.mode_configs: Dict[str, Dict[str, str]] = {} self.mode_configs: dict[str, dict[str, str]] = {}
self.notebook: Optional[ttk.Notebook] = None self.notebook: Optional[ttk.Notebook] = None
self.templates_combobox: Optional[ttk.Combobox] = None self.templates_combobox: Optional[ttk.Combobox] = None
self.modes_combobox: Optional[ttk.Combobox] = None self.modes_combobox: Optional[ttk.Combobox] = None
@ -62,12 +62,12 @@ class ConfigServiceConfigDialog(Dialog):
self.template_text: Optional[CodeText] = None self.template_text: Optional[CodeText] = None
self.rendered_text: Optional[CodeText] = None self.rendered_text: Optional[CodeText] = None
self.validation_period_entry: Optional[ttk.Entry] = None self.validation_period_entry: Optional[ttk.Entry] = None
self.original_service_files: Dict[str, str] = {} self.original_service_files: dict[str, str] = {}
self.temp_service_files: Dict[str, str] = {} self.temp_service_files: dict[str, str] = {}
self.modified_files: Set[str] = set() self.modified_files: set[str] = set()
self.config_frame: Optional[ConfigFrame] = None self.config_frame: Optional[ConfigFrame] = None
self.default_config: Dict[str, str] = {} self.default_config: dict[str, str] = {}
self.config: Dict[str, ConfigOption] = {} self.config: dict[str, ConfigOption] = {}
self.has_error: bool = False self.has_error: bool = False
self.load() self.load()
if not self.has_error: if not self.has_error:
@ -405,7 +405,7 @@ class ConfigServiceConfigDialog(Dialog):
pass pass
def append_commands( def append_commands(
self, commands: List[str], listbox: tk.Listbox, to_add: List[str] self, commands: list[str], listbox: tk.Listbox, to_add: list[str]
) -> None: ) -> None:
for cmd in to_add: for cmd in to_add:
commands.append(cmd) commands.append(cmd)

View file

@ -4,7 +4,7 @@ copy service config dialog
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Dict, Optional from typing import TYPE_CHECKING, Optional
from core.gui.dialogs.dialog import Dialog from core.gui.dialogs.dialog import Dialog
from core.gui.themes import PADX, PADY from core.gui.themes import PADX, PADY
@ -29,7 +29,7 @@ class CopyServiceConfigDialog(Dialog):
self.service: str = service self.service: str = service
self.file_name: str = file_name self.file_name: str = file_name
self.listbox: Optional[tk.Listbox] = None self.listbox: Optional[tk.Listbox] = None
self.nodes: Dict[str, int] = {} self.nodes: dict[str, int] = {}
self.draw() self.draw()
def draw(self) -> None: def draw(self) -> None:

View file

@ -2,7 +2,7 @@ import logging
import tkinter as tk import tkinter as tk
from pathlib import Path from pathlib import Path
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Optional, Set from typing import TYPE_CHECKING, Optional
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
@ -21,13 +21,13 @@ if TYPE_CHECKING:
class ServicesSelectDialog(Dialog): class ServicesSelectDialog(Dialog):
def __init__( def __init__(
self, master: tk.BaseWidget, app: "Application", current_services: Set[str] self, master: tk.BaseWidget, app: "Application", current_services: set[str]
) -> None: ) -> None:
super().__init__(app, "Node Config Services", master=master) super().__init__(app, "Node Config Services", master=master)
self.groups: Optional[ListboxScroll] = None self.groups: Optional[ListboxScroll] = None
self.services: Optional[CheckboxList] = None self.services: Optional[CheckboxList] = None
self.current: Optional[ListboxScroll] = None self.current: Optional[ListboxScroll] = None
self.current_services: Set[str] = current_services self.current_services: set[str] = current_services
self.draw() self.draw()
def draw(self) -> None: def draw(self) -> None:
@ -114,7 +114,7 @@ class CustomNodesDialog(Dialog):
self.image_button: Optional[ttk.Button] = None self.image_button: Optional[ttk.Button] = None
self.image: Optional[PhotoImage] = None self.image: Optional[PhotoImage] = None
self.image_file: Optional[str] = None self.image_file: Optional[str] = None
self.services: Set[str] = set() self.services: set[str] = set()
self.selected: Optional[str] = None self.selected: Optional[str] = None
self.selected_index: Optional[int] = None self.selected_index: Optional[int] = None
self.draw() self.draw()

View file

@ -4,7 +4,7 @@ emane configuration
import tkinter as tk import tkinter as tk
import webbrowser import webbrowser
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Dict, List, Optional from typing import TYPE_CHECKING, Optional
import grpc import grpc
@ -43,7 +43,7 @@ class EmaneModelDialog(Dialog):
config = self.app.core.get_emane_model_config( config = self.app.core.get_emane_model_config(
self.node.id, self.model, self.iface_id self.node.id, self.model, self.iface_id
) )
self.config: Dict[str, ConfigOption] = config self.config: dict[str, ConfigOption] = config
self.draw() self.draw()
except grpc.RpcError as e: except grpc.RpcError as e:
self.app.show_grpc_exception("Get EMANE Config Error", e) self.app.show_grpc_exception("Get EMANE Config Error", e)
@ -82,7 +82,7 @@ class EmaneConfigDialog(Dialog):
self.node: Node = node self.node: Node = node
self.radiovar: tk.IntVar = tk.IntVar() self.radiovar: tk.IntVar = tk.IntVar()
self.radiovar.set(1) self.radiovar.set(1)
self.emane_models: List[str] = [ self.emane_models: list[str] = [
x.split("_")[1] for x in self.app.core.emane_models x.split("_")[1] for x in self.app.core.emane_models
] ]
model = self.node.emane.split("_")[1] model = self.node.emane.split("_")[1]

View file

@ -1,6 +1,6 @@
import tkinter as tk import tkinter as tk
from tkinter import messagebox, ttk from tkinter import messagebox, ttk
from typing import TYPE_CHECKING, List, Optional from typing import TYPE_CHECKING, Optional
import netaddr import netaddr
@ -17,8 +17,8 @@ class IpConfigDialog(Dialog):
super().__init__(app, "IP Configuration") super().__init__(app, "IP Configuration")
self.ip4: str = self.app.guiconfig.ips.ip4 self.ip4: str = self.app.guiconfig.ips.ip4
self.ip6: str = self.app.guiconfig.ips.ip6 self.ip6: str = self.app.guiconfig.ips.ip6
self.ip4s: List[str] = self.app.guiconfig.ips.ip4s self.ip4s: list[str] = self.app.guiconfig.ips.ip4s
self.ip6s: List[str] = self.app.guiconfig.ips.ip6s self.ip6s: list[str] = self.app.guiconfig.ips.ip6s
self.ip4_entry: Optional[ttk.Entry] = None self.ip4_entry: Optional[ttk.Entry] = None
self.ip4_listbox: Optional[ListboxScroll] = None self.ip4_listbox: Optional[ListboxScroll] = None
self.ip6_entry: Optional[ttk.Entry] = None self.ip6_entry: Optional[ttk.Entry] = None

View file

@ -3,7 +3,7 @@ mobility configuration
""" """
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Dict, Optional from typing import TYPE_CHECKING, Optional
import grpc import grpc
@ -26,7 +26,7 @@ class MobilityConfigDialog(Dialog):
config = self.node.mobility_config config = self.node.mobility_config
if not config: if not config:
config = self.app.core.get_mobility_config(self.node.id) config = self.app.core.get_mobility_config(self.node.id)
self.config: Dict[str, ConfigOption] = config self.config: dict[str, ConfigOption] = config
self.draw() self.draw()
except grpc.RpcError as e: except grpc.RpcError as e:
self.app.show_grpc_exception("Get Mobility Config Error", e) self.app.show_grpc_exception("Get Mobility Config Error", e)

View file

@ -2,7 +2,7 @@ import logging
import tkinter as tk import tkinter as tk
from functools import partial from functools import partial
from tkinter import messagebox, ttk from tkinter import messagebox, ttk
from typing import TYPE_CHECKING, Dict, Optional from typing import TYPE_CHECKING, Optional
import netaddr import netaddr
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
@ -190,7 +190,7 @@ class NodeConfigDialog(Dialog):
if self.node.server: if self.node.server:
server = self.node.server server = self.node.server
self.server: tk.StringVar = tk.StringVar(value=server) self.server: tk.StringVar = tk.StringVar(value=server)
self.ifaces: Dict[int, InterfaceData] = {} self.ifaces: dict[int, InterfaceData] = {}
self.draw() self.draw()
def draw(self) -> None: def draw(self) -> None:

View file

@ -4,7 +4,7 @@ core node services
import logging import logging
import tkinter as tk import tkinter as tk
from tkinter import messagebox, ttk from tkinter import messagebox, ttk
from typing import TYPE_CHECKING, Optional, Set from typing import TYPE_CHECKING, Optional
from core.api.grpc.wrappers import Node from core.api.grpc.wrappers import Node
from core.gui.dialogs.configserviceconfig import ConfigServiceConfigDialog from core.gui.dialogs.configserviceconfig import ConfigServiceConfigDialog
@ -20,7 +20,7 @@ if TYPE_CHECKING:
class NodeConfigServiceDialog(Dialog): class NodeConfigServiceDialog(Dialog):
def __init__( def __init__(
self, app: "Application", node: Node, services: Set[str] = None self, app: "Application", node: Node, services: set[str] = None
) -> None: ) -> None:
title = f"{node.name} Config Services" title = f"{node.name} Config Services"
super().__init__(app, title) super().__init__(app, title)
@ -30,7 +30,7 @@ class NodeConfigServiceDialog(Dialog):
self.current: Optional[ListboxScroll] = None self.current: Optional[ListboxScroll] = None
if services is None: if services is None:
services = set(node.config_services) services = set(node.config_services)
self.current_services: Set[str] = services self.current_services: set[str] = services
self.protocol("WM_DELETE_WINDOW", self.click_cancel) self.protocol("WM_DELETE_WINDOW", self.click_cancel)
self.draw() self.draw()

View file

@ -3,7 +3,7 @@ core node services
""" """
import tkinter as tk import tkinter as tk
from tkinter import messagebox, ttk from tkinter import messagebox, ttk
from typing import TYPE_CHECKING, Optional, Set from typing import TYPE_CHECKING, Optional
from core.api.grpc.wrappers import Node from core.api.grpc.wrappers import Node
from core.gui.dialogs.dialog import Dialog from core.gui.dialogs.dialog import Dialog
@ -24,7 +24,7 @@ class NodeServiceDialog(Dialog):
self.services: Optional[CheckboxList] = None self.services: Optional[CheckboxList] = None
self.current: Optional[ListboxScroll] = None self.current: Optional[ListboxScroll] = None
services = set(node.services) services = set(node.services)
self.current_services: Set[str] = services self.current_services: set[str] = services
self.protocol("WM_DELETE_WINDOW", self.click_cancel) self.protocol("WM_DELETE_WINDOW", self.click_cancel)
self.draw() self.draw()

View file

@ -1,6 +1,6 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Dict, Optional from typing import TYPE_CHECKING, Optional
from core.gui import nodeutils as nutils from core.gui import nodeutils as nutils
from core.gui.dialogs.dialog import Dialog from core.gui.dialogs.dialog import Dialog
@ -17,7 +17,7 @@ class RunToolDialog(Dialog):
self.cmd: tk.StringVar = tk.StringVar(value="ps ax") self.cmd: tk.StringVar = tk.StringVar(value="ps ax")
self.result: Optional[CodeText] = None self.result: Optional[CodeText] = None
self.node_list: Optional[ListboxScroll] = None self.node_list: Optional[ListboxScroll] = None
self.executable_nodes: Dict[str, int] = {} self.executable_nodes: dict[str, int] = {}
self.store_nodes() self.store_nodes()
self.draw() self.draw()

View file

@ -2,7 +2,7 @@ import logging
import tkinter as tk import tkinter as tk
from pathlib import Path from pathlib import Path
from tkinter import filedialog, messagebox, ttk from tkinter import filedialog, messagebox, ttk
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple from typing import TYPE_CHECKING, Optional
import grpc import grpc
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
@ -35,21 +35,21 @@ class ServiceConfigDialog(Dialog):
self.service_name: str = service_name self.service_name: str = service_name
self.radiovar: tk.IntVar = tk.IntVar(value=2) self.radiovar: tk.IntVar = tk.IntVar(value=2)
self.metadata: str = "" self.metadata: str = ""
self.filenames: List[str] = [] self.filenames: list[str] = []
self.dependencies: List[str] = [] self.dependencies: list[str] = []
self.executables: List[str] = [] self.executables: list[str] = []
self.startup_commands: List[str] = [] self.startup_commands: list[str] = []
self.validation_commands: List[str] = [] self.validation_commands: list[str] = []
self.shutdown_commands: List[str] = [] self.shutdown_commands: list[str] = []
self.default_startup: List[str] = [] self.default_startup: list[str] = []
self.default_validate: List[str] = [] self.default_validate: list[str] = []
self.default_shutdown: List[str] = [] self.default_shutdown: list[str] = []
self.validation_mode: Optional[ServiceValidationMode] = None self.validation_mode: Optional[ServiceValidationMode] = None
self.validation_time: Optional[int] = None self.validation_time: Optional[int] = None
self.validation_period: Optional[float] = None self.validation_period: Optional[float] = None
self.directory_entry: Optional[ttk.Entry] = None self.directory_entry: Optional[ttk.Entry] = None
self.default_directories: List[str] = [] self.default_directories: list[str] = []
self.temp_directories: List[str] = [] self.temp_directories: list[str] = []
self.documentnew_img: PhotoImage = self.app.get_enum_icon( self.documentnew_img: PhotoImage = self.app.get_enum_icon(
ImageEnum.DOCUMENTNEW, width=ICON_SIZE ImageEnum.DOCUMENTNEW, width=ICON_SIZE
) )
@ -67,10 +67,10 @@ class ServiceConfigDialog(Dialog):
self.validation_mode_entry: Optional[ttk.Entry] = None self.validation_mode_entry: Optional[ttk.Entry] = None
self.service_file_data: Optional[CodeText] = None self.service_file_data: Optional[CodeText] = None
self.validation_period_entry: Optional[ttk.Entry] = None self.validation_period_entry: Optional[ttk.Entry] = None
self.original_service_files: Dict[str, str] = {} self.original_service_files: dict[str, str] = {}
self.default_config: Optional[NodeServiceData] = None self.default_config: Optional[NodeServiceData] = None
self.temp_service_files: Dict[str, str] = {} self.temp_service_files: dict[str, str] = {}
self.modified_files: Set[str] = set() self.modified_files: set[str] = set()
self.has_error: bool = False self.has_error: bool = False
self.load() self.load()
if not self.has_error: if not self.has_error:
@ -558,13 +558,13 @@ class ServiceConfigDialog(Dialog):
@classmethod @classmethod
def append_commands( def append_commands(
cls, commands: List[str], listbox: tk.Listbox, to_add: List[str] cls, commands: list[str], listbox: tk.Listbox, to_add: list[str]
) -> None: ) -> None:
for cmd in to_add: for cmd in to_add:
commands.append(cmd) commands.append(cmd)
listbox.insert(tk.END, cmd) listbox.insert(tk.END, cmd)
def get_commands(self) -> Tuple[List[str], List[str], List[str]]: def get_commands(self) -> tuple[list[str], list[str], list[str]]:
startup = self.startup_commands_listbox.get(0, "end") startup = self.startup_commands_listbox.get(0, "end")
shutdown = self.shutdown_commands_listbox.get(0, "end") shutdown = self.shutdown_commands_listbox.get(0, "end")
validate = self.validate_commands_listbox.get(0, "end") validate = self.validate_commands_listbox.get(0, "end")

View file

@ -1,7 +1,7 @@
import logging import logging
import tkinter as tk import tkinter as tk
from tkinter import messagebox, ttk from tkinter import messagebox, ttk
from typing import TYPE_CHECKING, List, Optional from typing import TYPE_CHECKING, Optional
import grpc import grpc
@ -30,7 +30,7 @@ class SessionsDialog(Dialog):
self.protocol("WM_DELETE_WINDOW", self.on_closing) self.protocol("WM_DELETE_WINDOW", self.on_closing)
self.draw() self.draw()
def get_sessions(self) -> List[SessionSummary]: def get_sessions(self) -> list[SessionSummary]:
try: try:
sessions = self.app.core.client.get_sessions() sessions = self.app.core.client.get_sessions()
logger.info("sessions: %s", sessions) logger.info("sessions: %s", sessions)

View file

@ -3,7 +3,7 @@ shape input dialog
""" """
import tkinter as tk import tkinter as tk
from tkinter import font, ttk from tkinter import font, ttk
from typing import TYPE_CHECKING, List, Optional, Union from typing import TYPE_CHECKING, Optional, Union
from core.gui.dialogs.colorpicker import ColorPickerDialog from core.gui.dialogs.colorpicker import ColorPickerDialog
from core.gui.dialogs.dialog import Dialog from core.gui.dialogs.dialog import Dialog
@ -16,8 +16,8 @@ if TYPE_CHECKING:
from core.gui.graph.graph import CanvasGraph from core.gui.graph.graph import CanvasGraph
from core.gui.graph.shape import Shape from core.gui.graph.shape import Shape
FONT_SIZES: List[int] = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72] FONT_SIZES: list[int] = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72]
BORDER_WIDTH: List[int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] BORDER_WIDTH: list[int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
class ShapeDialog(Dialog): class ShapeDialog(Dialog):
@ -168,7 +168,7 @@ class ShapeDialog(Dialog):
self.add_text() self.add_text()
self.destroy() self.destroy()
def make_font(self) -> List[Union[int, str]]: def make_font(self) -> list[Union[int, str]]:
""" """
create font for text or shape label create font for text or shape label
""" """

View file

@ -1,6 +1,6 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Dict, Optional from typing import TYPE_CHECKING, Optional
import grpc import grpc
@ -19,12 +19,12 @@ class WirelessConfigDialog(Dialog):
super().__init__(app, f"Wireless Configuration - {canvas_node.core_node.name}") super().__init__(app, f"Wireless Configuration - {canvas_node.core_node.name}")
self.node: Node = canvas_node.core_node self.node: Node = canvas_node.core_node
self.config_frame: Optional[ConfigFrame] = None self.config_frame: Optional[ConfigFrame] = None
self.config: Dict[str, ConfigOption] = {} self.config: dict[str, ConfigOption] = {}
try: try:
config = self.node.wireless_config config = self.node.wireless_config
if not config: if not config:
config = self.app.core.get_wireless_config(self.node.id) config = self.app.core.get_wireless_config(self.node.id)
self.config: Dict[str, ConfigOption] = config self.config: dict[str, ConfigOption] = config
self.draw() self.draw()
except grpc.RpcError as e: except grpc.RpcError as e:
self.app.show_grpc_exception("Wireless Config Error", e) self.app.show_grpc_exception("Wireless Config Error", e)

View file

@ -1,6 +1,6 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Dict, Optional from typing import TYPE_CHECKING, Optional
import grpc import grpc
@ -27,13 +27,13 @@ class WlanConfigDialog(Dialog):
self.config_frame: Optional[ConfigFrame] = None self.config_frame: Optional[ConfigFrame] = None
self.range_entry: Optional[ttk.Entry] = None self.range_entry: Optional[ttk.Entry] = None
self.has_error: bool = False self.has_error: bool = False
self.ranges: Dict[int, int] = {} self.ranges: dict[int, int] = {}
self.positive_int: int = self.app.master.register(self.validate_and_update) self.positive_int: int = self.app.master.register(self.validate_and_update)
try: try:
config = self.node.wlan_config config = self.node.wlan_config
if not config: if not config:
config = self.app.core.get_wlan_config(self.node.id) config = self.app.core.get_wlan_config(self.node.id)
self.config: Dict[str, ConfigOption] = config self.config: dict[str, ConfigOption] = config
self.init_draw_range() self.init_draw_range()
self.draw() self.draw()
except grpc.RpcError as e: except grpc.RpcError as e:

View file

@ -2,7 +2,7 @@ import functools
import logging import logging
import math import math
import tkinter as tk import tkinter as tk
from typing import TYPE_CHECKING, Optional, Tuple, Union from typing import TYPE_CHECKING, Optional, Union
from core.api.grpc.wrappers import Interface, Link from core.api.grpc.wrappers import Interface, Link
from core.gui import nodeutils, themes from core.gui import nodeutils, themes
@ -54,7 +54,7 @@ def create_edge_token(link: Link) -> str:
def node_label_positions( def node_label_positions(
src_x: int, src_y: int, dst_x: int, dst_y: int src_x: int, src_y: int, dst_x: int, dst_y: int
) -> Tuple[Tuple[float, float], Tuple[float, float]]: ) -> tuple[tuple[float, float], tuple[float, float]]:
v_x, v_y = dst_x - src_x, dst_y - src_y v_x, v_y = dst_x - src_x, dst_y - src_y
v_len = math.sqrt(v_x**2 + v_y**2) v_len = math.sqrt(v_x**2 + v_y**2)
if v_len == 0: if v_len == 0:
@ -128,8 +128,8 @@ class Edge:
return self.width * self.app.app_scale return self.width * self.app.app_scale
def _get_arcpoint( def _get_arcpoint(
self, src_pos: Tuple[float, float], dst_pos: Tuple[float, float] self, src_pos: tuple[float, float], dst_pos: tuple[float, float]
) -> Tuple[float, float]: ) -> tuple[float, float]:
src_x, src_y = src_pos src_x, src_y = src_pos
dst_x, dst_y = dst_pos dst_x, dst_y = dst_pos
mp_x = (src_x + dst_x) / 2 mp_x = (src_x + dst_x) / 2
@ -317,7 +317,7 @@ class Edge:
if self.dst_label2: if self.dst_label2:
self.dst.canvas.itemconfig(self.dst_label2, text=text) self.dst.canvas.itemconfig(self.dst_label2, text=text)
def drawing(self, pos: Tuple[float, float]) -> None: def drawing(self, pos: tuple[float, float]) -> None:
src_x, src_y, _, _, _, _ = self.src.canvas.coords(self.id) src_x, src_y, _, _, _, _ = self.src.canvas.coords(self.id)
src_pos = src_x, src_y src_pos = src_x, src_y
self.moved(src_pos, pos) self.moved(src_pos, pos)
@ -368,7 +368,7 @@ class Edge:
dst_pos = dst_x, dst_y dst_pos = dst_x, dst_y
self.moved(self.src.position(), dst_pos) self.moved(self.src.position(), dst_pos)
def moved(self, src_pos: Tuple[float, float], dst_pos: Tuple[float, float]) -> None: def moved(self, src_pos: tuple[float, float], dst_pos: tuple[float, float]) -> None:
arc_pos = self._get_arcpoint(src_pos, dst_pos) arc_pos = self._get_arcpoint(src_pos, dst_pos)
self.src.canvas.coords(self.id, *src_pos, *arc_pos, *dst_pos) self.src.canvas.coords(self.id, *src_pos, *arc_pos, *dst_pos)
if self.middle_label: if self.middle_label:
@ -381,7 +381,7 @@ class Edge:
self.src.canvas.coords(self.dst_label, *dst_pos) self.src.canvas.coords(self.dst_label, *dst_pos)
def moved2( def moved2(
self, src_pos: Tuple[float, float], dst_pos: Tuple[float, float] self, src_pos: tuple[float, float], dst_pos: tuple[float, float]
) -> None: ) -> None:
arc_pos = self._get_arcpoint(src_pos, dst_pos) arc_pos = self._get_arcpoint(src_pos, dst_pos)
self.dst.canvas.coords(self.id2, *src_pos, *arc_pos, *dst_pos) self.dst.canvas.coords(self.id2, *src_pos, *arc_pos, *dst_pos)
@ -568,7 +568,7 @@ class CanvasEdge(Edge):
label += f"{iface.ip6}/{iface.ip6_mask}" label += f"{iface.ip6}/{iface.ip6_mask}"
return label return label
def create_node_labels(self) -> Tuple[str, str]: def create_node_labels(self) -> tuple[str, str]:
label1 = None label1 = None
if self.link.iface1: if self.link.iface1:
label1 = self.iface_label(self.link.iface1) label1 = self.iface_label(self.link.iface1)

View file

@ -2,7 +2,7 @@ import logging
import tkinter as tk import tkinter as tk
from copy import deepcopy from copy import deepcopy
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple from typing import TYPE_CHECKING, Any, Optional
from PIL import Image from PIL import Image
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
@ -27,8 +27,8 @@ if TYPE_CHECKING:
ZOOM_IN: float = 1.1 ZOOM_IN: float = 1.1
ZOOM_OUT: float = 0.9 ZOOM_OUT: float = 0.9
MOVE_NODE_MODES: Set[GraphMode] = {GraphMode.NODE, GraphMode.SELECT} MOVE_NODE_MODES: set[GraphMode] = {GraphMode.NODE, GraphMode.SELECT}
MOVE_SHAPE_MODES: Set[GraphMode] = {GraphMode.ANNOTATION, GraphMode.SELECT} MOVE_SHAPE_MODES: set[GraphMode] = {GraphMode.ANNOTATION, GraphMode.SELECT}
BACKGROUND_COLOR: str = "#cccccc" BACKGROUND_COLOR: str = "#cccccc"
@ -40,32 +40,32 @@ class CanvasGraph(tk.Canvas):
manager: "CanvasManager", manager: "CanvasManager",
core: "CoreClient", core: "CoreClient",
_id: int, _id: int,
dimensions: Tuple[int, int], dimensions: tuple[int, int],
) -> None: ) -> None:
super().__init__(master, highlightthickness=0, background=BACKGROUND_COLOR) super().__init__(master, highlightthickness=0, background=BACKGROUND_COLOR)
self.id: int = _id self.id: int = _id
self.app: "Application" = app self.app: "Application" = app
self.manager: "CanvasManager" = manager self.manager: "CanvasManager" = manager
self.core: "CoreClient" = core self.core: "CoreClient" = core
self.selection: Dict[int, int] = {} self.selection: dict[int, int] = {}
self.select_box: Optional[Shape] = None self.select_box: Optional[Shape] = None
self.selected: Optional[int] = None self.selected: Optional[int] = None
self.nodes: Dict[int, CanvasNode] = {} self.nodes: dict[int, CanvasNode] = {}
self.shadow_nodes: Dict[int, ShadowNode] = {} self.shadow_nodes: dict[int, ShadowNode] = {}
self.shapes: Dict[int, Shape] = {} self.shapes: dict[int, Shape] = {}
self.shadow_core_nodes: Dict[int, ShadowNode] = {} self.shadow_core_nodes: dict[int, ShadowNode] = {}
# map wireless/EMANE node to the set of MDRs connected to that node # map wireless/EMANE node to the set of MDRs connected to that node
self.wireless_network: Dict[int, Set[int]] = {} self.wireless_network: dict[int, set[int]] = {}
self.drawing_edge: Optional[CanvasEdge] = None self.drawing_edge: Optional[CanvasEdge] = None
self.rect: Optional[int] = None self.rect: Optional[int] = None
self.shape_drawing: bool = False self.shape_drawing: bool = False
self.current_dimensions: Tuple[int, int] = dimensions self.current_dimensions: tuple[int, int] = dimensions
self.ratio: float = 1.0 self.ratio: float = 1.0
self.offset: Tuple[int, int] = (0, 0) self.offset: tuple[int, int] = (0, 0)
self.cursor: Tuple[int, int] = (0, 0) self.cursor: tuple[int, int] = (0, 0)
self.to_copy: List[CanvasNode] = [] self.to_copy: list[CanvasNode] = []
# background related # background related
self.wallpaper_id: Optional[int] = None self.wallpaper_id: Optional[int] = None
@ -82,7 +82,7 @@ class CanvasGraph(tk.Canvas):
self.draw_canvas() self.draw_canvas()
self.draw_grid() self.draw_grid()
def draw_canvas(self, dimensions: Tuple[int, int] = None) -> None: def draw_canvas(self, dimensions: tuple[int, int] = None) -> None:
if self.rect is not None: if self.rect is not None:
self.delete(self.rect) self.delete(self.rect)
if not dimensions: if not dimensions:
@ -126,23 +126,23 @@ class CanvasGraph(tk.Canvas):
shadow_node = ShadowNode(self.app, self, node) shadow_node = ShadowNode(self.app, self, node)
return shadow_node return shadow_node
def get_actual_coords(self, x: float, y: float) -> Tuple[float, float]: def get_actual_coords(self, x: float, y: float) -> tuple[float, float]:
actual_x = (x - self.offset[0]) / self.ratio actual_x = (x - self.offset[0]) / self.ratio
actual_y = (y - self.offset[1]) / self.ratio actual_y = (y - self.offset[1]) / self.ratio
return actual_x, actual_y return actual_x, actual_y
def get_scaled_coords(self, x: float, y: float) -> Tuple[float, float]: def get_scaled_coords(self, x: float, y: float) -> tuple[float, float]:
scaled_x = (x * self.ratio) + self.offset[0] scaled_x = (x * self.ratio) + self.offset[0]
scaled_y = (y * self.ratio) + self.offset[1] scaled_y = (y * self.ratio) + self.offset[1]
return scaled_x, scaled_y return scaled_x, scaled_y
def inside_canvas(self, x: float, y: float) -> Tuple[bool, bool]: def inside_canvas(self, x: float, y: float) -> tuple[bool, bool]:
x1, y1, x2, y2 = self.bbox(self.rect) x1, y1, x2, y2 = self.bbox(self.rect)
valid_x = x1 <= x <= x2 valid_x = x1 <= x <= x2
valid_y = y1 <= y <= y2 valid_y = y1 <= y <= y2
return valid_x and valid_y return valid_x and valid_y
def valid_position(self, x1: int, y1: int, x2: int, y2: int) -> Tuple[bool, bool]: def valid_position(self, x1: int, y1: int, x2: int, y2: int) -> tuple[bool, bool]:
valid_topleft = self.inside_canvas(x1, y1) valid_topleft = self.inside_canvas(x1, y1)
valid_bottomright = self.inside_canvas(x2, y2) valid_bottomright = self.inside_canvas(x2, y2)
return valid_topleft and valid_bottomright return valid_topleft and valid_bottomright
@ -161,7 +161,7 @@ class CanvasGraph(tk.Canvas):
self.tag_lower(tags.GRIDLINE) self.tag_lower(tags.GRIDLINE)
self.tag_lower(self.rect) self.tag_lower(self.rect)
def canvas_xy(self, event: tk.Event) -> Tuple[float, float]: def canvas_xy(self, event: tk.Event) -> tuple[float, float]:
""" """
Convert window coordinate to canvas coordinate Convert window coordinate to canvas coordinate
""" """
@ -516,7 +516,7 @@ class CanvasGraph(tk.Canvas):
self.nodes[node.id] = node self.nodes[node.id] = node
self.core.set_canvas_node(core_node, node) self.core.set_canvas_node(core_node, node)
def width_and_height(self) -> Tuple[int, int]: def width_and_height(self) -> tuple[int, int]:
""" """
retrieve canvas width and height in pixels retrieve canvas width and height in pixels
""" """
@ -601,7 +601,7 @@ class CanvasGraph(tk.Canvas):
self.redraw_canvas((image.width(), image.height())) self.redraw_canvas((image.width(), image.height()))
self.draw_wallpaper(image) self.draw_wallpaper(image)
def redraw_canvas(self, dimensions: Tuple[int, int] = None) -> None: def redraw_canvas(self, dimensions: tuple[int, int] = None) -> None:
logger.debug("redrawing canvas to dimensions: %s", dimensions) logger.debug("redrawing canvas to dimensions: %s", dimensions)
# reset scale and move back to original position # reset scale and move back to original position
@ -814,7 +814,7 @@ class CanvasGraph(tk.Canvas):
for edge_id in self.find_withtag(tags.EDGE): for edge_id in self.find_withtag(tags.EDGE):
self.itemconfig(edge_id, width=int(EDGE_WIDTH * self.app.app_scale)) self.itemconfig(edge_id, width=int(EDGE_WIDTH * self.app.app_scale))
def get_metadata(self) -> Dict[str, Any]: def get_metadata(self) -> dict[str, Any]:
wallpaper_path = None wallpaper_path = None
if self.wallpaper_file: if self.wallpaper_file:
wallpaper = Path(self.wallpaper_file) wallpaper = Path(self.wallpaper_file)
@ -830,7 +830,7 @@ class CanvasGraph(tk.Canvas):
dimensions=self.current_dimensions, dimensions=self.current_dimensions,
) )
def parse_metadata(self, config: Dict[str, Any]) -> None: def parse_metadata(self, config: dict[str, Any]) -> None:
fit_image = config.get("fit_image", False) fit_image = config.get("fit_image", False)
self.adjust_to_dim.set(fit_image) self.adjust_to_dim.set(fit_image)
wallpaper_style = config.get("wallpaper_style", 1) wallpaper_style = config.get("wallpaper_style", 1)

View file

@ -1,9 +1,10 @@
import json import json
import logging import logging
import tkinter as tk import tkinter as tk
from collections.abc import ValuesView
from copy import deepcopy from copy import deepcopy
from tkinter import BooleanVar, messagebox, ttk from tkinter import BooleanVar, messagebox, ttk
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, ValuesView from typing import TYPE_CHECKING, Any, Optional
from core.api.grpc.wrappers import Link, LinkType, Node, Session, ThroughputsEvent from core.api.grpc.wrappers import Link, LinkType, Node, Session, ThroughputsEvent
from core.gui import nodeutils as nutils from core.gui import nodeutils as nutils
@ -78,14 +79,14 @@ class CanvasManager:
self.mode: GraphMode = GraphMode.SELECT self.mode: GraphMode = GraphMode.SELECT
self.annotation_type: Optional[ShapeType] = None self.annotation_type: Optional[ShapeType] = None
self.node_draw: Optional[NodeDraw] = None self.node_draw: Optional[NodeDraw] = None
self.canvases: Dict[int, CanvasGraph] = {} self.canvases: dict[int, CanvasGraph] = {}
# global edge management # global edge management
self.edges: Dict[str, CanvasEdge] = {} self.edges: dict[str, CanvasEdge] = {}
self.wireless_edges: Dict[str, CanvasWirelessEdge] = {} self.wireless_edges: dict[str, CanvasWirelessEdge] = {}
# global canvas settings # global canvas settings
self.default_dimensions: Tuple[int, int] = ( self.default_dimensions: tuple[int, int] = (
self.app.guiconfig.preferences.width, self.app.guiconfig.preferences.width,
self.app.guiconfig.preferences.height, self.app.guiconfig.preferences.height,
) )
@ -111,8 +112,8 @@ class CanvasManager:
# widget # widget
self.notebook: Optional[ttk.Notebook] = None self.notebook: Optional[ttk.Notebook] = None
self.canvas_ids: Dict[str, int] = {} self.canvas_ids: dict[str, int] = {}
self.unique_ids: Dict[int, str] = {} self.unique_ids: dict[int, str] = {}
self.draw() self.draw()
self.setup_bindings() self.setup_bindings()
@ -273,17 +274,17 @@ class CanvasManager:
if not self.canvases: if not self.canvases:
self.add_canvas() self.add_canvas()
def redraw_canvas(self, dimensions: Tuple[int, int]) -> None: def redraw_canvas(self, dimensions: tuple[int, int]) -> None:
canvas = self.current() canvas = self.current()
canvas.redraw_canvas(dimensions) canvas.redraw_canvas(dimensions)
if canvas.wallpaper: if canvas.wallpaper:
canvas.redraw_wallpaper() canvas.redraw_wallpaper()
def get_metadata(self) -> Dict[str, Any]: def get_metadata(self) -> dict[str, Any]:
canvases = [x.get_metadata() for x in self.all()] canvases = [x.get_metadata() for x in self.all()]
return dict(gridlines=self.show_grid.get(), canvases=canvases) return dict(gridlines=self.show_grid.get(), canvases=canvases)
def parse_metadata_canvas(self, metadata: Dict[str, Any]) -> None: def parse_metadata_canvas(self, metadata: dict[str, Any]) -> None:
# canvas setting # canvas setting
canvas_config = metadata.get("canvas") canvas_config = metadata.get("canvas")
logger.debug("canvas metadata: %s", canvas_config) logger.debug("canvas metadata: %s", canvas_config)
@ -303,7 +304,7 @@ class CanvasManager:
canvas = self.get(canvas_id) canvas = self.get(canvas_id)
canvas.parse_metadata(canvas_config) canvas.parse_metadata(canvas_config)
def parse_metadata_shapes(self, metadata: Dict[str, Any]) -> None: def parse_metadata_shapes(self, metadata: dict[str, Any]) -> None:
# load saved shapes # load saved shapes
shapes_config = metadata.get("shapes") shapes_config = metadata.get("shapes")
if not shapes_config: if not shapes_config:
@ -313,7 +314,7 @@ class CanvasManager:
logger.debug("loading shape: %s", shape_config) logger.debug("loading shape: %s", shape_config)
Shape.from_metadata(self.app, shape_config) Shape.from_metadata(self.app, shape_config)
def parse_metadata_edges(self, metadata: Dict[str, Any]) -> None: def parse_metadata_edges(self, metadata: dict[str, Any]) -> None:
# load edges config # load edges config
edges_config = metadata.get("edges") edges_config = metadata.get("edges")
if not edges_config: if not edges_config:
@ -330,7 +331,7 @@ class CanvasManager:
else: else:
logger.warning("invalid edge token to configure: %s", edge_token) logger.warning("invalid edge token to configure: %s", edge_token)
def parse_metadata_hidden(self, metadata: Dict[str, Any]) -> None: def parse_metadata_hidden(self, metadata: dict[str, Any]) -> None:
# read hidden nodes # read hidden nodes
hidden_config = metadata.get("hidden") hidden_config = metadata.get("hidden")
if not hidden_config: if not hidden_config:

View file

@ -2,7 +2,7 @@ import functools
import logging import logging
import tkinter as tk import tkinter as tk
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple from typing import TYPE_CHECKING, Optional
import grpc import grpc
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
@ -62,17 +62,17 @@ class CanvasNode:
state=self.app.manager.show_node_labels.state(), state=self.app.manager.show_node_labels.state(),
) )
self.tooltip: CanvasTooltip = CanvasTooltip(self.canvas) self.tooltip: CanvasTooltip = CanvasTooltip(self.canvas)
self.edges: Set[CanvasEdge] = set() self.edges: set[CanvasEdge] = set()
self.ifaces: Dict[int, Interface] = {} self.ifaces: dict[int, Interface] = {}
self.wireless_edges: Set[CanvasWirelessEdge] = set() self.wireless_edges: set[CanvasWirelessEdge] = set()
self.antennas: List[int] = [] self.antennas: list[int] = []
self.antenna_images: Dict[int, PhotoImage] = {} self.antenna_images: dict[int, PhotoImage] = {}
self.hidden: bool = False self.hidden: bool = False
self.setup_bindings() self.setup_bindings()
self.context: tk.Menu = tk.Menu(self.canvas) self.context: tk.Menu = tk.Menu(self.canvas)
themes.style_menu(self.context) themes.style_menu(self.context)
def position(self) -> Tuple[int, int]: def position(self) -> tuple[int, int]:
return self.canvas.coords(self.id) return self.canvas.coords(self.id)
def next_iface_id(self) -> int: def next_iface_id(self) -> int:
@ -543,7 +543,7 @@ class ShadowNode:
self.canvas.shadow_nodes[self.id] = self self.canvas.shadow_nodes[self.id] = self
self.canvas.shadow_core_nodes[self.node.core_node.id] = self self.canvas.shadow_core_nodes[self.node.core_node.id] = self
def position(self) -> Tuple[int, int]: def position(self) -> tuple[int, int]:
return self.canvas.coords(self.id) return self.canvas.coords(self.id)
def should_delete(self) -> bool: def should_delete(self) -> bool:

View file

@ -1,5 +1,5 @@
import logging import logging
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from typing import TYPE_CHECKING, Any, Optional, Union
from core.gui.dialogs.shapemod import ShapeDialog from core.gui.dialogs.shapemod import ShapeDialog
from core.gui.graph import tags from core.gui.graph import tags
@ -72,7 +72,7 @@ class Shape:
self.draw() self.draw()
@classmethod @classmethod
def from_metadata(cls, app: "Application", config: Dict[str, Any]) -> None: def from_metadata(cls, app: "Application", config: dict[str, Any]) -> None:
shape_type = config["type"] shape_type = config["type"]
try: try:
shape_type = ShapeType(shape_type) shape_type = ShapeType(shape_type)
@ -144,7 +144,7 @@ class Shape:
logger.error("unknown shape type: %s", self.shape_type) logger.error("unknown shape type: %s", self.shape_type)
self.created = True self.created = True
def get_font(self) -> List[Union[int, str]]: def get_font(self) -> list[Union[int, str]]:
font = [self.shape_data.font, self.shape_data.font_size] font = [self.shape_data.font, self.shape_data.font_size]
if self.shape_data.bold: if self.shape_data.bold:
font.append("bold") font.append("bold")
@ -198,7 +198,7 @@ class Shape:
self.canvas.delete(self.id) self.canvas.delete(self.id)
self.canvas.delete(self.text_id) self.canvas.delete(self.text_id)
def metadata(self) -> Dict[str, Union[str, int, bool]]: def metadata(self) -> dict[str, Union[str, int, bool]]:
coords = self.canvas.coords(self.id) coords = self.canvas.coords(self.id)
# update coords to actual positions # update coords to actual positions
if len(coords) == 4: if len(coords) == 4:

View file

@ -1,5 +1,4 @@
import enum import enum
from typing import Set
class ShapeType(enum.Enum): class ShapeType(enum.Enum):
@ -9,7 +8,7 @@ class ShapeType(enum.Enum):
TEXT = "text" TEXT = "text"
SHAPES: Set[ShapeType] = {ShapeType.OVAL, ShapeType.RECTANGLE} SHAPES: set[ShapeType] = {ShapeType.OVAL, ShapeType.RECTANGLE}
def is_draw_shape(shape_type: ShapeType) -> bool: def is_draw_shape(shape_type: ShapeType) -> bool:

View file

@ -1,5 +1,3 @@
from typing import List
ANNOTATION: str = "annotation" ANNOTATION: str = "annotation"
GRIDLINE: str = "gridline" GRIDLINE: str = "gridline"
SHAPE: str = "shape" SHAPE: str = "shape"
@ -15,7 +13,7 @@ WALLPAPER: str = "wallpaper"
SELECTION: str = "selectednodes" SELECTION: str = "selectednodes"
MARKER: str = "marker" MARKER: str = "marker"
HIDDEN: str = "hidden" HIDDEN: str = "hidden"
ORGANIZE_TAGS: List[str] = [ ORGANIZE_TAGS: list[str] = [
WALLPAPER, WALLPAPER,
GRIDLINE, GRIDLINE,
SHAPE, SHAPE,
@ -29,7 +27,7 @@ ORGANIZE_TAGS: List[str] = [
SELECTION, SELECTION,
MARKER, MARKER,
] ]
RESET_TAGS: List[str] = [ RESET_TAGS: list[str] = [
EDGE, EDGE,
NODE, NODE,
NODE_LABEL, NODE_LABEL,

View file

@ -1,6 +1,6 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Optional, Tuple from typing import TYPE_CHECKING, Optional
from core.gui.themes import Styles from core.gui.themes import Styles
@ -27,7 +27,7 @@ class CanvasTooltip:
self, self,
canvas: "CanvasGraph", canvas: "CanvasGraph",
*, *,
pad: Tuple[int, int, int, int] = (5, 3, 5, 3), pad: tuple[int, int, int, int] = (5, 3, 5, 3),
waittime: int = 400, waittime: int = 400,
wraplength: int = 600 wraplength: int = 600
) -> None: ) -> None:
@ -37,7 +37,7 @@ class CanvasTooltip:
self.wraplength: int = wraplength self.wraplength: int = wraplength
self.canvas: "CanvasGraph" = canvas self.canvas: "CanvasGraph" = canvas
self.text: tk.StringVar = tk.StringVar() self.text: tk.StringVar = tk.StringVar()
self.pad: Tuple[int, int, int, int] = pad self.pad: tuple[int, int, int, int] = pad
self.id: Optional[str] = None self.id: Optional[str] = None
self.tw: Optional[tk.Toplevel] = None self.tw: Optional[tk.Toplevel] = None
@ -63,8 +63,8 @@ class CanvasTooltip:
canvas: "CanvasGraph", canvas: "CanvasGraph",
label: ttk.Label, label: ttk.Label,
*, *,
tip_delta: Tuple[int, int] = (10, 5), tip_delta: tuple[int, int] = (10, 5),
pad: Tuple[int, int, int, int] = (5, 3, 5, 3) pad: tuple[int, int, int, int] = (5, 3, 5, 3)
): ):
c = canvas c = canvas
s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight() s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight()

View file

@ -1,5 +1,5 @@
from enum import Enum from enum import Enum
from typing import Dict, Optional, Tuple from typing import Optional
from PIL import Image from PIL import Image
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
@ -12,7 +12,7 @@ ANTENNA_SIZE: int = 32
BUTTON_SIZE: int = 16 BUTTON_SIZE: int = 16
ERROR_SIZE: int = 24 ERROR_SIZE: int = 24
DIALOG_SIZE: int = 16 DIALOG_SIZE: int = 16
IMAGES: Dict[str, str] = {} IMAGES: dict[str, str] = {}
def load_all() -> None: def load_all() -> None:
@ -87,7 +87,7 @@ class ImageEnum(Enum):
SHADOW = "shadow" SHADOW = "shadow"
TYPE_MAP: Dict[Tuple[NodeType, str], ImageEnum] = { TYPE_MAP: dict[tuple[NodeType, str], ImageEnum] = {
(NodeType.DEFAULT, "router"): ImageEnum.ROUTER, (NodeType.DEFAULT, "router"): ImageEnum.ROUTER,
(NodeType.DEFAULT, "PC"): ImageEnum.PC, (NodeType.DEFAULT, "PC"): ImageEnum.PC,
(NodeType.DEFAULT, "host"): ImageEnum.HOST, (NodeType.DEFAULT, "host"): ImageEnum.HOST,

View file

@ -1,5 +1,5 @@
import logging import logging
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple from typing import TYPE_CHECKING, Any, Optional
import netaddr import netaddr
from netaddr import EUI, IPNetwork from netaddr import EUI, IPNetwork
@ -43,7 +43,7 @@ class Subnets:
def __hash__(self) -> int: def __hash__(self) -> int:
return hash(self.key()) return hash(self.key())
def key(self) -> Tuple[IPNetwork, IPNetwork]: def key(self) -> tuple[IPNetwork, IPNetwork]:
return self.ip4, self.ip6 return self.ip4, self.ip6
def next(self) -> "Subnets": def next(self) -> "Subnets":
@ -61,8 +61,8 @@ class InterfaceManager:
self.mac: EUI = EUI(mac, dialect=netaddr.mac_unix_expanded) self.mac: EUI = EUI(mac, dialect=netaddr.mac_unix_expanded)
self.current_mac: Optional[EUI] = None self.current_mac: Optional[EUI] = None
self.current_subnets: Optional[Subnets] = None self.current_subnets: Optional[Subnets] = None
self.used_subnets: Dict[Tuple[IPNetwork, IPNetwork], Subnets] = {} self.used_subnets: dict[tuple[IPNetwork, IPNetwork], Subnets] = {}
self.used_macs: Set[str] = set() self.used_macs: set[str] = set()
def update_ips(self, ip4: str, ip6: str) -> None: def update_ips(self, ip4: str, ip6: str) -> None:
self.reset() self.reset()
@ -91,7 +91,7 @@ class InterfaceManager:
self.current_subnets = None self.current_subnets = None
self.used_subnets.clear() self.used_subnets.clear()
def removed(self, links: List[Link]) -> None: def removed(self, links: list[Link]) -> None:
# get remaining subnets # get remaining subnets
remaining_subnets = set() remaining_subnets = set()
for edge in self.app.core.links.values(): for edge in self.app.core.links.values():
@ -121,7 +121,7 @@ class InterfaceManager:
subnets.used_indexes.discard(index) subnets.used_indexes.discard(index)
self.current_subnets = None self.current_subnets = None
def set_macs(self, links: List[Link]) -> None: def set_macs(self, links: list[Link]) -> None:
self.current_mac = self.mac self.current_mac = self.mac
self.used_macs.clear() self.used_macs.clear()
for link in links: for link in links:
@ -130,7 +130,7 @@ class InterfaceManager:
if link.iface2: if link.iface2:
self.used_macs.add(link.iface2.mac) self.used_macs.add(link.iface2.mac)
def joined(self, links: List[Link]) -> None: def joined(self, links: list[Link]) -> None:
ifaces = [] ifaces = []
for link in links: for link in links:
if link.iface1: if link.iface1:
@ -208,7 +208,7 @@ class InterfaceManager:
logger.info("ignoring subnet change for link between network nodes") logger.info("ignoring subnet change for link between network nodes")
def find_subnets( def find_subnets(
self, canvas_node: CanvasNode, visited: Set[int] = None self, canvas_node: CanvasNode, visited: set[int] = None
) -> Optional[IPNetwork]: ) -> Optional[IPNetwork]:
logger.info("finding subnet for node: %s", canvas_node.core_node.name) logger.info("finding subnet for node: %s", canvas_node.core_node.name)
subnets = None subnets = None

View file

@ -1,5 +1,5 @@
import logging import logging
from typing import TYPE_CHECKING, List, Optional, Set from typing import TYPE_CHECKING, Optional
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
@ -13,22 +13,22 @@ logger = logging.getLogger(__name__)
if TYPE_CHECKING: if TYPE_CHECKING:
from core.gui.app import Application from core.gui.app import Application
NODES: List["NodeDraw"] = [] NODES: list["NodeDraw"] = []
NETWORK_NODES: List["NodeDraw"] = [] NETWORK_NODES: list["NodeDraw"] = []
NODE_ICONS = {} NODE_ICONS = {}
CONTAINER_NODES: Set[NodeType] = {NodeType.DEFAULT, NodeType.DOCKER, NodeType.LXC} CONTAINER_NODES: set[NodeType] = {NodeType.DEFAULT, NodeType.DOCKER, NodeType.LXC}
IMAGE_NODES: Set[NodeType] = {NodeType.DOCKER, NodeType.LXC} IMAGE_NODES: set[NodeType] = {NodeType.DOCKER, NodeType.LXC}
WIRELESS_NODES: Set[NodeType] = { WIRELESS_NODES: set[NodeType] = {
NodeType.WIRELESS_LAN, NodeType.WIRELESS_LAN,
NodeType.EMANE, NodeType.EMANE,
NodeType.WIRELESS, NodeType.WIRELESS,
} }
RJ45_NODES: Set[NodeType] = {NodeType.RJ45} RJ45_NODES: set[NodeType] = {NodeType.RJ45}
BRIDGE_NODES: Set[NodeType] = {NodeType.HUB, NodeType.SWITCH} BRIDGE_NODES: set[NodeType] = {NodeType.HUB, NodeType.SWITCH}
IGNORE_NODES: Set[NodeType] = {NodeType.CONTROL_NET} IGNORE_NODES: set[NodeType] = {NodeType.CONTROL_NET}
MOBILITY_NODES: Set[NodeType] = {NodeType.WIRELESS_LAN, NodeType.EMANE} MOBILITY_NODES: set[NodeType] = {NodeType.WIRELESS_LAN, NodeType.EMANE}
NODE_MODELS: Set[str] = {"router", "PC", "mdr", "prouter"} NODE_MODELS: set[str] = {"router", "PC", "mdr", "prouter"}
ROUTER_NODES: Set[str] = {"router", "mdr"} ROUTER_NODES: set[str] = {"router", "mdr"}
ANTENNA_ICON: Optional[PhotoImage] = None ANTENNA_ICON: Optional[PhotoImage] = None
@ -106,7 +106,7 @@ def is_iface_node(node: Node) -> bool:
return is_container(node) or is_bridge(node) return is_container(node) or is_bridge(node)
def get_custom_services(gui_config: GuiConfig, name: str) -> List[str]: def get_custom_services(gui_config: GuiConfig, name: str) -> list[str]:
for custom_node in gui_config.nodes: for custom_node in gui_config.nodes:
if custom_node.name == name: if custom_node.name == name:
return custom_node.services return custom_node.services
@ -154,7 +154,7 @@ class NodeDraw:
self.image_file: Optional[str] = None self.image_file: Optional[str] = None
self.node_type: Optional[NodeType] = None self.node_type: Optional[NodeType] = None
self.model: Optional[str] = None self.model: Optional[str] = None
self.services: Set[str] = set() self.services: set[str] = set()
self.label: Optional[str] = None self.label: Optional[str] = None
@classmethod @classmethod

View file

@ -1,13 +1,13 @@
import tkinter as tk import tkinter as tk
from functools import partial from functools import partial
from typing import TYPE_CHECKING, Dict from typing import TYPE_CHECKING
from core.gui.dialogs.observers import ObserverDialog from core.gui.dialogs.observers import ObserverDialog
if TYPE_CHECKING: if TYPE_CHECKING:
from core.gui.app import Application from core.gui.app import Application
OBSERVERS: Dict[str, str] = { OBSERVERS: dict[str, str] = {
"List Processes": "ps", "List Processes": "ps",
"Show Interfaces": "ip address", "Show Interfaces": "ip address",
"IPV4 Routes": "ip -4 route", "IPV4 Routes": "ip -4 route",

View file

@ -3,7 +3,7 @@ status bar
""" """
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, List, Optional from typing import TYPE_CHECKING, Optional
from core.api.grpc.wrappers import ExceptionEvent, ExceptionLevel from core.api.grpc.wrappers import ExceptionEvent, ExceptionLevel
from core.gui.dialogs.alerts import AlertsDialog from core.gui.dialogs.alerts import AlertsDialog
@ -24,7 +24,7 @@ class StatusBar(ttk.Frame):
self.alerts_button: Optional[ttk.Button] = None self.alerts_button: Optional[ttk.Button] = None
self.alert_style = Styles.no_alert self.alert_style = Styles.no_alert
self.running: bool = False self.running: bool = False
self.core_alarms: List[ExceptionEvent] = [] self.core_alarms: list[ExceptionEvent] = []
self.draw() self.draw()
def draw(self) -> None: def draw(self) -> None:

View file

@ -2,7 +2,7 @@ import logging
import threading import threading
import time import time
import tkinter as tk import tkinter as tk
from typing import TYPE_CHECKING, Any, Callable, Optional, Tuple from typing import TYPE_CHECKING, Any, Callable, Optional
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -17,7 +17,7 @@ class ProgressTask:
title: str, title: str,
task: Callable, task: Callable,
callback: Callable = None, callback: Callable = None,
args: Tuple[Any] = None, args: tuple[Any] = None,
): ):
self.app: "Application" = app self.app: "Application" = app
self.title: str = title self.title: str = title
@ -25,7 +25,7 @@ class ProgressTask:
self.callback: Callable = callback self.callback: Callable = callback
if args is None: if args is None:
args = () args = ()
self.args: Tuple[Any] = args self.args: tuple[Any] = args
self.time: Optional[float] = None self.time: Optional[float] = None
def start(self) -> None: def start(self) -> None:

View file

@ -1,10 +1,9 @@
import tkinter as tk import tkinter as tk
from tkinter import font, ttk from tkinter import font, ttk
from typing import Dict, Tuple
THEME_DARK: str = "black" THEME_DARK: str = "black"
PADX: Tuple[int, int] = (0, 5) PADX: tuple[int, int] = (0, 5)
PADY: Tuple[int, int] = (0, 5) PADY: tuple[int, int] = (0, 5)
FRAME_PAD: int = 5 FRAME_PAD: int = 5
DIALOG_PAD: int = 5 DIALOG_PAD: int = 5
@ -201,7 +200,7 @@ def theme_change(event: tk.Event) -> None:
_alert_style(style, Styles.red_alert, "red") _alert_style(style, Styles.red_alert, "red")
def scale_fonts(fonts_size: Dict[str, int], scale: float) -> None: def scale_fonts(fonts_size: dict[str, int], scale: float) -> None:
for name in font.names(): for name in font.names():
f = font.nametofont(name) f = font.nametofont(name)
if name in fonts_size: if name in fonts_size:

View file

@ -3,7 +3,7 @@ import tkinter as tk
from enum import Enum from enum import Enum
from functools import partial from functools import partial
from tkinter import ttk from tkinter import ttk
from typing import TYPE_CHECKING, Callable, List, Optional from typing import TYPE_CHECKING, Callable, Optional
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
@ -90,7 +90,7 @@ class ButtonBar(ttk.Frame):
def __init__(self, master: tk.Widget, app: "Application") -> None: def __init__(self, master: tk.Widget, app: "Application") -> None:
super().__init__(master) super().__init__(master)
self.app: "Application" = app self.app: "Application" = app
self.radio_buttons: List[ttk.Button] = [] self.radio_buttons: list[ttk.Button] = []
def create_button( def create_button(
self, image_enum: ImageEnum, func: Callable, tooltip: str, radio: bool = False self, image_enum: ImageEnum, func: Callable, tooltip: str, radio: bool = False
@ -303,7 +303,7 @@ class Toolbar(ttk.Frame):
) )
task.start() task.start()
def start_callback(self, result: bool, exceptions: List[str]) -> None: def start_callback(self, result: bool, exceptions: list[str]) -> None:
self.set_runtime() self.set_runtime()
self.app.core.show_mobility_players() self.app.core.show_mobility_players()
if not result and exceptions: if not result and exceptions:

View file

@ -5,7 +5,7 @@ from typing import Optional
from core.gui.themes import Styles from core.gui.themes import Styles
class Tooltip(object): class Tooltip:
""" """
Create tool tip for a given widget Create tool tip for a given widget
""" """

View file

@ -3,8 +3,9 @@ input validation
""" """
import re import re
import tkinter as tk import tkinter as tk
from re import Pattern
from tkinter import ttk from tkinter import ttk
from typing import Any, Optional, Pattern from typing import Any, Optional
SMALLEST_SCALE: float = 0.5 SMALLEST_SCALE: float = 0.5
LARGEST_SCALE: float = 5.0 LARGEST_SCALE: float = 5.0

View file

@ -3,7 +3,7 @@ import tkinter as tk
from functools import partial from functools import partial
from pathlib import Path from pathlib import Path
from tkinter import filedialog, font, ttk from tkinter import filedialog, font, ttk
from typing import TYPE_CHECKING, Any, Callable, Dict, Set, Type from typing import TYPE_CHECKING, Any, Callable
from core.api.grpc.wrappers import ConfigOption, ConfigOptionType from core.api.grpc.wrappers import ConfigOption, ConfigOptionType
from core.gui import appconfig, themes, validation from core.gui import appconfig, themes, validation
@ -15,7 +15,7 @@ logger = logging.getLogger(__name__)
if TYPE_CHECKING: if TYPE_CHECKING:
from core.gui.app import Application from core.gui.app import Application
INT_TYPES: Set[ConfigOptionType] = { INT_TYPES: set[ConfigOptionType] = {
ConfigOptionType.UINT8, ConfigOptionType.UINT8,
ConfigOptionType.UINT16, ConfigOptionType.UINT16,
ConfigOptionType.UINT32, ConfigOptionType.UINT32,
@ -40,7 +40,7 @@ class FrameScroll(ttk.Frame):
self, self,
master: tk.Widget, master: tk.Widget,
app: "Application", app: "Application",
_cls: Type[ttk.Frame] = ttk.Frame, _cls: type[ttk.Frame] = ttk.Frame,
**kw: Any **kw: Any
) -> None: ) -> None:
super().__init__(master, **kw) super().__init__(master, **kw)
@ -86,14 +86,14 @@ class ConfigFrame(ttk.Notebook):
self, self,
master: tk.Widget, master: tk.Widget,
app: "Application", app: "Application",
config: Dict[str, ConfigOption], config: dict[str, ConfigOption],
enabled: bool = True, enabled: bool = True,
**kw: Any **kw: Any
) -> None: ) -> None:
super().__init__(master, **kw) super().__init__(master, **kw)
self.app: "Application" = app self.app: "Application" = app
self.config: Dict[str, ConfigOption] = config self.config: dict[str, ConfigOption] = config
self.values: Dict[str, tk.StringVar] = {} self.values: dict[str, tk.StringVar] = {}
self.enabled: bool = enabled self.enabled: bool = enabled
def draw_config(self) -> None: def draw_config(self) -> None:
@ -166,7 +166,7 @@ class ConfigFrame(ttk.Notebook):
logger.error("unhandled config option type: %s", option.type) logger.error("unhandled config option type: %s", option.type)
self.values[option.name] = value self.values[option.name] = value
def parse_config(self) -> Dict[str, str]: def parse_config(self) -> dict[str, str]:
for key in self.config: for key in self.config:
option = self.config[key] option = self.config[key]
value = self.values[key] value = self.values[key]
@ -180,7 +180,7 @@ class ConfigFrame(ttk.Notebook):
option.value = config_value option.value = config_value
return {x: self.config[x].value for x in self.config} return {x: self.config[x].value for x in self.config}
def set_values(self, config: Dict[str, str]) -> None: def set_values(self, config: dict[str, str]) -> None:
for name, data in config.items(): for name, data in config.items():
option = self.config[name] option = self.config[name]
value = self.values[name] value = self.values[name]