Skip to content

doc(mypy): Add type annotations to function definitions #86

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 3 commits into from
Oct 17, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
13 changes: 10 additions & 3 deletions adafruit_hid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,21 @@
"""

# imports
try:
from typing import Sequence
import usb_hid
except ImportError:
pass

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_HID.git"


def find_device(devices, *, usage_page, usage):
"""Search through the provided list of devices to find the one with the matching usage_page and
usage."""
def find_device(
devices: Sequence[usb_hid.device], *, usage_page: int, usage: int
) -> usb_hid.device:
"""Search through the provided sequence of devices to find the one with the matching
usage_page and usage."""
if hasattr(devices, "send_report"):
devices = [devices]
for device in devices:
Expand Down
16 changes: 11 additions & 5 deletions adafruit_hid/consumer_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,20 @@
import time
from . import find_device

try:
from typing import Sequence
import usb_hid
except ImportError:
pass


class ConsumerControl:
"""Send ConsumerControl code reports, used by multimedia keyboards, remote controls, etc."""

def __init__(self, devices):
def __init__(self, devices: Sequence[usb_hid.device]) -> None:
"""Create a ConsumerControl object that will send Consumer Control Device HID reports.

Devices can be a list of devices that includes a Consumer Control device or a CC device
Devices can be a sequence of devices that includes a Consumer Control device or a CC device
itself. A device is any object that implements ``send_report()``, ``usage_page`` and
``usage``.
"""
Expand All @@ -45,7 +51,7 @@ def __init__(self, devices):
time.sleep(1)
self.send(0x0)

def send(self, consumer_code):
def send(self, consumer_code: int) -> None:
"""Send a report to do the specified consumer control action,
and then stop the action (so it will not repeat).

Expand All @@ -64,7 +70,7 @@ def send(self, consumer_code):
self.press(consumer_code)
self.release()

def press(self, consumer_code):
def press(self, consumer_code: int) -> None:
"""Send a report to indicate that the given key has been pressed.
Only one consumer control action can be pressed at a time, so any one
that was previously pressed will be released.
Expand All @@ -83,7 +89,7 @@ def press(self, consumer_code):
struct.pack_into("<H", self._report, 0, consumer_code)
self._consumer_device.send_report(self._report)

def release(self):
def release(self) -> None:
"""Send a report indicating that the consumer control key has been
released. Only one consumer control key can be pressed at a time.

Expand Down
26 changes: 16 additions & 10 deletions adafruit_hid/keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@

from . import find_device

try:
from typing import Sequence
import usb_hid
except ImportError:
pass

_MAX_KEYPRESSES = const(6)


Expand All @@ -33,10 +39,10 @@ class Keyboard:

# No more than _MAX_KEYPRESSES regular keys may be pressed at once.

def __init__(self, devices):
def __init__(self, devices: Sequence[usb_hid.device]) -> None:
"""Create a Keyboard object that will send keyboard HID reports.

Devices can be a list of devices that includes a keyboard device or a keyboard device
Devices can be a sequence of devices that includes a keyboard device or a keyboard device
itself. A device is any object that implements ``send_report()``, ``usage_page`` and
``usage``.
"""
Expand Down Expand Up @@ -64,7 +70,7 @@ def __init__(self, devices):
time.sleep(1)
self.release_all()

def press(self, *keycodes):
def press(self, *keycodes: int) -> None:
"""Send a report indicating that the given keys have been pressed.

:param keycodes: Press these keycodes all at once.
Expand All @@ -90,7 +96,7 @@ def press(self, *keycodes):
self._add_keycode_to_report(keycode)
self._keyboard_device.send_report(self.report)

def release(self, *keycodes):
def release(self, *keycodes: int) -> None:
"""Send a USB HID report indicating that the given keys have been released.

:param keycodes: Release these keycodes all at once.
Expand All @@ -106,21 +112,21 @@ def release(self, *keycodes):
self._remove_keycode_from_report(keycode)
self._keyboard_device.send_report(self.report)

def release_all(self):
def release_all(self) -> None:
"""Release all pressed keys."""
for i in range(8):
self.report[i] = 0
self._keyboard_device.send_report(self.report)

def send(self, *keycodes):
def send(self, *keycodes: int) -> None:
"""Press the given keycodes and then release all pressed keys.

:param keycodes: keycodes to send together
"""
self.press(*keycodes)
self.release_all()

def _add_keycode_to_report(self, keycode):
def _add_keycode_to_report(self, keycode: int) -> None:
"""Add a single keycode to the USB HID report."""
modifier = Keycode.modifier_bit(keycode)
if modifier:
Expand All @@ -141,7 +147,7 @@ def _add_keycode_to_report(self, keycode):
# All slots are filled.
raise ValueError("Trying to press more than six keys at once.")

def _remove_keycode_from_report(self, keycode):
def _remove_keycode_from_report(self, keycode: int) -> None:
"""Remove a single keycode from the report."""
modifier = Keycode.modifier_bit(keycode)
if modifier:
Expand All @@ -154,11 +160,11 @@ def _remove_keycode_from_report(self, keycode):
self.report_keys[i] = 0

@property
def led_status(self):
def led_status(self) -> bytes:
"""Returns the last received report"""
return self._keyboard_device.last_received_report

def led_on(self, led_code):
def led_on(self, led_code: int) -> bool:
"""Returns whether an LED is on based on the led code

Examples::
Expand Down
14 changes: 10 additions & 4 deletions adafruit_hid/keyboard_layout_us.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@

from .keycode import Keycode

try:
from .keyboard import Keyboard
from typing import Tuple
except ImportError:
pass


class KeyboardLayoutUS:
"""Map ASCII characters to appropriate keypresses on a standard US PC keyboard.
Expand Down Expand Up @@ -163,7 +169,7 @@ class KeyboardLayoutUS:
b"\x4c" # DEL DELETE (called Forward Delete in usb.org document)
)

def __init__(self, keyboard):
def __init__(self, keyboard: Keyboard) -> None:
"""Specify the layout for the given keyboard.

:param keyboard: a Keyboard object. Write characters to this keyboard when requested.
Expand All @@ -176,7 +182,7 @@ def __init__(self, keyboard):

self.keyboard = keyboard

def write(self, string):
def write(self, string: str) -> None:
"""Type the string by pressing and releasing keys on my keyboard.

:param string: A string of ASCII characters.
Expand All @@ -197,7 +203,7 @@ def write(self, string):
self.keyboard.press(keycode)
self.keyboard.release_all()

def keycodes(self, char):
def keycodes(self, char: str) -> Tuple[int, ...]:
"""Return a tuple of keycodes needed to type the given character.

:param char: A single ASCII character in a string.
Expand All @@ -222,7 +228,7 @@ def keycodes(self, char):

return (keycode,)

def _char_to_keycode(self, char):
def _char_to_keycode(self, char: str) -> int:
"""Return the HID keycode for the given ASCII character, with the SHIFT_FLAG possibly set.

If the character requires pressing the Shift key, the SHIFT_FLAG bit is set.
Expand Down
7 changes: 6 additions & 1 deletion adafruit_hid/keycode.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
* Author(s): Scott Shawcroft, Dan Halbert
"""

try:
import typing # pylint: disable=unused-import
except ImportError:
pass


class Keycode:
"""USB HID Keycode constants.
Expand Down Expand Up @@ -299,7 +304,7 @@ class Keycode:

# pylint: enable-msg=invalid-name
@classmethod
def modifier_bit(cls, keycode):
def modifier_bit(cls, keycode: int) -> int:
"""Return the modifer bit to be set in an HID keycode report if this is a
modifier key; otherwise return 0."""
return (
Expand Down
24 changes: 15 additions & 9 deletions adafruit_hid/mouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@

from . import find_device

try:
from typing import Sequence
import usb_hid
except ImportError:
pass


class Mouse:
"""Send USB HID mouse reports."""
Expand All @@ -23,10 +29,10 @@ class Mouse:
MIDDLE_BUTTON = 4
"""Middle mouse button."""

def __init__(self, devices):
def __init__(self, devices: Sequence[usb_hid.device]):
"""Create a Mouse object that will send USB mouse HID reports.

Devices can be a list of devices that includes a keyboard device or a keyboard device
Devices can be a sequence of devices that includes a keyboard device or a keyboard device
itself. A device is any object that implements ``send_report()``, ``usage_page`` and
``usage``.
"""
Expand All @@ -47,7 +53,7 @@ def __init__(self, devices):
time.sleep(1)
self._send_no_move()

def press(self, buttons):
def press(self, buttons: int) -> None:
"""Press the given mouse buttons.

:param buttons: a bitwise-or'd combination of ``LEFT_BUTTON``,
Expand All @@ -64,7 +70,7 @@ def press(self, buttons):
self.report[0] |= buttons
self._send_no_move()

def release(self, buttons):
def release(self, buttons: int) -> None:
"""Release the given mouse buttons.

:param buttons: a bitwise-or'd combination of ``LEFT_BUTTON``,
Expand All @@ -73,12 +79,12 @@ def release(self, buttons):
self.report[0] &= ~buttons
self._send_no_move()

def release_all(self):
def release_all(self) -> None:
"""Release all the mouse buttons."""
self.report[0] = 0
self._send_no_move()

def click(self, buttons):
def click(self, buttons: int) -> None:
"""Press and release the given mouse buttons.

:param buttons: a bitwise-or'd combination of ``LEFT_BUTTON``,
Expand All @@ -96,7 +102,7 @@ def click(self, buttons):
self.press(buttons)
self.release(buttons)

def move(self, x=0, y=0, wheel=0):
def move(self, x: int = 0, y: int = 0, wheel: int = 0) -> None:
"""Move the mouse and turn the wheel as directed.

:param x: Move the mouse along the x axis. Negative is to the left, positive
Expand Down Expand Up @@ -134,13 +140,13 @@ def move(self, x=0, y=0, wheel=0):
y -= partial_y
wheel -= partial_wheel

def _send_no_move(self):
def _send_no_move(self) -> None:
"""Send a button-only report."""
self.report[1] = 0
self.report[2] = 0
self.report[3] = 0
self._mouse_device.send_report(self.report)

@staticmethod
def _limit(dist):
def _limit(dist: int) -> int:
return min(127, max(-127, dist))