mirror of
https://github.com/esphome/aioesphomeapi.git
synced 2024-09-28 04:27:27 +02:00
Small speed up to parsing LE advertisement data (#330)
This commit is contained in:
parent
9d9d19a2c1
commit
6d4b9df969
@ -1,5 +1,6 @@
|
|||||||
import enum
|
import enum
|
||||||
from dataclasses import asdict, dataclass, field, fields
|
from dataclasses import asdict, dataclass, field, fields
|
||||||
|
from functools import cache
|
||||||
from typing import (
|
from typing import (
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Any,
|
Any,
|
||||||
@ -51,10 +52,15 @@ class APIIntEnum(enum.IntEnum):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
# Fields do not change so we can cache the result
|
||||||
|
# of calling fields() on the dataclass
|
||||||
|
cached_fields = cache(fields)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class APIModelBase:
|
class APIModelBase:
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
for field_ in fields(type(self)):
|
for field_ in cached_fields(type(self)): # type: ignore[arg-type]
|
||||||
convert = field_.metadata.get("converter")
|
convert = field_.metadata.get("converter")
|
||||||
if convert is None:
|
if convert is None:
|
||||||
continue
|
continue
|
||||||
@ -71,14 +77,14 @@ class APIModelBase:
|
|||||||
) -> _V:
|
) -> _V:
|
||||||
init_args = {
|
init_args = {
|
||||||
f.name: data[f.name]
|
f.name: data[f.name]
|
||||||
for f in fields(cls)
|
for f in cached_fields(cls) # type: ignore[arg-type]
|
||||||
if f.name in data or (not ignore_missing)
|
if f.name in data or (not ignore_missing)
|
||||||
}
|
}
|
||||||
return cls(**init_args)
|
return cls(**init_args)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_pb(cls: Type[_V], data: Any) -> _V:
|
def from_pb(cls: Type[_V], data: Any) -> _V:
|
||||||
return cls(**{f.name: getattr(data, f.name) for f in fields(cls)})
|
return cls(**{f.name: getattr(data, f.name) for f in cached_fields(cls)}) # type: ignore[arg-type]
|
||||||
|
|
||||||
|
|
||||||
def converter_field(*, converter: Callable[[Any], _V], **kwargs: Any) -> _V:
|
def converter_field(*, converter: Callable[[Any], _V], **kwargs: Any) -> _V:
|
||||||
@ -783,6 +789,9 @@ def _convert_bluetooth_le_service_data(
|
|||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
if not value:
|
||||||
|
return {}
|
||||||
|
|
||||||
# Long UUID inlined to avoid call stack inside the dict comprehension
|
# Long UUID inlined to avoid call stack inside the dict comprehension
|
||||||
return {
|
return {
|
||||||
f"0000{v.uuid[2:].lower()}-0000-1000-8000-00805f9b34fb" # type: ignore[union-attr]
|
f"0000{v.uuid[2:].lower()}-0000-1000-8000-00805f9b34fb" # type: ignore[union-attr]
|
||||||
@ -798,6 +807,10 @@ def _convert_bluetooth_le_manufacturer_data(
|
|||||||
) -> Dict[int, bytes]:
|
) -> Dict[int, bytes]:
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
if not value:
|
||||||
|
return {}
|
||||||
|
|
||||||
# v.data if v.data else v.legacy_data is backwards compatible with ESPHome devices before 2022.10.0
|
# v.data if v.data else v.legacy_data is backwards compatible with ESPHome devices before 2022.10.0
|
||||||
return {int(v.uuid, 16): bytes(v.data if v.data else v.legacy_data) for v in value} # type: ignore
|
return {int(v.uuid, 16): bytes(v.data if v.data else v.legacy_data) for v in value} # type: ignore
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user