more on type hinting, remove unecessary function comments

This commit is contained in:
Huy Pham 2020-01-13 12:03:13 -08:00
parent 7bbd6aa353
commit eb5f2c5648
34 changed files with 169 additions and 326 deletions

View file

@ -14,7 +14,14 @@ EDGE_COLOR = "#ff0000"
class CanvasWirelessEdge:
def __init__(self, token: Tuple[int, int], position, src: int, dst: int, canvas):
def __init__(
self,
token: Tuple[int, int],
position: Tuple[int, int, int, int],
src: int,
dst: int,
canvas,
):
self.token = token
self.src = src
self.dst = dst
@ -35,11 +42,6 @@ class CanvasEdge:
def __init__(self, x1: int, y1: int, x2: int, y2: int, src: int, canvas):
"""
Create an instance of canvas edge object
:param int x1: source x-coord
:param int y1: source y-coord
:param int x2: destination x-coord
:param int y2: destination y-coord
:param int src: source id
:param coretk.graph.graph.GraphCanvas canvas: canvas object
"""
self.src = src
@ -67,7 +69,7 @@ class CanvasEdge:
self.link = link
self.draw_labels()
def get_coordinates(self):
def get_coordinates(self) -> [int, int, int, int]:
x1, y1, x2, y2 = self.canvas.coords(self.id)
v1 = x2 - x1
v2 = y2 - y1
@ -79,7 +81,7 @@ class CanvasEdge:
y2 = y2 - uy
return x1, y1, x2, y2
def get_midpoint(self):
def get_midpoint(self) -> [float, float]:
x1, y1, x2, y2 = self.canvas.coords(self.id)
x = (x1 + x2) / 2
y = (y1 + y2) / 2
@ -119,8 +121,6 @@ class CanvasEdge:
def update_labels(self):
"""
Move edge labels based on current position.
:return: nothing
"""
x1, y1, x2, y2 = self.get_coordinates()
self.canvas.coords(self.text_src, x1, y1)
@ -158,7 +158,7 @@ class CanvasEdge:
self.canvas.tag_raise(self.src)
self.canvas.tag_raise(self.dst)
def is_wireless(self):
def is_wireless(self) -> [bool, bool]:
src_node = self.canvas.nodes[self.src]
dst_node = self.canvas.nodes[self.dst]
src_node_type = src_node.core_node.type
@ -184,7 +184,6 @@ class CanvasEdge:
dst_node.add_antenna()
elif not is_src_wireless and is_dst_wireless:
src_node.add_antenna()
# TODO: remove this? dont allow linking wireless nodes?
else:
src_node.add_antenna()

View file

@ -1,5 +1,6 @@
import logging
import tkinter as tk
from typing import List, Optional
from PIL import Image, ImageTk
@ -84,13 +85,11 @@ class CanvasGraph(tk.Canvas):
)
self.configure(scrollregion=self.bbox(tk.ALL))
def reset_and_redraw(self, session):
def reset_and_redraw(self, session: core_pb2.Session):
"""
Reset the private variables CanvasGraph object, redraw nodes given the new grpc
client.
:param core.api.grpc.core_pb2.Session session: session to draw
:return: nothing
"""
# hide context
self.hide_context()
@ -114,8 +113,6 @@ class CanvasGraph(tk.Canvas):
def setup_bindings(self):
"""
Bind any mouse events or hot keys to the matching action
:return: nothing
"""
self.bind("<ButtonPress-1>", self.click_press)
self.bind("<ButtonRelease-1>", self.click_release)
@ -135,28 +132,28 @@ class CanvasGraph(tk.Canvas):
self.context.unpost()
self.context = None
def get_actual_coords(self, x, y):
def get_actual_coords(self, x: float, y: float) -> [float, float]:
actual_x = (x - self.offset[0]) / self.ratio
actual_y = (y - self.offset[1]) / self.ratio
return actual_x, actual_y
def get_scaled_coords(self, x, y):
def get_scaled_coords(self, x: float, y: float) -> [float, float]:
scaled_x = (x * self.ratio) + self.offset[0]
scaled_y = (y * self.ratio) + self.offset[1]
return scaled_x, scaled_y
def inside_canvas(self, x, y):
def inside_canvas(self, x: float, y: float) -> [bool, bool]:
x1, y1, x2, y2 = self.bbox(self.grid)
valid_x = x1 <= x <= x2
valid_y = y1 <= y <= y2
return valid_x and valid_y
def valid_position(self, x1, y1, x2, y2):
def valid_position(self, x1: int, y1: int, x2: int, y2: int) -> [bool, bool]:
valid_topleft = self.inside_canvas(x1, y1)
valid_bottomright = self.inside_canvas(x2, y2)
return valid_topleft and valid_bottomright
def set_throughputs(self, throughputs_event):
def set_throughputs(self, throughputs_event: core_pb2.ThroughputsEvent):
for interface_throughput in throughputs_event.interface_throughputs:
node_id = interface_throughput.node_id
interface_id = interface_throughput.interface_id
@ -174,8 +171,6 @@ class CanvasGraph(tk.Canvas):
def draw_grid(self):
"""
Create grid.
:return: nothing
"""
width, height = self.width_and_height()
width = int(width)
@ -187,13 +182,12 @@ class CanvasGraph(tk.Canvas):
self.tag_lower(tags.GRIDLINE)
self.tag_lower(self.grid)
def add_wireless_edge(self, src, dst):
def add_wireless_edge(self, src: CanvasNode, dst: CanvasNode):
"""
add a wireless edge between 2 canvas nodes
:param CanvasNode src: source node
:param CanvasNode dst: destination node
:return: nothing
"""
token = tuple(sorted((src.id, dst.id)))
x1, y1 = self.coords(src.id)
@ -206,18 +200,16 @@ class CanvasGraph(tk.Canvas):
self.tag_raise(src.id)
self.tag_raise(dst.id)
def delete_wireless_edge(self, src, dst):
def delete_wireless_edge(self, src: CanvasNode, dst: CanvasNode):
token = tuple(sorted((src.id, dst.id)))
edge = self.wireless_edges.pop(token)
edge.delete()
src.wireless_edges.remove(edge)
dst.wireless_edges.remove(edge)
def draw_session(self, session):
def draw_session(self, session: core_pb2.Session):
"""
Draw existing session.
:return: nothing
"""
# draw existing nodes
for core_node in session.nodes:
@ -296,25 +288,17 @@ class CanvasGraph(tk.Canvas):
for edge in self.edges.values():
edge.reset()
def canvas_xy(self, event):
def canvas_xy(self, event: tk.Event) -> [float, float]:
"""
Convert window coordinate to canvas coordinate
:param event:
:rtype: (int, int)
:return: x, y canvas coordinate
"""
x = self.canvasx(event.x)
y = self.canvasy(event.y)
return x, y
def get_selected(self, event):
def get_selected(self, event: tk.Event) -> int:
"""
Retrieve the item id that is on the mouse position
:param event: mouse event
:rtype: int
:return: the item that the mouse point to
"""
x, y = self.canvas_xy(event)
overlapping = self.find_overlapping(x, y, x, y)
@ -332,7 +316,7 @@ class CanvasGraph(tk.Canvas):
return selected
def click_release(self, event):
def click_release(self, event: tk.Event):
"""
Draw a node or finish drawing an edge according to the current graph mode
@ -380,7 +364,7 @@ class CanvasGraph(tk.Canvas):
self.mode = GraphMode.NODE
self.selected = None
def handle_edge_release(self, event):
def handle_edge_release(self, event: tk.Event):
edge = self.drawing_edge
self.drawing_edge = None
@ -417,7 +401,7 @@ class CanvasGraph(tk.Canvas):
node_dst.edges.add(edge)
self.core.create_link(edge, node_src, node_dst)
def select_object(self, object_id, choose_multiple=False):
def select_object(self, object_id: int, choose_multiple: Optional[bool] = False):
"""
create a bounding box when a node is selected
"""
@ -441,19 +425,17 @@ class CanvasGraph(tk.Canvas):
def clear_selection(self):
"""
Clear current selection boxes.
:return: nothing
"""
for _id in self.selection.values():
self.delete(_id)
self.selection.clear()
def move_selection(self, object_id, x_offset, y_offset):
def move_selection(self, object_id: int, x_offset: float, y_offset: float):
select_id = self.selection.get(object_id)
if select_id is not None:
self.move(select_id, x_offset, y_offset)
def delete_selection_objects(self):
def delete_selection_objects(self) -> List[CanvasNode]:
edges = set()
nodes = []
for object_id in self.selection:
@ -499,7 +481,7 @@ class CanvasGraph(tk.Canvas):
self.selection.clear()
return nodes
def zoom(self, event, factor=None):
def zoom(self, event: tk.Event, factor: Optional[float] = None):
if not factor:
factor = ZOOM_IN if event.delta > 0 else ZOOM_OUT
event.x, event.y = self.canvasx(event.x), self.canvasy(event.y)
@ -517,12 +499,9 @@ class CanvasGraph(tk.Canvas):
if self.wallpaper:
self.redraw_wallpaper()
def click_press(self, event):
def click_press(self, event: tk.Event):
"""
Start drawing an edge if mouse click is on a node
:param event: mouse event
:return: nothing
"""
x, y = self.canvas_xy(event)
if not self.inside_canvas(x, y):
@ -581,7 +560,7 @@ class CanvasGraph(tk.Canvas):
self.select_box = shape
self.clear_selection()
def ctrl_click(self, event):
def ctrl_click(self, event: tk.Event):
# update cursor location
x, y = self.canvas_xy(event)
if not self.inside_canvas(x, y):
@ -599,12 +578,9 @@ class CanvasGraph(tk.Canvas):
):
self.select_object(selected, choose_multiple=True)
def click_motion(self, event):
def click_motion(self, event: tk.Event):
"""
Redraw drawing edge according to the current position of the mouse
:param event: mouse event
:return: nothing
"""
x, y = self.canvas_xy(event)
if not self.inside_canvas(x, y):
@ -658,7 +634,7 @@ class CanvasGraph(tk.Canvas):
if self.select_box and self.mode == GraphMode.SELECT:
self.select_box.shape_motion(x, y)
def click_context(self, event):
def click_context(self, event: tk.Event):
logging.info("context event: %s", self.context)
if not self.context:
selected = self.get_selected(event)
@ -670,24 +646,22 @@ class CanvasGraph(tk.Canvas):
else:
self.hide_context()
def press_delete(self, event):
def press_delete(self, event: tk.Event):
"""
delete selected nodes and any data that relates to it
:param event:
:return:
"""
logging.debug("press delete key")
nodes = self.delete_selection_objects()
self.core.delete_graph_nodes(nodes)
def double_click(self, event):
def double_click(self, event: tk.Event):
selected = self.get_selected(event)
if selected is not None and selected in self.shapes:
shape = self.shapes[selected]
dialog = ShapeDialog(self.app, self.app, shape)
dialog.show()
def add_node(self, x, y):
def add_node(self, x: float, y: float) -> CanvasNode:
if self.selected is None or self.selected in self.shapes:
actual_x, actual_y = self.get_actual_coords(x, y)
core_node = self.core.create_node(
@ -701,26 +675,28 @@ class CanvasGraph(tk.Canvas):
def width_and_height(self):
"""
retrieve canvas width and height in pixels
:return: nothing
"""
x0, y0, x1, y1 = self.coords(self.grid)
canvas_w = abs(x0 - x1)
canvas_h = abs(y0 - y1)
return canvas_w, canvas_h
def get_wallpaper_image(self):
def get_wallpaper_image(self) -> Image.Image:
width = int(self.wallpaper.width * self.ratio)
height = int(self.wallpaper.height * self.ratio)
image = self.wallpaper.resize((width, height), Image.ANTIALIAS)
return image
def draw_wallpaper(self, image, x=None, y=None):
def draw_wallpaper(
self,
image: ImageTk.PhotoImage,
x: Optional[float] = None,
y: Optional[float] = None,
):
if x is None and y is None:
x1, y1, x2, y2 = self.bbox(self.grid)
x = (x1 + x2) / 2
y = (y1 + y2) / 2
self.wallpaper_id = self.create_image((x, y), image=image, tags=tags.WALLPAPER)
self.wallpaper_drawn = image
@ -748,8 +724,6 @@ class CanvasGraph(tk.Canvas):
def wallpaper_center(self):
"""
place the image at the center of canvas
:return: nothing
"""
self.delete(self.wallpaper_id)
@ -773,8 +747,6 @@ class CanvasGraph(tk.Canvas):
def wallpaper_scaled(self):
"""
scale image based on canvas dimension
:return: nothing
"""
self.delete(self.wallpaper_id)
canvas_w, canvas_h = self.width_and_height()
@ -788,7 +760,7 @@ class CanvasGraph(tk.Canvas):
self.redraw_canvas((image.width(), image.height()))
self.draw_wallpaper(image)
def redraw_canvas(self, dimensions=None):
def redraw_canvas(self, dimensions: Optional[List[int]] = None):
logging.info("redrawing canvas to dimensions: %s", dimensions)
# reset scale and move back to original position
@ -836,7 +808,7 @@ class CanvasGraph(tk.Canvas):
else:
self.itemconfig(tags.GRIDLINE, state=tk.HIDDEN)
def set_wallpaper(self, filename):
def set_wallpaper(self, filename: str):
logging.info("setting wallpaper: %s", filename)
if filename:
img = Image.open(filename)
@ -849,16 +821,12 @@ class CanvasGraph(tk.Canvas):
self.wallpaper = None
self.wallpaper_file = None
def is_selection_mode(self):
def is_selection_mode(self) -> bool:
return self.mode == GraphMode.SELECT
def create_edge(self, source, dest):
def create_edge(self, source: CanvasNode, dest: CanvasNode):
"""
create an edge between source node and destination node
:param CanvasNode source: source node
:param CanvasNode dest: destination node
:return: nothing
"""
if (source.id, dest.id) not in self.edges:
pos0 = source.core_node.position

View file

@ -20,7 +20,7 @@ NODE_TEXT_OFFSET = 5
class CanvasNode:
def __init__(self, app, x: int, y: int, core_node: core_pb2.Node, image):
def __init__(self, app, x: float, y: float, core_node: core_pb2.Node, image):
self.app = app
self.canvas = app.canvas
self.image = image
@ -70,8 +70,6 @@ class CanvasNode:
def delete_antenna(self):
"""
delete one antenna
:return: nothing
"""
if self.antennae:
antenna_id = self.antennae.pop()
@ -80,8 +78,6 @@ class CanvasNode:
def delete_antennae(self):
"""
delete all antennas
:return: nothing
"""
for antenna_id in self.antennae:
self.canvas.delete(antenna_id)

View file

@ -1,4 +1,5 @@
import logging
from typing import List, Optional, Union
from core.gui.dialogs.shapemod import ShapeDialog
from core.gui.graph import tags
@ -8,16 +9,16 @@ from core.gui.graph.shapeutils import ShapeType
class AnnotationData:
def __init__(
self,
text="",
font="Arial",
font_size=12,
text_color="#000000",
fill_color="",
border_color="#000000",
border_width=1,
bold=False,
italic=False,
underline=False,
text: Optional[str] = "",
font: Optional[str] = "Arial",
font_size: Optional[int] = 12,
text_color: Optional[str] = "#000000",
fill_color: Optional[str] = "",
border_color: Optional[str] = "#000000",
border_width: Optional[int] = 1,
bold: Optional[bool] = False,
italic: Optional[bool] = False,
underline: Optional[bool] = False,
):
self.text = text
self.font = font
@ -99,7 +100,7 @@ class Shape:
logging.error("unknown shape type: %s", self.shape_type)
self.created = True
def get_font(self):
def get_font(self) -> List[Union[int, str]]:
font = [self.shape_data.font, self.shape_data.font_size]
if self.shape_data.bold:
font.append("bold")
@ -123,10 +124,10 @@ class Shape:
font=font,
)
def shape_motion(self, x1: int, y1: int):
def shape_motion(self, x1: float, y1: float):
self.canvas.coords(self.id, self.x1, self.y1, x1, y1)
def shape_complete(self, x, y):
def shape_complete(self, x: float, y: float):
for component in tags.ABOVE_SHAPE:
self.canvas.tag_raise(component)
s = ShapeDialog(self.app, self.app, self)
@ -135,7 +136,7 @@ class Shape:
def disappear(self):
self.canvas.delete(self.id)
def motion(self, x_offset: int, y_offset: int):
def motion(self, x_offset: float, y_offset: float):
original_position = self.canvas.coords(self.id)
self.canvas.move(self.id, x_offset, y_offset)
coords = self.canvas.coords(self.id)

View file

@ -11,13 +11,13 @@ class ShapeType(enum.Enum):
SHAPES = {ShapeType.OVAL, ShapeType.RECTANGLE}
def is_draw_shape(shape_type):
def is_draw_shape(shape_type: ShapeType) -> bool:
return shape_type in SHAPES
def is_shape_text(shape_type):
def is_shape_text(shape_type: ShapeType) -> bool:
return shape_type == ShapeType.TEXT
def is_marker(shape_type):
def is_marker(shape_type: ShapeType) -> bool:
return shape_type == ShapeType.MARKER

View file

@ -1,5 +1,6 @@
import tkinter as tk
from tkinter import ttk
from typing import Optional
from core.gui.themes import Styles
@ -30,10 +31,10 @@ class CanvasTooltip:
self.id = None
self.tw = None
def on_enter(self, event=None):
def on_enter(self, event: Optional[tk.Event] = None):
self.schedule()
def on_leave(self, event=None):
def on_leave(self, event: Optional[tk.Event] = None):
self.unschedule()
self.hide()
@ -47,7 +48,7 @@ class CanvasTooltip:
if id_:
self.canvas.after_cancel(id_)
def show(self, event=None):
def show(self, event: Optional[tk.Event] = None):
def tip_pos_calculator(canvas, label, *, tip_delta=(10, 5), pad=(5, 3, 5, 3)):
c = canvas
s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight()