diff --git a/src/blinkstick/backends/base.py b/src/blinkstick/backends/base.py index 1e18472..7e0e1ed 100644 --- a/src/blinkstick/backends/base.py +++ b/src/blinkstick/backends/base.py @@ -29,17 +29,17 @@ def control_transfer(self, bmRequestType: int, bRequest: int, wValue: int, wInde raise NotImplementedError @abstractmethod - def get_serial(self): + def get_serial(self) -> str: raise NotImplementedError @abstractmethod - def get_manufacturer(self): + def get_manufacturer(self) -> str: raise NotImplementedError @abstractmethod - def get_version_attribute(self): + def get_version_attribute(self) -> int: raise NotImplementedError @abstractmethod - def get_description(self): + def get_description(self) -> str: raise NotImplementedError diff --git a/src/blinkstick/backends/unix_like.py b/src/blinkstick/backends/unix_like.py index bfd8add..e2a7172 100644 --- a/src/blinkstick/backends/unix_like.py +++ b/src/blinkstick/backends/unix_like.py @@ -10,6 +10,8 @@ class UnixLikeBackend(BaseBackend): + serial: str + def __init__(self, device=None): self.device = device super().__init__() @@ -17,7 +19,7 @@ def __init__(self, device=None): self.open_device() self.serial = self.get_serial() - def open_device(self): + def open_device(self) -> None: if self.device is None: raise BlinkStickException("Could not find BlinkStick...") @@ -27,8 +29,6 @@ def open_device(self): except usb.core.USBError as e: raise BlinkStickException("Could not detach kernel driver: %s" % str(e)) - return True - def _refresh_device(self): if not self.serial: return False @@ -67,23 +67,23 @@ def control_transfer(self, bmRequestType: int, bRequest: int, wValue: int, wInde def get_serial(self) -> str: return self._usb_get_string(3) - def get_manufacturer(self): + def get_manufacturer(self)-> str: return self._usb_get_string(1) - def get_version_attribute(self): - return self.device.bcdDevice + def get_version_attribute(self) -> int: + return int(self.device.bcdDevice) def get_description(self): return self._usb_get_string(2) - def _usb_get_string(self, index): + def _usb_get_string(self, index: int) -> str: try: - return usb.util.get_string(self.device, index, 1033) + return str(usb.util.get_string(self.device, index, 1033)) except usb.USBError: # Could not communicate with BlinkStick backend # attempt to find it again based on serial if self._refresh_device(): - return usb.util.get_string(self.device, index, 1033) + return str(usb.util.get_string(self.device, index, 1033)) else: raise BlinkStickException("Could not communicate with BlinkStick {0} - it may have been removed".format(self.serial)) \ No newline at end of file diff --git a/src/blinkstick/backends/win32.py b/src/blinkstick/backends/win32.py index 42ad5b4..a383cdc 100644 --- a/src/blinkstick/backends/win32.py +++ b/src/blinkstick/backends/win32.py @@ -65,14 +65,14 @@ def control_transfer(self, bmRequestType, bRequest, wValue, wIndex, data_or_wLen elif bmRequestType == 0x80 | 0x20: return self.reports[wValue - 1].get() - def get_serial(self): - return self.device.serial_number + def get_serial(self) -> str: + return str(self.device.serial_number) - def get_manufacturer(self): - return self.device.vendor_name + def get_manufacturer(self) -> str: + return str(self.device.vendor_name) - def get_version_attribute(self): - return self.device.version_number + def get_version_attribute(self) -> int: + return int(self.device.version_number) - def get_description(self): - return self.device.product_name \ No newline at end of file + def get_description(self) -> str: + return str(self.device.product_name) \ No newline at end of file diff --git a/src/blinkstick/blinkstick.py b/src/blinkstick/blinkstick.py index 75955a8..5238fee 100644 --- a/src/blinkstick/blinkstick.py +++ b/src/blinkstick/blinkstick.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys import time import warnings @@ -44,7 +46,10 @@ class BlinkStick: error_reporting = True max_rgb_value: int - def __init__(self, device=None, error_reporting=True): + backend: USBBackend + bs_serial: str + + def __init__(self, device=None, error_reporting: bool=True): """ Constructor for the class. @@ -60,7 +65,7 @@ def __init__(self, device=None, error_reporting=True): self.bs_serial = self.get_serial() - def get_serial(self): + def get_serial(self) -> str: """ Returns the serial number of backend.:: @@ -77,7 +82,7 @@ def get_serial(self): """ return self.backend.get_serial() - def get_manufacturer(self): + def get_manufacturer(self) -> str: """ Get the manufacturer of the backend @@ -110,7 +115,7 @@ def get_variant_string(self) -> str: """ return self.get_variant().description - def get_description(self): + def get_description(self) -> str: """ Get the description of the backend @@ -119,7 +124,7 @@ def get_description(self): """ return self.backend.get_description() - def set_error_reporting(self, error_reporting): + def set_error_reporting(self, error_reporting: bool) -> None: """ Enable or disable error reporting @@ -128,7 +133,7 @@ def set_error_reporting(self, error_reporting): """ self.error_reporting = error_reporting - def set_color(self, channel=0, index=0, red=0, green=0, blue=0, name=None, hex=None): + def set_color(self, channel: int = 0, index: int = 0, red: int = 0, green: int = 0, blue: int = 0, name: str | None = None, hex: str | None = None) -> None : """ Set the color to the backend as RGB @@ -172,7 +177,7 @@ def set_color(self, channel=0, index=0, red=0, green=0, blue=0, name=None, hex=N except Exception: pass - def _determine_rgb(self, red=0, green=0, blue=0, name=None, hex=None): + def _determine_rgb(self, red: int = 0, green: int = 0, blue: int = 0, name: str | None = None, hex: str | None = None) -> tuple[int, int, int]: try: if name: @@ -194,7 +199,7 @@ def _determine_rgb(self, red=0, green=0, blue=0, name=None, hex=None): return red, green, blue - def _get_color_rgb(self, index=0): + def _get_color_rgb(self, index: int = 0) -> tuple[int, int, int]: if index == 0: device_bytes = self.backend.control_transfer(0x80 | 0x20, 0x1, 0x0001, 0, 33) if self.inverse: @@ -206,11 +211,11 @@ def _get_color_rgb(self, index=0): return data[index * 3 + 1], data[index * 3], data[index * 3 + 2] - def _get_color_hex(self, index=0): + def _get_color_hex(self, index: int = 0) -> str: r, g, b = self._get_color_rgb(index) return '#%02x%02x%02x' % (r, g, b) - def get_color(self, index: int=0, color_mode: ColorFormat = ColorFormat.RGB, color_format: str=None): + def get_color(self, index: int=0, color_mode: ColorFormat = ColorFormat.RGB, color_format: str=None) -> tuple[int, int, int] | str: """ Get the current backend color in the defined format. @@ -253,7 +258,7 @@ def get_color(self, index: int=0, color_mode: ColorFormat = ColorFormat.RGB, col return color_funcs.get(color_mode, ColorFormat.RGB)(index) - def _determine_report_id(self, led_count): + def _determine_report_id(self, led_count: int) -> tuple[int, int]: report_id = 9 max_leds = 64 @@ -272,7 +277,7 @@ def _determine_report_id(self, led_count): return report_id, max_leds - def set_led_data(self, channel, data): + def set_led_data(self, channel: int, data: list[int]) -> None: """ Send LED data frame. @@ -294,7 +299,7 @@ def set_led_data(self, channel, data): self.backend.control_transfer(0x20, 0x9, report_id, 0, bytes(bytearray(report))) - def get_led_data(self, count): + def get_led_data(self, count: int) -> list[int]: """ Get LED data frame on the backend. @@ -310,7 +315,7 @@ def get_led_data(self, count): return device_bytes[2: 2 + count * 3] - def set_mode(self, mode): + def set_mode(self, mode: int) -> None: """ Set backend mode for BlinkStick Pro. Device currently supports the following modes: @@ -329,7 +334,7 @@ def set_mode(self, mode): self.backend.control_transfer(0x20, 0x9, 0x0004, 0, control_string) - def get_mode(self): + def get_mode(self) -> int: """ Get BlinkStick Pro mode. Device currently supports the following modes: @@ -352,7 +357,7 @@ def get_mode(self): else: return -1 - def set_led_count(self, count): + def set_led_count(self, count: int) -> None: """ Set number of LEDs for supported devices @@ -364,7 +369,7 @@ def set_led_count(self, count): self.backend.control_transfer(0x20, 0x9, 0x81, 0, control_string) - def get_led_count(self): + def get_led_count(self) -> int: """ Get number of LEDs for supported devices @@ -379,7 +384,7 @@ def get_led_count(self): else: return -1 - def get_info_block1(self): + def get_info_block1(self) -> str: """ Get the infoblock1 of the backend. @@ -399,7 +404,7 @@ def get_info_block1(self): result += chr(i) return result - def get_info_block2(self): + def get_info_block2(self) -> str: """ Get the infoblock2 of the backend. @@ -416,7 +421,7 @@ def get_info_block2(self): result += chr(i) return result - def _data_to_message(self, data): + def _data_to_message(self, data) -> bytes: """ Helper method to convert a string to byte array of 32 bytes. @@ -435,7 +440,7 @@ def _data_to_message(self, data): return bytes - def set_info_block1(self, data): + def set_info_block1(self, data: str) -> None: """ Sets the infoblock1 with specified string. @@ -446,7 +451,7 @@ def set_info_block1(self, data): """ self.backend.control_transfer(0x20, 0x9, 0x0002, 0, self._data_to_message(data)) - def set_info_block2(self, data): + def set_info_block2(self, data: str) -> None: """ Sets the infoblock2 with specified string. @@ -457,19 +462,19 @@ def set_info_block2(self, data): """ self.backend.control_transfer(0x20, 0x9, 0x0003, 0, self._data_to_message(data)) - def set_random_color(self): + def set_random_color(self) -> None: """ Sets random color to the backend. """ self.set_color(name="random") - def turn_off(self): + def turn_off(self) -> None: """ Turns off LED. """ self.set_color() - def pulse(self, channel=0, index=0, red=0, green=0, blue=0, name=None, hex=None, repeats=1, duration=1000, steps=50): + def pulse(self, channel: int = 0, index: int = 0, red: int = 0, green: int = 0, blue: int = 0, name: str | None = None, hex: str | None = None, repeats: int = 1, duration: int = 1000, steps: int = 50) -> None: """ Morph to the specified color from black and back again. @@ -499,7 +504,7 @@ def pulse(self, channel=0, index=0, red=0, green=0, blue=0, name=None, hex=None, self.morph(channel=channel, index=index, red=red, green=green, blue=blue, name=name, hex=hex, duration=duration, steps=steps) self.morph(channel=channel, index=index, red=0, green=0, blue=0, duration=duration, steps=steps) - def blink(self, channel=0, index=0, red=0, green=0, blue=0, name=None, hex=None, repeats=1, delay=500): + def blink(self, channel: int = 0, index: int = 0, red: int = 0, green: int = 0, blue: int = 0, name: str | None = None, hex: str | None = None, repeats: int = 1, delay: int = 500) -> None: """ Blink the specified color. @@ -530,7 +535,7 @@ def blink(self, channel=0, index=0, red=0, green=0, blue=0, name=None, hex=None, time.sleep(ms_delay) self.set_color(channel=channel, index=index) - def morph(self, channel=0, index=0, red=0, green=0, blue=0, name=None, hex=None, duration=1000, steps=50): + def morph(self, channel: int = 0, index: int = 0, red: int = 0, green: int = 0, blue: int = 0, name: str | None = None, hex: str | None = None, duration: int = 1000, steps: int = 50) -> None: """ Morph to the specified color. @@ -661,7 +666,17 @@ class BlinkStickPro: U{https://github.com/arvydas/blinkstick-python/wiki#code-examples-for-blinkstick-pro} """ - def __init__(self, r_led_count=0, g_led_count=0, b_led_count=0, delay=0.002, max_rgb_value=255): + r_led_count: int + g_led_count: int + b_led_count: int + fps_count: int + data_transmission_delay: float + max_rgb_value: int + data: list[list[list[int]]] + bstick: BlinkStick | None + + + def __init__(self, r_led_count: int = 0, g_led_count: int = 0, b_led_count: int = 0, delay: float = 0.002, max_rgb_value: int = 255): """ Initialize BlinkStickPro class. @@ -703,7 +718,7 @@ def __init__(self, r_led_count=0, g_led_count=0, b_led_count=0, delay=0.002, max self.bstick = None - def set_color(self, channel, index, r, g, b, remap_values=True): + def set_color(self, channel: int, index: int, r: int, g: int, b: int, remap_values: bool = True) -> None: """ Set the color of a single pixel @@ -726,7 +741,7 @@ def set_color(self, channel, index, r, g, b, remap_values=True): self.data[channel][index] = [g, r, b] - def get_color(self, channel, index): + def get_color(self, channel: int, index: int) -> tuple[int, int, int]: """ Get the current color of a single pixel. @@ -742,7 +757,7 @@ def get_color(self, channel, index): val = self.data[channel][index] return val[1], val[0], val[2] - def clear(self): + def clear(self) -> None: """ Set all pixels to black in the frame buffer. """ @@ -755,14 +770,14 @@ def clear(self): for x in range(0, self.b_led_count): self.set_color(2, x, 0, 0, 0) - def off(self): + def off(self) -> None: """ Set all pixels to black in on the backend. """ self.clear() self.send_data_all() - def connect(self, serial=None): + def connect(self, serial: str | None = None): """ Connect to the first BlinkStick found @@ -777,7 +792,7 @@ def connect(self, serial=None): return self.bstick is not None - def send_data(self, channel): + def send_data(self, channel: int) -> None: """ Send data stored in the internal buffer to the channel. @@ -794,7 +809,7 @@ def send_data(self, channel): except Exception as e: print("Exception: {0}".format(e)) - def send_data_all(self): + def send_data_all(self) -> None: """ Send data to all channels """ @@ -838,7 +853,17 @@ class BlinkStickProMatrix(BlinkStickPro): """ - def __init__(self, r_columns=0, r_rows=0, g_columns=0, g_rows=0, b_columns=0, b_rows=0, delay=0.002, max_rgb_value=255): + r_columns: int + r_rows: int + g_columns: int + g_rows: int + b_columns: int + b_rows: int + rows: int + cols: int + matrix_data: list[list[int]] + + def __init__(self, r_columns: int = 0, r_rows: int = 0, g_columns: int = 0, g_rows: int = 0, b_columns: int = 0, b_rows: int = 0, delay: float = 0.002, max_rgb_value: int = 255): """ Initialize BlinkStickProMatrix class. @@ -875,7 +900,7 @@ def __init__(self, r_columns=0, r_rows=0, g_columns=0, g_rows=0, b_columns=0, b_ for i in range(0, self.rows * self.cols): self.matrix_data.append([0, 0, 0]) - def set_color(self, x, y, r, g, b, remap_values=True): + def set_color(self, x: int, y: int, r: int, g: int, b: int, remap_values: bool = True) -> None: """ Set the color of a single pixel in the internal framebuffer. @@ -898,10 +923,10 @@ def set_color(self, x, y, r, g, b, remap_values=True): self.matrix_data[self._coord_to_index(x, y)] = [g, r, b] - def _coord_to_index(self, x, y): + def _coord_to_index(self, x: int, y: int) -> int: return y * self.cols + x - def get_color(self, x, y): + def get_color(self, x: int, y: int) -> tuple[int, int, int]: """ Get the current color of a single pixel. @@ -917,7 +942,7 @@ def get_color(self, x, y): val = self.matrix_data[self._coord_to_index(x, y)] return val[1], val[0], val[2] - def shift_left(self, remove=False): + def shift_left(self, remove: bool = False) -> None: """ Shift all LED values in the matrix to the left @@ -943,7 +968,7 @@ def shift_left(self, remove=False): col = temp[y] self.set_color(self.cols - 1, y, col[0], col[1], col[2], False) - def shift_right(self, remove=False): + def shift_right(self, remove: bool = False) -> None: """ Shift all LED values in the matrix to the right @@ -970,7 +995,7 @@ def shift_right(self, remove=False): col = temp[y] self.set_color(0, y, col[0], col[1], col[2], False) - def shift_down(self, remove=False): + def shift_down(self, remove: bool = False) -> None: """ Shift all LED values in the matrix down @@ -997,7 +1022,7 @@ def shift_down(self, remove=False): col = temp[x] self.set_color(x, 0, col[0], col[1], col[2], False) - def shift_up(self, remove=False): + def shift_up(self, remove: bool = False): """ Shift all LED values in the matrix up @@ -1024,7 +1049,7 @@ def shift_up(self, remove=False): col = temp[x] self.set_color(x, self.rows - 1, col[0], col[1], col[2], False) - def number(self, x, y, n, r, g, b): + def number(self, x: int, y: int, n: int, r: int, g: int, b: int) -> None: """ Render a 3x5 number n at location x,y and r,g,b color @@ -1096,7 +1121,7 @@ def number(self, x, y, n, r, g, b): self.set_color(x + 2, y + 1, r, g, b) self.set_color(x + 2, y + 3, r, g, b) - def rectangle(self, x1, y1, x2, y2, r, g, b): + def rectangle(self, x1: int, y1: int, x2: int, y2: int, r: int, g: int, b: int) -> None: """ Draw a rectangle with it's corners at x1:y1 and x2:y2 @@ -1121,7 +1146,7 @@ def rectangle(self, x1, y1, x2, y2, r, g, b): self.line(x2, y1, x2, y2, r, g, b) self.line(x1, y2, x2, y2, r, g, b) - def line(self, x1, y1, x2, y2, r, g, b): + def line(self, x1: int, y1: int, x2: int, y2: int, r: int, g: int, b: int) -> list[tuple[int, int]]: """ Draw a line from x1:y1 and x2:y2 @@ -1178,7 +1203,7 @@ def line(self, x1, y1, x2, y2, r, g, b): points.reverse() return points - def clear(self): + def clear(self) -> None: """ Set all pixels to black in the cached matrix """ @@ -1186,7 +1211,7 @@ def clear(self): for x in range(0, self.cols): self.set_color(x, y, 0, 0, 0) - def send_data(self, channel): + def send_data(self, channel: int) -> None: """ Send data stored in the internal buffer to the channel. @@ -1222,7 +1247,7 @@ def send_data(self, channel): super(BlinkStickProMatrix, self).send_data(channel) -def _find_blicksticks(find_all=True): +def _find_blicksticks(find_all: bool = True) -> list[BlinkStick] | None: if sys.platform == "win32": devices = hid.HidDeviceFilter(vendor_id =VENDOR_ID, product_id =PRODUCT_ID).get_devices() if find_all: @@ -1236,7 +1261,7 @@ def _find_blicksticks(find_all=True): return usb.core.find(find_all=find_all, idVendor=VENDOR_ID, idProduct=PRODUCT_ID) -def find_all(): +def find_all() -> list[BlinkStick]: """ Find all attached BlinkStick devices. @@ -1250,7 +1275,7 @@ def find_all(): return result -def find_first(): +def find_first() -> BlinkStick | None: """ Find first attached BlinkStick. @@ -1263,7 +1288,7 @@ def find_first(): return BlinkStick(device=d) -def find_by_serial(serial=None): +def find_by_serial(serial: str | None = None) -> BlinkStick | None: """ Find BlinkStick backend based on serial number. @@ -1277,5 +1302,5 @@ def find_by_serial(serial=None): return BlinkStick(device=devices[0]) -def get_blinkstick_package_version(): +def get_blinkstick_package_version() -> str: return version("blinkstick") diff --git a/src/blinkstick/constants.py b/src/blinkstick/constants.py index 8a0c755..8cee3b8 100644 --- a/src/blinkstick/constants.py +++ b/src/blinkstick/constants.py @@ -15,11 +15,11 @@ class BlinkStickVariant(Enum): BLINKSTICK_FLEX = (6, "BlinkStick Flex") @property - def value(self): + def value(self) -> int: return self._value_[0] @property - def description(self): + def description(self) -> str: return self._value_[1] @staticmethod