Skip to content

Commit

Permalink
Updated to conform to lint specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonytw committed Apr 21, 2023
1 parent 638e931 commit 7954a9c
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 85 deletions.
74 changes: 42 additions & 32 deletions _bleio/scan_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,46 +148,56 @@ def _advertisement_fields(self) -> List[bytes]:
bytes((data_type,)) + data for data_type, data in self._data_dict.items()
)

@staticmethod
def _manufacturer_data_from_bleak(manufacturer_data: Dict[int, bytes]) -> bytes:
# The manufacturer data value is a dictionary.
# Re-concatenate it into bytes
all_mfr_data = bytearray()
for mfr_id, mfr_data in manufacturer_data.items():
all_mfr_data.extend(mfr_id.to_bytes(2, byteorder="little"))
all_mfr_data.extend(mfr_data)
return bytes(all_mfr_data)

@staticmethod
def _uuids_from_bleak(uuids: List[str]) -> bytes:
uuids16 = bytearray()
uuids32 = bytearray()
uuids128 = bytearray()
for uuid in uuids:
bleio_uuid = UUID(uuid)
# If this is a Standard UUID in 128-bit form, convert it to a 16- or 32-bit UUID.
if bleio_uuid.is_standard_uuid:
if bleio_uuid.size == 16:
uuids16.extend(bleio_uuid.uuid128[12:14])
elif bleio_uuid.size == 32:
uuids32.extend(bleio_uuid.uuid128[12:16])
else:
raise RuntimeError("Unexpected UUID size")
else:
uuids128.extend(bleio_uuid.uuid128)

fields = {}
if uuids16:
# Complete list of 16-bit UUIDs.
fields[0x03] = uuids16
if uuids32:
# Complete list of 32-bit UUIDs.
fields[0x05] = uuids32
if uuids128:
# Complete list of 128-bit UUIDs
fields[0x07] = uuids128
return fields

@staticmethod
def _data_dict_from_bleak(
device: BLEDevice, advertisement_data: AdvertisementData
) -> DataDict:
data_dict = {}
if manufacturer_data := advertisement_data.manufacturer_data:
# The manufacturer data value is a dictionary.
# Re-concatenate it into bytes
all_mfr_data = bytearray()
for mfr_id, mfr_data in manufacturer_data.items():
all_mfr_data.extend(mfr_id.to_bytes(2, byteorder="little"))
all_mfr_data.extend(mfr_data)
data_dict[0xFF] = all_mfr_data
data_dict[0xFF] = ScanEntry._manufacturer_data_from_bleak(manufacturer_data)

if uuids := advertisement_data.service_uuids:
uuids16 = bytearray()
uuids32 = bytearray()
uuids128 = bytearray()
for uuid in uuids:
bleio_uuid = UUID(uuid)
# If this is a Standard UUID in 128-bit form, convert it to a 16- or 32-bit UUID.
if bleio_uuid.is_standard_uuid:
if bleio_uuid.size == 16:
uuids16.extend(bleio_uuid.uuid128[12:14])
elif bleio_uuid.size == 32:
uuids32.extend(bleio_uuid.uuid128[12:16])
else:
raise RuntimeError("Unexpected UUID size")
else:
uuids128.extend(bleio_uuid.uuid128)

if uuids16:
# Complete list of 16-bit UUIDs.
data_dict[0x03] = uuids16
if uuids32:
# Complete list of 32-bit UUIDs.
data_dict[0x05] = uuids32
if uuids128:
# Complete list of 128-bit UUIDs
data_dict[0x07] = uuids128
data_dict.update(ScanEntry._uuids_from_bleak(uuids))

name = advertisement_data.local_name or device.name
if name and not ScanEntry._RE_IGNORABLE_NAME.fullmatch(name):
Expand Down
124 changes: 71 additions & 53 deletions _bleio/uuid_.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,63 +44,77 @@ class UUID:
@staticmethod
def standard_uuid128_from_uuid32(uuid32: int) -> bytes:
"""Return a 128-bit standard UUID from a 32-bit standard UUID."""
if not 0 <= uuid32 < 2 ** 32:
if not 0 <= uuid32 < 2**32:
raise ValueError("UUID integer value must be unsigned 32-bit")
return _BASE_STANDARD_UUID[:-4] + uuid32.to_bytes(4, "little")

@staticmethod
def _init_from_str(uuid: str) -> tuple[bytes, int]:
if _UUID_RE.fullmatch(uuid):
# Pick the smallest standard size.
if _STANDARD_UUID_RE_16.fullmatch(uuid):
size = 16
uuid16 = int(uuid[4:8], 16)
uuid128 = UUID.standard_uuid128_from_uuid32(uuid16)
return uuid128, size

if _STANDARD_UUID_RE_32.fullmatch(uuid):
size = 32
uuid32 = int(uuid[0:8], 16)
uuid128 = UUID.standard_uuid128_from_uuid32(uuid32)
return uuid128, size

size = 128
uuid = uuid.replace("-", "")
uuid128 = bytes(int(uuid[i : i + 2], 16) for i in range(30, -1, -2))
return uuid128, size

if _STANDARD_HEX_UUID_RE.fullmatch(uuid) and len(uuid) in (4, 8):
# Fall through and reprocess as an int.
uuid_int = int(uuid, 16)
size = len(uuid) * 4 # 4 bits per hex digit
uuid128 = UUID.standard_uuid128_from_uuid32(uuid_int)
return uuid128, size

raise ValueError(
"UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',"
"'xxxx', or 'xxxxxxxx', but is " + uuid
)

@staticmethod
def _init_from_int(uuid: int) -> tuple[bytes, int]:
if not 0 <= uuid <= 2**32:
raise ValueError("UUID integer value must be unsigned 16- or 32-bit")
if uuid <= 2**16:
size = 16
if uuid <= 2**32:
size = 32
uuid128 = UUID.standard_uuid128_from_uuid32(uuid)
return uuid128, size

@staticmethod
def _init_from_buf(uuid: Buf) -> tuple[bytes, int]:
try:
uuid = memoryview(uuid)
except TypeError:
raise ValueError("UUID value is not str, int or byte buffer") from TypeError
if len(uuid) != 16:
raise ValueError("Byte buffer must be 16 bytes")
size = 128
uuid128 = bytes(uuid)
return uuid128, size

def __init__(self, uuid: Union[int, Buf, str]):
self.__bleak_uuid = None

if isinstance(uuid, str):
if _UUID_RE.fullmatch(uuid):
# Pick the smallest standard size.
if _STANDARD_UUID_RE_16.fullmatch(uuid):
self._size = 16
uuid16 = int(uuid[4:8], 16)
self._uuid128 = self.standard_uuid128_from_uuid32(uuid16)
elif _STANDARD_UUID_RE_32.fullmatch(uuid):
self._size = 32
uuid32 = int(uuid[0:8], 16)
self._uuid128 = self.standard_uuid128_from_uuid32(uuid32)
else:
self._size = 128
uuid = uuid.replace("-", "")
self._uuid128 = bytes(
int(uuid[i : i + 2], 16) for i in range(30, -1, -2)
)

elif _STANDARD_HEX_UUID_RE.fullmatch(uuid) and len(uuid) in (4, 8):
# Fall through and reprocess as an int.
uuid_int = int(uuid, 16)
self._size = len(uuid)*4 # 4 bits per hex digit
self._uuid128 = self.standard_uuid128_from_uuid32(uuid_int)

else:
raise ValueError(
"UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'xxxx', or 'xxxxxxxx', but is "
+ uuid
)
self._uuid128, self._size = self._init_from_str(uuid)

elif isinstance(uuid, int):
if not 0 <= uuid <= 2**32:
raise ValueError("UUID integer value must be unsigned 16- or 32-bit")
if uuid <= 2**16:
self._size = 16
if uuid <= 2**32:
self._size = 32
self._uuid128 = self.standard_uuid128_from_uuid32(uuid)
self._uuid128, self._size = self._init_from_int(uuid)

else:
try:
uuid = memoryview(uuid)
except TypeError:
raise ValueError(
"UUID value is not str, int or byte buffer"
) from TypeError
if len(uuid) != 16:
raise ValueError("Byte buffer must be 16 bytes")
self._size = 128
self._uuid128 = bytes(uuid)
self._uuid128, self._size = self._init_from_buf(uuid)

@classmethod
def _from_bleak(cls, bleak_uuid: Any) -> "UUID":
Expand Down Expand Up @@ -151,26 +165,30 @@ def pack_into(self, buffer, offset=0) -> None:
def is_standard_uuid(self) -> bool:
"""True if this is a standard 16 or 32-bit UUID (xxxxxxxx-0000-1000-8000-00805F9B34FB)
even if it's 128-bit."""
return self.size == 16 or self.size == 32 or (
self._uuid128[0:12] == _BASE_STANDARD_UUID[0:12]
and self._uuid128[14:] == _BASE_STANDARD_UUID[14:]
return (
self.size == 16
or self.size == 32
or (
self._uuid128[0:12] == _BASE_STANDARD_UUID[0:12]
and self._uuid128[14:] == _BASE_STANDARD_UUID[14:]
)
)

def __eq__(self, other: Any) -> bool:
if isinstance(other, UUID):
if self.size == 16 and other.size == 16:
return self.uuid16 == other.uuid16
elif self.size == 32 and other.size == 32:
if self.size == 32 and other.size == 32:
return self.uuid32 == other.uuid32
elif self.size == 128 and other.size == 128:
if self.size == 128 and other.size == 128:
return self.uuid128 == other.uuid128

return False

def __hash__(self):
if self.size == 16:
return hash(self.uuid16)
elif self.size == 32:
if self.size == 32:
return hash(self.uuid32)
return hash(self.uuid128)

Expand All @@ -186,6 +204,6 @@ def __str__(self) -> str:
def __repr__(self) -> str:
if self.size == 16:
return f"UUID({self.uuid16:#04x})"
elif self.size == 32:
if self.size == 32:
return f"UUID({self.uuid32:#08x})"
return f"UUID({self!s})"

0 comments on commit 7954a9c

Please sign in to comment.