From c4a117a2366b42845ba5f2c8462e80f5668cb2f1 Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Tue, 10 Dec 2019 13:23:03 -0800 Subject: [PATCH 1/2] insert default value to some entry when entry is empty --- coretk/coretk/coreclient.py | 42 +++++-------------- coretk/coretk/dialogs/canvassizeandscale.py | 20 ++++----- coretk/coretk/dialogs/nodeconfig.py | 6 ++- coretk/coretk/dialogs/servers.py | 10 ++++- coretk/coretk/dialogs/serviceconfiguration.py | 1 - coretk/coretk/graph/node.py | 8 +++- coretk/coretk/validation.py | 17 +++++--- coretk/coretk/widgets.py | 10 ++++- 8 files changed, 61 insertions(+), 53 deletions(-) diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 8738c4f7..ad85b689 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -70,8 +70,6 @@ class CoreClient: # helpers self.interface_to_edge = {} self.interfaces_manager = InterfaceManager(self.app) - self.created_nodes = set() - self.created_links = set() # session data self.state = None @@ -90,8 +88,6 @@ class CoreClient: def reset(self): # helpers - self.created_nodes.clear() - self.created_links.clear() self.interfaces_manager.reset() self.interface_to_edge.clear() # session data @@ -181,7 +177,6 @@ class CoreClient: canvas_node.move(x, y, update=False) def handle_throughputs(self, event): - # print(event.interface_throughputs) if self.throughput: self.app.canvas.throughput_draw.process_grpc_throughput_event( event.interface_throughputs @@ -243,8 +238,6 @@ class CoreClient: # save and retrieve data, needed for session nodes for node in session.nodes: # get node service config and file config - self.created_nodes.add(node.id) - # get wlan configs for wlan nodes if node.type == core_pb2.NodeType.WIRELESS_LAN: response = self.client.get_wlan_config(self.session_id, node.id) @@ -435,8 +428,6 @@ class CoreClient: hooks = list(self.hooks.values()) service_configs = self.get_service_config_proto() file_configs = self.get_service_file_config_proto() - self.created_links.clear() - self.created_nodes.clear() if self.emane_config: emane_config = {x: self.emane_config[x].value for x in self.emane_config} else: @@ -585,31 +576,20 @@ class CoreClient: self.session_id, core_pb2.SessionState.DEFINITION ) - # temp self.client.set_session_state(self.session_id, core_pb2.SessionState.DEFINITION) for node_proto in node_protos: - if node_proto.id not in self.created_nodes or True: - response = self.client.add_node(self.session_id, node_proto) - logging.debug("create node: %s", response) - self.created_nodes.add(node_proto.id) + response = self.client.add_node(self.session_id, node_proto) + logging.debug("create node: %s", response) for link_proto in link_protos: - if ( - tuple([link_proto.node_one_id, link_proto.node_two_id]) - not in self.created_links - or True - ): - response = self.client.add_link( - self.session_id, - link_proto.node_one_id, - link_proto.node_two_id, - link_proto.interface_one, - link_proto.interface_two, - link_proto.options, - ) - logging.debug("create link: %s", response) - self.created_links.add( - tuple([link_proto.node_one_id, link_proto.node_two_id]) - ) + response = self.client.add_link( + self.session_id, + link_proto.node_one_id, + link_proto.node_two_id, + link_proto.interface_one, + link_proto.interface_two, + link_proto.options, + ) + logging.debug("create link: %s", response) def close(self): """ diff --git a/coretk/coretk/dialogs/canvassizeandscale.py b/coretk/coretk/dialogs/canvassizeandscale.py index 624e4246..f2bf4fc3 100644 --- a/coretk/coretk/dialogs/canvassizeandscale.py +++ b/coretk/coretk/dialogs/canvassizeandscale.py @@ -66,7 +66,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_int, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=1, sticky="ew", padx=PAD) label = ttk.Label(frame, text="x Height") label.grid(row=0, column=2, sticky="w", padx=PAD) @@ -76,7 +76,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_int, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=3, sticky="ew", padx=PAD) label = ttk.Label(frame, text="Pixels") label.grid(row=0, column=4, sticky="w") @@ -94,7 +94,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_float, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=1, sticky="ew", padx=PAD) label = ttk.Label(frame, text="x Height") label.grid(row=0, column=2, sticky="w", padx=PAD) @@ -104,7 +104,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_float, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=3, sticky="ew", padx=PAD) label = ttk.Label(frame, text="Meters") label.grid(row=0, column=4, sticky="w") @@ -125,7 +125,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_float, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=1, sticky="ew", padx=PAD) label = ttk.Label(frame, text="Meters") label.grid(row=0, column=2, sticky="w") @@ -153,7 +153,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_float, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=1, sticky="ew", padx=PAD) label = ttk.Label(frame, text="Y") @@ -164,7 +164,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_float, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=3, sticky="ew", padx=PAD) label = ttk.Label(label_frame, text="Translates To") @@ -184,7 +184,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_float, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=1, sticky="ew", padx=PAD) label = ttk.Label(frame, text="Lon") @@ -195,7 +195,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_float, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=3, sticky="ew", padx=PAD) label = ttk.Label(frame, text="Alt") @@ -206,7 +206,7 @@ class SizeAndScaleDialog(Dialog): validate="key", validatecommand=(self.validation.positive_float, "%P"), ) - entry.bind("", self.validation.focus_out) + entry.bind("", lambda event: self.validation.focus_out(event, "0")) entry.grid(row=0, column=5, sticky="ew") def draw_save_as_default(self): diff --git a/coretk/coretk/dialogs/nodeconfig.py b/coretk/coretk/dialogs/nodeconfig.py index 9f7c4d6c..8853e908 100644 --- a/coretk/coretk/dialogs/nodeconfig.py +++ b/coretk/coretk/dialogs/nodeconfig.py @@ -75,7 +75,9 @@ class NodeConfigDialog(Dialog): validate="key", validatecommand=(self.app.validation.name, "%P"), ) - entry.bind("", self.app.validation.name_focus_out) + entry.bind( + "", lambda event: self.app.validation.focus_out(event, "noname") + ) entry.grid(row=row, column=1, sticky="ew") row += 1 @@ -165,12 +167,14 @@ class NodeConfigDialog(Dialog): label.grid(row=1, column=0, padx=PAD, pady=PAD) ip4 = tk.StringVar(value=f"{interface.ip4}/{interface.ip4mask}") entry = ttk.Entry(frame, textvariable=ip4) + entry.bind("", self.app.validation.ip_focus_out) entry.grid(row=1, column=1, columnspan=2, sticky="ew") label = ttk.Label(frame, text="IPv6") label.grid(row=2, column=0, padx=PAD, pady=PAD) ip6 = tk.StringVar(value=f"{interface.ip6}/{interface.ip6mask}") entry = ttk.Entry(frame, textvariable=ip6) + entry.bind("", self.app.validation.ip_focus_out) entry.grid(row=2, column=1, columnspan=2, sticky="ew") self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6) diff --git a/coretk/coretk/dialogs/servers.py b/coretk/coretk/dialogs/servers.py index 10a6e79e..9df7bf55 100644 --- a/coretk/coretk/dialogs/servers.py +++ b/coretk/coretk/dialogs/servers.py @@ -72,7 +72,15 @@ class ServersDialog(Dialog): label = ttk.Label(frame, text="Port") label.grid(row=0, column=4, sticky="w") - entry = ttk.Entry(frame, textvariable=self.port) + entry = ttk.Entry( + frame, + textvariable=self.port, + validate="key", + validatecommand=(self.app.validation.positive_int, "%P"), + ) + entry.bind( + "", lambda event: self.app.validation.focus_out(event, "50051") + ) entry.grid(row=0, column=5, sticky="ew") def draw_servers_buttons(self): diff --git a/coretk/coretk/dialogs/serviceconfiguration.py b/coretk/coretk/dialogs/serviceconfiguration.py index 354937e5..01610eb1 100644 --- a/coretk/coretk/dialogs/serviceconfiguration.py +++ b/coretk/coretk/dialogs/serviceconfiguration.py @@ -51,7 +51,6 @@ class ServiceConfiguration(Dialog): def load(self): try: - # create nodes and links in definition state for getting and setting service file self.app.core.create_nodes_and_links() service_configs = self.app.core.service_configs if ( diff --git a/coretk/coretk/graph/node.py b/coretk/coretk/graph/node.py index ede26440..bfc11cbf 100644 --- a/coretk/coretk/graph/node.py +++ b/coretk/coretk/graph/node.py @@ -8,6 +8,7 @@ from core.api.grpc.core_pb2 import NodeType from coretk.dialogs.emaneconfig import EmaneConfigDialog from coretk.dialogs.mobilityconfig import MobilityConfigDialog from coretk.dialogs.nodeconfig import NodeConfigDialog +from coretk.dialogs.nodeservice import NodeService from coretk.dialogs.wlanconfig import WlanConfigDialog from coretk.errors import show_grpc_error from coretk.graph import tags @@ -217,7 +218,7 @@ class CanvasNode: else: context.add_command(label="Configure", command=self.show_config) if NodeUtils.is_container_node(self.core_node.type): - context.add_command(label="Services", state=tk.DISABLED) + context.add_command(label="Services", command=self.show_services) if is_emane: context.add_command( label="EMANE Config", command=self.show_emane_config @@ -268,3 +269,8 @@ class CanvasNode: self.canvas.context = None dialog = EmaneConfigDialog(self.app, self.app, self) dialog.show() + + def show_services(self): + self.canvas.context = None + dialog = NodeService(self.app.master, self.app, self) + dialog.show() diff --git a/coretk/coretk/validation.py b/coretk/coretk/validation.py index a580c712..403e073d 100644 --- a/coretk/coretk/validation.py +++ b/coretk/coretk/validation.py @@ -4,6 +4,9 @@ input validation import logging import tkinter as tk +import netaddr +from netaddr import IPNetwork + class InputValidation: def __init__(self, app): @@ -18,16 +21,18 @@ class InputValidation: self.positive_float = self.master.register(self.check_positive_float) self.name = self.master.register(self.check_node_name) - def focus_out(self, event): + def ip_focus_out(self, event): value = event.widget.get() - if value == "": - event.widget.insert(tk.END, 0) + try: + IPNetwork(value) + except netaddr.core.AddrFormatError: + event.widget.delete(0, tk.END) + event.widget.insert(tk.END, "invalid") - def name_focus_out(self, event): - logging.debug("name focus out") + def focus_out(self, event, default): value = event.widget.get() if value == "": - event.widget.insert(tk.END, "empty") + event.widget.insert(tk.END, default) def check_positive_int(self, s): logging.debug("int validation...") diff --git a/coretk/coretk/widgets.py b/coretk/coretk/widgets.py index 7d908476..68983210 100644 --- a/coretk/coretk/widgets.py +++ b/coretk/coretk/widgets.py @@ -127,7 +127,10 @@ class ConfigFrame(FrameScroll): validate="key", validatecommand=(self.app.validation.positive_int, "%P"), ) - entry.bind("", self.app.validation.focus_out) + entry.bind( + "", + lambda event: self.app.validation.focus_out(event, "0"), + ) entry.grid(row=index, column=1, sticky="ew", pady=pady) elif option.type == core_pb2.ConfigOptionType.FLOAT: value.set(option.value) @@ -137,7 +140,10 @@ class ConfigFrame(FrameScroll): validate="key", validatecommand=(self.app.validation.positive_float, "%P"), ) - entry.bind("", self.app.validation.focus_out) + entry.bind( + "", + lambda event: self.app.validation.focus_out(event, "0"), + ) entry.grid(row=index, column=1, sticky="ew", pady=pady) else: logging.error("unhandled config option type: %s", option.type) From 6a42748191f07e8bd3611d564641d3b06fa17125 Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Tue, 10 Dec 2019 16:50:28 -0800 Subject: [PATCH 2/2] controlnet validation --- coretk/coretk/validation.py | 24 ++++++++++++++++++------ coretk/coretk/widgets.py | 14 ++++++++++++-- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/coretk/coretk/validation.py b/coretk/coretk/validation.py index 403e073d..68fc79c3 100644 --- a/coretk/coretk/validation.py +++ b/coretk/coretk/validation.py @@ -1,7 +1,7 @@ """ input validation """ -import logging +import re import tkinter as tk import netaddr @@ -14,12 +14,14 @@ class InputValidation: self.positive_int = None self.positive_float = None self.name = None + self.ip4 = None self.register() def register(self): self.positive_int = self.master.register(self.check_positive_int) self.positive_float = self.master.register(self.check_positive_float) self.name = self.master.register(self.check_node_name) + self.ip4 = self.master.register(self.check_ip4) def ip_focus_out(self, event): value = event.widget.get() @@ -35,7 +37,6 @@ class InputValidation: event.widget.insert(tk.END, default) def check_positive_int(self, s): - logging.debug("int validation...") if len(s) == 0: return True try: @@ -47,7 +48,6 @@ class InputValidation: return False def check_positive_float(self, s): - logging.debug("float validation...") if len(s) == 0: return True try: @@ -59,7 +59,6 @@ class InputValidation: return False def check_node_name(self, s): - logging.debug("node name validation...") if len(s) < 0: return False if len(s) == 0: @@ -70,7 +69,6 @@ class InputValidation: return True def check_canvas_int(sefl, s): - logging.debug("int validation...") if len(s) == 0: return True try: @@ -82,7 +80,6 @@ class InputValidation: return False def check_canvas_float(self, s): - logging.debug("canvas float validation") if not s: return True try: @@ -92,3 +89,18 @@ class InputValidation: return False except ValueError: return False + + def check_ip4(self, s): + if not s: + return True + pat = re.compile("^([0-9]+[.])*[0-9]*$") + if pat.match(s) is not None: + _32bits = s.split(".") + if len(_32bits) > 4: + return False + for _8bits in _32bits: + if (_8bits and int(_8bits) > 255) or len(_8bits) > 3: + return False + return True + else: + return False diff --git a/coretk/coretk/widgets.py b/coretk/coretk/widgets.py index 68983210..fb5582a1 100644 --- a/coretk/coretk/widgets.py +++ b/coretk/coretk/widgets.py @@ -117,8 +117,18 @@ class ConfigFrame(FrameScroll): button = ttk.Button(file_frame, text="...", command=func) button.grid(row=0, column=1) else: - entry = ttk.Entry(frame, textvariable=value) - entry.grid(row=index, column=1, sticky="ew", pady=pady) + if "controlnet" in option.name and "script" not in option.name: + entry = ttk.Entry( + frame, + textvariable=value, + validate="key", + validatecommand=(self.app.validation.ip4, "%P"), + ) + entry.grid(row=index, column=1, sticky="ew", pady=pady) + else: + entry = ttk.Entry(frame, textvariable=value) + entry.grid(row=index, column=1, sticky="ew", pady=pady) + elif option.type in INT_TYPES: value.set(option.value) entry = ttk.Entry(