Skip to content

Commit

Permalink
use zigpy types
Browse files Browse the repository at this point in the history
  • Loading branch information
DamKast committed Nov 6, 2023
1 parent 1b69201 commit 6b0eaa0
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 286 deletions.
2 changes: 1 addition & 1 deletion zigpy_zboss/commands/af.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import zigpy_zboss.types as t


class AFCommandCode(t.enum_uint16):
class AFCommandCode(t.enum16):
"""Enum class for AF command_ids."""

AF_SET_SIMPLE_DESC = 0x0101
Expand Down
6 changes: 3 additions & 3 deletions zigpy_zboss/commands/aps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import zigpy_zboss.types as t


class APSCommandCode(t.enum_uint16):
class APSCommandCode(t.enum16):
"""Enum class for APS command_ids."""

APSDE_DATA_REQ = 0x0301
Expand All @@ -18,14 +18,14 @@ class APSCommandCode(t.enum_uint16):
APSME_UNBIND_ALL = 0x030a


class KeySrcAndAttr(t.enum_flag_uint8):
class KeySrcAndAttr(t.bitmap8):
"""Enum class for key source."""

KeySrc = 1 << 0
KeyUsed = 3 << 1


class TransmitOptions(t.enum_flag_uint8):
class TransmitOptions(t.bitmap8):
"""Enum class for transmit options."""

NONE = 0x00
Expand Down
2 changes: 1 addition & 1 deletion zigpy_zboss/commands/ncp_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import zigpy_zboss.types as t


class NcpConfigCommandCode(t.enum_uint16):
class NcpConfigCommandCode(t.enum16):
"""Enum class for NCP config command_ids."""

GET_MODULE_VERSION = 0x0001
Expand Down
2 changes: 1 addition & 1 deletion zigpy_zboss/commands/nwk_mgmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import zigpy_zboss.types as t


class NWKCommandCode(t.enum_uint16):
class NWKCommandCode(t.enum16):
"""Enum class for NWK command_ids."""

NWK_FORMATION = 0x0401
Expand Down
2 changes: 1 addition & 1 deletion zigpy_zboss/commands/security.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import zigpy_zboss.types as t


class SecurityCommandCode(t.enum_uint16):
class SecurityCommandCode(t.enum16):
"""Enum class for Security command_ids."""

SECUR_SET_LOCAL_IC = 0x0501
Expand Down
4 changes: 2 additions & 2 deletions zigpy_zboss/commands/zdo.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import zigpy_zboss.types as t


class ZdoCommandCode(t.enum_uint16):
class ZdoCommandCode(t.enum16):
"""Enum class for ZDO command_ids."""

ZDO_NWK_ADDR_REQ = 0x0201
Expand Down Expand Up @@ -42,7 +42,7 @@ class NWKArray(t.CompleteList, item_type=t.NWK):
"""List of nwk addresses."""


class AddrRequestType(t.enum_uint8):
class AddrRequestType(t.enum8):
"""Enum class for address request type."""

SINGLE = 0x00
Expand Down
269 changes: 49 additions & 220 deletions zigpy_zboss/types/basic.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,58 @@
"""Module defining basic types."""
from __future__ import annotations
import typing

import enum
from zigpy.types import int8s, uint8_t, enum_factory # noqa: F401

from zigpy_zboss.types.cstruct import CStruct

if typing.TYPE_CHECKING:
import enum

class enum8(int, enum.Enum):
"""Enum with 8 bits value."""

class enum16(int, enum.Enum):
"""Enum with 16 bits value."""

class enum24(int, enum.Enum):
"""Enum with 24 bits value."""

class enum40(int, enum.Enum):
"""Enum with 40 bits value."""

class enum64(int, enum.Enum):
"""Enum with 64 bits value."""

class bitmap8(enum.IntFlag):
"""Bitmap with 8 bits value."""

class bitmap16(enum.IntFlag):
"""Bitmap with 16 bits value."""

else:
from zigpy.types import ( # noqa: F401
enum8,
enum16,
bitmap8,
bitmap16,
uint16_t,
uint24_t,
uint32_t,
uint40_t,
uint56_t,
uint64_t,
)

class enum24(enum_factory(uint24_t)):
"""Enum with 24 bits value."""

class enum40(enum_factory(uint40_t)):
"""Enum with 40 bits value."""

class enum64(enum_factory(uint64_t)):
"""Enum with 64 bits value."""


class Bytes(bytes):
"""Class for Bytes representation."""
Expand All @@ -29,137 +77,6 @@ def __repr__(self) -> str:
__str__ = __repr__


class FixedIntType(int):
"""Class for fized int type."""

_signed = None
_size = None

def __new__(cls, *args, **kwargs):
"""Instantiate object."""
if cls._signed is None or cls._size is None:
raise TypeError(f"{cls} is abstract and cannot be created")

instance = super().__new__(cls, *args, **kwargs)
instance.serialize()

return instance

def __init_subclass__(cls, signed=None, size=None, hex_repr=None) -> None:
"""Define parameters when the class is used as parent."""
super().__init_subclass__()

if signed is not None:
cls._signed = signed

if size is not None:
cls._size = size

if hex_repr:
fmt = f"0x{{:0{cls._size * 2}X}}"
cls.__str__ = cls.__repr__ = lambda self: fmt.format(self)
elif hex_repr is not None and not hex_repr:
cls.__str__ = super().__str__
cls.__repr__ = super().__repr__

# XXX: The enum module uses the first class with __new__ in its
# __dict__ as the member type.
# We have to ensure this is true for every subclass.
if "__new__" not in cls.__dict__:
cls.__new__ = cls.__new__

def serialize(self) -> bytes:
"""Serialize object."""
try:
return self.to_bytes(self._size, "little", signed=self._signed)
except OverflowError as e:
# OverflowError is not a subclass of ValueError,
# making it annoying to catch
raise ValueError(str(e)) from e

@classmethod
def deserialize(cls, data: bytes) -> tuple[FixedIntType, bytes]:
"""Deserialize object."""
if len(data) < cls._size:
raise ValueError(f"Data is too short to contain {cls._size} bytes")

r = cls.from_bytes(data[: cls._size], "little", signed=cls._signed)
data = data[cls._size:]
return r, data


class uint_t(FixedIntType, signed=False):
"""Class representing the uint_t type."""


class int_t(FixedIntType, signed=True):
"""Class representing int_t type."""


class int8s(int_t, size=1):
"""Class representing the int8s type."""


class int16s(int_t, size=2):
"""Class representing the int16s type."""


class int24s(int_t, size=3):
"""Class representing the int24s type."""


class int32s(int_t, size=4):
"""Class representing the int32s type."""


class int40s(int_t, size=5):
"""Class representing the int40s type."""


class int48s(int_t, size=6):
"""Class representing the int48s type."""


class int56s(int_t, size=7):
"""Class representing the int56s type."""


class int64s(int_t, size=8):
"""Class representing the int64s type."""


class uint8_t(uint_t, size=1):
"""Class representing the uint8_t type."""


class uint16_t(uint_t, size=2):
"""Class representing the uint16_t type."""


class uint24_t(uint_t, size=3):
"""Class representing the uint24_t type."""


class uint32_t(uint_t, size=4):
"""Class representing the uint32_t type."""


class uint40_t(uint_t, size=5):
"""Class representing the uint40_t type."""


class uint48_t(uint_t, size=6):
"""Class representing the uint48_t type."""


class uint56_t(uint_t, size=7):
"""Class representing the uint56_t type."""


class uint64_t(uint_t, size=8):
"""Class representing the uint64_t type."""


class ShortBytes(Bytes):
"""Class representing Bytes with 1 byte header."""

Expand Down Expand Up @@ -292,91 +209,3 @@ def deserialize(
item, data = cls._deserialize_item(data, align=align)
r.append(item)
return r, data


def enum_flag_factory(int_type: FixedIntType) -> enum.Flag:
"""Enum flag factory.
Mixins are broken by Python 3.8.6 so we must dynamically create the enum
with the appropriate methods but with only one non-Enum parent class.
"""
class _NewEnum(int_type, enum.Flag):
# Rebind classmethods to our own class
_missing_ = classmethod(enum.IntFlag._missing_.__func__)
_create_pseudo_member_ = classmethod(
enum.IntFlag._create_pseudo_member_.__func__
)

__or__ = enum.IntFlag.__or__
__and__ = enum.IntFlag.__and__
__xor__ = enum.IntFlag.__xor__
__ror__ = enum.IntFlag.__ror__
__rand__ = enum.IntFlag.__rand__
__rxor__ = enum.IntFlag.__rxor__
__invert__ = enum.IntFlag.__invert__

return _NewEnum


class enum_uint8(uint8_t, enum.Enum):
"""Class representing the enum_uint8 type."""


class enum_uint16(uint16_t, enum.Enum):
"""Class representing the enum_uint16 type."""


class enum_uint24(uint24_t, enum.Enum):
"""Class representing the enum_uint24 type."""


class enum_uint32(uint32_t, enum.Enum):
"""Class representing the enum_uint32 type."""


class enum_uint40(uint40_t, enum.Enum):
"""Class representing the enum_uint40 type."""


class enum_uint48(uint48_t, enum.Enum):
"""Class representing the enum_uint48 type."""


class enum_uint56(uint56_t, enum.Enum):
"""Class representing the enum_uint56 type."""


class enum_uint64(uint64_t, enum.Enum):
"""Class representing the enum_uint64 type."""


class enum_flag_uint8(enum_flag_factory(uint8_t)):
"""Class representing the enum_flag_uint8 type."""


class enum_flag_uint16(enum_flag_factory(uint16_t)):
"""Class representing the enum_flag_uint16 type."""


class enum_flag_uint24(enum_flag_factory(uint24_t)):
"""Class representing the enum_flag_uint24 type."""


class enum_flag_uint32(enum_flag_factory(uint32_t)):
"""Class representing the enum_flag_uint32 type."""


class enum_flag_uint40(enum_flag_factory(uint40_t)):
"""Class representing the enum_flag_uint40 type."""


class enum_flag_uint48(enum_flag_factory(uint48_t)):
"""Class representing the enum_flag_uint48 type."""


class enum_flag_uint56(enum_flag_factory(uint56_t)):
"""Class representing the enum_flag_uint56 type."""


class enum_flag_uint64(enum_flag_factory(uint64_t)):
"""Class representing the enum_flag_uint64 type."""
Loading

0 comments on commit 6b0eaa0

Please sign in to comment.