Skip to content

Commit

Permalink
Use zigpy integer, enum, and bitmap types (#225)
Browse files Browse the repository at this point in the history
* Use zigpy integer, enum, and bitmap types

* Re-add exported objects removed during pre-commit

* Create typing-compatible stubs
  • Loading branch information
puddly authored Sep 26, 2023
1 parent e60c556 commit d6c39ea
Show file tree
Hide file tree
Showing 19 changed files with 113 additions and 340 deletions.
2 changes: 1 addition & 1 deletion tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def test_error_code():

r, rest = t.ErrorCode.deserialize(b"\xaa" + extra)
assert rest == extra
assert r.name == "unknown_0xAA"
assert r.name == "undefined_0xaa"


def _validate_schema(schema):
Expand Down
42 changes: 3 additions & 39 deletions tests/test_types_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ class TestList(t.LVList, item_type=t.uint8_t, length_type=t.uint8_t):
assert t.serialize_list([]) == b""


def test_enum_uint():
class TestEnum(t.enum_flag_uint16):
def test_enum():
class TestEnum(t.bitmap16):
ALL = 0xFFFF
CH_1 = 0x0001
CH_2 = 0x0002
Expand All @@ -39,19 +39,6 @@ class TestEnum(t.enum_flag_uint16):
assert TestEnum(0x8012).serialize() == data


def test_abstract_ints():
assert issubclass(t.uint8_t, t.uint_t)
assert not issubclass(t.uint8_t, t.int_t)
assert t.int_t._signed is True
assert t.uint_t._signed is False

with pytest.raises(TypeError):
t.int_t(0)

with pytest.raises(TypeError):
t.FixedIntType(0)


def test_int_too_short():
with pytest.raises(ValueError):
t.uint8_t.deserialize(b"")
Expand Down Expand Up @@ -132,29 +119,6 @@ class TestList(t.LVList, item_type=t.uint8_t, length_type=t.uint8_t):
TestList.deserialize(b"\x04123")


def test_hex_repr():
class NwkAsHex(t.uint16_t, hex_repr=True):
pass

nwk = NwkAsHex(0x123A)
assert str(nwk) == "0x123A"
assert repr(nwk) == "0x123A"

assert str([nwk]) == "[0x123A]"
assert repr([nwk]) == "[0x123A]"

# You can turn it off as well
class NwkWithoutHex(NwkAsHex, hex_repr=False):
pass

nwk = NwkWithoutHex(1234)
assert str(nwk) == "1234"
assert repr(nwk) == "1234"

assert str([nwk]) == "[1234]"
assert repr([nwk]) == "[1234]"


def test_fixed_list():
class TestList(t.FixedList, item_type=t.uint16_t, length=3):
pass
Expand Down Expand Up @@ -187,7 +151,7 @@ class TestList(t.FixedList, length=3, item_type=t.uint16_t):


def test_enum_instance_types():
class TestEnum(t.enum_uint8):
class TestEnum(t.enum8):
Member = 0x00

assert TestEnum._member_type_ is t.uint8_t
Expand Down
2 changes: 1 addition & 1 deletion tests/test_types_cstruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ class TestStruct(t.CStruct):
def test_old_nib_deserialize():
PaddingByte: typing_extensions.TypeAlias = t.uint8_t

class NwkState16(t.enum_uint16):
class NwkState16(t.enum16):
NWK_INIT = 0
NWK_JOINING_ORPHAN = 1
NWK_DISC = 2
Expand Down
29 changes: 1 addition & 28 deletions tests/test_types_named.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def test_status():
assert rest == extra
assert r == 0x33
assert r.value == 0x33
assert r.name == "unknown_0x33"
assert r.name == "undefined_0x33"


def test_addr_mode_address():
Expand Down Expand Up @@ -99,24 +99,6 @@ def test_addr_mode_address():
assert r3 != r4


def test_missing_status_enum():
class TestEnum(t.MissingEnumMixin, t.enum_uint8):
Member = 0x00

assert 0xFF not in list(TestEnum)
assert isinstance(TestEnum(0xFF), TestEnum)
assert TestEnum(0xFF).value == 0xFF
assert type(TestEnum(0xFF).value) is t.uint8_t

# Missing members that don't fit can't be created
with pytest.raises(ValueError):
TestEnum(0xFF + 1)

# Missing members that aren't integers can't be created
with pytest.raises(ValueError):
TestEnum("0xFF")


def test_zdo_nullable_node_descriptor():
desc1, data = c.zdo.NullableNodeDescriptor.deserialize(b"\x00")

Expand All @@ -131,12 +113,3 @@ def test_zdo_nullable_node_descriptor():

assert not data
assert desc2.serialize() == desc3.serialize()


def test_missing_enum_mixin():
class TestEnum(t.MissingEnumMixin, t.enum_uint8):
FOO = 0x01

assert TestEnum(0x01) == 0x01 == TestEnum.FOO
assert TestEnum(0x02) == 0x02
assert 0x02 not in TestEnum._value2member_map_
4 changes: 2 additions & 2 deletions zigpy_znp/commands/af.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import zigpy_znp.types as t


class TransmitOptions(t.enum_flag_uint8):
class TransmitOptions(t.bitmap8):
NONE = 0

# Will force the message to use Wildcard ProfileID
Expand All @@ -19,7 +19,7 @@ class TransmitOptions(t.enum_flag_uint8):
SKIP_ROUTING = 0x80


class LatencyReq(t.enum_uint8):
class LatencyReq(t.enum8):
NoLatencyReqs = 0x00
FastBeacons = 0x01
SlowBeacons = 0x02
Expand Down
10 changes: 5 additions & 5 deletions zigpy_znp/commands/app_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import zigpy_znp.types as t


class TimeoutIndex(t.enum_uint8):
class TimeoutIndex(t.enum8):
Seconds_10 = 0x00

Minutes_2 = 0x01
Expand All @@ -22,15 +22,15 @@ class TimeoutIndex(t.enum_uint8):
Minutes_16384 = 0x0E


class CentralizedLinkKeyMode(t.enum_uint8):
class CentralizedLinkKeyMode(t.enum8):
UseDefault = 0x00
UseProvidedInstallCode = 0x01
UseProvidedInstallCodeAndFallbackToDefault = 0x02
UseProvidedAPSLinkKey = 0x03
UseProvidedAPSLinkKeyAndFallbackToDefault = 0x04


class BDBCommissioningStatus(t.enum_uint8):
class BDBCommissioningStatus(t.enum8):
Success = 0x00
InProgress = 0x01
NoNetwork = 0x02
Expand All @@ -48,7 +48,7 @@ class BDBCommissioningStatus(t.enum_uint8):
Failure = 0x0E


class BDBCommissioningMode(t.enum_flag_uint8):
class BDBCommissioningMode(t.bitmap8):
NONE = 0

InitiatorTouchLink = 1 << 0
Expand All @@ -59,7 +59,7 @@ class BDBCommissioningMode(t.enum_flag_uint8):
ParentLost = 1 << 5


class InstallCodeFormat(t.enum_uint8):
class InstallCodeFormat(t.enum8):
InstallCodeAndCRC = 0x01
KeyDerivedFromInstallCode = 0x02

Expand Down
2 changes: 1 addition & 1 deletion zigpy_znp/commands/rpc_error.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import zigpy_znp.types as t


class ErrorCode(t.enum_uint8):
class ErrorCode(t.enum8):
InvalidSubsystem = 0x01
InvalidCommandId = 0x02
InvalidParameter = 0x03
Expand Down
14 changes: 7 additions & 7 deletions zigpy_znp/commands/sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import zigpy_znp.types as t


class BootloaderBuildType(t.enum_uint8):
class BootloaderBuildType(t.enum8):
NON_BOOTLOADER_BUILD = 0
BUILT_AS_BIN = 1
BUILT_AS_HEX = 2


class ADCChannel(t.enum_uint8):
class ADCChannel(t.enum8):
"""The ADC channel."""

AIN0 = 0x00
Expand All @@ -26,7 +26,7 @@ class ADCChannel(t.enum_uint8):
Voltage = 0x0F


class ADCResolution(t.enum_uint8):
class ADCResolution(t.enum8):
"""Resolution of the ADC channel."""

bits_8 = 0x00
Expand All @@ -35,7 +35,7 @@ class ADCResolution(t.enum_uint8):
bits_14 = 0x03


class GPIOPinMode(t.enum_flag_uint8):
class GPIOPinMode(t.bitmap8):
"""Pin state. Any pin with an unspecified state bit is pulled up."""

Tristate0 = 0b0000_0001
Expand All @@ -49,7 +49,7 @@ class GPIOPinMode(t.enum_flag_uint8):
PullDown3 = 0b1000_0000


class GPIOPinDirection(t.enum_flag_uint8):
class GPIOPinDirection(t.bitmap8):
"""Pin direction. Any pin with an unspecified direction bit is an input pin."""

Output0 = 0b0000_0001
Expand All @@ -58,7 +58,7 @@ class GPIOPinDirection(t.enum_flag_uint8):
Output3 = 0b0000_1000


class GPIOOperation(t.enum_uint8):
class GPIOOperation(t.enum8):
"""Specifies the type of operation to perform on the GPIO pins."""

SetDirection = 0x00
Expand All @@ -70,7 +70,7 @@ class GPIOOperation(t.enum_uint8):
HiD = 0x12 # ???


class StackTuneOperation(t.enum_uint8):
class StackTuneOperation(t.enum8):
"""The tuning operation to be executed."""

# XXX: [Value] should correspond to the valid values specified by the
Expand Down
6 changes: 3 additions & 3 deletions zigpy_znp/commands/ubl.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
FLASH_WORD_SIZE = 4


class BootloaderStatus(t.enum_uint8):
class BootloaderStatus(t.enum8):
SUCCESS = 0
FAILURE = 1
INVALID_FCS = 2
Expand All @@ -23,12 +23,12 @@ class BootloaderStatus(t.enum_uint8):
CANCELED = 8


class BootloaderDeviceType(t.enum_uint8):
class BootloaderDeviceType(t.enum8):
CC2538 = 1
CC2530 = 2


class BootloaderRunMode(t.enum_uint8):
class BootloaderRunMode(t.enum8):
# Read the code, not the spec
FORCE_BOOT = 0x10
FORCE_RUN = FORCE_BOOT ^ 0xFF
Expand Down
4 changes: 2 additions & 2 deletions zigpy_znp/commands/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import zigpy_znp.types as t


class NodeRelation(t.enum_uint8):
class NodeRelation(t.enum8):
PARENT = 0
CHILD_RFD = 1
CHILD_RFD_RX_IDLE = 2
Expand Down Expand Up @@ -62,7 +62,7 @@ class RandomNumbers(t.FixedList, item_type=t.uint8_t, length=100):
pass


class LEDMode(t.enum_uint8):
class LEDMode(t.enum8):
OFF = 0
ON = 1
BLINK = 2
Expand Down
16 changes: 8 additions & 8 deletions zigpy_znp/commands/zdo.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,27 @@ class SecurityEntry(t.FixedList, item_type=t.uint8_t, length=5):
pass


class StartupState(t.enum_uint8):
class StartupState(t.enum8):
RestoredNetworkState = 0x00
NewNetworkState = 0x01
NotStarted = 0x02


class RouteDiscoveryOptions(t.enum_flag_uint8):
class RouteDiscoveryOptions(t.bitmap8):
UNICAST = 0x00
MTO_WITH_ROUTE_CACHE = 0x01
MTO_WITHOUT_ROUTE_CACHE = 0x03


class RouteStatus(t.enum_uint8):
class RouteStatus(t.enum8):
INIT = 0
ACTIVE = 1
DISC = 2
LINK_FAIL = 3
REPAIR = 4


class RouteOptions(t.enum_flag_uint8):
class RouteOptions(t.bitmap8):
# Used in option of NLME_RouteDiscoveryRequest() and rtgTable[]
MTO_ROUTE = 0x01

Expand All @@ -60,7 +60,7 @@ class RouteOptions(t.enum_flag_uint8):
MULTICAST_ROUTE = 0x40


class RoutingStatus(t.enum_uint8):
class RoutingStatus(t.enum8):
SUCCESS = 0
FAIL = 1
TBL_FULL = 2
Expand All @@ -71,7 +71,7 @@ class RoutingStatus(t.enum_uint8):
SRC_TBL_FULL = 7


class MACCapabilities(t.enum_flag_uint8):
class MACCapabilities(t.bitmap8):
PANCoordinator = 1 << 0
Router = 1 << 1
MainsPowered = 1 << 2
Expand All @@ -82,7 +82,7 @@ class MACCapabilities(t.enum_flag_uint8):
AllocateShortAddrDuringAssocNeeded = 1 << 7


class LeaveOptions(t.enum_flag_uint8):
class LeaveOptions(t.bitmap8):
NONE = 0
Rejoin = 1 << 0
RemoveChildren = 1 << 1
Expand Down Expand Up @@ -136,7 +136,7 @@ def serialize(self) -> bytes:
return super().serialize()


class AddrRequestType(t.enum_uint8):
class AddrRequestType(t.enum8):
SINGLE = 0x00
EXTENDED = 0x01

Expand Down
2 changes: 1 addition & 1 deletion zigpy_znp/commands/znp.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import zigpy_znp.types as t


class DiscreteCommand(t.enum_flag_uint8):
class DiscreteCommand(t.bitmap8):
ZDOStart = 0x40
ResetNwk = 0x80

Expand Down
Loading

0 comments on commit d6c39ea

Please sign in to comment.