Skip to content

Commit

Permalink
Merge pull request #34 from BrianPugh/immediate-print
Browse files Browse the repository at this point in the history
immediately print once a newline is detected; do not wait for calling function to return
  • Loading branch information
BrianPugh authored Oct 28, 2022
2 parents ddc7ca0 + 4e38e2f commit 1967a10
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 32 deletions.
35 changes: 22 additions & 13 deletions belay/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,27 +567,36 @@ def __call__(
):
self._cmd_history.append(cmd)

out = None
data_consumer_buffer = []

def data_consumer(data):
"""Handle input data stream immediately."""
nonlocal out
if data == b"\x04":
return
data_consumer_buffer.append(data.decode())
if b"\n" in data:
line = "".join(data_consumer_buffer)
data_consumer_buffer.clear()

try:
out = _parse_belay_response(line)
except NotBelayResponse:
if stream_out:
stream_out.write(line)

try:
res = self._board.exec(cmd).decode()
self._board.exec(cmd, data_consumer=data_consumer)
except (SerialException, ConnectionResetError):
# Board probably disconnected.
if self.attempts:
self.reconnect()
res = self._board.exec(cmd).decode()
self._board.exec(cmd, data_consumer=data_consumer_buffer)
else:
raise ConnectionLost

lines = res.split("\r\n")

for line in lines[:-1]:
try:
return _parse_belay_response(line)
except NotBelayResponse:
pass

if stream_out:
stream_out.write(line)
stream_out.write("\n")
return out

def sync(
self,
Expand Down
4 changes: 1 addition & 3 deletions belay/pyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,7 @@ def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None):
new_data = self.serial.read(1)
if data_consumer:
data_consumer(new_data)
data = new_data
else:
data = data + new_data
data = data + new_data
timeout_count = 0
else:
timeout_count += 1
Expand Down
17 changes: 13 additions & 4 deletions tests/test_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@

@pytest.fixture
def mock_pyboard(mocker):
exec_side_effect = [b'_BELAYR("micropython", (1, 19, 1), "rp2")\r\n'] * 100

def mock_init(self, *args, **kwargs):
self.serial = None

exec_side_effect = [b'_BELAYR("micropython", (1, 19, 1), "rp2")\r\n'] * 100
def mock_exec(cmd, data_consumer=None):
data = exec_side_effect.pop()
if data_consumer:
data_consumer(data)

mocker.patch.object(belay.device.Pyboard, "__init__", mock_init)
mocker.patch.object(belay.device.Pyboard, "exec", side_effect=mock_exec)
mocker.patch("belay.device.Pyboard.enter_raw_repl", return_value=None)
mocker.patch("belay.device.Pyboard.exec", side_effect=exec_side_effect)
mocker.patch("belay.device.Pyboard.fs_put")


Expand All @@ -38,7 +43,9 @@ def test_device_task(mocker, mock_device):
def foo(a, b):
c = a + b # noqa: F841

mock_device._board.exec.assert_any_call("@__belay('foo')\ndef foo(a,b):\n c=a+b\n")
mock_device._board.exec.assert_any_call(
"@__belay('foo')\ndef foo(a,b):\n c=a+b\n", data_consumer=mocker.ANY
)

foo(1, 2)
assert (
Expand Down Expand Up @@ -78,7 +85,9 @@ def test_device_thread(mocker, mock_device):
def foo(a, b):
c = a + b # noqa: F841

mock_device._board.exec.assert_any_call("def foo(a,b):\n c=a+b\n")
mock_device._board.exec.assert_any_call(
"def foo(a,b):\n c=a+b\n", data_consumer=mocker.ANY
)

foo(1, 2)
assert (
Expand Down
42 changes: 30 additions & 12 deletions tests/test_device_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ def mock_init(self, *args, **kwargs):

exec_side_effect = [b'_BELAYR("micropython", (1, 19, 1), "rp2")\r\n'] * 100

def mock_exec(cmd, data_consumer=None):
data = exec_side_effect.pop()
if data_consumer:
data_consumer(data)

mocker.patch.object(belay.device.Pyboard, "__init__", mock_init)
mocker.patch.object(belay.device.Pyboard, "exec", side_effect=mock_exec)
mocker.patch("belay.device.Pyboard.enter_raw_repl", return_value=None)
mocker.patch("belay.device.Pyboard.exec", side_effect=exec_side_effect)
mocker.patch("belay.device.Pyboard.fs_put")


Expand Down Expand Up @@ -186,19 +191,28 @@ def test_sync_device_belay_fs_does_not_exist(sync_begin, tmp_path):


def test_device_sync_empty_remote(mocker, mock_device, sync_path):
payload = ("_BELAYR" + repr([b""] * 5) + "\r\n").encode("utf-8")
mock_device._board.exec = mocker.MagicMock(return_value=payload)
exec_side_effect = ("_BELAYR" + repr([b""] * 5) + "\r\n").encode("utf-8")

def mock_exec(cmd, data_consumer=None):
data_consumer(exec_side_effect)

mocker.patch.object(belay.device.Pyboard, "exec", side_effect=mock_exec)

mock_device.sync(sync_path)

mock_device._board.exec.assert_has_calls(
[
call(
"for x in['/alpha.py','/bar.txt','/folder1/file1.txt','/folder1/folder1_1/file1_1.txt','/foo.txt','/boot.py','/webrepl_cfg.py']:\n all_files.discard(x)"
"for x in['/alpha.py','/bar.txt','/folder1/file1.txt','/folder1/folder1_1/file1_1.txt','/foo.txt','/boot.py','/webrepl_cfg.py']:\n all_files.discard(x)",
data_consumer=mocker.ANY,
),
call("__belay_mkdirs(['/folder1','/folder1/folder1_1'])"),
call(
"__belay_hfs(['/alpha.py','/bar.txt','/folder1/file1.txt','/folder1/folder1_1/file1_1.txt','/foo.txt'])"
"__belay_mkdirs(['/folder1','/folder1/folder1_1'])",
data_consumer=mocker.ANY,
),
call(
"__belay_hfs(['/alpha.py','/bar.txt','/folder1/file1.txt','/folder1/folder1_1/file1_1.txt','/foo.txt'])",
data_consumer=mocker.ANY,
),
]
)
Expand Down Expand Up @@ -227,13 +241,17 @@ def __belay_hfs(fns):
out.append(belay.device._local_hash_file(local_fn))
return out

def side_effect(cmd):
if not cmd.startswith("__belay_hfs"):
return b""
nonlocal __belay_hfs
return ("_BELAYR" + repr(eval(cmd)) + "\r\n").encode("utf-8")
def mock_exec(cmd, data_consumer=None):
if cmd.startswith("__belay_hfs"):
nonlocal __belay_hfs
out = ("_BELAYR" + repr(eval(cmd)) + "\r\n").encode("utf-8")
else:
out = b""
if data_consumer is not None:
data_consumer(out)
return out

mock_device._board.exec = mocker.MagicMock(side_effect=side_effect)
mock_device._board.exec = mocker.MagicMock(side_effect=mock_exec)

mock_device.sync(sync_path)

Expand Down

0 comments on commit 1967a10

Please sign in to comment.