From ffd1f1d9f08dc9df6ea1a4ac08338e999b052f75 Mon Sep 17 00:00:00 2001 From: dherrada Date: Mon, 16 Mar 2020 15:39:06 -0400 Subject: [PATCH 1/2] Ran black, updated to pylint 2.x --- .github/workflows/build.yml | 2 +- adafruit_ble/__init__.py | 54 ++- adafruit_ble/advertising/__init__.py | 39 +- adafruit_ble/advertising/adafruit.py | 29 +- adafruit_ble/advertising/standard.py | 85 +++-- adafruit_ble/attributes/__init__.py | 2 + adafruit_ble/characteristics/__init__.py | 85 ++++- adafruit_ble/characteristics/float.py | 25 +- adafruit_ble/characteristics/int.py | 47 ++- adafruit_ble/characteristics/stream.py | 61 ++- adafruit_ble/characteristics/string.py | 40 +- adafruit_ble/services/__init__.py | 11 +- adafruit_ble/services/circuitpython.py | 12 +- adafruit_ble/services/midi.py | 20 +- adafruit_ble/services/nordic.py | 16 +- adafruit_ble/services/sphero.py | 2 + adafruit_ble/services/standard/__init__.py | 24 +- adafruit_ble/services/standard/device_info.py | 57 +-- adafruit_ble/services/standard/hid.py | 355 ++++++++++-------- adafruit_ble/uuid/__init__.py | 6 + docs/conf.py | 113 +++--- examples/ble_bluefruit_connect_plotter.py | 2 +- examples/ble_color_proximity.py | 24 +- examples/ble_demo_central.py | 4 +- examples/ble_demo_periph.py | 1 + examples/ble_hid_periph.py | 5 +- examples/ble_uart_echo_client.py | 4 +- setup.py | 51 +-- 28 files changed, 765 insertions(+), 411 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fff3aa9..1dad804 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: source actions-ci/install.sh - name: Pip install pylint, black, & Sphinx run: | - pip install --force-reinstall pylint==1.9.2 black==19.10b0 Sphinx sphinx-rtd-theme + pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme - name: Library version run: git describe --dirty --always --tags - name: PyLint diff --git a/adafruit_ble/__init__.py b/adafruit_ble/__init__.py index ec8b949..12b88e6 100755 --- a/adafruit_ble/__init__.py +++ b/adafruit_ble/__init__.py @@ -26,12 +26,14 @@ building on the native `_bleio` module. """ -#pylint: disable=wrong-import-position +# pylint: disable=wrong-import-position import sys -if sys.implementation.name == 'circuitpython' and sys.implementation.version[0] <= 4: + +if sys.implementation.name == "circuitpython" and sys.implementation.version[0] <= 4: raise ImportError( - "This release is not compatible with CircuitPython 4.x; use library release 1.x.x") -#pylint: enable=wrong-import-position + "This release is not compatible with CircuitPython 4.x; use library release 1.x.x" + ) +# pylint: enable=wrong-import-position import _bleio @@ -41,6 +43,7 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git" + class BLEConnection: """ Represents a connection to a peer BLE device. @@ -49,6 +52,7 @@ class BLEConnection: :param bleio_connection _bleio.Connection: the native `_bleio.Connection` object to wrap """ + def __init__(self, bleio_connection): self._bleio_connection = bleio_connection # _bleio.Service objects representing services found during discovery. @@ -61,7 +65,9 @@ def _discover_remote(self, uuid): if uuid in self._discovered_bleio_services: remote_service = self._discovered_bleio_services[uuid] else: - results = self._bleio_connection.discover_remote_services((uuid.bleio_uuid,)) + results = self._bleio_connection.discover_remote_services( + (uuid.bleio_uuid,) + ) if results: remote_service = results[0] self._discovered_bleio_services[uuid] = remote_service @@ -140,6 +146,7 @@ def disconnect(self): """Disconnect from peer.""" self._bleio_connection.disconnect() + class BLERadio: """ BLERadio provides the interfaces for BLE advertising, @@ -172,17 +179,28 @@ def start_advertising(self, advertisement, scan_response=None, interval=0.1): scan_response.tx_power = self.tx_power if scan_response: scan_response_bytes = bytes(scan_response) - self._adapter.start_advertising(advertisement_bytes, - scan_response=scan_response_bytes, - connectable=advertisement.connectable, - interval=interval) + self._adapter.start_advertising( + advertisement_bytes, + scan_response=scan_response_bytes, + connectable=advertisement.connectable, + interval=interval, + ) def stop_advertising(self): """Stops advertising.""" self._adapter.stop_advertising() - def start_scan(self, *advertisement_types, buffer_size=512, extended=False, timeout=None, - interval=0.1, window=0.1, minimum_rssi=-80, active=True): + def start_scan( + self, + *advertisement_types, + buffer_size=512, + extended=False, + timeout=None, + interval=0.1, + window=0.1, + minimum_rssi=-80, + active=True + ): """ Starts scanning. Returns an iterator of advertisement objects of the types given in advertisement_types. The iterator will block until an advertisement is heard or the scan @@ -214,10 +232,16 @@ def start_scan(self, *advertisement_types, buffer_size=512, extended=False, time prefixes = b"" if advertisement_types: prefixes = b"".join(adv.prefix for adv in advertisement_types) - for entry in self._adapter.start_scan(prefixes=prefixes, buffer_size=buffer_size, - extended=extended, timeout=timeout, - interval=interval, window=window, - minimum_rssi=minimum_rssi, active=active): + for entry in self._adapter.start_scan( + prefixes=prefixes, + buffer_size=buffer_size, + extended=extended, + timeout=timeout, + interval=interval, + window=window, + minimum_rssi=minimum_rssi, + active=active, + ): adv_type = Advertisement for possible_type in advertisement_types: if possible_type.matches(entry) and issubclass(possible_type, adv_type): diff --git a/adafruit_ble/advertising/__init__.py b/adafruit_ble/advertising/__init__.py index 27cde40..0781f70 100644 --- a/adafruit_ble/advertising/__init__.py +++ b/adafruit_ble/advertising/__init__.py @@ -25,13 +25,16 @@ import struct + def to_hex(seq): """Pretty prints a byte sequence as hex values.""" return " ".join("{:02x}".format(v) for v in seq) + def to_bytes_literal(seq): """Prints a byte sequence as a Python bytes literal that only uses hex encoding.""" - return "b\"" + "".join("\\x{:02x}".format(v) for v in seq) + "\"" + return 'b"' + "".join("\\x{:02x}".format(v) for v in seq) + '"' + def decode_data(data, *, key_encoding="B"): """Helper which decodes length encoded structures into a dictionary with the given key @@ -45,7 +48,7 @@ def decode_data(data, *, key_encoding="B"): if item_length == 0: break key = struct.unpack_from(key_encoding, data, i)[0] - value = data[i + key_size:i + item_length] + value = data[i + key_size : i + item_length] if key in data_dict: if not isinstance(data_dict[key], list): data_dict[key] = [data_dict[key]] @@ -55,6 +58,7 @@ def decode_data(data, *, key_encoding="B"): i += item_length return data_dict + def compute_length(data_dict, *, key_encoding="B"): """Computes the length of the encoded data dictionary.""" value_size = 0 @@ -66,6 +70,7 @@ def compute_length(data_dict, *, key_encoding="B"): value_size += len(value) return len(data_dict) + len(data_dict) * struct.calcsize(key_encoding) + value_size + def encode_data(data_dict, *, key_encoding="B"): """Helper which encodes dictionaries into length encoded structures with the given key encoding.""" @@ -79,17 +84,21 @@ def encode_data(data_dict, *, key_encoding="B"): item_length = key_size + len(value) struct.pack_into("B", data, i, item_length) struct.pack_into(key_encoding, data, i + 1, key) - data[i + 1 + key_size: i + 1 + item_length] = bytes(value) + data[i + 1 + key_size : i + 1 + item_length] = bytes(value) i += 1 + item_length return data + class AdvertisingDataField: """Top level class for any descriptor classes that live in Advertisement or its subclasses.""" + # pylint: disable=too-few-public-methods,unnecessary-pass pass + class AdvertisingFlag: """A single bit flag within an AdvertisingFlags object.""" + def __init__(self, bit_position): self._bitmask = 1 << bit_position @@ -102,6 +111,7 @@ def __set__(self, obj, value): else: obj.flags &= ~self._bitmask + class AdvertisingFlags(AdvertisingDataField): """Standard advertising flags""" @@ -135,10 +145,12 @@ def __str__(self): parts.append(attr) return "".format(" ".join(parts)) + class String(AdvertisingDataField): """UTF-8 encoded string in an Advertisement. Not null terminated once encoded because length is always transmitted.""" + def __init__(self, *, advertising_data_type): self._adt = advertising_data_type @@ -152,8 +164,10 @@ def __get__(self, obj, cls): def __set__(self, obj, value): obj.data_dict[self._adt] = value.encode("utf-8") + class Struct(AdvertisingDataField): """`struct` encoded data in an Advertisement.""" + def __init__(self, struct_format, *, advertising_data_type): self._format = struct_format self._adt = advertising_data_type @@ -171,6 +185,7 @@ def __set__(self, obj, value): class LazyObjectField(AdvertisingDataField): """Non-data descriptor useful for lazily binding a complex object to an advertisement object.""" + def __init__(self, cls, attribute_name, *, advertising_data_type, **kwargs): self._cls = cls self._attribute_name = attribute_name @@ -197,15 +212,17 @@ def advertising_data_type(self): # TODO: Add __set_name__ support to CircuitPython so that we automatically tell the descriptor # instance the attribute name it has and the class it is on. + class Advertisement: """Core Advertisement type""" - prefix = b"\x00" # This is an empty prefix and will match everything. + + prefix = b"\x00" # This is an empty prefix and will match everything. flags = LazyObjectField(AdvertisingFlags, "flags", advertising_data_type=0x01) short_name = String(advertising_data_type=0x08) """Short local device name (shortened to fit).""" complete_name = String(advertising_data_type=0x09) """Complete local device name.""" - tx_power = Struct("".format(self.company_id, hex_data) + return "".format( + self.company_id, hex_data + ) + class ManufacturerDataField: """A single piece of data within the manufacturer specific data. The format can be repeated.""" + def __init__(self, key, value_format, field_names=None): self._key = key self._format = value_format # TODO: Support format strings that use numbers to repeat a given type. For now, we strip # numbers because Radio specifies string length with it. self.element_count = len(value_format.strip("> 1 and (not field_names or len(field_names) != self.element_count): - raise ValueError("Provide field_names when multiple values are in the format") + if self.element_count > 1 and ( + not field_names or len(field_names) != self.element_count + ): + raise ValueError( + "Provide field_names when multiple values are in the format" + ) self._entry_length = struct.calcsize(value_format) self.field_names = field_names @@ -248,7 +286,9 @@ def __get__(self, obj, cls): def __set__(self, obj, value): if not obj.mutable: raise AttributeError() - if isinstance(value, tuple) and (self.element_count == 1 or isinstance(value[0], tuple)): + if isinstance(value, tuple) and ( + self.element_count == 1 or isinstance(value[0], tuple) + ): packed = bytearray(self._entry_length * len(value)) for i, entry in enumerate(value): offset = i * self._entry_length @@ -262,9 +302,11 @@ def __set__(self, obj, value): else: obj.manufacturer_data.data[self._key] = struct.pack(self._format, *value) + class ServiceData(AdvertisingDataField): """Encapsulates service data. It is read as a memoryview which can be manipulated or set as a bytearray to change the size.""" + def __init__(self, service): if isinstance(service.uuid, StandardUUID): self._adt = 0x16 @@ -289,11 +331,11 @@ def __get__(self, obj, cls): if not isinstance(service_data, bytearray): service_data = bytearray(service_data) all_service_data[i] = service_data - return memoryview(service_data)[len(self._prefix):] + return memoryview(service_data)[len(self._prefix) :] if obj.mutable: service_data = bytearray(self._prefix) all_service_data.append(service_data) - return memoryview(service_data)[len(self._prefix):] + return memoryview(service_data)[len(self._prefix) :] # Existing data is a single set of bytes. elif isinstance(all_service_data, (bytes, bytearray)): service_data = all_service_data @@ -306,11 +348,10 @@ def __get__(self, obj, cls): if not isinstance(service_data, bytearray): service_data = bytearray(service_data) obj.data_dict[self._adt] = service_data - return memoryview(service_data)[len(self._prefix):] + return memoryview(service_data)[len(self._prefix) :] return None - def __set__(self, obj, value): if not obj.mutable: raise RuntimeError("Advertisement immutable") diff --git a/adafruit_ble/attributes/__init__.py b/adafruit_ble/attributes/__init__.py index 3138a21..977ae69 100644 --- a/adafruit_ble/attributes/__init__.py +++ b/adafruit_ble/attributes/__init__.py @@ -32,6 +32,7 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git" + class Attribute: """Constants describing security levels. @@ -63,6 +64,7 @@ class Attribute: security_mode: authenticated data signing, without man-in-the-middle protection """ + # pylint: disable=too-few-public-methods NO_ACCESS = _bleio.Attribute.NO_ACCESS OPEN = _bleio.Attribute.OPEN diff --git a/adafruit_ble/characteristics/__init__.py b/adafruit_ble/characteristics/__init__.py index 1692b84..7253488 100644 --- a/adafruit_ble/characteristics/__init__.py +++ b/adafruit_ble/characteristics/__init__.py @@ -81,6 +81,7 @@ class Characteristic: property: clients may write this characteristic; no response will be sent back """ + BROADCAST = _bleio.Characteristic.BROADCAST INDICATE = _bleio.Characteristic.INDICATE NOTIFY = _bleio.Characteristic.NOTIFY @@ -88,10 +89,18 @@ class Characteristic: WRITE = _bleio.Characteristic.WRITE WRITE_NO_RESPONSE = _bleio.Characteristic.WRITE_NO_RESPONSE - def __init__(self, *, uuid=None, properties=0, - read_perm=Attribute.OPEN, write_perm=Attribute.OPEN, - max_length=None, fixed_length=False, initial_value=None): - self.field_name = None # Set by Service during basic binding + def __init__( + self, + *, + uuid=None, + properties=0, + read_perm=Attribute.OPEN, + write_perm=Attribute.OPEN, + max_length=None, + fixed_length=False, + initial_value=None + ): + self.field_name = None # Set by Service during basic binding if uuid: self.uuid = uuid @@ -130,9 +139,15 @@ def __bind_locally(self, service, initial_value): elif max_length is None: max_length = len(initial_value) return _bleio.Characteristic.add_to_service( - service.bleio_service, self.uuid.bleio_uuid, initial_value=initial_value, - max_length=max_length, fixed_length=self.fixed_length, - properties=self.properties, read_perm=self.read_perm, write_perm=self.write_perm) + service.bleio_service, + self.uuid.bleio_uuid, + initial_value=initial_value, + max_length=max_length, + fixed_length=self.fixed_length, + properties=self.properties, + read_perm=self.read_perm, + write_perm=self.write_perm, + ) def __get__(self, service, cls=None): self._ensure_bound(service) @@ -146,16 +161,26 @@ def __set__(self, service, value): bleio_characteristic = service.bleio_characteristics[self.field_name] bleio_characteristic.value = value + class ComplexCharacteristic: """ Characteristic class that does complex binding where the subclass returns a full object for interacting with the characteristic data. The Characteristic itself will be shadowed once it has been bound to the corresponding instance attribute. """ - def __init__(self, *, uuid=None, properties=0, - read_perm=Attribute.OPEN, write_perm=Attribute.OPEN, - max_length=20, fixed_length=False, initial_value=None): - self.field_name = None # Set by Service during basic binding + + def __init__( + self, + *, + uuid=None, + properties=0, + read_perm=Attribute.OPEN, + write_perm=Attribute.OPEN, + max_length=20, + fixed_length=False, + initial_value=None + ): + self.field_name = None # Set by Service during basic binding if uuid: self.uuid = uuid @@ -174,15 +199,21 @@ def bind(self, service): return characteristic raise AttributeError("Characteristic not available on remote service") return _bleio.Characteristic.add_to_service( - service.bleio_service, self.uuid.bleio_uuid, - initial_value=self.initial_value, max_length=self.max_length, - properties=self.properties, read_perm=self.read_perm, write_perm=self.write_perm) + service.bleio_service, + self.uuid.bleio_uuid, + initial_value=self.initial_value, + max_length=self.max_length, + properties=self.properties, + read_perm=self.read_perm, + write_perm=self.write_perm, + ) def __get__(self, service, cls=None): bound_object = self.bind(service) setattr(service, self.field_name, bound_object) return bound_object + class StructCharacteristic(Characteristic): """ Data descriptor for a structure with a fixed format. @@ -195,16 +226,30 @@ class StructCharacteristic(Characteristic): :param int write_perm: see `Characteristic` :param buf initial_value: see `Characteristic` """ - def __init__(self, struct_format, *, uuid=None, properties=0, - read_perm=Attribute.OPEN, write_perm=Attribute.OPEN, - initial_value=None): + + def __init__( + self, + struct_format, + *, + uuid=None, + properties=0, + read_perm=Attribute.OPEN, + write_perm=Attribute.OPEN, + initial_value=None + ): self._struct_format = struct_format self._expected_size = struct.calcsize(struct_format) if initial_value: initial_value = struct.pack(self._struct_format, *initial_value) - super().__init__(uuid=uuid, initial_value=initial_value, - max_length=self._expected_size, fixed_length=True, - properties=properties, read_perm=read_perm, write_perm=write_perm) + super().__init__( + uuid=uuid, + initial_value=initial_value, + max_length=self._expected_size, + fixed_length=True, + properties=properties, + read_perm=read_perm, + write_perm=write_perm, + ) def __get__(self, obj, cls=None): raw_data = super().__get__(obj, cls) diff --git a/adafruit_ble/characteristics/float.py b/adafruit_ble/characteristics/float.py index eced8c3..3dfc5e3 100644 --- a/adafruit_ble/characteristics/float.py +++ b/adafruit_ble/characteristics/float.py @@ -33,16 +33,29 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git" + class FloatCharacteristic(StructCharacteristic): """32-bit float""" - def __init__(self, *, uuid=None, properties=0, - read_perm=Attribute.OPEN, write_perm=Attribute.OPEN, - initial_value=None): + + def __init__( + self, + *, + uuid=None, + properties=0, + read_perm=Attribute.OPEN, + write_perm=Attribute.OPEN, + initial_value=None + ): if initial_value: initial_value = (initial_value,) - super().__init__("> 8 - uuid128[-4] = uuid16 & 0xff + uuid128[-4] = uuid16 & 0xFF super().__init__(uuid128) + class CircuitPythonService(Service): """Core CircuitPython service that allows for file modification and REPL access. Unimplemented.""" + uuid = CircuitPythonUUID(0x0100) - filename = StringCharacteristic(uuid=CircuitPythonUUID(0x0200), - properties=(Characteristic.READ | Characteristic.WRITE)) + filename = StringCharacteristic( + uuid=CircuitPythonUUID(0x0200), + properties=(Characteristic.READ | Characteristic.WRITE), + ) contents = StreamOut(uuid=CircuitPythonUUID(0x0201)) diff --git a/adafruit_ble/services/midi.py b/adafruit_ble/services/midi.py index ab94d44..df71fc9 100644 --- a/adafruit_ble/services/midi.py +++ b/adafruit_ble/services/midi.py @@ -34,20 +34,30 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git" + class MidiIOCharacteristic(Characteristic): """Workhorse MIDI Characteristic that carries midi messages both directions. Unimplemented.""" + # pylint: disable=too-few-public-methods uuid = VendorUUID("7772E5DB-3868-4112-A1A9-F2669D106BF3") + def __init__(self, **kwargs): - super().__init__(properties=(Characteristic.NOTIFY | - Characteristic.READ | - Characteristic.WRITE | - Characteristic.WRITE_NO_RESPONSE), **kwargs) + super().__init__( + properties=( + Characteristic.NOTIFY + | Characteristic.READ + | Characteristic.WRITE + | Characteristic.WRITE_NO_RESPONSE + ), + **kwargs + ) + class MidiService(Service): """BLE Service that transports MIDI messages. Unimplemented.""" + uuid = VendorUUID("03B80E5A-EDE8-4B33-A751-6CE34EC4C700") - io = MidiIOCharacteristic() # pylint: disable=invalid-name + io = MidiIOCharacteristic() # pylint: disable=invalid-name # pylint: disable=unnecessary-pass def write(self): diff --git a/adafruit_ble/services/nordic.py b/adafruit_ble/services/nordic.py index 2ec636e..54bdd18 100755 --- a/adafruit_ble/services/nordic.py +++ b/adafruit_ble/services/nordic.py @@ -35,6 +35,7 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git" + class UARTService(Service): """ Provide UART-like functionality via the Nordic NUS service. @@ -46,12 +47,19 @@ class UARTService(Service): See ``examples/ble_uart_echo_test.py`` for a usage example. """ + # pylint: disable=no-member uuid = VendorUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E") - _server_tx = StreamOut(uuid=VendorUUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"), - timeout=1.0, buffer_size=64) - _server_rx = StreamIn(uuid=VendorUUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"), - timeout=1.0, buffer_size=64) + _server_tx = StreamOut( + uuid=VendorUUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"), + timeout=1.0, + buffer_size=64, + ) + _server_rx = StreamIn( + uuid=VendorUUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"), + timeout=1.0, + buffer_size=64, + ) def __init__(self, service=None): super().__init__(service=service) diff --git a/adafruit_ble/services/sphero.py b/adafruit_ble/services/sphero.py index 8627ee3..205d92c 100644 --- a/adafruit_ble/services/sphero.py +++ b/adafruit_ble/services/sphero.py @@ -33,6 +33,8 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git" + class SpheroService(Service): """Core Sphero Service. Unimplemented.""" + uuid = VendorUUID("!!orehpS OOW\x01\x00\x01\x00") diff --git a/adafruit_ble/services/standard/__init__.py b/adafruit_ble/services/standard/__init__.py index 1914f0a..60b23d6 100644 --- a/adafruit_ble/services/standard/__init__.py +++ b/adafruit_ble/services/standard/__init__.py @@ -36,41 +36,51 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git" + class AppearanceCharacteristic(StructCharacteristic): """What type of device it is""" + # pylint: disable=too-few-public-methods - uuid = StandardUUID(0x2a01) + uuid = StandardUUID(0x2A01) def __init__(self, **kwargs): super().__init__("> 4 + tag = (b & 0xF0) >> 4 _type = (b & 0b1100) >> 2 size = b & 0b11 size = 4 if size == 3 else size i += 1 - data = hid_descriptor[i:i+size] + data = hid_descriptor[i : i + size] if _type == _ITEM_TYPE_GLOBAL: global_table[tag] = data elif _type == _ITEM_TYPE_MAIN: if tag == _MAIN_ITEM_TAG_START_COLLECTION: - collections.append({"type": data, - "locals": list(local_table), - "globals": list(global_table), - "mains": []}) + collections.append( + { + "type": data, + "locals": list(local_table), + "globals": list(global_table), + "mains": [], + } + ) elif tag == _MAIN_ITEM_TAG_END_COLLECTION: collection = collections.pop() # This is a top level collection if the collections list is now empty. @@ -338,13 +378,21 @@ def _init_devices(self): else: collections[-1]["mains"].append(collection) elif tag == _MAIN_ITEM_TAG_INPUT: - collections[-1]["mains"].append({"tag": "input", - "locals": list(local_table), - "globals": list(global_table)}) + collections[-1]["mains"].append( + { + "tag": "input", + "locals": list(local_table), + "globals": list(global_table), + } + ) elif tag == _MAIN_ITEM_TAG_OUTPUT: - collections[-1]["mains"].append({"tag": "output", - "locals": list(local_table), - "globals": list(global_table)}) + collections[-1]["mains"].append( + { + "tag": "output", + "locals": list(local_table), + "globals": list(global_table), + } + ) else: raise RuntimeError("Unsupported main item in HID descriptor") local_table = [None] * 3 @@ -359,7 +407,9 @@ def get_report_info(collection, reports): if "type" in main: get_report_info(main, reports) else: - report_size, report_id, report_count = [x[0] for x in main["globals"][7:10]] + report_size, report_id, report_count = [ + x[0] for x in main["globals"][7:10] + ] if report_id not in reports: reports[report_id] = {"input_size": 0, "output_size": 0} if main["tag"] == "input": @@ -367,24 +417,33 @@ def get_report_info(collection, reports): elif main["tag"] == "output": reports[report_id]["output_size"] += report_size * report_count - for collection in top_level_collections: if collection["type"][0] != 1: - raise NotImplementedError("Only Application top level collections supported.") + raise NotImplementedError( + "Only Application top level collections supported." + ) usage_page = collection["globals"][0][0] usage = collection["locals"][0][0] reports = {} get_report_info(collection, reports) if len(reports) > 1: - raise NotImplementedError("Only one report id per Application collection supported") + raise NotImplementedError( + "Only one report id per Application collection supported" + ) report_id, report = list(reports.items())[0] output_size = report["output_size"] if output_size > 0: - self.devices.append(ReportOut(self, report_id, usage_page, usage, - max_length=output_size // 8)) + self.devices.append( + ReportOut( + self, report_id, usage_page, usage, max_length=output_size // 8 + ) + ) input_size = reports[report_id]["input_size"] if input_size > 0: - self.devices.append(ReportIn(self, report_id, usage_page, usage, - max_length=input_size // 8)) + self.devices.append( + ReportIn( + self, report_id, usage_page, usage, max_length=input_size // 8 + ) + ) diff --git a/adafruit_ble/uuid/__init__.py b/adafruit_ble/uuid/__init__.py index f1f5c72..4549f92 100644 --- a/adafruit_ble/uuid/__init__.py +++ b/adafruit_ble/uuid/__init__.py @@ -32,8 +32,10 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BLE.git" + class UUID: """Top level UUID""" + # TODO: Make subclassing _bleio.UUID work so we can just use it directly. # pylint: disable=no-member def __hash__(self): @@ -60,16 +62,20 @@ def pack_into(self, buffer, offset=0): """Packs the UUID into the buffer at the given offset.""" self.bleio_uuid.pack_into(buffer, offset=offset) + class StandardUUID(UUID): """Standard 16-bit UUID defined by the Bluetooth SIG.""" + def __init__(self, uuid16): if not isinstance(uuid16, int): uuid16 = struct.unpack(" Date: Mon, 16 Mar 2020 15:44:56 -0400 Subject: [PATCH 2/2] More pylint --- adafruit_ble/services/standard/device_info.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/adafruit_ble/services/standard/device_info.py b/adafruit_ble/services/standard/device_info.py index ab4ab9a..7b631da 100644 --- a/adafruit_ble/services/standard/device_info.py +++ b/adafruit_ble/services/standard/device_info.py @@ -66,10 +66,8 @@ def __init__( model_number = sys.platform if serial_number is None: serial_number = binascii.hexlify( - microcontroller.cpu.uid - ).decode( # pylint: disable=no-member - "utf-8" - ) + microcontroller.cpu.uid # pylint: disable=no-member + ).decode("utf-8") if firmware_revision is None: firmware_revision = os.uname().version super().__init__(