Skip to content

Commit

Permalink
Add specific errors subclasses for message_read
Browse files Browse the repository at this point in the history
When reading a message queue, it is useful to make the distinction
between several possible errors. Add DirectProtocolError exception
subclasses: NoActiveProgramError and EmptyMailboxError.

Also update stop_program and get_current_program_name documentation to
reflect the change.

This is backward compatible as they are subclasses of the original error
exceptions.
  • Loading branch information
schodet committed Mar 23, 2024
1 parent 960ca03 commit 93e9987
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 5 deletions.
2 changes: 2 additions & 0 deletions docs/migration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ From :mod:`nxt.error`:
:exc:`DirectProtocolError` and :exc:`SystemProtocolError`.
- :exc:`!FileNotFound` has been renamed to :exc:`FileNotFoundError`.
- :exc:`!ModuleNotFound` has been renamed to :exc:`ModuleNotFoundError`.
- New :exc:`EmptyMailboxError` and :exc:`NoActiveProgramError` have been added
as subclasses of :exc:`DirectProtocolError`.

Sensors:

Expand Down
7 changes: 4 additions & 3 deletions nxt/brick.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def start_program(self, name):
def stop_program(self):
"""Stop the running program on the brick.
:raises nxt.error.DirectProtocolError: When no program is running.
:raises nxt.error.NoActiveProgramError: When no program is running.
"""
tgram = Telegram(Opcode.DIRECT_STOP_PROGRAM)
self._cmd(tgram)
Expand Down Expand Up @@ -655,7 +655,7 @@ def get_current_program_name(self):
:return: Program file name
:rtype: str
:raises nxt.error.DirectProtocolError: When no program is running.
:raises nxt.error.NoActiveProgramError: When no program is running.
"""
tgram = Telegram(Opcode.DIRECT_GET_CURR_PROGRAM)
tgram = self._cmd(tgram)
Expand All @@ -670,7 +670,8 @@ def message_read(self, remote_inbox, local_inbox, remove):
:param bool remove: Whether to remove the message from the mailbox.
:return: The read message.
:rtype: bytes
:raises nxt.error.DirectProtocolError: When mailbox is empty.
:raises nxt.error.EmptyMailboxError: When mailbox is empty.
:raises nxt.error.NoActiveProgramError: When no program is running.
"""
tgram = Telegram(Opcode.DIRECT_MESSAGE_READ)
tgram.add_u8(remote_inbox)
Expand Down
12 changes: 12 additions & 0 deletions nxt/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,24 @@ class DirectProtocolError(ProtocolError):
pass


class EmptyMailboxError(DirectProtocolError):
"""Raised when trying to read from empty mailbox."""

pass


class I2CError(DirectProtocolError):
"""Raised on I2C error on a sensor port."""

pass


class NoActiveProgramError(DirectProtocolError):
"""Raised when no program is running."""

pass


class I2CPendingError(I2CError):
"""Raised when an I2C transaction on a sensor port is still in progress."""

Expand Down
4 changes: 2 additions & 2 deletions nxt/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def is_system(self):
CODES = {
0x00: None,
0x20: nxt.error.I2CPendingError("pending communication transaction in progress"),
0x40: nxt.error.DirectProtocolError("specified mailbox queue is empty"),
0x40: nxt.error.EmptyMailboxError("specified mailbox queue is empty"),
0x81: nxt.error.SystemProtocolError("no more handles"),
0x82: nxt.error.SystemProtocolError("no space"),
0x83: nxt.error.SystemProtocolError("no more files"),
Expand Down Expand Up @@ -118,7 +118,7 @@ def is_system(self):
0xDE: nxt.error.DirectProtocolError("no free memory in communication buffer"),
0xDF: nxt.error.DirectProtocolError("specified channel/connection is not valid"),
0xE0: nxt.error.I2CError("specified channel/connection not configured or busy"),
0xEC: nxt.error.DirectProtocolError("no active program"),
0xEC: nxt.error.NoActiveProgramError("no active program"),
0xED: nxt.error.DirectProtocolError("illegal size specified"),
0xEE: nxt.error.DirectProtocolError("illegal mailbox queue ID specified"),
0xEF: nxt.error.DirectProtocolError(
Expand Down
10 changes: 10 additions & 0 deletions tests/test_brick.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@ def test_stop_program(self, sock, brick):
brick.stop_program()
assert sock.mock_calls == sent_recved(bytes.fromhex("0001"))

def test_stop_program_fail(self, sock, brick):
sock.recv.return_value = bytes.fromhex("0201ec")
with pytest.raises(nxt.error.NoActiveProgramError):
brick.stop_program()

def test_play_sound_file(self, sock, brick):
brick.play_sound_file(True, "test.rso")
assert sock.mock_calls == sent(bytes.fromhex("8002 01") + test_rso_bin)
Expand Down Expand Up @@ -463,6 +468,11 @@ def test_message_read(self, sock, brick):
assert local_inbox == 0
assert message == bytes.fromhex("21222324252627")

def test_message_read_fail(self, sock, brick):
sock.recv.return_value = bytes.fromhex("021340 00 00") + bytes(59)
with pytest.raises(nxt.error.EmptyMailboxError):
local_inbox, message = brick.message_read(10, 0, True)


class TestFilesModules:
"""Test nxt.brick files & modules access."""
Expand Down

0 comments on commit 93e9987

Please sign in to comment.