Avoid Jupyter terminal job-control noise
This commit is contained in:
+23
-2
@@ -542,7 +542,7 @@ PY
|
|||||||
pid_file = shlex.quote(f'{run_dir}/{marker}.pid')
|
pid_file = shlex.quote(f'{run_dir}/{marker}.pid')
|
||||||
env_prefix = self._remote_env_prefix()
|
env_prefix = self._remote_env_prefix()
|
||||||
inner_command = f'{env_prefix}{command}'
|
inner_command = f'{env_prefix}{command}'
|
||||||
wrapped = (
|
wrapper_script = (
|
||||||
f'mkdir -p {workspace} {quoted_run_dir} && '
|
f'mkdir -p {workspace} {quoted_run_dir} && '
|
||||||
f'cd {workspace} && '
|
f'cd {workspace} && '
|
||||||
f'printf "\\n{start_marker}\\n"; '
|
f'printf "\\n{start_marker}\\n"; '
|
||||||
@@ -561,6 +561,11 @@ PY
|
|||||||
f'rm -f {pid_file}; '
|
f'rm -f {pid_file}; '
|
||||||
f'printf "\\n{marker}:%s\\n" "$__zk_status"'
|
f'printf "\\n{marker}:%s\\n" "$__zk_status"'
|
||||||
)
|
)
|
||||||
|
# Run the wrapper inside a foreground non-interactive bash. Sending the
|
||||||
|
# whole background-job wrapper directly to the terminal shell can make
|
||||||
|
# the interactive shell print job-control lines such as
|
||||||
|
# "[1] + Done (setsid bash -lc ...)", which can hide the real stdout.
|
||||||
|
wrapped = f'bash -lc {shlex.quote(wrapper_script)}'
|
||||||
with self._lock:
|
with self._lock:
|
||||||
name = self._ensure_terminal()
|
name = self._ensure_terminal()
|
||||||
ws_url = self._terminal_websocket_url(name)
|
ws_url = self._terminal_websocket_url(name)
|
||||||
@@ -1288,11 +1293,27 @@ def clean_terminal_output(text: str) -> str:
|
|||||||
lines = [
|
lines = [
|
||||||
line.rstrip('\r')
|
line.rstrip('\r')
|
||||||
for line in cleaned.splitlines()
|
for line in cleaned.splitlines()
|
||||||
if line.strip() not in {'#', '>'} and not re.fullmatch(r'(>\s*)+', line.strip())
|
if (
|
||||||
|
line.strip() not in {'#', '>'}
|
||||||
|
and not re.fullmatch(r'(>\s*)+', line.strip())
|
||||||
|
and not is_wrapper_job_control_line(line.strip())
|
||||||
|
)
|
||||||
]
|
]
|
||||||
return '\n'.join(lines).strip('\r\n')
|
return '\n'.join(lines).strip('\r\n')
|
||||||
|
|
||||||
|
|
||||||
|
def is_wrapper_job_control_line(line: str) -> bool:
|
||||||
|
"""Return true for terminal job-control notices created by our wrapper."""
|
||||||
|
if 'setsid bash -lc' not in line:
|
||||||
|
return False
|
||||||
|
return bool(
|
||||||
|
re.match(
|
||||||
|
r'^\[\d+\]\s*[+-]?\s*(Done|done|Terminated|terminated|Killed|killed|Exit \d+)',
|
||||||
|
line,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def extract_terminal_command_output(text: str, *, start_marker: str) -> str:
|
def extract_terminal_command_output(text: str, *, start_marker: str) -> str:
|
||||||
"""Drop terminal echo/prompt text before the wrapper's real start marker."""
|
"""Drop terminal echo/prompt text before the wrapper's real start marker."""
|
||||||
if not start_marker:
|
if not start_marker:
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ class TestJupyterRuntimeOutputFiltering(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(output, 'actual')
|
self.assertEqual(output, 'actual')
|
||||||
|
|
||||||
|
def test_clean_terminal_output_drops_wrapper_job_control_line(self) -> None:
|
||||||
|
cleaned = clean_terminal_output(
|
||||||
|
'real-output\r\n'
|
||||||
|
'[1] + Done (setsid bash -lc "export A=1; lscpu")\r\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(cleaned, 'real-output')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user