refactor(cli): clean shell start/restart, drop redundant ipc check
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -18,29 +18,32 @@ def kill():
|
|||||||
sys.stderr.write(result.stderr.decode())
|
sys.stderr.write(result.stderr.decode())
|
||||||
|
|
||||||
|
|
||||||
|
def start_instance(no_daemon: bool = False) -> None:
|
||||||
|
result = subprocess.run(args + ["-n"] + ([] if no_daemon else ["-d"]), capture_output=True)
|
||||||
|
stdout = result.stdout.decode().strip()
|
||||||
|
if stdout:
|
||||||
|
if "already running" in stdout.lower():
|
||||||
|
raise click.ClickException(stdout)
|
||||||
|
if result.returncode != 0:
|
||||||
|
stderr = result.stderr.decode().strip()
|
||||||
|
raise click.ClickException(stderr)
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def start(no_daemon: bool = False):
|
def start(no_daemon: bool = False):
|
||||||
check = subprocess.run(args + ["ipc"] + ["show"], capture_output=True)
|
start_instance(no_daemon)
|
||||||
if check.returncode == 0:
|
|
||||||
raise click.ClickException("An instance of this configuration is already running.")
|
|
||||||
result = subprocess.run(args + ["-n"] + ([] if no_daemon else ["-d"]), capture_output=True)
|
|
||||||
if result.returncode != 0:
|
|
||||||
raise click.ClickException(result.stderr.decode().strip())
|
|
||||||
sys.stderr.write(result.stderr.decode())
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def restart(no_daemon: bool = False):
|
def restart(no_daemon: bool = False):
|
||||||
subprocess.run(args + ["kill"])
|
subprocess.run(args + ["kill"], capture_output=True)
|
||||||
for _ in range(50):
|
deadline = time.monotonic() + 2.5
|
||||||
|
while time.monotonic() < deadline:
|
||||||
result = subprocess.run(args + ["kill"], capture_output=True)
|
result = subprocess.run(args + ["kill"], capture_output=True)
|
||||||
if result.returncode == 255:
|
if result.returncode == 255:
|
||||||
break
|
break
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
result = subprocess.run(args + ["-n"] + ([] if no_daemon else ["-d"]), capture_output=True)
|
start_instance(no_daemon=no_daemon)
|
||||||
if result.returncode != 0:
|
|
||||||
raise click.ClickException(result.stderr.decode().strip())
|
|
||||||
sys.stderr.write(result.stderr.decode())
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
|
|||||||
+21
-26
@@ -34,35 +34,30 @@ class TestKill:
|
|||||||
class TestStart:
|
class TestStart:
|
||||||
@patch("zshell.subcommands.shell.subprocess.run")
|
@patch("zshell.subcommands.shell.subprocess.run")
|
||||||
def test_start_default_daemon(self, mock_run):
|
def test_start_default_daemon(self, mock_run):
|
||||||
mock_run.side_effect = [
|
mock_run.return_value = CompletedProcess([], 0, b"", b"Launching config\n")
|
||||||
CompletedProcess([], 1, b"", b""), # ipc show → no instance
|
|
||||||
CompletedProcess([], 0, b"", b"Launching config\n"), # launch ok
|
|
||||||
]
|
|
||||||
invoke("start")
|
invoke("start")
|
||||||
assert mock_run.call_args_list == [
|
mock_run.assert_called_once_with(["qs", "-c", "zshell", "-n", "-d"], capture_output=True)
|
||||||
call(["qs", "-c", "zshell", "ipc", "show"], capture_output=True),
|
|
||||||
call(["qs", "-c", "zshell", "-n", "-d"], capture_output=True),
|
|
||||||
]
|
|
||||||
|
|
||||||
@patch("zshell.subcommands.shell.subprocess.run")
|
@patch("zshell.subcommands.shell.subprocess.run")
|
||||||
def test_start_no_daemon(self, mock_run):
|
def test_start_no_daemon(self, mock_run):
|
||||||
mock_run.side_effect = [
|
mock_run.return_value = CompletedProcess([], 0, b"", b"Launching config\n")
|
||||||
CompletedProcess([], 1, b"", b""),
|
|
||||||
CompletedProcess([], 0, b"", b"Launching config\n"),
|
|
||||||
]
|
|
||||||
invoke("start", "--no-daemon")
|
invoke("start", "--no-daemon")
|
||||||
assert mock_run.call_args_list == [
|
mock_run.assert_called_once_with(["qs", "-c", "zshell", "-n"], capture_output=True)
|
||||||
call(["qs", "-c", "zshell", "ipc", "show"], capture_output=True),
|
|
||||||
call(["qs", "-c", "zshell", "-n"], capture_output=True),
|
|
||||||
]
|
|
||||||
|
|
||||||
@patch("zshell.subcommands.shell.subprocess.run")
|
@patch("zshell.subcommands.shell.subprocess.run")
|
||||||
def test_start_already_running_errors(self, mock_run):
|
def test_start_already_running_errors(self, mock_run):
|
||||||
mock_run.return_value = CompletedProcess([], 0, b"", b"target visibilities\n")
|
mock_run.return_value = CompletedProcess([], 0, b"An instance of this configuration is already running.\n", b"")
|
||||||
result = runner.invoke(app, ["start"])
|
result = runner.invoke(app, ["start"])
|
||||||
assert result.exit_code != 0
|
assert result.exit_code != 0
|
||||||
assert "already running" in result.output
|
assert "already running" in result.output
|
||||||
|
|
||||||
|
@patch("zshell.subcommands.shell.subprocess.run")
|
||||||
|
def test_start_other_failure_errors(self, mock_run):
|
||||||
|
mock_run.return_value = CompletedProcess([], 1, b"", b"Config error\n")
|
||||||
|
result = runner.invoke(app, ["start"])
|
||||||
|
assert result.exit_code != 0
|
||||||
|
assert "Config error" in result.output
|
||||||
|
|
||||||
|
|
||||||
class TestShow:
|
class TestShow:
|
||||||
@patch("zshell.subcommands.shell.subprocess.run")
|
@patch("zshell.subcommands.shell.subprocess.run")
|
||||||
@@ -106,30 +101,30 @@ class TestCall:
|
|||||||
|
|
||||||
|
|
||||||
class TestRestart:
|
class TestRestart:
|
||||||
|
@patch("zshell.subcommands.shell.start_instance")
|
||||||
@patch("zshell.subcommands.shell.subprocess.run")
|
@patch("zshell.subcommands.shell.subprocess.run")
|
||||||
def test_restart_kills_then_starts(self, mock_run):
|
def test_restart_kills_then_starts(self, mock_run, mock_start):
|
||||||
mock_run.side_effect = [
|
mock_run.side_effect = [
|
||||||
CompletedProcess([], 0, b"", b"Killed abc\n"), # first kill (no capture)
|
CompletedProcess([], 0, b"", b"Killed abc\n"), # first kill (captured)
|
||||||
CompletedProcess([], 255, b"", b""), # poll → no instance
|
CompletedProcess([], 255, b"", b""), # poll → no instance
|
||||||
CompletedProcess([], 0, b"", b"Launching config\n"), # launch ok
|
|
||||||
]
|
]
|
||||||
invoke("restart")
|
invoke("restart")
|
||||||
assert mock_run.call_args_list == [
|
assert mock_run.call_args_list == [
|
||||||
call(["qs", "-c", "zshell", "kill"]), # no capture_output
|
|
||||||
call(["qs", "-c", "zshell", "kill"], capture_output=True),
|
call(["qs", "-c", "zshell", "kill"], capture_output=True),
|
||||||
call(["qs", "-c", "zshell", "-n", "-d"], capture_output=True),
|
call(["qs", "-c", "zshell", "kill"], capture_output=True),
|
||||||
]
|
]
|
||||||
|
mock_start.assert_called_once_with(no_daemon=False)
|
||||||
|
|
||||||
|
@patch("zshell.subcommands.shell.start_instance")
|
||||||
@patch("zshell.subcommands.shell.subprocess.run")
|
@patch("zshell.subcommands.shell.subprocess.run")
|
||||||
def test_restart_no_daemon(self, mock_run):
|
def test_restart_no_daemon(self, mock_run, mock_start):
|
||||||
mock_run.side_effect = [
|
mock_run.side_effect = [
|
||||||
CompletedProcess([], 0, b"", b"Killed abc\n"),
|
CompletedProcess([], 0, b"", b"Killed abc\n"),
|
||||||
CompletedProcess([], 255, b"", b""),
|
CompletedProcess([], 255, b"", b""),
|
||||||
CompletedProcess([], 0, b"", b"Launching config\n"),
|
|
||||||
]
|
]
|
||||||
invoke("restart", "--no-daemon")
|
invoke("restart", "--no-daemon")
|
||||||
assert mock_run.call_args_list == [
|
assert mock_run.call_args_list == [
|
||||||
call(["qs", "-c", "zshell", "kill"]),
|
|
||||||
call(["qs", "-c", "zshell", "kill"], capture_output=True),
|
call(["qs", "-c", "zshell", "kill"], capture_output=True),
|
||||||
call(["qs", "-c", "zshell", "-n"], capture_output=True),
|
call(["qs", "-c", "zshell", "kill"], capture_output=True),
|
||||||
]
|
]
|
||||||
|
mock_start.assert_called_once_with(no_daemon=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user