diff --git a/pytest_pyodide/__init__.py b/pytest_pyodide/__init__.py index fe1d4fd..bf147e3 100644 --- a/pytest_pyodide/__init__.py +++ b/pytest_pyodide/__init__.py @@ -1,6 +1,6 @@ from importlib.metadata import PackageNotFoundError, version -from .decorator import run_in_pyodide +from .decorator import copy_files_to_pyodide, run_in_pyodide from .runner import ( NodeRunner, PlaywrightChromeRunner, @@ -28,5 +28,6 @@ "set_webdriver_script_timeout", "parse_driver_timeout", "run_in_pyodide", + "copy_files_to_pyodide", "spawn_web_server", ] diff --git a/pytest_pyodide/node_test_driver.js b/pytest_pyodide/node_test_driver.js index b95cb0f..cd8e66d 100644 --- a/pytest_pyodide/node_test_driver.js +++ b/pytest_pyodide/node_test_driver.js @@ -55,7 +55,18 @@ rl.on("line", async function (line) { return; } if (line !== cur_uuid) { - cur_code += line + "\n"; + // each line ends with an extra $, to avoid problems with end-of-line + // translation etc. + line = line.substring(0, line.lastIndexOf('$')) + if(line === ""){ + cur_code += "\n"; + } else { + cur_code += line; + } + // tell runner.py that the line has been read + // so it can send the next line without worrying about + // filling buffers + console.log("{LINE_OK}") } else { evalCode(cur_uuid, cur_code, context); cur_code = ""; diff --git a/pytest_pyodide/runner.py b/pytest_pyodide/runner.py index f60b046..e278134 100644 --- a/pytest_pyodide/runner.py +++ b/pytest_pyodide/runner.py @@ -536,9 +536,6 @@ def init_node(self, jspi=False): self.p = pexpect.spawn("/bin/bash", timeout=60) self.p.setecho(False) self.p.delaybeforesend = None - # disable canonical input processing mode to allow sending longer lines - # See: https://pexpect.readthedocs.io/en/stable/api/pexpect.html#pexpect.spawn.send - self.p.sendline("stty -icanon") node_version = pexpect.spawn("node --version").read().decode("utf-8") node_major = int(node_version.split(".")[0][1:]) # vAA.BB.CC -> AA @@ -610,7 +607,29 @@ def run_js_inner(self, code, check_code): cmd_id = str(uuid4()) self.p.sendline(cmd_id) - self.p.sendline(wrapped) + # split long lines into shorter buffers + # because some ttys don't like long + # single lines + all_lines = wrapped.split("\n") + for c, line in enumerate(all_lines): + count = 0 + while count < len(line): + to_read = min(128, len(line) - count) + # each sent line ends with an extra $, to avoid problems with end-of-line + # translation etc. it doesn't matter if there are $ in the string elsewhere + # because the last $ is always the one we added + self.p.sendline(line[count : count + to_read] + "$") + # after we send a line, we wait for a response + # before sending the next line + # this means we don't overflow input buffers + self.p.expect_exact("{LINE_OK}\r\n") + count += to_read + if c < len(all_lines) - 1: + # to insert a line break into the received code string + # we send a blank line with just the $ end-of-line character + # and await response + self.p.sendline("$") + self.p.expect_exact("{LINE_OK}\r\n") self.p.sendline(cmd_id) self.p.expect_exact(f"{cmd_id}:UUID\r\n", timeout=self.script_timeout) self.p.expect_exact(f"{cmd_id}:UUID\r\n")