treefmt v2.5.0ERRO formatter | ruff-check: failed to apply with options '[check --fix]': exit status 1 D301 Use `r"""` if any backslashes in a docstring --> lib/spaces_install_lib.py:400:5 | 399 | def nix_string(value: str) -> str: 400 | / """`value` as a Nix double-quoted string literal. The three sequences 401 | | that Nix reads inside `"…"` are escaped: `\\`, `"` and `${`. 402 | | """ | |_______^ 403 | escaped = value.replace("\\", "\\\\").replace('"', '\\"').replace("${", "\\${") 404 | return f'"{escaped}"' | help: Add `r` prefix RUF005 Consider iterable unpacking instead of concatenation --> packages/spaces-install-backend/backend.py:728:22 | 726 | host = plan["hostname"] 727 | live_modules = [m.format(host=host) for m in LIVE_FLAKE_MODULES] if live else [] 728 | config_modules = live_modules + [ | ______________________^ 729 | | f"./machines/{host}/generated.nix", 730 | | f"./machines/{host}/configuration.nix", 731 | | f"./machines/{host}/hardware-configuration.nix", 732 | | f"./machines/{host}/hermes.nix", 733 | | ] | |_____^ 734 | extra = [] 735 | if Path("/etc/spaces-test-support").exists(): | help: Replace with iterable unpacking PLR2004 Magic value used in comparison, consider replacing `127` with a constant variable --> packages/spaces-install-backend/backend.py:954:53 | 952 | # merge-file exits with the conflict count, 0 for a clean merge, 953 | # and negative (255 here) on an error. 954 | if proc.returncode < 0 or proc.returncode > 127: | ^^^ 955 | msg = f"git merge-file failed on {dest}: {proc.stderr.strip()}" 956 | raise InstallError(msg) | TRY301 Abstract `raise` to an inner function --> packages/spaces-install-backend/backend.py:1804:17 | 1802 | run_checked(["systemctl", "reboot"]) 1803 | else: # pragma: no cover 1804 | raise AssertionError(action) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1805 | except Exception: 1806 | # Past the stop the user has no agent. Whatever failed (the stop | PT008 Use `return_value=` instead of patching with `lambda` --> packages/spaces-install-backend/test_backend.py:832:13 | 830 | with ( 831 | tempfile.TemporaryDirectory() as tmp, 832 | mock.patch.object(backend.os, "uname", lambda: uname), | ^^^^^^^^^^^^^^^^^ 833 | ): 834 | repo = Path(tmp) / "dotfiles" | RUF012 Mutable default value for class attribute --> packages/spaces-install-backend/test_backend.py:856:17 | 854 | HARDWARE = LiveRepoTest.HARDWARE 855 | SPACES_FLAKE = "/nix/store/aaaa-spaces-src" 856 | OVERRIDES = {"nixpkgs": "/nix/store/bbbb-nixpkgs"} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 857 | 858 | def seed(self): | help: Consider initializing in `__init__` or annotating with `typing.ClassVar` RUF012 Mutable default value for class attribute --> packages/spaces-install-backend/test_backend.py:941:17 | 939 | HARDWARE_TARGET = '{ ... }:\n{ boot.initrd.availableKernelModules = [ "nvme" ]; }\n' 940 | SPACES_FLAKE = "/nix/store/aaaa-spaces-src" 941 | OVERRIDES = {"nixpkgs": "/nix/store/bbbb-nixpkgs"} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 942 | DRV = "/nix/store/cccc-nixos-system-testhost.drv" 943 | TOPLEVEL = "/nix/store/dddd-nixos-system-testhost" | help: Consider initializing in `__init__` or annotating with `typing.ClassVar` SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements --> packages/spaces-install-backend/test_backend.py:1162:13 | 1160 | stale = run_dir / "configuration.nix.rej" 1161 | stale.write_text("<<<<<<< stale\n") 1162 | / with mock.patch.object(backend, "RUN_DIR", run_dir): 1163 | | with self.assertRaises(backend.InstallError): | |_____________________________________________________________^ 1164 | backend.install_to( 1165 | tmp / "mnt", plan(password_file=str(tmp / "missing")), "efi" | help: Combine `with` statements SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements --> packages/spaces-install-backend/test_backend.py:1178:13 | 1176 | stale = run_dir / "installed.json" 1177 | stale.write_text("{}\n") 1178 | / with mock.patch.object(backend, "RUN_DIR", run_dir): 1179 | | with self.assertRaises(backend.InstallError): | |_____________________________________________________________^ 1180 | backend.install_to( 1181 | tmp / "mnt", plan(password_file=str(tmp / "missing")), "efi" | help: Combine `with` statements EM102 Exception must not use an f-string literal, assign to variable first --> packages/spaces-install-backend/test_backend.py:1501:44 | 1499 | mode_at_reboot.append(unplug.stat().st_mode & 0o777 if unplug.exists() else None) 1500 | if armed and argv[0] == fail_at: 1501 | raise backend.InstallError(f"{argv[0]} failed") | ^^^^^^^^^^^^^^^^^^^ 1502 | if argv[0] == "ssh-keygen": 1503 | return real_run(argv, **kwargs) | help: Assign to variable; remove f-string literal ARG001 Unused function argument: `unit` --> packages/spaces-install-backend/test_backend.py:1524:29 | 1522 | return "" 1523 | 1524 | def fake_unit_state(unit): | ^^^^ 1525 | return "inactive" | S105 Possible hardcoded password assigned to: "TOKEN_HEADER" --> packages/spaces-installer-session/bootstrap.py:51:16 | 49 | from websockets.exceptions import WebSocketException 50 | 51 | TOKEN_HEADER = "X-Hermes-Session-Token" | ^^^^^^^^^^^^^^^^^^^^^^^^ 52 | 53 | # The first user turn. It names the situation and the skill, nothing | ANN201 Missing return type annotation for public function `log` --> packages/spaces-installer-session/bootstrap.py:60:5 | 60 | def log(msg): | ^^^ 61 | print(f"spaces-installer-session: {msg}", file=sys.stderr) | help: Add return type annotation: `None` ANN001 Missing type annotation for function argument `msg` --> packages/spaces-installer-session/bootstrap.py:60:9 | 60 | def log(msg): | ^^^ 61 | print(f"spaces-installer-session: {msg}", file=sys.stderr) | ANN204 Missing return type annotation for special method `__init__` --> packages/spaces-installer-session/bootstrap.py:65:9 | 64 | class Dashboard: 65 | def __init__(self, base_url, ws_url, token): | ^^^^^^^^ 66 | self.base_url = base_url.rstrip("/") 67 | self.ws_url = ws_url | help: Add return type annotation: `None` ANN001 Missing type annotation for function argument `base_url` --> packages/spaces-installer-session/bootstrap.py:65:24 | 64 | class Dashboard: 65 | def __init__(self, base_url, ws_url, token): | ^^^^^^^^ 66 | self.base_url = base_url.rstrip("/") 67 | self.ws_url = ws_url | ANN001 Missing type annotation for function argument `ws_url` --> packages/spaces-installer-session/bootstrap.py:65:34 | 64 | class Dashboard: 65 | def __init__(self, base_url, ws_url, token): | ^^^^^^ 66 | self.base_url = base_url.rstrip("/") 67 | self.ws_url = ws_url | ANN001 Missing type annotation for function argument `token` --> packages/spaces-installer-session/bootstrap.py:65:42 | 64 | class Dashboard: 65 | def __init__(self, base_url, ws_url, token): | ^^^^^ 66 | self.base_url = base_url.rstrip("/") 67 | self.ws_url = ws_url | ANN202 Missing return type annotation for private function `_request` --> packages/spaces-installer-session/bootstrap.py:70:9 | 68 | self.token = token 69 | 70 | def _request(self, method, path, body=None): | ^^^^^^^^ 71 | data = None 72 | headers = {TOKEN_HEADER: self.token} | help: Add return type annotation ANN001 Missing type annotation for function argument `method` --> packages/spaces-installer-session/bootstrap.py:70:24 | 68 | self.token = token 69 | 70 | def _request(self, method, path, body=None): | ^^^^^^ 71 | data = None 72 | headers = {TOKEN_HEADER: self.token} | ANN001 Missing type annotation for function argument `path` --> packages/spaces-installer-session/bootstrap.py:70:32 | 68 | self.token = token 69 | 70 | def _request(self, method, path, body=None): | ^^^^ 71 | data = None 72 | headers = {TOKEN_HEADER: self.token} | ANN001 Missing type annotation for function argument `body` --> packages/spaces-installer-session/bootstrap.py:70:38 | 68 | self.token = token 69 | 70 | def _request(self, method, path, body=None): | ^^^^ 71 | data = None 72 | headers = {TOKEN_HEADER: self.token} | ANN201 Missing return type annotation for public function `ready` --> packages/spaces-installer-session/bootstrap.py:84:9 | 82 | return err.code, err.read() 83 | 84 | def ready(self): | ^^^^^ 85 | try: 86 | with urllib.request.urlopen(self.base_url + "/api/status", timeout=5) as resp: | help: Add return type annotation PLR2004 Magic value used in comparison, consider replacing `200` with a constant variable --> packages/spaces-installer-session/bootstrap.py:87:39 | 85 | try: 86 | with urllib.request.urlopen(self.base_url + "/api/status", timeout=5) as resp: 87 | return resp.status == 200 | ^^^ 88 | except urllib.error.HTTPError as err: 89 | err.close() | ANN201 Missing return type annotation for public function `session_exists` --> packages/spaces-installer-session/bootstrap.py:94:9 | 92 | return False 93 | 94 | def session_exists(self, sid): | ^^^^^^^^^^^^^^ 95 | status, _ = self._request("GET", f"/api/sessions/{sid}") 96 | return status == 200 | help: Add return type annotation ANN001 Missing type annotation for function argument `sid` --> packages/spaces-installer-session/bootstrap.py:94:30 | 92 | return False 93 | 94 | def session_exists(self, sid): | ^^^ 95 | status, _ = self._request("GET", f"/api/sessions/{sid}") 96 | return status == 200 | PLR2004 Magic value used in comparison, consider replacing `200` with a constant variable --> packages/spaces-installer-session/bootstrap.py:96:26 | 94 | def session_exists(self, sid): 95 | status, _ = self._request("GET", f"/api/sessions/{sid}") 96 | return status == 200 | ^^^ 97 | 98 | def find_by_title(self, title): | ANN201 Missing return type annotation for public function `find_by_title` --> packages/spaces-installer-session/bootstrap.py:98:9 | 96 | return status == 200 97 | 98 | def find_by_title(self, title): | ^^^^^^^^^^^^^ 99 | # `order=recent` puts the newest activity first, so the session 100 | # the user last talked to wins when several carry the title. | help: Add return type annotation ANN001 Missing type annotation for function argument `title` --> packages/spaces-installer-session/bootstrap.py:98:29 | 96 | return status == 200 97 | 98 | def find_by_title(self, title): | ^^^^^ 99 | # `order=recent` puts the newest activity first, so the session 100 | # the user last talked to wins when several carry the title. | PLR2004 Magic value used in comparison, consider replacing `200` with a constant variable --> packages/spaces-installer-session/bootstrap.py:106:26 | 104 | "GET", f"/api/sessions?limit=100&offset={offset}&archived=include&order=recent" 105 | ) 106 | if status != 200: | ^^^ 107 | raise RuntimeError(f"GET /api/sessions answered {status}: {body!r}") 108 | rows = body.get("sessions") or [] | EM102 Exception must not use an f-string literal, assign to variable first --> packages/spaces-installer-session/bootstrap.py:107:36 | 105 | ) 106 | if status != 200: 107 | raise RuntimeError(f"GET /api/sessions answered {status}: {body!r}") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 108 | rows = body.get("sessions") or [] 109 | for row in rows: | help: Assign to variable; remove f-string literal ANN201 Missing return type annotation for public function `set_title` --> packages/spaces-installer-session/bootstrap.py:116:9 | 114 | return None 115 | 116 | def set_title(self, sid, title): | ^^^^^^^^^ 117 | status, body = self._request("PATCH", f"/api/sessions/{sid}", {"title": title}) 118 | if status != 200: | help: Add return type annotation: `None` ANN001 Missing type annotation for function argument `sid` --> packages/spaces-installer-session/bootstrap.py:116:25 | 114 | return None 115 | 116 | def set_title(self, sid, title): | ^^^ 117 | status, body = self._request("PATCH", f"/api/sessions/{sid}", {"title": title}) 118 | if status != 200: | ANN001 Missing type annotation for function argument `title` --> packages/spaces-installer-session/bootstrap.py:116:30 | 114 | return None 115 | 116 | def set_title(self, sid, title): | ^^^^^ 117 | status, body = self._request("PATCH", f"/api/sessions/{sid}", {"title": title}) 118 | if status != 200: | PLR2004 Magic value used in comparison, consider replacing `200` with a constant variable --> packages/spaces-installer-session/bootstrap.py:118:22 | 116 | def set_title(self, sid, title): 117 | status, body = self._request("PATCH", f"/api/sessions/{sid}", {"title": title}) 118 | if status != 200: | ^^^ 119 | raise RuntimeError(f"PATCH /api/sessions/{sid} answered {status}: {body!r}") | EM102 Exception must not use an f-string literal, assign to variable first --> packages/spaces-installer-session/bootstrap.py:119:32 | 117 | status, body = self._request("PATCH", f"/api/sessions/{sid}", {"title": title}) 118 | if status != 200: 119 | raise RuntimeError(f"PATCH /api/sessions/{sid} answered {status}: {body!r}") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 120 | 121 | async def _rpc(self, ws, rid, method, params): | help: Assign to variable; remove f-string literal ANN202 Missing return type annotation for private function `_rpc` --> packages/spaces-installer-session/bootstrap.py:121:15 | 119 | raise RuntimeError(f"PATCH /api/sessions/{sid} answered {status}: {body!r}") 120 | 121 | async def _rpc(self, ws, rid, method, params): | ^^^^ 122 | await ws.send(json.dumps({"jsonrpc": "2.0", "id": rid, "method": method, "params": params})) 123 | # Events (gateway.ready, message.start, ...) interleave with replies. | help: Add return type annotation ANN001 Missing type annotation for function argument `ws` --> packages/spaces-installer-session/bootstrap.py:121:26 | 119 | raise RuntimeError(f"PATCH /api/sessions/{sid} answered {status}: {body!r}") 120 | 121 | async def _rpc(self, ws, rid, method, params): | ^^ 122 | await ws.send(json.dumps({"jsonrpc": "2.0", "id": rid, "method": method, "params": params})) 123 | # Events (gateway.ready, message.start, ...) interleave with replies. | ANN001 Missing type annotation for function argument `rid` --> packages/spaces-installer-session/bootstrap.py:121:30 | 119 | raise RuntimeError(f"PATCH /api/sessions/{sid} answered {status}: {body!r}") 120 | 121 | async def _rpc(self, ws, rid, method, params): | ^^^ 122 | await ws.send(json.dumps({"jsonrpc": "2.0", "id": rid, "method": method, "params": params})) 123 | # Events (gateway.ready, message.start, ...) interleave with replies. | ANN001 Missing type annotation for function argument `method` --> packages/spaces-installer-session/bootstrap.py:121:35 | 119 | raise RuntimeError(f"PATCH /api/sessions/{sid} answered {status}: {body!r}") 120 | 121 | async def _rpc(self, ws, rid, method, params): | ^^^^^^ 122 | await ws.send(json.dumps({"jsonrpc": "2.0", "id": rid, "method": method, "params": params})) 123 | # Events (gateway.ready, message.start, ...) interleave with replies. | ANN001 Missing type annotation for function argument `params` --> packages/spaces-installer-session/bootstrap.py:121:43 | 119 | raise RuntimeError(f"PATCH /api/sessions/{sid} answered {status}: {body!r}") 120 | 121 | async def _rpc(self, ws, rid, method, params): | ^^^^^^ 122 | await ws.send(json.dumps({"jsonrpc": "2.0", "id": rid, "method": method, "params": params})) 123 | # Events (gateway.ready, message.start, ...) interleave with replies. | EM102 Exception must not use an f-string literal, assign to variable first --> packages/spaces-installer-session/bootstrap.py:129:36 | 127 | continue 128 | if "error" in frame: 129 | raise RuntimeError(f"{method}: {frame['error']}") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 130 | return frame.get("result") or {} 131 | raise RuntimeError(f"{method}: the gateway closed the socket before it answered") | help: Assign to variable; remove f-string literal EM102 Exception must not use an f-string literal, assign to variable first --> packages/spaces-installer-session/bootstrap.py:131:28 | 129 | raise RuntimeError(f"{method}: {frame['error']}") 130 | return frame.get("result") or {} 131 | raise RuntimeError(f"{method}: the gateway closed the socket before it answered") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 132 | 133 | async def _create_and_prompt(self, title, text): | help: Assign to variable; remove f-string literal ANN202 Missing return type annotation for private function `_create_and_prompt` --> packages/spaces-installer-session/bootstrap.py:133:15 | 131 | raise RuntimeError(f"{method}: the gateway closed the socket before it answered") 132 | 133 | async def _create_and_prompt(self, title, text): | ^^^^^^^^^^^^^^^^^^ 134 | url = f"{self.ws_url}?token={self.token}" 135 | async with connect(url, open_timeout=30) as ws: | help: Add return type annotation ANN001 Missing type annotation for function argument `title` --> packages/spaces-installer-session/bootstrap.py:133:40 | 131 | raise RuntimeError(f"{method}: the gateway closed the socket before it answered") 132 | 133 | async def _create_and_prompt(self, title, text): | ^^^^^ 134 | url = f"{self.ws_url}?token={self.token}" 135 | async with connect(url, open_timeout=30) as ws: | ANN001 Missing type annotation for function argument `text` --> packages/spaces-installer-session/bootstrap.py:133:47 | 131 | raise RuntimeError(f"{method}: the gateway closed the socket before it answered") 132 | 133 | async def _create_and_prompt(self, title, text): | ^^^^ 134 | url = f"{self.ws_url}?token={self.token}" 135 | async with connect(url, open_timeout=30) as ws: | EM102 Exception must not use an f-string literal, assign to variable first --> packages/spaces-installer-session/bootstrap.py:140:36 | 138 | stored_id = created.get("stored_session_id") 139 | if not runtime_id or not stored_id: 140 | raise RuntimeError(f"session.create returned no ids: {created!r}") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 141 | await self._rpc(ws, 2, "prompt.submit", {"session_id": runtime_id, "text": text}) 142 | return stored_id | help: Assign to variable; remove f-string literal ANN201 Missing return type annotation for public function `create_and_prompt` --> packages/spaces-installer-session/bootstrap.py:144:9 | 142 | return stored_id 143 | 144 | def create_and_prompt(self, title, text): | ^^^^^^^^^^^^^^^^^ 145 | return asyncio.run(self._create_and_prompt(title, text)) | help: Add return type annotation ANN001 Missing type annotation for function argument `title` --> packages/spaces-installer-session/bootstrap.py:144:33 | 142 | return stored_id 143 | 144 | def create_and_prompt(self, title, text): | ^^^^^ 145 | return asyncio.run(self._create_and_prompt(title, text)) | ANN001 Missing type annotation for function argument `text` --> packages/spaces-installer-session/bootstrap.py:144:40 | 142 | return stored_id 143 | 144 | def create_and_prompt(self, title, text): | ^^^^ 145 | return asyncio.run(self._create_and_prompt(title, text)) | ANN201 Missing return type annotation for public function `parse_args` --> packages/spaces-installer-session/bootstrap.py:148:5 | 148 | def parse_args(argv): | ^^^^^^^^^^ 149 | p = argparse.ArgumentParser(description="open the install conversation once per boot") 150 | p.add_argument("--base-url", required=True, help="dashboard URL, http://127.0.0.1:") | help: Add return type annotation ANN001 Missing type annotation for function argument `argv` --> packages/spaces-installer-session/bootstrap.py:148:16 | 148 | def parse_args(argv): | ^^^^ 149 | p = argparse.ArgumentParser(description="open the install conversation once per boot") 150 | p.add_argument("--base-url", required=True, help="dashboard URL, http://127.0.0.1:") | PTH118 `os.path.join()` should be replaced by `Path` with `/` operator --> packages/spaces-installer-session/bootstrap.py:154:17 | 152 | p.add_argument( 153 | "--state-file", 154 | default=os.path.join(os.environ.get("XDG_RUNTIME_DIR", "/run/user/%d" % os.getuid()), "spaces-installer", "session"), | ^^^^^^^^^^^^ 155 | help="where the stored session id is recorded", 156 | ) | UP031 Use format specifiers instead of percent format --> packages/spaces-installer-session/bootstrap.py:154:64 | 152 | p.add_argument( 153 | "--state-file", 154 | default=os.path.join(os.environ.get("XDG_RUNTIME_DIR", "/run/user/%d" % os.getuid()), "spaces-installer", "session"), | ^^^^^^^^^^^^^^ 155 | help="where the stored session id is recorded", 156 | ) | help: Replace with format specifiers ANN201 Missing return type annotation for public function `record` --> packages/spaces-installer-session/bootstrap.py:165:5 | 165 | def record(state_file, sid): | ^^^^^^ 166 | path = Path(state_file) 167 | path.parent.mkdir(parents=True, exist_ok=True) | help: Add return type annotation: `None` ANN001 Missing type annotation for function argument `state_file` --> packages/spaces-installer-session/bootstrap.py:165:12 | 165 | def record(state_file, sid): | ^^^^^^^^^^ 166 | path = Path(state_file) 167 | path.parent.mkdir(parents=True, exist_ok=True) | ANN001 Missing type annotation for function argument `sid` --> packages/spaces-installer-session/bootstrap.py:165:24 | 165 | def record(state_file, sid): | ^^^ 166 | path = Path(state_file) 167 | path.parent.mkdir(parents=True, exist_ok=True) | PTH105 `os.replace()` should be replaced by `Path.replace()` --> packages/spaces-installer-session/bootstrap.py:170:5 | 168 | tmp = path.with_name(path.name + ".tmp") 169 | tmp.write_text(sid) 170 | os.replace(tmp, path) | ^^^^^^^^^^ help: Replace with `Path(...).replace(...)` ANN201 Missing return type annotation for public function `main` --> packages/spaces-installer-session/bootstrap.py:173:5 | 173 | def main(argv=None): | ^^^^ 174 | args = parse_args(argv) 175 | try: | help: Add return type annotation: `int | None` ANN001 Missing type annotation for function argument `argv` --> packages/spaces-installer-session/bootstrap.py:173:10 | 173 | def main(argv=None): | ^^^^ 174 | args = parse_args(argv) 175 | try: | TRY300 Consider moving this statement to an `else` block --> packages/spaces-installer-session/bootstrap.py:209:9 | 207 | log(f"created session {sid} titled {args.title!r}") 208 | record(args.state_file, sid) 209 | return 0 | ^^^^^^^^ 210 | except (RuntimeError, OSError, WebSocketException, ValueError) as err: 211 | log(str(err)) | Found 80 errors (19 fixed, 61 remaining). No fixes available (13 hidden fixes can be enabled with the `--unsafe-fixes` option). ERRO formatter | shellcheck: failed to apply with options '[]': exit status 1 In packages/spaces-install-secret/spaces-install-secret.sh line 1: # Usage: spaces-install-secret password|luks-passphrase ^-- SC2148 (error): Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive. For more information: https://www.shellcheck.net/wiki/SC2148 -- Tips depend on target shell and y... traversed 596 files emitted 398 files for processing formatted 239 files (14 changed) in 910ms Error: failed to finalise formatting: formatting failures detected