Skip to content

MNT: Add type hints to Mouse methods #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 68 additions & 52 deletions botcity/core/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ def get_element_coords_centered(
height: Optional[int] = None,
matching: float = 0.9,
best: bool = True,
):
) -> Union[Tuple[int, int], Tuple[None, None]]:
"""
Find an element defined by label on screen and returns its centered coordinates.

Expand Down Expand Up @@ -807,7 +807,7 @@ def browse(self, url, location=0):
# Mouse
#######

def click_on(self, label):
def click_on(self, label: str) -> None:
"""
Click on the element.

Expand All @@ -819,7 +819,7 @@ def click_on(self, label):
raise ValueError(f"Element not available. Cannot find {label}.")
_mouse_click(self._mouse_controller, x, y)

def get_last_x(self):
def get_last_x(self) -> int:
"""
Get the last X position for the mouse.

Expand All @@ -828,7 +828,7 @@ def get_last_x(self):
"""
return self._mouse_controller.position[0]

def get_last_y(self):
def get_last_y(self) -> int:
"""
Get the last Y position for the mouse.

Expand All @@ -837,7 +837,7 @@ def get_last_y(self):
"""
return self._mouse_controller.position[1]

def mouse_move(self, x, y):
def mouse_move(self, x: int, y: int) -> None:
"""
Move the mouse to the coordinate defined by x and y

Expand All @@ -849,7 +849,7 @@ def mouse_move(self, x, y):
self._mouse_controller.position = (x, y)
self.sleep(config.DEFAULT_SLEEP_AFTER_ACTION)

def click_at(self, x, y):
def click_at(self, x: int, y: int) -> None:
"""
Click at the coordinate defined by x and y

Expand All @@ -862,12 +862,12 @@ def click_at(self, x, y):
@only_if_element
def click(
self,
wait_after=config.DEFAULT_SLEEP_AFTER_ACTION,
wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION,
*,
clicks=1,
interval_between_clicks=0,
button="left",
):
clicks: int = 1,
interval_between_clicks: int = 0,
button: str = "left",
) -> None:
"""
Click on the last found element.

Expand All @@ -878,22 +878,25 @@ def click(
button (str, optional): One of 'left', 'right', 'middle'. Defaults to 'left'
"""
x, y = self.state.center()

mouse_button = mouse_map.get(button, "left")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@welli7ngton I think we'll just need to make a small adjustment.

In the click(), click_relative(), mouse_down() and mouse_up() methods we can remove this treatment:

  • mouse_button = mouse_map.get(button, "left")

I say this because the _mouse_click() method that is invoked expects the parameter to be of type 'str'. This treatment means the mouse_button variable can be an Enum (if it exists in the mouse_map dictionary).

With this, the internal check that is done within the _mouse_click() method would cause the ValueError exception to be thrown: https://github.com/botcity-dev/botcity-framework-core-python/blob/815196110f09b028b9546c0af8bc523cf1ecc8d8/botcity/core/input_utils.py#L77#L80

Since this parameter value check is already done in _mouse_click(), I think we can leave it out of the methods in bot.py. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @joao-voltarelli, i see now, it also ensure consistency in handling mouse button inputs. I agree, ill solve this soon, thanks for the feedback


_mouse_click(
self._mouse_controller, x, y, clicks, interval_between_clicks, button
self._mouse_controller, x, y, clicks, interval_between_clicks, mouse_button
)
self.sleep(wait_after)

@only_if_element
def click_relative(
self,
x,
y,
wait_after=config.DEFAULT_SLEEP_AFTER_ACTION,
x: int,
y: int,
wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION,
*,
clicks=1,
interval_between_clicks=0,
button="left",
):
clicks: int = 1,
interval_between_clicks: int = 0,
button: str = "left",
) -> None:
"""
Click Relative on the last found element.

Expand All @@ -907,13 +910,16 @@ def click_relative(
"""
x = self.state.x() + x
y = self.state.y() + y

mouse_button = mouse_map.get(button, "left")

_mouse_click(
self._mouse_controller, x, y, clicks, interval_between_clicks, button
self._mouse_controller, x, y, clicks, interval_between_clicks, mouse_button
)
self.sleep(wait_after)

@only_if_element
def double_click(self, wait_after=config.DEFAULT_SLEEP_AFTER_ACTION):
def double_click(self, wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION) -> None:
"""
Double Click on the last found element.

Expand All @@ -925,11 +931,11 @@ def double_click(self, wait_after=config.DEFAULT_SLEEP_AFTER_ACTION):
@only_if_element
def double_click_relative(
self,
x,
y,
interval_between_clicks=0,
wait_after=config.DEFAULT_SLEEP_AFTER_ACTION,
):
x: int,
y: int,
interval_between_clicks: int = 0,
wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION,
) -> None:
"""
Double Click Relative on the last found element.

Expand All @@ -949,7 +955,7 @@ def double_click_relative(
)

@only_if_element
def triple_click(self, wait_after=config.DEFAULT_SLEEP_AFTER_ACTION):
def triple_click(self, wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION) -> None:
"""
Triple Click on the last found element.

Expand All @@ -961,11 +967,11 @@ def triple_click(self, wait_after=config.DEFAULT_SLEEP_AFTER_ACTION):
@only_if_element
def triple_click_relative(
self,
x,
y,
interval_between_clicks=0,
wait_after=config.DEFAULT_SLEEP_AFTER_ACTION,
):
x: int,
y: int,
interval_between_clicks: int = 0,
wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION,
) -> None:
"""
Triple Click Relative on the last found element.

Expand All @@ -985,32 +991,42 @@ def triple_click_relative(
)

def mouse_down(
self, wait_after=config.DEFAULT_SLEEP_AFTER_ACTION, *, button="left"
):
self,
wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION,
*,
button: str = "left",
) -> None:
"""
Holds down the requested mouse button.

Args:
wait_after (int, optional): Interval to wait after clicking on the element.
button (str, optional): One of 'left', 'right', 'middle'. Defaults to 'left'
"""
mouse_button = mouse_map.get(button, None)
mouse_button = mouse_map.get(button, "left")

self._mouse_controller.press(mouse_button)
self.sleep(wait_after)

def mouse_up(self, wait_after=config.DEFAULT_SLEEP_AFTER_ACTION, *, button="left"):
def mouse_up(
self,
wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION,
*,
button: str = "left",
) -> None:
"""
Releases the requested mouse button.

Args:
wait_after (int, optional): Interval to wait after clicking on the element.
button (str, optional): One of 'left', 'right', 'middle'. Defaults to 'left'
"""
mouse_button = mouse_map.get(button, None)
mouse_button = mouse_map.get(button, "left")

self._mouse_controller.release(mouse_button)
self.sleep(wait_after)

def scroll_down(self, clicks):
def scroll_down(self, clicks: int) -> None:
"""
Scroll Down n clicks

Expand All @@ -1020,7 +1036,7 @@ def scroll_down(self, clicks):
self._mouse_controller.scroll(0, -1 * clicks)
self.sleep(config.DEFAULT_SLEEP_AFTER_ACTION)

def scroll_up(self, clicks):
def scroll_up(self, clicks: int) -> None:
"""
Scroll Up n clicks

Expand All @@ -1031,15 +1047,15 @@ def scroll_up(self, clicks):
self.sleep(config.DEFAULT_SLEEP_AFTER_ACTION)

@only_if_element
def move(self):
def move(self) -> None:
"""
Move to the center position of last found item.
"""
x, y = self.state.center()
self._mouse_controller.position = (x, y)
self.sleep(config.DEFAULT_SLEEP_AFTER_ACTION)

def move_relative(self, x, y):
def move_relative(self, x: int, y: int) -> None:
"""
Move the mouse relative to its current position.

Expand All @@ -1053,7 +1069,7 @@ def move_relative(self, x, y):
self._mouse_controller.position = (x, y)
self.sleep(config.DEFAULT_SLEEP_AFTER_ACTION)

def move_random(self, range_x, range_y):
def move_random(self, range_x: int, range_y: int) -> None:
"""
Move randomly along the given x, y range.

Expand All @@ -1070,11 +1086,11 @@ def move_random(self, range_x, range_y):
@only_if_element
def right_click(
self,
wait_after=config.DEFAULT_SLEEP_AFTER_ACTION,
wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION,
*,
clicks=1,
interval_between_clicks=0,
):
clicks: int = 1,
interval_between_clicks: int = 0,
) -> None:
"""
Right click on the last found element.

Expand All @@ -1094,7 +1110,7 @@ def right_click(
)
self.sleep(wait_after)

def right_click_at(self, x, y):
def right_click_at(self, x: int, y: int) -> None:
"""
Right click at the coordinate defined by x and y

Expand All @@ -1107,11 +1123,11 @@ def right_click_at(self, x, y):
@only_if_element
def right_click_relative(
self,
x,
y,
interval_between_clicks=0,
wait_after=config.DEFAULT_SLEEP_AFTER_ACTION,
):
x: int,
y: int,
interval_between_clicks: int = 0,
wait_after: int = config.DEFAULT_SLEEP_AFTER_ACTION,
) -> None:
"""
Right Click Relative on the last found element.

Expand Down
62 changes: 35 additions & 27 deletions botcity/core/input_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
from pynput.mouse import Button, Controller

keys_map = {
"num0": '0',
"num1": '1',
"num2": '2',
"num3": '3',
"num4": '4',
"num5": '5',
"num6": '6',
"num7": '7',
"num8": '8',
"num9": '9',
"add": '+',
"decimal": ',',
"subtract": '-',
"multiply": '*',
"divide": '/',
"separator": '|',
"num0": "0",
"num1": "1",
"num2": "2",
"num3": "3",
"num4": "4",
"num5": "5",
"num6": "6",
"num7": "7",
"num8": "8",
"num9": "9",
"add": "+",
"decimal": ",",
"subtract": "-",
"multiply": "*",
"divide": "/",
"separator": "|",
"altleft": Key.alt_l,
"altright": Key.alt_r,
"capslock": Key.caps_lock,
Expand All @@ -43,14 +43,14 @@
"volumeup": Key.media_volume_up,
"prevtrack": Key.media_previous,
"nexttrack": Key.media_next,
"return": Key.enter
"return": Key.enter,
}

if platform.system() != "Darwin":
keys_map.update(
{
"numlock": Key.num_lock,
"prtsc": Key.print_screen,
"prtsc": Key.print_screen,
"prtscr": Key.print_screen,
"printscreen": Key.print_screen,
"prntscrn": Key.print_screen,
Expand All @@ -59,25 +59,33 @@
}
)

mouse_map = {
"left": Button.left,
"right": Button.right,
"middle": Button.middle
}
mouse_map = {"left": Button.left, "right": Button.right, "middle": Button.middle}


def _mouse_click(mouse_controller: Controller, x: int, y: int, clicks=1, interval_between_clicks=0, button='left'):
def _mouse_click(
mouse_controller: Controller,
x: int,
y: int,
clicks: int = 1,
interval_between_clicks: int = 0,
button: str = "left",
) -> None:
"""
Moves the mouse and clicks at the coordinate defined by x and y.
"""
if platform.system() == "Darwin":
from . import os_compat
os_compat.osx_click(x=x, y=y, clicks=clicks, interval=interval_between_clicks, button=button)

os_compat.osx_click(
x=x, y=y, clicks=clicks, interval=interval_between_clicks, button=button
)
else:
mouse_button = mouse_map.get(button, None)
if not mouse_button:
raise ValueError(f'''Invalid mouse button name.
The mouse button has to be one of these values: {list(mouse_map.keys())}''')
raise ValueError(
f"""Invalid mouse button name.
The mouse button has to be one of these values: {list(mouse_map.keys())}"""
)

mouse_controller.position = (x, y)
time.sleep(0.1)
Expand Down